VirtualBox

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

Last change on this file since 91483 was 91204, checked in by vboxsync, 3 years ago

doc, Frontends/VBoxManage: Integrate several refentry documentation pieces, bringing them up to date (making sure everything documented is actually understood). Remove the corresponding old style documentation and also the manually written help text in VBoxManage. Also fixes the synopsis printing when showing a syntax error message for new style documentation.

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