/** * The main loop for the VBoxClient daemon. */ int main(int argc, char *argv[]) { /* Initialise our runtime before all else. */ int rc = RTR3InitExe(argc, &argv, 0); if (RT_FAILURE(rc)) return RTMsgInitFailure(rc); int rcClipboard; const char *pszFileName = RTPathFilename(argv[0]); bool fDaemonise = true; /* Have any fatal errors occurred yet? */ bool fSuccess = true; /* Do we know which service we wish to run? */ bool fHaveService = false; if (NULL == pszFileName) pszFileName = "VBoxClient"; /* Initialise our global clean-up critical section */ rc = RTCritSectInit(&g_critSect); if (RT_FAILURE(rc)) { /* Of course, this should never happen. */ RTPrintf("%s: Failed to initialise the global critical section, rc=%Rrc\n", pszFileName, rc); return 1; } /* Parse our option(s) */ /** @todo Use RTGetOpt() if the arguments become more complex. */ for (int i = 1; i < argc; ++i) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--nodaemon")) fDaemonise = false; else if (!strcmp(argv[i], "--clipboard")) { if (g_pService == NULL) g_pService = VBoxClient::GetClipboardService(); else fSuccess = false; } else if (!strcmp(argv[i], "--display")) { if (g_pService == NULL) g_pService = VBoxClient::GetDisplayService(); else fSuccess = false; } else if (!strcmp(argv[i], "--seamless")) { if (g_pService == NULL) g_pService = VBoxClient::GetSeamlessService(); else fSuccess = false; } else if (!strcmp(argv[i], "--checkhostversion")) { if (g_pService == NULL) g_pService = VBoxClient::GetHostVersionService(); else fSuccess = false; } #ifdef VBOX_WITH_DRAG_AND_DROP else if (!strcmp(argv[i], "--draganddrop")) { if (g_pService == NULL) g_pService = VBoxClient::GetDragAndDropService(); else fSuccess = false; } #endif /* VBOX_WITH_DRAG_AND_DROP */ else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { vboxClientUsage(pszFileName); return 0; } else { RTPrintf("%s: unrecognized option `%s'\n", pszFileName, argv[i]); RTPrintf("Try `%s --help' for more information\n", pszFileName); return 1; } } if (!fSuccess || !g_pService) { vboxClientUsage(pszFileName); return 1; } /* Get the path for the pidfiles */ rc = RTPathUserHome(g_szPidFile, sizeof(g_szPidFile)); if (RT_FAILURE(rc)) { RTPrintf("VBoxClient: failed to get home directory, rc=%Rrc. Exiting.\n", rc); LogRel(("VBoxClient: failed to get home directory, rc=%Rrc. Exiting.\n", rc)); return 1; } rc = RTPathAppend(g_szPidFile, sizeof(g_szPidFile), g_pService->getPidFilePath()); if (RT_FAILURE(rc)) { RTPrintf("VBoxClient: RTPathAppend failed with rc=%Rrc. Exiting.\n", rc); LogRel(("VBoxClient: RTPathAppend failed with rc=%Rrc. Exiting.\n", rc)); return 1; } /* Initialise the guest library. */ if (RT_FAILURE(VbglR3InitUser())) { RTPrintf("Failed to connect to the VirtualBox kernel service\n"); LogRel(("Failed to connect to the VirtualBox kernel service\n")); return 1; } if (fDaemonise) { rc = VbglR3Daemonize(false /* fNoChDir */, false /* fNoClose */); if (RT_FAILURE(rc)) { RTPrintf("VBoxClient: failed to daemonize. Exiting.\n"); LogRel(("VBoxClient: failed to daemonize. Exiting.\n")); # ifdef DEBUG RTPrintf("Error %Rrc\n", rc); # endif return 1; } } if (g_szPidFile[0] && RT_FAILURE(VbglR3PidFile(g_szPidFile, &g_hPidFile))) { RTPrintf("Failed to create a pidfile. Exiting.\n"); LogRel(("Failed to create a pidfile. Exiting.\n")); VbglR3Term(); return 1; } /* Set signal handlers to clean up on exit. */ vboxClientSetSignalHandlers(); /* Set an X11 error handler, so that we don't die when we get unavoidable errors. */ XSetErrorHandler(vboxClientXLibErrorHandler); /* Set an X11 I/O error handler, so that we can shutdown properly on fatal errors. */ XSetIOErrorHandler(vboxClientXLibIOErrorHandler); g_pService->run(fDaemonise); VBoxClient::CleanUp(); return 1; /* We should never get here. */ }
/** * The main loop for the VBoxClient daemon. * @todo Clean up for readability. */ int main(int argc, char *argv[]) { bool fDaemonise = true, fRespawn = true; int rc; const char *pcszFileName, *pcszStage; /* Initialise our runtime before all else. */ rc = RTR3InitExe(argc, &argv, 0); if (RT_FAILURE(rc)) return RTMsgInitFailure(rc); /* This should never be called twice in one process - in fact one Display * object should probably never be used from multiple threads anyway. */ if (!XInitThreads()) VBClFatalError(("Failed to initialize X11 threads\n")); /* Get our file name for error output. */ pcszFileName = RTPathFilename(argv[0]); if (!pcszFileName) pcszFileName = "VBoxClient"; /* Parse our option(s) */ /** @todo Use RTGetOpt() if the arguments become more complex. */ for (int i = 1; i < argc; ++i) { rc = VERR_INVALID_PARAMETER; if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--nodaemon")) { /* If the user is running in "no daemon" mode anyway, send critical * logging to stdout as well. */ PRTLOGGER pReleaseLog = RTLogRelDefaultInstance(); if (pReleaseLog) rc = RTLogDestinations(pReleaseLog, "stdout"); if (pReleaseLog && RT_FAILURE(rc)) RTPrintf("%s: failed to redivert error output, rc=%Rrc\n", pcszFileName, rc); fDaemonise = false; } else if (!strcmp(argv[i], "--no-respawn")) { fRespawn = false; } else if (!strcmp(argv[i], "--clipboard")) { if (g_pService) break; g_pService = VBClGetClipboardService(); } else if (!strcmp(argv[i], "--display")) { if (g_pService) break; g_pService = VBClGetDisplayService(); } else if (!strcmp(argv[i], "--seamless")) { if (g_pService) break; g_pService = VBClGetSeamlessService(); } else if (!strcmp(argv[i], "--checkhostversion")) { if (g_pService) break; g_pService = VBClGetHostVersionService(); } #ifdef VBOX_WITH_DRAG_AND_DROP else if (!strcmp(argv[i], "--draganddrop")) { if (g_pService) break; g_pService = VBClGetDragAndDropService(); } #endif /* VBOX_WITH_DRAG_AND_DROP */ else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { vboxClientUsage(pcszFileName); return 0; } else { RTPrintf("%s: unrecognized option `%s'\n", pcszFileName, argv[i]); RTPrintf("Try `%s --help' for more information\n", pcszFileName); return 1; } rc = VINF_SUCCESS; } if (RT_FAILURE(rc) || !g_pService) { vboxClientUsage(pcszFileName); return 1; } rc = RTCritSectInit(&g_critSect); if (RT_FAILURE(rc)) VBClFatalError(("Initialising critical section: %Rrc\n", rc)); rc = RTPathUserHome(g_szPidFile, sizeof(g_szPidFile)); if (RT_FAILURE(rc)) VBClFatalError(("Getting home directory for pid-file: %Rrc\n", rc)); rc = RTPathAppend(g_szPidFile, sizeof(g_szPidFile), (*g_pService)->getPidFilePath()); if (RT_FAILURE(rc)) VBClFatalError(("Creating pid-file path: %Rrc\n", rc)); if (fDaemonise) rc = VbglR3Daemonize(false /* fNoChDir */, false /* fNoClose */, fRespawn, &cRespawn); if (RT_FAILURE(rc)) VBClFatalError(("Daemonizing: %Rrc\n", rc)); if (g_szPidFile[0]) rc = VbglR3PidFile(g_szPidFile, &g_hPidFile); if (rc == VERR_FILE_LOCK_VIOLATION) /* Already running. */ return 0; if (RT_FAILURE(rc)) VBClFatalError(("Creating pid-file: %Rrc\n", rc)); /* Set signal handlers to clean up on exit. */ vboxClientSetSignalHandlers(); #ifndef VBOXCLIENT_WITHOUT_X11 /* Set an X11 error handler, so that we don't die when we get unavoidable * errors. */ XSetErrorHandler(vboxClientXLibErrorHandler); /* Set an X11 I/O error handler, so that we can shutdown properly on * fatal errors. */ XSetIOErrorHandler(vboxClientXLibIOErrorHandler); #endif rc = (*g_pService)->init(g_pService); if (RT_FAILURE(rc)) VBClFatalError(("Initialising service: %Rrc\n", rc)); rc = (*g_pService)->run(g_pService, fDaemonise); if (RT_FAILURE(rc)) VBClFatalError(("Service main loop failed: %Rrc\n", rc)); VBClCleanUp(); return 0; }