Changeset 47557 in vbox for trunk/src/VBox/Frontends/VBoxManage
- Timestamp:
- Aug 6, 2013 11:59:35 AM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 87756
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r47538 r47557 266 266 " list <all|sessions|processes> [--verbose]\n" 267 267 "\n" 268 /** @todo Add an own help group for "session" and "process" sub commands. */ 269 " process kill --session-id <ID>\n" 270 " | --session-name <name or pattern>\n" 271 " [--verbose]\n" 272 " <PID> ... <PID n>\n" 273 "\n" 274 " [p[s]]kill --session-id <ID>\n" 275 " | --session-name <name or pattern>\n" 276 " [--verbose]\n" 277 " <PID> ... <PID n>\n" 278 "\n" 268 279 " session close --session-id <ID>\n" 269 280 " | --session-name <name or pattern>\n" … … 2941 2952 } 2942 2953 2943 static RTEXITCODE handleCtrl SessionClose(ComPtr<IGuest> guest, HandlerArg *pArg)2954 static RTEXITCODE handleCtrlProcessClose(ComPtr<IGuest> guest, HandlerArg *pArg) 2944 2955 { 2945 2956 AssertPtrReturn(pArg, RTEXITCODE_SYNTAX); 2946 2957 2947 2958 if (pArg->argc < 1) 2948 return errorSyntax(USAGE_GUESTCONTROL, "Must specify at least sessionID to close");2959 return errorSyntax(USAGE_GUESTCONTROL, "Must specify at least a PID to close"); 2949 2960 2950 2961 /* … … 2956 2967 static const RTGETOPTDEF s_aOptions[] = 2957 2968 { 2958 { "--all", GETOPTDEF_SESSIONCLOSE_ALL, RTGETOPT_REQ_NOTHING },2959 2969 { "--session-id", 'i', RTGETOPT_REQ_UINT32 }, 2960 { "--session-name", 'n', RTGETOPT_REQ_ UINT32},2970 { "--session-name", 'n', RTGETOPT_REQ_STRING }, 2961 2971 { "--verbose", 'v', RTGETOPT_REQ_NOTHING } 2962 2972 }; … … 2968 2978 s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_OPTS_FIRST); 2969 2979 2980 std::vector < uint32_t > vecPID; 2970 2981 ULONG ulSessionID = UINT32_MAX; 2971 Utf8Str str NamePattern;2982 Utf8Str strSessionName; 2972 2983 bool fVerbose = false; 2973 2984 2974 while ((ch = RTGetOpt(&GetState, &ValueUnion))) 2985 int vrc = VINF_SUCCESS; 2986 2987 while ( (ch = RTGetOpt(&GetState, &ValueUnion)) 2988 && RT_SUCCESS(vrc)) 2975 2989 { 2976 2990 /* For options that require an argument, ValueUnion has received the value. */ 2977 2991 switch (ch) 2978 2992 { 2979 case 'n': /* Session name pattern*/2980 str NamePattern= ValueUnion.psz;2993 case 'n': /* Session name (or pattern) */ 2994 strSessionName = ValueUnion.psz; 2981 2995 break; 2982 2996 … … 2985 2999 break; 2986 3000 2987 /** @todo Add an option for finding all session by a name pattern. */2988 2989 3001 case 'v': /* Verbose */ 2990 3002 fVerbose = true; 2991 3003 break; 2992 3004 2993 case GETOPTDEF_SESSIONCLOSE_ALL:2994 strNamePattern = "*";2995 break;2996 2997 3005 case VINF_GETOPT_NOT_OPTION: 2998 /** @todo Supply a CSV list of IDs or patterns to close? */ 3006 if (pArg->argc == GetState.iNext) 3007 { 3008 /* Treat every else specified as a PID to kill. */ 3009 try 3010 { 3011 uint32_t uPID = RTStrToUInt32(ValueUnion.psz); 3012 if (uPID) /** @todo Is this what we want? If specifying PID 0 3013 this is not going to work on most systems anyway. */ 3014 vecPID.push_back(uPID); 3015 else 3016 vrc = VERR_INVALID_PARAMETER; 3017 } 3018 catch(std::bad_alloc &) 3019 { 3020 vrc = VERR_NO_MEMORY; 3021 } 3022 } 2999 3023 break; 3000 3024 … … 3004 3028 } 3005 3029 3006 if ( strNamePattern.isEmpty() 3007 && ulSessionID == UINT32_MAX) 3030 if (vecPID.empty()) 3031 return errorSyntax(USAGE_GUESTCONTROL, "At least one PID must be specified to kill!"); 3032 else if ( strSessionName.isEmpty() 3033 && ulSessionID == UINT32_MAX) 3008 3034 { 3009 3035 return errorSyntax(USAGE_GUESTCONTROL, "No session ID specified!"); 3010 3036 } 3011 else if ( !str NamePattern.isEmpty()3037 else if ( !strSessionName.isEmpty() 3012 3038 && ulSessionID != UINT32_MAX) 3013 3039 { … … 3015 3041 } 3016 3042 3043 if (RT_FAILURE(vrc)) 3044 return errorSyntax(USAGE_GUESTCONTROL, "Invalid parameters specified"); 3045 3017 3046 HRESULT rc = S_OK; 3018 3047 3019 3048 ComPtr<IGuestSession> pSession; 3049 ComPtr<IGuestProcess> pProcess; 3020 3050 do 3021 3051 { … … 3037 3067 Utf8Str strNameUtf8(strName); /* Session name */ 3038 3068 3039 if (str NamePattern.isEmpty()) /* Search by ID. Slow lookup. */3069 if (strSessionName.isEmpty()) /* Search by ID. Slow lookup. */ 3040 3070 { 3041 3071 fSessionFound = uID == ulSessionID; … … 3043 3073 else /* ... or by naming pattern. */ 3044 3074 { 3045 if (RTStrSimplePatternMatch(strNamePattern.c_str(), strNameUtf8.c_str())) 3075 if (RTStrSimplePatternMatch(strSessionName.c_str(), strNameUtf8.c_str())) 3076 fSessionFound = true; 3077 } 3078 3079 if (fSessionFound) 3080 { 3081 Assert(!pSession.isNull()); 3082 3083 SafeIfaceArray <IGuestProcess> collProcs; 3084 CHECK_ERROR_BREAK(pSession, COMGETTER(Processes)(ComSafeArrayAsOutParam(collProcs))); 3085 3086 size_t cProcs = collProcs.size(); 3087 for (size_t p = 0; p < cProcs; p++) 3088 { 3089 pProcess = collProcs[p]; 3090 Assert(!pProcess.isNull()); 3091 3092 ULONG uPID; /* Process ID */ 3093 CHECK_ERROR_BREAK(pProcess, COMGETTER(PID)(&uPID)); 3094 3095 bool fProcFound = false; 3096 for (size_t a = 0; a < vecPID.size(); a++) /* Slow, but works. */ 3097 { 3098 fProcFound = vecPID[a] == uPID; 3099 if (fProcFound) 3100 break; 3101 } 3102 3103 if (fProcFound) 3104 { 3105 if (fVerbose) 3106 RTPrintf("Terminating process PID=%RU32 (session ID=%RU32) ...\n", 3107 uPID, uID); 3108 CHECK_ERROR_BREAK(pProcess, Terminate()); 3109 } 3110 3111 pProcess.setNull(); 3112 } 3113 3114 pSession.setNull(); 3115 } 3116 } 3117 3118 if (!fSessionFound) 3119 { 3120 RTPrintf("No guest session(s) found\n"); 3121 rc = E_ABORT; /* To set exit code accordingly. */ 3122 } 3123 3124 } while (0); 3125 3126 pProcess.setNull(); 3127 pSession.setNull(); 3128 3129 return SUCCEEDED(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; 3130 } 3131 3132 static RTEXITCODE handleCtrlProcess(ComPtr<IGuest> guest, HandlerArg *pArg) 3133 { 3134 AssertPtrReturn(pArg, RTEXITCODE_SYNTAX); 3135 3136 if (pArg->argc < 1) 3137 return errorSyntax(USAGE_GUESTCONTROL, "Must specify an action"); 3138 3139 /** Use RTGetOpt here when handling command line args gets more complex. */ 3140 3141 HandlerArg argSub = *pArg; 3142 argSub.argc = pArg->argc - 1; /* Skip session action. */ 3143 argSub.argv = pArg->argv + 1; /* Same here. */ 3144 3145 if ( !RTStrICmp(pArg->argv[0], "close") 3146 || !RTStrICmp(pArg->argv[0], "kill") 3147 || !RTStrICmp(pArg->argv[0], "terminate")) 3148 { 3149 return handleCtrlProcessClose(guest, &argSub); 3150 } 3151 3152 return errorSyntax(USAGE_GUESTCONTROL, "Invalid process action '%s'", pArg->argv[0]); 3153 } 3154 3155 static RTEXITCODE handleCtrlSessionClose(ComPtr<IGuest> guest, HandlerArg *pArg) 3156 { 3157 AssertPtrReturn(pArg, RTEXITCODE_SYNTAX); 3158 3159 if (pArg->argc < 1) 3160 return errorSyntax(USAGE_GUESTCONTROL, "Must specify at least a session ID to close"); 3161 3162 /* 3163 * Parse arguments. 3164 * 3165 * Note! No direct returns here, everyone must go thru the cleanup at the 3166 * end of this function. 3167 */ 3168 static const RTGETOPTDEF s_aOptions[] = 3169 { 3170 { "--all", GETOPTDEF_SESSIONCLOSE_ALL, RTGETOPT_REQ_NOTHING }, 3171 { "--session-id", 'i', RTGETOPT_REQ_UINT32 }, 3172 { "--session-name", 'n', RTGETOPT_REQ_STRING }, 3173 { "--verbose", 'v', RTGETOPT_REQ_NOTHING } 3174 }; 3175 3176 int ch; 3177 RTGETOPTUNION ValueUnion; 3178 RTGETOPTSTATE GetState; 3179 RTGetOptInit(&GetState, pArg->argc, pArg->argv, 3180 s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_OPTS_FIRST); 3181 3182 ULONG ulSessionID = UINT32_MAX; 3183 Utf8Str strSessionName; 3184 bool fVerbose = false; 3185 3186 while ((ch = RTGetOpt(&GetState, &ValueUnion))) 3187 { 3188 /* For options that require an argument, ValueUnion has received the value. */ 3189 switch (ch) 3190 { 3191 case 'n': /* Session name pattern */ 3192 strSessionName = ValueUnion.psz; 3193 break; 3194 3195 case 'i': /* Session ID */ 3196 ulSessionID = ValueUnion.u32; 3197 break; 3198 3199 case 'v': /* Verbose */ 3200 fVerbose = true; 3201 break; 3202 3203 case GETOPTDEF_SESSIONCLOSE_ALL: 3204 strSessionName = "*"; 3205 break; 3206 3207 case VINF_GETOPT_NOT_OPTION: 3208 /** @todo Supply a CSV list of IDs or patterns to close? */ 3209 break; 3210 3211 default: 3212 return RTGetOptPrintError(ch, &ValueUnion); 3213 } 3214 } 3215 3216 if ( strSessionName.isEmpty() 3217 && ulSessionID == UINT32_MAX) 3218 { 3219 return errorSyntax(USAGE_GUESTCONTROL, "No session ID specified!"); 3220 } 3221 else if ( !strSessionName.isEmpty() 3222 && ulSessionID != UINT32_MAX) 3223 { 3224 return errorSyntax(USAGE_GUESTCONTROL, "Either session ID or name (pattern) must be specified"); 3225 } 3226 3227 HRESULT rc = S_OK; 3228 3229 ComPtr<IGuestSession> pSession; 3230 do 3231 { 3232 bool fSessionFound = false; 3233 3234 SafeIfaceArray <IGuestSession> collSessions; 3235 CHECK_ERROR_BREAK(guest, COMGETTER(Sessions)(ComSafeArrayAsOutParam(collSessions))); 3236 size_t cSessions = collSessions.size(); 3237 3238 for (size_t i = 0; i < cSessions; i++) 3239 { 3240 pSession = collSessions[i]; 3241 Assert(!pSession.isNull()); 3242 3243 ULONG uID; /* Session ID */ 3244 CHECK_ERROR_BREAK(pSession, COMGETTER(Id)(&uID)); 3245 Bstr strName; 3246 CHECK_ERROR_BREAK(pSession, COMGETTER(Name)(strName.asOutParam())); 3247 Utf8Str strNameUtf8(strName); /* Session name */ 3248 3249 if (strSessionName.isEmpty()) /* Search by ID. Slow lookup. */ 3250 { 3251 fSessionFound = uID == ulSessionID; 3252 } 3253 else /* ... or by naming pattern. */ 3254 { 3255 if (RTStrSimplePatternMatch(strSessionName.c_str(), strNameUtf8.c_str())) 3046 3256 fSessionFound = true; 3047 3257 } … … 3138 3348 || !RTStrICmp(pArg->argv[1], "mktemp")) 3139 3349 rcExit = handleCtrlCreateTemp(guest, &arg); 3350 else if ( !RTStrICmp(pArg->argv[1], "kill") /* Linux. */ 3351 || !RTStrICmp(pArg->argv[1], "pkill") /* Solaris / *BSD. */ 3352 || !RTStrICmp(pArg->argv[1], "pskill")) /* SysInternals version. */ 3353 { 3354 /** @todo What about "taskkill" on Windows? */ 3355 rcExit = handleCtrlProcessClose(guest, &arg); 3356 } 3357 /** @todo Implement "killall"? */ 3140 3358 else if ( !RTStrICmp(pArg->argv[1], "stat")) 3141 3359 rcExit = handleCtrlStat(guest, &arg); … … 3147 3365 else if ( !RTStrICmp(pArg->argv[1], "session")) 3148 3366 rcExit = handleCtrlSession(guest, &arg); 3367 else if ( !RTStrICmp(pArg->argv[1], "process")) 3368 rcExit = handleCtrlProcess(guest, &arg); 3149 3369 else 3150 3370 rcExit = errorSyntax(USAGE_GUESTCONTROL, "Unknown sub command '%s' specified!", pArg->argv[1]);
Note:
See TracChangeset
for help on using the changeset viewer.