VirtualBox

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

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

Additions/x11/VBoxClient: detect X server termination and remove two unused files

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.8 KB
Line 
1/** @file
2 *
3 * VirtualBox Guest Service:
4 * Linux guest.
5 */
6
7/*
8 * Copyright (C) 2006-2007 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/stream.h>
37#include <iprt/string.h>
38#include <VBox/VBoxGuest.h>
39#include <VBox/log.h>
40
41#include "VBoxClient.h"
42
43#define TRACE RTPrintf("%s: %d\n", __PRETTY_FUNCTION__, __LINE__); Log(("%s: %d\n", __PRETTY_FUNCTION__, __LINE__))
44
45static int (*gpfnOldIOErrorHandler)(Display *) = NULL;
46
47/** Object representing the service we are running. This has to be global
48 * so that the cleanup routine can access it. */
49VBoxClient::Service *g_pService;
50/** The name of our pidfile. It is global for the benefit of the cleanup
51 * routine. */
52static char *g_pszPidFile;
53/** The file handle of our pidfile. It is global for the benefit of the
54 * cleanup routine. */
55static RTFILE g_hPidFile;
56
57/** Clean up if we get a signal or something. This is extern so that we
58 * can call it from other compilation units. */
59void VBoxClient::CleanUp()
60{
61 if (g_pService)
62 {
63 g_pService->cleanup();
64 delete g_pService;
65 }
66 if (g_pszPidFile && g_hPidFile)
67 VbglR3ClosePidFile(g_pszPidFile, g_hPidFile);
68 VbglR3Term();
69 exit(0);
70}
71
72/**
73 * A standard signal handler which cleans up and exits.
74 */
75void vboxClientSignalHandler(int cSignal)
76{
77 Log(("VBoxClient: terminated with signal %d\n", cSignal));
78 /** Disable seamless mode */
79 RTPrintf(("VBoxClient: terminating...\n"));
80 VBoxClient::CleanUp();
81}
82
83/**
84 * Xlib error handler for certain errors that we can't avoid.
85 */
86int vboxClientXLibErrorHandler(Display *pDisplay, XErrorEvent *pError)
87{
88 char errorText[1024];
89
90 if (pError->error_code == BadAtom)
91 {
92 /* This can be triggered in debug builds if a guest application passes a bad atom
93 in its list of supported clipboard formats. As such it is harmless. */
94 Log(("VBoxClient: ignoring BadAtom error and returning\n"));
95 return 0;
96 }
97 if (pError->error_code == BadWindow)
98 {
99 /* This can be triggered if a guest application destroys a window before we notice. */
100 Log(("VBoxClient: ignoring BadWindow error and returning\n"));
101 return 0;
102 }
103 XGetErrorText(pDisplay, pError->error_code, errorText, sizeof(errorText));
104 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));
105 VBoxClient::CleanUp();
106 return 0; /* We should never reach this. */
107}
108
109/**
110 * Xlib error handler for fatal errors. This often means that the programme is still running
111 * when X exits.
112 */
113static int vboxClientXLibIOErrorHandler(Display *pDisplay)
114{
115 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"));
116 VBoxClient::CleanUp();
117 return 0; /* We should never reach this. */
118}
119
120/**
121 * Reset all standard termination signals to call our signal handler, which
122 * cleans up and exits.
123 */
124void vboxClientSetSignalHandlers(void)
125{
126 struct sigaction sigAction;
127
128 LogFlowFunc(("\n"));
129 sigAction.sa_handler = vboxClientSignalHandler;
130 sigemptyset(&sigAction.sa_mask);
131 sigAction.sa_flags = 0;
132 sigaction(SIGHUP, &sigAction, NULL);
133 sigaction(SIGINT, &sigAction, NULL);
134 sigaction(SIGQUIT, &sigAction, NULL);
135 sigaction(SIGABRT, &sigAction, NULL);
136 sigaction(SIGPIPE, &sigAction, NULL);
137 sigaction(SIGALRM, &sigAction, NULL);
138 sigaction(SIGTERM, &sigAction, NULL);
139 sigaction(SIGUSR1, &sigAction, NULL);
140 sigaction(SIGUSR2, &sigAction, NULL);
141 LogFlowFunc(("returning\n"));
142}
143
144/**
145 * Print out a usage message and exit with success.
146 */
147void vboxClientUsage(const char *pcszFileName)
148{
149 RTPrintf("Usage: %s --clipboard|--autoresize|--seamless [-d|--nodaemon]\n", pcszFileName);
150 RTPrintf("Start the VirtualBox X Window System guest services.\n\n");
151 RTPrintf("Options:\n");
152 RTPrintf(" --clipboard start the shared clipboard service\n");
153 RTPrintf(" --autoresize start the display auto-resize service\n");
154 RTPrintf(" --seamless start the seamless windows service\n");
155 RTPrintf(" -d, --nodaemon continue running as a system service\n");
156 RTPrintf("\n");
157 exit(0);
158}
159
160/**
161 * The main loop for the VBoxClient daemon.
162 */
163int main(int argc, char *argv[])
164{
165 int rcClipboard, rc = VINF_SUCCESS;
166 const char *pszFileName = RTPathFilename(argv[0]);
167 bool fDaemonise = true;
168 /* Have any fatal errors occurred yet? */
169 bool fSuccess = true;
170 /* Do we know which service we wish to run? */
171 bool fHaveService = false;
172
173 if (NULL == pszFileName)
174 pszFileName = "VBoxClient";
175
176 /* Initialise our runtime before all else. */
177 RTR3Init();
178
179 /* Parse our option(s) */
180 /** @todo Use RTGetOpt() if the arguments become more complex. */
181 for (int i = 1; i < argc; ++i)
182 {
183 if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--nodaemon"))
184 fDaemonise = false;
185 else if (!strcmp(argv[i], "--clipboard"))
186 {
187 if (g_pService == NULL)
188 g_pService = VBoxClient::GetClipboardService();
189 else
190 fSuccess = false;
191 }
192 else if (!strcmp(argv[i], "--autoresize"))
193 {
194 if (g_pService == NULL)
195 g_pService = VBoxClient::GetAutoResizeService();
196 else
197 fSuccess = false;
198 }
199 else if (!strcmp(argv[i], "--seamless"))
200 {
201 if (g_pService == NULL)
202 g_pService = VBoxClient::GetSeamlessService();
203 else
204 fSuccess = false;
205 }
206 else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
207 {
208 vboxClientUsage(pszFileName);
209 exit(0);
210 }
211 else
212 {
213 RTPrintf("%s: unrecognized option `%s'\n", pszFileName, argv[i]);
214 RTPrintf("Try `%s --help' for more information\n", pszFileName);
215 exit(1);
216 }
217 }
218 if (!fSuccess || !g_pService)
219 {
220 vboxClientUsage(pszFileName);
221 exit(1);
222 }
223 if (fDaemonise)
224 {
225 rc = VbglR3Daemonize(false /* fNoChDir */, false /* fNoClose */);
226 if (RT_FAILURE(rc))
227 {
228 RTPrintf("VBoxClient: failed to daemonize. Exiting.\n");
229 Log(("VBoxClient: failed to daemonize. Exiting.\n"));
230#ifdef DEBUG
231 RTPrintf("Error %Rrc\n", rc);
232#endif
233 return 1;
234 }
235 }
236 const char *pszHome = RTEnvGet("HOME");
237 if (pszHome == NULL)
238 {
239 RTPrintf("VBoxClient: failed to get home directory. Exiting.\n");
240 Log(("VBoxClient: failed to get home directory. Exiting.\n"));
241 return 1;
242 }
243 if (RTStrAPrintf(&g_pszPidFile, "%s/%s", pszHome, g_pService->getPidFilePath()) == -1)
244 if (pszHome == NULL)
245 {
246 RTPrintf("VBoxClient: out of memory. Exiting.\n");
247 Log(("VBoxClient: out of memory. Exiting.\n"));
248 return 1;
249 }
250 /* Initialise the guest library. */
251 if (RT_FAILURE(VbglR3InitUser()))
252 {
253 RTPrintf("Failed to connect to the VirtualBox kernel service\n");
254 Log(("Failed to connect to the VirtualBox kernel service\n"));
255 return 1;
256 }
257 if (g_pszPidFile && RT_FAILURE(VbglR3PidFile(g_pszPidFile, &g_hPidFile)))
258 {
259 RTPrintf("Failed to create a pidfile. Exiting.\n");
260 Log(("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();
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