1 /* 2 * Copyright 2001-2015, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 * Ingo Weinhold, bonefish@@users.sf.net 8 */ 9 10 11 #include <AppMisc.h> 12 13 #include <stdlib.h> 14 #include <string.h> 15 #include <sys/utsname.h> 16 #include <unistd.h> 17 18 #include <Entry.h> 19 #include <image.h> 20 #include <Messenger.h> 21 #include <OS.h> 22 23 #include <ServerLink.h> 24 #include <ServerProtocol.h> 25 26 27 namespace BPrivate { 28 29 30 static team_id sCurrentTeam = -1; 31 32 33 /*! \brief Returns the path to an application's executable. 34 \param team The application's team ID. 35 \param buffer A pointer to a pre-allocated character array of at least 36 size B_PATH_NAME_LENGTH to be filled in by this function. 37 \return 38 - \c B_OK: Everything went fine. 39 - \c B_BAD_VALUE: \c NULL \a buffer. 40 - another error code 41 */ 42 status_t 43 get_app_path(team_id team, char *buffer) 44 { 45 // The only way to get the path to the application's executable seems to 46 // be to get an image_info of its image, which also contains a path. 47 // Several images may belong to the team (libraries, add-ons), but only 48 // the one in question should be typed B_APP_IMAGE. 49 if (!buffer) 50 return B_BAD_VALUE; 51 52 image_info info; 53 int32 cookie = 0; 54 55 while (get_next_image_info(team, &cookie, &info) == B_OK) { 56 if (info.type == B_APP_IMAGE) { 57 strlcpy(buffer, info.name, B_PATH_NAME_LENGTH - 1); 58 return B_OK; 59 } 60 } 61 62 return B_ENTRY_NOT_FOUND; 63 } 64 65 66 /*! \brief Returns the path to the application's executable. 67 \param buffer A pointer to a pre-allocated character array of at least 68 size B_PATH_NAME_LENGTH to be filled in by this function. 69 \return 70 - \c B_OK: Everything went fine. 71 - \c B_BAD_VALUE: \c NULL \a buffer. 72 - another error code 73 */ 74 status_t 75 get_app_path(char *buffer) 76 { 77 return get_app_path(B_CURRENT_TEAM, buffer); 78 } 79 80 81 /*! \brief Returns an entry_ref referring to an application's executable. 82 \param team The application's team ID. 83 \param ref A pointer to a pre-allocated entry_ref to be initialized 84 to an entry_ref referring to the application's executable. 85 \param traverse If \c true, the function traverses symbolic links. 86 \return 87 - \c B_OK: Everything went fine. 88 - \c B_BAD_VALUE: \c NULL \a ref. 89 - another error code 90 */ 91 status_t 92 get_app_ref(team_id team, entry_ref *ref, bool traverse) 93 { 94 status_t error = (ref ? B_OK : B_BAD_VALUE); 95 char appFilePath[B_PATH_NAME_LENGTH]; 96 97 if (error == B_OK) 98 error = get_app_path(team, appFilePath); 99 100 if (error == B_OK) { 101 BEntry entry(appFilePath, traverse); 102 error = entry.GetRef(ref); 103 } 104 105 return error; 106 } 107 108 109 /*! \brief Returns an entry_ref referring to the application's executable. 110 \param ref A pointer to a pre-allocated entry_ref to be initialized 111 to an entry_ref referring to the application's executable. 112 \param traverse If \c true, the function traverses symbolic links. 113 \return 114 - \c B_OK: Everything went fine. 115 - \c B_BAD_VALUE: \c NULL \a ref. 116 - another error code 117 */ 118 status_t 119 get_app_ref(entry_ref *ref, bool traverse) 120 { 121 return get_app_ref(B_CURRENT_TEAM, ref, traverse); 122 } 123 124 125 /*! \brief Returns the ID of the current team. 126 \return The ID of the current team. 127 */ 128 team_id 129 current_team() 130 { 131 if (sCurrentTeam < 0) { 132 thread_info info; 133 if (get_thread_info(find_thread(NULL), &info) == B_OK) 134 sCurrentTeam = info.team; 135 } 136 return sCurrentTeam; 137 } 138 139 140 void 141 init_team_after_fork() 142 { 143 sCurrentTeam = -1; 144 } 145 146 147 /*! Returns the ID of the supplied team's main thread. 148 \param team The team. 149 \return 150 - The thread ID of the supplied team's main thread 151 - \c B_BAD_TEAM_ID: The supplied team ID does not identify a running team. 152 - another error code 153 */ 154 thread_id 155 main_thread_for(team_id team) 156 { 157 // Under Haiku the team ID is equal to it's main thread ID. We just get 158 // a team info to verify the existence of the team. 159 team_info info; 160 status_t error = get_team_info(team, &info); 161 return error == B_OK ? team : error; 162 } 163 164 165 /*! \brief Returns whether the application identified by the supplied 166 \c team_id is currently showing a modal window. 167 \param team the ID of the application in question. 168 \return \c true, if the application is showing a modal window, \c false 169 otherwise. 170 */ 171 bool 172 is_app_showing_modal_window(team_id team) 173 { 174 // TODO: Implement! 175 return true; 176 } 177 178 179 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST 180 181 182 /*! Creates a connection with the desktop. 183 */ 184 status_t 185 create_desktop_connection(ServerLink* link, const char* name, int32 capacity) 186 { 187 // Create the port so that the app_server knows where to send messages 188 port_id clientPort = create_port(capacity, name); 189 if (clientPort < 0) 190 return clientPort; 191 192 link->SetReceiverPort(clientPort); 193 194 BMessage request(AS_GET_DESKTOP); 195 request.AddInt32("user", getuid()); 196 request.AddInt32("version", AS_PROTOCOL_VERSION); 197 request.AddString("target", getenv("TARGET_SCREEN")); 198 199 BMessenger server("application/x-vnd.Haiku-app_server"); 200 BMessage reply; 201 status_t status = server.SendMessage(&request, &reply); 202 if (status != B_OK) 203 return status; 204 205 port_id desktopPort = reply.GetInt32("port", B_ERROR); 206 if (desktopPort < 0) 207 return desktopPort; 208 209 link->SetSenderPort(desktopPort); 210 return B_OK; 211 } 212 213 214 #else // HAIKU_TARGET_PLATFORM_LIBBE_TEST 215 216 217 static port_id sServerPort = -1; 218 219 220 port_id 221 get_app_server_port() 222 { 223 if (sServerPort < 0) { 224 // No need for synchronization - in the worst case, we'll call 225 // find_port() twice. 226 sServerPort = find_port(SERVER_PORT_NAME); 227 } 228 229 return sServerPort; 230 } 231 232 233 /*! Creates a connection with the desktop. 234 */ 235 status_t 236 create_desktop_connection(ServerLink* link, const char* name, int32 capacity) 237 { 238 port_id serverPort = get_app_server_port(); 239 if (serverPort < 0) 240 return serverPort; 241 242 // Create the port so that the app_server knows where to send messages 243 port_id clientPort = create_port(capacity, name); 244 if (clientPort < 0) 245 return clientPort; 246 247 link->SetTo(serverPort, clientPort); 248 249 link->StartMessage(AS_GET_DESKTOP); 250 link->Attach<port_id>(clientPort); 251 link->Attach<int32>(getuid()); 252 link->AttachString(getenv("TARGET_SCREEN")); 253 link->Attach<int32>(AS_PROTOCOL_VERSION); 254 255 int32 code; 256 if (link->FlushWithReply(code) != B_OK || code != B_OK) { 257 link->SetSenderPort(-1); 258 return B_ERROR; 259 } 260 261 link->Read<port_id>(&serverPort); 262 link->SetSenderPort(serverPort); 263 264 return B_OK; 265 } 266 267 268 #endif // HAIKU_TARGET_PLATFORM_LIBBE_TEST 269 270 271 } // namespace BPrivate 272