VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/VBoxClient/main.cpp@ 27709

Last change on this file since 27709 was 27709, checked in by vboxsync, 15 years ago

Additions/x11/VBoxClient: converted logging to release logging (which is opt-in at runtime in guest R3)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.9 KB
Line 
1/** @file
2 *
3 * VirtualBox Guest Service:
4 * Linux guest.
5 */
6
7/*
8 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23#include <sys/types.h>
24#include <stdlib.h> /* For exit */
25#include <stdio.h>
26#include <string.h>
27#include <unistd.h>
28#include <errno.h>
29#include <signal.h>
30
31#include <X11/Xlib.h>
32
33#include <iprt/env.h>
34#include <iprt/initterm.h>
35#include <iprt/path.h>
36#include <iprt/param.h>
37#include <iprt/stream.h>
38#include <iprt/string.h>
39#include <VBox/VBoxGuestLib.h>
40#include <VBox/log.h>
41
42#include "VBoxClient.h"
43
44#define TRACE RTPrintf("%s: %d\n", __PRETTY_FUNCTION__, __LINE__); LogRel(("%s: %d\n", __PRETTY_FUNCTION__, __LINE__))
45
46static int (*gpfnOldIOErrorHandler)(Display *) = NULL;
47
48/** Object representing the service we are running. This has to be global
49 * so that the cleanup routine can access it. */
50VBoxClient::Service *g_pService;
51/** The name of our pidfile. It is global for the benefit of the cleanup
52 * routine. */
53static char g_szPidFile[RTPATH_MAX];
54/** The file handle of our pidfile. It is global for the benefit of the
55 * cleanup routine. */
56static RTFILE g_hPidFile;
57
58/** Clean up if we get a signal or something. This is extern so that we
59 * can call it from other compilation units. */
60void VBoxClient::CleanUp()
61{
62 if (g_pService)
63 {
64 g_pService->cleanup();
65 delete g_pService;
66 }
67 if (g_szPidFile[0] && g_hPidFile)
68 VbglR3ClosePidFile(g_szPidFile, g_hPidFile);
69 VbglR3Term();
70 exit(0);
71}
72
73/**
74 * A standard signal handler which cleans up and exits.
75 */
76void vboxClientSignalHandler(int cSignal)
77{
78 LogRel(("VBoxClient: terminated with signal %d\n", cSignal));
79 /** Disable seamless mode */
80 RTPrintf(("VBoxClient: terminating...\n"));
81 VBoxClient::CleanUp();
82}
83
84/**
85 * Xlib error handler for certain errors that we can't avoid.
86 */
87int vboxClientXLibErrorHandler(Display *pDisplay, XErrorEvent *pError)
88{
89 char errorText[1024];
90
91 XGetErrorText(pDisplay, pError->error_code, errorText, sizeof(errorText));
92 LogRelFlow(("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));
93 return 0; /* We should never reach this. */
94}
95
96/**
97 * Xlib error handler for fatal errors. This often means that the programme is still running
98 * when X exits.
99 */
100static int vboxClientXLibIOErrorHandler(Display *pDisplay)
101{
102 LogRel(("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"));
103 VBoxClient::CleanUp();
104 return 0; /* We should never reach this. */
105}
106
107/**
108 * Reset all standard termination signals to call our signal handler, which
109 * cleans up and exits.
110 */
111void vboxClientSetSignalHandlers(void)
112{
113 struct sigaction sigAction;
114
115 LogRelFlowFunc(("\n"));
116 sigAction.sa_handler = vboxClientSignalHandler;
117 sigemptyset(&sigAction.sa_mask);
118 sigAction.sa_flags = 0;
119 sigaction(SIGHUP, &sigAction, NULL);
120 sigaction(SIGINT, &sigAction, NULL);
121 sigaction(SIGQUIT, &sigAction, NULL);
122 sigaction(SIGABRT, &sigAction, NULL);
123 sigaction(SIGPIPE, &sigAction, NULL);
124 sigaction(SIGALRM, &sigAction, NULL);
125 sigaction(SIGTERM, &sigAction, NULL);
126 sigaction(SIGUSR1, &sigAction, NULL);
127 sigaction(SIGUSR2, &sigAction, NULL);
128 LogRelFlowFunc(("returning\n"));
129}
130
131/**
132 * Print out a usage message and exit with success.
133 */
134void vboxClientUsage(const char *pcszFileName)
135{
136 RTPrintf("Usage: %s --clipboard|--display|--checkhostversion|--seamless [-d|--nodaemon]\n", pcszFileName);
137 RTPrintf("Start the VirtualBox X Window System guest services.\n\n");
138 RTPrintf("Options:\n");
139 RTPrintf(" --clipboard start the shared clipboard service\n");
140 RTPrintf(" --display start the display management service\n");
141# ifdef VBOX_WITH_GUEST_PROPS
142 RTPrintf(" --checkhostversion start the host version notifier service\n");
143# endif
144 RTPrintf(" --seamless start the seamless windows service\n");
145 RTPrintf(" -d, --nodaemon continue running as a system service\n");
146 RTPrintf("\n");
147 exit(0);
148}
149
150/**
151 * The main loop for the VBoxClient daemon.
152 */
153int main(int argc, char *argv[])
154{
155 int rcClipboard, rc = VINF_SUCCESS;
156 const char *pszFileName = RTPathFilename(argv[0]);
157 bool fDaemonise = true;
158 /* Have any fatal errors occurred yet? */
159 bool fSuccess = true;
160 /* Do we know which service we wish to run? */
161 bool fHaveService = false;
162
163 if (NULL == pszFileName)
164 pszFileName = "VBoxClient";
165
166 /* Initialise our runtime before all else. */
167 RTR3Init();
168
169 /* Parse our option(s) */
170 /** @todo Use RTGetOpt() if the arguments become more complex. */
171 for (int i = 1; i < argc; ++i)
172 {
173 if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--nodaemon"))
174 fDaemonise = false;
175 else if (!strcmp(argv[i], "--clipboard"))
176 {
177 if (g_pService == NULL)
178 g_pService = VBoxClient::GetClipboardService();
179 else
180 fSuccess = false;
181 }
182 else if (!strcmp(argv[i], "--display"))
183 {
184 if (g_pService == NULL)
185 g_pService = VBoxClient::GetDisplayService();
186 else
187 fSuccess = false;
188 }
189 else if (!strcmp(argv[i], "--seamless"))
190 {
191 if (g_pService == NULL)
192 g_pService = VBoxClient::GetSeamlessService();
193 else
194 fSuccess = false;
195 }
196 else if (!strcmp(argv[i], "--checkhostversion"))
197 {
198 if (g_pService == NULL)
199 g_pService = VBoxClient::GetHostVersionService();
200 else
201 fSuccess = false;
202 }
203 else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
204 {
205 vboxClientUsage(pszFileName);
206 exit(0);
207 }
208 else
209 {
210 RTPrintf("%s: unrecognized option `%s'\n", pszFileName, argv[i]);
211 RTPrintf("Try `%s --help' for more information\n", pszFileName);
212 exit(1);
213 }
214 }
215 if (!fSuccess || !g_pService)
216 {
217 vboxClientUsage(pszFileName);
218 exit(1);
219 }
220 if (fDaemonise)
221 {
222 rc = VbglR3Daemonize(false /* fNoChDir */, false /* fNoClose */);
223 if (RT_FAILURE(rc))
224 {
225 RTPrintf("VBoxClient: failed to daemonize. Exiting.\n");
226 LogRel(("VBoxClient: failed to daemonize. Exiting.\n"));
227# ifdef DEBUG
228 RTPrintf("Error %Rrc\n", rc);
229# endif
230 return 1;
231 }
232 }
233 /** @todo explain why we aren't using RTPathUserHome here so it doesn't get
234 * changed accidentally during some cleanup effort. */
235 rc = RTEnvGetEx(RTENV_DEFAULT, "HOME", g_szPidFile, sizeof(g_szPidFile), NULL);
236 if (RT_FAILURE(rc))
237 {
238 RTPrintf("VBoxClient: failed to get home directory, rc=%Rrc. Exiting.\n", rc);
239 LogRel(("VBoxClient: failed to get home directory, rc=%Rrc. Exiting.\n", rc));
240 return 1;
241 }
242 rc = RTPathAppend(g_szPidFile, sizeof(g_szPidFile), g_pService->getPidFilePath());
243 if (RT_FAILURE(rc))
244 {
245 RTPrintf("VBoxClient: RTPathAppend failed with rc=%Rrc. Exiting.\n", rc);
246 LogRel(("VBoxClient: RTPathAppend failed with rc=%Rrc. Exiting.\n", rc));
247 return 1;
248 }
249
250 /* Initialise the guest library. */
251 if (RT_FAILURE(VbglR3InitUser()))
252 {
253 RTPrintf("Failed to connect to the VirtualBox kernel service\n");
254 LogRel(("Failed to connect to the VirtualBox kernel service\n"));
255 return 1;
256 }
257 if (g_szPidFile[0] && RT_FAILURE(VbglR3PidFile(g_szPidFile, &g_hPidFile)))
258 {
259 RTPrintf("Failed to create a pidfile. Exiting.\n");
260 LogRel(("Failed to create a pidfile. Exiting.\n"));
261 VbglR3Term();
262 return 1;
263 }
264 /* Set signal handlers to clean up on exit. */
265 vboxClientSetSignalHandlers();
266 /* Set an X11 error handler, so that we don't die when we get unavoidable errors. */
267 XSetErrorHandler(vboxClientXLibErrorHandler);
268 /* Set an X11 I/O error handler, so that we can shutdown properly on fatal errors. */
269 XSetIOErrorHandler(vboxClientXLibIOErrorHandler);
270 g_pService->run(fDaemonise);
271 VBoxClient::CleanUp();
272 return 1; /* We should never get here. */
273}
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