VirtualBox

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

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

warning

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.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// #define LOG_GROUP LOG_GROUP_DEV_VMM_BACKDOOR
20
21#include <VBox/VBoxGuest.h>
22#include <VBox/log.h>
23#include <iprt/initterm.h>
24
25#include <iostream>
26
27#include <sys/types.h>
28#include <stdlib.h> /* For exit */
29#include <unistd.h>
30#include <getopt.h>
31#include <errno.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
45static bool gbDaemonise = true;
46static int (*gpfnOldIOErrorHandler)(Display *) = NULL;
47
48/**
49 * Drop the programmes privileges to the caller's.
50 * @returns IPRT status code
51 * @todo move this into the R3 guest library
52 */
53int vboxClientDropPrivileges(void)
54{
55 int rc = VINF_SUCCESS;
56 int rcSystem, rcErrno;
57
58#ifdef _POSIX_SAVED_IDS
59 rcSystem = setuid(getuid());
60#else
61 rcSystem = setreuid(-1, getuid());
62#endif
63 if (rcSystem < 0)
64 {
65 rcErrno = errno;
66 rc = RTErrConvertFromErrno(rcErrno);
67 LogRel(("VBoxClient: failed to drop privileges, error %Rrc.\n", rc));
68 }
69 return rc;
70}
71
72/**
73 * Xlib error handler for certain errors that we can't avoid.
74 */
75int vboxClientXLibErrorHandler(Display *pDisplay, XErrorEvent *pError)
76{
77 char errorText[1024];
78
79 if (pError->error_code == BadAtom)
80 {
81 /* This can be triggered in debug builds if a guest application passes a bad atom
82 in its list of supported clipboard formats. As such it is harmless. */
83 Log(("VBoxClient: ignoring BadAtom error and returning\n"));
84 return 0;
85 }
86 if (pError->error_code == BadWindow)
87 {
88 /* This can be triggered if a guest application destroys a window before we notice. */
89 Log(("VBoxClient: ignoring BadWindow error and returning\n"));
90 return 0;
91 }
92#ifdef VBOX_X11_CLIPBOARD
93 vboxClipboardDisconnect();
94#endif
95 XGetErrorText(pDisplay, pError->error_code, errorText, sizeof(errorText));
96 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));
97 VbglR3Term();
98 exit(1);
99}
100
101/**
102 * Xlib error handler for fatal errors. This often means that the programme is still running
103 * when X exits.
104 */
105int vboxClientXLibIOErrorHandler(Display *pDisplay)
106{
107 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"));
108 VbglR3Term();
109 return gpfnOldIOErrorHandler(pDisplay);
110}
111
112int main(int argc, char *argv[])
113{
114 int rcClipboard, rc = VINF_SUCCESS;
115#ifdef DYNAMIC_RESIZE
116 VBoxGuestDisplayChangeMonitor displayChange;
117# ifdef SEAMLESS_GUEST
118 /** Our instance of the seamless class. This only makes sense if dynamic resizing
119 is enabled. */
120 VBoxGuestSeamless seamless;
121# endif /* SEAMLESS_GUEST defined */
122#endif /* DYNAMIC_RESIZE */
123
124 /* Parse our option(s) */
125/** @todo r=bird: use RTGetOpt */
126 while (1)
127 {
128 static struct option sOpts[] =
129 {
130 {"nodaemon", 0, 0, 'd'},
131 {0, 0, 0, 0}
132 };
133 int cOpt = getopt_long(argc, argv, "", sOpts, 0);
134 if (cOpt == -1)
135 {
136 if (optind < argc)
137 {
138 std::cout << "Unrecognized command line argument: " << argv[argc] << std::endl;
139 exit(1);
140 }
141 break;
142 }
143 switch(cOpt)
144 {
145 case 'd':
146 gbDaemonise = false;
147 break;
148 default:
149 std::cout << "Unrecognized command line option: " << static_cast<char>(cOpt)
150 << std::endl;
151 case '?':
152 exit(1);
153 }
154 }
155 if (gbDaemonise)
156 {
157 rc = VbglR3Daemonize(false /* fNoChDir */, false /* fNoClose */);
158 if (RT_FAILURE(rc))
159 {
160 std::cout << "VBoxClient: failed to daemonize. exiting."<< std::endl;
161 return 1;
162 }
163 }
164 /* Initialise our runtime before all else. */
165 RTR3Init(false);
166 if (RT_FAILURE(VbglR3Init()))
167 {
168 std::cout << "Failed to connect to the VirtualBox kernel service" << std::endl;
169 return 1;
170 }
171 if (RT_FAILURE(vboxClientDropPrivileges()))
172 return 1;
173 LogRel(("VBoxClient: starting...\n"));
174 /* Initialise threading in X11 and in Xt. */
175 if (!XInitThreads() || !XtToolkitThreadInitialize())
176 {
177 LogRel(("VBoxClient: error initialising threads in X11, exiting."));
178 return 1;
179 }
180 /* Set an X11 error handler, so that we don't die when we get unavoidable errors. */
181 XSetErrorHandler(vboxClientXLibErrorHandler);
182 /* Set an X11 I/O error handler, so that we can shutdown properly on fatal errors. */
183 gpfnOldIOErrorHandler = XSetIOErrorHandler(vboxClientXLibIOErrorHandler);
184#ifdef VBOX_X11_CLIPBOARD
185 /* Connect to the host clipboard. */
186 LogRel(("VBoxClient: starting clipboard Guest Additions...\n"));
187 rcClipboard = vboxClipboardConnect();
188 if (RT_FAILURE(rcClipboard))
189 {
190 LogRel(("VBoxClient: vboxClipboardConnect failed with rc = %Rrc\n", rc));
191 }
192#endif /* VBOX_X11_CLIPBOARD defined */
193 try
194 {
195#ifdef DYNAMIC_RESIZE
196 LogRel(("VBoxClient: starting dynamic guest resizing...\n"));
197 rc = displayChange.init();
198 if (RT_FAILURE(rc))
199 {
200 LogRel(("VBoxClient: failed to start dynamic guest resizing, rc = %Rrc\n", rc));
201 }
202# ifdef SEAMLESS_GUEST
203 if (RT_SUCCESS(rc))
204 {
205 LogRel(("VBoxClient: starting seamless Guest Additions...\n"));
206 rc = seamless.init();
207 if (RT_FAILURE(rc))
208 {
209 LogRel(("VBoxClient: failed to start seamless Additions, rc = %Rrc\n", rc));
210 }
211 }
212# endif /* SEAMLESS_GUEST defined */
213#endif /* DYNAMIC_RESIZE defined */
214 }
215 catch (std::exception e)
216 {
217 LogRel(("VBoxClient: failed to initialise seamless Additions - caught exception: %s\n", e.what()));
218 rc = VERR_UNRESOLVED_ERROR;
219 }
220 catch (...)
221 {
222 LogRel(("VBoxClient: failed to initialise seamless Additions - caught unknown exception.\n"));
223 rc = VERR_UNRESOLVED_ERROR;
224 }
225#ifdef VBOX_X11_CLIPBOARD
226 if (RT_SUCCESS(rcClipboard))
227 {
228 LogRel(("VBoxClient: connecting to the shared clipboard service.\n"));
229 vboxClipboardMain();
230 vboxClipboardDisconnect();
231 }
232#else /* VBOX_X11_CLIPBOARD not defined */
233 LogRel(("VBoxClient: sleeping...\n"));
234 pause();
235 LogRel(("VBoxClient: exiting...\n"));
236#endif /* VBOX_X11_CLIPBOARD not defined */
237 try
238 {
239#ifdef DYNAMIC_RESIZE
240 displayChange.uninit();
241# ifdef SEAMLESS_GUEST
242 seamless.uninit();
243# endif /* SEAMLESS_GUEST defined */
244#endif /* DYNAMIC_RESIZE defined */
245 }
246 catch (std::exception e)
247 {
248 LogRel(("VBoxClient: error shutting down seamless Additions - caught exception: %s\n", e.what()));
249 rc = VERR_UNRESOLVED_ERROR;
250 }
251 catch (...)
252 {
253 LogRel(("VBoxClient: error shutting down seamless Additions - caught unknown exception.\n"));
254 rc = VERR_UNRESOLVED_ERROR;
255 }
256 VbglR3Term();
257 return RT_SUCCESS(rc) ? 0 : 1;
258}
Note: See TracBrowser for help on using the repository browser.

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