vfs: check userland buffers before reading them.
[haiku.git] / src / servers / app / AppServer.cpp
bloba69f97432b46716e1e865109819534cde04821ab
1 /*
2 * Copyright 2001-2016, Haiku, Inc.
3 * Distributed under the terms of the MIT license.
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
13 #include "AppServer.h"
15 #include <syslog.h>
17 #include <LaunchRoster.h>
18 #include <PortLink.h>
20 #include "BitmapManager.h"
21 #include "Desktop.h"
22 #include "FontManager.h"
23 #include "InputManager.h"
24 #include "ScreenManager.h"
25 #include "ServerProtocol.h"
28 //#define DEBUG_SERVER
29 #ifdef DEBUG_SERVER
30 # include <stdio.h>
31 # define STRACE(x) printf x
32 #else
33 # define STRACE(x) ;
34 #endif
37 // Globals
38 port_id gAppServerPort;
39 BTokenSpace gTokenSpace;
40 uint32 gAppServerSIMDFlags = 0;
43 /*! \brief Constructor
45 This loads the default fonts, allocates all the major global variables,
46 spawns the main housekeeping threads, loads user preferences for the UI
47 and decorator, and allocates various locks.
49 AppServer::AppServer(status_t* status)
51 SERVER_BASE("application/x-vnd.Haiku-app_server", "picasso", -1, false,
52 status),
53 fDesktopLock("AppServerDesktopLock")
55 openlog("app_server", 0, LOG_DAEMON);
57 gInputManager = new InputManager();
59 // Create the font server and scan the proper directories.
60 gFontManager = new FontManager;
61 if (gFontManager->InitCheck() != B_OK)
62 debugger("font manager could not be initialized!");
64 gFontManager->Run();
66 gScreenManager = new ScreenManager();
67 gScreenManager->Run();
69 // Create the bitmap allocator. Object declared in BitmapManager.cpp
70 gBitmapManager = new BitmapManager();
72 // TODO: check the attached displays, and launch login session for them
73 BMessage data;
74 data.AddString("name", "app_server");
75 data.AddInt32("session", 0);
76 BLaunchRoster().Target("login", data);
80 /*! \brief Destructor
81 Reached only when the server is asked to shut down in Test mode.
83 AppServer::~AppServer()
85 delete gBitmapManager;
87 gScreenManager->Lock();
88 gScreenManager->Quit();
90 gFontManager->Lock();
91 gFontManager->Quit();
93 closelog();
97 void
98 AppServer::MessageReceived(BMessage* message)
100 switch (message->what) {
101 case AS_GET_DESKTOP:
103 Desktop* desktop = NULL;
105 int32 userID = message->GetInt32("user", 0);
106 int32 version = message->GetInt32("version", 0);
107 const char* targetScreen = message->GetString("target");
109 if (version != AS_PROTOCOL_VERSION) {
110 syslog(LOG_ERR, "Application for user %" B_PRId32 " does not "
111 "support the current server protocol (%" B_PRId32 ").\n",
112 userID, version);
113 } else {
114 desktop = _FindDesktop(userID, targetScreen);
115 if (desktop == NULL) {
116 // we need to create a new desktop object for this user
117 // TODO: test if the user exists on the system
118 // TODO: maybe have a separate AS_START_DESKTOP_SESSION for
119 // authorizing the user
120 desktop = _CreateDesktop(userID, targetScreen);
124 BMessage reply;
125 if (desktop != NULL)
126 reply.AddInt32("port", desktop->MessagePort());
127 else
128 reply.what = (uint32)B_ERROR;
130 message->SendReply(&reply);
131 break;
134 default:
135 // We don't allow application scripting
136 STRACE(("AppServer received unexpected code %" B_PRId32 "\n",
137 message->what));
138 break;
143 bool
144 AppServer::QuitRequested()
146 #if TEST_MODE
147 while (fDesktops.CountItems() > 0) {
148 Desktop *desktop = fDesktops.RemoveItemAt(0);
150 thread_id thread = desktop->Thread();
151 desktop->PostMessage(B_QUIT_REQUESTED);
153 // we just wait for the desktop to kill itself
154 status_t status;
155 wait_for_thread(thread, &status);
158 delete this;
159 exit(0);
161 return SERVER_BASE::QuitRequested();
162 #else
163 return false;
164 #endif
169 /*! \brief Creates a desktop object for an authorized user
171 Desktop*
172 AppServer::_CreateDesktop(uid_t userID, const char* targetScreen)
174 BAutolock locker(fDesktopLock);
175 Desktop* desktop = NULL;
176 try {
177 desktop = new Desktop(userID, targetScreen);
179 status_t status = desktop->Init();
180 if (status == B_OK)
181 status = desktop->Run();
182 if (status == B_OK && !fDesktops.AddItem(desktop))
183 status = B_NO_MEMORY;
185 if (status != B_OK) {
186 syslog(LOG_ERR, "Cannot initialize Desktop object: %s\n",
187 strerror(status));
188 delete desktop;
189 return NULL;
191 } catch (...) {
192 // there is obviously no memory left
193 return NULL;
196 return desktop;
200 /*! \brief Finds the desktop object that belongs to a certain user
202 Desktop*
203 AppServer::_FindDesktop(uid_t userID, const char* targetScreen)
205 BAutolock locker(fDesktopLock);
207 for (int32 i = 0; i < fDesktops.CountItems(); i++) {
208 Desktop* desktop = fDesktops.ItemAt(i);
210 if (desktop->UserID() == userID
211 && ((desktop->TargetScreen() == NULL && targetScreen == NULL)
212 || (desktop->TargetScreen() != NULL && targetScreen != NULL
213 && strcmp(desktop->TargetScreen(), targetScreen) == 0))) {
214 return desktop;
218 return NULL;
222 // #pragma mark -
226 main(int argc, char** argv)
228 srand(real_time_clock_usecs());
230 status_t status;
231 AppServer* server = new AppServer(&status);
232 if (status == B_OK)
233 server->Run();
235 return status == B_OK ? EXIT_SUCCESS : EXIT_FAILURE;