VBoxAutostartCfg.cpp revision b56ca3f25c9c141f3c0855b656f8f64bbfa19496
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * VBoxAutostart - VirtualBox Autostart service, configuration parser.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Copyright (C) 2012 Oracle Corporation
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * available from http://www.virtualbox.org. This file is free software;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * you can redistribute it and/or modify it under the terms of the GNU
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * General Public License (GPL) as published by the Free Software
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/*******************************************************************************
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync* Header Files *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync*******************************************************************************/
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/*******************************************************************************
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync* Constants And Macros, Structures and Typedefs *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync*******************************************************************************/
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Tokenizer instance data for the config data.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsynctypedef struct CFGTOKENIZER
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /** Config file handle. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /** String buffer for the current line we are operating in. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /** Size of the string buffer. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /** Current position in the line. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /** Current line in the config file. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/*******************************************************************************
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync* Internal Functions *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync*******************************************************************************/
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Reads the next line from the config stream.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns VBox status code.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pCfgTokenizer The config tokenizer.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic int autostartConfigTokenizerReadNextLine(PCFGTOKENIZER pCfgTokenizer)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = RTStrmGetLine(pCfgTokenizer->hStrmConfig, pCfgTokenizer->pszLine,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync pszTmp = (char *)RTMemRealloc(pCfgTokenizer->pszLine, pCfgTokenizer->cbLine);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync pCfgTokenizer->pszLineCurr = pCfgTokenizer->pszLine;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Creates the config tokenizer from the given filename.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns VBox status code.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pszFilename Config filename.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param ppCfgTokenizer Where to store the pointer to the config tokenizer on
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic int autostartConfigTokenizerCreate(const char *pszFilename, PCFGTOKENIZER *ppCfgTokenizer)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync PCFGTOKENIZER pCfgTokenizer = (PCFGTOKENIZER)RTMemAllocZ(sizeof(CFGTOKENIZER));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync pCfgTokenizer->pszLine = (char *)RTMemAllocZ(pCfgTokenizer->cbLine);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = RTStrmOpen(pszFilename, "r", &pCfgTokenizer->hStrmConfig);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerReadNextLine(pCfgTokenizer);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Destroys the given config tokenizer.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns nothing.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pCfgTokenizer The config tokenizer to destroy.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic void autostartConfigTokenizerDestroy(PCFGTOKENIZER pCfgTokenizer)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Read the next token from the config file.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns VBox status code.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pCfgTokenizer The config tokenizer data.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param ppszToken Where to store the start to the next token on success.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pcchToken Where to store the number of characters of the next token
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * excluding the \0 terminator on success.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic int autostartConfigTokenizerReadNext(PCFGTOKENIZER pCfgTokenizer, const char **ppszToken,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Skip all spaces. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Check if we have to read a new line. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerReadNextLine(pCfgTokenizer);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* start from the beginning. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Get the complete token. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic int autostartConfigTokenizerCheckAndConsume(PCFGTOKENIZER pCfgTokenizer, const char *pszTokCheck)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken, &cchToken);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync RTMsgError("Unexpected token at line %d, expected '%s'",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Returns the start of the next token without consuming it.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns VBox status code.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pCfgTokenizer Tokenizer instance data.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param ppszTok Where to store the start of the next token on success.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic int autostartConfigTokenizerPeek(PCFGTOKENIZER pCfgTokenizer, const char **ppszTok)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Skip all spaces. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Check if we have to read a new line. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerReadNextLine(pCfgTokenizer);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* start from the beginning. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Check whether the given token is a reserved token.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns true if the token is reserved or false otherwise.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pszToken The token to check.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param cchToken Size of the token in characters.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncstatic bool autostartConfigTokenizerIsReservedToken(const char *pszToken, size_t cchToken)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return true;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync && ( !RTStrNCmp(pszToken, "default_policy", cchToken)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync || !RTStrNCmp(pszToken, "exception_list", cchToken)))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return true;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync return false;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncDECLHIDDEN(int) autostartParseConfig(const char *pszFilename, bool *pfAllowed, uint32_t *puStartupDelay)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync AssertPtrReturn(puStartupDelay, VERR_INVALID_POINTER);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = RTProcQueryUsernameA(RTProcSelf(), &pszUserProcess);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerCreate(pszFilename, &pCfgTokenizer);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (!RTStrNCmp(pszToken, "default_policy", strlen("default_policy")))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, "=");
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (!RTStrNCmp(pszToken, "allow", strlen("allow")))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else if (!RTStrNCmp(pszToken, "deny", strlen("deny")))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync RTMsgError("Unexpected token at line %d, expected either 'allow' or 'deny'",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else if (!RTStrNCmp(pszToken, "exception_list", strlen("exception_list")))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, "=");
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync if (autostartConfigTokenizerIsReservedToken(pszToken, cchToken))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync RTMsgError("Unexpected token at line %d, expected a username",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else if (!RTStrNCmp(pszUserProcess, pszToken, strlen(pszUserProcess)))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Skip , */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerPeek(pCfgTokenizer, &pszToken);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, ",");
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync else if (!autostartConfigTokenizerIsReservedToken(pszToken, cchToken))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync /* Treat as 'username = <base delay in seconds>. */
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, "=");
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszDelay,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync && !RTStrNCmp(pszUserProcess, pszToken, strlen(pszUserProcess)))
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync RTMsgError("Unexpected token at line %d, expected a number",
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync RTMsgError("Unexpected token at line %d, expected a username",