VirtualBox

Changeset 55604 in vbox for trunk/src


Ignore:
Timestamp:
May 2, 2015 8:21:33 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
99977
Message:

VBoxManageGuestCtrl.cpp: Refactored the common option handling. Made the default --username value be the host user id, if we can get at it. Dropped all the short common option, except for -v and the new -q (--quiet), as they may be needed in emulating some unix or DOS command. Shouldn't be any trouble for anyone except vbox devs since they are undocument. All commands are case sensitive now. Use gctl as prefix instead of a mix of it and ctrl. Expanded upon GCTLCMD, renaming it GCTLCMDDEF and refactoring handleGuestControl with it in mind. While doing so, I've made the unix command names the preferred ones both internally and in the help text. Various adjustments has been made to option parsing code and one or two other places, but there shouldn't be any real functional changes. (The code still needs more TLC though, too sparsly commented and full of todos and quick-and-dirty error handling. This is all the care I'm willing to give it for now.)

Location:
trunk/src/VBox/Frontends/VBoxManage
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h

    r55535 r55604  
    115115# define USAGE_GSTCTRL_COPYFROM     RT_BIT(2)
    116116# define USAGE_GSTCTRL_COPYTO       RT_BIT(3)
    117 # define USAGE_GSTCTRL_CREATEDIR    RT_BIT(4)
    118 # define USAGE_GSTCTRL_REMOVEDIR    RT_BIT(5)
    119 # define USAGE_GSTCTRL_REMOVEFILE   RT_BIT(6)
    120 # define USAGE_GSTCTRL_RENAME       RT_BIT(7)
    121 # define USAGE_GSTCTRL_CREATETEMP   RT_BIT(8)
     117# define USAGE_GSTCTRL_MKDIR        RT_BIT(4)
     118# define USAGE_GSTCTRL_RMDIR        RT_BIT(5)
     119# define USAGE_GSTCTRL_RM           RT_BIT(6)
     120# define USAGE_GSTCTRL_MV           RT_BIT(7)
     121# define USAGE_GSTCTRL_MKTEMP       RT_BIT(8)
    122122# define USAGE_GSTCTRL_LIST         RT_BIT(9)
    123 # define USAGE_GSTCTRL_PROCESS      RT_BIT(10)
    124 # define USAGE_GSTCTRL_KILL         RT_BIT(11)
    125 # define USAGE_GSTCTRL_SESSION      RT_BIT(12)
    126 # define USAGE_GSTCTRL_STAT         RT_BIT(13)
    127 # define USAGE_GSTCTRL_UPDATEADDS   RT_BIT(14)
    128 # define USAGE_GSTCTRL_WATCH        RT_BIT(15)
     123# define USAGE_GSTCTRL_CLOSEPROCESS RT_BIT(10)
     124# define USAGE_GSTCTRL_CLOSESESSION RT_BIT(11)
     125# define USAGE_GSTCTRL_STAT         RT_BIT(12)
     126# define USAGE_GSTCTRL_UPDATEGA     RT_BIT(13)
     127# define USAGE_GSTCTRL_WATCH        RT_BIT(14)
    129128# define USAGE_GSTCTRL_EXEC         RT_BIT(31) /**< @deprecated Remember to remove. */
    130129#endif
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp

    r55598 r55604  
    55
    66/*
    7  * Copyright (C) 2010-2013 Oracle Corporation
     7 * Copyright (C) 2010-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    6464using namespace com;
    6565
     66/*******************************************************************************
     67*   Defined Constants And Macros                                               *
     68*******************************************************************************/
     69#define GCTLCMD_COMMON_OPT_USER             999 /**< The --username option number. */
     70#define GCTLCMD_COMMON_OPT_PASSWORD         998 /**< The --password option number. */
     71#define GCTLCMD_COMMON_OPT_PASSWORD_FILE    997 /**< The --password-file option number. */
     72#define GCTLCMD_COMMON_OPT_DOMAIN           996 /**< The --domain option number. */
     73/** Common option definitions. */
     74#define GCTLCMD_COMMON_OPTION_DEFS() \
     75    { "--username",            GCTLCMD_COMMON_OPT_USER,         RTGETOPT_REQ_STRING  }, \
     76    { "--passwordfile",        GCTLCMD_COMMON_OPT_PASSWORD_FILE,RTGETOPT_REQ_STRING  }, \
     77    { "--password",            GCTLCMD_COMMON_OPT_PASSWORD,     RTGETOPT_REQ_STRING  }, \
     78    { "--domain",              GCTLCMD_COMMON_OPT_DOMAIN,       RTGETOPT_REQ_STRING  }, \
     79    { "--quiet",               'q',                             RTGETOPT_REQ_NOTHING }, \
     80    { "--verbose",             'v',                             RTGETOPT_REQ_NOTHING },
     81
     82/** Handles common options in the typical option parsing switch. */
     83#define GCTLCMD_COMMON_OPTION_CASES(a_pCtx, a_ch, a_pValueUnion) \
     84        case 'v': \
     85        case 'q': \
     86        case GCTLCMD_COMMON_OPT_USER: \
     87        case GCTLCMD_COMMON_OPT_DOMAIN: \
     88        case GCTLCMD_COMMON_OPT_PASSWORD: \
     89        case GCTLCMD_COMMON_OPT_PASSWORD_FILE: \
     90        { \
     91            RTEXITCODE rcExitCommon = gctlCtxSetOption(a_pCtx, a_ch, a_pValueUnion); \
     92            if (RT_UNLIKELY(rcExitCommon != RTEXITCODE_SUCCESS)) \
     93                return rcExitCommon; \
     94        } break
     95
     96
     97/*******************************************************************************
     98*   Global Variables                                                           *
     99*******************************************************************************/
    66100/** Set by the signal handler when current guest control
    67101 *  action shall be aborted. */
    68102static volatile bool g_fGuestCtrlCanceled = false;
    69103
     104
     105/*******************************************************************************
     106*   Structures and Typedefs                                                    *
     107*******************************************************************************/
    70108/**
    71109 * Listener declarations.
     
    76114VBOX_LISTENER_DECLARE(GuestEventListenerImpl)
    77115
     116
    78117/**
    79  * Command context flags.
     118 * Definition of a guestcontrol command, with handler and various flags.
     119 */
     120typedef struct GCTLCMDDEF
     121{
     122    /** The command name. */
     123    const char *pszName;
     124
     125    /**
     126     * Actual command handler callback.
     127     *
     128     * @param   pCtx            Pointer to command context to use.
     129     */
     130    DECLR3CALLBACKMEMBER(RTEXITCODE, pfnHandler, (struct GCTLCMDCTX *pCtx));
     131
     132    /** The command usage flags. */
     133    uint32_t    fCmdUsage;
     134    /** Command context flags (GCTLCMDCTX_F_XXX). */
     135    uint32_t    fCmdCtx;
     136} GCTLCMD;
     137/** Pointer to a const guest control command definition. */
     138typedef GCTLCMDDEF const *PCGCTLCMDDEF;
     139
     140/** @name GCTLCMDCTX_F_XXX - Command context flags.
     141 * @{
    80142 */
    81143/** No flags set. */
    82 #define CTLCMDCTX_FLAGS_NONE                0
     144#define GCTLCMDCTX_F_NONE               0
    83145/** Don't install a signal handler (CTRL+C trap). */
    84 #define CTLCMDCTX_FLAGS_NO_SIGNAL_HANDLER   RT_BIT(0)
     146#define GCTLCMDCTX_F_NO_SIGNAL_HANDLER  RT_BIT(0)
    85147/** No guest session needed. */
    86 #define CTLCMDCTX_FLAGS_SESSION_ANONYMOUS   RT_BIT(1)
    87 /** Detach the guest session. That is, don't close the
    88  *  guest session automatically on exit. */
    89 #define CTLCMDCTX_FLAGS_SESSION_DETACH      RT_BIT(2)
     148#define GCTLCMDCTX_F_SESSION_ANONYMOUS  RT_BIT(1)
     149/** @} */
    90150
    91151/**
     
    94154typedef struct GCTLCMDCTX
    95155{
    96     HandlerArg handlerArg;
    97     /** Command-specific argument count. */
    98     int iArgc;
    99     /** Command-specific argument vector. */
    100     char **ppaArgv;
    101     /** First argv to start parsing with. */
    102     int iFirstArgc;
    103     /** Command context flags. */
    104     uint32_t uFlags;
    105     /** Verbose flag. */
    106     bool fVerbose;
     156    HandlerArg *pArg;
     157
     158    /** Pointer to the command definition. */
     159    PCGCTLCMDDEF pCmdDef;
     160    /** The VM name or UUID. */
     161    const char *pszVmNameOrUuid;
     162
     163    /** Whether we've locked the VM session. */
     164    bool fLockedVmSession;
     165    /** Whether to detach (@c true) or close the session. */
     166    bool fDetachGuestSession;
     167    /** Set if we've installed the signal handler.   */
     168    bool fInstalledSignalHandler;
     169    /** The verbosity level. */
     170    uint32_t cVerbose;
    107171    /** User name. */
    108172    Utf8Str strUsername;
     
    120184} GCTLCMDCTX, *PGCTLCMDCTX;
    121185
    122 typedef struct GCTLCMD
    123 {
    124     /**
    125      * Actual command handler callback.
    126      *
    127      * @param   pCtx            Pointer to command context to use.
    128      */
    129     DECLR3CALLBACKMEMBER(RTEXITCODE, pfnHandler, (PGCTLCMDCTX pCtx));
    130 
    131 } GCTLCMD, *PGCTLCMD;
    132186
    133187typedef struct COPYCONTEXT
     
    220274
    221275
    222 /*
    223  * Common getopt definitions, starting at 1000.
    224  * Specific command definitions will start all at 2000.
    225  */
    226 enum GETOPTDEF_COMMON
    227 {
    228     GETOPTDEF_COMMON_PASSWORD = 1000
    229 };
    230 
    231 /**
    232  * Long option IDs for the guestcontrol run command.
    233  */
    234 enum kGstCtrlRunOpt
    235 {
    236     kGstCtrlRunOpt_IgnoreOrphanedProcesses = 1000,
    237     kGstCtrlRunOpt_NoProfile,
    238     kGstCtrlRunOpt_Dos2Unix,
    239     kGstCtrlRunOpt_Unix2Dos,
    240     kGstCtrlRunOpt_WaitForStdOut,
    241     kGstCtrlRunOpt_NoWaitForStdOut,
    242     kGstCtrlRunOpt_WaitForStdErr,
    243     kGstCtrlRunOpt_NoWaitForStdErr
    244 };
    245 
    246276/**
    247277 * RTGetOpt-IDs for the guest execution control command line.
     
    266296};
    267297
    268 enum GETOPTDEF_MKDIR
    269 {
    270 };
    271 
    272 enum GETOPTDEF_RM
    273 {
    274 };
    275 
    276 enum GETOPTDEF_RMDIR
    277 {
    278 };
    279 
    280 enum GETOPTDEF_SESSIONCLOSE
    281 {
    282     GETOPTDEF_SESSIONCLOSE_ALL = 2000
    283 };
    284 
    285 enum GETOPTDEF_STAT
    286 {
    287 };
    288298
    289299enum kStreamTransform
     
    294304};
    295305
    296 static int ctrlCopyDirExists(PCOPYCONTEXT pContext, bool bGuest, const char *pszDir, bool *fExists);
     306
     307/*******************************************************************************
     308*   Internal Functions                                                         *
     309*******************************************************************************/
     310static int gctlCopyDirExists(PCOPYCONTEXT pContext, bool bGuest, const char *pszDir, bool *fExists);
    297311
    298312#endif /* VBOX_ONLY_DOCS */
     313
     314
    299315
    300316void usageGuestControl(PRTSTREAM pStrm, const char *pcszSep1, const char *pcszSep2, uint32_t uSubCmd)
     
    304320                 pcszSep1, pcszSep2,
    305321                 uSubCmd == ~0U ? "\n" : "");
     322    /*                0         1         2         3         4         5         6         7         8XXXXXXXXXX */
     323    /*                0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 */
     324#define COMMON_OPTION_HELP \
     325                     "                              [--username <name>] [--domain <domain>]\n" \
     326                     "                              [--passwordfile <file> | --password <password>]\n" \
     327                     "                              [--verbose|-v] [--quiet|-q]\n"
     328#define COMMON_OPTION_HELP_ANON \
     329                     "                              [--verbose|-v] [--quiet|-q]\n"
    306330    if (uSubCmd & USAGE_GSTCTRL_RUN)
    307331        RTStrmPrintf(pStrm,
    308                      "                              run\n"
    309                      "                              [--image <path to executable>] --username <name>\n"
    310                      "                              [--passwordfile <file> | --password <password>]\n"
    311                      "                              [--domain <domain>] [--verbose] [--timeout <msec>]\n"
     332                     "                              run\n" COMMON_OPTION_HELP
     333                     "                              [--image <path to executable>] [--timeout <msec>]\n"
    312334                     "                              [--putenv <NAME>[=<VALUE>]] [--unquoted-args]\n"
    313335                     "                              [--no-wait-stdout|--wait-stdout]\n"
     
    318340    if (uSubCmd & USAGE_GSTCTRL_START)
    319341        RTStrmPrintf(pStrm,
    320                      "                              start\n"
    321                      "                              [--image <path to executable>] --username <name>\n"
    322                      "                              [--passwordfile <file> | --password <password>]\n"
    323                      "                              [--domain <domain>] [--verbose] [--timeout <msec>]\n"
     342                     "                              start\n" COMMON_OPTION_HELP
     343                     "                              [--image <path to executable>] [--timeout <msec>]\n"
    324344                     "                              [--putenv <NAME>[=<VALUE>]] [--unquoted-args]\n"
    325                      "                              [--dos2unix] [--unix2dos]\n"
    326345                     "                              -- <program/arg0> [argument1] ... [argumentN]]\n"
    327346                 "\n");
     347    /*            0         1         2         3         4         5         6         7         8XXXXXXXXXX */
     348    /*            0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 */
    328349    if (uSubCmd == USAGE_GSTCTRL_EXEC)
    329350        RTStrmPrintf(pStrm,
     
    339360    if (uSubCmd & USAGE_GSTCTRL_COPYFROM)
    340361        RTStrmPrintf(pStrm,
    341                  "                              copyfrom\n"
    342                  "                              <guest source> <host dest> --username <name>\n"
    343                  "                              [--passwordfile <file> | --password <password>]\n"
    344                  "                              [--domain <domain>] [--verbose]\n"
     362                 "                              copyfrom\n" COMMON_OPTION_HELP
    345363                 "                              [--dryrun] [--follow] [--recursive]\n"
     364                 "                              <guest source> <host dest>\n"
    346365                 "\n");
    347366    if (uSubCmd & USAGE_GSTCTRL_COPYTO)
    348367        RTStrmPrintf(pStrm,
    349                  "                              copyto|cp\n"
    350                  "                              <host source> <guest dest> --username <name>\n"
    351                  "                              [--passwordfile <file> | --password <password>]\n"
    352                  "                              [--domain <domain>] [--verbose]\n"
     368                 "                              copyto|cp\n" COMMON_OPTION_HELP
    353369                 "                              [--dryrun] [--follow] [--recursive]\n"
     370                 "                              <host source> <guest dest> "
    354371                 "\n");
    355     if (uSubCmd & USAGE_GSTCTRL_CREATEDIR)
     372    if (uSubCmd & USAGE_GSTCTRL_MKDIR)
    356373        RTStrmPrintf(pStrm,
    357                  "                              createdir[ectory]|mkdir|md\n"
    358                  "                              <guest directory>... --username <name>\n"
    359                  "                              [--passwordfile <file> | --password <password>]\n"
    360                  "                              [--domain <domain>] [--verbose]\n"
     374                 "                              mkdir|md|createdir[ectory]\n" COMMON_OPTION_HELP
    361375                 "                              [--parents] [--mode <mode>]\n"
     376                 "                              <guest directory> [...]\n"
    362377                 "\n");
    363     if (uSubCmd & USAGE_GSTCTRL_REMOVEDIR)
     378    if (uSubCmd & USAGE_GSTCTRL_RMDIR)
    364379        RTStrmPrintf(pStrm,
    365                  "                              removedir[ectory]|rmdir\n"
    366                  "                              <guest directory>... --username <name>\n"
    367                  "                              [--passwordfile <file> | --password <password>]\n"
    368                  "                              [--domain <domain>] [--verbose]\n"
     380                 "                              rmdir|removedir[ectory]\n" COMMON_OPTION_HELP
    369381                 "                              [--recursive|-R|-r]\n"
     382                 "                              <guest directory> [...]\n"
    370383                 "\n");
    371     if (uSubCmd & USAGE_GSTCTRL_REMOVEFILE)
     384    if (uSubCmd & USAGE_GSTCTRL_RM)
    372385        RTStrmPrintf(pStrm,
    373                  "                              removefile|rm\n"
    374                  "                              <guest file>... --username <name>\n"
    375                  "                              [--passwordfile <file> | --password <password>]\n"
    376                  "                              [--domain <domain>] [--verbose]\n"
     386                 "                              removefile|rm\n" COMMON_OPTION_HELP
     387                 "                              <guest file> [...]\n"
    377388                 "\n");
    378     if (uSubCmd & USAGE_GSTCTRL_RENAME)
     389    if (uSubCmd & USAGE_GSTCTRL_MV)
    379390        RTStrmPrintf(pStrm,
    380                  "                              ren[ame]|mv\n"
    381                  "                              <source>... <dest> --username <name>\n"
    382                  "                              [--passwordfile <file> | --password <password>]\n"
    383                  "                              [--domain <domain>] [--verbose]\n"
     391                 "                              mv|move|ren[ame]\n" COMMON_OPTION_HELP
     392                 "                              <source> [source1 [...]] <dest>\n"
    384393                 "\n");
    385     if (uSubCmd & USAGE_GSTCTRL_CREATETEMP)
     394    if (uSubCmd & USAGE_GSTCTRL_MKTEMP)
    386395        RTStrmPrintf(pStrm,
    387                  "                              createtemp[orary]|mktemp\n"
    388                  "                              <template> --username <name>\n"
    389                  "                              [--passwordfile <file> | --password <password>]\n"
    390                  "                              [--directory] [--secure] [--tmpdir <directory>]\n"
    391                  "                              [--domain <domain>] [--mode <mode>] [--verbose]\n"
    392                  "\n");
    393     if (uSubCmd & USAGE_GSTCTRL_LIST)
    394         RTStrmPrintf(pStrm,
    395                  "                              list <all|sessions|processes|files> [--verbose]\n"
    396                  "\n");
    397     /** @todo Add an own help group for "session" and "process" sub commands. */
    398     if (uSubCmd & USAGE_GSTCTRL_PROCESS)
    399          RTStrmPrintf(pStrm,
    400                  "                              process kill --session-id <ID>\n"
    401                  "                                           | --session-name <name or pattern>\n"
    402                  "                                           [--verbose]\n"
    403                  "                                           <PID> ... <PID n>\n"
    404                  "\n");
    405     if (uSubCmd & USAGE_GSTCTRL_KILL)
    406         RTStrmPrintf(pStrm,
    407                  "                              [p[s]]kill --session-id <ID>\n"
    408                  "                                         | --session-name <name or pattern>\n"
    409                  "                                         [--verbose]\n"
    410                  "                                         <PID> ... <PID n>\n"
    411                  "\n");
    412     if (uSubCmd & USAGE_GSTCTRL_SESSION)
    413         RTStrmPrintf(pStrm,
    414                  "                              session close  --session-id <ID>\n"
    415                  "                                           | --session-name <name or pattern>\n"
    416                  "                                           | --all\n"
    417                  "                                           [--verbose]\n"
     396                 "                              mktemp|createtemp[orary]\n" COMMON_OPTION_HELP
     397                 "                              [--secure] [--mode <mode>] [--tmpdir <directory>]\n"
     398                 "                              <template>\n"
    418399                 "\n");
    419400    if (uSubCmd & USAGE_GSTCTRL_STAT)
    420401        RTStrmPrintf(pStrm,
    421                  "                              stat\n"
    422                  "                              <file>... --username <name>\n"
    423                  "                              [--passwordfile <file> | --password <password>]\n"
    424                  "                              [--domain <domain>] [--verbose]\n"
     402                 "                              stat\n" COMMON_OPTION_HELP
     403                 "                              <file> [...]\n"
    425404                 "\n");
    426     if (uSubCmd & USAGE_GSTCTRL_UPDATEADDS)
     405
     406    /* Command not requiring authentication. */
     407    if (uSubCmd & USAGE_GSTCTRL_LIST)
    427408        RTStrmPrintf(pStrm,
    428                  "                              updateadditions\n"
    429                  "                              [--source <guest additions .ISO>] [--verbose]\n"
     409                 "                              list <all|sessions|processes|files>\n" COMMON_OPTION_HELP_ANON
     410                 "\n");
     411    if (uSubCmd & USAGE_GSTCTRL_CLOSEPROCESS)
     412        RTStrmPrintf(pStrm,
     413                 "                              closeprocess|kill\n" COMMON_OPTION_HELP_ANON
     414                 "                              <   --session-id <ID>\n"
     415                 "                                | --session-name <name or pattern>\n"
     416                 "                              <PID1> [PID1 [...]]\n"
     417                 "\n");
     418    if (uSubCmd & USAGE_GSTCTRL_CLOSESESSION)
     419        RTStrmPrintf(pStrm,
     420                 "                              closesession\n" COMMON_OPTION_HELP_ANON
     421                 "                              <  --all | --session-id <ID>\n"
     422                 "                                | --session-name <name or pattern> >\n"
     423                 "\n");
     424    if (uSubCmd & USAGE_GSTCTRL_UPDATEGA)
     425        RTStrmPrintf(pStrm,
     426                 "                              updatega|updateguestadditions|updateadditions\n" COMMON_OPTION_HELP_ANON
     427                 "                              [--source <guest additions .ISO>]\n"
    430428                 "                              [--wait-start]\n"
    431429                 "                              [-- [<argument1>] ... [<argumentN>]]\n"
     
    433431    if (uSubCmd & USAGE_GSTCTRL_WATCH)
    434432        RTStrmPrintf(pStrm,
    435                  "                              watch [--verbose]\n"
     433                 "                              watch\n" COMMON_OPTION_HELP_ANON
    436434                 "\n");
    437435}
     
    439437#ifndef VBOX_ONLY_DOCS
    440438
     439
    441440#ifdef RT_OS_WINDOWS
    442 static BOOL WINAPI guestCtrlSignalHandler(DWORD dwCtrlType)
     441static BOOL WINAPI gctlSignalHandler(DWORD dwCtrlType)
    443442{
    444443    bool fEventHandled = FALSE;
     
    468467 * unnecessary here.
    469468 */
    470 static void guestCtrlSignalHandler(int iSignal)
     469static void gctlSignalHandler(int iSignal)
    471470{
    472471    NOREF(iSignal);
     
    474473}
    475474#endif
     475
    476476
    477477/**
     
    479479 * whenever the user wants to intercept the program.
    480480 *
    481  ** @todo Make this handler available for all VBoxManage modules?
    482  */
    483 static int ctrlSignalHandlerInstall(void)
    484 {
     481 * @todo Make this handler available for all VBoxManage modules?
     482 */
     483static int gctlSignalHandlerInstall(void)
     484{
     485    g_fGuestCtrlCanceled = false;
     486
    485487    int rc = VINF_SUCCESS;
    486488#ifdef RT_OS_WINDOWS
    487     if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)guestCtrlSignalHandler, TRUE /* Add handler */))
     489    if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)gctlSignalHandler, TRUE /* Add handler */))
    488490    {
    489491        rc = RTErrConvertFromWin32(GetLastError());
     
    491493    }
    492494#else
    493     signal(SIGINT,   guestCtrlSignalHandler);
     495    signal(SIGINT,   gctlSignalHandler);
    494496# ifdef SIGBREAK
    495     signal(SIGBREAK, guestCtrlSignalHandler);
     497    signal(SIGBREAK, gctlSignalHandler);
    496498# endif
    497499#endif
     
    499501}
    500502
     503
    501504/**
    502505 * Uninstalls a previously installed signal handler.
    503506 */
    504 static int ctrlSignalHandlerUninstall(void)
     507static int gctlSignalHandlerUninstall(void)
    505508{
    506509    int rc = VINF_SUCCESS;
     
    520523}
    521524
     525
    522526/**
    523  * Translates a process status to a human readable
    524  * string.
    525  */
    526 const char *ctrlProcessStatusToText(ProcessStatus_T enmStatus)
     527 * Translates a process status to a human readable string.
     528 */
     529const char *gctlProcessStatusToText(ProcessStatus_T enmStatus)
    527530{
    528531    switch (enmStatus)
     
    556559}
    557560
    558 const char *ctrlProcessWaitResultToText(ProcessWaitResult_T enmWaitResult)
     561/**
     562 * Translates a guest process wait result to a human readable string.
     563 */
     564const char *gctlProcessWaitResultToText(ProcessWaitResult_T enmWaitResult)
    559565{
    560566    switch (enmWaitResult)
     
    585591
    586592/**
    587  * Translates a guest session status to a human readable
    588  * string.
    589  */
    590 const char *ctrlSessionStatusToText(GuestSessionStatus_T enmStatus)
     593 * Translates a guest session status to a human readable string.
     594 */
     595const char *gctlGuestSessionStatusToText(GuestSessionStatus_T enmStatus)
    591596{
    592597    switch (enmStatus)
     
    615620
    616621/**
    617  * Translates a guest file status to a human readable
    618  * string.
    619  */
    620 const char *ctrlFileStatusToText(FileStatus_T enmStatus)
     622 * Translates a guest file status to a human readable string.
     623 */
     624const char *gctlFileStatusToText(FileStatus_T enmStatus)
    621625{
    622626    switch (enmStatus)
     
    640644}
    641645
    642 static int ctrlPrintError(com::ErrorInfo &errorInfo)
     646static int gctlPrintError(com::ErrorInfo &errorInfo)
    643647{
    644648    if (   errorInfo.isFullAvailable()
     
    660664}
    661665
    662 static int ctrlPrintError(IUnknown *pObj, const GUID &aIID)
     666static int gctlPrintError(IUnknown *pObj, const GUID &aIID)
    663667{
    664668    com::ErrorInfo ErrInfo(pObj, aIID);
    665     return ctrlPrintError(ErrInfo);
    666 }
    667 
    668 static int ctrlPrintProgressError(ComPtr<IProgress> pProgress)
     669    return gctlPrintError(ErrInfo);
     670}
     671
     672static int gctlPrintProgressError(ComPtr<IProgress> pProgress)
    669673{
    670674    int vrc = VINF_SUCCESS;
     
    682686            {
    683687                com::ProgressErrorInfo ErrInfo(pProgress);
    684                 vrc = ctrlPrintError(ErrInfo);
     688                vrc = gctlPrintError(ErrInfo);
    685689            }
    686690        }
     
    693697}
    694698
     699
     700
     701/*
     702 *
     703 *
     704 * Guest Control Command Context
     705 * Guest Control Command Context
     706 * Guest Control Command Context
     707 * Guest Control Command Context
     708 *
     709 *
     710 *
     711 */
     712
     713
    695714/**
     715 * Initializes a guest control command context structure.
     716 *
     717 * @returns RTEXITCODE_SUCCESS on success, RTEXITCODE_FAILURE on failure (after
     718 *           informing the user of course).
     719 * @param   pCtx                The command context to init.
     720 * @param   pArg                The handle argument package.
     721 * @param   pCmdDef             The command definition.
     722 */
     723static RTEXITCODE gctrCmdCtxInit(PGCTLCMDCTX pCtx, HandlerArg *pArg, PCGCTLCMDDEF pCmdDef)
     724{
     725    Assert(pArg->argc >= 2);
     726    RT_ZERO(*pCtx);
     727    pCtx->pArg = pArg;
     728    pCtx->pCmdDef = pCmdDef;
     729    pCtx->pszVmNameOrUuid = pArg->argv[0];
     730
     731    /*
     732     * The user name defaults to the host one, if we can get at it.
     733     */
     734    char szUser[1024];
     735    int rc = RTProcQueryUsername(RTProcSelf(), szUser, sizeof(szUser), NULL);
     736    if (   RT_SUCCESS(rc)
     737        && RTStrIsValidEncoding(szUser)) /* paranoia required on posix */
     738    {
     739        try
     740        {
     741            pCtx->strUsername = szUser;
     742        }
     743        catch (std::bad_alloc &)
     744        {
     745            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Out of memory");
     746        }
     747    }
     748    /* else: ignore this failure. */
     749
     750    return RTEXITCODE_SUCCESS;
     751}
     752
     753
     754/**
     755 * Worker for GCTLCMD_COMMON_OPTION_CASES.
     756 *
     757 * @returns RTEXITCODE_SUCCESS if the option was handled successfully.  If not,
     758 *          an error message is printed and an appropriate failure exit code is
     759 *          returned.
     760 * @param   pCtx                The guest control command context.
     761 * @param   ch                  The option char or ordinal.
     762 * @param   pValueUnion         The option value union.
     763 */
     764static RTEXITCODE gctlCtxSetOption(PGCTLCMDCTX pCtx, int ch, PRTGETOPTUNION pValueUnion)
     765{
     766    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     767    switch (ch)
     768    {
     769        case 'u': /* User name */
     770            if (!(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS))
     771                pCtx->strUsername = pValueUnion->psz;
     772            else
     773                return errorSyntaxEx(USAGE_GUESTCONTROL, pCtx->pCmdDef->fCmdUsage,
     774                                     "The --username|-u option is not valid with this command");
     775            break;
     776
     777        case GCTLCMD_COMMON_OPT_PASSWORD: /* Password */
     778            if (!(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS))
     779            {
     780                if (pCtx->strPassword.isNotEmpty())
     781                    RTMsgWarning("Password is given more than once.");
     782                pCtx->strPassword = pValueUnion->psz;
     783            }
     784            else
     785                return errorSyntaxEx(USAGE_GUESTCONTROL, pCtx->pCmdDef->fCmdUsage,
     786                                     "The --password option is not valid with this command");
     787            break;
     788
     789        case 'p': /* Password file */
     790            if (!(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS))
     791                rcExit = readPasswordFile(pValueUnion->psz, &pCtx->strPassword);
     792            else
     793                return errorSyntaxEx(USAGE_GUESTCONTROL, pCtx->pCmdDef->fCmdUsage,
     794                                     "The --password-file|-p option is not valid with this command");
     795            break;
     796
     797        case 'd': /* domain */
     798            if (!(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS))
     799                pCtx->strDomain = pValueUnion->psz;
     800            else
     801                return errorSyntaxEx(USAGE_GUESTCONTROL, pCtx->pCmdDef->fCmdUsage,
     802                                     "The --domain option is not valid with this command");
     803            break;
     804
     805        case 'v': /* --verbose */
     806            pCtx->cVerbose++;
     807            break;
     808
     809        case 'q': /* --quiet */
     810            if (pCtx->cVerbose)
     811                pCtx->cVerbose--;
     812            break;
     813
     814        default:
     815            AssertFatalMsgFailed(("ch=%d (%c)\n", ch, ch));
     816    }
     817    return rcExit;
     818}
     819
     820
     821/**
     822 * Initializes the VM for IGuest operation.
     823 *
     824 * This opens a shared session to a running VM and gets hold of IGuest.
     825 *
     826 * @returns RTEXITCODE_SUCCESS on success.  RTEXITCODE_FAILURE and user message
     827 *          on failure.
     828 * @param   pCtx            The guest control command context.
     829 *                          GCTLCMDCTX::pGuest will be set on success.
     830 */
     831static RTEXITCODE gctlCtxInitVmSession(PGCTLCMDCTX pCtx)
     832{
     833    HRESULT rc;
     834    AssertPtr(pCtx);
     835    AssertPtr(pCtx->pArg);
     836
     837    /*
     838     * Find the VM and check if it's running.
     839     */
     840    ComPtr<IMachine> machine;
     841    CHECK_ERROR(pCtx->pArg->virtualBox, FindMachine(Bstr(pCtx->pszVmNameOrUuid).raw(), machine.asOutParam()));
     842    if (SUCCEEDED(rc))
     843    {
     844        MachineState_T enmMachineState;
     845        CHECK_ERROR(machine, COMGETTER(State)(&enmMachineState));
     846        if (   SUCCEEDED(rc)
     847            && enmMachineState == MachineState_Running)
     848        {
     849            /*
     850             * It's running. So, open a session to it and get the IGuest interface.
     851             */
     852            CHECK_ERROR(machine, LockMachine(pCtx->pArg->session, LockType_Shared));
     853            if (SUCCEEDED(rc))
     854            {
     855                pCtx->fLockedVmSession = true;
     856                ComPtr<IConsole> ptrConsole;
     857                CHECK_ERROR(pCtx->pArg->session, COMGETTER(Console)(ptrConsole.asOutParam()));
     858                if (SUCCEEDED(rc))
     859                {
     860                    CHECK_ERROR(ptrConsole, COMGETTER(Guest)(pCtx->pGuest.asOutParam()));
     861                    if (SUCCEEDED(rc))
     862                        return RTEXITCODE_SUCCESS;
     863                }
     864            }
     865        }
     866        else if(SUCCEEDED(rc))
     867            RTMsgError("Machine \"%s\" is not running (currently %s)!\n",
     868                       pCtx->pszVmNameOrUuid, machineStateToName(enmMachineState, false));
     869    }
     870    return RTEXITCODE_FAILURE;
     871}
     872
     873
     874/**
     875 * Creates a guest session with the VM.
     876 *
     877 * @retval  RTEXITCODE_SUCCESS on success.
     878 * @retval  RTEXITCODE_FAILURE and user message on failure.
     879 * @param   pCtx            The guest control command context.
     880 *                          GCTCMDCTX::pGuestSession and GCTLCMDCTX::uSessionID
     881 *                          will be set.
     882 */
     883static RTEXITCODE gctlCtxInitGuestSession(PGCTLCMDCTX pCtx)
     884{
     885    HRESULT rc;
     886    AssertPtr(pCtx);
     887    Assert(!(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS));
     888    Assert(pCtx->pGuest.isNotNull());
     889
     890    /*
     891     * Build up a reasonable guest session name. Useful for identifying
     892     * a specific session when listing / searching for them.
     893     */
     894    char *pszSessionName;
     895    if (RTStrAPrintf(&pszSessionName,
     896                     "[%RU32] VBoxManage Guest Control [%s] - %s",
     897                     RTProcSelf(), pCtx->pszVmNameOrUuid, pCtx->pCmdDef->pszName) < 0)
     898        return RTMsgErrorExit(RTEXITCODE_FAILURE, "No enough memory for session name");
     899
     900    /*
     901     * Create a guest session.
     902     */
     903    if (pCtx->cVerbose > 1)
     904        RTPrintf("Creating guest session as user '%s'...\n", pCtx->strUsername.c_str());
     905    try
     906    {
     907        CHECK_ERROR(pCtx->pGuest, CreateSession(Bstr(pCtx->strUsername).raw(),
     908                                                Bstr(pCtx->strPassword).raw(),
     909                                                Bstr(pCtx->strDomain).raw(),
     910                                                Bstr(pszSessionName).raw(),
     911                                                pCtx->pGuestSession.asOutParam()));
     912    }
     913    catch (std::bad_alloc &)
     914    {
     915        RTMsgError("Out of memory setting up IGuest::CreateSession call");
     916        rc = E_OUTOFMEMORY;
     917    }
     918    if (SUCCEEDED(rc))
     919    {
     920        /*
     921         * Wait for guest session to start.
     922         */
     923        if (pCtx->cVerbose > 1)
     924            RTPrintf("Waiting for guest session to start...\n");
     925        GuestSessionWaitResult_T enmWaitResult;
     926        try
     927        {
     928            com::SafeArray<GuestSessionWaitForFlag_T> aSessionWaitFlags;
     929            aSessionWaitFlags.push_back(GuestSessionWaitForFlag_Start);
     930            CHECK_ERROR(pCtx->pGuestSession, WaitForArray(ComSafeArrayAsInParam(aSessionWaitFlags),
     931                                                          /** @todo Make session handling timeouts configurable. */
     932                                                          30 * 1000, &enmWaitResult));
     933        }
     934        catch (std::bad_alloc &)
     935        {
     936            RTMsgError("Out of memory setting up IGuestSession::WaitForArray call");
     937            rc = E_OUTOFMEMORY;
     938        }
     939        if (SUCCEEDED(rc))
     940        {
     941            /* The WaitFlagNotSupported result may happen with GAs older than 4.3. */
     942            if (   enmWaitResult == GuestSessionWaitResult_Start
     943                || enmWaitResult == GuestSessionWaitResult_WaitFlagNotSupported)
     944            {
     945                /*
     946                 * Get the session ID and we're ready to rumble.
     947                 */
     948                CHECK_ERROR(pCtx->pGuestSession, COMGETTER(Id)(&pCtx->uSessionID));
     949                if (SUCCEEDED(rc))
     950                {
     951                    if (pCtx->cVerbose > 1)
     952                        RTPrintf("Successfully started guest session (ID %RU32)\n", pCtx->uSessionID);
     953                    RTStrFree(pszSessionName);
     954                    return RTEXITCODE_SUCCESS;
     955                }
     956            }
     957            else
     958            {
     959                GuestSessionStatus_T enmSessionStatus;
     960                CHECK_ERROR(pCtx->pGuestSession, COMGETTER(Status)(&enmSessionStatus));
     961                RTMsgError("Error starting guest session (current status is: %s)\n",
     962                           SUCCEEDED(rc) ? gctlGuestSessionStatusToText(enmSessionStatus) : "<unknown>");
     963            }
     964        }
     965    }
     966
     967    RTStrFree(pszSessionName);
     968    return RTEXITCODE_FAILURE;
     969}
     970
     971
     972/**
     973 * Completes the guest control context initialization after parsing arguments.
     974 *
     975 * Will validate common arguments, open a VM session, and if requested open a
     976 * guest session and install the CTRL-C signal handler.
     977 *
     978 * It is good to validate all the options and arguments you can before making
     979 * this call.  However, the VM session, IGuest and IGuestSession interfaces are
     980 * not availabe till after this call, so take care.
     981 *
     982 * @retval  RTEXITCODE_SUCCESS on success.
     983 * @retval  RTEXITCODE_FAILURE and user message on failure.
     984 * @param   pCtx            The guest control command context.
     985 *                          GCTCMDCTX::pGuestSession and GCTLCMDCTX::uSessionID
     986 *                          will be set.
     987 */
     988static RTEXITCODE gctlCtxPostArgParsingInit(PGCTLCMDCTX pCtx)
     989{
     990    /*
     991     * Check that the user name isn't empty when we need it.
     992     */
     993    RTEXITCODE rcExit;
     994    if (  (pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS)
     995        || pCtx->strUsername.isNotEmpty())
     996    {
     997        /*
     998         * Open the VM session and if required, a guest session.
     999         */
     1000        rcExit = gctlCtxInitVmSession(pCtx);
     1001        if (   rcExit == RTEXITCODE_SUCCESS
     1002            && !(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS))
     1003            rcExit = gctlCtxInitGuestSession(pCtx);
     1004        if (rcExit == RTEXITCODE_SUCCESS)
     1005        {
     1006            /*
     1007             * Install signal handler if requested (errors are ignored).
     1008             */
     1009            if (!(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_NO_SIGNAL_HANDLER))
     1010            {
     1011                int rc = gctlSignalHandlerInstall();
     1012                pCtx->fInstalledSignalHandler = RT_SUCCESS(rc);
     1013            }
     1014        }
     1015    }
     1016    else
     1017        rcExit = errorSyntaxEx(USAGE_GUESTCONTROL, pCtx->pCmdDef->fCmdUsage, "No user name specified!");
     1018    return rcExit;
     1019}
     1020
     1021
     1022/**
     1023 * Cleans up the context when the command returns.
     1024 *
     1025 * This will close any open guest session, unless the DETACH flag is set.
     1026 * It will also close any VM session that may be been established.  Any signal
     1027 * handlers we've installed will also be removed.
     1028 *
    6961029 * Un-initializes the VM after guest control usage.
    6971030 * @param   pCmdCtx                 Pointer to command context.
    698  * @param   uFlags                  Command context flags.
    699  */
    700 static void ctrlUninitVM(PGCTLCMDCTX pCtx, uint32_t uFlags)
    701 {
    702     AssertPtrReturnVoid(pCtx);
    703 
    704     if (!(pCtx->uFlags & CTLCMDCTX_FLAGS_NO_SIGNAL_HANDLER))
    705         ctrlSignalHandlerUninstall();
    706 
     1031 */
     1032static void gctlCtxTerm(PGCTLCMDCTX pCtx)
     1033{
    7071034    HRESULT rc;
    708 
    709     do
    710     {
    711         if (!pCtx->pGuestSession.isNull())
    712         {
    713             if (   !(pCtx->uFlags & CTLCMDCTX_FLAGS_SESSION_ANONYMOUS)
    714                 && !(pCtx->uFlags & CTLCMDCTX_FLAGS_SESSION_DETACH))
    715             {
    716                 if (pCtx->fVerbose)
    717                     RTPrintf("Closing guest session ...\n");
    718 
    719                 CHECK_ERROR(pCtx->pGuestSession, Close());
    720                 /* Keep going - don't break here. Try to unlock the
    721                  * machine down below. */
    722             }
    723             else if (   (pCtx->uFlags & CTLCMDCTX_FLAGS_SESSION_DETACH)
    724                      && pCtx->fVerbose)
    725                 RTPrintf("Guest session detached\n");
    726 
    727             pCtx->pGuestSession.setNull();
    728         }
    729 
    730         if (pCtx->handlerArg.session)
    731             CHECK_ERROR(pCtx->handlerArg.session, UnlockMachine());
    732 
    733     } while (0);
    734 
    735     for (int i = 0; i < pCtx->iArgc; i++)
    736         RTStrFree(pCtx->ppaArgv[i]);
    737     RTMemFree(pCtx->ppaArgv);
    738     pCtx->iArgc = 0;
    739 }
    740 
    741 /**
    742  * Initializes the VM for IGuest operations.
    743  *
    744  * That is, checks whether it's up and running, if it can be locked (shared
    745  * only) and returns a valid IGuest pointer on success. Also, it does some
    746  * basic command line processing and opens a guest session, if required.
    747  *
    748  * @return  RTEXITCODE status code.
    749  * @param   pArg                    Pointer to command line argument structure.
    750  * @param   pCmdCtx                 Pointer to command context.
    751  * @param   uFlags                  Command context flags.
    752  */
    753 static RTEXITCODE ctrlInitVM(HandlerArg *pArg,
    754                              PGCTLCMDCTX pCtx, uint32_t uFlags, uint32_t uUsage)
    755 {
    756     AssertPtrReturn(pArg, RTEXITCODE_FAILURE);
    757     AssertReturn(pArg->argc > 1, RTEXITCODE_FAILURE);
    758     AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
    759 
    760 #ifdef DEBUG_andy
    761     RTPrintf("Original argv:\n");
    762     for (int i=0; i<pArg->argc;i++)
    763         RTPrintf("\targv[%d]=%s\n", i, pArg->argv[i]);
    764 #endif
    765 
    766     RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    767 
    768     const char *pszNameOrId = pArg->argv[0];
    769     const char *pszCmd = pArg->argv[1];
    770 
    771     /* Lookup VM. */
    772     ComPtr<IMachine> machine;
    773     /* Assume it's an UUID. */
    774     HRESULT rc;
    775     CHECK_ERROR(pArg->virtualBox, FindMachine(Bstr(pszNameOrId).raw(),
    776                                               machine.asOutParam()));
    777     if (SUCCEEDED(rc))
    778     {
    779         /* Machine is running? */
    780         MachineState_T machineState;
    781         CHECK_ERROR(machine, COMGETTER(State)(&machineState));
    782         if (   SUCCEEDED(rc)
    783             && (machineState != MachineState_Running))
    784             rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Machine \"%s\" is not running (currently %s)!\n",
    785                                     pszNameOrId, machineStateToName(machineState, false));
    786     }
    787     else
    788         rcExit = RTEXITCODE_FAILURE;
    789 
    790     if (rcExit == RTEXITCODE_SUCCESS)
    791     {
    792         /*
    793          * Process standard options which are served by all commands.
    794          */
    795         static const RTGETOPTDEF s_aOptions[] =
    796         {
    797             { "--username",            'u',                             RTGETOPT_REQ_STRING  },
    798             { "--passwordfile",        'p',                             RTGETOPT_REQ_STRING  },
    799             { "--password",            GETOPTDEF_COMMON_PASSWORD,       RTGETOPT_REQ_STRING  },
    800             { "--domain",              'd',                             RTGETOPT_REQ_STRING  },
    801             { "--verbose",             'v',                             RTGETOPT_REQ_NOTHING }
    802         };
    803 
    804 
    805 
    806         /** @todo r=bird: This is just SOOOO hackish and fragile, especially wrt to the
    807          * exec/run commands. If you don't have the full option syntax, there is no way
    808          * you can safely tell an option from an option value. sigh.
    809          * The way to do this is by a defines with the above s_aOptions entries, calling
    810          * a common function in the default case of each option parser, and a routine to
    811          * be called at the end of option parsing to open the session. */
    812 
    813 
    814 
    815         /*
    816          * Allocate per-command argv. This then only contains the specific arguments
    817          * the command needs.
    818          */
    819         pCtx->ppaArgv = (char**)RTMemAlloc(pArg->argc * sizeof(char*) + 1);
    820         if (!pCtx->ppaArgv)
    821         {
    822             rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Not enough memory for per-command argv\n");
    823         }
    824         else
    825         {
    826             pCtx->iArgc = 0;
    827 
    828             int iArgIdx = 2; /* Skip VM name and guest control command */
    829             int ch;
    830             RTGETOPTUNION ValueUnion;
    831             RTGETOPTSTATE GetState;
    832             RTGetOptInit(&GetState, pArg->argc, pArg->argv,
    833                          s_aOptions, RT_ELEMENTS(s_aOptions),
    834                          iArgIdx, 0);
    835 
    836             while (   (ch = RTGetOpt(&GetState, &ValueUnion))
    837                    && (rcExit == RTEXITCODE_SUCCESS))
    838             {
    839                 /* For options that require an argument, ValueUnion has received the value. */
    840                 switch (ch)
    841                 {
    842                     case 'u': /* User name */
    843                         if (!(uFlags & CTLCMDCTX_FLAGS_SESSION_ANONYMOUS))
    844                             pCtx->strUsername = ValueUnion.psz;
    845                         iArgIdx = GetState.iNext;
    846                         break;
    847 
    848                     case GETOPTDEF_COMMON_PASSWORD: /* Password */
    849                         if (!(uFlags & CTLCMDCTX_FLAGS_SESSION_ANONYMOUS))
    850                         {
    851                             if (pCtx->strPassword.isEmpty())
    852                                 pCtx->strPassword = ValueUnion.psz;
    853                         }
    854                         iArgIdx = GetState.iNext;
    855                         break;
    856 
    857                     case 'p': /* Password file */
    858                     {
    859                         if (!(uFlags & CTLCMDCTX_FLAGS_SESSION_ANONYMOUS))
    860                             rcExit = readPasswordFile(ValueUnion.psz, &pCtx->strPassword);
    861                         iArgIdx = GetState.iNext;
    862                         break;
    863                     }
    864 
    865                     case 'd': /* domain */
    866                         if (!(uFlags & CTLCMDCTX_FLAGS_SESSION_ANONYMOUS))
    867                             pCtx->strDomain = ValueUnion.psz;
    868                         iArgIdx = GetState.iNext;
    869                         break;
    870 
    871                     case 'v': /* Verbose */
    872                         pCtx->fVerbose = true;
    873                         iArgIdx = GetState.iNext;
    874                         break;
    875 
    876                     case 'h': /* Help */
    877                         errorGetOptEx(USAGE_GUESTCONTROL, uUsage, ch, &ValueUnion);
    878                         return RTEXITCODE_SYNTAX;
    879 
    880                     default:
    881                         /* Simply skip; might be handled in a specific command
    882                          * handler later. */
    883                         break;
    884 
    885                 } /* switch */
    886 
    887                 int iArgDiff = GetState.iNext - iArgIdx;
    888                 if (iArgDiff)
    889                 {
    890 #ifdef DEBUG_andy
    891                     RTPrintf("Not handled (iNext=%d, iArgsCur=%d):\n", GetState.iNext, iArgIdx);
    892 #endif
    893                     for (int i = iArgIdx; i < GetState.iNext; i++)
    894                     {
    895                         char *pszArg = RTStrDup(pArg->argv[i]);
    896                         if (!pszArg)
    897                         {
    898                             rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE,
    899                                                     "Not enough memory for command line handling\n");
    900                             break;
    901                         }
    902                         pCtx->ppaArgv[pCtx->iArgc] = pszArg;
    903                         pCtx->iArgc++;
    904 #ifdef DEBUG_andy
    905                         RTPrintf("\targv[%d]=%s\n", i, pArg->argv[i]);
    906 #endif
    907                     }
    908 
    909                     iArgIdx = GetState.iNext;
    910                 }
    911 
    912             } /* while RTGetOpt */
    913         }
    914     }
     1035    AssertPtr(pCtx);
    9151036
    9161037    /*
    917      * Check for mandatory stuff.
     1038     * Uninstall signal handler.
    9181039     */
    919     if (rcExit == RTEXITCODE_SUCCESS)
    920     {
    921 #if 0
    922         RTPrintf("argc=%d\n", pCtx->iArgc);
    923         for (int i = 0; i < pCtx->iArgc; i++)
    924             RTPrintf("argv[%d]=%s\n", i, pCtx->ppaArgv[i]);
    925 #endif
    926         if (!(uFlags & CTLCMDCTX_FLAGS_SESSION_ANONYMOUS))
    927         {
    928             if (pCtx->strUsername.isEmpty())
    929                 rcExit = errorSyntaxEx(USAGE_GUESTCONTROL, uUsage, "No user name specified!");
    930         }
    931     }
    932 
    933     if (rcExit == RTEXITCODE_SUCCESS)
    934     {
    935         /*
    936          * Build up a reasonable guest session name. Useful for identifying
    937          * a specific session when listing / searching for them.
    938          */
    939         char *pszSessionName;
    940         if (0 >= RTStrAPrintf(&pszSessionName,
    941                               "[%RU32] VBoxManage Guest Control [%s] - %s",
    942                               RTProcSelf(), pszNameOrId, pszCmd))
    943             return RTMsgErrorExit(RTEXITCODE_FAILURE, "No enough memory for session name\n");
    944 
    945         do
    946         {
    947             /* Open a session for the VM. */
    948             CHECK_ERROR_BREAK(machine, LockMachine(pArg->session, LockType_Shared));
    949             /* Get the associated console. */
    950             ComPtr<IConsole> console;
    951             CHECK_ERROR_BREAK(pArg->session, COMGETTER(Console)(console.asOutParam()));
    952             /* ... and session machine. */
    953             ComPtr<IMachine> sessionMachine;
    954             CHECK_ERROR_BREAK(pArg->session, COMGETTER(Machine)(sessionMachine.asOutParam()));
    955             /* Get IGuest interface. */
    956             CHECK_ERROR_BREAK(console, COMGETTER(Guest)(pCtx->pGuest.asOutParam()));
    957             if (!(uFlags & CTLCMDCTX_FLAGS_SESSION_ANONYMOUS))
    958             {
    959                 if (pCtx->fVerbose)
    960                     RTPrintf("Opening guest session as user '%s' ...\n", pCtx->strUsername.c_str());
    961 
    962                 /* Open a guest session. */
    963                 Assert(!pCtx->pGuest.isNull());
    964                 CHECK_ERROR_BREAK(pCtx->pGuest, CreateSession(Bstr(pCtx->strUsername).raw(),
    965                                                               Bstr(pCtx->strPassword).raw(),
    966                                                               Bstr(pCtx->strDomain).raw(),
    967                                                               Bstr(pszSessionName).raw(),
    968                                                               pCtx->pGuestSession.asOutParam()));
    969 
    970                 /*
    971                  * Wait for guest session to start.
    972                  */
    973                 if (pCtx->fVerbose)
    974                     RTPrintf("Waiting for guest session to start ...\n");
    975 
    976                 com::SafeArray<GuestSessionWaitForFlag_T> aSessionWaitFlags;
    977                 aSessionWaitFlags.push_back(GuestSessionWaitForFlag_Start);
    978                 GuestSessionWaitResult_T sessionWaitResult;
    979                 CHECK_ERROR_BREAK(pCtx->pGuestSession, WaitForArray(ComSafeArrayAsInParam(aSessionWaitFlags),
    980                                                                     /** @todo Make session handling timeouts configurable. */
    981                                                                     30 * 1000, &sessionWaitResult));
    982 
    983                 if (   sessionWaitResult == GuestSessionWaitResult_Start
    984                     /* Note: This might happen when Guest Additions < 4.3 are installed which don't
    985                      *       support dedicated guest sessions. */
    986                     || sessionWaitResult == GuestSessionWaitResult_WaitFlagNotSupported)
    987                 {
    988                     CHECK_ERROR_BREAK(pCtx->pGuestSession, COMGETTER(Id)(&pCtx->uSessionID));
    989                     if (pCtx->fVerbose)
    990                         RTPrintf("Guest session (ID %RU32) has been started\n", pCtx->uSessionID);
    991                 }
    992                 else
    993                 {
    994                     GuestSessionStatus_T sessionStatus;
    995                     CHECK_ERROR_BREAK(pCtx->pGuestSession, COMGETTER(Status)(&sessionStatus));
    996                     rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error starting guest session (current status is: %s)\n",
    997                                             ctrlSessionStatusToText(sessionStatus));
    998                     break;
    999                 }
    1000             }
    1001 
    1002             if (   SUCCEEDED(rc)
    1003                 && !(uFlags & CTLCMDCTX_FLAGS_NO_SIGNAL_HANDLER))
    1004             {
    1005                 ctrlSignalHandlerInstall();
    1006             }
    1007 
    1008         } while (0);
    1009 
    1010         if (FAILED(rc))
    1011             rcExit = RTEXITCODE_FAILURE;
    1012 
    1013         RTStrFree(pszSessionName);
    1014     }
    1015 
    1016     if (rcExit == RTEXITCODE_SUCCESS)
    1017     {
    1018         pCtx->handlerArg = *pArg;
    1019         pCtx->uFlags = uFlags;
    1020     }
    1021     else /* Clean up on failure. */
    1022         ctrlUninitVM(pCtx, uFlags);
    1023 
    1024     return rcExit;
    1025 }
     1040    if (pCtx->fInstalledSignalHandler)
     1041    {
     1042        gctlSignalHandlerUninstall();
     1043        pCtx->fInstalledSignalHandler = false;
     1044    }
     1045
     1046    /*
     1047     * Close, or at least release, the guest session.
     1048     */
     1049    if (pCtx->pGuestSession.isNotNull())
     1050    {
     1051        if (   !(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS)
     1052            && !pCtx->fDetachGuestSession)
     1053        {
     1054            if (pCtx->cVerbose > 1)
     1055                RTPrintf("Closing guest session ...\n");
     1056
     1057            CHECK_ERROR(pCtx->pGuestSession, Close());
     1058        }
     1059        else if (   pCtx->fDetachGuestSession
     1060                 && pCtx->cVerbose > 1)
     1061            RTPrintf("Guest session detached\n");
     1062
     1063        pCtx->pGuestSession.setNull();
     1064    }
     1065
     1066    /*
     1067     * Close the VM session.
     1068     */
     1069    if (pCtx->fLockedVmSession)
     1070    {
     1071        Assert(pCtx->pArg->session.isNotNull());
     1072        CHECK_ERROR(pCtx->pArg->session, UnlockMachine());
     1073        pCtx->fLockedVmSession = false;
     1074    }
     1075}
     1076
     1077
     1078
     1079
     1080
     1081/*
     1082 *
     1083 *
     1084 * Guest Control Command Handling.
     1085 * Guest Control Command Handling.
     1086 * Guest Control Command Handling.
     1087 * Guest Control Command Handling.
     1088 * Guest Control Command Handling.
     1089 *
     1090 *
     1091 */
    10261092
    10271093
     
    10441110 * @note    The guest exit code mappings was introduced with 5.0 and the 'run'
    10451111 *          command, they are/was not supported by 'exec'.
    1046  * @sa      ctrlRunCalculateExitCode
     1112 * @sa      gctlRunCalculateExitCode
    10471113 */
    10481114/** Process exited normally but with an exit code <> 0. */
     
    10791145 *                              exit codes.
    10801146 */
    1081 static RTEXITCODE ctrlRunCalculateExitCode(ProcessStatus_T enmStatus, ULONG uExitCode, bool fReturnExitCodes)
     1147static RTEXITCODE gctlRunCalculateExitCode(ProcessStatus_T enmStatus, ULONG uExitCode, bool fReturnExitCodes)
    10821148{
    10831149    int vrc = RTEXITCODE_SUCCESS;
     
    11341200 *                          complete.
    11351201 */
    1136 static int ctrlRunPumpOutput(IProcess *pProcess, RTVFSIOSTREAM hVfsIosDst, ULONG uHandle, RTMSINTERVAL cMsTimeout)
     1202static int gctlRunPumpOutput(IProcess *pProcess, RTVFSIOSTREAM hVfsIosDst, ULONG uHandle, RTMSINTERVAL cMsTimeout)
    11371203{
    11381204    AssertPtrReturn(pProcess, VERR_INVALID_POINTER);
     
    11591225    }
    11601226    else
    1161         vrc = ctrlPrintError(pProcess, COM_IIDOF(IProcess));
     1227        vrc = gctlPrintError(pProcess, COM_IIDOF(IProcess));
    11621228    return vrc;
    11631229}
     
    11741240 * @param   phVfsIos            Where to return the resulting I/O stream handle.
    11751241 */
    1176 static bool ctrlRunSetupHandle(bool fEnabled, RTHANDLESTD enmHandle, const char *pszName,
     1242static bool gctlRunSetupHandle(bool fEnabled, RTHANDLESTD enmHandle, const char *pszName,
    11771243                               kStreamTransform enmTransformation, PRTVFSIOSTREAM phVfsIos)
    11781244{
     
    12031269 * @param   cMsTimeout      Timeout value (in ms).
    12041270 */
    1205 static RTMSINTERVAL ctrlExecGetRemainingTime(uint64_t u64StartMs, RTMSINTERVAL cMsTimeout)
     1271static RTMSINTERVAL gctlRunGetRemainingTime(uint64_t u64StartMs, RTMSINTERVAL cMsTimeout)
    12061272{
    12071273    if (!cMsTimeout || cMsTimeout == RT_INDEFINITE_WAIT) /* If no timeout specified, wait forever. */
     
    12231289 * @param   fHelp       The help flag for the command.
    12241290 */
    1225 static RTEXITCODE handleCtrlProcessRunCommon(PGCTLCMDCTX pCtx, bool fRunCmd, uint32_t fHelp)
     1291static RTEXITCODE gctlHandleRunCommon(PGCTLCMDCTX pCtx, bool fRunCmd, uint32_t fHelp)
    12261292{
    12271293    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
     
    12301296     * Parse arguments.
    12311297     */
     1298    enum kGstCtrlRunOpt
     1299    {
     1300        kGstCtrlRunOpt_IgnoreOrphanedProcesses = 1000,
     1301        kGstCtrlRunOpt_NoProfile,
     1302        kGstCtrlRunOpt_Dos2Unix,
     1303        kGstCtrlRunOpt_Unix2Dos,
     1304        kGstCtrlRunOpt_WaitForStdOut,
     1305        kGstCtrlRunOpt_NoWaitForStdOut,
     1306        kGstCtrlRunOpt_WaitForStdErr,
     1307        kGstCtrlRunOpt_NoWaitForStdErr
     1308    };
    12321309    static const RTGETOPTDEF s_aOptions[] =
    12331310    {
     1311        GCTLCMD_COMMON_OPTION_DEFS()
    12341312        { "--putenv",                       'E',                                      RTGETOPT_REQ_STRING  },
    12351313        { "--executable",                   'e',                                      RTGETOPT_REQ_STRING  },
     
    12491327    RTGETOPTUNION           ValueUnion;
    12501328    RTGETOPTSTATE           GetState;
    1251     RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv, s_aOptions, RT_ELEMENTS(s_aOptions),
    1252                  pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     1329    RTGetOptInit(&GetState, pCtx->pArg->argc, pCtx->pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions),
     1330                 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    12531331
    12541332    com::SafeArray<ProcessCreateFlag_T>     aCreateFlags;
     
    12761354            switch (ch)
    12771355            {
     1356                GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion);
     1357
    12781358                case 'E':
    12791359                    if (   ValueUnion.psz[0] == '\0'
     
    13661446        {
    13671447            aWaitFlags.push_back(ProcessWaitForFlag_Terminate);
    1368             fWaitForStdOut = ctrlRunSetupHandle(fWaitForStdOut, RTHANDLESTD_OUTPUT, "stdout", enmStdOutTransform, &hVfsStdOut);
     1448            fWaitForStdOut = gctlRunSetupHandle(fWaitForStdOut, RTHANDLESTD_OUTPUT, "stdout", enmStdOutTransform, &hVfsStdOut);
    13691449            if (fWaitForStdOut)
    13701450            {
     
    13721452                aWaitFlags.push_back(ProcessWaitForFlag_StdOut);
    13731453            }
    1374             fWaitForStdErr = ctrlRunSetupHandle(fWaitForStdErr, RTHANDLESTD_ERROR, "stderr", enmStdErrTransform, &hVfsStdErr);
     1454            fWaitForStdErr = gctlRunSetupHandle(fWaitForStdErr, RTHANDLESTD_ERROR, "stderr", enmStdErrTransform, &hVfsStdErr);
    13751455            if (fWaitForStdErr)
    13761456            {
     
    13851465    }
    13861466
    1387     RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     1467    RTEXITCODE rcExit = gctlCtxPostArgParsingInit(pCtx);
     1468    if (rcExit != RTEXITCODE_SUCCESS)
     1469        return rcExit;
     1470
    13881471    HRESULT rc;
    13891472
     
    13981481             * Create the process.
    13991482             */
    1400             if (pCtx->fVerbose)
     1483            if (pCtx->cVerbose > 1)
    14011484            {
    14021485                if (cMsTimeout == 0)
     
    14101493                                                                 ComSafeArrayAsInParam(aEnv),
    14111494                                                                 ComSafeArrayAsInParam(aCreateFlags),
    1412                                                                  ctrlExecGetRemainingTime(msStart, cMsTimeout),
     1495                                                                 gctlRunGetRemainingTime(msStart, cMsTimeout),
    14131496                                                                 pProcess.asOutParam()));
    14141497
     
    14201503            ProcessWaitResult_T waitResult;
    14211504            CHECK_ERROR_BREAK(pProcess, WaitForArray(ComSafeArrayAsInParam(aWaitStartFlags),
    1422                                                      ctrlExecGetRemainingTime(msStart, cMsTimeout), &waitResult));
     1505                                                     gctlRunGetRemainingTime(msStart, cMsTimeout), &waitResult));
    14231506
    14241507            ULONG uPID = 0;
    14251508            CHECK_ERROR_BREAK(pProcess, COMGETTER(PID)(&uPID));
    1426             if (fRunCmd && pCtx->fVerbose)
     1509            if (fRunCmd && pCtx->cVerbose > 1)
    14271510                RTPrintf("Process '%s' (PID %RU32) started\n", pszImage, uPID);
    14281511            else if (!fRunCmd) /** @todo Introduce a --quiet option for not printing this. */
     
    14461529                   && cMsTimeLeft > 0)
    14471530            {
    1448                 cMsTimeLeft = ctrlExecGetRemainingTime(msStart, cMsTimeout);
     1531                cMsTimeLeft = gctlRunGetRemainingTime(msStart, cMsTimeout);
    14491532                CHECK_ERROR_BREAK(pProcess, WaitForArray(ComSafeArrayAsInParam(aWaitFlags),
    14501533                                                         RT_MIN(500 /*ms*/, RT_MAX(cMsTimeLeft, 1 /*ms*/)),
     
    14621545                        break;
    14631546                    case ProcessWaitResult_Terminate:
    1464                         if (pCtx->fVerbose)
     1547                        if (pCtx->cVerbose > 1)
    14651548                            RTPrintf("Process terminated\n");
    14661549                        /* Process terminated, we're done. */
     
    15081591                if (fReadStdOut)
    15091592                {
    1510                     cMsTimeLeft = ctrlExecGetRemainingTime(msStart, cMsTimeout);
    1511                     int vrc2 = ctrlRunPumpOutput(pProcess, hVfsStdOut, 1 /* StdOut */, cMsTimeLeft);
     1593                    cMsTimeLeft = gctlRunGetRemainingTime(msStart, cMsTimeout);
     1594                    int vrc2 = gctlRunPumpOutput(pProcess, hVfsStdOut, 1 /* StdOut */, cMsTimeLeft);
    15121595                    if (RT_FAILURE(vrc2) && RT_SUCCESS(vrc))
    15131596                        vrc = vrc2;
     
    15161599                if (fReadStdErr)
    15171600                {
    1518                     cMsTimeLeft = ctrlExecGetRemainingTime(msStart, cMsTimeout);
    1519                     int vrc2 = ctrlRunPumpOutput(pProcess, hVfsStdErr, 2 /* StdErr */, cMsTimeLeft);
     1601                    cMsTimeLeft = gctlRunGetRemainingTime(msStart, cMsTimeout);
     1602                    int vrc2 = gctlRunPumpOutput(pProcess, hVfsStdErr, 2 /* StdErr */, cMsTimeLeft);
    15201603                    if (RT_FAILURE(vrc2) && RT_SUCCESS(vrc))
    15211604                        vrc = vrc2;
     
    15371620            if (g_fGuestCtrlCanceled)
    15381621            {
    1539                 if (pCtx->fVerbose)
     1622                if (pCtx->cVerbose > 1)
    15401623                    RTPrintf("Process execution aborted!\n");
    15411624                rcExit = EXITCODEEXEC_CANCELED;
     
    15431626            else if (fCompletedStartCmd)
    15441627            {
    1545                 if (pCtx->fVerbose)
     1628                if (pCtx->cVerbose > 1)
    15461629                    RTPrintf("Process successfully started!\n");
    15471630                rcExit = RTEXITCODE_SUCCESS;
     
    15571640                    LONG lExitCode;
    15581641                    CHECK_ERROR_BREAK(pProcess, COMGETTER(ExitCode)(&lExitCode));
    1559                     if (pCtx->fVerbose)
     1642                    if (pCtx->cVerbose > 1)
    15601643                        RTPrintf("Exit code=%u (Status=%u [%s])\n",
    1561                                  lExitCode, procStatus, ctrlProcessStatusToText(procStatus));
    1562 
    1563                     rcExit = ctrlRunCalculateExitCode(procStatus, lExitCode, true /*fReturnExitCodes*/);
     1644                                 lExitCode, procStatus, gctlProcessStatusToText(procStatus));
     1645
     1646                    rcExit = gctlRunCalculateExitCode(procStatus, lExitCode, true /*fReturnExitCodes*/);
    15641647                }
    15651648                else if (   procStatus == ProcessStatus_TimedOutKilled
    15661649                         || procStatus == ProcessStatus_TimedOutAbnormally)
    15671650                {
    1568                     if (pCtx->fVerbose)
     1651                    if (pCtx->cVerbose > 1)
    15691652                        RTPrintf("Process timed out (guest side) and\n",
    15701653                                 procStatus == ProcessStatus_TimedOutAbnormally
     
    15741657                else
    15751658                {
    1576                     if (pCtx->fVerbose)
    1577                         RTPrintf("Process now is in status [%s] (unexpected)\n", ctrlProcessStatusToText(procStatus));
     1659                    if (pCtx->cVerbose > 1)
     1660                        RTPrintf("Process now is in status [%s] (unexpected)\n", gctlProcessStatusToText(procStatus));
    15781661                    rcExit = RTEXITCODE_FAILURE;
    15791662                }
     
    15811664            else if (RT_FAILURE_NP(vrc))
    15821665            {
    1583                 if (pCtx->fVerbose)
     1666                if (pCtx->cVerbose > 1)
    15841667                    RTPrintf("Process monitor loop quit with vrc=%Rrc\n", vrc);
    15851668                rcExit = RTEXITCODE_FAILURE;
     
    15871670            else
    15881671            {
    1589                 if (pCtx->fVerbose)
     1672                if (pCtx->cVerbose > 1)
    15901673                    RTPrintf("Process monitor loop timed out\n");
    15911674                rcExit = EXITCODEEXEC_TIMEOUT;
     
    16091692     */
    16101693    if (!fRunCmd && SUCCEEDED(rc) && !g_fGuestCtrlCanceled)
    1611         pCtx->uFlags |= CTLCMDCTX_FLAGS_SESSION_DETACH;
     1694        pCtx->fDetachGuestSession = true;
    16121695
    16131696    /* Make sure we return failure on failure. */
     
    16181701
    16191702
    1620 static DECLCALLBACK(RTEXITCODE) handleCtrlProcessRun(PGCTLCMDCTX pCtx)
    1621 {
    1622     return handleCtrlProcessRunCommon(pCtx, true /*fRunCmd*/, USAGE_GSTCTRL_RUN);
    1623 }
    1624 
    1625 
    1626 static DECLCALLBACK(RTEXITCODE) handleCtrlProcessStart(PGCTLCMDCTX pCtx)
    1627 {
    1628     return handleCtrlProcessRunCommon(pCtx, false /*fRunCmd*/, USAGE_GSTCTRL_START);
     1703static DECLCALLBACK(RTEXITCODE) gctlHandleRun(PGCTLCMDCTX pCtx)
     1704{
     1705    return gctlHandleRunCommon(pCtx, true /*fRunCmd*/, USAGE_GSTCTRL_RUN);
     1706}
     1707
     1708
     1709static DECLCALLBACK(RTEXITCODE) gctlHandleStart(PGCTLCMDCTX pCtx)
     1710{
     1711    return gctlHandleRunCommon(pCtx, false /*fRunCmd*/, USAGE_GSTCTRL_START);
    16291712}
    16301713
     
    17491832    }
    17501833    else
    1751         vrc = ctrlPrintError(pProcess, COM_IIDOF(IProcess));
     1834        vrc = gctlPrintError(pProcess, COM_IIDOF(IProcess));
    17521835    return vrc;
    17531836}
    17541837
    17551838
    1756 static DECLCALLBACK(RTEXITCODE) handleCtrlProcessExecDeprecated(PGCTLCMDCTX pCtx)
     1839static DECLCALLBACK(RTEXITCODE) gctlHandleProcessExecDeprecated(PGCTLCMDCTX pCtx)
    17571840{
    17581841    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
     
    17631846    static const RTGETOPTDEF s_aOptions[] =
    17641847    {
     1848        GCTLCMD_COMMON_OPTION_DEFS()
    17651849        { "--dos2unix",                     GETOPTDEF_EXEC_DOS2UNIX,                  RTGETOPT_REQ_NOTHING },
    17661850        { "--environment",                  'e',                                      RTGETOPT_REQ_STRING  },
     
    17711855        { "--timeout",                      't',                                      RTGETOPT_REQ_UINT32  },
    17721856        { "--unix2dos",                     GETOPTDEF_EXEC_UNIX2DOS,                  RTGETOPT_REQ_NOTHING },
    1773         { "--unquoted-args",                'u',                                      RTGETOPT_REQ_NOTHING },
     1857        { "--unquoted-args",                'U',                                      RTGETOPT_REQ_NOTHING },
    17741858        { "--wait-exit",                    GETOPTDEF_EXEC_WAITFOREXIT,               RTGETOPT_REQ_NOTHING },
    17751859        { "--wait-stdout",                  GETOPTDEF_EXEC_WAITFORSTDOUT,             RTGETOPT_REQ_NOTHING },
     
    17771861    };
    17781862
    1779 #ifdef DEBUG_andy
    1780     RTPrintf("first=%d\n", pCtx->iFirstArgc);
    1781     for (int i=0; i<pCtx->iArgc;i++)
    1782         RTPrintf("\targv[%d]=%s\n", i, pCtx->ppaArgv[i]);
    1783 #endif
    1784 
    17851863    int                     ch;
    17861864    RTGETOPTUNION           ValueUnion;
    17871865    RTGETOPTSTATE           GetState;
    1788     RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv, s_aOptions, RT_ELEMENTS(s_aOptions),
    1789                  pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     1866    RTGetOptInit(&GetState, pCtx->pArg->argc, pCtx->pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions),
     1867                 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    17901868
    17911869    Utf8Str                              strCmd;
     
    18111889            switch (ch)
    18121890            {
     1891                GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion);
     1892
    18131893                case 'e': /* Environment */
    18141894                {
     
    18391919                    break;
    18401920
    1841                 case 'u':
     1921                case 'U':
    18421922                    aCreateFlags.push_back(ProcessCreateFlag_UnquotedArguments);
    18431923                    break;
     
    19071987                             "No command to execute specified!");
    19081988
    1909     RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     1989    RTEXITCODE rcExit = gctlCtxPostArgParsingInit(pCtx);
     1990    if (rcExit != RTEXITCODE_SUCCESS)
     1991        return rcExit;
     1992
    19101993    HRESULT rc;
    19111994
     
    19212004            uint64_t u64StartMS = RTTimeMilliTS();
    19222005
    1923             if (pCtx->fVerbose)
     2006            if (pCtx->cVerbose > 1)
    19242007            {
    19252008                if (cMsTimeout == 0)
     
    19372020                                                                 ComSafeArrayAsInParam(aEnv),
    19382021                                                                 ComSafeArrayAsInParam(aCreateFlags),
    1939                                                                  ctrlExecGetRemainingTime(u64StartMS, cMsTimeout),
     2022                                                                 gctlRunGetRemainingTime(u64StartMS, cMsTimeout),
    19402023                                                                 pProcess.asOutParam()));
    19412024
     
    19482031            ProcessWaitResult_T waitResult;
    19492032            CHECK_ERROR_BREAK(pProcess, WaitForArray(ComSafeArrayAsInParam(aWaitStartFlags),
    1950                                                      ctrlExecGetRemainingTime(u64StartMS, cMsTimeout), &waitResult));
     2033                                                     gctlRunGetRemainingTime(u64StartMS, cMsTimeout), &waitResult));
    19512034            bool fCompleted = false;
    19522035
    19532036            ULONG uPID = 0;
    19542037            CHECK_ERROR_BREAK(pProcess, COMGETTER(PID)(&uPID));
    1955             if (!fDetached && pCtx->fVerbose)
     2038            if (!fDetached && pCtx->cVerbose > 1)
    19562039            {
    19572040                RTPrintf("Process '%s' (PID %RU32) started\n",
     
    19812064                   && cMsTimeLeft != 0)
    19822065            {
    1983                 cMsTimeLeft = ctrlExecGetRemainingTime(u64StartMS, cMsTimeout);
     2066                cMsTimeLeft = gctlRunGetRemainingTime(u64StartMS, cMsTimeout);
    19842067                CHECK_ERROR_BREAK(pProcess, WaitForArray(ComSafeArrayAsInParam(aWaitFlags),
    19852068                                                         500 /* ms */, &waitResult));
     
    20012084                        break;
    20022085                    case ProcessWaitResult_Terminate:
    2003                         if (pCtx->fVerbose)
     2086                        if (pCtx->cVerbose > 1)
    20042087                            RTPrintf("Process terminated\n");
    20052088                        /* Process terminated, we're done. */
     
    20282111                if (fReadStdOut) /* Do we need to fetch stdout data? */
    20292112                {
    2030                     cMsTimeLeft = ctrlExecGetRemainingTime(u64StartMS, cMsTimeout);
     2113                    cMsTimeLeft = gctlRunGetRemainingTime(u64StartMS, cMsTimeout);
    20312114                    vrc = ctrlExecPrintOutputDeprecated(pProcess, g_pStdOut,
    20322115                                                        1 /* StdOut */, cMsTimeLeft);
     
    20362119                if (fReadStdErr) /* Do we need to fetch stdout data? */
    20372120                {
    2038                     cMsTimeLeft = ctrlExecGetRemainingTime(u64StartMS, cMsTimeout);
     2121                    cMsTimeLeft = gctlRunGetRemainingTime(u64StartMS, cMsTimeout);
    20392122                    vrc = ctrlExecPrintOutputDeprecated(pProcess, g_pStdErr,
    20402123                                                        2 /* StdErr */, cMsTimeLeft);
     
    20712154                            LONG exitCode;
    20722155                            CHECK_ERROR_BREAK(pProcess, COMGETTER(ExitCode)(&exitCode));
    2073                             if (pCtx->fVerbose)
     2156                            if (pCtx->cVerbose > 1)
    20742157                                RTPrintf("Exit code=%u (Status=%u [%s])\n",
    2075                                          exitCode, procStatus, ctrlProcessStatusToText(procStatus));
     2158                                         exitCode, procStatus, gctlProcessStatusToText(procStatus));
    20762159
    20772160                            rcExit = (RTEXITCODE)ctrlExecProcessStatusToExitCodeDeprecated(procStatus, exitCode);
    20782161                        }
    2079                         else if (pCtx->fVerbose)
    2080                             RTPrintf("Process now is in status [%s]\n", ctrlProcessStatusToText(procStatus));
     2162                        else if (pCtx->cVerbose > 1)
     2163                            RTPrintf("Process now is in status [%s]\n", gctlProcessStatusToText(procStatus));
    20812164                    }
    20822165                }
    20832166                else
    20842167                {
    2085                     if (pCtx->fVerbose)
     2168                    if (pCtx->cVerbose > 1)
    20862169                        RTPrintf("Process execution aborted!\n");
    20872170
     
    21232206
    21242207    if (!fCloseSession)
    2125         pCtx->uFlags |= CTLCMDCTX_FLAGS_SESSION_DETACH;
     2208        pCtx->fDetachGuestSession = true;
    21262209
    21272210    if (   rcExit == RTEXITCODE_SUCCESS
     
    21392222/**
    21402223 * Creates a copy context structure which then can be used with various
    2141  * guest control copy functions. Needs to be free'd with ctrlCopyContextFree().
     2224 * guest control copy functions. Needs to be free'd with gctlCopyContextFree().
    21422225 *
    21432226 * @return  IPRT status code.
     
    21492232 * @param   ppContext               Pointer which receives the allocated copy context.
    21502233 */
    2151 static int ctrlCopyContextCreate(PGCTLCMDCTX pCtx, bool fDryRun, bool fHostToGuest,
     2234static int gctlCopyContextCreate(PGCTLCMDCTX pCtx, bool fDryRun, bool fHostToGuest,
    21522235                                 const Utf8Str &strSessionName,
    21532236                                 PCOPYCONTEXT *ppContext)
     
    21792262 * @param   pContext                Pointer to copy context to free.
    21802263 */
    2181 static void ctrlCopyContextFree(PCOPYCONTEXT pContext)
     2264static void gctlCopyContextFree(PCOPYCONTEXT pContext)
    21822265{
    21832266    if (pContext)
     
    21992282 *                                  path. Must be free'd with RTStrFree().
    22002283 */
    2201 static int ctrlCopyTranslatePath(const char *pszSourceRoot, const char *pszSource,
     2284static int gctlCopyTranslatePath(const char *pszSourceRoot, const char *pszSource,
    22022285                                 const char *pszDest, char **ppszTranslated)
    22032286{
     
    22932376
    22942377        char *pszTranslated = NULL;
    2295         int iResult =  ctrlCopyTranslatePath(aTests[iTest].pszSourceRoot, aTests[iTest].pszSource,
     2378        int iResult =  gctlCopyTranslatePath(aTests[iTest].pszSourceRoot, aTests[iTest].pszSource,
    22962379                                             aTests[iTest].pszDest, &pszTranslated);
    22972380        if (iResult != aTests[iTest].iResult)
     
    23262409 * @param   pszDir                  Directory to create.
    23272410 */
    2328 static int ctrlCopyDirCreate(PCOPYCONTEXT pContext, const char *pszDir)
     2411static int gctlCopyDirCreate(PCOPYCONTEXT pContext, const char *pszDir)
    23292412{
    23302413    AssertPtrReturn(pContext, VERR_INVALID_POINTER);
     
    23322415
    23332416    bool fDirExists;
    2334     int vrc = ctrlCopyDirExists(pContext, pContext->fHostToGuest, pszDir, &fDirExists);
     2417    int vrc = gctlCopyDirExists(pContext, pContext->fHostToGuest, pszDir, &fDirExists);
    23352418    if (   RT_SUCCESS(vrc)
    23362419        && fDirExists)
    23372420    {
    2338         if (pContext->pCmdCtx->fVerbose)
     2421        if (pContext->pCmdCtx->cVerbose > 1)
    23392422            RTPrintf("Directory \"%s\" already exists\n", pszDir);
    23402423        return VINF_SUCCESS;
     
    23462429        return vrc;
    23472430
    2348     if (pContext->pCmdCtx->fVerbose)
     2431    if (pContext->pCmdCtx->cVerbose > 1)
    23492432        RTPrintf("Creating directory \"%s\" ...\n", pszDir);
    23502433
     
    23592442                                                                       0700, ComSafeArrayAsInParam(dirCreateFlags));
    23602443        if (FAILED(rc))
    2361             vrc = ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
     2444            vrc = gctlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
    23622445    }
    23632446    else /* ... or on the host. */
     
    23812464 *                                  given directory exists or not.
    23822465 */
    2383 static int ctrlCopyDirExists(PCOPYCONTEXT pContext, bool fOnGuest,
     2466static int gctlCopyDirExists(PCOPYCONTEXT pContext, bool fOnGuest,
    23842467                             const char *pszDir, bool *fExists)
    23852468{
     
    23942477        HRESULT rc = pContext->pCmdCtx->pGuestSession->DirectoryExists(Bstr(pszDir).raw(), &fDirExists);
    23952478        if (FAILED(rc))
    2396             vrc = ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
     2479            vrc = gctlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
    23972480        else
    23982481            *fExists = fDirExists ? true : false;
     
    24132496 *                                  given directory exists or not.
    24142497 */
    2415 static int ctrlCopyDirExistsOnDest(PCOPYCONTEXT pContext, const char *pszDir,
     2498static int gctlCopyDirExistsOnDest(PCOPYCONTEXT pContext, const char *pszDir,
    24162499                                   bool *fExists)
    24172500{
    2418     return ctrlCopyDirExists(pContext, pContext->fHostToGuest,
     2501    return gctlCopyDirExists(pContext, pContext->fHostToGuest,
    24192502                             pszDir, fExists);
    24202503}
     
    24302513 *                                  given directory exists or not.
    24312514 */
    2432 static int ctrlCopyDirExistsOnSource(PCOPYCONTEXT pContext, const char *pszDir,
     2515static int gctlCopyDirExistsOnSource(PCOPYCONTEXT pContext, const char *pszDir,
    24332516                                     bool *fExists)
    24342517{
    2435     return ctrlCopyDirExists(pContext, !pContext->fHostToGuest,
     2518    return gctlCopyDirExists(pContext, !pContext->fHostToGuest,
    24362519                             pszDir, fExists);
    24372520}
     
    24482531 *                                  given file exists or not.
    24492532 */
    2450 static int ctrlCopyFileExists(PCOPYCONTEXT pContext, bool bOnGuest,
     2533static int gctlCopyFileExists(PCOPYCONTEXT pContext, bool bOnGuest,
    24512534                              const char *pszFile, bool *fExists)
    24522535{
     
    24612544        HRESULT rc = pContext->pCmdCtx->pGuestSession->FileExists(Bstr(pszFile).raw(), &fFileExists);
    24622545        if (FAILED(rc))
    2463             vrc = ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
     2546            vrc = gctlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
    24642547        else
    24652548            *fExists = fFileExists ? true : false;
     
    24802563 *                                  given file exists or not.
    24812564 */
    2482 static int ctrlCopyFileExistsOnDest(PCOPYCONTEXT pContext, const char *pszFile,
     2565static int gctlCopyFileExistsOnDest(PCOPYCONTEXT pContext, const char *pszFile,
    24832566                                    bool *fExists)
    24842567{
    2485     return ctrlCopyFileExists(pContext, pContext->fHostToGuest,
     2568    return gctlCopyFileExists(pContext, pContext->fHostToGuest,
    24862569                              pszFile, fExists);
    24872570}
     
    24972580 *                                  given file exists or not.
    24982581 */
    2499 static int ctrlCopyFileExistsOnSource(PCOPYCONTEXT pContext, const char *pszFile,
     2582static int gctlCopyFileExistsOnSource(PCOPYCONTEXT pContext, const char *pszFile,
    25002583                                      bool *fExists)
    25012584{
    2502     return ctrlCopyFileExists(pContext, !pContext->fHostToGuest,
     2585    return gctlCopyFileExists(pContext, !pContext->fHostToGuest,
    25032586                              pszFile, fExists);
    25042587}
     
    25142597 *                                  to be set to 0.
    25152598 */
    2516 static int ctrlCopyFileToDest(PCOPYCONTEXT pContext, const char *pszFileSource,
     2599static int gctlCopyFileToDest(PCOPYCONTEXT pContext, const char *pszFileSource,
    25172600                              const char *pszFileDest, uint32_t fFlags)
    25182601{
     
    25222605    AssertReturn(!fFlags, VERR_INVALID_POINTER); /* No flags supported yet. */
    25232606
    2524     if (pContext->pCmdCtx->fVerbose)
     2607    if (pContext->pCmdCtx->cVerbose > 1)
    25252608        RTPrintf("Copying \"%s\" to \"%s\" ...\n",
    25262609                 pszFileSource, pszFileDest);
     
    25492632    if (FAILED(rc))
    25502633    {
    2551         vrc = ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
     2634        vrc = gctlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
    25522635    }
    25532636    else
    25542637    {
    2555         if (pContext->pCmdCtx->fVerbose)
     2638        if (pContext->pCmdCtx->cVerbose > 1)
    25562639            rc = showProgress(pProgress);
    25572640        else
     
    25592642        if (SUCCEEDED(rc))
    25602643            CHECK_PROGRESS_ERROR(pProgress, ("File copy failed"));
    2561         vrc = ctrlPrintProgressError(pProgress);
     2644        vrc = gctlPrintProgressError(pProgress);
    25622645    }
    25632646
     
    25772660 *                                  is needed for recursion.
    25782661 */
    2579 static int ctrlCopyDirToGuest(PCOPYCONTEXT pContext,
     2662static int gctlCopyDirToGuest(PCOPYCONTEXT pContext,
    25802663                              const char *pszSource, const char *pszFilter,
    25812664                              const char *pszDest, uint32_t fFlags,
     
    25962679        vrc = RTPathAppend(szCurDir, sizeof(szCurDir), pszSubDir);
    25972680
    2598     if (pContext->pCmdCtx->fVerbose)
     2681    if (pContext->pCmdCtx->cVerbose > 1)
    25992682        RTPrintf("Processing host directory: %s\n", szCurDir);
    26002683
     
    26412724                        break;
    26422725
    2643                     if (pContext->pCmdCtx->fVerbose)
     2726                    if (pContext->pCmdCtx->cVerbose > 1)
    26442727                        RTPrintf("Directory: %s\n", DirEntry.szName);
    26452728
     
    26572740                        if (pszNewSub)
    26582741                        {
    2659                             vrc = ctrlCopyDirToGuest(pContext,
     2742                            vrc = gctlCopyDirToGuest(pContext,
    26602743                                                     pszSource, pszFilter,
    26612744                                                     pszDest, fFlags, pszNewSub);
     
    26852768                    }
    26862769
    2687                     if (pContext->pCmdCtx->fVerbose)
     2770                    if (pContext->pCmdCtx->cVerbose > 1)
    26882771                        RTPrintf("File: %s\n", DirEntry.szName);
    26892772
     
    26912774                    {
    26922775                        char *pszDestDir;
    2693                         vrc = ctrlCopyTranslatePath(pszSource, szCurDir,
     2776                        vrc = gctlCopyTranslatePath(pszSource, szCurDir,
    26942777                                                    pszDest, &pszDestDir);
    26952778                        if (RT_SUCCESS(vrc))
    26962779                        {
    2697                             vrc = ctrlCopyDirCreate(pContext, pszDestDir);
     2780                            vrc = gctlCopyDirCreate(pContext, pszDestDir);
    26982781                            RTStrFree(pszDestDir);
    26992782
     
    27082791                        {
    27092792                            char *pszFileDest;
    2710                             vrc = ctrlCopyTranslatePath(pszSource, pszFileSource,
     2793                            vrc = gctlCopyTranslatePath(pszSource, pszFileSource,
    27112794                                                       pszDest, &pszFileDest);
    27122795                            if (RT_SUCCESS(vrc))
    27132796                            {
    2714                                 vrc = ctrlCopyFileToDest(pContext, pszFileSource,
     2797                                vrc = gctlCopyFileToDest(pContext, pszFileSource,
    27152798                                                        pszFileDest, 0 /* Flags */);
    27162799                                RTStrFree(pszFileDest);
     
    27462829 *                                  is needed for recursion.
    27472830 */
    2748 static int ctrlCopyDirToHost(PCOPYCONTEXT pContext,
     2831static int gctlCopyDirToHost(PCOPYCONTEXT pContext,
    27492832                             const char *pszSource, const char *pszFilter,
    27502833                             const char *pszDest, uint32_t fFlags,
     
    27682851        return vrc;
    27692852
    2770     if (pContext->pCmdCtx->fVerbose)
     2853    if (pContext->pCmdCtx->cVerbose > 1)
    27712854        RTPrintf("Processing guest directory: %s\n", szCurDir);
    27722855
     
    27802863                                                        pDirectory.asOutParam());
    27812864    if (FAILED(rc))
    2782         return ctrlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
     2865        return gctlPrintError(pContext->pCmdCtx->pGuestSession, COM_IIDOF(IGuestSession));
    27832866    ComPtr<IFsObjInfo> dirEntry;
    27842867    while (true)
     
    28052888                    break;
    28062889
    2807                 if (pContext->pCmdCtx->fVerbose)
     2890                if (pContext->pCmdCtx->cVerbose > 1)
    28082891                {
    28092892                    Utf8Str strDir(strName);
     
    28242907                    if (pszNewSub)
    28252908                    {
    2826                         vrc = ctrlCopyDirToHost(pContext,
     2909                        vrc = gctlCopyDirToHost(pContext,
    28272910                                                pszSource, pszFilter,
    28282911                                                pszDest, fFlags, pszNewSub);
     
    28552938                }
    28562939
    2857                 if (pContext->pCmdCtx->fVerbose)
     2940                if (pContext->pCmdCtx->cVerbose > 1)
    28582941                    RTPrintf("File: %s\n", strFile.c_str());
    28592942
     
    28612944                {
    28622945                    char *pszDestDir;
    2863                     vrc = ctrlCopyTranslatePath(pszSource, szCurDir,
     2946                    vrc = gctlCopyTranslatePath(pszSource, szCurDir,
    28642947                                                pszDest, &pszDestDir);
    28652948                    if (RT_SUCCESS(vrc))
    28662949                    {
    2867                         vrc = ctrlCopyDirCreate(pContext, pszDestDir);
     2950                        vrc = gctlCopyDirCreate(pContext, pszDestDir);
    28682951                        RTStrFree(pszDestDir);
    28692952
     
    28782961                    {
    28792962                        char *pszFileDest;
    2880                         vrc = ctrlCopyTranslatePath(pszSource, pszFileSource,
     2963                        vrc = gctlCopyTranslatePath(pszSource, pszFileSource,
    28812964                                                   pszDest, &pszFileDest);
    28822965                        if (RT_SUCCESS(vrc))
    28832966                        {
    2884                             vrc = ctrlCopyFileToDest(pContext, pszFileSource,
     2967                            vrc = gctlCopyFileToDest(pContext, pszFileSource,
    28852968                                                    pszFileDest, 0 /* Flags */);
    28862969                            RTStrFree(pszFileDest);
     
    29203003
    29213004            default:
    2922                 vrc = ctrlPrintError(pDirectory, COM_IIDOF(IGuestDirectory));
     3005                vrc = gctlPrintError(pDirectory, COM_IIDOF(IGuestDirectory));
    29233006                break;
    29243007        }
     
    29283011    if (FAILED(rc2))
    29293012    {
    2930         int vrc2 = ctrlPrintError(pDirectory, COM_IIDOF(IGuestDirectory));
     3013        int vrc2 = gctlPrintError(pDirectory, COM_IIDOF(IGuestDirectory));
    29313014        if (RT_SUCCESS(vrc))
    29323015            vrc = vrc2;
     
    29503033 * @param   fFlags                  Copy flags, such as recursive copying.
    29513034 */
    2952 static int ctrlCopyDirToDest(PCOPYCONTEXT pContext,
     3035static int gctlCopyDirToDest(PCOPYCONTEXT pContext,
    29533036                             const char *pszSource, const char *pszFilter,
    29543037                             const char *pszDest, uint32_t fFlags)
    29553038{
    29563039    if (pContext->fHostToGuest)
    2957         return ctrlCopyDirToGuest(pContext, pszSource, pszFilter,
     3040        return gctlCopyDirToGuest(pContext, pszSource, pszFilter,
    29583041                                  pszDest, fFlags, NULL /* Sub directory, only for recursion. */);
    2959     return ctrlCopyDirToHost(pContext, pszSource, pszFilter,
     3042    return gctlCopyDirToHost(pContext, pszSource, pszFilter,
    29603043                             pszDest, fFlags, NULL /* Sub directory, only for recursion. */);
    29613044}
     
    29673050 * @param   pszSource               Source to create source root for.
    29683051 * @param   ppszSourceRoot          Pointer that receives the allocated source root. Needs
    2969  *                                  to be free'd with ctrlCopyFreeSourceRoot().
    2970  */
    2971 static int ctrlCopyCreateSourceRoot(const char *pszSource, char **ppszSourceRoot)
     3052 *                                  to be free'd with gctlCopyFreeSourceRoot().
     3053 */
     3054static int gctlCopyCreateSourceRoot(const char *pszSource, char **ppszSourceRoot)
    29723055{
    29733056    AssertPtrReturn(pszSource, VERR_INVALID_POINTER);
     
    30133096 * @param   pszSourceRoot           Source root to free.
    30143097 */
    3015 static void ctrlCopyFreeSourceRoot(char *pszSourceRoot)
     3098static void gctlCopyFreeSourceRoot(char *pszSourceRoot)
    30163099{
    30173100    RTStrFree(pszSourceRoot);
    30183101}
    30193102
    3020 static RTEXITCODE handleCtrlCopy(PGCTLCMDCTX pCtx, bool fHostToGuest)
     3103static RTEXITCODE gctlHandleCopy(PGCTLCMDCTX pCtx, bool fHostToGuest)
    30213104{
    30223105    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
     
    30383121    static const RTGETOPTDEF s_aOptions[] =
    30393122    {
     3123        GCTLCMD_COMMON_OPTION_DEFS()
    30403124        { "--dryrun",              GETOPTDEF_COPY_DRYRUN,           RTGETOPT_REQ_NOTHING },
    30413125        { "--follow",              GETOPTDEF_COPY_FOLLOW,           RTGETOPT_REQ_NOTHING },
     
    30473131    RTGETOPTUNION ValueUnion;
    30483132    RTGETOPTSTATE GetState;
    3049     RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv,
    3050                  s_aOptions, RT_ELEMENTS(s_aOptions), pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     3133    RTGetOptInit(&GetState, pCtx->pArg->argc, pCtx->pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions),
     3134                 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    30513135
    30523136    Utf8Str strSource;
     
    30653149        switch (ch)
    30663150        {
     3151            GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion);
     3152
    30673153            case GETOPTDEF_COPY_DRYRUN:
    30683154                fDryRun = true;
     
    30863172                 * --target-directory yet? Then use the current
    30873173                 * (= last) argument as destination. */
    3088                 if (  pCtx->iArgc == GetState.iNext
     3174                if (   pCtx->pArg->argc == GetState.iNext
    30893175                    && strDest.isEmpty())
    30903176                {
     
    31123198                             "No destination specified!");
    31133199
     3200    RTEXITCODE rcExit = gctlCtxPostArgParsingInit(pCtx);
     3201    if (rcExit != RTEXITCODE_SUCCESS)
     3202        return rcExit;
     3203
    31143204    /*
    31153205     * Done parsing arguments, do some more preparations.
    31163206     */
    3117     if (pCtx->fVerbose)
     3207    if (pCtx->cVerbose > 1)
    31183208    {
    31193209        if (fHostToGuest)
     
    31283218     * the routines need to know when handling the actual copying. */
    31293219    PCOPYCONTEXT pContext = NULL;
    3130     vrc = ctrlCopyContextCreate(pCtx, fDryRun, fHostToGuest,
     3220    vrc = gctlCopyContextCreate(pCtx, fDryRun, fHostToGuest,
    31313221                                  fHostToGuest
    31323222                                ? "VBoxManage Guest Control - Copy to guest"
     
    31533243    if (!RTPathFilename(pszDest))
    31543244    {
    3155         vrc = ctrlCopyDirCreate(pContext, pszDest);
     3245        vrc = gctlCopyDirCreate(pContext, pszDest);
    31563246    }
    31573247    else
     
    31633253        AssertPtr(pszDestDir);
    31643254        RTPathStripFilename(pszDestDir);
    3165         vrc = ctrlCopyDirCreate(pContext, pszDestDir);
     3255        vrc = gctlCopyDirCreate(pContext, pszDestDir);
    31663256        RTStrFree(pszDestDir);
    31673257    }
     
    31823272
    31833273            char *pszSourceRoot;
    3184             vrc = ctrlCopyCreateSourceRoot(pszSource, &pszSourceRoot);
     3274            vrc = gctlCopyCreateSourceRoot(pszSource, &pszSourceRoot);
    31853275            if (RT_FAILURE(vrc))
    31863276            {
     
    31893279            }
    31903280
    3191             if (pCtx->fVerbose)
     3281            if (pCtx->cVerbose > 1)
    31923282                RTPrintf("Source: %s\n", pszSource);
    31933283
     
    32013291            {
    32023292                if (pszFilter) /* Directory with filter (so use source root w/o the actual filter). */
    3203                     vrc = ctrlCopyDirExistsOnSource(pContext, pszSourceRoot, &fSourceExists);
     3293                    vrc = gctlCopyDirExistsOnSource(pContext, pszSourceRoot, &fSourceExists);
    32043294                else /* Regular directory without filter. */
    3205                     vrc = ctrlCopyDirExistsOnSource(pContext, pszSource, &fSourceExists);
     3295                    vrc = gctlCopyDirExistsOnSource(pContext, pszSource, &fSourceExists);
    32063296
    32073297                if (fSourceExists)
     
    32143304            else
    32153305            {
    3216                 vrc = ctrlCopyFileExistsOnSource(pContext, pszSource, &fSourceExists);
     3306                vrc = gctlCopyFileExistsOnSource(pContext, pszSource, &fSourceExists);
    32173307                if (   RT_SUCCESS(vrc)
    32183308                    && fSourceExists)
     
    32293319                    /* Single file. */
    32303320                    char *pszDestFile;
    3231                     vrc = ctrlCopyTranslatePath(pszSourceRoot, pszSource,
     3321                    vrc = gctlCopyTranslatePath(pszSourceRoot, pszSource,
    32323322                                                strDest.c_str(), &pszDestFile);
    32333323                    if (RT_SUCCESS(vrc))
    32343324                    {
    3235                         vrc = ctrlCopyFileToDest(pContext, pszSource,
     3325                        vrc = gctlCopyFileToDest(pContext, pszSource,
    32363326                                                 pszDestFile, 0 /* Flags */);
    32373327                        RTStrFree(pszDestFile);
     
    32443334                {
    32453335                    /* Directory (with filter?). */
    3246                     vrc = ctrlCopyDirToDest(pContext, pszSource, pszFilter,
     3336                    vrc = gctlCopyDirToDest(pContext, pszSource, pszFilter,
    32473337                                            strDest.c_str(), fFlags);
    32483338                }
    32493339            }
    32503340
    3251             ctrlCopyFreeSourceRoot(pszSourceRoot);
     3341            gctlCopyFreeSourceRoot(pszSourceRoot);
    32523342
    32533343            if (   RT_SUCCESS(vrc)
     
    32713361    }
    32723362
    3273     ctrlCopyContextFree(pContext);
     3363    gctlCopyContextFree(pContext);
    32743364
    32753365    return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
    32763366}
    32773367
    3278 static DECLCALLBACK(RTEXITCODE) handleCtrlCopyFrom(PGCTLCMDCTX pCtx)
    3279 {
    3280     return handleCtrlCopy(pCtx, false /* Guest to host */);
    3281 }
    3282 
    3283 static DECLCALLBACK(RTEXITCODE) handleCtrlCopyTo(PGCTLCMDCTX pCtx)
    3284 {
    3285     return handleCtrlCopy(pCtx, true /* Host to guest */);
    3286 }
    3287 
    3288 static DECLCALLBACK(RTEXITCODE) handleCtrlCreateDirectory(PGCTLCMDCTX pCtx)
     3368static DECLCALLBACK(RTEXITCODE) gctlHandleCopyFrom(PGCTLCMDCTX pCtx)
     3369{
     3370    return gctlHandleCopy(pCtx, false /* Guest to host */);
     3371}
     3372
     3373static DECLCALLBACK(RTEXITCODE) gctlHandleCopyTo(PGCTLCMDCTX pCtx)
     3374{
     3375    return gctlHandleCopy(pCtx, true /* Host to guest */);
     3376}
     3377
     3378static DECLCALLBACK(RTEXITCODE) handleCtrtMkDir(PGCTLCMDCTX pCtx)
    32893379{
    32903380    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
     
    32923382    static const RTGETOPTDEF s_aOptions[] =
    32933383    {
     3384        GCTLCMD_COMMON_OPTION_DEFS()
    32943385        { "--mode",                'm',                             RTGETOPT_REQ_UINT32  },
    32953386        { "--parents",             'P',                             RTGETOPT_REQ_NOTHING }
     
    32993390    RTGETOPTUNION ValueUnion;
    33003391    RTGETOPTSTATE GetState;
    3301     RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv,
    3302                  s_aOptions, RT_ELEMENTS(s_aOptions), pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     3392    RTGetOptInit(&GetState, pCtx->pArg->argc, pCtx->pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2,
     3393                 RTGETOPTINIT_FLAGS_OPTS_FIRST);
    33033394
    33043395    SafeArray<DirectoryCreateFlag_T> dirCreateFlags;
     
    33113402        switch (ch)
    33123403        {
     3404            GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion);
     3405
    33133406            case 'm': /* Mode */
    33143407                fDirMode = ValueUnion.u32;
     
    33243417
    33253418            default:
    3326                 return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CREATEDIR, ch, &ValueUnion);
     3419                return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_MKDIR, ch, &ValueUnion);
    33273420        }
    33283421    }
     
    33303423    size_t cDirs = mapDirs.size();
    33313424    if (!cDirs)
    3332         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CREATEDIR,
     3425        return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_MKDIR,
    33333426                             "No directory to create specified!");
     3427
     3428    RTEXITCODE rcExit = gctlCtxPostArgParsingInit(pCtx);
     3429    if (rcExit != RTEXITCODE_SUCCESS)
     3430        return rcExit;
    33343431
    33353432    /*
     
    33373434     */
    33383435    HRESULT rc = S_OK;
    3339     if (pCtx->fVerbose && cDirs)
     3436    if (pCtx->cVerbose > 1)
    33403437        RTPrintf("Creating %RU32 directories ...\n", cDirs);
    33413438
     
    33443441           && !g_fGuestCtrlCanceled)
    33453442    {
    3346         if (pCtx->fVerbose)
     3443        if (pCtx->cVerbose > 1)
    33473444            RTPrintf("Creating directory \"%s\" ...\n", it->first.c_str());
    33483445
     
    33553452}
    33563453
    3357 static DECLCALLBACK(RTEXITCODE) handleCtrlRemoveDirectory(PGCTLCMDCTX pCtx)
     3454static DECLCALLBACK(RTEXITCODE) gctlHandleRmDir(PGCTLCMDCTX pCtx)
    33583455{
    33593456    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
     
    33613458    static const RTGETOPTDEF s_aOptions[] =
    33623459    {
     3460        GCTLCMD_COMMON_OPTION_DEFS()
    33633461        { "--recursive",           'R',                             RTGETOPT_REQ_NOTHING }
    33643462    };
     
    33673465    RTGETOPTUNION ValueUnion;
    33683466    RTGETOPTSTATE GetState;
    3369     RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv,
    3370                  s_aOptions, RT_ELEMENTS(s_aOptions), pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     3467    RTGetOptInit(&GetState, pCtx->pArg->argc, pCtx->pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions),
     3468                 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    33713469
    33723470    bool fRecursive = false;
     
    33783476        switch (ch)
    33793477        {
     3478            GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion);
     3479
    33803480            case 'R':
    33813481                fRecursive = true;
     
    33873487
    33883488            default:
    3389                 return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_REMOVEDIR, ch, &ValueUnion);
     3489                return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_RMDIR, ch, &ValueUnion);
    33903490        }
    33913491    }
     
    33933493    size_t cDirs = mapDirs.size();
    33943494    if (!cDirs)
    3395         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_REMOVEDIR,
     3495        return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_RMDIR,
    33963496                             "No directory to remove specified!");
     3497
     3498    RTEXITCODE rcExit = gctlCtxPostArgParsingInit(pCtx);
     3499    if (rcExit != RTEXITCODE_SUCCESS)
     3500        return rcExit;
    33973501
    33983502    /*
     
    34003504     */
    34013505    HRESULT rc = S_OK;
    3402     if (pCtx->fVerbose && cDirs)
     3506    if (pCtx->cVerbose > 1)
    34033507        RTPrintf("Removing %RU32 directories ...\n", cDirs);
    34043508
     
    34073511           && !g_fGuestCtrlCanceled)
    34083512    {
    3409         if (pCtx->fVerbose)
     3513        if (pCtx->cVerbose > 1)
    34103514            RTPrintf("%s directory \"%s\" ...\n",
    34113515                     fRecursive ? "Recursively removing" : "Removing",
     
    34233527                                                                                ComSafeArrayAsInParam(aRemRecFlags),
    34243528                                                                                pProgress.asOutParam()));
    3425                 if (pCtx->fVerbose)
     3529                if (pCtx->cVerbose > 1)
    34263530                    rc = showProgress(pProgress);
    34273531                else
     
    34473551}
    34483552
    3449 static DECLCALLBACK(RTEXITCODE) handleCtrlRemoveFile(PGCTLCMDCTX pCtx)
     3553static DECLCALLBACK(RTEXITCODE) gctlHandleRm(PGCTLCMDCTX pCtx)
    34503554{
    34513555    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
     3556
     3557    static const RTGETOPTDEF s_aOptions[] =
     3558    {
     3559        GCTLCMD_COMMON_OPTION_DEFS()
     3560    };
    34523561
    34533562    int ch;
    34543563    RTGETOPTUNION ValueUnion;
    34553564    RTGETOPTSTATE GetState;
    3456     RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv,
    3457                  NULL /* s_aOptions */, 0 /* RT_ELEMENTS(s_aOptions) */,
    3458                  pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     3565    RTGetOptInit(&GetState, pCtx->pArg->argc, pCtx->pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions),
     3566                 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    34593567
    34603568    DESTDIRMAP mapDirs;
     
    34653573        switch (ch)
    34663574        {
     3575            GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion);
     3576
    34673577            case VINF_GETOPT_NOT_OPTION:
    34683578                mapDirs[ValueUnion.psz]; /* Add destination directory to map. */
     
    34703580
    34713581            default:
    3472                 return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_REMOVEFILE, ch, &ValueUnion);
     3582                return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_RM, ch, &ValueUnion);
    34733583        }
    34743584    }
     
    34763586    size_t cFiles = mapDirs.size();
    34773587    if (!cFiles)
    3478         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_REMOVEFILE,
    3479                              "No file to remove specified!");
     3588        return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_RM, "No file to remove specified!");
     3589
     3590    RTEXITCODE rcExit = gctlCtxPostArgParsingInit(pCtx);
     3591    if (rcExit != RTEXITCODE_SUCCESS)
     3592        return rcExit;
    34803593
    34813594    /*
     
    34833596     */
    34843597    HRESULT rc = S_OK;
    3485     if (pCtx->fVerbose && cFiles)
     3598    if (pCtx->cVerbose > 1)
    34863599        RTPrintf("Removing %RU32 file(s) ...\n", cFiles);
    34873600
     
    34903603           && !g_fGuestCtrlCanceled)
    34913604    {
    3492         if (pCtx->fVerbose)
     3605        if (pCtx->cVerbose > 1)
    34933606            RTPrintf("Removing file \"%s\" ...\n", it->first.c_str());
    34943607
     
    35013614}
    35023615
    3503 static DECLCALLBACK(RTEXITCODE) handleCtrlRename(PGCTLCMDCTX pCtx)
     3616static DECLCALLBACK(RTEXITCODE) gctlHandleMv(PGCTLCMDCTX pCtx)
    35043617{
    35053618    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
    35063619
    3507     static const RTGETOPTDEF s_aOptions[] = { { 0 } };
     3620    static const RTGETOPTDEF s_aOptions[] =
     3621    {
     3622        GCTLCMD_COMMON_OPTION_DEFS()
     3623    };
    35083624
    35093625    int ch;
    35103626    RTGETOPTUNION ValueUnion;
    35113627    RTGETOPTSTATE GetState;
    3512     RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv,
    3513                  NULL /*s_aOptions*/, 0 /*RT_ELEMENTS(s_aOptions)*/, pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     3628    RTGetOptInit(&GetState, pCtx->pArg->argc, pCtx->pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions),
     3629                 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    35143630
    35153631    int vrc = VINF_SUCCESS;
     
    35313647            switch (ch)
    35323648            {
     3649                GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion);
     3650
    35333651                /** @todo Implement a --dryrun command. */
    35343652                /** @todo Implement rename flags. */
     
    35403658
    35413659                default:
    3542                     return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_RENAME, ch, &ValueUnion);
     3660                    return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_MV, ch, &ValueUnion);
    35433661            }
    35443662        }
     
    35543672    size_t cSources = vecSources.size();
    35553673    if (!cSources)
    3556         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_RENAME,
     3674        return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_MV,
    35573675                             "No source(s) to move specified!");
    35583676    if (cSources < 2)
    3559         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_RENAME,
     3677        return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_MV,
    35603678                             "No destination specified!");
     3679
     3680    RTEXITCODE rcExit = gctlCtxPostArgParsingInit(pCtx);
     3681    if (rcExit != RTEXITCODE_SUCCESS)
     3682        return rcExit;
    35613683
    35623684    /* Delete last element, which now is the destination. */
     
    35773699     * Rename (move) the entries.
    35783700     */
    3579     if (pCtx->fVerbose && cSources)
    3580         RTPrintf("Renaming %RU32 %s ...\n", cSources,
    3581                    cSources > 1
    3582                  ? "entries" : "entry");
     3701    if (pCtx->cVerbose > 1)
     3702        RTPrintf("Renaming %RU32 %s ...\n", cSources, cSources > 1 ? "entries" : "entry");
    35833703
    35843704    std::vector< Utf8Str >::iterator it = vecSources.begin();
     
    36003720        if (FAILED(rc))
    36013721        {
    3602             if (pCtx->fVerbose)
     3722            if (pCtx->cVerbose > 1)
    36033723                RTPrintf("Warning: Cannot stat for element \"%s\": No such element\n",
    36043724                         strCurSource.c_str());
     
    36073727        }
    36083728
    3609         if (pCtx->fVerbose)
     3729        if (pCtx->cVerbose > 1)
    36103730            RTPrintf("Renaming %s \"%s\" to \"%s\" ...\n",
    36113731                     fSourceIsDirectory ? "directory" : "file",
     
    36353755
    36363756    if (   (it != vecSources.end())
    3637         && pCtx->fVerbose)
     3757        && pCtx->cVerbose > 1)
    36383758    {
    36393759        RTPrintf("Warning: Not all sources were renamed\n");
     
    36433763}
    36443764
    3645 static DECLCALLBACK(RTEXITCODE) handleCtrlCreateTemp(PGCTLCMDCTX pCtx)
     3765static DECLCALLBACK(RTEXITCODE) gctlHandleMkTemp(PGCTLCMDCTX pCtx)
    36463766{
    36473767    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
     
    36493769    static const RTGETOPTDEF s_aOptions[] =
    36503770    {
     3771        GCTLCMD_COMMON_OPTION_DEFS()
    36513772        { "--mode",                'm',                             RTGETOPT_REQ_UINT32  },
    36523773        { "--directory",           'D',                             RTGETOPT_REQ_NOTHING },
     
    36583779    RTGETOPTUNION ValueUnion;
    36593780    RTGETOPTSTATE GetState;
    3660     RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv,
    3661                  s_aOptions, RT_ELEMENTS(s_aOptions), pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     3781    RTGetOptInit(&GetState, pCtx->pArg->argc, pCtx->pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions),
     3782                 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    36623783
    36633784    Utf8Str strTemplate;
     
    36693790    DESTDIRMAP mapDirs;
    36703791
    3671     while ((ch = RTGetOpt(&GetState, &ValueUnion)))
     3792    while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0)
    36723793    {
    36733794        /* For options that require an argument, ValueUnion has received the value. */
    36743795        switch (ch)
    36753796        {
     3797            GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion);
     3798
    36763799            case 'm': /* Mode */
    36773800                fMode = ValueUnion.u32;
     
    36953818                    strTemplate = ValueUnion.psz;
    36963819                else
    3697                     return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CREATETEMP,
     3820                    return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_MKTEMP,
    36983821                                         "More than one template specified!\n");
    36993822                break;
     
    37013824
    37023825            default:
    3703                 return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CREATETEMP, ch, &ValueUnion);
     3826                return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_MKTEMP, ch, &ValueUnion);
    37043827        }
    37053828    }
    37063829
    37073830    if (strTemplate.isEmpty())
    3708         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CREATETEMP,
     3831        return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_MKTEMP,
    37093832                             "No template specified!");
    37103833
    37113834    if (!fDirectory)
    3712         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CREATETEMP,
     3835        return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_MKTEMP,
    37133836                             "Creating temporary files is currently not supported!");
     3837
     3838    RTEXITCODE rcExit = gctlCtxPostArgParsingInit(pCtx);
     3839    if (rcExit != RTEXITCODE_SUCCESS)
     3840        return rcExit;
    37143841
    37153842    /*
    37163843     * Create the directories.
    37173844     */
    3718     if (pCtx->fVerbose)
     3845    if (pCtx->cVerbose > 1)
    37193846    {
    37203847        if (fDirectory && !strTempDir.isEmpty())
     
    37433870            RTPrintf("Directory name: %ls\n", directory.raw());
    37443871    }
    3745     // else - temporary file not yet implemented
     3872    else
     3873    {
     3874        // else - temporary file not yet implemented
     3875        /** @todo implement temporary file creation (we fend it off above, no
     3876         *        worries). */
     3877        rc = E_FAIL;
     3878    }
    37463879
    37473880    return FAILED(rc) ? RTEXITCODE_FAILURE : RTEXITCODE_SUCCESS;
    37483881}
    37493882
    3750 static DECLCALLBACK(RTEXITCODE) handleCtrlStat(PGCTLCMDCTX pCtx)
     3883static DECLCALLBACK(RTEXITCODE) gctlHandleStat(PGCTLCMDCTX pCtx)
    37513884{
    37523885    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
     
    37543887    static const RTGETOPTDEF s_aOptions[] =
    37553888    {
     3889        GCTLCMD_COMMON_OPTION_DEFS()
    37563890        { "--dereference",         'L',                             RTGETOPT_REQ_NOTHING },
    37573891        { "--file-system",         'f',                             RTGETOPT_REQ_NOTHING },
     
    37633897    RTGETOPTUNION ValueUnion;
    37643898    RTGETOPTSTATE GetState;
    3765     RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv,
    3766                  s_aOptions, RT_ELEMENTS(s_aOptions), pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     3899    RTGetOptInit(&GetState, pCtx->pArg->argc, pCtx->pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions),
     3900                 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    37673901
    37683902    DESTDIRMAP mapObjs;
     
    37733907        switch (ch)
    37743908        {
     3909            GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion);
     3910
    37753911            case 'L': /* Dereference */
    37763912            case 'f': /* File-system */
     
    37943930                             "No element(s) to check specified!");
    37953931
     3932    RTEXITCODE rcExit = gctlCtxPostArgParsingInit(pCtx);
     3933    if (rcExit != RTEXITCODE_SUCCESS)
     3934        return rcExit;
     3935
    37963936    HRESULT rc;
    37973937
     
    37993939     * Doing the checks.
    38003940     */
    3801     RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    38023941    DESTDIRMAPITER it = mapObjs.begin();
    38033942    while (it != mapObjs.end())
    38043943    {
    3805         if (pCtx->fVerbose)
     3944        if (pCtx->cVerbose > 1)
    38063945            RTPrintf("Checking for element \"%s\" ...\n", it->first.c_str());
    38073946
     
    38153954            /* If there's at least one element which does not exist on the guest,
    38163955             * drop out with exitcode 1. */
    3817             if (pCtx->fVerbose)
     3956            if (pCtx->cVerbose > 1)
    38183957                RTPrintf("Cannot stat for element \"%s\": No such element\n",
    38193958                         it->first.c_str());
     
    38523991}
    38533992
    3854 static DECLCALLBACK(RTEXITCODE) handleCtrlUpdateAdditions(PGCTLCMDCTX pCtx)
     3993static DECLCALLBACK(RTEXITCODE) gctlHandleUpdateAdditions(PGCTLCMDCTX pCtx)
    38553994{
    38563995    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
     
    38664005    static const RTGETOPTDEF s_aOptions[] =
    38674006    {
     4007        GCTLCMD_COMMON_OPTION_DEFS()
    38684008        { "--source",              's',         RTGETOPT_REQ_STRING  },
    38694009        { "--wait-start",          'w',         RTGETOPT_REQ_NOTHING }
     
    38734013    RTGETOPTUNION ValueUnion;
    38744014    RTGETOPTSTATE GetState;
    3875     RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv, s_aOptions, RT_ELEMENTS(s_aOptions), pCtx->iFirstArgc, 0);
     4015    RTGetOptInit(&GetState, pCtx->pArg->argc, pCtx->pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions),
     4016                 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    38764017
    38774018    int vrc = VINF_SUCCESS;
     
    38814022        switch (ch)
    38824023        {
     4024            GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion);
     4025
    38834026            case 's':
    38844027                strSource = ValueUnion.psz;
     
    38974040
    38984041            default:
    3899                 return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_UPDATEADDS, ch, &ValueUnion);
    3900         }
    3901     }
    3902 
    3903     if (pCtx->fVerbose)
     4042                return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_UPDATEGA, ch, &ValueUnion);
     4043        }
     4044    }
     4045
     4046    if (pCtx->cVerbose > 1)
    39044047        RTPrintf("Updating Guest Additions ...\n");
    39054048
     
    39084051    {
    39094052        ComPtr<ISystemProperties> pProperties;
    3910         CHECK_ERROR_BREAK(pCtx->handlerArg.virtualBox, COMGETTER(SystemProperties)(pProperties.asOutParam()));
     4053        CHECK_ERROR_BREAK(pCtx->pArg->virtualBox, COMGETTER(SystemProperties)(pProperties.asOutParam()));
    39114054        Bstr strISO;
    39124055        CHECK_ERROR_BREAK(pProperties, COMGETTER(DefaultAdditionsISO)(strISO.asOutParam()));
     
    39294072    if (RT_SUCCESS(vrc))
    39304073    {
    3931         if (pCtx->fVerbose)
     4074        if (pCtx->cVerbose > 1)
    39324075            RTPrintf("Using source: %s\n", strSource.c_str());
     4076
     4077
     4078        RTEXITCODE rcExit = gctlCtxPostArgParsingInit(pCtx);
     4079        if (rcExit != RTEXITCODE_SUCCESS)
     4080            return rcExit;
     4081
    39334082
    39344083        com::SafeArray<AdditionsUpdateFlag_T> aUpdateFlags;
     
    39364085        {
    39374086            aUpdateFlags.push_back(AdditionsUpdateFlag_WaitForUpdateStartOnly);
    3938             if (pCtx->fVerbose)
     4087            if (pCtx->cVerbose > 1)
    39394088                RTPrintf("Preparing and waiting for Guest Additions installer to start ...\n");
    39404089        }
     
    39474096                                                pProgress.asOutParam()));
    39484097        if (FAILED(rc))
    3949             vrc = ctrlPrintError(pCtx->pGuest, COM_IIDOF(IGuest));
     4098            vrc = gctlPrintError(pCtx->pGuest, COM_IIDOF(IGuest));
    39504099        else
    39514100        {
    3952             if (pCtx->fVerbose)
     4101            if (pCtx->cVerbose > 1)
    39534102                rc = showProgress(pProgress);
    39544103            else
     
    39574106            if (SUCCEEDED(rc))
    39584107                CHECK_PROGRESS_ERROR(pProgress, ("Guest additions update failed"));
    3959             vrc = ctrlPrintProgressError(pProgress);
     4108            vrc = gctlPrintProgressError(pProgress);
    39604109            if (   RT_SUCCESS(vrc)
    3961                 && pCtx->fVerbose)
     4110                && pCtx->cVerbose > 1)
    39624111            {
    39634112                RTPrintf("Guest Additions update successful\n");
     
    39694118}
    39704119
    3971 static DECLCALLBACK(RTEXITCODE) handleCtrlList(PGCTLCMDCTX pCtx)
     4120static DECLCALLBACK(RTEXITCODE) gctlHandleList(PGCTLCMDCTX pCtx)
    39724121{
    39734122    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
    39744123
    3975     if (pCtx->iArgc < 1)
    3976         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_LIST,
    3977                              "Must specify a listing category");
    3978 
    3979     RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    3980 
    3981     /** Use RTGetOpt here when handling command line args gets more complex. */
    3982 
    3983     bool fListAll = false;
    3984     bool fListSessions = false;
     4124    static const RTGETOPTDEF s_aOptions[] =
     4125    {
     4126        GCTLCMD_COMMON_OPTION_DEFS()
     4127    };
     4128
     4129    int ch;
     4130    RTGETOPTUNION ValueUnion;
     4131    RTGETOPTSTATE GetState;
     4132    RTGetOptInit(&GetState, pCtx->pArg->argc, pCtx->pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions),
     4133                 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     4134
     4135    bool fSeenListArg   = false;
     4136    bool fListAll       = false;
     4137    bool fListSessions  = false;
    39854138    bool fListProcesses = false;
    3986     bool fListFiles = false;
    3987     if (   !RTStrICmp(pCtx->ppaArgv[0], "sessions")
    3988         || !RTStrICmp(pCtx->ppaArgv[0], "sess"))
    3989         fListSessions = true;
    3990     else if (   !RTStrICmp(pCtx->ppaArgv[0], "processes")
    3991              || !RTStrICmp(pCtx->ppaArgv[0], "procs"))
    3992         fListSessions = fListProcesses = true; /* Showing processes implies showing sessions. */
    3993     else if (   !RTStrICmp(pCtx->ppaArgv[0], "files"))
    3994         fListSessions = fListFiles = true;     /* Showing files implies showing sessions. */
    3995     else if (!RTStrICmp(pCtx->ppaArgv[0], "all"))
    3996         fListAll = true;
    3997 
    3998     /** @todo Handle "--verbose" using RTGetOpt. */
     4139    bool fListFiles     = false;
     4140
     4141    int vrc = VINF_SUCCESS;
     4142    while (   (ch = RTGetOpt(&GetState, &ValueUnion))
     4143           && RT_SUCCESS(vrc))
     4144    {
     4145        switch (ch)
     4146        {
     4147            GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion);
     4148
     4149            case VINF_GETOPT_NOT_OPTION:
     4150                if (   !RTStrICmp(ValueUnion.psz, "sessions")
     4151                    || !RTStrICmp(ValueUnion.psz, "sess"))
     4152                    fListSessions = true;
     4153                else if (   !RTStrICmp(ValueUnion.psz, "processes")
     4154                         || !RTStrICmp(ValueUnion.psz, "procs"))
     4155                    fListSessions = fListProcesses = true; /* Showing processes implies showing sessions. */
     4156                else if (!RTStrICmp(ValueUnion.psz, "files"))
     4157                    fListSessions = fListFiles = true;     /* Showing files implies showing sessions. */
     4158                else if (!RTStrICmp(ValueUnion.psz, "all"))
     4159                    fListAll = true;
     4160                else
     4161                    return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_LIST,
     4162                                         "Unknown list: '%s'", ValueUnion.psz);
     4163                fSeenListArg = true;
     4164                break;
     4165
     4166            default:
     4167                return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_UPDATEGA, ch, &ValueUnion);
     4168        }
     4169    }
     4170
     4171    if (fSeenListArg)
     4172        return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_LIST, "Missing list name");
     4173    Assert(fListAll || fListSessions);
     4174
     4175    RTEXITCODE rcExit = gctlCtxPostArgParsingInit(pCtx);
     4176    if (rcExit != RTEXITCODE_SUCCESS)
     4177        return rcExit;
     4178
     4179
    39994180    /** @todo Do we need a machine-readable output here as well? */
    40004181
    4001     if (   fListAll
    4002         || fListSessions)
    4003     {
    4004         HRESULT rc;
    4005         do
    4006         {
    4007             size_t cTotalProcs = 0;
    4008             size_t cTotalFiles = 0;
    4009 
    4010             SafeIfaceArray <IGuestSession> collSessions;
    4011             CHECK_ERROR_BREAK(pCtx->pGuest, COMGETTER(Sessions)(ComSafeArrayAsOutParam(collSessions)));
    4012             size_t cSessions = collSessions.size();
    4013 
    4014             if (cSessions)
    4015             {
    4016                 RTPrintf("Active guest sessions:\n");
    4017 
    4018                 /** @todo Make this output a bit prettier. No time now. */
    4019 
    4020                 for (size_t i = 0; i < cSessions; i++)
     4182    HRESULT rc;
     4183    size_t cTotalProcs = 0;
     4184    size_t cTotalFiles = 0;
     4185
     4186    SafeIfaceArray <IGuestSession> collSessions;
     4187    CHECK_ERROR(pCtx->pGuest, COMGETTER(Sessions)(ComSafeArrayAsOutParam(collSessions)));
     4188    if (SUCCEEDED(rc))
     4189    {
     4190        size_t const cSessions = collSessions.size();
     4191        if (cSessions)
     4192        {
     4193            RTPrintf("Active guest sessions:\n");
     4194
     4195            /** @todo Make this output a bit prettier. No time now. */
     4196
     4197            for (size_t i = 0; i < cSessions; i++)
     4198            {
     4199                ComPtr<IGuestSession> pCurSession = collSessions[i];
     4200                if (!pCurSession.isNull())
    40214201                {
    4022                     ComPtr<IGuestSession> pCurSession = collSessions[i];
    4023                     if (!pCurSession.isNull())
     4202                    do
    40244203                    {
    40254204                        ULONG uID;
     
    40324211                        CHECK_ERROR_BREAK(pCurSession, COMGETTER(Status)(&sessionStatus));
    40334212                        RTPrintf("\n\tSession #%-3zu ID=%-3RU32 User=%-16ls Status=[%s] Name=%ls",
    4034                                  i, uID, strUser.raw(), ctrlSessionStatusToText(sessionStatus), strName.raw());
    4035 
    4036                         if (   fListAll
    4037                             || fListProcesses)
     4213                                 i, uID, strUser.raw(), gctlGuestSessionStatusToText(sessionStatus), strName.raw());
     4214                    } while (0);
     4215
     4216                    if (   fListAll
     4217                        || fListProcesses)
     4218                    {
     4219                        SafeIfaceArray <IGuestProcess> collProcesses;
     4220                        CHECK_ERROR_BREAK(pCurSession, COMGETTER(Processes)(ComSafeArrayAsOutParam(collProcesses)));
     4221                        for (size_t a = 0; a < collProcesses.size(); a++)
    40384222                        {
    4039                             SafeIfaceArray <IGuestProcess> collProcesses;
    4040                             CHECK_ERROR_BREAK(pCurSession, COMGETTER(Processes)(ComSafeArrayAsOutParam(collProcesses)));
    4041                             for (size_t a = 0; a < collProcesses.size(); a++)
     4223                            ComPtr<IGuestProcess> pCurProcess = collProcesses[a];
     4224                            if (!pCurProcess.isNull())
    40424225                            {
    4043                                 ComPtr<IGuestProcess> pCurProcess = collProcesses[a];
    4044                                 if (!pCurProcess.isNull())
     4226                                do
    40454227                                {
    40464228                                    ULONG uPID;
     
    40524234
    40534235                                    RTPrintf("\n\t\tProcess #%-03zu PID=%-6RU32 Status=[%s] Command=%ls",
    4054                                              a, uPID, ctrlProcessStatusToText(procStatus), strExecPath.raw());
    4055                                 }
     4236                                             a, uPID, gctlProcessStatusToText(procStatus), strExecPath.raw());
     4237                                } while (0);
    40564238                            }
    4057 
    4058                             cTotalProcs += collProcesses.size();
    40594239                        }
    40604240
    4061                         if (   fListAll
    4062                             || fListFiles)
     4241                        cTotalProcs += collProcesses.size();
     4242                    }
     4243
     4244                    if (   fListAll
     4245                        || fListFiles)
     4246                    {
     4247                        SafeIfaceArray <IGuestFile> collFiles;
     4248                        CHECK_ERROR_BREAK(pCurSession, COMGETTER(Files)(ComSafeArrayAsOutParam(collFiles)));
     4249                        for (size_t a = 0; a < collFiles.size(); a++)
    40634250                        {
    4064                             SafeIfaceArray <IGuestFile> collFiles;
    4065                             CHECK_ERROR_BREAK(pCurSession, COMGETTER(Files)(ComSafeArrayAsOutParam(collFiles)));
    4066                             for (size_t a = 0; a < collFiles.size(); a++)
     4251                            ComPtr<IGuestFile> pCurFile = collFiles[a];
     4252                            if (!pCurFile.isNull())
    40674253                            {
    4068                                 ComPtr<IGuestFile> pCurFile = collFiles[a];
    4069                                 if (!pCurFile.isNull())
     4254                                do
    40704255                                {
    4071                                     CHECK_ERROR_BREAK(pCurFile, COMGETTER(Id)(&uID));
     4256                                    ULONG idFile;
     4257                                    CHECK_ERROR_BREAK(pCurFile, COMGETTER(Id)(&idFile));
     4258                                    Bstr strName;
    40724259                                    CHECK_ERROR_BREAK(pCurFile, COMGETTER(FileName)(strName.asOutParam()));
    40734260                                    FileStatus_T fileStatus;
     
    40754262
    40764263                                    RTPrintf("\n\t\tFile #%-03zu ID=%-6RU32 Status=[%s] Name=%ls",
    4077                                              a, uID, ctrlFileStatusToText(fileStatus), strName.raw());
    4078                                 }
     4264                                             a, idFile, gctlFileStatusToText(fileStatus), strName.raw());
     4265                                } while (0);
    40794266                            }
    4080 
    4081                             cTotalFiles += collFiles.size();
    40824267                        }
     4268
     4269                        cTotalFiles += collFiles.size();
    40834270                    }
    40844271                }
    4085 
    4086                 RTPrintf("\n\nTotal guest sessions: %zu\n", collSessions.size());
    4087                 if (fListAll || fListProcesses)
    4088                     RTPrintf("Total guest processes: %zu\n", cTotalProcs);
    4089                 if (fListAll || fListFiles)
    4090                     RTPrintf("Total guest files: %zu\n", cTotalFiles);
    4091             }
    4092             else
    4093                 RTPrintf("No active guest sessions found\n");
    4094 
    4095         } while (0);
    4096 
    4097         if (FAILED(rc))
    4098             rcExit = RTEXITCODE_FAILURE;
    4099     }
    4100     else
    4101         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_LIST,
    4102                              "Invalid listing category '%s", pCtx->ppaArgv[0]);
     4272            }
     4273
     4274            RTPrintf("\n\nTotal guest sessions: %zu\n", collSessions.size());
     4275            if (fListAll || fListProcesses)
     4276                RTPrintf("Total guest processes: %zu\n", cTotalProcs);
     4277            if (fListAll || fListFiles)
     4278                RTPrintf("Total guest files: %zu\n", cTotalFiles);
     4279        }
     4280        else
     4281            RTPrintf("No active guest sessions found\n");
     4282    }
     4283
     4284    if (FAILED(rc))
     4285        rcExit = RTEXITCODE_FAILURE;
    41034286
    41044287    return rcExit;
    41054288}
    41064289
    4107 static DECLCALLBACK(RTEXITCODE) handleCtrlProcessClose(PGCTLCMDCTX pCtx)
     4290static DECLCALLBACK(RTEXITCODE) gctlHandleCloseProcess(PGCTLCMDCTX pCtx)
    41084291{
    41094292    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
    41104293
    4111     if (pCtx->iArgc < 1)
    4112         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_PROCESS,
    4113                              "Must specify at least a PID to close");
    4114 
    41154294    static const RTGETOPTDEF s_aOptions[] =
    41164295    {
     4296        GCTLCMD_COMMON_OPTION_DEFS()
    41174297        { "--session-id",          'i',                             RTGETOPT_REQ_UINT32  },
    41184298        { "--session-name",        'n',                             RTGETOPT_REQ_STRING  }
     
    41224302    RTGETOPTUNION ValueUnion;
    41234303    RTGETOPTSTATE GetState;
    4124     RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv,
    4125                  s_aOptions, RT_ELEMENTS(s_aOptions), pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     4304    RTGetOptInit(&GetState, pCtx->pArg->argc, pCtx->pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions),
     4305                 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    41264306
    41274307    std::vector < uint32_t > vecPID;
     
    41294309    Utf8Str strSessionName;
    41304310
    4131     int vrc = VINF_SUCCESS;
    4132 
    4133     while (   (ch = RTGetOpt(&GetState, &ValueUnion))
    4134            && RT_SUCCESS(vrc))
     4311    while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0)
    41354312    {
    41364313        /* For options that require an argument, ValueUnion has received the value. */
    41374314        switch (ch)
    41384315        {
     4316            GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion);
     4317
    41394318            case 'n': /* Session name (or pattern) */
    41404319                strSessionName = ValueUnion.psz;
     
    41464325
    41474326            case VINF_GETOPT_NOT_OPTION:
    4148                 if (pCtx->iArgc == GetState.iNext)
     4327            {
     4328                /* Treat every else specified as a PID to kill. */
     4329                uint32_t uPid;
     4330                int rc = RTStrToUInt32Ex(ValueUnion.psz, NULL, 0, &uPid);
     4331                if (   RT_SUCCESS(rc)
     4332                    && rc != VWRN_TRAILING_CHARS
     4333                    && rc != VWRN_NUMBER_TOO_BIG
     4334                    && rc != VWRN_NEGATIVE_UNSIGNED)
    41494335                {
    4150                     /* Treat every else specified as a PID to kill. */
    4151                     try
     4336                    if (uPid != 0)
    41524337                    {
    4153                         uint32_t uPID = RTStrToUInt32(ValueUnion.psz);
    4154                         if (uPID) /** @todo Is this what we want? If specifying PID 0
    4155                                             this is not going to work on most systems anyway. */
    4156                             vecPID.push_back(uPID);
    4157                         else
    4158                             vrc = VERR_INVALID_PARAMETER;
     4338                        try
     4339                        {
     4340                            vecPID.push_back(uPid);
     4341                        }
     4342                        catch (std::bad_alloc &)
     4343                        {
     4344                            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Out of memory");
     4345                        }
    41594346                    }
    4160                     catch(std::bad_alloc &)
    4161                     {
    4162                         vrc = VERR_NO_MEMORY;
    4163                     }
     4347                    else
     4348                        return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CLOSEPROCESS, "Invalid PID value: 0");
    41644349                }
     4350                else
     4351                    return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CLOSEPROCESS,
     4352                                         "Error parsing PID value: %Rrc", rc);
    41654353                break;
     4354            }
    41664355
    41674356            default:
    4168                 return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_PROCESS, ch, &ValueUnion);
     4357                return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CLOSEPROCESS, ch, &ValueUnion);
    41694358        }
    41704359    }
    41714360
    41724361    if (vecPID.empty())
    4173         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_PROCESS,
     4362        return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CLOSEPROCESS,
    41744363                             "At least one PID must be specified to kill!");
    41754364
    41764365    if (   strSessionName.isEmpty()
    41774366        && ulSessionID == UINT32_MAX)
    4178         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_PROCESS,
    4179                              "No session ID specified!");
    4180 
    4181     if (   !strSessionName.isEmpty()
     4367        return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CLOSEPROCESS, "No session ID specified!");
     4368
     4369    if (   strSessionName.isNotEmpty()
    41824370        && ulSessionID != UINT32_MAX)
    4183         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_PROCESS,
     4371        return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CLOSEPROCESS,
    41844372                             "Either session ID or name (pattern) must be specified");
    41854373
    4186     if (RT_FAILURE(vrc))
    4187         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_PROCESS,
    4188                              "Invalid parameters specified");
     4374    RTEXITCODE rcExit = gctlCtxPostArgParsingInit(pCtx);
     4375    if (rcExit != RTEXITCODE_SUCCESS)
     4376        return rcExit;
    41894377
    41904378    HRESULT rc = S_OK;
     
    42494437                    if (fProcFound)
    42504438                    {
    4251                         if (pCtx->fVerbose)
     4439                        if (pCtx->cVerbose > 1)
    42524440                            RTPrintf("Terminating process (PID %RU32) (session ID %RU32) ...\n",
    42534441                                     uPID, uID);
     
    42844472}
    42854473
    4286 static DECLCALLBACK(RTEXITCODE) handleCtrlProcess(PGCTLCMDCTX pCtx)
     4474
     4475static DECLCALLBACK(RTEXITCODE) gctlHandleCloseSession(PGCTLCMDCTX pCtx)
    42874476{
    42884477    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
    42894478
    4290     if (pCtx->iArgc < 1)
    4291         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_PROCESS,
    4292                              "Must specify an action");
    4293 
    4294     /** Use RTGetOpt here when handling command line args gets more complex. */
    4295 
    4296     if (   !RTStrICmp(pCtx->ppaArgv[0], "close")
    4297         || !RTStrICmp(pCtx->ppaArgv[0], "kill")
    4298         || !RTStrICmp(pCtx->ppaArgv[0], "terminate"))
    4299     {
    4300         pCtx->iFirstArgc++; /* Skip process action. */
    4301         return handleCtrlProcessClose(pCtx);
    4302     }
    4303 
    4304     return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_PROCESS,
    4305                          "Invalid process action '%s'", pCtx->ppaArgv[0]);
    4306 }
    4307 
    4308 static DECLCALLBACK(RTEXITCODE) handleCtrlSessionClose(PGCTLCMDCTX pCtx)
    4309 {
    4310     AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
    4311 
    4312     if (pCtx->iArgc < 1)
    4313         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_SESSION,
    4314                              "Must specify at least a session to close");
    4315 
     4479    enum GETOPTDEF_SESSIONCLOSE
     4480    {
     4481        GETOPTDEF_SESSIONCLOSE_ALL = 2000
     4482    };
    43164483    static const RTGETOPTDEF s_aOptions[] =
    43174484    {
     4485        GCTLCMD_COMMON_OPTION_DEFS()
    43184486        { "--all",                 GETOPTDEF_SESSIONCLOSE_ALL,      RTGETOPT_REQ_NOTHING  },
    43194487        { "--session-id",          'i',                             RTGETOPT_REQ_UINT32  },
     
    43244492    RTGETOPTUNION ValueUnion;
    43254493    RTGETOPTSTATE GetState;
    4326     RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv,
    4327                  s_aOptions, RT_ELEMENTS(s_aOptions), pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     4494    RTGetOptInit(&GetState, pCtx->pArg->argc, pCtx->pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions),
     4495                 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    43284496
    43294497    ULONG ulSessionID = UINT32_MAX;
     
    43354503        switch (ch)
    43364504        {
     4505            GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion);
     4506
    43374507            case 'n': /* Session name pattern */
    43384508                strSessionName = ValueUnion.psz;
     
    43484518
    43494519            case VINF_GETOPT_NOT_OPTION:
    4350                 /** @todo Supply a CSV list of IDs or patterns to close? */
    4351                 break;
    4352 
     4520                /** @todo Supply a CSV list of IDs or patterns to close?
     4521                 *  break; */
    43534522            default:
    4354                 return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_SESSION, ch, &ValueUnion);
     4523                return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CLOSESESSION, ch, &ValueUnion);
    43554524        }
    43564525    }
     
    43584527    if (   strSessionName.isEmpty()
    43594528        && ulSessionID == UINT32_MAX)
    4360         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_SESSION,
     4529        return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CLOSESESSION,
    43614530                             "No session ID specified!");
    43624531
    43634532    if (   !strSessionName.isEmpty()
    43644533        && ulSessionID != UINT32_MAX)
    4365         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_SESSION,
     4534        return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_CLOSESESSION,
    43664535                             "Either session ID or name (pattern) must be specified");
     4536
     4537    RTEXITCODE rcExit = gctlCtxPostArgParsingInit(pCtx);
     4538    if (rcExit != RTEXITCODE_SUCCESS)
     4539        return rcExit;
    43674540
    43684541    HRESULT rc = S_OK;
     
    44034576
    44044577                Assert(!pSession.isNull());
    4405                 if (pCtx->fVerbose)
     4578                if (pCtx->cVerbose > 1)
    44064579                    RTPrintf("Closing guest session ID=#%RU32 \"%s\" ...\n",
    44074580                             uID, strNameUtf8.c_str());
    44084581                CHECK_ERROR_BREAK(pSession, Close());
    4409                 if (pCtx->fVerbose)
     4582                if (pCtx->cVerbose > 1)
    44104583                    RTPrintf("Guest session successfully closed\n");
    44114584
     
    44254598}
    44264599
    4427 static DECLCALLBACK(RTEXITCODE) handleCtrlSession(PGCTLCMDCTX pCtx)
    4428 {
    4429     AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
    4430 
    4431     if (pCtx->iArgc < 1)
    4432         return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_SESSION,
    4433                              "Must specify an action");
    4434 
    4435     /** Use RTGetOpt here when handling command line args gets more complex. */
    4436 
    4437     if (   !RTStrICmp(pCtx->ppaArgv[0], "close")
    4438         || !RTStrICmp(pCtx->ppaArgv[0], "kill")
    4439         || !RTStrICmp(pCtx->ppaArgv[0], "terminate"))
    4440     {
    4441         pCtx->iFirstArgc++; /* Skip session action. */
    4442         return handleCtrlSessionClose(pCtx);
    4443     }
    4444 
    4445     return errorSyntaxEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_SESSION,
    4446                          "Invalid session action '%s'", pCtx->ppaArgv[0]);
    4447 }
    4448 
    4449 static DECLCALLBACK(RTEXITCODE) handleCtrlWatch(PGCTLCMDCTX pCtx)
     4600
     4601static DECLCALLBACK(RTEXITCODE) gctlHandleWatch(PGCTLCMDCTX pCtx)
    44504602{
    44514603    AssertPtrReturn(pCtx, RTEXITCODE_FAILURE);
     
    44544606     * Parse arguments.
    44554607     */
    4456     static const RTGETOPTDEF s_aOptions[] = { { 0 } };
     4608    static const RTGETOPTDEF s_aOptions[] =
     4609    {
     4610        GCTLCMD_COMMON_OPTION_DEFS()
     4611    };
    44574612
    44584613    int ch;
    44594614    RTGETOPTUNION ValueUnion;
    44604615    RTGETOPTSTATE GetState;
    4461     RTGetOptInit(&GetState, pCtx->iArgc, pCtx->ppaArgv,
    4462                  NULL /*s_aOptions*/, 0 /*RT_ELEMENTS(s_aOptions)*/, pCtx->iFirstArgc, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     4616    RTGetOptInit(&GetState, pCtx->pArg->argc, pCtx->pArg->argv, s_aOptions, RT_ELEMENTS(s_aOptions),
     4617                 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    44634618
    44644619    while ((ch = RTGetOpt(&GetState, &ValueUnion)))
     
    44674622        switch (ch)
    44684623        {
     4624            GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion);
     4625
    44694626            case VINF_GETOPT_NOT_OPTION:
    4470                 break;
    4471 
    44724627            default:
    44734628                return errorGetOptEx(USAGE_GUESTCONTROL, USAGE_GSTCTRL_WATCH, ch, &ValueUnion);
     
    44774632    /** @todo Specify categories to watch for. */
    44784633    /** @todo Specify a --timeout for waiting only for a certain amount of time? */
     4634
     4635    RTEXITCODE rcExit = gctlCtxPostArgParsingInit(pCtx);
     4636    if (rcExit != RTEXITCODE_SUCCESS)
     4637        return rcExit;
    44794638
    44804639    HRESULT rc;
     
    45024661        } while (0);
    45034662
    4504         if (pCtx->fVerbose)
     4663        if (pCtx->cVerbose > 1)
    45054664            RTPrintf("Waiting for events ...\n");
    45064665
     
    45114670        }
    45124671
    4513         if (pCtx->fVerbose)
     4672        if (pCtx->cVerbose > 1)
    45144673            RTPrintf("Signal caught, exiting ...\n");
    45154674
     
    45474706#endif
    45484707
    4549     /* pArg->argv[0] contains the VM name. */
    4550     /* pArg->argv[1] contains the guest control command. */
    4551     if (pArg->argc < 2)
    4552         return errorSyntax(USAGE_GUESTCONTROL, "No sub command specified!");
    4553 
    4554     uint32_t uCmdCtxFlags = 0;
    4555     uint32_t uUsage;
    4556     GCTLCMD gctlCmd;
    4557     if (   !RTStrICmp(pArg->argv[1], "exec")
    4558         || !RTStrICmp(pArg->argv[1], "execute"))
    4559     {
    4560         gctlCmd.pfnHandler = handleCtrlProcessExecDeprecated;
    4561         uUsage = USAGE_GSTCTRL_EXEC;
    4562     }
    4563     else if (!strcmp(pArg->argv[1], "run"))
    4564     {
    4565         gctlCmd.pfnHandler = handleCtrlProcessRun;
    4566         uUsage = USAGE_GSTCTRL_RUN;
    4567     }
    4568     else if (!strcmp(pArg->argv[1], "start"))
    4569     {
    4570         gctlCmd.pfnHandler = handleCtrlProcessStart;
    4571         uUsage = USAGE_GSTCTRL_START;
    4572     }
    4573     else if (!RTStrICmp(pArg->argv[1], "copyfrom"))
    4574     {
    4575         gctlCmd.pfnHandler = handleCtrlCopyFrom;
    4576         uUsage = USAGE_GSTCTRL_COPYFROM;
    4577     }
    4578     else if (   !RTStrICmp(pArg->argv[1], "copyto")
    4579              || !RTStrICmp(pArg->argv[1], "cp"))
    4580     {
    4581         gctlCmd.pfnHandler = handleCtrlCopyTo;
    4582         uUsage = USAGE_GSTCTRL_COPYTO;
    4583     }
    4584     else if (   !RTStrICmp(pArg->argv[1], "createdirectory")
    4585              || !RTStrICmp(pArg->argv[1], "createdir")
    4586              || !RTStrICmp(pArg->argv[1], "mkdir")
    4587              || !RTStrICmp(pArg->argv[1], "md"))
    4588     {
    4589         gctlCmd.pfnHandler = handleCtrlCreateDirectory;
    4590         uUsage = USAGE_GSTCTRL_CREATEDIR;
    4591     }
    4592     else if (   !RTStrICmp(pArg->argv[1], "removedirectory")
    4593              || !RTStrICmp(pArg->argv[1], "removedir")
    4594              || !RTStrICmp(pArg->argv[1], "rmdir"))
    4595     {
    4596         gctlCmd.pfnHandler = handleCtrlRemoveDirectory;
    4597         uUsage = USAGE_GSTCTRL_REMOVEDIR;
    4598     }
    4599     else if (   !RTStrICmp(pArg->argv[1], "rm")
    4600              || !RTStrICmp(pArg->argv[1], "removefile"))
    4601     {
    4602         gctlCmd.pfnHandler = handleCtrlRemoveFile;
    4603         uUsage = USAGE_GSTCTRL_REMOVEFILE;
    4604     }
    4605     else if (   !RTStrICmp(pArg->argv[1], "ren")
    4606              || !RTStrICmp(pArg->argv[1], "rename")
    4607              || !RTStrICmp(pArg->argv[1], "mv"))
    4608     {
    4609         gctlCmd.pfnHandler = handleCtrlRename;
    4610         uUsage = USAGE_GSTCTRL_RENAME;
    4611     }
    4612     else if (   !RTStrICmp(pArg->argv[1], "createtemporary")
    4613              || !RTStrICmp(pArg->argv[1], "createtemp")
    4614              || !RTStrICmp(pArg->argv[1], "mktemp"))
    4615     {
    4616         gctlCmd.pfnHandler = handleCtrlCreateTemp;
    4617         uUsage = USAGE_GSTCTRL_CREATETEMP;
    4618     }
    4619     else if (   !RTStrICmp(pArg->argv[1], "kill")    /* Linux. */
    4620              || !RTStrICmp(pArg->argv[1], "pkill")   /* Solaris / *BSD. */
    4621              || !RTStrICmp(pArg->argv[1], "pskill")) /* SysInternals version. */
    4622     {
    4623         /** @todo What about "taskkill" on Windows? */
    4624         uCmdCtxFlags = CTLCMDCTX_FLAGS_SESSION_ANONYMOUS
    4625                      | CTLCMDCTX_FLAGS_NO_SIGNAL_HANDLER;
    4626         gctlCmd.pfnHandler = handleCtrlProcessClose;
    4627         uUsage = USAGE_GSTCTRL_KILL;
    4628     }
    4629     /** @todo Implement "killall"? */
    4630     else if (   !RTStrICmp(pArg->argv[1], "stat"))
    4631     {
    4632         gctlCmd.pfnHandler = handleCtrlStat;
    4633         uUsage = USAGE_GSTCTRL_STAT;
    4634     }
    4635     else if (   !RTStrICmp(pArg->argv[1], "updateadditions")
    4636              || !RTStrICmp(pArg->argv[1], "updateadds"))
    4637     {
    4638         uCmdCtxFlags = CTLCMDCTX_FLAGS_SESSION_ANONYMOUS
    4639                      | CTLCMDCTX_FLAGS_NO_SIGNAL_HANDLER;
    4640         gctlCmd.pfnHandler = handleCtrlUpdateAdditions;
    4641         uUsage = USAGE_GSTCTRL_UPDATEADDS;
    4642     }
    4643     else if (   !RTStrICmp(pArg->argv[1], "list"))
    4644     {
    4645         uCmdCtxFlags = CTLCMDCTX_FLAGS_SESSION_ANONYMOUS
    4646                      | CTLCMDCTX_FLAGS_NO_SIGNAL_HANDLER;
    4647         gctlCmd.pfnHandler = handleCtrlList;
    4648         uUsage = USAGE_GSTCTRL_LIST;
    4649     }
    4650     else if (   !RTStrICmp(pArg->argv[1], "session"))
    4651     {
    4652         uCmdCtxFlags = CTLCMDCTX_FLAGS_SESSION_ANONYMOUS
    4653                      | CTLCMDCTX_FLAGS_NO_SIGNAL_HANDLER;
    4654         gctlCmd.pfnHandler = handleCtrlSession;
    4655         uUsage = USAGE_GSTCTRL_SESSION;
    4656     }
    4657     else if (   !RTStrICmp(pArg->argv[1], "process"))
    4658     {
    4659         uCmdCtxFlags = CTLCMDCTX_FLAGS_SESSION_ANONYMOUS
    4660                      | CTLCMDCTX_FLAGS_NO_SIGNAL_HANDLER;
    4661         gctlCmd.pfnHandler = handleCtrlProcess;
    4662         uUsage = USAGE_GSTCTRL_PROCESS;
    4663     }
    4664     else if (   !RTStrICmp(pArg->argv[1], "watch"))
    4665     {
    4666         uCmdCtxFlags = CTLCMDCTX_FLAGS_SESSION_ANONYMOUS
    4667                      | CTLCMDCTX_FLAGS_NO_SIGNAL_HANDLER;
    4668         gctlCmd.pfnHandler = handleCtrlWatch;
    4669         uUsage = USAGE_GSTCTRL_WATCH;
    4670     }
    4671     else
    4672         return errorSyntax(USAGE_GUESTCONTROL, "Unknown sub command '%s' specified!", pArg->argv[1]);
    4673 
    4674     GCTLCMDCTX cmdCtx;
    4675     RT_ZERO(cmdCtx);
    4676 
    4677     RTEXITCODE rcExit = ctrlInitVM(pArg, &cmdCtx, uCmdCtxFlags, uUsage);
    4678     if (rcExit == RTEXITCODE_SUCCESS)
    4679     {
    4680         /* Kick off the actual command handler. */
    4681         rcExit = gctlCmd.pfnHandler(&cmdCtx);
    4682 
    4683         ctrlUninitVM(&cmdCtx, cmdCtx.uFlags);
    4684         return rcExit;
    4685     }
    4686 
    4687     return rcExit;
     4708    /*
     4709     * Command definitions.
     4710     */
     4711    static const GCTLCMDDEF s_aCmdDefs[] =
     4712    {
     4713        { "exec",               gctlHandleProcessExecDeprecated,USAGE_GSTCTRL_EXEC,      0, },
     4714        { "execute",            gctlHandleProcessExecDeprecated,USAGE_GSTCTRL_EXEC,      0, },
     4715        { "run",                gctlHandleRun,              USAGE_GSTCTRL_RUN,       0, },
     4716        { "start",              gctlHandleStart,            USAGE_GSTCTRL_START,     0, },
     4717        { "copyfrom",           gctlHandleCopyFrom,         USAGE_GSTCTRL_COPYFROM,  0, },
     4718        { "copyto",             gctlHandleCopyTo,           USAGE_GSTCTRL_COPYTO,    0, },
     4719        { "cp",                 gctlHandleCopyTo,           USAGE_GSTCTRL_COPYTO,    0, },
     4720
     4721        { "mkdir",              handleCtrtMkDir,            USAGE_GSTCTRL_MKDIR,     0, },
     4722        { "md",                 handleCtrtMkDir,            USAGE_GSTCTRL_MKDIR,     0, },
     4723        { "createdirectory",    handleCtrtMkDir,            USAGE_GSTCTRL_MKDIR,     0, },
     4724        { "createdir",          handleCtrtMkDir,            USAGE_GSTCTRL_MKDIR,     0, },
     4725
     4726        { "rmdir",              gctlHandleRmDir,            USAGE_GSTCTRL_RMDIR,     0, },
     4727        { "removedir",          gctlHandleRmDir,            USAGE_GSTCTRL_RMDIR,     0, },
     4728        { "removedirectory",    gctlHandleRmDir,            USAGE_GSTCTRL_RMDIR,     0, },
     4729
     4730        { "rm",                 gctlHandleRm,               USAGE_GSTCTRL_RM,        0, },
     4731        { "removefile",         gctlHandleRm,               USAGE_GSTCTRL_RM,        0, },
     4732        { "erase",              gctlHandleRm,               USAGE_GSTCTRL_RM,        0, },
     4733        { "del",                gctlHandleRm,               USAGE_GSTCTRL_RM,        0, },
     4734        { "delete",             gctlHandleRm,               USAGE_GSTCTRL_RM,        0, },
     4735
     4736        { "mv",                 gctlHandleMv,               USAGE_GSTCTRL_MV,        0, },
     4737        { "move",               gctlHandleMv,               USAGE_GSTCTRL_MV,        0, },
     4738        { "ren",                gctlHandleMv,               USAGE_GSTCTRL_MV,        0, },
     4739        { "rename",             gctlHandleMv,               USAGE_GSTCTRL_MV,        0, },
     4740
     4741        { "mktemp",             gctlHandleMkTemp,           USAGE_GSTCTRL_MKTEMP,    0, },
     4742        { "createtemp",         gctlHandleMkTemp,           USAGE_GSTCTRL_MKTEMP,    0, },
     4743        { "createtemporary",    gctlHandleMkTemp,           USAGE_GSTCTRL_MKTEMP,    0, },
     4744
     4745        { "stat",               gctlHandleStat,             USAGE_GSTCTRL_STAT,      0, },
     4746
     4747        /** @todo r=bird: these just work on processes we created, would be better to
     4748         *        use some different command names here and leave the standard unix
     4749         *        kill commands for killing/signalling ANY guest process, unix style. */
     4750        { "closeprocess",       gctlHandleCloseProcess,     USAGE_GSTCTRL_CLOSEPROCESS, GCTLCMDCTX_F_SESSION_ANONYMOUS | GCTLCMDCTX_F_NO_SIGNAL_HANDLER, },
     4751        { "kill",               gctlHandleCloseProcess,     USAGE_GSTCTRL_CLOSEPROCESS, GCTLCMDCTX_F_SESSION_ANONYMOUS | GCTLCMDCTX_F_NO_SIGNAL_HANDLER, },
     4752        { "pkill",              gctlHandleCloseProcess,     USAGE_GSTCTRL_CLOSEPROCESS, GCTLCMDCTX_F_SESSION_ANONYMOUS | GCTLCMDCTX_F_NO_SIGNAL_HANDLER, },
     4753        { "pskill",             gctlHandleCloseProcess,     USAGE_GSTCTRL_CLOSEPROCESS, GCTLCMDCTX_F_SESSION_ANONYMOUS | GCTLCMDCTX_F_NO_SIGNAL_HANDLER, },
     4754
     4755        { "closesession",       gctlHandleCloseSession,     USAGE_GSTCTRL_CLOSESESSION, GCTLCMDCTX_F_SESSION_ANONYMOUS | GCTLCMDCTX_F_NO_SIGNAL_HANDLER, },
     4756        { "list",               gctlHandleList,             USAGE_GSTCTRL_LIST,         GCTLCMDCTX_F_SESSION_ANONYMOUS | GCTLCMDCTX_F_NO_SIGNAL_HANDLER, },
     4757        { "watch",              gctlHandleWatch,            USAGE_GSTCTRL_WATCH,        GCTLCMDCTX_F_SESSION_ANONYMOUS | GCTLCMDCTX_F_NO_SIGNAL_HANDLER, },
     4758
     4759        {"updateguestadditions",gctlHandleUpdateAdditions,  USAGE_GSTCTRL_UPDATEGA,     GCTLCMDCTX_F_SESSION_ANONYMOUS | GCTLCMDCTX_F_NO_SIGNAL_HANDLER, },
     4760        { "updateadditions",    gctlHandleUpdateAdditions,  USAGE_GSTCTRL_UPDATEGA,     GCTLCMDCTX_F_SESSION_ANONYMOUS | GCTLCMDCTX_F_NO_SIGNAL_HANDLER, },
     4761        { "updatega",           gctlHandleUpdateAdditions,  USAGE_GSTCTRL_UPDATEGA,     GCTLCMDCTX_F_SESSION_ANONYMOUS | GCTLCMDCTX_F_NO_SIGNAL_HANDLER, },
     4762    };
     4763
     4764    /*
     4765     * Lookup the command and invoke the handler.
     4766     *
     4767     * Our Argument expectations:
     4768     *      argv[0] is the VM name.
     4769     *      argv[1] is the guest control command.
     4770     */
     4771    if (pArg->argc >= 2)
     4772    {
     4773        const char *pszCmd = pArg->argv[1];
     4774        uint32_t    iCmd;
     4775        for (iCmd = 0; iCmd < RT_ELEMENTS(s_aCmdDefs); iCmd++)
     4776            if (strcmp(s_aCmdDefs[iCmd].pszName, pszCmd) == 0)
     4777            {
     4778                GCTLCMDCTX CmdCtx;
     4779                RTEXITCODE rcExit = gctrCmdCtxInit(&CmdCtx, pArg, &s_aCmdDefs[iCmd]);
     4780                if (rcExit == RTEXITCODE_SUCCESS)
     4781                {
     4782                    rcExit = s_aCmdDefs[iCmd].pfnHandler(&CmdCtx);
     4783
     4784                    gctlCtxTerm(&CmdCtx);
     4785                }
     4786                return rcExit;
     4787            }
     4788
     4789        return errorSyntax(USAGE_GUESTCONTROL, "Unknown sub-command: '%s'", pszCmd);
     4790    }
     4791    return errorSyntax(USAGE_GUESTCONTROL, "Missing sub-command");
    46884792}
    46894793#endif /* !VBOX_ONLY_DOCS */
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.h

    r49181 r55604  
    55
    66/*
    7  * Copyright (C) 2013 Oracle Corporation
     7 * Copyright (C) 2013-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2929#include <map>
    3030
    31 const char *ctrlFileStatusToText(FileStatus_T enmStatus);
    32 const char *ctrlProcessStatusToText(ProcessStatus_T enmStatus);
    33 const char *ctrlSessionStatusToText(GuestSessionStatus_T enmStatus);
     31const char *gctlFileStatusToText(FileStatus_T enmStatus);
     32const char *gctlProcessStatusToText(ProcessStatus_T enmStatus);
     33const char *gctlGuestSessionStatusToText(GuestSessionStatus_T enmStatus);
    3434
    3535using namespace com;
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrlListener.cpp

    r49181 r55604  
    55
    66/*
    7  * Copyright (C) 2013 Oracle Corporation
     7 * Copyright (C) 2013-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3434#include <vector>
    3535
     36
     37
     38/*
     39 * GuestListenerBase
     40 * GuestListenerBase
     41 * GuestListenerBase
     42 */
     43
    3644GuestListenerBase::GuestListenerBase(void)
    3745    : mfVerbose(false)
     
    4957}
    5058
     59
     60
     61/*
     62 * GuestFileEventListener
     63 * GuestFileEventListener
     64 * GuestFileEventListener
     65 */
    5166
    5267GuestFileEventListener::GuestFileEventListener(void)
     
    86101
    87102                RTPrintf("File ID=%RU32 \"%s\" changed status to [%s]\n",
    88                          uID, Utf8Str(strPath).c_str(),
    89                          ctrlFileStatusToText(fileSts));
     103                         uID, Utf8Str(strPath).c_str(), gctlFileStatusToText(fileSts));
    90104
    91105            } while (0);
     
    99113    return S_OK;
    100114}
     115
     116
     117/*
     118 * GuestProcessEventListener
     119 * GuestProcessEventListener
     120 * GuestProcessEventListener
     121 */
    101122
    102123GuestProcessEventListener::GuestProcessEventListener(void)
     
    136157
    137158                RTPrintf("Process PID=%RU32 \"%s\" changed status to [%s]\n",
    138                          uPID, Utf8Str(strPath).c_str(),
    139                          ctrlProcessStatusToText(procSts));
     159                         uPID, Utf8Str(strPath).c_str(), gctlProcessStatusToText(procSts));
    140160
    141161            } while (0);
     
    149169    return S_OK;
    150170}
     171
     172
     173/*
     174 * GuestSessionEventListener
     175 * GuestSessionEventListener
     176 * GuestSessionEventListener
     177 */
    151178
    152179GuestSessionEventListener::GuestSessionEventListener(void)
     
    356383
    357384                RTPrintf("Session ID=%RU32 \"%s\" changed status to [%s]\n",
    358                          uID, Utf8Str(strName).c_str(),
    359                          ctrlSessionStatusToText(sessSts));
     385                         uID, Utf8Str(strName).c_str(), gctlGuestSessionStatusToText(sessSts));
    360386
    361387            } while (0);
     
    369395    return S_OK;
    370396}
     397
     398
     399/*
     400 * GuestEventListener
     401 * GuestEventListener
     402 * GuestEventListener
     403 */
    371404
    372405GuestEventListener::GuestEventListener(void)
     
    481514    return S_OK;
    482515}
     516
    483517#endif /* !VBOX_ONLY_DOCS */
    484518
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette