VirtualBox

source: vbox/trunk/src/VBox/Additions/darwin/VBoxClient/VBoxClient.cpp@ 100063

Last change on this file since 100063 was 98103, checked in by vboxsync, 22 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.4 KB
Line 
1/** $Id: VBoxClient.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxClient - User specific services, Darwin.
4 */
5
6/*
7 * Copyright (C) 2007-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <stdio.h>
33#include <signal.h>
34#include <unistd.h>
35#include <stdlib.h>
36
37#include <VBox/log.h>
38#include <VBox/VBoxGuestLib.h>
39#include <iprt/stream.h>
40#include <iprt/initterm.h>
41#include <iprt/message.h>
42#include <iprt/process.h>
43#include <iprt/string.h>
44
45#include "VBoxClientInternal.h"
46
47
48/*********************************************************************************************************************************
49* Glogal Variables *
50*********************************************************************************************************************************/
51
52static int g_cVerbosity = 0;
53static PRTLOGGER g_pLogger = NULL;
54
55static VBOXCLIENTSERVICE g_aServices[] =
56{
57#ifdef VBOX_WITH_SHARED_CLIPBOARD
58 g_ClipboardService
59#endif
60};
61
62
63/**
64 * Create default logger in order to print output to the specified file.
65 *
66 * @return IPRT status code.
67 */
68static int vbclInitLogger(char *pszLogFileName)
69{
70 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
71 int rc = RTLogCreateEx(&g_pLogger, "VBOXCLIENT_RELEASE_LOG", RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG, "all",
72 RT_ELEMENTS(s_apszGroups), s_apszGroups, UINT32_MAX /*cMaxEntriesPerGroup*/,
73 0 /*cBufDescs*/, NULL /*paBufDescs*/, RTLOGDEST_STDOUT,
74 NULL /*pfnPhase*/,
75 pszLogFileName ? 10 : 0 /*cHistory*/,
76 pszLogFileName ? 100 * _1M : 0 /*cbHistoryFileMax*/,
77 pszLogFileName ? RT_SEC_1DAY : 0 /*cSecsHistoryTimeSlot*/,
78 NULL /*pOutputIf*/, NULL /*pvOutputIfUser*/,
79 NULL /*pErrInfo*/, "%s", pszLogFileName ? pszLogFileName : "");
80 AssertRCReturn(rc, rc);
81
82 /* Register this logger as the release logger */
83 RTLogRelSetDefaultInstance(g_pLogger);
84
85 /* Explicitly flush the log in case of VBOXCLIENT_RELEASE_LOG=buffered. */
86 RTLogFlush(g_pLogger);
87
88 return VINF_SUCCESS;
89}
90
91
92/**
93 * Destroy logger.
94 */
95static void vbclTermLogger(char *szLogFileName)
96{
97 // Why SIGBUS here?
98 RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
99
100 if (szLogFileName)
101 RTStrFree(szLogFileName);
102}
103
104/**
105 * Displays a verbose message.
106 *
107 * @param iLevel Minimum log level required to display this message.
108 * @param pszFormat The message text.
109 * @param ... Format arguments.
110 */
111void VBoxClientVerbose(int iLevel, const char *pszFormat, ...)
112{
113 if (iLevel > g_cVerbosity)
114 return;
115
116 va_list args;
117 va_start(args, pszFormat);
118 char *psz = NULL;
119 RTStrAPrintfV(&psz, pszFormat, args);
120 va_end(args);
121
122 AssertPtr(psz);
123 LogRel(("%s", psz));
124
125 RTStrFree(psz);
126}
127
128/**
129 * Wait for signals in order to safely terminate process.
130 */
131static void vbclWait(void)
132{
133 sigset_t signalMask;
134 int iSignal;
135
136 /* Register signals that we are waiting for */
137 sigemptyset(&signalMask);
138 sigaddset(&signalMask, SIGHUP);
139 sigaddset(&signalMask, SIGINT);
140 sigaddset(&signalMask, SIGQUIT);
141 sigaddset(&signalMask, SIGABRT);
142 sigaddset(&signalMask, SIGTERM);
143 pthread_sigmask(SIG_BLOCK, &signalMask, NULL);
144
145 /* Ignoring return status */
146 sigwait(&signalMask, &iSignal);
147}
148
149/**
150 * Start registered services.
151 *
152 * @return IPRT status code.
153 */
154static int vbclStartServices(void)
155{
156 int rc;
157 unsigned int iServiceId = 0;
158
159 VBoxClientVerbose(1, "Starting services...\n");
160 for (iServiceId = 0; iServiceId < RT_ELEMENTS(g_aServices); iServiceId++)
161 {
162 VBoxClientVerbose(1, "Starting service: %s\n", g_aServices[iServiceId].pszName);
163 rc = (g_aServices[iServiceId].pfnStart)();
164 if (RT_FAILURE(rc))
165 {
166 VBoxClientVerbose(1, "unable to start service: %s (%Rrc)\n", g_aServices[iServiceId].pszName, rc);
167 VBoxClientVerbose(1, "Rolling back..\n");
168
169 /* Stop running services */
170 do
171 {
172 VBoxClientVerbose(1, "Stopping service: %s\n", g_aServices[iServiceId].pszName);
173 int rcStop = (g_aServices[iServiceId].pfnStop)();
174 if (RT_FAILURE(rcStop))
175 VBoxClientVerbose(1, "unable to stop service: %s (%Rrc)\n", g_aServices[iServiceId].pszName, rcStop);
176 } while (--iServiceId != 0);
177
178 break;
179 }
180 }
181
182 if (RT_SUCCESS(rc))
183 VBoxClientVerbose(1, "Services start completed.\n");
184
185 return rc;
186}
187
188/**
189 * Stop registered services.
190 *
191 * @return IPRT status code.
192 */
193static void vbclStopServices(void)
194{
195 unsigned int iServiceId = 0;
196
197 VBoxClientVerbose(1, "Stopping services...\n");
198 for (iServiceId = 0; iServiceId < RT_ELEMENTS(g_aServices); iServiceId++)
199 {
200 VBoxClientVerbose(1, "Stopping service: %s\n", g_aServices[iServiceId].pszName);
201 int rc = (g_aServices[iServiceId].pfnStop)();
202 if (RT_FAILURE(rc))
203 VBoxClientVerbose(1, "unable to stop service: %s (%Rrc)\n", g_aServices[iServiceId].pszName, rc);
204 }
205 VBoxClientVerbose(1, "Services stop completed\n");
206}
207
208
209static void usage(char *sProgName)
210{
211 RTPrintf("usage: %s [-fvl]\n", sProgName);
212 RTPrintf(" -f\tRun in foreground (default: no)\n");
213 RTPrintf(" -v\tIncrease verbosity level (default: no verbosity)\n");
214 RTPrintf(" -l\tSpecify log file name (default: no log file)\n");
215 exit(1);
216}
217
218int main(int argc, char *argv[])
219{
220 int rc;
221 int c;
222
223 bool fDemonize = true;
224 static char *szLogFileName = NULL;
225
226 rc = RTR3InitExe(argc, &argv, 0);
227 if (RT_FAILURE(rc))
228 {
229 RTPrintf("RTR3InitExe() failed: (%Rrc)\n", rc);
230 return RTMsgInitFailure(rc);
231 }
232
233 /* Parse command line */
234 while((c = getopt(argc, argv, "fvl:")) != -1)
235 {
236 switch(c)
237 {
238 case 'f':
239 fDemonize = false;
240 break;
241 case 'v':
242 g_cVerbosity++;
243 break;
244 case 'l':
245 szLogFileName = RTStrDup(optarg);
246 break;
247
248 default : usage(argv[0]);
249 }
250 }
251
252 /* No more arguments allowed */
253 if ((argc - optind) != 0)
254 usage(argv[0]);
255
256 if (fDemonize)
257 {
258 rc = RTProcDaemonizeUsingFork(true /* fNoChDir */, false /* fNoClose */, NULL);
259 if (RT_FAILURE(rc))
260 {
261 RTPrintf("failed to run into background\n");
262 return 1;
263 }
264 }
265
266 rc = VbglR3Init();
267 if (RT_SUCCESS(rc))
268 {
269 rc = vbclInitLogger(szLogFileName);
270 if (RT_SUCCESS(rc))
271 {
272 rc = vbclStartServices();
273 if (RT_SUCCESS(rc))
274 {
275 vbclWait();
276 vbclStopServices();
277 }
278 else
279 {
280 RTPrintf("failed to start services: (%Rrc)\n", rc);
281 }
282
283 vbclTermLogger(szLogFileName);
284 }
285 else
286 {
287 RTPrintf("failed to start logger: (%Rrc)\n", rc);
288 }
289
290 VbglR3Term();
291 }
292 else
293 {
294 RTPrintf("failed to initialize guest library: (%Rrc)\n", rc);
295 }
296
297 return 0;
298}
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