VBoxAutostart.cpp revision e366e4992f5d81a0b93412e10d2ef9dc06f930ed
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/* $Id$ */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/** @file
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * VBoxAutostart - VirtualBox Autostart service.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Copyright (C) 2012 Oracle Corporation
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * This file is part of VirtualBox Open Source Edition (OSE), as
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * available from http://www.virtualbox.org. This file is free software;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * you can redistribute it and/or modify it under the terms of the GNU
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * General Public License (GPL) as published by the Free Software
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Foundation, in version 2 as it comes in the "COPYING" file of the
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/*******************************************************************************
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys* Header Files *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys*******************************************************************************/
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <VBox/com/com.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <VBox/com/string.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <VBox/com/Guid.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <VBox/com/array.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <VBox/com/ErrorInfo.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <VBox/com/errorprint.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <VBox/com/EventQueue.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <VBox/com/listeners.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <VBox/com/VirtualBox.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <VBox/err.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <VBox/log.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <VBox/version.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <package-generated.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <iprt/asm.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <iprt/buildconfig.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <iprt/critsect.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <iprt/getopt.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <iprt/initterm.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <iprt/message.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <iprt/path.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <iprt/process.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <iprt/semaphore.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <iprt/stream.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <iprt/string.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <iprt/system.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <iprt/time.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <iprt/ctype.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <algorithm>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <list>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <string>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#include <signal.h>
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysusing namespace com;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/**
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Tokenizer instance data for the config data.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllystypedef struct CFGTOKENIZER
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /** Config file handle. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys PRTSTREAM hStrmConfig;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /** String buffer for the current line we are operating in. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys char *pszLine;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /** Size of the string buffer. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys size_t cbLine;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /** Current position in the line. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys char *pszLineCurr;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /** Current line in the config file. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys unsigned iLine;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys} CFGTOKENIZER, *PCFGTOKENIZER;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/**
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * VM list entry.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllystypedef struct AUTOSTARTVM
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /** ID of the VM to start. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys Bstr strId;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /** Startup delay of the VM. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ULONG uStartupDelay;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys} AUTOSTARTVM;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic ComPtr<IVirtualBoxClient> g_pVirtualBoxClient = NULL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic bool g_fVerbose = false;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic ComPtr<IVirtualBox> g_pVirtualBox = NULL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic ComPtr<ISession> g_pSession = NULL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/** Logging parameters. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic uint32_t g_cHistory = 10; /* Enable log rotation, 10 files. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic uint32_t g_uHistoryFileTime = RT_SEC_1DAY; /* Max 1 day per file. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic uint64_t g_uHistoryFileSize = 100 * _1M; /* Max 100MB per file. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/** Run in background. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic bool g_fDaemonize = false;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/**
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Command line arguments.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic const RTGETOPTDEF g_aOptions[] = {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#if defined(RT_OS_LINUX) || defined (RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_DARWIN)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys { "--background", 'b', RTGETOPT_REQ_NOTHING },
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#endif
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /** For displayHelp(). */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys { "--help", 'h', RTGETOPT_REQ_NOTHING },
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys { "--start", 's', RTGETOPT_REQ_NOTHING },
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys { "--stop", 'd', RTGETOPT_REQ_NOTHING },
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys { "--config", 'c', RTGETOPT_REQ_STRING },
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys { "--logfile", 'F', RTGETOPT_REQ_STRING },
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys { "--logrotate", 'R', RTGETOPT_REQ_UINT32 },
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys { "--logsize", 'S', RTGETOPT_REQ_UINT64 },
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys { "--loginterval", 'I', RTGETOPT_REQ_UINT32 },
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys { "--quiet", 'Q', RTGETOPT_REQ_NOTHING }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys};
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic void serviceLog(const char *pszFormat, ...)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys va_list args;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys va_start(args, pszFormat);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys char *psz = NULL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTStrAPrintfV(&psz, pszFormat, args);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys va_end(args);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys LogRel(("%s", psz));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTStrFree(psz);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys#define serviceLogVerbose(a) if (g_fVerbose) { serviceLog a; }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/**
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Reads the next line from the config stream.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @returns VBox status code.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @param pCfgTokenizer The config tokenizer.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic int autostartConfigTokenizerReadNextLine(PCFGTOKENIZER pCfgTokenizer)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int rc = VINF_SUCCESS;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys do
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = RTStrmGetLine(pCfgTokenizer->hStrmConfig, pCfgTokenizer->pszLine,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->cbLine);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (rc == VERR_BUFFER_OVERFLOW)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys char *pszTmp;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->cbLine += 128;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pszTmp = (char *)RTMemRealloc(pCfgTokenizer->pszLine, pCfgTokenizer->cbLine);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (pszTmp)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->pszLine = pszTmp;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = VERR_NO_MEMORY;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys } while (rc == VERR_BUFFER_OVERFLOW);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_SUCCESS(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->iLine++;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->pszLineCurr = pCfgTokenizer->pszLine;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return rc;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/**
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Creates the config tokenizer from the given filename.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @returns VBox status code.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @param pszFilename Config filename.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @param ppCfgTokenizer Where to store the pointer to the config tokenizer on
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * success.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic int autostartConfigTokenizerCreate(const char *pszFilename, PCFGTOKENIZER *ppCfgTokenizer)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int rc = VINF_SUCCESS;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys PCFGTOKENIZER pCfgTokenizer = (PCFGTOKENIZER)RTMemAllocZ(sizeof(CFGTOKENIZER));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (pCfgTokenizer)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->iLine = 1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->cbLine = 128;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->pszLine = (char *)RTMemAllocZ(pCfgTokenizer->cbLine);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (pCfgTokenizer->pszLine)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = RTStrmOpen(pszFilename, "r", &pCfgTokenizer->hStrmConfig);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_SUCCESS(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerReadNextLine(pCfgTokenizer);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = VERR_NO_MEMORY;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = VERR_NO_MEMORY;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_SUCCESS(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *ppCfgTokenizer = pCfgTokenizer;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else if ( RT_FAILURE(rc)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys && pCfgTokenizer)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (pCfgTokenizer->pszLine)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTMemFree(pCfgTokenizer->pszLine);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (pCfgTokenizer->hStrmConfig)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTStrmClose(pCfgTokenizer->hStrmConfig);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTMemFree(pCfgTokenizer);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return rc;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/**
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Destroys the given config tokenizer.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @returns nothing.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @param pCfgTokenizer The config tokenizer to destroy.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic void autostartConfigTokenizerDestroy(PCFGTOKENIZER pCfgTokenizer)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (pCfgTokenizer->pszLine)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTMemFree(pCfgTokenizer->pszLine);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (pCfgTokenizer->hStrmConfig)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTStrmClose(pCfgTokenizer->hStrmConfig);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTMemFree(pCfgTokenizer);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/**
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Read the next token from the config file.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @returns VBox status code.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @param pCfgTokenizer The config tokenizer data.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @param ppszToken Where to store the start to the next token on success.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @param pcchToken Where to store the number of characters of the next token
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * excluding the \0 terminator on success.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic int autostartConfigTokenizerReadNext(PCFGTOKENIZER pCfgTokenizer, const char **ppszToken,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys size_t *pcchToken)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (!pCfgTokenizer->pszLineCurr)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return VERR_EOF;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int rc = VINF_SUCCESS;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys for (;;)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys char *pszTok = pCfgTokenizer->pszLineCurr;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* Skip all spaces. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys while (RT_C_IS_BLANK(*pszTok))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pszTok++;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* Check if we have to read a new line. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ( *pszTok == '\0'
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys || *pszTok == '#')
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerReadNextLine(pCfgTokenizer);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_FAILURE(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys break;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* start from the beginning. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else if ( *pszTok == '='
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys || *pszTok == ',')
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *ppszToken = pszTok;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *pcchToken = 1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->pszLineCurr = pszTok + 1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys break;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* Get the complete token. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys size_t cchToken = 1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys char *pszTmp = pszTok + 1;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys while ( RT_C_IS_ALNUM(*pszTmp)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys || *pszTmp == '_')
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pszTmp++;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys cchToken++;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *ppszToken = pszTok;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *pcchToken = cchToken;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->pszLineCurr = pszTmp;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys break;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return rc;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic int autostartConfigTokenizerCheckAndConsume(PCFGTOKENIZER pCfgTokenizer, const char *pszTokCheck)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int rc = VINF_SUCCESS;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys const char *pszToken = NULL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys size_t cchToken = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken, &cchToken);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_SUCCESS(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RTStrNCmp(pszToken, pszTokCheck, cchToken))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTMsgError("Unexpected token at line %d, expected '%s'",
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->iLine, pszTokCheck);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = VERR_INVALID_PARAMETER;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return rc;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/**
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Returns the start of the next token without consuming it.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @returns VBox status code.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @param pCfgTokenizer Tokenizer instance data.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @param ppszTok Where to store the start of the next token on success.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic int autostartConfigTokenizerPeek(PCFGTOKENIZER pCfgTokenizer, const char **ppszTok)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int rc = VINF_SUCCESS;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys for (;;)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys char *pszTok = pCfgTokenizer->pszLineCurr;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* Skip all spaces. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys while (RT_C_IS_BLANK(*pszTok))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pszTok++;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* Check if we have to read a new line. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ( *pszTok == '\0'
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys || *pszTok == '#')
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerReadNextLine(pCfgTokenizer);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_FAILURE(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys break;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* start from the beginning. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *ppszTok = pszTok;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys break;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return rc;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/**
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Check whether the given token is a reserved token.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @returns true if the token is reserved or false otherwise.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @param pszToken The token to check.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @param cchToken Size of the token in characters.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic bool autostartConfigTokenizerIsReservedToken(const char *pszToken, size_t cchToken)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ( cchToken == 1
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys && ( *pszToken == ','
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys || *pszToken == '='))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return true;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else if ( cchToken > 1
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys && ( !RTStrNCmp(pszToken, "default_policy", cchToken)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys || !RTStrNCmp(pszToken, "exception_list", cchToken)))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return true;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return false;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/**
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Parse the given configuration file and return the interesting config parameters.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @returns VBox status code.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @param pszFilename The config file to parse.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @param pfAllowed Where to store the flag whether the user of this process
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * is allowed to start VMs automatically during system startup.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @param puStartupDelay Where to store the startup delay for the user.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic int autostartParseConfig(const char *pszFilename, bool *pfAllowed, uint32_t *puStartupDelay)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int rc = VINF_SUCCESS;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys char *pszUserProcess = NULL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys bool fDefaultAllow = false;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys bool fInExceptionList = false;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys AssertPtrReturn(pfAllowed, VERR_INVALID_POINTER);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys AssertPtrReturn(puStartupDelay, VERR_INVALID_POINTER);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *pfAllowed = false;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *puStartupDelay = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = RTProcQueryUsernameA(RTProcSelf(), &pszUserProcess);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_SUCCESS(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys PCFGTOKENIZER pCfgTokenizer = NULL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerCreate(pszFilename, &pCfgTokenizer);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_SUCCESS(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys do
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys size_t cchToken = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys const char *pszToken = NULL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys &cchToken);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_SUCCESS(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (!RTStrNCmp(pszToken, "default_policy", strlen("default_policy")))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, "=");
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_SUCCESS(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys &cchToken);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_SUCCESS(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (!RTStrNCmp(pszToken, "allow", strlen("allow")))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys fDefaultAllow = true;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else if (!RTStrNCmp(pszToken, "deny", strlen("deny")))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys fDefaultAllow = false;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTMsgError("Unexpected token at line %d, expected either 'allow' or 'deny'",
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->iLine);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = VERR_INVALID_PARAMETER;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys break;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else if (!RTStrNCmp(pszToken, "exception_list", strlen("exception_list")))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, "=");
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_SUCCESS(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys &cchToken);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys while (RT_SUCCESS(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (autostartConfigTokenizerIsReservedToken(pszToken, cchToken))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTMsgError("Unexpected token at line %d, expected a username",
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->iLine);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = VERR_INVALID_PARAMETER;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys break;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else if (!RTStrNCmp(pszUserProcess, pszToken, strlen(pszUserProcess)))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys fInExceptionList = true;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* Skip , */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerPeek(pCfgTokenizer, &pszToken);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ( RT_SUCCESS(rc)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys && *pszToken == ',')
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, ",");
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys AssertRC(rc);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else if (RT_SUCCESS(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys break;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys &cchToken);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (rc == VERR_EOF)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = VINF_SUCCESS;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else if (!autostartConfigTokenizerIsReservedToken(pszToken, cchToken))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* Treat as 'username = <base delay in seconds>. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, "=");
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_SUCCESS(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys size_t cchDelay = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys const char *pszDelay = NULL;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszDelay,
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys &cchDelay);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_SUCCESS(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys uint32_t uDelay = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = RTStrToUInt32Ex(pszDelay, NULL, 10, &uDelay);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (rc == VWRN_TRAILING_SPACES)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = VINF_SUCCESS;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ( RT_SUCCESS(rc)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys && !RTStrNCmp(pszUserProcess, pszToken, strlen(pszUserProcess)))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *puStartupDelay = uDelay;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (RT_FAILURE(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTMsgError("Unexpected token at line %d, expected a number",
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->iLine);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTMsgError("Unexpected token at line %d, expected a username",
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys pCfgTokenizer->iLine);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = VERR_INVALID_PARAMETER;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys else if (rc == VERR_EOF)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys rc = VINF_SUCCESS;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys break;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys } while (RT_SUCCESS(rc));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ( RT_SUCCESS(rc)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys && ( (fDefaultAllow && !fInExceptionList)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys || (!fDefaultAllow && fInExceptionList)))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *pfAllowed= true;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys autostartConfigTokenizerDestroy(pCfgTokenizer);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTStrFree(pszUserProcess);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return rc;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic DECLCALLBACK(bool) autostartVMCmp(const AUTOSTARTVM &vm1, const AUTOSTARTVM &vm2)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return vm1.uStartupDelay <= vm2.uStartupDelay;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys}
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys/**
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Main routine for the autostart daemon.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys *
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * @returns exit status code.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllysstatic RTEXITCODE autostartMain(uint32_t uStartupDelay)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys{
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys int vrc = VINF_SUCCESS;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys std::list<AUTOSTARTVM> listVM;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (uStartupDelay)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys serviceLogVerbose(("Delay starting for %d seconds ...\n", uStartupDelay));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys vrc = RTThreadSleep(uStartupDelay * 1000);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (vrc == VERR_INTERRUPTED)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys return RTEXITCODE_SUCCESS;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Build a list of all VMs we need to autostart first, apply the overrides
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * from the configuration and start the VMs afterwards.
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys com::SafeIfaceArray<IMachine> machines;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys HRESULT rc = g_pVirtualBox->COMGETTER(Machines)(ComSafeArrayAsOutParam(machines));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (SUCCEEDED(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /*
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys * Iterate through the collection
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys for (size_t i = 0; i < machines.size(); ++i)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (machines[i])
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys BOOL fAccessible;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys CHECK_ERROR_BREAK(machines[i], COMGETTER(Accessible)(&fAccessible));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (!fAccessible)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys continue;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys BOOL fAutostart;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys CHECK_ERROR_BREAK(machines[i], COMGETTER(AutostartEnabled)(&fAutostart));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (fAutostart)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys AUTOSTARTVM autostartVM;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys CHECK_ERROR_BREAK(machines[i], COMGETTER(Id)(autostartVM.strId.asOutParam()));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys CHECK_ERROR_BREAK(machines[i], COMGETTER(AutostartDelay)(&autostartVM.uStartupDelay));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys listVM.push_back(autostartVM);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ( SUCCEEDED(rc)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys && listVM.size())
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ULONG uDelayCurr = 0;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys /* Sort by startup delay and apply base override. */
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys listVM.sort(autostartVMCmp);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys std::list<AUTOSTARTVM>::iterator it;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys for (it = listVM.begin(); it != listVM.end(); it++)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ComPtr<IMachine> machine;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys ComPtr<IProgress> progress;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if ((*it).uStartupDelay > uDelayCurr)
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys serviceLogVerbose(("Delay starting of the next VMs for %d seconds ...\n",
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys (*it).uStartupDelay - uDelayCurr));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys RTThreadSleep(((*it).uStartupDelay - uDelayCurr) * 1000);
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys uDelayCurr = (*it).uStartupDelay;
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys }
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys CHECK_ERROR_BREAK(g_pVirtualBox, FindMachine((*it).strId.raw(),
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys machine.asOutParam()));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys CHECK_ERROR_BREAK(machine, LaunchVMProcess(g_pSession, Bstr("headless").raw(),
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys Bstr("").raw(), progress.asOutParam()));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (SUCCEEDED(rc) && !progress.isNull())
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys serviceLogVerbose(("Waiting for VM \"%ls\" to power on...\n", (*it).strId.raw()));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys CHECK_ERROR(progress, WaitForCompletion(-1));
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys if (SUCCEEDED(rc))
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys {
99ebb4ca412cb0a19d77a3899a87c055b9c30fa8wyllys BOOL completed = true;
CHECK_ERROR(progress, COMGETTER(Completed)(&completed));
if (SUCCEEDED(rc))
{
ASSERT(completed);
LONG iRc;
CHECK_ERROR(progress, COMGETTER(ResultCode)(&iRc));
if (SUCCEEDED(rc))
{
if (FAILED(iRc))
{
ProgressErrorInfo info(progress);
com::GluePrintErrorInfo(info);
}
else
serviceLogVerbose(("VM \"%ls\" has been successfully started.\n", (*it).strId.raw()));
}
}
}
}
g_pSession->UnlockMachine();
}
}
}
return rcExit;
}
static void displayHeader()
{
RTStrmPrintf(g_pStdErr, VBOX_PRODUCT " Autostart " VBOX_VERSION_STRING "\n"
"(C) " VBOX_C_YEAR " " VBOX_VENDOR "\n"
"All rights reserved.\n\n");
}
/**
* Displays the help.
*
* @param pszImage Name of program name (image).
*/
static void displayHelp(const char *pszImage)
{
AssertPtrReturnVoid(pszImage);
displayHeader();
RTStrmPrintf(g_pStdErr,
"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);
RTStrmPrintf(g_pStdErr, "\n"
"Options:\n");
for (unsigned i = 0;
i < RT_ELEMENTS(g_aOptions);
++i)
{
std::string str(g_aOptions[i].pszLong);
if (g_aOptions[i].iShort < 1000) /* Don't show short options which are defined by an ID! */
{
str += ", -";
str += g_aOptions[i].iShort;
}
str += ":";
const char *pcszDescr = "";
switch (g_aOptions[i].iShort)
{
case 'h':
pcszDescr = "Print this help message and exit.";
break;
#if defined(RT_OS_LINUX) || defined (RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_DARWIN)
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, "%-23s%s\n", str.c_str(), pcszDescr);
}
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.
*/
HRESULT rc = g_pVirtualBoxClient->COMGETTER(VirtualBox)(g_pVirtualBox.asOutParam());
if (SUCCEEDED(rc))
{
rc = g_pSession.createInprocObject(CLSID_Session);
if (FAILED(rc))
RTMsgError("Failed to create a session object (rc=%Rhrc)!", rc);
}
else
RTMsgError("Failed to get VirtualBox object (rc=%Rhrc)!", rc);
if (FAILED(rc))
return VERR_COM_OBJECT_NOT_FOUND;
return VINF_SUCCESS;
}
static void autostartShutdown()
{
serviceLogVerbose(("Shutting down ...\n"));
g_pSession.setNull();
g_pVirtualBox.setNull();
}
int main(int argc, char *argv[])
{
/*
* Before we do anything, init the runtime without loading
* the support driver.
*/
int rc = RTR3InitExe(argc, &argv, 0);
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;
RTGETOPTUNION ValueUnion;
RTGETOPTSTATE GetState;
RTGetOptInit(&GetState, argc, argv,
g_aOptions, RT_ELEMENTS(g_aOptions), 1 /* First */, 0 /*fFlags*/);
while ((c = RTGetOpt(&GetState, &ValueUnion)))
{
switch (c)
{
case 'h':
displayHelp(argv[0]);
return 0;
case 'v':
g_fVerbose = true;
break;
#if defined(RT_OS_LINUX) || defined (RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_DARWIN)
case 'b':
g_fDaemonize = true;
break;
#endif
case 'V':
RTPrintf("%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr());
return 0;
case 'F':
pszLogFile = ValueUnion.psz;
break;
case 'R':
g_cHistory = ValueUnion.u32;
break;
case 'S':
g_uHistoryFileSize = ValueUnion.u64;
break;
case 'I':
g_uHistoryFileTime = ValueUnion.u32;
break;
case 'Q':
fQuiet = true;
break;
case 'c':
pszConfigFile = ValueUnion.psz;
break;
case 's':
fStart = true;
break;
case 'd':
fStop = true;
break;
default:
return RTGetOptPrintError(c, &ValueUnion);
}
}
if (!fStart && !fStop)
{
displayHelp(argv[0]);
return RTMsgErrorExit(RTEXITCODE_FAILURE, "Either --start or --stop must be present");
}
else if (fStart && fStop)
{
displayHelp(argv[0]);
return RTMsgErrorExit(RTEXITCODE_FAILURE, "--start or --stop are mutually exclusive");
}
if (!pszConfigFile)
{
displayHelp(argv[0]);
return RTMsgErrorExit(RTEXITCODE_FAILURE, "--config <config file> is missing");
}
if (!fQuiet)
displayHeader();
bool fAllowed = false;
uint32_t uStartupDelay = 0;
rc = autostartParseConfig(pszConfigFile, &fAllowed, &uStartupDelay);
if (RT_FAILURE(rc))
return RTEXITCODE_FAILURE;
if (!fAllowed)
return RTMsgErrorExit(RTEXITCODE_FAILURE, "User is not allowed to autostart VMs");
/* create release logger, to stdout */
char szError[RTPATH_MAX + 128];
rc = com::VBoxLogRelCreate("Autostart", g_fDaemonize ? NULL : pszLogFile,
RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG,
"all", "VBOXAUTOSTART_RELEASE_LOG",
RTLOGDEST_STDOUT, UINT32_MAX /* cMaxEntriesPerGroup */,
g_cHistory, g_uHistoryFileTime, g_uHistoryFileSize,
szError, sizeof(szError));
if (RT_FAILURE(rc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to open release log (%s, %Rrc)", szError, rc);
#if defined(RT_OS_LINUX) || defined (RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_DARWIN)
if (g_fDaemonize)
{
/* prepare release logging */
char szLogFile[RTPATH_MAX];
if (!pszLogFile || !*pszLogFile)
{
rc = com::GetVBoxUserHomeDirectory(szLogFile, sizeof(szLogFile));
if (RT_FAILURE(rc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "could not get base directory for logging: %Rrc", rc);
rc = RTPathAppend(szLogFile, sizeof(szLogFile), "vboxautostart.log");
if (RT_FAILURE(rc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "could not construct logging path: %Rrc", rc);
pszLogFile = szLogFile;
}
rc = RTProcDaemonizeUsingFork(false /* fNoChDir */, false /* fNoClose */, NULL);
if (RT_FAILURE(rc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to daemonize, rc=%Rrc. exiting.", rc);
/* create release logger, to file */
rc = com::VBoxLogRelCreate("Autostart", pszLogFile,
RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG,
"all", "VBOXAUTOSTART_RELEASE_LOG",
RTLOGDEST_FILE, UINT32_MAX /* cMaxEntriesPerGroup */,
g_cHistory, g_uHistoryFileTime, g_uHistoryFileSize,
szError, sizeof(szError));
if (RT_FAILURE(rc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to open release log (%s, %Rrc)", szError, rc);
}
#endif
/*
* Initialize COM.
*/
using namespace com;
HRESULT hrc = com::Initialize();
# ifdef VBOX_WITH_XPCOM
if (hrc == NS_ERROR_FILE_ACCESS_DENIED)
{
char szHome[RTPATH_MAX] = "";
com::GetVBoxUserHomeDirectory(szHome, sizeof(szHome));
return RTMsgErrorExit(RTEXITCODE_FAILURE,
"Failed to initialize COM because the global settings directory '%s' is not accessible!", szHome);
}
# endif
if (FAILED(hrc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to initialize COM (%Rhrc)!", hrc);
hrc = g_pVirtualBoxClient.createInprocObject(CLSID_VirtualBoxClient);
if (FAILED(hrc))
{
RTMsgError("Failed to create the VirtualBoxClient object (%Rhrc)!", hrc);
com::ErrorInfo info;
if (!info.isFullAvailable() && !info.isBasicAvailable())
{
com::GluePrintRCMessage(hrc);
RTMsgError("Most likely, the VirtualBox COM server is not running or failed to start.");
}
else
com::GluePrintErrorInfo(info);
return RTEXITCODE_FAILURE;
}
rc = autostartSetup();
if (RT_FAILURE(rc))
return RTEXITCODE_FAILURE;
RTEXITCODE rcExit = autostartMain(uStartupDelay);
EventQueue::getMainEventQueue()->processEventQueue(0);
autostartShutdown();
g_pVirtualBoxClient.setNull();
com::Shutdown();
return rcExit;
}