VirtualBox

Changeset 44959 in vbox


Ignore:
Timestamp:
Mar 7, 2013 6:24:50 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
84171
Message:

FE/VBoxManage/GuestCtrl: Added "guestcontrol list" command (debug versions only), proper RTEXITCODEs for handler returns.

File:
1 edited

Legend:

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

    r44885 r44959  
    556556
    557557/* <Missing documentation> */
    558 static int handleCtrlExecProgram(ComPtr<IGuest> pGuest, HandlerArg *pArg)
    559 {
    560     AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);
     558static RTEXITCODE handleCtrlExecProgram(ComPtr<IGuest> pGuest, HandlerArg *pArg)
     559{
     560    AssertPtrReturn(pArg, RTEXITCODE_SYNTAX);
    561561
    562562    /*
     
    727727    HRESULT rc = S_OK;
    728728    if (fVerbose)
    729     {
    730         if (cMsTimeout == 0)
    731             RTPrintf("Waiting for guest to start process ...\n");
    732         else
    733             RTPrintf("Waiting for guest to start process (within %ums)\n", cMsTimeout);
    734     }
    735 
    736     /* Adjust process creation flags if we don't want to wait for process termination. */
    737     if (!fWaitForExit)
    738         aCreateFlags.push_back(ProcessCreateFlag_WaitForProcessStartOnly);
     729        RTPrintf("Opening guest session as user '%s' ...\n", strUsername.c_str());
    739730
    740731    /** @todo This eventually needs a bit of revamping so that a valid session gets passed
     
    754745    }
    755746
     747    if (fVerbose)
     748    {
     749        if (cMsTimeout == 0)
     750            RTPrintf("Waiting for guest to start process ...\n");
     751        else
     752            RTPrintf("Waiting for guest to start process (within %ums)\n", cMsTimeout);
     753    }
     754
     755    /* Adjust process creation flags if we don't want to wait for process termination. */
     756    if (!fWaitForExit)
     757        aCreateFlags.push_back(ProcessCreateFlag_WaitForProcessStartOnly);
     758
    756759    /* Get current time stamp to later calculate rest of timeout left. */
    757760    uint64_t u64StartMS = RTTimeMilliTS();
    758761
    759     /*
    760      * Execute the process.
    761      */
    762     ComPtr<IGuestProcess> pProcess;
    763     rc = pGuestSession->ProcessCreate(Bstr(strCmd).raw(),
    764                                       ComSafeArrayAsInParam(args),
    765                                       ComSafeArrayAsInParam(env),
    766                                       ComSafeArrayAsInParam(aCreateFlags),
    767                                       cMsTimeout,
    768                                       pProcess.asOutParam());
    769     if (FAILED(rc))
    770     {
    771         ctrlPrintError(pGuestSession, COM_IIDOF(IGuestSession));
    772 
    773         pGuestSession->Close();
    774         return RTEXITCODE_FAILURE;
    775     }
    776 
    777     /** @todo does this need signal handling? there's no progress object etc etc */
    778 
    779     vrc = RTStrmSetMode(g_pStdOut, 1 /* Binary mode */, -1 /* Code set, unchanged */);
    780     if (RT_FAILURE(vrc))
    781         RTMsgError("Unable to set stdout's binary mode, rc=%Rrc\n", vrc);
    782     vrc = RTStrmSetMode(g_pStdErr, 1 /* Binary mode */, -1 /* Code set, unchanged */);
    783     if (RT_FAILURE(vrc))
    784         RTMsgError("Unable to set stderr's binary mode, rc=%Rrc\n", vrc);
    785 
    786     /* Wait for process to exit ... */
    787     RTMSINTERVAL cMsTimeLeft = 1;
    788     bool fReadStdOut, fReadStdErr;
    789     fReadStdOut = fReadStdErr = false;
    790     bool fCompleted = false;
    791     while (!fCompleted && cMsTimeLeft != 0)
    792     {
    793         cMsTimeLeft = ctrlExecGetRemainingTime(u64StartMS, cMsTimeout);
    794         ProcessWaitResult_T waitResult;
    795         rc = pProcess->WaitForArray(ComSafeArrayAsInParam(aWaitFlags), cMsTimeLeft, &waitResult);
     762    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     763    do
     764    {
     765        /*
     766         * Execute the process.
     767         */
     768        ComPtr<IGuestProcess> pProcess;
     769        rc = pGuestSession->ProcessCreate(Bstr(strCmd).raw(),
     770                                          ComSafeArrayAsInParam(args),
     771                                          ComSafeArrayAsInParam(env),
     772                                          ComSafeArrayAsInParam(aCreateFlags),
     773                                          cMsTimeout,
     774                                          pProcess.asOutParam());
    796775        if (FAILED(rc))
    797776        {
    798             ctrlPrintError(pProcess, COM_IIDOF(IProcess));
    799 
    800             pGuestSession->Close();
    801             return RTEXITCODE_FAILURE;
     777            ctrlPrintError(pGuestSession, COM_IIDOF(IGuestSession));
     778
     779            rcExit = RTEXITCODE_FAILURE;
     780            break;
    802781        }
    803782
    804         switch (waitResult)
    805         {
    806             case ProcessWaitResult_Start:
    807             {
    808                 ULONG uPID = 0;
    809                 rc = pProcess->COMGETTER(PID)(&uPID);
     783        /** @todo does this need signal handling? there's no progress object etc etc */
     784
     785        vrc = RTStrmSetMode(g_pStdOut, 1 /* Binary mode */, -1 /* Code set, unchanged */);
     786        if (RT_FAILURE(vrc))
     787            RTMsgError("Unable to set stdout's binary mode, rc=%Rrc\n", vrc);
     788        vrc = RTStrmSetMode(g_pStdErr, 1 /* Binary mode */, -1 /* Code set, unchanged */);
     789        if (RT_FAILURE(vrc))
     790            RTMsgError("Unable to set stderr's binary mode, rc=%Rrc\n", vrc);
     791
     792        /* Wait for process to exit ... */
     793        RTMSINTERVAL cMsTimeLeft = 1;
     794        bool fReadStdOut, fReadStdErr;
     795        fReadStdOut = fReadStdErr = false;
     796        bool fCompleted = false;
     797        while (!fCompleted && cMsTimeLeft != 0)
     798        {
     799            cMsTimeLeft = ctrlExecGetRemainingTime(u64StartMS, cMsTimeout);
     800            ProcessWaitResult_T waitResult;
     801            rc = pProcess->WaitForArray(ComSafeArrayAsInParam(aWaitFlags), cMsTimeLeft, &waitResult);
     802            if (FAILED(rc))
     803            {
     804                ctrlPrintError(pProcess, COM_IIDOF(IProcess));
     805
     806                rcExit = RTEXITCODE_FAILURE;
     807                break;
     808            }
     809
     810            switch (waitResult)
     811            {
     812                case ProcessWaitResult_Start:
     813                {
     814                    ULONG uPID = 0;
     815                    rc = pProcess->COMGETTER(PID)(&uPID);
     816                    if (FAILED(rc))
     817                    {
     818                        ctrlPrintError(pProcess, COM_IIDOF(IProcess));
     819
     820                        rcExit = RTEXITCODE_FAILURE;
     821                        break;
     822                    }
     823
     824                    if (fVerbose)
     825                    {
     826                        RTPrintf("Process '%s' (PID: %ul) %s\n",
     827                                 strCmd.c_str(), uPID,
     828                                 fWaitForExit ? "started" : "started (detached)");
     829                    }
     830                    else /** @todo Introduce a --quiet option for not printing this. */
     831                    {
     832                        /* Just print plain PID to make it easier for scripts
     833                         * invoking VBoxManage. */
     834                        RTPrintf("%ul\n", uPID);
     835                    }
     836
     837                    /* We're done here if we don't want to wait for termination. */
     838                    if (!fWaitForExit)
     839                        fCompleted = true;
     840
     841                    break;
     842                }
     843                case ProcessWaitResult_StdOut:
     844                    fReadStdOut = true;
     845                    break;
     846                case ProcessWaitResult_StdErr:
     847                    fReadStdErr = true;
     848                    break;
     849                case ProcessWaitResult_Terminate:
     850                    /* Process terminated, we're done */
     851                    fCompleted = true;
     852                    break;
     853                case ProcessWaitResult_WaitFlagNotSupported:
     854                {
     855                    /* The guest does not support waiting for stdout/err, so
     856                     * yield to reduce the CPU load due to busy waiting. */
     857                    RTThreadYield(); /* Optional, don't check rc. */
     858
     859                    /* Try both, stdout + stderr. */
     860                    fReadStdOut = fReadStdErr = true;
     861                    break;
     862                }
     863                default:
     864                    /* Ignore all other results, let the timeout expire */
     865                    break;
     866            }
     867
     868            if (FAILED(rc))
     869                break;
     870
     871            if (fReadStdOut) /* Do we need to fetch stdout data? */
     872            {
     873                cMsTimeLeft = ctrlExecGetRemainingTime(u64StartMS, cMsTimeout);
     874                vrc = ctrlExecPrintOutput(pProcess, g_pStdOut,
     875                                          1 /* StdOut */, cMsTimeLeft);
     876                fReadStdOut = false;
     877            }
     878
     879            if (fReadStdErr) /* Do we need to fetch stdout data? */
     880            {
     881                cMsTimeLeft = ctrlExecGetRemainingTime(u64StartMS, cMsTimeout);
     882                vrc = ctrlExecPrintOutput(pProcess, g_pStdErr,
     883                                          2 /* StdErr */, cMsTimeLeft);
     884                fReadStdErr = false;
     885            }
     886
     887            if (RT_FAILURE(vrc))
     888                break;
     889
     890        } /* while */
     891
     892        /* Report status back to the user. */
     893        if (fCompleted)
     894        {
     895            ProcessStatus_T status;
     896            rc = pProcess->COMGETTER(Status)(&status);
     897            if (FAILED(rc))
     898            {
     899                ctrlPrintError(pProcess, COM_IIDOF(IProcess));
     900
     901                rcExit = RTEXITCODE_FAILURE;
     902            }
     903            else
     904            {
     905                LONG exitCode;
     906                rc = pProcess->COMGETTER(ExitCode)(&exitCode);
    810907                if (FAILED(rc))
    811908                {
    812909                    ctrlPrintError(pProcess, COM_IIDOF(IProcess));
    813910
    814                     pGuestSession->Close();
    815                     return RTEXITCODE_FAILURE;
    816                 }
    817 
    818                 if (fVerbose)
    819                 {
    820                     RTPrintf("Process '%s' (PID: %ul) %s\n",
    821                              strCmd.c_str(), uPID,
    822                              fWaitForExit ? "started" : "started (detached)");
     911                    rcExit = RTEXITCODE_FAILURE;
    823912                }
    824913                else
    825914                {
    826                     /* Just print plain PID to make it easier for scripts
    827                      * invoking VBoxManage. */
    828                     RTPrintf("%ul\n", uPID);
     915                    if (fVerbose)
     916                        RTPrintf("Exit code=%u (Status=%u [%s])\n", exitCode, status, ctrlExecProcessStatusToText(status));
     917
     918                    rcExit = (RTEXITCODE)ctrlExecProcessStatusToExitCode(status, exitCode);
    829919                }
    830 
    831                 /* We're done here if we don't want to wait for termination. */
    832                 if (!fWaitForExit)
    833                     fCompleted = true;
    834 
    835                 break;
    836             }
    837             case ProcessWaitResult_StdOut:
    838                 fReadStdOut = true;
    839                 break;
    840             case ProcessWaitResult_StdErr:
    841                 fReadStdErr = true;
    842                 break;
    843             case ProcessWaitResult_Terminate:
    844                 /* Process terminated, we're done */
    845                 fCompleted = true;
    846                 break;
    847             case ProcessWaitResult_WaitFlagNotSupported:
    848             {
    849                 /* The guest does not support waiting for stdout/err, so
    850                  * yield to reduce the CPU load due to busy waiting. */
    851                 RTThreadYield(); /* Optional, don't check rc. */
    852 
    853                 /* Try both, stdout + stderr. */
    854                 fReadStdOut = fReadStdErr = true;
    855                 break;
    856             }
    857             default:
    858                 /* Ignore all other results, let the timeout expire */
    859                 break;
     920            }
    860921        }
    861 
    862         if (fReadStdOut) /* Do we need to fetch stdout data? */
    863         {
    864             cMsTimeLeft = ctrlExecGetRemainingTime(u64StartMS, cMsTimeout);
    865             vrc = ctrlExecPrintOutput(pProcess, g_pStdOut,
    866                                       1 /* StdOut */, cMsTimeLeft);
    867             fReadStdOut = false;
     922        else
     923        {
     924            if (fVerbose)
     925                RTPrintf("Process execution aborted!\n");
     926
     927            rcExit = (RTEXITCODE)EXITCODEEXEC_TERM_ABEND;
    868928        }
    869 
    870         if (fReadStdErr) /* Do we need to fetch stdout data? */
    871         {
    872             cMsTimeLeft = ctrlExecGetRemainingTime(u64StartMS, cMsTimeout);
    873             vrc = ctrlExecPrintOutput(pProcess, g_pStdErr,
    874                                       2 /* StdErr */, cMsTimeLeft);
    875             fReadStdErr = false;
    876         }
    877 
    878         if (RT_FAILURE(vrc))
    879             break;
    880 
    881     } /* while */
    882 
    883     /* Report status back to the user. */
    884     if (fCompleted)
    885     {
    886         ProcessStatus_T status;
    887         rc = pProcess->COMGETTER(Status)(&status);
    888         if (FAILED(rc))
    889         {
    890             ctrlPrintError(pProcess, COM_IIDOF(IProcess));
    891 
    892             pGuestSession->Close();
    893             return RTEXITCODE_FAILURE;
    894         }
    895         LONG exitCode;
    896         rc = pProcess->COMGETTER(ExitCode)(&exitCode);
    897         if (FAILED(rc))
    898         {
    899             ctrlPrintError(pProcess, COM_IIDOF(IProcess));
    900 
    901             pGuestSession->Close();
    902             return RTEXITCODE_FAILURE;
    903         }
    904         if (fVerbose)
    905             RTPrintf("Exit code=%u (Status=%u [%s])\n", exitCode, status, ctrlExecProcessStatusToText(status));
    906 
    907         pGuestSession->Close();
    908         return ctrlExecProcessStatusToExitCode(status, exitCode);
    909     }
    910     else
    911     {
    912         if (fVerbose)
    913             RTPrintf("Process execution aborted!\n");
    914 
    915         pGuestSession->Close();
    916         return EXITCODEEXEC_TERM_ABEND;
    917     }
    918 
    919     pGuestSession->Close();
    920 
    921     return RT_FAILURE(vrc) || FAILED(rc) ? RTEXITCODE_FAILURE : RTEXITCODE_SUCCESS;
     929    } while (0);
     930
     931    if (fVerbose)
     932        RTPrintf("Closing guest session ...\n");
     933    rc = pGuestSession->Close();
     934    if (FAILED(rc))
     935    {
     936        ctrlPrintError(pGuestSession, COM_IIDOF(ISession));
     937
     938        if (rcExit == RTEXITCODE_SUCCESS)
     939            rcExit = RTEXITCODE_FAILURE;
     940    }
     941
     942    return rcExit;
    922943}
    923944
     
    18071828}
    18081829
    1809 static int handleCtrlCopy(ComPtr<IGuest> guest, HandlerArg *pArg,
    1810                           bool fHostToGuest)
    1811 {
    1812     AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);
     1830static RTEXITCODE handleCtrlCopy(ComPtr<IGuest> guest, HandlerArg *pArg,
     1831                                 bool fHostToGuest)
     1832{
     1833    AssertPtrReturn(pArg, RTEXITCODE_SYNTAX);
    18131834
    18141835    /** @todo r=bird: This command isn't very unix friendly in general. mkdir
     
    21012122}
    21022123
    2103 static int handleCtrlCreateDirectory(ComPtr<IGuest> pGuest, HandlerArg *pArg)
    2104 {
    2105     AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);
     2124static RTEXITCODE handleCtrlCreateDirectory(ComPtr<IGuest> pGuest, HandlerArg *pArg)
     2125{
     2126    AssertPtrReturn(pArg, RTEXITCODE_SYNTAX);
    21062127
    21072128    /*
     
    22062227                                pGuestSession.asOutParam());
    22072228    if (FAILED(hrc))
    2208         return ctrlPrintError(pGuest, COM_IIDOF(IGuest));
     2229    {
     2230        ctrlPrintError(pGuest, COM_IIDOF(IGuest));
     2231        return RTEXITCODE_FAILURE;
     2232    }
    22092233
    22102234    DESTDIRMAPITER it = mapDirs.begin();
     
    22302254}
    22312255
    2232 static int handleCtrlCreateTemp(ComPtr<IGuest> pGuest, HandlerArg *pArg)
    2233 {
    2234     AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);
     2256static RTEXITCODE handleCtrlCreateTemp(ComPtr<IGuest> pGuest, HandlerArg *pArg)
     2257{
     2258    AssertPtrReturn(pArg, RTEXITCODE_SYNTAX);
    22352259
    22362260    /*
     
    23672391                                pGuestSession.asOutParam());
    23682392    if (FAILED(hrc))
    2369         return ctrlPrintError(pGuest, COM_IIDOF(IGuest));
     2393    {
     2394        ctrlPrintError(pGuest, COM_IIDOF(IGuest));
     2395        return RTEXITCODE_FAILURE;
     2396    }
    23702397
    23712398    if (fDirectory)
     
    26572684    return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
    26582685}
     2686
     2687#ifdef DEBUG
     2688static RTEXITCODE handleCtrlList(ComPtr<IGuest> guest, HandlerArg *pArg)
     2689{
     2690    AssertPtrReturn(pArg, RTEXITCODE_SYNTAX);
     2691
     2692    if (pArg->argc < 1)
     2693        return errorSyntax(USAGE_GUESTCONTROL, "Must specify a listing category");
     2694
     2695    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     2696
     2697    bool fListSessions = false;
     2698    if (!RTStrICmp(pArg->argv[0], "sessions"))
     2699        fListSessions = true;
     2700    bool fListProcesses = false;
     2701    if (!RTStrICmp(pArg->argv[0], "all"))
     2702    {
     2703        fListSessions = true;
     2704        fListProcesses = true;
     2705    }
     2706
     2707    if (fListSessions)
     2708    {
     2709        RTPrintf("Active guest sessions:\n");
     2710
     2711        HRESULT rc;
     2712        do
     2713        {
     2714            size_t cTotalProcs = 0;
     2715
     2716            SafeIfaceArray <IGuestSession> collSessions;
     2717            CHECK_ERROR_BREAK(guest, COMGETTER(Sessions)(ComSafeArrayAsOutParam(collSessions)));
     2718            for (size_t i = 0; i < collSessions.size(); i++)
     2719            {
     2720                ComPtr<IGuestSession> pCurSession = collSessions[i];
     2721                if (!pCurSession.isNull())
     2722                {
     2723                    Bstr strName;
     2724                    CHECK_ERROR_BREAK(pCurSession, COMGETTER(Name)(strName.asOutParam()));
     2725                    Bstr strUser;
     2726                    CHECK_ERROR_BREAK(pCurSession, COMGETTER(User)(strUser.asOutParam()));
     2727                    ULONG uID;
     2728                    CHECK_ERROR_BREAK(pCurSession, COMGETTER(Id)(&uID));
     2729
     2730                    RTPrintf("\n\tSession #%zu: ID=%RU32, User=%ls, Name=%ls",
     2731                             i, uID, strUser.raw(), strName.raw());
     2732
     2733                    if (fListProcesses)
     2734                    {
     2735                        SafeIfaceArray <IGuestProcess> collProcesses;
     2736                        CHECK_ERROR_BREAK(pCurSession, COMGETTER(Processes)(ComSafeArrayAsOutParam(collProcesses)));
     2737                        for (size_t a = 0; a < collProcesses.size(); a++)
     2738                        {
     2739                            ComPtr<IGuestProcess> pCurProcess = collProcesses[a];
     2740                            if (!pCurProcess.isNull())
     2741                            {
     2742                                ULONG uPID;
     2743                                CHECK_ERROR_BREAK(pCurProcess, COMGETTER(PID)(&uPID));
     2744                                Bstr strExecPath;
     2745                                CHECK_ERROR_BREAK(pCurProcess, COMGETTER(ExecutablePath)(strExecPath.asOutParam()));
     2746
     2747                                RTPrintf("\n\t\tProcess #%zu: PID=%RU32, CmdLine=%ls",
     2748                                         i, uPID, strExecPath.raw());
     2749                            }
     2750                        }
     2751
     2752                        cTotalProcs += collProcesses.size();
     2753                    }
     2754                }
     2755            }
     2756
     2757            RTPrintf("\n\nTotal guest sessions: %zu", collSessions.size());
     2758            RTPrintf("\n\nTotal guest processes: %zu", cTotalProcs);
     2759
     2760        } while (0);
     2761
     2762        if (FAILED(rc))
     2763            rcExit = RTEXITCODE_FAILURE;
     2764    }
     2765    else
     2766        return errorSyntax(USAGE_GUESTCONTROL, "Invalid listing category '%s", pArg->argv[0]);
     2767
     2768    return rcExit;
     2769}
     2770#endif
    26592771
    26602772/**
     
    27062818                 || !strcmp(pArg->argv[1], "updateadds"))
    27072819            rcExit = handleCtrlUpdateAdditions(guest, &arg);
     2820#ifdef DEBUG
     2821        else if (   !strcmp(pArg->argv[1], "list"))
     2822            rcExit = handleCtrlList(guest, &arg);
     2823#endif
    27082824        /** @todo Implement a "sessions list" command to list all opened
    27092825         *        guest sessions along with their (friendly) names. */
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