VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp@ 92372

最後變更 在這個檔案從92372是 92372,由 vboxsync 提交於 3 年 前

Main: bugref:1909: Added translation marks around messages of VBoxManage output

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 48.8 KB
 
1/* $Id: VBoxManageHelp.cpp 92372 2021-11-11 14:45:18Z vboxsync $ */
2/** @file
3 * VBoxManage - help and other message output.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <VBox/version.h>
23
24#include <iprt/buildconfig.h>
25#include <iprt/ctype.h>
26#include <iprt/assert.h>
27#include <iprt/env.h>
28#include <iprt/err.h>
29#include <iprt/getopt.h>
30#include <iprt/stream.h>
31#include <iprt/message.h>
32
33#include "VBoxManage.h"
34
35
36/*********************************************************************************************************************************
37* Defined Constants And Macros *
38*********************************************************************************************************************************/
39/** If the usage is the given number of length long or longer, the error is
40 * repeated so the user can actually see it. */
41#define ERROR_REPEAT_AFTER_USAGE_LENGTH 16
42
43
44/*********************************************************************************************************************************
45* Global Variables *
46*********************************************************************************************************************************/
47DECLARE_TRANSLATION_CONTEXT(Help);
48
49#ifndef VBOX_ONLY_DOCS
50static enum HELP_CMD_VBOXMANAGE g_enmCurCommand = HELP_CMD_VBOXMANAGE_INVALID;
51/** The scope mask for the current subcommand. */
52static uint64_t g_fCurSubcommandScope = RTMSGREFENTRYSTR_SCOPE_GLOBAL;
53
54/**
55 * Sets the current command.
56 *
57 * This affects future calls to error and help functions.
58 *
59 * @param enmCommand The command.
60 */
61void setCurrentCommand(enum HELP_CMD_VBOXMANAGE enmCommand)
62{
63 Assert(g_enmCurCommand == HELP_CMD_VBOXMANAGE_INVALID);
64 g_enmCurCommand = enmCommand;
65 g_fCurSubcommandScope = RTMSGREFENTRYSTR_SCOPE_GLOBAL;
66}
67
68
69/**
70 * Sets the current subcommand.
71 *
72 * This affects future calls to error and help functions.
73 *
74 * @param fSubcommandScope The subcommand scope.
75 */
76void setCurrentSubcommand(uint64_t fSubcommandScope)
77{
78 g_fCurSubcommandScope = fSubcommandScope;
79}
80
81
82
83
84/**
85 * Prints brief help for a command or subcommand.
86 *
87 * @returns Number of lines written.
88 * @param enmCommand The command.
89 * @param fSubcommandScope The subcommand scope, REFENTRYSTR_SCOPE_GLOBAL
90 * for all.
91 * @param pStrm The output stream.
92 */
93static uint32_t printBriefCommandOrSubcommandHelp(enum HELP_CMD_VBOXMANAGE enmCommand, uint64_t fSubcommandScope, PRTSTREAM pStrm)
94{
95 uint32_t cLinesWritten = 0;
96 uint32_t cPendingBlankLines = 0;
97 uint32_t cFound = 0;
98 for (uint32_t i = 0; i < g_cHelpEntries; i++)
99 {
100 PCRTMSGREFENTRY pHelp = g_apHelpEntries[i];
101 if (pHelp->idInternal == (int64_t)enmCommand)
102 {
103 cFound++;
104 if (cFound == 1)
105 {
106 if (fSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL)
107 RTStrmPrintf(pStrm, Help::tr("Usage - %c%s:\n"), RT_C_TO_UPPER(pHelp->pszBrief[0]), pHelp->pszBrief + 1);
108 else
109 RTStrmPrintf(pStrm, Help::tr("Usage:\n"));
110 }
111 RTMsgRefEntryPrintStringTable(pStrm, &pHelp->Synopsis, fSubcommandScope, &cPendingBlankLines, &cLinesWritten);
112 if (!cPendingBlankLines)
113 cPendingBlankLines = 1;
114 }
115 }
116 Assert(cFound > 0);
117 return cLinesWritten;
118}
119
120
121/**
122 * Prints the brief usage information for the current (sub)command.
123 *
124 * @param pStrm The output stream.
125 */
126void printUsage(PRTSTREAM pStrm)
127{
128 printBriefCommandOrSubcommandHelp(g_enmCurCommand, g_fCurSubcommandScope, pStrm);
129}
130
131
132/**
133 * Prints full help for a command or subcommand.
134 *
135 * @param enmCommand The command.
136 * @param fSubcommandScope The subcommand scope, REFENTRYSTR_SCOPE_GLOBAL
137 * for all.
138 * @param pStrm The output stream.
139 */
140static void printFullCommandOrSubcommandHelp(enum HELP_CMD_VBOXMANAGE enmCommand, uint64_t fSubcommandScope, PRTSTREAM pStrm)
141{
142 uint32_t cPendingBlankLines = 0;
143 uint32_t cFound = 0;
144 for (uint32_t i = 0; i < g_cHelpEntries; i++)
145 {
146 PCRTMSGREFENTRY pHelp = g_apHelpEntries[i];
147 if ( pHelp->idInternal == (int64_t)enmCommand
148 || enmCommand == HELP_CMD_VBOXMANAGE_INVALID)
149 {
150 cFound++;
151 RTMsgRefEntryPrintStringTable(pStrm, &pHelp->Help, fSubcommandScope, &cPendingBlankLines, NULL /*pcLinesWritten*/);
152 if (cPendingBlankLines < 2)
153 cPendingBlankLines = 2;
154 }
155 }
156 Assert(cFound > 0);
157}
158
159
160/**
161 * Prints the full help for the current (sub)command.
162 *
163 * @param pStrm The output stream.
164 */
165void printHelp(PRTSTREAM pStrm)
166{
167 printFullCommandOrSubcommandHelp(g_enmCurCommand, g_fCurSubcommandScope, pStrm);
168}
169
170
171/**
172 * Display no subcommand error message and current command usage.
173 *
174 * @returns RTEXITCODE_SYNTAX.
175 */
176RTEXITCODE errorNoSubcommand(void)
177{
178 Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID);
179 Assert(g_fCurSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL);
180
181 return errorSyntax(Help::tr("No subcommand specified"));
182}
183
184
185/**
186 * Display unknown subcommand error message and current command usage.
187 *
188 * May show full command help instead if the subcommand is a common help option.
189 *
190 * @returns RTEXITCODE_SYNTAX, or RTEXITCODE_SUCCESS if common help option.
191 * @param pszSubcommand The name of the alleged subcommand.
192 */
193RTEXITCODE errorUnknownSubcommand(const char *pszSubcommand)
194{
195 Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID);
196 Assert(g_fCurSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL);
197
198 /* check if help was requested. */
199 if ( strcmp(pszSubcommand, "--help") == 0
200 || strcmp(pszSubcommand, "-h") == 0
201 || strcmp(pszSubcommand, "-?") == 0)
202 {
203 printFullCommandOrSubcommandHelp(g_enmCurCommand, g_fCurSubcommandScope, g_pStdOut);
204 return RTEXITCODE_SUCCESS;
205 }
206
207 return errorSyntax(Help::tr("Unknown subcommand: %s"), pszSubcommand);
208}
209
210
211/**
212 * Display too many parameters error message and current command usage.
213 *
214 * May show full command help instead if the subcommand is a common help option.
215 *
216 * @returns RTEXITCODE_SYNTAX, or RTEXITCODE_SUCCESS if common help option.
217 * @param papszArgs The first unwanted parameter. Terminated by
218 * NULL entry.
219 */
220RTEXITCODE errorTooManyParameters(char **papszArgs)
221{
222 Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID);
223 Assert(g_fCurSubcommandScope != RTMSGREFENTRYSTR_SCOPE_GLOBAL);
224
225 /* check if help was requested. */
226 if (papszArgs)
227 {
228 for (uint32_t i = 0; papszArgs[i]; i++)
229 if ( strcmp(papszArgs[i], "--help") == 0
230 || strcmp(papszArgs[i], "-h") == 0
231 || strcmp(papszArgs[i], "-?") == 0)
232 {
233 printFullCommandOrSubcommandHelp(g_enmCurCommand, g_fCurSubcommandScope, g_pStdOut);
234 return RTEXITCODE_SUCCESS;
235 }
236 else if (!strcmp(papszArgs[i], "--"))
237 break;
238 }
239
240 return errorSyntax(Help::tr("Too many parameters"));
241}
242
243
244/**
245 * Display current (sub)command usage and the custom error message.
246 *
247 * @returns RTEXITCODE_SYNTAX.
248 * @param pszFormat Custom error message format string.
249 * @param ... Format arguments.
250 */
251RTEXITCODE errorSyntax(const char *pszFormat, ...)
252{
253 Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID);
254
255 showLogo(g_pStdErr);
256
257 va_list va;
258 va_start(va, pszFormat);
259 RTMsgErrorV(pszFormat, va);
260 va_end(va);
261
262 RTStrmPutCh(g_pStdErr, '\n');
263 if ( printBriefCommandOrSubcommandHelp(g_enmCurCommand, g_fCurSubcommandScope, g_pStdErr)
264 >= ERROR_REPEAT_AFTER_USAGE_LENGTH)
265 {
266 /* Usage was very long, repeat the error message. */
267 RTStrmPutCh(g_pStdErr, '\n');
268 va_start(va, pszFormat);
269 RTMsgErrorV(pszFormat, va);
270 va_end(va);
271 }
272 return RTEXITCODE_SYNTAX;
273}
274
275
276/**
277 * Worker for errorGetOpt.
278 *
279 * @param rcGetOpt The RTGetOpt return value.
280 * @param pValueUnion The value union returned by RTGetOpt.
281 */
282static void errorGetOptWorker(int rcGetOpt, union RTGETOPTUNION const *pValueUnion)
283{
284 if (rcGetOpt == VINF_GETOPT_NOT_OPTION)
285 RTMsgError(Help::tr("Invalid parameter '%s'"), pValueUnion->psz);
286 else if (rcGetOpt > 0)
287 {
288 if (RT_C_IS_PRINT(rcGetOpt))
289 RTMsgError(Help::tr("Invalid option -%c"), rcGetOpt);
290 else
291 RTMsgError(Help::tr("Invalid option case %i"), rcGetOpt);
292 }
293 else if (rcGetOpt == VERR_GETOPT_UNKNOWN_OPTION)
294 RTMsgError(Help::tr("Unknown option: %s"), pValueUnion->psz);
295 else if (rcGetOpt == VERR_GETOPT_INVALID_ARGUMENT_FORMAT)
296 RTMsgError(Help::tr("Invalid argument format: %s"), pValueUnion->psz);
297 else if (pValueUnion->pDef)
298 RTMsgError("%s: %Rrs", pValueUnion->pDef->pszLong, rcGetOpt);
299 else
300 RTMsgError("%Rrs", rcGetOpt);
301}
302
303
304/**
305 * For use to deal with RTGetOptFetchValue failures.
306 *
307 * @retval RTEXITCODE_SYNTAX
308 * @param iValueNo The value number being fetched, counting the
309 * RTGetOpt value as zero and the first
310 * RTGetOptFetchValue call as one.
311 * @param pszOption The option being parsed.
312 * @param rcGetOptFetchValue The status returned by RTGetOptFetchValue.
313 * @param pValueUnion The value union returned by the fetch.
314 */
315RTEXITCODE errorFetchValue(int iValueNo, const char *pszOption, int rcGetOptFetchValue, union RTGETOPTUNION const *pValueUnion)
316{
317 Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID);
318 showLogo(g_pStdErr);
319 if (rcGetOptFetchValue == VERR_GETOPT_REQUIRED_ARGUMENT_MISSING)
320 RTMsgError(Help::tr("Missing the %u%s value for option %s"),
321 iValueNo,
322 iValueNo == 1 ? Help::tr("st")
323 : iValueNo == 2 ? Help::tr("nd")
324 : iValueNo == 3 ? Help::tr("rd")
325 : Help::tr("th"),
326 pszOption);
327 else
328 errorGetOptWorker(rcGetOptFetchValue, pValueUnion);
329 return RTEXITCODE_SYNTAX;
330
331}
332
333
334/**
335 * Handled an RTGetOpt error or common option.
336 *
337 * This implements the 'V' and 'h' cases. It reports appropriate syntax errors
338 * for other @a rcGetOpt values.
339 *
340 * @retval RTEXITCODE_SUCCESS if help or version request.
341 * @retval RTEXITCODE_SYNTAX if not help or version request.
342 * @param rcGetOpt The RTGetOpt return value.
343 * @param pValueUnion The value union returned by RTGetOpt.
344 */
345RTEXITCODE errorGetOpt(int rcGetOpt, union RTGETOPTUNION const *pValueUnion)
346{
347 Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID);
348
349 /*
350 * Check if it is an unhandled standard option.
351 */
352 if (rcGetOpt == 'V')
353 {
354 RTPrintf("%sr%d\n", VBOX_VERSION_STRING, RTBldCfgRevision());
355 return RTEXITCODE_SUCCESS;
356 }
357
358 if (rcGetOpt == 'h')
359 {
360 printFullCommandOrSubcommandHelp(g_enmCurCommand, g_fCurSubcommandScope, g_pStdOut);
361 return RTEXITCODE_SUCCESS;
362 }
363
364 /*
365 * We failed.
366 */
367 showLogo(g_pStdErr);
368 errorGetOptWorker(rcGetOpt, pValueUnion);
369 if ( printBriefCommandOrSubcommandHelp(g_enmCurCommand, g_fCurSubcommandScope, g_pStdErr)
370 >= ERROR_REPEAT_AFTER_USAGE_LENGTH)
371 {
372 /* Usage was very long, repeat the error message. */
373 RTStrmPutCh(g_pStdErr, '\n');
374 errorGetOptWorker(rcGetOpt, pValueUnion);
375 }
376 return RTEXITCODE_SYNTAX;
377}
378
379#endif /* !VBOX_ONLY_DOCS */
380
381
382
383void showLogo(PRTSTREAM pStrm)
384{
385 static bool s_fShown; /* show only once */
386
387 if (!s_fShown)
388 {
389 RTStrmPrintf(pStrm, VBOX_PRODUCT " Command Line Management Interface Version "
390 VBOX_VERSION_STRING "\n"
391 "(C) 2005-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
392 "All rights reserved.\n"
393 "\n");
394 s_fShown = true;
395 }
396}
397
398
399
400
401void printUsage(USAGECATEGORY enmCommand, uint64_t fSubcommandScope, PRTSTREAM pStrm)
402{
403 bool fDumpOpts = false;
404#ifdef RT_OS_LINUX
405 bool fLinux = true;
406#else
407 bool fLinux = false;
408#endif
409#ifdef RT_OS_WINDOWS
410 bool fWin = true;
411#else
412 bool fWin = false;
413#endif
414#ifdef RT_OS_SOLARIS
415 bool fSolaris = true;
416#else
417 bool fSolaris = false;
418#endif
419#ifdef RT_OS_FREEBSD
420 bool fFreeBSD = true;
421#else
422 bool fFreeBSD = false;
423#endif
424#ifdef RT_OS_DARWIN
425 bool fDarwin = true;
426#else
427 bool fDarwin = false;
428#endif
429#ifdef VBOX_WITH_VBOXSDL
430 bool fVBoxSDL = true;
431#else
432 bool fVBoxSDL = false;
433#endif
434
435 Assert(enmCommand != USAGE_INVALID);
436 Assert(enmCommand != USAGE_S_NEWCMD);
437
438 if (enmCommand == USAGE_S_DUMPOPTS)
439 {
440 fDumpOpts = true;
441 fLinux = true;
442 fWin = true;
443 fSolaris = true;
444 fFreeBSD = true;
445 fDarwin = true;
446 fVBoxSDL = true;
447 enmCommand = USAGE_S_ALL;
448 }
449
450 RTStrmPrintf(pStrm,
451 Help::tr("Usage:\n"
452 "\n"));
453
454 if (enmCommand == USAGE_S_ALL)
455 RTStrmPrintf(pStrm,
456 Help::tr(
457 " VBoxManage [<general option>] <command>\n"
458 "\n"
459 "\n"
460 "General Options:\n"
461 "\n"
462 " [-V|--version] print version number and exit\n"
463 " [--dump-build-type] print build type and exit\n"
464 " [-q|--nologo] suppress the logo\n"
465 " [--settingspw <pw>] provide the settings password\n"
466 " [--settingspwfile <file>] provide a file containing the settings password\n"
467 " [@<response-file>] load arguments from the given response file (bourne style)\n"
468 "\n"
469 "\n"
470 "Commands:\n"
471 "\n"));
472
473 const char *pcszSep1 = " ";
474 const char *pcszSep2 = " ";
475 if (enmCommand != USAGE_S_ALL)
476 {
477 pcszSep1 = "VBoxManage";
478 pcszSep2 = "";
479 }
480
481#define SEP pcszSep1, pcszSep2
482
483 if (enmCommand == USAGE_STARTVM || enmCommand == USAGE_S_ALL)
484 {
485 RTStrmPrintf(pStrm,
486 Help::tr(
487 "%s startvm %s <uuid|vmname>...\n"
488 " [--type gui"), SEP);
489 if (fVBoxSDL)
490 RTStrmPrintf(pStrm, "|sdl");
491 RTStrmPrintf(pStrm, "|headless|separate]\n");
492 RTStrmPrintf(pStrm,
493 Help::tr(
494 " [-E|--putenv <NAME>[=<VALUE>]]\n"
495 "\n"));
496 }
497
498 if (enmCommand == USAGE_CONTROLVM || enmCommand == USAGE_S_ALL)
499 {
500 RTStrmPrintf(pStrm,
501 Help::tr(
502 "%s controlvm %s <uuid|vmname>\n"
503 " pause|resume|reset|poweroff|savestate|\n"), SEP);
504#ifdef VBOX_WITH_GUEST_CONTROL
505 RTStrmPrintf(pStrm,
506 " reboot|shutdown [--force]|\n");
507#endif
508 RTStrmPrintf(pStrm,
509 Help::tr(
510 " acpipowerbutton|acpisleepbutton|\n"
511 " keyboardputscancode <hex> [<hex> ...]|\n"
512 " keyboardputstring <string1> [<string2> ...]|\n"
513 " keyboardputfile <filename>|\n"
514 " setlinkstate<1-N> on|off |\n"));
515#if defined(VBOX_WITH_NETFLT)
516 RTStrmPrintf(pStrm,
517 Help::tr(
518 " nic<1-N> null|nat|bridged|intnet|hostonly|generic|\n"
519 " natnetwork [<devicename>] |\n"));
520#else /* !VBOX_WITH_NETFLT */
521 RTStrmPrintf(pStrm,
522 Help::tr(
523 " nic<1-N> null|nat|bridged|intnet|generic|natnetwork\n"
524 " [<devicename>] |\n"));
525#endif /* !VBOX_WITH_NETFLT */
526 RTStrmPrintf(pStrm,
527 Help::tr(
528 " nictrace<1-N> on|off |\n"
529 " nictracefile<1-N> <filename> |\n"
530 " nicproperty<1-N> name=[value] |\n"
531 " nicpromisc<1-N> deny|allow-vms|allow-all |\n"
532 " natpf<1-N> [<rulename>],tcp|udp,[<hostip>],\n"
533 " <hostport>,[<guestip>],<guestport> |\n"
534 " natpf<1-N> delete <rulename> |\n"
535 " guestmemoryballoon <balloonsize in MB> |\n"
536 " usbattach <uuid>|<address>\n"
537 " [--capturefile <filename>] |\n"
538 " usbdetach <uuid>|<address> |\n"
539 " audioin on|off |\n"
540 " audioout on|off |\n"));
541#ifdef VBOX_WITH_SHARED_CLIPBOARD
542 RTStrmPrintf(pStrm,
543 " clipboard mode disabled|hosttoguest|guesttohost|\n"
544 " bidirectional |\n");
545# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
546 RTStrmPrintf(pStrm,
547 " clipboard filetransfers enabled|disabled |\n");
548# endif
549#endif
550 RTStrmPrintf(pStrm,
551 Help::tr(
552 " draganddrop disabled|hosttoguest|guesttohost|\n"
553 " bidirectional |\n"
554 " vrde on|off |\n"
555 " vrdeport <port> |\n"
556 " vrdeproperty <name=[value]> |\n"
557 " vrdevideochannelquality <percent> |\n"
558 " setvideomodehint <xres> <yres> <bpp>\n"
559 " [[<display>] [<enabled:yes|no> |\n"
560 " [<xorigin> <yorigin>]]] |\n"
561 " setscreenlayout <display> on|primary <xorigin> <yorigin> <xres> <yres> <bpp> | off\n"
562 " screenshotpng <file> [display] |\n"));
563#ifdef VBOX_WITH_RECORDING
564 RTStrmPrintf(pStrm,
565 Help::tr(
566 " recording on|off |\n"
567 " recording screens all|none|<screen>,[<screen>...] |\n"
568 " recording filename <file> |\n"
569 " recording videores <width>x<height> |\n"
570 " recording videorate <rate> |\n"
571 " recording videofps <fps> |\n"
572 " recording maxtime <s> |\n"
573 " recording maxfilesize <MB> |\n"));
574#endif /* VBOX_WITH_RECORDING */
575 RTStrmPrintf(pStrm,
576 Help::tr(
577 " setcredentials <username>\n"
578 " --passwordfile <file> | <password>\n"
579 " <domain>\n"
580 " [--allowlocallogon <yes|no>] |\n"
581 " teleport --host <name> --port <port>\n"
582 " [--maxdowntime <msec>]\n"
583 " [--passwordfile <file> |\n"
584 " --password <password>] |\n"
585 " plugcpu <id> |\n"
586 " unplugcpu <id> |\n"
587 " cpuexecutioncap <1-100>\n"
588 " webcam <attach [path [settings]]> | <detach [path]> | <list>\n"
589 " addencpassword <id>\n"
590 " <password file>|-\n"
591 " [--removeonsuspend <yes|no>]\n"
592 " removeencpassword <id>\n"
593 " removeallencpasswords\n"
594 " changeuartmode<1-N> disconnected|\n"
595 " server <pipe>|\n"
596 " client <pipe>|\n"
597 " tcpserver <port>|\n"
598 " tcpclient <hostname:port>|\n"
599 " file <file>|\n"
600 " <devicename>\n"
601 " vm-process-priority default|flat|low|normal|high\n"
602 " autostart-enabled on|off\n"
603 " autostart-delay <seconds>\n"
604 "\n"));
605 }
606
607 if (enmCommand == USAGE_DISCARDSTATE || enmCommand == USAGE_S_ALL)
608 RTStrmPrintf(pStrm,
609 Help::tr(
610 "%s discardstate %s <uuid|vmname>\n"
611 "\n"), SEP);
612
613 if (enmCommand == USAGE_ADOPTSTATE || enmCommand == USAGE_S_ALL)
614 RTStrmPrintf(pStrm,
615 Help::tr(
616 "%s adoptstate %s <uuid|vmname> <state_file>\n"
617 "\n"), SEP);
618
619 if (enmCommand == USAGE_CLOSEMEDIUM || enmCommand == USAGE_S_ALL)
620 RTStrmPrintf(pStrm,
621 Help::tr(
622 "%s closemedium %s [disk|dvd|floppy] <uuid|filename>\n"
623 " [--delete]\n"
624 "\n"), SEP);
625
626 if (enmCommand == USAGE_STORAGEATTACH || enmCommand == USAGE_S_ALL)
627 RTStrmPrintf(pStrm,
628 Help::tr(
629 "%s storageattach %s <uuid|vmname>\n"
630 " --storagectl <name>\n"
631 " [--port <number>]\n"
632 " [--device <number>]\n"
633 " [--type dvddrive|hdd|fdd]\n"
634 " [--medium none|emptydrive|additions|\n"
635 " <uuid|filename>|host:<drive>|iscsi]\n"
636 " [--mtype normal|writethrough|immutable|shareable|\n"
637 " readonly|multiattach]\n"
638 " [--comment <text>]\n"
639 " [--setuuid <uuid>]\n"
640 " [--setparentuuid <uuid>]\n"
641 " [--passthrough on|off]\n"
642 " [--tempeject on|off]\n"
643 " [--nonrotational on|off]\n"
644 " [--discard on|off]\n"
645 " [--hotpluggable on|off]\n"
646 " [--bandwidthgroup <name>]\n"
647 " [--forceunmount]\n"
648 " [--server <name>|<ip>]\n"
649 " [--target <target>]\n"
650 " [--tport <port>]\n"
651 " [--lun <lun>]\n"
652 " [--encodedlun <lun>]\n"
653 " [--username <username>]\n"
654 " [--password <password>]\n"
655 " [--passwordfile <file>]\n"
656 " [--initiator <initiator>]\n"
657 " [--intnet]\n"
658 "\n"), SEP);
659
660 if (enmCommand == USAGE_STORAGECONTROLLER || enmCommand == USAGE_S_ALL)
661 RTStrmPrintf(pStrm,
662 Help::tr(
663 "%s storagectl %s <uuid|vmname>\n"
664 " --name <name>\n"
665 " [--add ide|sata|scsi|floppy|sas|usb|pcie|virtio]\n"
666 " [--controller LSILogic|LSILogicSAS|BusLogic|\n"
667 " IntelAHCI|PIIX3|PIIX4|ICH6|I82078|\n"
668 " [ USB|NVMe|VirtIO]\n"
669 " [--portcount <1-n>]\n"
670 " [--hostiocache on|off]\n"
671 " [--bootable on|off]\n"
672 " [--rename <name>]\n"
673 " [--remove]\n"
674 "\n"), SEP);
675
676 if (enmCommand == USAGE_BANDWIDTHCONTROL || enmCommand == USAGE_S_ALL)
677 RTStrmPrintf(pStrm,
678 Help::tr(
679 "%s bandwidthctl %s <uuid|vmname>\n"
680 " add <name> --type disk|network\n"
681 " --limit <megabytes per second>[k|m|g|K|M|G] |\n"
682 " set <name>\n"
683 " --limit <megabytes per second>[k|m|g|K|M|G] |\n"
684 " remove <name> |\n"
685 " list [--machinereadable]\n"
686 " (limit units: k=kilobit, m=megabit, g=gigabit,\n"
687 " K=kilobyte, M=megabyte, G=gigabyte)\n"
688 "\n"), SEP);
689
690 if (enmCommand == USAGE_SHOWMEDIUMINFO || enmCommand == USAGE_S_ALL)
691 RTStrmPrintf(pStrm,
692 Help::tr(
693 "%s showmediuminfo %s [disk|dvd|floppy] <uuid|filename>\n"
694 "\n"), SEP);
695
696 if (enmCommand == USAGE_CREATEMEDIUM || enmCommand == USAGE_S_ALL)
697 RTStrmPrintf(pStrm,
698 Help::tr(
699 "%s createmedium %s [disk|dvd|floppy] --filename <filename>\n"
700 " [--size <megabytes>|--sizebyte <bytes>]\n"
701 " [--diffparent <uuid>|<filename>]\n"
702 " [--format VDI|VMDK|VHD] (default: VDI)]\n"
703 " [--variant Standard,Fixed,Split2G,Stream,ESX,\n"
704 " Formatted,RawDisk]\n"
705 " [[--property <name>=<value>] --property <name>=<value>\n"
706 " --property-file <name>=</path/to/file/with/value>]...\n"
707 "\n"), SEP);
708
709 if (enmCommand == USAGE_MODIFYMEDIUM || enmCommand == USAGE_S_ALL)
710 RTStrmPrintf(pStrm,
711 Help::tr(
712 "%s modifymedium %s [disk|dvd|floppy] <uuid|filename>\n"
713 " [--type normal|writethrough|immutable|shareable|\n"
714 " readonly|multiattach]\n"
715 " [--autoreset on|off]\n"
716 " [--property <name=[value]>]\n"
717 " [--compact]\n"
718 " [--resize <megabytes>|--resizebyte <bytes>]\n"
719 " [--move <path>]\n"
720 " [--setlocation <path>]\n"
721 " [--description <description string>]"
722 "\n"), SEP);
723
724 if (enmCommand == USAGE_CLONEMEDIUM || enmCommand == USAGE_S_ALL)
725 RTStrmPrintf(pStrm,
726 Help::tr(
727 "%s clonemedium %s [disk|dvd|floppy] <uuid|inputfile> <uuid|outputfile>\n"
728 " [--format VDI|VMDK|VHD|RAW|<other>]\n"
729 " [--variant Standard,Fixed,Split2G,Stream,ESX]\n"
730 " [--existing]\n"
731 "\n"), SEP);
732
733 if (enmCommand == USAGE_MEDIUMPROPERTY || enmCommand == USAGE_S_ALL)
734 RTStrmPrintf(pStrm,
735 Help::tr(
736 "%s mediumproperty %s [disk|dvd|floppy] set <uuid|filename>\n"
737 " <property> <value>\n"
738 "\n"
739 " [disk|dvd|floppy] get <uuid|filename>\n"
740 " <property>\n"
741 "\n"
742 " [disk|dvd|floppy] delete <uuid|filename>\n"
743 " <property>\n"
744 "\n"), SEP);
745
746 if (enmCommand == USAGE_ENCRYPTMEDIUM || enmCommand == USAGE_S_ALL)
747 RTStrmPrintf(pStrm,
748 Help::tr(
749 "%s encryptmedium %s <uuid|filename>\n"
750 " [--newpassword <file>|-]\n"
751 " [--oldpassword <file>|-]\n"
752 " [--cipher <cipher identifier>]\n"
753 " [--newpasswordid <password identifier>]\n"
754 "\n"), SEP);
755
756 if (enmCommand == USAGE_MEDIUMENCCHKPWD || enmCommand == USAGE_S_ALL)
757 RTStrmPrintf(pStrm,
758 Help::tr(
759 "%s checkmediumpwd %s <uuid|filename>\n"
760 " <pwd file>|-\n"
761 "\n"), SEP);
762
763 if (enmCommand == USAGE_CONVERTFROMRAW || enmCommand == USAGE_S_ALL)
764 RTStrmPrintf(pStrm,
765 Help::tr(
766 "%s convertfromraw %s <filename> <outputfile>\n"
767 " [--format VDI|VMDK|VHD]\n"
768 " [--variant Standard,Fixed,Split2G,Stream,ESX]\n"
769 " [--uuid <uuid>]\n"
770 "%s convertfromraw %s stdin <outputfile> <bytes>\n"
771 " [--format VDI|VMDK|VHD]\n"
772 " [--variant Standard,Fixed,Split2G,Stream,ESX]\n"
773 " [--uuid <uuid>]\n"
774 "\n"), SEP, SEP);
775
776 if (enmCommand == USAGE_GETEXTRADATA || enmCommand == USAGE_S_ALL)
777 RTStrmPrintf(pStrm,
778 Help::tr(
779 "%s getextradata %s global|<uuid|vmname>\n"
780 " <key>|[enumerate]\n"
781 "\n"), SEP);
782
783 if (enmCommand == USAGE_SETEXTRADATA || enmCommand == USAGE_S_ALL)
784 RTStrmPrintf(pStrm,
785 Help::tr(
786 "%s setextradata %s global|<uuid|vmname>\n"
787 " <key>\n"
788 " [<value>] (no value deletes key)\n"
789 "\n"), SEP);
790
791 if (enmCommand == USAGE_SETPROPERTY || enmCommand == USAGE_S_ALL)
792 RTStrmPrintf(pStrm,
793 Help::tr(
794 "%s setproperty %s machinefolder default|<folder> |\n"
795 " hwvirtexclusive on|off |\n"
796 " vrdeauthlibrary default|<library> |\n"
797 " websrvauthlibrary default|null|<library> |\n"
798 " vrdeextpack null|<library> |\n"
799 " autostartdbpath null|<folder> |\n"
800 " loghistorycount <value>\n"
801 " defaultfrontend default|<name>\n"
802 " logginglevel <log setting>\n"
803 " proxymode system|noproxy|manual\n"
804 " proxyurl <url>\n"), SEP);
805#ifdef VBOX_WITH_MAIN_NLS
806 RTStrmPrintf(pStrm,
807 Help::tr(
808 " language <language id>\n"));
809#endif
810 RTStrmPrintf(pStrm,
811 "\n");
812
813 if (enmCommand == USAGE_USBFILTER || enmCommand == USAGE_S_ALL)
814 {
815 if (fSubcommandScope & HELP_SCOPE_USBFILTER_ADD)
816 RTStrmPrintf(pStrm,
817 Help::tr(
818 "%s usbfilter %s add <index,0-N>\n"
819 " --target <uuid|vmname>|global\n"
820 " --name <string>\n"
821 " --action ignore|hold (global filters only)\n"
822 " [--active yes|no] (yes)\n"
823 " [--vendorid <XXXX>] (null)\n"
824 " [--productid <XXXX>] (null)\n"
825 " [--revision <IIFF>] (null)\n"
826 " [--manufacturer <string>] (null)\n"
827 " [--product <string>] (null)\n"
828 " [--remote yes|no] (null, VM filters only)\n"
829 " [--serialnumber <string>] (null)\n"
830 " [--maskedinterfaces <XXXXXXXX>]\n"
831 "\n"), SEP);
832
833 if (fSubcommandScope & HELP_SCOPE_USBFILTER_MODIFY)
834 RTStrmPrintf(pStrm,
835 Help::tr(
836 "%s usbfilter %s modify <index,0-N>\n"
837 " --target <uuid|vmname>|global\n"
838 " [--name <string>]\n"
839 " [--action ignore|hold] (global filters only)\n"
840 " [--active yes|no]\n"
841 " [--vendorid <XXXX>|\"\"]\n"
842 " [--productid <XXXX>|\"\"]\n"
843 " [--revision <IIFF>|\"\"]\n"
844 " [--manufacturer <string>|\"\"]\n"
845 " [--product <string>|\"\"]\n"
846 " [--remote yes|no] (null, VM filters only)\n"
847 " [--serialnumber <string>|\"\"]\n"
848 " [--maskedinterfaces <XXXXXXXX>]\n"
849 "\n"), SEP);
850
851 if (fSubcommandScope & HELP_SCOPE_USBFILTER_REMOVE)
852 RTStrmPrintf(pStrm,
853 Help::tr(
854 "%s usbfilter %s remove <index,0-N>\n"
855 " --target <uuid|vmname>|global\n"
856 "\n"), SEP);
857 }
858
859#ifdef VBOX_WITH_GUEST_PROPS
860 if (enmCommand == USAGE_GUESTPROPERTY || enmCommand == USAGE_S_ALL)
861 usageGuestProperty(pStrm, SEP);
862#endif /* VBOX_WITH_GUEST_PROPS defined */
863
864#ifdef VBOX_WITH_GUEST_CONTROL
865 if (enmCommand == USAGE_GUESTCONTROL || enmCommand == USAGE_S_ALL)
866 usageGuestControl(pStrm, SEP, fSubcommandScope);
867#endif /* VBOX_WITH_GUEST_CONTROL defined */
868
869 if (enmCommand == USAGE_METRICS || enmCommand == USAGE_S_ALL)
870 RTStrmPrintf(pStrm,
871 Help::tr(
872 "%s metrics %s list [*|host|<vmname> [<metric_list>]]\n"
873 " (comma-separated)\n\n"
874 "%s metrics %s setup\n"
875 " [--period <seconds>] (default: 1)\n"
876 " [--samples <count>] (default: 1)\n"
877 " [--list]\n"
878 " [*|host|<vmname> [<metric_list>]]\n\n"
879 "%s metrics %s query [*|host|<vmname> [<metric_list>]]\n\n"
880 "%s metrics %s enable\n"
881 " [--list]\n"
882 " [*|host|<vmname> [<metric_list>]]\n\n"
883 "%s metrics %s disable\n"
884 " [--list]\n"
885 " [*|host|<vmname> [<metric_list>]]\n\n"
886 "%s metrics %s collect\n"
887 " [--period <seconds>] (default: 1)\n"
888 " [--samples <count>] (default: 1)\n"
889 " [--list]\n"
890 " [--detach]\n"
891 " [*|host|<vmname> [<metric_list>]]\n"
892 "\n"), SEP, SEP, SEP, SEP, SEP, SEP);
893
894#if defined(VBOX_WITH_NAT_SERVICE)
895 if (enmCommand == USAGE_NATNETWORK || enmCommand == USAGE_S_ALL)
896 {
897 RTStrmPrintf(pStrm,
898 Help::tr(
899 "%s natnetwork %s add --netname <name>\n"
900 " --network <network>\n"
901 " [--enable|--disable]\n"
902 " [--dhcp on|off]\n"
903 " [--port-forward-4 <rule>]\n"
904 " [--loopback-4 <rule>]\n"
905 " [--ipv6 on|off]\n"
906 " [--port-forward-6 <rule>]\n"
907 " [--loopback-6 <rule>]\n\n"
908 "%s natnetwork %s remove --netname <name>\n\n"
909 "%s natnetwork %s modify --netname <name>\n"
910 " [--network <network>]\n"
911 " [--enable|--disable]\n"
912 " [--dhcp on|off]\n"
913 " [--port-forward-4 <rule>]\n"
914 " [--loopback-4 <rule>]\n"
915 " [--ipv6 on|off]\n"
916 " [--port-forward-6 <rule>]\n"
917 " [--loopback-6 <rule>]\n\n"
918 "%s natnetwork %s start --netname <name>\n\n"
919 "%s natnetwork %s stop --netname <name>\n\n"
920 "%s natnetwork %s list [<pattern>]\n"
921 "\n"), SEP, SEP, SEP, SEP, SEP, SEP);
922
923
924 }
925#endif
926
927#if defined(VBOX_WITH_NETFLT)
928 if (enmCommand == USAGE_HOSTONLYIFS || enmCommand == USAGE_S_ALL)
929 {
930 RTStrmPrintf(pStrm,
931 Help::tr(
932 "%s hostonlyif %s ipconfig <name>\n"
933 " [--dhcp |\n"
934 " --ip <ipv4> [--netmask <ipv4> (def:255.255.255.0)]|\n"
935 " --ipv6 <ipv6> [--netmasklengthv6 <N> (def:64)]]"), SEP);
936# if !defined(RT_OS_SOLARIS) || defined(VBOX_ONLY_DOCS)
937 RTStrmPrintf(pStrm,
938 Help::tr(
939 " |\n"
940 " create |\n"
941 " remove <name>\n"));
942# else
943 RTStrmPrintf(pStrm,
944 Help::tr(
945 "\n");
946# endif
947 RTStrmPrintf(pStrm,
948 "\n");
949 }
950#endif
951
952 if (enmCommand == USAGE_USBDEVSOURCE || enmCommand == USAGE_S_ALL)
953 {
954 RTStrmPrintf(pStrm,
955 Help::tr(
956 "%s usbdevsource %s add <source name>\n"
957 " --backend <backend>\n"
958 " --address <address>\n"
959 "%s usbdevsource %s remove <source name>\n"
960 "\n"), SEP, SEP);
961 }
962
963#ifndef VBOX_ONLY_DOCS /* Converted to man page, not needed. */
964 if (enmCommand == USAGE_S_ALL)
965 {
966 uint32_t cPendingBlankLines = 0;
967 for (uint32_t i = 0; i < g_cHelpEntries; i++)
968 {
969 PCRTMSGREFENTRY pHelp = g_apHelpEntries[i];
970 while (cPendingBlankLines-- > 0)
971 RTStrmPutCh(pStrm, '\n');
972 RTStrmPrintf(pStrm, " %c%s:\n", RT_C_TO_UPPER(pHelp->pszBrief[0]), pHelp->pszBrief + 1);
973 cPendingBlankLines = 0;
974 RTMsgRefEntryPrintStringTable(pStrm, &pHelp->Synopsis, RTMSGREFENTRYSTR_SCOPE_GLOBAL,
975 &cPendingBlankLines, NULL /*pcLinesWritten*/);
976 cPendingBlankLines = RT_MAX(cPendingBlankLines, 1);
977 }
978 }
979#endif
980}
981
982/**
983 * Print a usage synopsis and the syntax error message.
984 * @returns RTEXITCODE_SYNTAX.
985 */
986RTEXITCODE errorSyntax(USAGECATEGORY enmCommand, const char *pszFormat, ...)
987{
988 va_list args;
989 showLogo(g_pStdErr); // show logo even if suppressed
990#ifndef VBOX_ONLY_DOCS
991 if (g_fInternalMode)
992 printUsageInternal(enmCommand, g_pStdErr);
993 else if (g_enmCurCommand == HELP_CMD_VBOXMANAGE_INVALID)
994 printUsage(enmCommand, RTMSGREFENTRYSTR_SCOPE_GLOBAL, g_pStdErr);
995 else
996 printUsage(g_pStdErr);
997#else
998 RT_NOREF_PV(enmCommand);
999#endif
1000 va_start(args, pszFormat);
1001 RTStrmPrintf(g_pStdErr, Help::tr("\nSyntax error: %N\n"), pszFormat, &args);
1002 va_end(args);
1003 return RTEXITCODE_SYNTAX;
1004}
1005
1006/**
1007 * Print a usage synopsis and the syntax error message.
1008 * @returns RTEXITCODE_SYNTAX.
1009 */
1010RTEXITCODE errorSyntaxEx(USAGECATEGORY enmCommand, uint64_t fSubcommandScope, const char *pszFormat, ...)
1011{
1012 va_list args;
1013 showLogo(g_pStdErr); // show logo even if suppressed
1014#ifndef VBOX_ONLY_DOCS
1015 if (g_fInternalMode)
1016 printUsageInternal(enmCommand, g_pStdErr);
1017 else if (g_enmCurCommand == HELP_CMD_VBOXMANAGE_INVALID)
1018 printUsage(enmCommand, fSubcommandScope, g_pStdErr);
1019 else
1020 printUsage(g_pStdErr);
1021#else
1022 RT_NOREF2(enmCommand, fSubcommandScope);
1023#endif
1024 va_start(args, pszFormat);
1025 RTStrmPrintf(g_pStdErr, Help::tr("\nSyntax error: %N\n"), pszFormat, &args);
1026 va_end(args);
1027 return RTEXITCODE_SYNTAX;
1028}
1029
1030/**
1031 * errorSyntax for RTGetOpt users.
1032 *
1033 * @returns RTEXITCODE_SYNTAX.
1034 *
1035 * @param enmCommand The command.
1036 * @param fSubcommandScope The subcommand scope, REFENTRYSTR_SCOPE_GLOBAL
1037 * for all.
1038 * @param rc The RTGetOpt return code.
1039 * @param pValueUnion The value union.
1040 */
1041RTEXITCODE errorGetOptEx(USAGECATEGORY enmCommand, uint64_t fSubcommandScope, int rc, union RTGETOPTUNION const *pValueUnion)
1042{
1043 /*
1044 * Check if it is an unhandled standard option.
1045 */
1046#ifndef VBOX_ONLY_DOCS
1047 if (rc == 'V')
1048 {
1049 RTPrintf("%sr%d\n", VBOX_VERSION_STRING, RTBldCfgRevision());
1050 return RTEXITCODE_SUCCESS;
1051 }
1052#endif
1053
1054 if (rc == 'h')
1055 {
1056 showLogo(g_pStdErr);
1057#ifndef VBOX_ONLY_DOCS
1058 if (g_fInternalMode)
1059 printUsageInternal(enmCommand, g_pStdOut);
1060 else if (g_enmCurCommand == HELP_CMD_VBOXMANAGE_INVALID)
1061 printUsage(enmCommand, fSubcommandScope, g_pStdOut);
1062 else
1063 printUsage(g_pStdErr);
1064#endif
1065 return RTEXITCODE_SUCCESS;
1066 }
1067
1068 /*
1069 * General failure.
1070 */
1071 showLogo(g_pStdErr); // show logo even if suppressed
1072#ifndef VBOX_ONLY_DOCS
1073 if (g_fInternalMode)
1074 printUsageInternal(enmCommand, g_pStdErr);
1075 else if (g_enmCurCommand == HELP_CMD_VBOXMANAGE_INVALID)
1076 printUsage(enmCommand, fSubcommandScope, g_pStdErr);
1077 else
1078 printUsage(g_pStdErr);
1079#else
1080 RT_NOREF2(enmCommand, fSubcommandScope);
1081#endif
1082
1083 if (rc == VINF_GETOPT_NOT_OPTION)
1084 return RTMsgErrorExit(RTEXITCODE_SYNTAX, Help::tr("Invalid parameter '%s'"), pValueUnion->psz);
1085 if (rc > 0)
1086 {
1087 if (RT_C_IS_PRINT(rc))
1088 return RTMsgErrorExit(RTEXITCODE_SYNTAX, Help::tr("Invalid option -%c"), rc);
1089 return RTMsgErrorExit(RTEXITCODE_SYNTAX, Help::tr("Invalid option case %i"), rc);
1090 }
1091 if (rc == VERR_GETOPT_UNKNOWN_OPTION)
1092 return RTMsgErrorExit(RTEXITCODE_SYNTAX, Help::tr("Unknown option: %s"), pValueUnion->psz);
1093 if (rc == VERR_GETOPT_INVALID_ARGUMENT_FORMAT)
1094 return RTMsgErrorExit(RTEXITCODE_SYNTAX, Help::tr("Invalid argument format: %s"), pValueUnion->psz);
1095 if (pValueUnion->pDef)
1096 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "%s: %Rrs", pValueUnion->pDef->pszLong, rc);
1097 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "%Rrs", rc);
1098}
1099
1100/**
1101 * errorSyntax for RTGetOpt users.
1102 *
1103 * @returns RTEXITCODE_SYNTAX.
1104 *
1105 * @param enmCommand The command.
1106 * @param rc The RTGetOpt return code.
1107 * @param pValueUnion The value union.
1108 */
1109RTEXITCODE errorGetOpt(USAGECATEGORY enmCommand, int rc, union RTGETOPTUNION const *pValueUnion)
1110{
1111 return errorGetOptEx(enmCommand, RTMSGREFENTRYSTR_SCOPE_GLOBAL, rc, pValueUnion);
1112}
1113
1114/**
1115 * Print an error message without the syntax stuff.
1116 *
1117 * @returns RTEXITCODE_SYNTAX.
1118 */
1119RTEXITCODE errorArgument(const char *pszFormat, ...)
1120{
1121 va_list args;
1122 va_start(args, pszFormat);
1123 RTMsgErrorV(pszFormat, args);
1124 va_end(args);
1125 return RTEXITCODE_SYNTAX;
1126}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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