VirtualBox

Changeset 36099 in vbox for trunk/src/VBox/Frontends


Ignore:
Timestamp:
Feb 28, 2011 2:20:13 PM (14 years ago)
Author:
vboxsync
Message:

Main/VBoxManage: Added ExecuteProcessStatus, update on todos.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp

    r36035 r36099  
    8080 * started guest process to the command line VBoxManage was started from.
    8181 * Useful for e.g. scripting.
    82  * @todo r=bird: RTEXITCODE is using the RT prefix, that is reserved for IPRT
    83  *       use only.
    84  */
    85 enum RTEXITCODE_EXEC
    86 {
    87     RTEXITCODE_EXEC_SUCCESS      = RTEXITCODE_SUCCESS,
    88     RTEXITCODE_EXEC_FAILED       = 16,
    89     RTEXITCODE_EXEC_TERM_SIGNAL  = 17,
    90     RTEXITCODE_EXEC_TERM_ABEND   = 18,
    91     RTEXITCODE_EXEC_TIMEOUT      = 19,
    92     RTEXITCODE_EXEC_CANCELED     = 20
     82 */
     83enum EXITCODE_EXEC
     84{
     85    EXITCODE_EXEC_SUCCESS      = RTEXITCODE_SUCCESS,
     86    /* Process exited normally but with an exit code <> 0. */
     87    EXITCODE_EXEC_CODE         = 16,
     88    EXITCODE_EXEC_FAILED       = 17,
     89    EXITCODE_EXEC_TERM_SIGNAL  = 18,
     90    EXITCODE_EXEC_TERM_ABEND   = 19,
     91    EXITCODE_EXEC_TIMEOUT      = 20,
     92    EXITCODE_EXEC_DOWN         = 21,
     93    EXITCODE_EXEC_CANCELED     = 22
    9394};
    9495
    9596/**
    9697 * RTGetOpt-IDs for the guest execution control command line.
    97  * @todo r=bird: RTGETOPTDEF_EXEC is using the RT prefix, that is reserved for
    98  *       IPRT use only.
    99  */
    100 enum RTGETOPTDEF_EXEC
    101 {
    102     RTGETOPTDEF_EXEC_IGNOREORPHANEDPROCESSES = 1000,
    103     RTGETOPTDEF_EXEC_OUTPUTFORMAT,
    104     RTGETOPTDEF_EXEC_OUTPUTTYPE,
    105     RTGETOPTDEF_EXEC_WAITFOREXIT,
    106     RTGETOPTDEF_EXEC_WAITFORSTDOUT,
    107     RTGETOPTDEF_EXEC_WAITFORSTDERR,
    108     RTGETOPTDEF_EXEC_ARGS
     98 */
     99enum GETOPTDEF_EXEC
     100{
     101    GETOPTDEF_EXEC_IGNOREORPHANEDPROCESSES = 1000,
     102    GETOPTDEF_EXEC_OUTPUTFORMAT,
     103    GETOPTDEF_EXEC_DOS2UNIX,
     104    GETOPTDEF_EXEC_UNIX2DOS,
     105    GETOPTDEF_EXEC_WAITFOREXIT,
     106    GETOPTDEF_EXEC_WAITFORSTDOUT,
     107    GETOPTDEF_EXEC_WAITFORSTDERR
     108};
     109
     110enum OUTPUT_TYPE
     111{
     112    OUTPUT_TYPE_UNDEFINED = 0,
     113    OUTPUT_TYPE_DOS2UNIX  = 10,
     114    OUTPUT_TYPE_UNIX2DOS  = 20
    109115};
    110116
     
    117123                 "                            --image <path to program>\n"
    118124                 "                            --username <name> --password <password>\n"
     125                 "                            [--dos2unix]\n"
    119126                 "                            [--environment \"<NAME>=<VALUE> [<NAME>=<VALUE>]\"]\n"
    120                  "                            [--timeout <msec>] [--verbose]\n"
     127                 "                            [--timeout <msec>] [--unix2dos] [--verbose]\n"
    121128                 "                            [--wait-exit] [--wait-stdout] [--wait-stdout]"
    122129                 //"                          [--output-format=<dos>|<unix>]\n"
     
    183190 * string.
    184191 */
    185 static const char *ctrlExecProcessStatusToText(ULONG uStatus)
    186 {
    187     switch (uStatus)
    188     {
    189         case guestControl::PROC_STS_STARTED:
     192static const char *ctrlExecProcessStatusToText(ExecuteProcessStatus enmStatus)
     193{
     194    switch (enmStatus)
     195    {
     196        case ExecuteProcessStatus_Started:
    190197            return "started";
    191         case guestControl::PROC_STS_TEN:
     198        case ExecuteProcessStatus_TerminatedNormally:
    192199            return "successfully terminated";
    193         case guestControl::PROC_STS_TES:
     200        case ExecuteProcessStatus_TerminatedSignal:
    194201            return "terminated by signal";
    195         case guestControl::PROC_STS_TEA:
     202        case ExecuteProcessStatus_TerminatedAbnormally:
    196203            return "abnormally aborted";
    197         case guestControl::PROC_STS_TOK:
     204        case ExecuteProcessStatus_TimedOutKilled:
    198205            return "timed out";
    199         case guestControl::PROC_STS_TOA:
     206        case ExecuteProcessStatus_TimedOutAbnormally:
    200207            return "timed out, hanging";
    201         case guestControl::PROC_STS_DWN:
     208        case ExecuteProcessStatus_Down:
    202209            return "killed";
    203         case guestControl::PROC_STS_ERROR:
     210        case ExecuteProcessStatus_Error:
    204211            return "error";
    205212        default:
     
    209216}
    210217
    211 static int ctrlExecProcessStatusToExitCode(ULONG uStatus)
    212 {
    213     int rc = RTEXITCODE_EXEC_SUCCESS;
    214     switch (uStatus)
    215     {
    216 /** @todo r=bird: Why do you use guestControl status codes here? Is the Main
    217  *        API not exposing these constants?  If so, it's something that
    218  *        needs fixing. */
    219         case guestControl::PROC_STS_STARTED:
    220             rc = RTEXITCODE_EXEC_SUCCESS;
     218static int ctrlExecProcessStatusToExitCode(ExecuteProcessStatus enmStatus, ULONG uExitCode)
     219{
     220    int rc = EXITCODE_EXEC_SUCCESS;
     221    switch (enmStatus)
     222    {
     223        case ExecuteProcessStatus_Started:
     224            rc = EXITCODE_EXEC_SUCCESS;
    221225            break;
    222         case guestControl::PROC_STS_TEN:
    223             /** @todo check the exit code, 0 is success, !0 should be indicated
    224              *        by a specail VBoxManage exit code. */
    225             rc = RTEXITCODE_EXEC_SUCCESS;
     226        case ExecuteProcessStatus_TerminatedNormally:
     227            rc = !uExitCode ? EXITCODE_EXEC_SUCCESS : EXITCODE_EXEC_CODE;
    226228            break;
    227         case guestControl::PROC_STS_TES:
    228             rc = RTEXITCODE_EXEC_TERM_SIGNAL;
     229        case ExecuteProcessStatus_TerminatedSignal:
     230            rc = EXITCODE_EXEC_TERM_SIGNAL;
    229231            break;
    230         case guestControl::PROC_STS_TEA:
    231             rc = RTEXITCODE_EXEC_TERM_ABEND;
     232        case ExecuteProcessStatus_TerminatedAbnormally:
     233            rc = EXITCODE_EXEC_TERM_ABEND;
    232234            break;
    233         case guestControl::PROC_STS_TOK:
    234             rc = RTEXITCODE_EXEC_TIMEOUT;
     235        case ExecuteProcessStatus_TimedOutKilled:
     236            rc = EXITCODE_EXEC_TIMEOUT;
    235237            break;
    236         case guestControl::PROC_STS_TOA:
    237             rc = RTEXITCODE_EXEC_TIMEOUT;
     238        case ExecuteProcessStatus_TimedOutAbnormally:
     239            rc = EXITCODE_EXEC_TIMEOUT;
    238240            break;
    239         case guestControl::PROC_STS_DWN:
     241        case ExecuteProcessStatus_Down:
    240242            /* Service/OS is stopping, process was killed, so
    241243             * not exactly an error of the started process ... */
    242             rc = RTEXITCODE_EXEC_SUCCESS; /** @todo r=bird: return failure if you don't know what happend. No false positives, please. */
     244            rc = EXITCODE_EXEC_DOWN;
    243245            break;
    244         case guestControl::PROC_STS_ERROR:
    245             rc = RTEXITCODE_EXEC_FAILED;
     246        case ExecuteProcessStatus_Error:
     247            rc = EXITCODE_EXEC_FAILED;
    246248            break;
    247249        default:
    248             AssertMsgFailed(("Unknown exit code (%u) from guest process returned!\n", uStatus));
     250            AssertMsgFailed(("Unknown exit code (%u) from guest process returned!\n", enmStatus));
    249251            break;
    250252    }
     
    373375    static const RTGETOPTDEF s_aOptions[] =
    374376    {
    375         { "--environment",                  'e',                                        RTGETOPT_REQ_STRING  },
    376         { "--flags",                        'f',                                        RTGETOPT_REQ_STRING  },
    377         { "--ignore-operhaned-processes",   RTGETOPTDEF_EXEC_IGNOREORPHANEDPROCESSES,   RTGETOPT_REQ_NOTHING },
    378         { "--image",                        'i',                                        RTGETOPT_REQ_STRING  },
    379         //{ "--output-format",                RTGETOPTDEF_EXEC_OUTPUTFORMAT,              RTGETOPT_REQ_STRING  },
    380         { "--output-type",                  RTGETOPTDEF_EXEC_OUTPUTTYPE,                RTGETOPT_REQ_STRING  },
    381         /** @todo r=bird: output-type and output-format are the same thing.
    382          *        Please just call it --dos2unix and --unix2dos and
    383          *        implement it them.   (If you insist on flexibility, it would
    384          *        be --input-type <x> and --output-type <y>, where x and y
    385          *        could indicate line ending styles (CR/LF/CRLF), encodings
    386          *        (UTF-8, UTF-16, ++), code pages and plugin provided
    387          *        conversions.  See the conv option of dd and iconv for
    388          *        inspiration.)
    389          *
    390          *        The default must be no conversion at all, i.e.
    391          *        --output-type=binary. */
    392         { "--password",                     'p',                                        RTGETOPT_REQ_STRING  },
    393         { "--timeout",                      't',                                        RTGETOPT_REQ_UINT32  },
    394         { "--username",                     'u',                                        RTGETOPT_REQ_STRING  },
    395         { "--verbose",                      'v',                                        RTGETOPT_REQ_NOTHING },
    396         { "--wait-exit",                    RTGETOPTDEF_EXEC_WAITFOREXIT,               RTGETOPT_REQ_NOTHING },
    397         { "--wait-stdout",                  RTGETOPTDEF_EXEC_WAITFORSTDOUT,             RTGETOPT_REQ_NOTHING },
    398         { "--wait-stderr",                  RTGETOPTDEF_EXEC_WAITFORSTDERR,             RTGETOPT_REQ_NOTHING },
    399         /* @todo r=bird: '--' is interpreted by RTGetOpt() to indicate the
    400          * end of arguments, you don't need to handle this specially.
    401          * RTGetOpt() will return VINF_GETOPT_NOT_OPTION for anything following
    402          * a '--' argument.  So, let me give you some other examples for illustrating
    403          * what I mean should work now (all the same, userid/pw missing):
    404          *  VBoxManage guestcontrol myvm exec --image /bin/busybox cp /foo /bar
    405          *  VBoxManage guestcontrol myvm exec --image /bin/busybox -- cp /foo /bar
    406          *  VBoxManage guestcontrol myvm exec --image /bin/busybox cp -- /foo /bar
    407          *  VBoxManage guestcontrol myvm exec --image /bin/busybox cp /foo -- /bar
    408          *
    409          * Same, but with standard cp (image defaults to /bin/cp):
    410          *  VBoxManage guestcontrol myvm exec /bin/cp /foo /bar
    411          *  VBoxManage guestcontrol myvm exec -- /bin/cp /foo /bar
    412          *  VBoxManage guestcontrol myvm exec /bin/cp -- /foo /bar
    413          *  VBoxManage guestcontrol myvm exec /bin/cp /foo -- /bar
    414          *
    415          * The old example:
    416          *  VBoxManage guestcontrol myvm exec --image /bin/busybox -- ln -s /foo /bar
    417          *
    418          * As an example of where '--' is used by standard linux utils, try delete a
    419          * file named '-f' without specifying the directory:
    420          *      > -f        # creates the file
    421          *      rm -v -f    # does nothing because '-f' is a rm option.
    422          *      rm -v -- -f # does the trick because '--' tells rm to not read '-f' as an option.
    423          */
    424         { "--",                             RTGETOPTDEF_EXEC_ARGS,                      RTGETOPT_REQ_STRING }
     377        { "--dos2unix",                     GETOPTDEF_EXEC_DOS2UNIX,                  RTGETOPT_REQ_NOTHING },
     378        { "--environment",                  'e',                                      RTGETOPT_REQ_STRING  },
     379        { "--flags",                        'f',                                      RTGETOPT_REQ_STRING  },
     380        { "--ignore-operhaned-processes",   GETOPTDEF_EXEC_IGNOREORPHANEDPROCESSES,   RTGETOPT_REQ_NOTHING },
     381        { "--image",                        'i',                                      RTGETOPT_REQ_STRING  },
     382        { "--password",                     'p',                                      RTGETOPT_REQ_STRING  },
     383        { "--timeout",                      't',                                      RTGETOPT_REQ_UINT32  },
     384        { "--unix2dos",                     GETOPTDEF_EXEC_UNIX2DOS,                  RTGETOPT_REQ_NOTHING },
     385        { "--username",                     'u',                                      RTGETOPT_REQ_STRING  },
     386        { "--verbose",                      'v',                                      RTGETOPT_REQ_NOTHING },
     387        { "--wait-exit",                    GETOPTDEF_EXEC_WAITFOREXIT,               RTGETOPT_REQ_NOTHING },
     388        { "--wait-stdout",                  GETOPTDEF_EXEC_WAITFORSTDOUT,             RTGETOPT_REQ_NOTHING },
     389        { "--wait-stderr",                  GETOPTDEF_EXEC_WAITFORSTDERR,             RTGETOPT_REQ_NOTHING }
    425390    };
    426391
     
    437402    Utf8Str                 Utf8Password;
    438403    uint32_t                cMsTimeout      = 0;
     404    OUTPUT_TYPE             eOutputType     = OUTPUT_TYPE_UNDEFINED;
    439405    bool                    fOutputBinary   = false;
    440406    bool                    fWaitForExit    = false;
     
    450416        switch (ch)
    451417        {
     418            case GETOPTDEF_EXEC_DOS2UNIX:
     419                if (eOutputType != OUTPUT_TYPE_UNDEFINED)
     420                    return errorSyntax(USAGE_GUESTCONTROL, "More than one output type (dos2unix/unix2dos) specified!");
     421                eOutputType = OUTPUT_TYPE_DOS2UNIX;
     422                break;
     423
    452424            case 'e': /* Environment */
    453425            {
     
    465437            }
    466438
    467             case RTGETOPTDEF_EXEC_IGNOREORPHANEDPROCESSES:
     439            case GETOPTDEF_EXEC_IGNOREORPHANEDPROCESSES:
    468440                fFlags |= ExecuteProcessFlag_IgnoreOrphanedProcesses;
    469441                break;
     
    473445                break;
    474446
    475             /** @todo Add DOS2UNIX and vice versa handling!
    476               case RTGETOPTDEF_EXEC_OUTPUTFORMAT:
    477                 break;*/
    478 
    479             case RTGETOPTDEF_EXEC_OUTPUTTYPE:
    480                 if (!RTStrICmp(ValueUnion.psz, "binary"))
    481                     fOutputBinary = true;
    482                 else if (!RTStrICmp(ValueUnion.psz, "text"))
    483                     fOutputBinary = false;
    484                 else
    485                 {
    486                     AssertPtr(GetState.pDef->pszLong);
    487                     return errorSyntax(USAGE_GUESTCONTROL, "Unknown value for '%s' specified! Use either 'binary' or 'text'",
    488                                        GetState.pDef->pszLong);
    489                 }
    490                 break;
    491 
    492447            /** @todo Add a hidden flag. */
    493448
     
    500455                break;
    501456
     457            case GETOPTDEF_EXEC_UNIX2DOS:
     458                if (eOutputType != OUTPUT_TYPE_UNDEFINED)
     459                    return errorSyntax(USAGE_GUESTCONTROL, "More than one output type (dos2unix/unix2dos) specified!");
     460                eOutputType = OUTPUT_TYPE_UNIX2DOS;
     461                break;
     462
    502463            case 'u': /* User name */
    503464                Utf8UserName = ValueUnion.psz;
     
    508469                break;
    509470
    510             case RTGETOPTDEF_EXEC_WAITFOREXIT:
     471            case GETOPTDEF_EXEC_WAITFOREXIT:
    511472                fWaitForExit = true;
    512473                break;
    513474
    514             case RTGETOPTDEF_EXEC_WAITFORSTDOUT:
     475            case GETOPTDEF_EXEC_WAITFORSTDOUT:
    515476                fWaitForExit = true;
    516477                fWaitForStdOut = true;
    517478                break;
    518479
    519             case RTGETOPTDEF_EXEC_WAITFORSTDERR:
     480            case GETOPTDEF_EXEC_WAITFORSTDERR:
    520481                fWaitForExit = true;
    521482                fWaitForStdErr = true;
    522483                break;
    523484
    524             case RTGETOPTDEF_EXEC_ARGS:
     485            case VINF_GETOPT_NOT_OPTION:
    525486            {
    526                 /* Push current parameter to vector. */
    527                 args.push_back(Bstr(ValueUnion.psz).raw());
    528 
    529                 /*
    530                  * Add all following parameters after this one to our guest process
    531                  * argument vector.
    532                  */
    533                 while (   (ch = RTGetOpt(&GetState, &ValueUnion))
    534                        && RT_SUCCESS(vrc))
    535                 {
    536                     /*
    537                      * Is this option unknown or not recognized an option? Then just
    538                      * add the raw string value to our argument vector.
    539                      */
    540                     if (   ch == VINF_GETOPT_NOT_OPTION
    541                         || ch == VERR_GETOPT_UNKNOWN_OPTION)
    542                         args.push_back(Bstr(ValueUnion.psz).raw());
    543                     /*
    544                      * If this is an option/parameter we already defined for our actual
    545                      * execution command we need to take the pDef->pszLong value instead.
    546                      */
    547                     else if (ValueUnion.pDef)
    548                         args.push_back(Bstr(ValueUnion.pDef->pszLong).raw());
    549                     else
    550                         AssertMsgFailed(("Unknown parameter type detected!\n"));
    551                 }
    552                 break;
    553             }
    554 
    555             case VINF_GETOPT_NOT_OPTION:
    556487                if (Utf8Cmd.isEmpty())
    557488                    Utf8Cmd = ValueUnion.psz;
    558489                else
    559                     return RTGetOptPrintError(ch, &ValueUnion);
    560                 break;
     490                {
     491                    /* Push current parameter to vector. */
     492                    args.push_back(Bstr(ValueUnion.psz).raw());
     493
     494                    /*
     495                     * Add all following parameters after this one to our guest process
     496                     * argument vector.
     497                     */
     498                    while (   (ch = RTGetOpt(&GetState, &ValueUnion))
     499                           && RT_SUCCESS(vrc))
     500                    {
     501                        /*
     502                         * Is this option unknown or not recognized an option? Then just
     503                         * add the raw string value to our argument vector.
     504                         */
     505                        if (   ch == VINF_GETOPT_NOT_OPTION
     506                            || ch == VERR_GETOPT_UNKNOWN_OPTION)
     507                            args.push_back(Bstr(ValueUnion.psz).raw());
     508                        /*
     509                         * If this is an option/parameter we already defined for our actual
     510                         * execution command we need to take the pDef->pszLong value instead.
     511                         */
     512                        else if (ValueUnion.pDef)
     513                            args.push_back(Bstr(ValueUnion.pDef->pszLong).raw());
     514                        else
     515                            AssertMsgFailed(("Unknown parameter type detected!\n"));
     516                    }
     517                }
     518                break;
     519            }
    561520
    562521            default:
    563522                return RTGetOptPrintError(ch, &ValueUnion);
    564523        }
    565     }
    566 
    567     if (RT_FAILURE(vrc)) /** @todo r=bird: You don't need to check vrc here or in any of the two while conditions above because you are now returning directly in those cases. Drop the checks, this will keep things simpler. */
    568     {
    569         RTMsgError("Failed to parse argument '%c', rc=%Rrc", ch, vrc);
    570         return RTEXITCODE_FAILURE;
    571524    }
    572525
     
    593546
    594547    /* Execute the process. */
    595     int rcProc = RTEXITCODE_EXEC_SUCCESS;   /** @todo r=bird: Don't initialize this, please, set it explicitly in the various branches.  It's easier to see what it's going to be that way. */
     548    int rcProc;
    596549    ComPtr<IProgress> progress;
    597550    ULONG uPID = 0;
     
    606559                               progress.asOutParam());
    607560    if (FAILED(rc))
    608         vrc = ctrlPrintError(guest, COM_IIDOF(IGuest)); /** @todo return straight away and drop state (e.g. rcProc) confusion. */
     561        return ctrlPrintError(guest, COM_IIDOF(IGuest));
    609562    else
    610563    {
     
    692645                        if (cbOutputData > 0)
    693646                        {
    694                             /** @todo r=bird: Adding exec options to convert unix2dos
    695                             *        and dos2unix.  Use a VFS I/O stream filter for doing this, it's a
     647                            /** @todo r=bird: Use a VFS I/O stream filter for doing this, it's a
    696648                            *        generic problem and the new VFS APIs will handle it more
    697649                            *        transparently. (requires writing dos2unix/unix2dos filters ofc) */
    698                             if (!fOutputBinary)
     650                            if (eOutputType != OUTPUT_TYPE_UNDEFINED)
    699651                            {
    700652                                /*
     
    769721                if (fVerbose)
    770722                    RTPrintf("Process execution canceled!\n");
    771                 rcProc = RTEXITCODE_EXEC_CANCELED;
     723                rcProc = EXITCODE_EXEC_CANCELED;
    772724            }
    773725            else if (   fCompleted
     
    780732                else
    781733                {
    782                     ULONG uRetStatus, uRetExitCode, uRetFlags;
    783                     rc = guest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &uRetStatus);
     734                    ExecuteProcessStatus retStatus;
     735                    ULONG uRetExitCode, uRetFlags;
     736                    rc = guest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus);
    784737                    if (SUCCEEDED(rc) && fVerbose)
    785                         RTPrintf("Exit code=%u (Status=%u [%s], Flags=%u)\n", uRetExitCode, uRetStatus, ctrlExecProcessStatusToText(uRetStatus), uRetFlags);
    786                     /** @todo r=bird: This isn't taking uRetExitCode into
    787                      *        account. We MUST give the users a way to indicate
    788                      *        whether the guest program terminated with an 0 or
    789                      *        non-zero exit code. */
    790                     rcProc = ctrlExecProcessStatusToExitCode(uRetStatus);
     738                        RTPrintf("Exit code=%u (Status=%u [%s], Flags=%u)\n", uRetExitCode, retStatus, ctrlExecProcessStatusToText(retStatus), uRetFlags);
     739                    rcProc = ctrlExecProcessStatusToExitCode(retStatus, uRetExitCode);
    791740                }
    792741            }
     
    795744                if (fVerbose)
    796745                    RTPrintf("Process execution aborted!\n");
    797                 /** @todo r=bird: Should set rcProc here, this is not a
    798                  *        success branch. */
     746                rcProc = EXITCODE_EXEC_TERM_ABEND;
    799747            }
    800748        }
     
    11971145    AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);
    11981146
    1199     /*
    1200      * Check the syntax.
    1201      */
    1202     if (pArg->argc < 2) /* At least the source + destination should be present :-). */
    1203         return errorSyntax(USAGE_GUESTCONTROL, "Incorrect parameters");
    1204 
    12051147    static const RTGETOPTDEF s_aOptions[] =
    12061148    {
     
    12291171    int vrc = VINF_SUCCESS;
    12301172    uint32_t idxNonOption = 0;
    1231     bool fUsageOK = true;
    1232     while (   (ch = RTGetOpt(&GetState, &ValueUnion))
    1233            && RT_SUCCESS(vrc))
     1173    while (ch = RTGetOpt(&GetState, &ValueUnion))
    12341174    {
    12351175        /* For options that require an argument, ValueUnion has received the value. */
     
    12741214
    12751215                    default:
    1276                         /** @todo r=bird: {2..UINT32_MAX-1} goes unnoticed
    1277                          *        to /dev/null? That doesn't make much
    1278                          *        sense... Why not just return with a syntax
    1279                          *        error straight away? */
     1216                        return errorSyntax(USAGE_GUESTCONTROL, "Too many parameters specified, only source and destination allowed!");
     1217                        /* Never reached. */
    12801218                        break;
    12811219                }
    12821220                idxNonOption++;
    12831221                if (idxNonOption == UINT32_MAX)
    1284                 {
    1285                     RTMsgError("Too many files specified! Aborting.\n");
    1286                     vrc = VERR_TOO_MUCH_DATA; /** @todo r=bird: return straight away, drop the RT_SUCCESS(vrc) from the while condition.  Keep things simple. */
    1287                 }
     1222                    return errorSyntax(USAGE_GUESTCONTROL, "Too many files specified!");
    12881223                break;
    12891224            }
     
    12931228        }
    12941229    }
    1295 
    1296     if (!fUsageOK) /** @todo r=bird: fUsageOK - never set to false, just drop it.  Keep the state simple. */
    1297         return errorSyntax(USAGE_GUESTCONTROL, "Incorrect parameters");
    12981230
    12991231    if (Utf8Source.isEmpty())
     
    13881320    AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);
    13891321
    1390     /*
    1391      * Check the syntax.  We can deduce the correct syntax from the number of
    1392      * arguments.
    1393      */
    1394     if (pArg->argc < 2) /* At least the directory we want to create should be present :-). */
    1395         return errorSyntax(USAGE_GUESTCONTROL, "Incorrect parameters");
    1396 
    13971322    static const RTGETOPTDEF s_aOptions[] =
    13981323    {
     
    15121437     * arguments.
    15131438     */
    1514     if (pArg->argc < 1) /* At least the VM name should be present :-). */ /** @todo r=bird: This is no longer correct. Ditto for all other handlers. */
    1515         return errorSyntax(USAGE_GUESTCONTROL, "Incorrect parameters");
    1516 
    15171439    Utf8Str Utf8Source;
    15181440    bool fVerbose = false;
     
    16211543    AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);
    16221544
    1623     /* At least the VM name + sub command needs to be specified. */
    1624     if (pArg->argc <= 2)
    1625         return errorSyntax(USAGE_GUESTCONTROL, "Incorrect parameters");
    1626 
    16271545    HandlerArg arg = *pArg;
    16281546    arg.argc = pArg->argc - 2; /* Skip VM name and sub command. */
Note: See TracChangeset for help on using the changeset viewer.

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