VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/xclient/main.cpp@ 7579

Last change on this file since 7579 was 7449, checked in by vboxsync, 17 years ago

Additions/x11: added flow logging statements to the VBoxClient code

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.7 KB
Line 
1/** @file
2 *
3 * VirtualBox Guest Service:
4 * Linux guest.
5 */
6
7/*
8 * Copyright (C) 2006-2007 innotek GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include <VBox/VBoxGuest.h>
20#include <VBox/log.h>
21#include <iprt/initterm.h>
22#include <iprt/path.h>
23
24#include <iostream>
25#include <cstdio>
26
27#include <sys/types.h>
28#include <stdlib.h> /* For exit */
29#include <unistd.h>
30#include <errno.h>
31#include <signal.h>
32
33#include <X11/Xlib.h>
34#include <X11/Intrinsic.h>
35
36#include "clipboard.h"
37
38#ifdef DYNAMIC_RESIZE
39# include "displaychange.h"
40# ifdef SEAMLESS_GUEST
41# include "seamless.h"
42# endif
43#endif
44
45#define TRACE printf("%s: %d\n", __PRETTY_FUNCTION__, __LINE__); Log(("%s: %d\n", __PRETTY_FUNCTION__, __LINE__))
46
47static int (*gpfnOldIOErrorHandler)(Display *) = NULL;
48
49/* Make these global so that the destructors are called if we make an "emergency exit",
50 i.e. a (handled) signal or an X11 error. */
51#ifdef DYNAMIC_RESIZE
52VBoxGuestDisplayChangeMonitor gDisplayChange;
53# ifdef SEAMLESS_GUEST
54 /** Our instance of the seamless class. This only makes sense if dynamic resizing
55 is enabled. */
56 VBoxGuestSeamless gSeamless;
57# endif /* SEAMLESS_GUEST defined */
58#endif /* DYNAMIC_RESIZE */
59#ifdef VBOX_X11_CLIPBOARD
60 VBoxGuestClipboard gClipboard;
61#endif
62
63/**
64 * Drop the programmes privileges to the caller's.
65 * @returns IPRT status code
66 * @todo move this into the R3 guest library
67 */
68int vboxClientDropPrivileges(void)
69{
70 int rc = VINF_SUCCESS;
71 int rcSystem, rcErrno;
72
73 LogFlowFunc(("\n"));
74#ifdef _POSIX_SAVED_IDS
75 rcSystem = setuid(getuid());
76#else
77 rcSystem = setreuid(-1, getuid());
78#endif
79 if (rcSystem < 0)
80 {
81 rcErrno = errno;
82 rc = RTErrConvertFromErrno(rcErrno);
83 LogRel(("VBoxClient: failed to drop privileges, error %Rrc.\n", rc));
84 }
85 LogFlowFunc(("returning %Rrc\n", rc));
86 return rc;
87}
88
89/**
90 * Xlib error handler for certain errors that we can't avoid.
91 */
92int vboxClientXLibErrorHandler(Display *pDisplay, XErrorEvent *pError)
93{
94 char errorText[1024];
95
96 if (pError->error_code == BadAtom)
97 {
98 /* This can be triggered in debug builds if a guest application passes a bad atom
99 in its list of supported clipboard formats. As such it is harmless. */
100 Log(("VBoxClient: ignoring BadAtom error and returning\n"));
101 return 0;
102 }
103 if (pError->error_code == BadWindow)
104 {
105 /* This can be triggered if a guest application destroys a window before we notice. */
106 Log(("VBoxClient: ignoring BadWindow error and returning\n"));
107 return 0;
108 }
109 XGetErrorText(pDisplay, pError->error_code, errorText, sizeof(errorText));
110 LogRel(("VBoxClient: an X Window protocol error occurred: %s (error code %d). Request code: %d, minor code: %d, serial number: %d\n", errorText, pError->error_code, pError->request_code, pError->minor_code, pError->serial));
111 VbglR3Term();
112 exit(1);
113}
114
115/**
116 * Xlib error handler for fatal errors. This often means that the programme is still running
117 * when X exits.
118 */
119int vboxClientXLibIOErrorHandler(Display *pDisplay)
120{
121 Log(("VBoxClient: a fatal guest X Window error occurred. This may just mean that the Window system was shut down while the client was still running.\n"));
122 VbglR3Term();
123 return gpfnOldIOErrorHandler(pDisplay);
124}
125
126/**
127 * A standard signal handler which cleans up and exits. Our global static objects will
128 * be cleaned up properly as we exit using "exit".
129 */
130void vboxClientSignalHandler(int cSignal)
131{
132 Log(("VBoxClient: terminated with signal %d\n", cSignal));
133 /* Our pause() call will now return and exit. */
134}
135
136/**
137 * Reset all standard termination signals to call our signal handler, which cleans up
138 * and exits.
139 */
140void vboxClientSetSignalHandlers(void)
141{
142 struct sigaction sigAction;
143
144 LogFlowFunc(("\n"));
145 sigAction.sa_handler = vboxClientSignalHandler;
146 sigemptyset(&sigAction.sa_mask);
147 sigAction.sa_flags = 0;
148 sigaction(SIGHUP, &sigAction, NULL);
149 sigaction(SIGINT, &sigAction, NULL);
150 sigaction(SIGQUIT, &sigAction, NULL);
151 sigaction(SIGABRT, &sigAction, NULL);
152 sigaction(SIGPIPE, &sigAction, NULL);
153 sigaction(SIGALRM, &sigAction, NULL);
154 sigaction(SIGTERM, &sigAction, NULL);
155 sigaction(SIGUSR1, &sigAction, NULL);
156 sigaction(SIGUSR2, &sigAction, NULL);
157 LogFlowFunc(("returning\n"));
158}
159
160/**
161 * Print out a usage message and exit with success.
162 */
163void vboxClientUsage(const char *pcszFileName)
164{
165 /* printf is better for i18n than iostream. */
166 printf("Usage: %s [-d|--nodaemon]\n", pcszFileName);
167 printf("Start the VirtualBox X Window System guest services.\n\n");
168 printf("Options:\n");
169 printf(" -d, --nodaemon do not lower privileges and continue running as a system\n");
170 printf(" service\n");
171 exit(0);
172}
173
174/**
175 * The main loop for the VBoxClient daemon.
176 */
177int main(int argc, char *argv[])
178{
179 int rcClipboard, rc = VINF_SUCCESS;
180 const char *pszFileName = RTPathFilename(argv[0]);
181 bool fDaemonise = true;
182
183 if (NULL == pszFileName)
184 pszFileName = "VBoxClient";
185
186 /* Parse our option(s) */
187 /** @todo Use RTGetOpt() if the arguments become more complex. */
188 for (int i = 1; i < argc; ++i)
189 {
190 if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--nodaemon"))
191 fDaemonise = false;
192 else if (!strcmp(argv[i], "-h") || strcmp(argv[i], "--help"))
193 {
194 vboxClientUsage(pszFileName);
195 exit(0);
196 }
197 else
198 {
199 /* printf is better than iostream for i18n. */
200 printf("%s: unrecognized option `%s'\n", pszFileName, argv[i]);
201 printf("Try `%s --help' for more information\n", pszFileName);
202 exit(1);
203 }
204 }
205 if (fDaemonise)
206 {
207 rc = VbglR3Daemonize(false /* fNoChDir */, false /* fNoClose */);
208 if (RT_FAILURE(rc))
209 {
210 std::cout << "VBoxClient: failed to daemonize. exiting."<< std::endl;
211 return 1;
212 }
213 }
214 /* Initialise our runtime before all else. */
215 RTR3Init(false);
216 if (RT_FAILURE(VbglR3Init()))
217 {
218 std::cout << "Failed to connect to the VirtualBox kernel service" << std::endl;
219 return 1;
220 }
221 if (fDaemonise && RT_FAILURE(vboxClientDropPrivileges()))
222 return 1;
223 LogRel(("VBoxClient: starting...\n"));
224 /* Initialise threading in X11 and in Xt. */
225 if (!XInitThreads() || !XtToolkitThreadInitialize())
226 {
227 LogRel(("VBoxClient: error initialising threads in X11, exiting."));
228 return 1;
229 }
230 /* Set an X11 error handler, so that we don't die when we get unavoidable errors. */
231 XSetErrorHandler(vboxClientXLibErrorHandler);
232 /* Set an X11 I/O error handler, so that we can shutdown properly on fatal errors. */
233 gpfnOldIOErrorHandler = XSetIOErrorHandler(vboxClientXLibIOErrorHandler);
234 vboxClientSetSignalHandlers();
235 try
236 {
237#ifdef VBOX_X11_CLIPBOARD
238 /* Connect to the host clipboard. */
239 LogRel(("VBoxClient: starting clipboard Guest Additions...\n"));
240 rcClipboard = gClipboard.init();
241 if (RT_FAILURE(rcClipboard))
242 {
243 LogRel(("VBoxClient: vboxClipboardConnect failed with rc = %Rrc\n", rc));
244 }
245#endif /* VBOX_X11_CLIPBOARD defined */
246#ifdef DYNAMIC_RESIZE
247 LogRel(("VBoxClient: starting dynamic guest resizing...\n"));
248 rc = gDisplayChange.init();
249 if (RT_FAILURE(rc))
250 {
251 LogRel(("VBoxClient: failed to start dynamic guest resizing, rc = %Rrc\n", rc));
252 }
253# ifdef SEAMLESS_GUEST
254 if (RT_SUCCESS(rc))
255 {
256 LogRel(("VBoxClient: starting seamless Guest Additions...\n"));
257 rc = gSeamless.init();
258 if (RT_FAILURE(rc))
259 {
260 LogRel(("VBoxClient: failed to start seamless Additions, rc = %Rrc\n", rc));
261 }
262 }
263# endif /* SEAMLESS_GUEST defined */
264#endif /* DYNAMIC_RESIZE defined */
265 }
266 catch (std::exception e)
267 {
268 LogRel(("VBoxClient: failed to initialise Guest Additions - caught exception: %s\n", e.what()));
269 rc = VERR_UNRESOLVED_ERROR;
270 }
271 catch (...)
272 {
273 LogRel(("VBoxClient: failed to initialise Guest Additions - caught unknown exception.\n"));
274 rc = VERR_UNRESOLVED_ERROR;
275 }
276 LogRel(("VBoxClient: sleeping...\n"));
277 pause();
278 LogRel(("VBoxClient: exiting...\n"));
279 try
280 {
281#ifdef DYNAMIC_RESIZE
282# ifdef SEAMLESS_GUEST
283 LogRel(("VBoxClient: shutting down seamless Guest Additions...\n"));
284 gSeamless.uninit(2000);
285# endif /* SEAMLESS_GUEST defined */
286 LogRel(("VBoxClient: shutting down dynamic guest resizing...\n"));
287 gDisplayChange.uninit(2000);
288#endif /* DYNAMIC_RESIZE defined */
289#ifdef VBOX_X11_CLIPBOARD
290 /* Connect to the host clipboard. */
291 LogRel(("VBoxClient: shutting down clipboard Guest Additions...\n"));
292 gClipboard.uninit(2000);
293#endif /* VBOX_X11_CLIPBOARD defined */
294 }
295 catch (std::exception e)
296 {
297 LogRel(("VBoxClient: failed to shut down Guest Additions - caught exception: %s\n", e.what()));
298 rc = VERR_UNRESOLVED_ERROR;
299 }
300 catch (...)
301 {
302 LogRel(("VBoxClient: failed to shut down Guest Additions - caught unknown exception.\n"));
303 rc = VERR_UNRESOLVED_ERROR;
304 }
305 VbglR3Term();
306 return RT_SUCCESS(rc) ? 0 : 1;
307}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette