VBoxAutostart-posix.cpp revision 881b409899b6340ee915403fe36330af367d02c9
/* $Id$ */
/** @file
* VBoxAutostart - VirtualBox Autostart service.
*/
/*
* Copyright (C) 2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <package-generated.h>
#include <iprt/buildconfig.h>
#include <iprt/critsect.h>
#include <iprt/initterm.h>
#include <iprt/semaphore.h>
#include <algorithm>
#include <list>
#include <string>
#include <signal.h>
#include "VBoxAutostart.h"
using namespace com;
#if defined(RT_OS_LINUX) || defined (RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_DARWIN)
# define VBOXAUTOSTART_DAEMONIZE
#endif
bool g_fVerbose = false;
/** Logging parameters. */
/** Run in background. */
static bool g_fDaemonize = false;
/**
* Command line arguments.
*/
static const RTGETOPTDEF g_aOptions[] = {
#ifdef VBOXAUTOSTART_DAEMONIZE
#endif
/** For displayHelp(). */
};
/** Set by the signal handler. */
static volatile bool g_fCanceled = false;
/**
* Signal handler that sets g_fCanceled.
*
* This can be executed on any thread in the process, on Windows it may even be
* a thread dedicated to delivering this signal. Do not doing anything
* unnecessary here.
*/
static void showProgressSignalHandler(int iSignal)
{
ASMAtomicWriteBool(&g_fCanceled, true);
}
/**
* Print out progress on the console.
*
* This runs the main event queue every now and then to prevent piling up
* unhandled things (which doesn't cause real problems, just makes things
* react a little slower than in the ideal case).
*/
{
using namespace com;
ULONG ulCurrentPercent = 0;
ULONG ulLastPercent = 0;
{
return hrc;
}
/*
* Note: Outputting the progress info to stderr (g_pStdErr) is intentional
* to not get intermixed with other (raw) stdout data which might get
* written in the meanwhile.
*/
/* setup signal handling if cancelable */
bool fCanceledAlready = false;
fCancelable = FALSE;
if (fCancelable)
{
#ifdef SIGBREAK
#endif
}
{
/* did we cross a 10% mark? */
{
/* make sure to also print out missed steps */
for (ULONG curVal = (ulLastPercent / 10) * 10 + 10; curVal <= (ulCurrentPercent / 10) * 10; curVal += 10)
{
if (curVal < 100)
{
}
}
}
if (fCompleted)
break;
/* process async cancelation */
if (g_fCanceled && !fCanceledAlready)
{
fCanceledAlready = true;
else
g_fCanceled = false;
}
/* make sure the loop is not too tight */
}
/* undo signal handling */
if (fCancelable)
{
#ifdef SIGBREAK
#endif
}
/* complete the line. */
{
else if (g_fCanceled)
else
{
}
}
else
{
}
return hrc;
}
{
}
static void displayHeader()
{
"All rights reserved.\n\n");
}
/**
* Displays the help.
*
* @param pszImage Name of program name (image).
*/
static void displayHelp(const char *pszImage)
{
"Usage:\n"
" %s [-v|--verbose] [-h|-?|--help]\n"
" [-F|--logfile=<file>] [-R|--logrotate=<num>] [-S|--logsize=<bytes>]\n"
" [-I|--loginterval=<seconds>]\n"
" [-c|--config=<config file>]\n", pszImage);
"Options:\n");
for (unsigned i = 0;
i < RT_ELEMENTS(g_aOptions);
++i)
{
{
str += ", -";
}
str += ":";
const char *pcszDescr = "";
switch (g_aOptions[i].iShort)
{
case 'h':
pcszDescr = "Print this help message and exit.";
break;
#ifdef VBOXAUTOSTART_DAEMONIZE
case 'b':
pcszDescr = "Run in background (daemon mode).";
break;
#endif
case 'F':
pcszDescr = "Name of file to write log to (no file).";
break;
case 'R':
pcszDescr = "Number of log files (0 disables log rotation).";
break;
case 'S':
pcszDescr = "Maximum size of a log file to trigger rotation (bytes).";
break;
case 'I':
pcszDescr = "Maximum time interval to trigger log rotation (seconds).";
break;
case 'c':
pcszDescr = "Name of the configuration file for the global overrides.";
break;
}
}
RTStrmPrintf(g_pStdErr, "\nUse environment variable VBOXAUTOSTART_RELEASE_LOG for logging options.\n");
}
/**
* Creates all global COM objects.
*
* @return HRESULT
*/
static int autostartSetup()
{
serviceLogVerbose(("Setting up ...\n"));
/*
* Setup VirtualBox + session interfaces.
*/
{
}
else
return VERR_COM_OBJECT_NOT_FOUND;
return VINF_SUCCESS;
}
static void autostartShutdown()
{
serviceLogVerbose(("Shutting down ...\n"));
}
{
/*
* Before we do anything, init the runtime without loading
* the support driver.
*/
if (RT_FAILURE(rc))
return RTMsgInitFailure(rc);
/*
* Parse the global options
*/
int c;
const char *pszLogFile = NULL;
const char *pszConfigFile = NULL;
bool fQuiet = false;
bool fStart = false;
bool fStop = false;
{
switch (c)
{
case 'h':
displayHelp(argv[0]);
return 0;
case 'v':
g_fVerbose = true;
break;
#ifdef VBOXAUTOSTART_DAEMONIZE
case 'b':
g_fDaemonize = true;
break;
#endif
case 'V':
return 0;
case 'F':
break;
case 'R':
break;
case 'S':
break;
case 'I':
break;
case 'Q':
fQuiet = true;
break;
case 'c':
break;
case 's':
fStart = true;
break;
case 'd':
fStop = true;
break;
default:
return RTGetOptPrintError(c, &ValueUnion);
}
}
{
displayHelp(argv[0]);
}
{
displayHelp(argv[0]);
}
if (!pszConfigFile)
{
displayHelp(argv[0]);
}
if (!fQuiet)
bool fAllow = false;
if (RT_FAILURE(rc))
return RTEXITCODE_FAILURE;
if (RT_FAILURE(rc))
/* Check default policy. */
if (pCfgAstPolicy)
{
{
fAllow = true;
}
else
}
if ( pCfgAstUser
{
if (pCfgAstPolicy)
{
{
fAllow = true;
else
fAllow = false;
}
else
}
}
else if (pCfgAstUser)
if (!fAllow)
/* Don't start if the VirtualBox settings directory does not exist. */
char szUserHomeDir[RTPATH_MAX];
if (RT_FAILURE(rc))
else if (!RTDirExists(szUserHomeDir))
return RTEXITCODE_SUCCESS;
/* create release logger, to stdout */
"all", "VBOXAUTOSTART_RELEASE_LOG",
if (RT_FAILURE(rc))
#ifdef VBOXAUTOSTART_DAEMONIZE
if (g_fDaemonize)
{
/* prepare release logging */
char szLogFile[RTPATH_MAX];
if (!pszLogFile || !*pszLogFile)
{
if (RT_FAILURE(rc))
if (RT_FAILURE(rc))
}
if (RT_FAILURE(rc))
/* create release logger, to file */
"all", "VBOXAUTOSTART_RELEASE_LOG",
if (RT_FAILURE(rc))
}
#endif
/*
* Initialize COM.
*/
using namespace com;
# ifdef VBOX_WITH_XPCOM
if (hrc == NS_ERROR_FILE_ACCESS_DENIED)
{
return RTMsgErrorExit(RTEXITCODE_FAILURE,
"Failed to initialize COM because the global settings directory '%s' is not accessible!", szHome);
}
# endif
{
{
RTMsgError("Most likely, the VirtualBox COM server is not running or failed to start.");
}
else
return RTEXITCODE_FAILURE;
}
rc = autostartSetup();
if (RT_FAILURE(rc))
return RTEXITCODE_FAILURE;
if (fStart)
else
{
}
return rcExit;
}