VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/xclient/main.cpp@ 5999

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

The Giant CDDL Dual-License Header Change.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.0 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
27using std::cout;
28using std::endl;
29
30#include <sys/types.h>
31#include <sys/stat.h> /* For umask */
32#include <fcntl.h> /* For open */
33#include <stdlib.h> /* For exit */
34#include <unistd.h>
35#include <getopt.h>
36
37#include <sys/time.h> /* For getrlimit */
38#include <sys/resource.h> /* For getrlimit */
39
40#include <X11/Xlib.h>
41#include <X11/Intrinsic.h>
42
43#include "clipboard.h"
44
45#ifdef SEAMLESS_LINUX
46# include "seamless.h"
47#endif
48
49static bool gbDaemonise = true;
50
51/**
52 * Go through the long Un*x ritual required to become a daemon process.
53 */
54void vboxDaemonise(void)
55{
56 /** rlimit structure for finding out how many open files we may have. */
57 struct rlimit rlim;
58
59 /* To make sure that we are not currently a session leader, we must first fork and let
60 the parent process exit, as a newly created child is never session leader. This will
61 allow us to call setsid() later. */
62 if (fork() != 0)
63 {
64 exit(0);
65 }
66 /* Find the maximum number of files we can have open and close them all. */
67 if (0 != getrlimit(RLIMIT_NOFILE, &rlim))
68 {
69 /* For some reason the call failed. In that case we will just close the three
70 standard files and hope. */
71 rlim.rlim_cur = 3;
72 }
73 for (unsigned int i = 0; i < rlim.rlim_cur; ++i)
74 {
75 close(i);
76 }
77 /* Change to the root directory to avoid keeping the one we were started in open. */
78 chdir("/");
79 /* Set our umask to zero. */
80 umask(0);
81 /* And open /dev/null on stdin/out/err. */
82 open("/dev/null", O_RDONLY);
83 open("/dev/null", O_WRONLY);
84 dup(1);
85 /* Detach from the controlling terminal by creating our own session, to avoid receiving
86 signals from the old session. */
87 setsid();
88 /* And fork again, letting the parent exit, to make us a child of init and avoid zombies. */
89 if (fork() != 0)
90 {
91 exit(0);
92 }
93}
94
95/**
96 * Xlib error handler, so that we don't abort when we get a BadAtom error.
97 */
98int vboxClipboardXLibErrorHandler(Display *pDisplay, XErrorEvent *pError)
99{
100 char errorText[1024];
101
102 LogFlowFunc(("\n"));
103 if (pError->error_code == BadAtom)
104 {
105 /* This can be triggered in debug builds if a guest application passes a bad atom
106 in its list of supported clipboard formats. As such it is harmless. */
107 LogFlowFunc(("ignoring BadAtom error and returning\n"));
108 return 0;
109 }
110 vboxClipboardDisconnect();
111 XGetErrorText(pDisplay, pError->error_code, errorText, sizeof(errorText));
112 if (!gbDaemonise)
113 {
114 cout << "An X Window protocol error occurred: " << errorText << endl
115 << " Request code: " << int(pError->request_code) << endl
116 << " Minor code: " << int(pError->minor_code) << endl
117 << " Serial number of the failed request: " << int(pError->serial) << endl;
118 }
119 Log(("%s: an X Window protocol error occurred: %s. Request code: %d, minor code: %d, serial number: %d\n",
120 __PRETTY_FUNCTION__, pError->error_code, pError->request_code, pError->minor_code,
121 pError->serial));
122 LogFlowFunc(("exiting\n"));
123 exit(1);
124}
125
126int main(int argc, char *argv[])
127{
128 int rc;
129#ifdef SEAMLESS_LINUX
130 /** Our instance of the seamless class. */
131 VBoxGuestSeamless seamless;
132#endif
133
134 /* Parse our option(s) */
135 while (1)
136 {
137 static struct option sOpts[] =
138 {
139 {"nodaemon", 0, 0, 'd'},
140 {0, 0, 0, 0}
141 };
142 int cOpt = getopt_long(argc, argv, "", sOpts, 0);
143 if (cOpt == -1)
144 {
145 if (optind < argc)
146 {
147 cout << "Unrecognized command line argument: " << argv[argc] << endl;
148 exit(1);
149 }
150 break;
151 }
152 switch(cOpt)
153 {
154 case 'd':
155 gbDaemonise = false;
156 break;
157 default:
158 cout << "Unrecognized command line option: " << static_cast<char>(cOpt) << endl;
159 case '?':
160 exit(1);
161 }
162 }
163 if (gbDaemonise)
164 {
165 vboxDaemonise();
166 }
167 /* Initialise our runtime before all else. */
168 RTR3Init(false);
169 LogFlowFunc(("\n"));
170 /* Initialise threading in X11 and in Xt. */
171 if (!XInitThreads() || !XtToolkitThreadInitialize())
172 {
173 LogRelFunc(("Error initialising threads in X11, returning 1."));
174 cout << "Your guest system appears to be using an old, single-threaded version of the X Window System libraries. This program cannot continue." << endl;
175 return 1;
176 }
177 /* Set an X11 error handler, so that we don't die when we get BadAtom errors. */
178 XSetErrorHandler(vboxClipboardXLibErrorHandler);
179 /* Connect to the host clipboard. */
180 LogRel(("Starting clipboard Guest Additions...\n"));
181 rc = vboxClipboardConnect();
182 if (rc != VINF_SUCCESS)
183 {
184 LogRel(("vboxClipboardConnect failed with rc = %d\n", rc));
185 cout << "Failed to connect to the host clipboard." << endl;
186 }
187#ifdef SEAMLESS_LINUX
188 try
189 {
190 LogRel(("Starting seamless Guest Additions...\n"));
191 rc = seamless.init();
192 if (rc != VINF_SUCCESS)
193 {
194 LogRel(("Failed to initialise seamless Additions, rc = %d\n", rc));
195 cout << "Failed to initialise seamless Additions." << endl;
196 }
197 }
198 catch (std::exception e)
199 {
200 LogRel(("Failed to initialise seamless Additions - caught exception: %s\n", e.what()));
201 cout << "Failed to initialise seamless Additions\n" << endl;
202 rc = VERR_UNRESOLVED_ERROR;
203 }
204 catch (...)
205 {
206 LogRel(("Failed to initialise seamless Additions - caught unknown exception.\n"));
207 cout << "Failed to initialise seamless Additions\n" << endl;
208 rc = VERR_UNRESOLVED_ERROR;
209 }
210#endif /* SEAMLESS_LINUX defined */
211 vboxClipboardMain();
212 vboxClipboardDisconnect();
213#ifdef SEAMLESS_LINUX
214 try
215 {
216 seamless.uninit();
217 }
218 catch (std::exception e)
219 {
220 LogRel(("Error shutting down seamless Additions - caught exception: %s\n", e.what()));
221 rc = VERR_UNRESOLVED_ERROR;
222 }
223 catch (...)
224 {
225 LogRel(("Error shutting down seamless Additions - caught unknown exception.\n"));
226 rc = VERR_UNRESOLVED_ERROR;
227 }
228#endif /* SEAMLESS_LINUX defined */
229 LogFlowFunc(("returning %Vrc\n", rc));
230 return rc;
231}
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