1 /* 2 * Copyright 2001-2016, Haiku, Inc. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * DarkWyrm <bpmagic@columbus.rr.com> 7 * Axel Dörfler, axeld@pinc-software.de 8 * Stephan Aßmus <superstippi@gmx.de> 9 * Christian Packmann 10 */ 11 12 13 #include "AppServer.h" 14 15 #include <syslog.h> 16 17 #include <AutoDeleter.h> 18 #include <LaunchRoster.h> 19 #include <PortLink.h> 20 21 #include "BitmapManager.h" 22 #include "Desktop.h" 23 #include "FontManager.h" 24 #include "InputManager.h" 25 #include "ScreenManager.h" 26 #include "ServerProtocol.h" 27 28 29 //#define DEBUG_SERVER 30 #ifdef DEBUG_SERVER 31 # include <stdio.h> 32 # define STRACE(x) printf x 33 #else 34 # define STRACE(x) ; 35 #endif 36 37 38 // Globals 39 port_id gAppServerPort; 40 BTokenSpace gTokenSpace; 41 uint32 gAppServerSIMDFlags = 0; 42 43 44 /*! \brief Constructor 45 46 This loads the default fonts, allocates all the major global variables, 47 spawns the main housekeeping threads, loads user preferences for the UI 48 and decorator, and allocates various locks. 49 */ 50 AppServer::AppServer(status_t* status) 51 : 52 SERVER_BASE("application/x-vnd.Haiku-app_server", "picasso", -1, false, 53 status), 54 fDesktopLock("AppServerDesktopLock") 55 { 56 openlog("app_server", 0, LOG_DAEMON); 57 58 gInputManager = new InputManager(); 59 60 // Create the font server and scan the proper directories. 61 gFontManager = new FontManager; 62 if (gFontManager->InitCheck() != B_OK) 63 debugger("font manager could not be initialized!"); 64 65 gFontManager->Run(); 66 67 gScreenManager = new ScreenManager(); 68 gScreenManager->Run(); 69 70 // Create the bitmap allocator. Object declared in BitmapManager.cpp 71 gBitmapManager = new BitmapManager(); 72 73 #if 0 74 // This is not presently needed, as app_server is launched from the login session. 75 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST 76 // TODO: check the attached displays, and launch login session for them 77 BMessage data; 78 data.AddString("name", "app_server"); 79 data.AddInt32("session", 0); 80 BLaunchRoster().Target("login", data); 81 #endif 82 #endif 83 } 84 85 86 /*! \brief Destructor 87 Reached only when the server is asked to shut down in Test mode. 88 */ 89 AppServer::~AppServer() 90 { 91 delete gBitmapManager; 92 93 gScreenManager->Lock(); 94 gScreenManager->Quit(); 95 96 gFontManager->Lock(); 97 gFontManager->Quit(); 98 99 closelog(); 100 } 101 102 103 void 104 AppServer::MessageReceived(BMessage* message) 105 { 106 switch (message->what) { 107 case AS_GET_DESKTOP: 108 { 109 Desktop* desktop = NULL; 110 111 int32 userID = message->GetInt32("user", 0); 112 int32 version = message->GetInt32("version", 0); 113 const char* targetScreen = message->GetString("target"); 114 115 if (version != AS_PROTOCOL_VERSION) { 116 syslog(LOG_ERR, "Application for user %" B_PRId32 " does not " 117 "support the current server protocol (%" B_PRId32 ").\n", 118 userID, version); 119 } else { 120 desktop = _FindDesktop(userID, targetScreen); 121 if (desktop == NULL) { 122 // we need to create a new desktop object for this user 123 // TODO: test if the user exists on the system 124 // TODO: maybe have a separate AS_START_DESKTOP_SESSION for 125 // authorizing the user 126 desktop = _CreateDesktop(userID, targetScreen); 127 } 128 } 129 130 BMessage reply; 131 if (desktop != NULL) 132 reply.AddInt32("port", desktop->MessagePort()); 133 else 134 reply.what = (uint32)B_ERROR; 135 136 message->SendReply(&reply); 137 break; 138 } 139 140 default: 141 // We don't allow application scripting 142 STRACE(("AppServer received unexpected code %" B_PRId32 "\n", 143 message->what)); 144 break; 145 } 146 } 147 148 149 bool 150 AppServer::QuitRequested() 151 { 152 #if TEST_MODE 153 while (fDesktops.CountItems() > 0) { 154 Desktop *desktop = fDesktops.RemoveItemAt(0); 155 156 thread_id thread = desktop->Thread(); 157 desktop->PostMessage(B_QUIT_REQUESTED); 158 159 // we just wait for the desktop to kill itself 160 status_t status; 161 wait_for_thread(thread, &status); 162 } 163 164 delete this; 165 exit(0); 166 167 return SERVER_BASE::QuitRequested(); 168 #else 169 return false; 170 #endif 171 172 } 173 174 175 /*! \brief Creates a desktop object for an authorized user 176 */ 177 Desktop* 178 AppServer::_CreateDesktop(uid_t userID, const char* targetScreen) 179 { 180 BAutolock locker(fDesktopLock); 181 ObjectDeleter<Desktop> desktop; 182 try { 183 desktop.SetTo(new Desktop(userID, targetScreen)); 184 185 status_t status = desktop->Init(); 186 if (status == B_OK) 187 status = desktop->Run(); 188 if (status == B_OK && !fDesktops.AddItem(desktop.Get())) 189 status = B_NO_MEMORY; 190 191 if (status != B_OK) { 192 syslog(LOG_ERR, "Cannot initialize Desktop object: %s\n", 193 strerror(status)); 194 return NULL; 195 } 196 } catch (...) { 197 // there is obviously no memory left 198 return NULL; 199 } 200 201 return desktop.Detach(); 202 } 203 204 205 /*! \brief Finds the desktop object that belongs to a certain user 206 */ 207 Desktop* 208 AppServer::_FindDesktop(uid_t userID, const char* targetScreen) 209 { 210 BAutolock locker(fDesktopLock); 211 212 for (int32 i = 0; i < fDesktops.CountItems(); i++) { 213 Desktop* desktop = fDesktops.ItemAt(i); 214 215 if (desktop->UserID() == userID 216 && ((desktop->TargetScreen() == NULL && targetScreen == NULL) 217 || (desktop->TargetScreen() != NULL && targetScreen != NULL 218 && strcmp(desktop->TargetScreen(), targetScreen) == 0))) { 219 return desktop; 220 } 221 } 222 223 return NULL; 224 } 225 226 227 // #pragma mark - 228 229 230 int 231 main(int argc, char** argv) 232 { 233 srand(real_time_clock_usecs()); 234 235 status_t status; 236 AppServer* server = new AppServer(&status); 237 if (status == B_OK) 238 server->Run(); 239 240 return status == B_OK ? EXIT_SUCCESS : EXIT_FAILURE; 241 } 242