Changeset 44959 in vbox
- Timestamp:
- Mar 7, 2013 6:24:50 PM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 84171
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r44885 r44959 556 556 557 557 /* <Missing documentation> */ 558 static inthandleCtrlExecProgram(ComPtr<IGuest> pGuest, HandlerArg *pArg)559 { 560 AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);558 static RTEXITCODE handleCtrlExecProgram(ComPtr<IGuest> pGuest, HandlerArg *pArg) 559 { 560 AssertPtrReturn(pArg, RTEXITCODE_SYNTAX); 561 561 562 562 /* … … 727 727 HRESULT rc = S_OK; 728 728 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()); 739 730 740 731 /** @todo This eventually needs a bit of revamping so that a valid session gets passed … … 754 745 } 755 746 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 756 759 /* Get current time stamp to later calculate rest of timeout left. */ 757 760 uint64_t u64StartMS = RTTimeMilliTS(); 758 761 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()); 796 775 if (FAILED(rc)) 797 776 { 798 ctrlPrintError(p Process, COM_IIDOF(IProcess));799 800 pGuestSession->Close();801 return RTEXITCODE_FAILURE;777 ctrlPrintError(pGuestSession, COM_IIDOF(IGuestSession)); 778 779 rcExit = RTEXITCODE_FAILURE; 780 break; 802 781 } 803 782 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); 810 907 if (FAILED(rc)) 811 908 { 812 909 ctrlPrintError(pProcess, COM_IIDOF(IProcess)); 813 910 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; 823 912 } 824 913 else 825 914 { 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); 829 919 } 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 } 860 921 } 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; 868 928 } 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; 922 943 } 923 944 … … 1807 1828 } 1808 1829 1809 static inthandleCtrlCopy(ComPtr<IGuest> guest, HandlerArg *pArg,1810 bool fHostToGuest)1811 { 1812 AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);1830 static RTEXITCODE handleCtrlCopy(ComPtr<IGuest> guest, HandlerArg *pArg, 1831 bool fHostToGuest) 1832 { 1833 AssertPtrReturn(pArg, RTEXITCODE_SYNTAX); 1813 1834 1814 1835 /** @todo r=bird: This command isn't very unix friendly in general. mkdir … … 2101 2122 } 2102 2123 2103 static inthandleCtrlCreateDirectory(ComPtr<IGuest> pGuest, HandlerArg *pArg)2104 { 2105 AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);2124 static RTEXITCODE handleCtrlCreateDirectory(ComPtr<IGuest> pGuest, HandlerArg *pArg) 2125 { 2126 AssertPtrReturn(pArg, RTEXITCODE_SYNTAX); 2106 2127 2107 2128 /* … … 2206 2227 pGuestSession.asOutParam()); 2207 2228 if (FAILED(hrc)) 2208 return ctrlPrintError(pGuest, COM_IIDOF(IGuest)); 2229 { 2230 ctrlPrintError(pGuest, COM_IIDOF(IGuest)); 2231 return RTEXITCODE_FAILURE; 2232 } 2209 2233 2210 2234 DESTDIRMAPITER it = mapDirs.begin(); … … 2230 2254 } 2231 2255 2232 static inthandleCtrlCreateTemp(ComPtr<IGuest> pGuest, HandlerArg *pArg)2233 { 2234 AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);2256 static RTEXITCODE handleCtrlCreateTemp(ComPtr<IGuest> pGuest, HandlerArg *pArg) 2257 { 2258 AssertPtrReturn(pArg, RTEXITCODE_SYNTAX); 2235 2259 2236 2260 /* … … 2367 2391 pGuestSession.asOutParam()); 2368 2392 if (FAILED(hrc)) 2369 return ctrlPrintError(pGuest, COM_IIDOF(IGuest)); 2393 { 2394 ctrlPrintError(pGuest, COM_IIDOF(IGuest)); 2395 return RTEXITCODE_FAILURE; 2396 } 2370 2397 2371 2398 if (fDirectory) … … 2657 2684 return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; 2658 2685 } 2686 2687 #ifdef DEBUG 2688 static 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 2659 2771 2660 2772 /** … … 2706 2818 || !strcmp(pArg->argv[1], "updateadds")) 2707 2819 rcExit = handleCtrlUpdateAdditions(guest, &arg); 2820 #ifdef DEBUG 2821 else if ( !strcmp(pArg->argv[1], "list")) 2822 rcExit = handleCtrlList(guest, &arg); 2823 #endif 2708 2824 /** @todo Implement a "sessions list" command to list all opened 2709 2825 * guest sessions along with their (friendly) names. */
Note:
See TracChangeset
for help on using the changeset viewer.