b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync/* $Id$ */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync/** @file
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * IPRT - Command Line Parsing, Argument Vector.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2010-2012 Oracle Corporation
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync *
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * available from http://www.virtualbox.org. This file is free software;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * General Public License (GPL) as published by the Free Software
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync *
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * The contents of this file may alternatively be used under the terms
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * of the Common Development and Distribution License Version 1.0
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * VirtualBox OSE distribution, in which case the provisions of the
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * CDDL are applicable instead of those of the GPL.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync *
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * You may elect to license modified versions of this file under the
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * terms and conditions of either the GPL or the CDDL or both.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync/*******************************************************************************
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync* Header Files *
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync*******************************************************************************/
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync#include <iprt/getopt.h>
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync#include "internal/iprt.h"
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync#include <iprt/asm.h>
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync#include <iprt/assert.h>
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync#include <iprt/err.h>
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync#include <iprt/mem.h>
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync#include <iprt/string.h>
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync/*******************************************************************************
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync* Header Files *
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync*******************************************************************************/
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync/**
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * Array indexed by the quoting type and 7-bit ASCII character.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync *
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * We include some extra stuff here that the corresponding shell would normally
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * require quoting of.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync */
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsyncstatic uint8_t const g_abmQuoteChars[RTGETOPTARGV_CNV_QUOTE_MASK + 1][128/8] =
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync{
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync { 0xfe, 0xff, 0x0f, 0x00, 0x65, 0x00, 0x00, 0x50 },
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync { 0xfe, 0xff, 0x0f, 0x00, 0xd7, 0x07, 0x00, 0xd8 },
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync};
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync#if 0 /* To re-generate the bitmaps. */
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync#include <stdio.h>
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsyncint main()
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync{
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync RT_ZERO(g_abmQuoteChars);
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync# define SET_ALL(ch) \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync do { \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync for (size_t iType = 0; iType <= RTGETOPTARGV_CNV_QUOTE_MASK; iType++) \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync ASMBitSet(&g_abmQuoteChars[iType], (ch)); \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync } while (0)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync# define SET(ConstSuffix, ch) \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync ASMBitSet(&g_abmQuoteChars[RTGETOPTARGV_CNV_QUOTE_##ConstSuffix], (ch));
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync /* just flag all the control chars as in need of quoting. */
0db53b55ed093edaf44670a5ee48769f11ddd9bdvboxsync for (char ch = 1; ch < 0x20; ch++)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET_ALL(ch);
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync /* ... and space of course */
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET_ALL(' ');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync /* MS CRT / CMD.EXE: */
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(MS_CRT, '"')
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(MS_CRT, '&')
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(MS_CRT, '>')
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(MS_CRT, '<')
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(MS_CRT, '|')
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(MS_CRT, '%')
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync /* Bourne shell: */
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '!');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '"');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '$');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '&');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '(');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, ')');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '*');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, ';');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '<');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '>');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '?');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '[');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '\'');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '\\');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '`');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '|');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync SET(BOURNE_SH, '~');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync for (size_t iType = 0; iType <= RTGETOPTARGV_CNV_QUOTE_MASK; iType++)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync {
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync printf(" {");
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync for (size_t iByte = 0; iByte < 8; iByte++)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync printf(iByte == 0 ? " 0x%02x" : ", 0x%02x", g_abmQuoteChars[iType][iByte]);
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync printf(" },\n");
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync }
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync return 0;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync}
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync#endif /* To re-generate the bitmaps. */
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync/**
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * Look for an unicode code point in the separator string.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync *
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @returns true if it's a separator, false if it isn't.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @param Cp The code point.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @param pszSeparators The separators.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsyncstatic bool rtGetOptIsUniCpInString(RTUNICP Cp, const char *pszSeparators)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync{
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync /* This could be done in a more optimal fashion. Probably worth a
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync separate RTStr function at some point. */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync for (;;)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync {
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync RTUNICP CpSep;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync int rc = RTStrGetCpEx(&pszSeparators, &CpSep);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync AssertRCReturn(rc, false);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (CpSep == Cp)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync return true;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (!CpSep)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync return false;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync }
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync}
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync/**
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * Look for an 7-bit ASCII character in the separator string.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync *
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @returns true if it's a separator, false if it isn't.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @param ch The character.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @param pszSeparators The separators.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @param cchSeparators The number of separators chars.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsyncDECLINLINE(bool) rtGetOptIsAsciiInSet(char ch, const char *pszSeparators, size_t cchSeparators)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync{
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync switch (cchSeparators)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync {
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync case 8: if (ch == pszSeparators[7]) return true;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync case 7: if (ch == pszSeparators[6]) return true;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync case 6: if (ch == pszSeparators[5]) return true;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync case 5: if (ch == pszSeparators[4]) return true;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync case 4: if (ch == pszSeparators[3]) return true;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync case 3: if (ch == pszSeparators[2]) return true;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync case 2: if (ch == pszSeparators[1]) return true;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync case 1: if (ch == pszSeparators[0]) return true;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync return false;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync default:
0aa150e34ed49f14aaa37368c2e6999ec89e5f43vboxsync return memchr(pszSeparators, ch, cchSeparators) != NULL;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync }
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync}
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync/**
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * Checks if the character is in the set of separators
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync *
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @returns true if it is, false if it isn't.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync *
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @param Cp The code point.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @param pszSeparators The separators.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @param cchSeparators The length of @a pszSeparators.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsyncDECL_FORCE_INLINE(bool) rtGetOptIsCpInSet(RTUNICP Cp, const char *pszSeparators, size_t cchSeparators)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync{
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (RT_LIKELY(Cp <= 127))
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync return rtGetOptIsAsciiInSet((char)Cp, pszSeparators, cchSeparators);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync return rtGetOptIsUniCpInString(Cp, pszSeparators);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync}
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync/**
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * Skips any delimiters at the start of the string that is pointed to.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync *
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @returns VINF_SUCCESS or RTStrGetCpEx status code.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @param ppszSrc Where to get and return the string pointer.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @param pszSeparators The separators.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * @param cchSeparators The length of @a pszSeparators.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsyncstatic int rtGetOptSkipDelimiters(const char **ppszSrc, const char *pszSeparators, size_t cchSeparators)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync{
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync const char *pszSrc = *ppszSrc;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync const char *pszRet;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync for (;;)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync {
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync pszRet = pszSrc;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync RTUNICP Cp;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync int rc = RTStrGetCpEx(&pszSrc, &Cp);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (RT_FAILURE(rc))
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync {
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync *ppszSrc = pszRet;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync return rc;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync }
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if ( !Cp
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync || !rtGetOptIsCpInSet(Cp, pszSeparators, cchSeparators))
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync break;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync }
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync *ppszSrc = pszRet;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync return VINF_SUCCESS;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync}
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsyncRTDECL(int) RTGetOptArgvFromString(char ***ppapszArgv, int *pcArgs, const char *pszCmdLine, const char *pszSeparators)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync{
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync /*
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * Some input validation.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync AssertPtr(pszCmdLine);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync AssertPtr(pcArgs);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync AssertPtr(ppapszArgv);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (!pszSeparators)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync pszSeparators = " \t\n\r";
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync else
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync AssertPtr(pszSeparators);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync size_t const cchSeparators = strlen(pszSeparators);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync AssertReturn(cchSeparators > 0, VERR_INVALID_PARAMETER);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync /*
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * Parse the command line and chop off it into argv individual argv strings.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync int rc = VINF_SUCCESS;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync const char *pszSrc = pszCmdLine;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync char *pszDup = (char *)RTMemAlloc(strlen(pszSrc) + 1);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync char *pszDst = pszDup;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (!pszDup)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync return VERR_NO_STR_MEMORY;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync char **papszArgs = NULL;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync unsigned iArg = 0;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync while (*pszSrc)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync {
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync /* Skip stuff */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync rc = rtGetOptSkipDelimiters(&pszSrc, pszSeparators, cchSeparators);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (RT_FAILURE(rc))
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync break;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (!*pszSrc)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync break;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync /* Start a new entry. */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if ((iArg % 32) == 0)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync {
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync void *pvNew = RTMemRealloc(papszArgs, (iArg + 33) * sizeof(char *));
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (!pvNew)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync {
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync rc = VERR_NO_MEMORY;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync break;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync }
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync papszArgs = (char **)pvNew;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync }
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync papszArgs[iArg++] = pszDst;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync /* Parse and copy the string over. */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync RTUNICP CpQuote = 0;
3bc27bc2604e7013a71c8a93bb64bc6d9e5f234bvboxsync RTUNICP Cp;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync for (;;)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync {
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync rc = RTStrGetCpEx(&pszSrc, &Cp);
3bc27bc2604e7013a71c8a93bb64bc6d9e5f234bvboxsync if (RT_FAILURE(rc) || !Cp)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync break;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (!CpQuote)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync {
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (Cp == '"' || Cp == '\'')
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync CpQuote = Cp;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync else if (rtGetOptIsCpInSet(Cp, pszSeparators, cchSeparators))
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync break;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync else
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync pszDst = RTStrPutCp(pszDst, Cp);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync }
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync else if (CpQuote != Cp)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync pszDst = RTStrPutCp(pszDst, Cp);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync else
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync CpQuote = 0;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync }
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync *pszDst++ = '\0';
3bc27bc2604e7013a71c8a93bb64bc6d9e5f234bvboxsync if (RT_FAILURE(rc) || !Cp)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync break;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync }
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (RT_FAILURE(rc))
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync {
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync RTMemFree(pszDup);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync RTMemFree(papszArgs);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync return rc;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync }
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync /*
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * Terminate the array.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync * Check for empty string to make sure we've got an array.
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (iArg == 0)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync {
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync RTMemFree(pszDup);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync papszArgs = (char **)RTMemAlloc(1 * sizeof(char *));
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (!papszArgs)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync return VERR_NO_MEMORY;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync }
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync papszArgs[iArg] = NULL;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync *pcArgs = iArg;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync *ppapszArgv = papszArgs;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync return VINF_SUCCESS;
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync}
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsyncRTDECL(void) RTGetOptArgvFree(char **papszArgv)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync{
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync if (papszArgv)
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync {
a39831afa9847c9eaf7d46a5372e99ee795d8da8vboxsync /*
a39831afa9847c9eaf7d46a5372e99ee795d8da8vboxsync * We've really only _two_ allocations here. Check the code in
a39831afa9847c9eaf7d46a5372e99ee795d8da8vboxsync * RTGetOptArgvFromString for the particulars.
a39831afa9847c9eaf7d46a5372e99ee795d8da8vboxsync */
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync RTMemFree(papszArgv[0]);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync RTMemFree(papszArgv);
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync }
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync}
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync/**
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * Checks if the argument needs quoting or not.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync *
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * @returns true if it needs, false if it don't.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * @param pszArg The argument.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * @param fFlags Quoting style.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * @param pcch Where to store the argument length when quoting
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * is not required. (optimization)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync */
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsyncDECLINLINE(bool) rtGetOpArgvRequiresQuoting(const char *pszArg, uint32_t fFlags, size_t *pcch)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync{
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync char const *psz = pszArg;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync unsigned char ch;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync while ((ch = (unsigned char)*psz))
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync {
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync if ( ch < 128
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync && ASMBitTest(&g_abmQuoteChars[fFlags & RTGETOPTARGV_CNV_QUOTE_MASK], ch))
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync return true;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync psz++;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync }
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync *pcch = psz - pszArg;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync return false;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync}
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync/**
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * Grows the command line string buffer.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync *
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * @param ppszCmdLine Pointer to the command line string pointer.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * @param pcbCmdLineAlloc Pointer to the allocation length variable.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * @param cchMin The minimum size to grow with, kind of.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync */
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsyncstatic int rtGetOptArgvToStringGrow(char **ppszCmdLine, size_t *pcbCmdLineAlloc, size_t cchMin)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync{
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync size_t cb = *pcbCmdLineAlloc;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync while (cb < cchMin)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync cb *= 2;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync cb *= 2;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync *pcbCmdLineAlloc = cb;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync return RTStrRealloc(ppszCmdLine, cb);
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync}
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync/**
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * Checks if we have a sequence of DOS slashes followed by a double quote char.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync *
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * @returns true / false accordingly.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * @param psz The string.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync */
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsyncDECLINLINE(bool) rtGetOptArgvMsCrtIsSlashQuote(const char *psz)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync{
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync while (*psz == '\\')
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync psz++;
53f225cb141e4ba722041eb59dea3df589a6cba4vboxsync return *psz == '"' || *psz == '\0';
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync}
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsyncRTDECL(int) RTGetOptArgvToString(char **ppszCmdLine, const char * const *papszArgv, uint32_t fFlags)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync{
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync AssertReturn(!(fFlags & ~RTGETOPTARGV_CNV_QUOTE_MASK), VERR_INVALID_PARAMETER);
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync#define PUT_CH(ch) \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync if (RT_UNLIKELY(off + 1 >= cbCmdLineAlloc)) { \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync rc = rtGetOptArgvToStringGrow(&pszCmdLine, &cbCmdLineAlloc, 1); \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync if (RT_FAILURE(rc)) \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync break; \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync } \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync pszCmdLine[off++] = (ch)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync#define PUT_PSZ(psz, cch) \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync if (RT_UNLIKELY(off + (cch) >= cbCmdLineAlloc)) { \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync rc = rtGetOptArgvToStringGrow(&pszCmdLine, &cbCmdLineAlloc, (cch)); \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync if (RT_FAILURE(rc)) \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync break; \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync } \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync memcpy(&pszCmdLine[off], (psz), (cch)); \
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync off += (cch);
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync#define PUT_SZ(sz) PUT_PSZ(sz, sizeof(sz) - 1)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync /*
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * Take the realloc approach, it requires less code and is probably more
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * efficient than figuring out the size first.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync */
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync int rc = VINF_SUCCESS;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync size_t off = 0;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync size_t cbCmdLineAlloc = 256;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync char *pszCmdLine = RTStrAlloc(256);
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync if (!pszCmdLine)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync return VERR_NO_STR_MEMORY;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync for (size_t i = 0; papszArgv[i]; i++)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync {
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync if (i > 0)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync {
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync PUT_CH(' ');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync }
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync /* does it need quoting? */
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync const char *pszArg = papszArgv[i];
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync size_t cchArg;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync if (!rtGetOpArgvRequiresQuoting(pszArg, fFlags, &cchArg))
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync {
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync /* No quoting needed, just append the argument. */
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync PUT_PSZ(pszArg, cchArg);
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync }
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync else if ((fFlags & RTGETOPTARGV_CNV_QUOTE_MASK) == RTGETOPTARGV_CNV_QUOTE_MS_CRT)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync {
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync /*
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * Microsoft CRT quoting. Quote the whole argument in double
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync * quotes to make it easier to read and code.
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync */
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync PUT_CH('"');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync char ch;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync while ((ch = *pszArg++))
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync {
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync if ( ch == '\\'
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync && rtGetOptArgvMsCrtIsSlashQuote(pszArg))
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync {
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync PUT_SZ("\\\\");
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync }
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync else if (ch == '"')
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync {
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync PUT_SZ("\\\"");
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync }
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync else
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync {
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync PUT_CH(ch);
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync }
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync }
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync PUT_CH('"');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync }
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync else
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync {
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync /*
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync * Bourne Shell quoting. Quote the whole thing in single quotes
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync * and use double quotes for any single quote chars.
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync */
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync PUT_CH('\'');
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync char ch;
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync while ((ch = *pszArg++))
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync {
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync if (ch == '\'')
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync {
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync PUT_SZ("'\"'\"'");
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync }
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync else
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync {
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync PUT_CH(ch);
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync }
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync }
ddee36cc1075885bd13dabbd814f18e6090b157fvboxsync PUT_CH('\'');
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync }
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync }
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync /* Set return value / cleanup. */
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync if (RT_SUCCESS(rc))
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync {
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync pszCmdLine[off] = '\0';
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync *ppszCmdLine = pszCmdLine;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync }
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync else
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync RTStrFree(pszCmdLine);
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync#undef PUT_SZ
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync#undef PUT_PSZ
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync#undef PUT_CH
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync return rc;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync}
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsyncRTDECL(int) RTGetOptArgvToUtf16String(PRTUTF16 *ppwszCmdLine, const char * const *papszArgv, uint32_t fFlags)
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync{
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync char *pszCmdLine;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync int rc = RTGetOptArgvToString(&pszCmdLine, papszArgv, fFlags);
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync if (RT_SUCCESS(rc))
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync {
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync rc = RTStrToUtf16(pszCmdLine, ppwszCmdLine);
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync RTStrFree(pszCmdLine);
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync }
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync return rc;
e8d7104a0c14c78c147fedeb2dee7053a17354ebvboxsync}
b6cc4092c1e80655a5bc19dc125e772a8d2b870dvboxsync