VirtualBox

Changeset 36099 in vbox


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

Main/VBoxManage: Added ExecuteProcessStatus, update on todos.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/HostServices/GuestControlSvc.h

    r34556 r36099  
    4444/**
    4545 * Process status when executed in the guest.
     46 * Note: Has to match Main's ExecuteProcessStatus_*!
    4647 */
    4748enum eProcessStatus
  • 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. */
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r36082 r36099  
    80768076
    80778077  <enum
     8078    name="ExecuteProcessStatus"
     8079    uuid="153768d9-d971-4098-8b5a-c5cb1ab9ea88"
     8080    >
     8081    <desc>
     8082      Guest process execution status.
     8083    </desc>
     8084
     8085    <const name="Undefined"               value="0">
     8086      <desc>Process is in an undefined state.</desc>
     8087    </const>
     8088
     8089    <const name="Started"                 value="1">
     8090      <desc>Process has been started.</desc>
     8091    </const>
     8092
     8093    <const name="TerminatedNormally"      value="2">
     8094      <desc>Process terminated normally.</desc>
     8095    </const>
     8096
     8097    <const name="TerminatedSignal"        value="3">
     8098      <desc>Process terminated via signal.</desc>
     8099    </const>
     8100
     8101    <const name="TerminatedAbnormally"    value="4">
     8102      <desc>Process terminated abnormally.</desc>
     8103    </const>
     8104
     8105     <const name="TimedOutKilled"         value="5">
     8106      <desc>Process timed out and was killed.</desc>
     8107    </const>
     8108
     8109    <const name="TimedOutAbnormally"      value="6">
     8110      <desc>Process timed out and was not killed successfully.</desc>
     8111    </const>
     8112
     8113    <const name="Down"                    value="7">
     8114      <desc>Service/OS is stopping, process was killed.</desc>
     8115    </const>
     8116
     8117    <const name="Error"                   value="8">
     8118      <desc>Something went wrong (error code in flags).</desc>
     8119    </const>
     8120  </enum>
     8121
     8122  <enum
    80788123    name="ProcessInputFlag"
    80798124    uuid="5d38c1dd-2604-4ddf-92e5-0c0cdd3bdbd5"
     
    80868131      <desc>No flag set.</desc>
    80878132    </const>
     8133
    80888134    <const name="EndOfFile"               value="1">
    80898135      <desc>End of file (input) reached.</desc>
     
    81368182  <interface
    81378183    name="IGuest" extends="$unknown"
    8138     uuid="4db4f806-0a20-4772-9419-14563b662f93"
     8184    uuid="4e78f7dd-8ca1-47e5-a344-5207f793df71"
    81398185    wsmap="managed"
    81408186    >
     
    84248470        </desc>
    84258471      </param>
    8426       <param name="reason" type="unsigned long" dir="return">
     8472      <param name="reason" type="ExecuteProcessStatus" dir="return">
    84278473        <desc>
    84288474          The current process status.
  • trunk/src/VBox/Main/include/GuestImpl.h

    r35967 r36099  
    9494    STDMETHOD(GetProcessOutput)(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS, LONG64 aSize, ComSafeArrayOut(BYTE, aData));
    9595    STDMETHOD(SetProcessInput)(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS, ComSafeArrayIn(BYTE, aData), ULONG *aBytesWritten);
    96     STDMETHOD(GetProcessStatus)(ULONG aPID, ULONG *aExitCode, ULONG *aFlags, ULONG *aStatus);
     96    STDMETHOD(GetProcessStatus)(ULONG aPID, ULONG *aExitCode, ULONG *aFlags, ExecuteProcessStatus *aStatus);
    9797    STDMETHOD(CopyToGuest)(IN_BSTR aSource, IN_BSTR aDest, IN_BSTR aUserName, IN_BSTR aPassword, ULONG aFlags, IProgress **aProgress);
    9898    STDMETHOD(CreateDirectory)(IN_BSTR aDirectory, IN_BSTR aUserName, IN_BSTR aPassword, ULONG aMode, ULONG aFlags, IProgress **aProgress);
     
    154154    struct GuestProcess
    155155    {
    156         uint32_t                    mStatus;
     156        ExecuteProcessStatus        mStatus;
    157157        uint32_t                    mFlags;
    158158        uint32_t                    mExitCode;
     
    179179    void destroyCtrlCallbackContext(CallbackMapIter it);
    180180    uint32_t addCtrlCallbackContext(eVBoxGuestCtrlCallbackType enmType, void *pvData, uint32_t cbData, Progress* pProgress);
    181     HRESULT waitForProcessStatusChange(ULONG uPID, ULONG *puRetStatus, ULONG *puRetExitCode, ULONG uTimeoutMS);
     181    HRESULT waitForProcessStatusChange(ULONG uPID, ExecuteProcessStatus *pRetStatus, ULONG *puRetExitCode, ULONG uTimeoutMS);
    182182# endif
    183183
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r35869 r36099  
    379379                             * canceled or we simply got all stuff transferred.
    380380                             */
    381                             ULONG uRetStatus, uRetExitCode;
    382                             rc = pGuest->waitForProcessStatusChange(uPID, &uRetStatus, &uRetExitCode, 10 * 1000 /* 10s timeout. */);
     381                            ExecuteProcessStatus retStatus;
     382                            ULONG uRetExitCode;
     383                            rc = pGuest->waitForProcessStatusChange(uPID, &retStatus, &uRetExitCode, 10 * 1000 /* 10s timeout. */);
    383384                            if (FAILED(rc))
    384385                            {
     
    388389                            {
    389390                                if (   uRetExitCode != 0
    390                                     || uRetStatus   != PROC_STS_TEN)
     391                                    || retStatus    != ExecuteProcessStatus_TerminatedNormally)
    391392                                {
    392393                                    rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
     
    786787                    }
    787788
    788                     ULONG uRetStatus, uRetExitCode, uRetFlags;
    789                     rc = pGuest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &uRetStatus);
     789                    ExecuteProcessStatus retStatus;
     790                    ULONG uRetExitCode, uRetFlags;
     791                    rc = pGuest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus);
    790792                    if (SUCCEEDED(rc))
    791793                    {
     
    802804                            {
    803805                                LogRel(("Guest Additions update failed (Exit code=%u, Status=%u, Flags=%u)\n",
    804                                         uRetExitCode, uRetStatus, uRetFlags));
     806                                        uRetExitCode, retStatus, uRetFlags));
    805807                                rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
    806808                                                                     Guest::tr("Guest Additions update failed with exit code=%u (status=%u, flags=%u)"),
    807                                                                      uRetExitCode, uRetStatus, uRetFlags);
     809                                                                     uRetExitCode, retStatus, uRetFlags);
    808810                            }
    809811                        }
     
    814816                            rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
    815817                                                                 Guest::tr("Guest Additions update was canceled by the guest with exit code=%u (status=%u, flags=%u)"),
    816                                                                  uRetExitCode, uRetStatus, uRetFlags);
     818                                                                 uRetExitCode, retStatus, uRetFlags);
    817819                        }
    818820                        else
     
    11131115                    /* Not found, add to map. */
    11141116                    GuestProcess newProcess;
    1115                     newProcess.mStatus = pCBData->u32Status;
     1117                    newProcess.mStatus = (ExecuteProcessStatus)pCBData->u32Status;
    11161118                    newProcess.mExitCode = pCBData->u32Flags; /* Contains exit code. */
    11171119                    newProcess.mFlags = 0;
     
    11211123                else /* Update map. */
    11221124                {
    1123                     it_proc->second.mStatus = pCBData->u32Status;
     1125                    it_proc->second.mStatus = (ExecuteProcessStatus)pCBData->u32Status;
    11241126                    it_proc->second.mExitCode = pCBData->u32Flags; /* Contains exit code. */
    11251127                    it_proc->second.mFlags = 0;
     
    14251427}
    14261428
    1427 HRESULT Guest::waitForProcessStatusChange(ULONG uPID, ULONG *puRetStatus, ULONG *puRetExitCode, ULONG uTimeoutMS)
    1428 {
    1429     AssertPtr(puRetStatus);
     1429HRESULT Guest::waitForProcessStatusChange(ULONG uPID, ExecuteProcessStatus *pRetStatus, ULONG *puRetExitCode, ULONG uTimeoutMS)
     1430{
     1431    AssertPtr(pRetStatus);
    14301432    AssertPtr(puRetExitCode);
    14311433
     
    14501452            break;
    14511453        }
    1452         hRC = GetProcessStatus(uPID, puRetExitCode, &uRetFlagsIgnored, puRetStatus);
     1454        hRC = GetProcessStatus(uPID, puRetExitCode, &uRetFlagsIgnored, pRetStatus);
    14531455        if (FAILED(hRC))
    14541456            break;
    14551457        RTThreadSleep(100);
    1456     } while(*puRetStatus == PROC_STS_STARTED && SUCCEEDED(hRC));
     1458    } while(*pRetStatus == ExecuteProcessStatus_Started && SUCCEEDED(hRC));
    14571459    return hRC;
    14581460}
     
    18491851            {
    18501852                /* PID exists; check if process is still running. */
    1851                 if (itProc->second.mStatus != PROC_STS_STARTED)
     1853                if (itProc->second.mStatus != ExecuteProcessStatus_Started)
    18521854                    rc = setError(VBOX_E_IPRT_ERROR,
    18531855                                  Guest::tr("Cannot inject input to not running process (PID %u)"), aPID);
     
    22002202}
    22012203
    2202 STDMETHODIMP Guest::GetProcessStatus(ULONG aPID, ULONG *aExitCode, ULONG *aFlags, ULONG *aStatus)
     2204STDMETHODIMP Guest::GetProcessStatus(ULONG aPID, ULONG *aExitCode, ULONG *aFlags, ExecuteProcessStatus *aStatus)
    22032205{
    22042206#ifndef VBOX_WITH_GUEST_CONTROL
     
    24402442            if (fCompleted)
    24412443            {
    2442                 ULONG uRetStatus, uRetExitCode, uRetFlags;
     2444                ExecuteProcessStatus retStatus;
     2445                ULONG uRetExitCode, uRetFlags;
    24432446                if (SUCCEEDED(rc))
    24442447                {
    2445                     rc = GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &uRetStatus);
     2448                    rc = GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus);
    24462449                    if (SUCCEEDED(rc) && uRetExitCode != 0)
    24472450                    {
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