VirtualBox

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

Last change on this file since 93632 was 93347, checked in by vboxsync, 3 years ago

Main: bugref:1909: Fixed help output in VBoxManage

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

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