diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
commit | f215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch) | |
tree | 6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Additions/darwin/VBoxClient/VBoxClient.cpp | |
parent | Initial commit. (diff) | |
download | virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip |
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Additions/darwin/VBoxClient/VBoxClient.cpp')
-rw-r--r-- | src/VBox/Additions/darwin/VBoxClient/VBoxClient.cpp | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/src/VBox/Additions/darwin/VBoxClient/VBoxClient.cpp b/src/VBox/Additions/darwin/VBoxClient/VBoxClient.cpp new file mode 100644 index 00000000..c80b1c9b --- /dev/null +++ b/src/VBox/Additions/darwin/VBoxClient/VBoxClient.cpp @@ -0,0 +1,298 @@ +/** $Id: VBoxClient.cpp $ */ +/** @file + * VBoxClient - User specific services, Darwin. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <stdio.h> +#include <signal.h> +#include <unistd.h> +#include <stdlib.h> + +#include <VBox/log.h> +#include <VBox/VBoxGuestLib.h> +#include <iprt/stream.h> +#include <iprt/initterm.h> +#include <iprt/message.h> +#include <iprt/process.h> +#include <iprt/string.h> + +#include "VBoxClientInternal.h" + + +/********************************************************************************************************************************* +* Glogal Variables * +*********************************************************************************************************************************/ + +static int g_cVerbosity = 0; +static PRTLOGGER g_pLogger = NULL; + +static VBOXCLIENTSERVICE g_aServices[] = +{ +#ifdef VBOX_WITH_SHARED_CLIPBOARD + g_ClipboardService +#endif +}; + + +/** + * Create default logger in order to print output to the specified file. + * + * @return IPRT status code. + */ +static int vbclInitLogger(char *pszLogFileName) +{ + static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES; + int rc = RTLogCreateEx(&g_pLogger, "VBOXCLIENT_RELEASE_LOG", RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG, "all", + RT_ELEMENTS(s_apszGroups), s_apszGroups, UINT32_MAX /*cMaxEntriesPerGroup*/, + 0 /*cBufDescs*/, NULL /*paBufDescs*/, RTLOGDEST_STDOUT, + NULL /*pfnPhase*/, + pszLogFileName ? 10 : 0 /*cHistory*/, + pszLogFileName ? 100 * _1M : 0 /*cbHistoryFileMax*/, + pszLogFileName ? RT_SEC_1DAY : 0 /*cSecsHistoryTimeSlot*/, + NULL /*pOutputIf*/, NULL /*pvOutputIfUser*/, + NULL /*pErrInfo*/, "%s", pszLogFileName ? pszLogFileName : ""); + AssertRCReturn(rc, rc); + + /* Register this logger as the release logger */ + RTLogRelSetDefaultInstance(g_pLogger); + + /* Explicitly flush the log in case of VBOXCLIENT_RELEASE_LOG=buffered. */ + RTLogFlush(g_pLogger); + + return VINF_SUCCESS; +} + + +/** + * Destroy logger. + */ +static void vbclTermLogger(char *szLogFileName) +{ + // Why SIGBUS here? + RTLogDestroy(RTLogRelSetDefaultInstance(NULL)); + + if (szLogFileName) + RTStrFree(szLogFileName); +} + +/** + * Displays a verbose message. + * + * @param iLevel Minimum log level required to display this message. + * @param pszFormat The message text. + * @param ... Format arguments. + */ +void VBoxClientVerbose(int iLevel, const char *pszFormat, ...) +{ + if (iLevel > g_cVerbosity) + return; + + va_list args; + va_start(args, pszFormat); + char *psz = NULL; + RTStrAPrintfV(&psz, pszFormat, args); + va_end(args); + + AssertPtr(psz); + LogRel(("%s", psz)); + + RTStrFree(psz); +} + +/** + * Wait for signals in order to safely terminate process. + */ +static void vbclWait(void) +{ + sigset_t signalMask; + int iSignal; + + /* Register signals that we are waiting for */ + sigemptyset(&signalMask); + sigaddset(&signalMask, SIGHUP); + sigaddset(&signalMask, SIGINT); + sigaddset(&signalMask, SIGQUIT); + sigaddset(&signalMask, SIGABRT); + sigaddset(&signalMask, SIGTERM); + pthread_sigmask(SIG_BLOCK, &signalMask, NULL); + + /* Ignoring return status */ + sigwait(&signalMask, &iSignal); +} + +/** + * Start registered services. + * + * @return IPRT status code. + */ +static int vbclStartServices(void) +{ + int rc; + unsigned int iServiceId = 0; + + VBoxClientVerbose(1, "Starting services...\n"); + for (iServiceId = 0; iServiceId < RT_ELEMENTS(g_aServices); iServiceId++) + { + VBoxClientVerbose(1, "Starting service: %s\n", g_aServices[iServiceId].pszName); + rc = (g_aServices[iServiceId].pfnStart)(); + if (RT_FAILURE(rc)) + { + VBoxClientVerbose(1, "unable to start service: %s (%Rrc)\n", g_aServices[iServiceId].pszName, rc); + VBoxClientVerbose(1, "Rolling back..\n"); + + /* Stop running services */ + do + { + VBoxClientVerbose(1, "Stopping service: %s\n", g_aServices[iServiceId].pszName); + int rcStop = (g_aServices[iServiceId].pfnStop)(); + if (RT_FAILURE(rcStop)) + VBoxClientVerbose(1, "unable to stop service: %s (%Rrc)\n", g_aServices[iServiceId].pszName, rcStop); + } while (--iServiceId != 0); + + break; + } + } + + if (RT_SUCCESS(rc)) + VBoxClientVerbose(1, "Services start completed.\n"); + + return rc; +} + +/** + * Stop registered services. + * + * @return IPRT status code. + */ +static void vbclStopServices(void) +{ + unsigned int iServiceId = 0; + + VBoxClientVerbose(1, "Stopping services...\n"); + for (iServiceId = 0; iServiceId < RT_ELEMENTS(g_aServices); iServiceId++) + { + VBoxClientVerbose(1, "Stopping service: %s\n", g_aServices[iServiceId].pszName); + int rc = (g_aServices[iServiceId].pfnStop)(); + if (RT_FAILURE(rc)) + VBoxClientVerbose(1, "unable to stop service: %s (%Rrc)\n", g_aServices[iServiceId].pszName, rc); + } + VBoxClientVerbose(1, "Services stop completed\n"); +} + + +static void usage(char *sProgName) +{ + RTPrintf("usage: %s [-fvl]\n", sProgName); + RTPrintf(" -f\tRun in foreground (default: no)\n"); + RTPrintf(" -v\tIncrease verbosity level (default: no verbosity)\n"); + RTPrintf(" -l\tSpecify log file name (default: no log file)\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + int rc; + int c; + + bool fDemonize = true; + static char *szLogFileName = NULL; + + rc = RTR3InitExe(argc, &argv, 0); + if (RT_FAILURE(rc)) + { + RTPrintf("RTR3InitExe() failed: (%Rrc)\n", rc); + return RTMsgInitFailure(rc); + } + + /* Parse command line */ + while((c = getopt(argc, argv, "fvl:")) != -1) + { + switch(c) + { + case 'f': + fDemonize = false; + break; + case 'v': + g_cVerbosity++; + break; + case 'l': + szLogFileName = RTStrDup(optarg); + break; + + default : usage(argv[0]); + } + } + + /* No more arguments allowed */ + if ((argc - optind) != 0) + usage(argv[0]); + + if (fDemonize) + { + rc = RTProcDaemonizeUsingFork(true /* fNoChDir */, false /* fNoClose */, NULL); + if (RT_FAILURE(rc)) + { + RTPrintf("failed to run into background\n"); + return 1; + } + } + + rc = VbglR3Init(); + if (RT_SUCCESS(rc)) + { + rc = vbclInitLogger(szLogFileName); + if (RT_SUCCESS(rc)) + { + rc = vbclStartServices(); + if (RT_SUCCESS(rc)) + { + vbclWait(); + vbclStopServices(); + } + else + { + RTPrintf("failed to start services: (%Rrc)\n", rc); + } + + vbclTermLogger(szLogFileName); + } + else + { + RTPrintf("failed to start logger: (%Rrc)\n", rc); + } + + VbglR3Term(); + } + else + { + RTPrintf("failed to initialize guest library: (%Rrc)\n", rc); + } + + return 0; +} |