VirtualBox

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

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

Main" bugref:1909: Removed translation marks form printUsage and its callees. Added missed help for "VBoxManage setproperty language"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 47.0 KB
Line 
1/* $Id: VBoxManageHelp.cpp 92432 2021-11-15 15:58:43Z 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*********************************************************************************************************************************/
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 " VBoxManage [<general option>] <command>\n"
457 "\n"
458 "\n"
459 "General Options:\n"
460 "\n"
461 " [-V|--version] print version number and exit\n"
462 " [--dump-build-type] print build type and exit\n"
463 " [-q|--nologo] suppress the logo\n"
464 " [--settingspw <pw>] provide the settings password\n"
465 " [--settingspwfile <file>] provide a file containing the settings password\n"
466 " [@<response-file>] load arguments from the given response file (bourne style)\n"
467 "\n"
468 "\n"
469 "Commands:\n"
470 "\n");
471
472 const char *pcszSep1 = " ";
473 const char *pcszSep2 = " ";
474 if (enmCommand != USAGE_S_ALL)
475 {
476 pcszSep1 = "VBoxManage";
477 pcszSep2 = "";
478 }
479
480#define SEP pcszSep1, pcszSep2
481
482 if (enmCommand == USAGE_STARTVM || enmCommand == USAGE_S_ALL)
483 {
484 RTStrmPrintf(pStrm,
485 "%s startvm %s <uuid|vmname>...\n"
486 " [--type gui", SEP);
487 if (fVBoxSDL)
488 RTStrmPrintf(pStrm, "|sdl");
489 RTStrmPrintf(pStrm, "|headless|separate]\n");
490 RTStrmPrintf(pStrm,
491 " [-E|--putenv <NAME>[=<VALUE>]]\n"
492 "\n");
493 }
494
495 if (enmCommand == USAGE_CONTROLVM || enmCommand == USAGE_S_ALL)
496 {
497 RTStrmPrintf(pStrm,
498 "%s controlvm %s <uuid|vmname>\n"
499 " pause|resume|reset|poweroff|savestate|\n", SEP);
500#ifdef VBOX_WITH_GUEST_CONTROL
501 RTStrmPrintf(pStrm,
502 " reboot|shutdown [--force]|\n");
503#endif
504 RTStrmPrintf(pStrm,
505 " acpipowerbutton|acpisleepbutton|\n"
506 " keyboardputscancode <hex> [<hex> ...]|\n"
507 " keyboardputstring <string1> [<string2> ...]|\n"
508 " keyboardputfile <filename>|\n"
509 " setlinkstate<1-N> on|off |\n");
510#if defined(VBOX_WITH_NETFLT)
511 RTStrmPrintf(pStrm,
512 " nic<1-N> null|nat|bridged|intnet|hostonly|generic|\n"
513 " natnetwork [<devicename>] |\n");
514#else /* !VBOX_WITH_NETFLT */
515 RTStrmPrintf(pStrm,
516 " nic<1-N> null|nat|bridged|intnet|generic|natnetwork\n"
517 " [<devicename>] |\n");
518#endif /* !VBOX_WITH_NETFLT */
519 RTStrmPrintf(pStrm,
520 " nictrace<1-N> on|off |\n"
521 " nictracefile<1-N> <filename> |\n"
522 " nicproperty<1-N> name=[value] |\n"
523 " nicpromisc<1-N> deny|allow-vms|allow-all |\n"
524 " natpf<1-N> [<rulename>],tcp|udp,[<hostip>],\n"
525 " <hostport>,[<guestip>],<guestport> |\n"
526 " natpf<1-N> delete <rulename> |\n"
527 " guestmemoryballoon <balloonsize in MB> |\n"
528 " usbattach <uuid>|<address>\n"
529 " [--capturefile <filename>] |\n"
530 " usbdetach <uuid>|<address> |\n"
531 " audioin on|off |\n"
532 " audioout on|off |\n");
533#ifdef VBOX_WITH_SHARED_CLIPBOARD
534 RTStrmPrintf(pStrm,
535 " clipboard mode disabled|hosttoguest|guesttohost|\n"
536 " bidirectional |\n");
537# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
538 RTStrmPrintf(pStrm,
539 " clipboard filetransfers enabled|disabled |\n");
540# endif
541#endif
542 RTStrmPrintf(pStrm,
543 " draganddrop disabled|hosttoguest|guesttohost|\n"
544 " bidirectional |\n"
545 " vrde on|off |\n"
546 " vrdeport <port> |\n"
547 " vrdeproperty <name=[value]> |\n"
548 " vrdevideochannelquality <percent> |\n"
549 " setvideomodehint <xres> <yres> <bpp>\n"
550 " [[<display>] [<enabled:yes|no> |\n"
551 " [<xorigin> <yorigin>]]] |\n"
552 " setscreenlayout <display> on|primary <xorigin> <yorigin> <xres> <yres> <bpp> | off\n"
553 " screenshotpng <file> [display] |\n");
554#ifdef VBOX_WITH_RECORDING
555 RTStrmPrintf(pStrm,
556 " recording on|off |\n"
557 " recording screens all|none|<screen>,[<screen>...] |\n"
558 " recording filename <file> |\n"
559 " recording videores <width>x<height> |\n"
560 " recording videorate <rate> |\n"
561 " recording videofps <fps> |\n"
562 " recording maxtime <s> |\n"
563 " recording maxfilesize <MB> |\n");
564#endif /* VBOX_WITH_RECORDING */
565 RTStrmPrintf(pStrm,
566 " setcredentials <username>\n"
567 " --passwordfile <file> | <password>\n"
568 " <domain>\n"
569 " [--allowlocallogon <yes|no>] |\n"
570 " teleport --host <name> --port <port>\n"
571 " [--maxdowntime <msec>]\n"
572 " [--passwordfile <file> |\n"
573 " --password <password>] |\n"
574 " plugcpu <id> |\n"
575 " unplugcpu <id> |\n"
576 " cpuexecutioncap <1-100>\n"
577 " webcam <attach [path [settings]]> | <detach [path]> | <list>\n"
578 " addencpassword <id>\n"
579 " <password file>|-\n"
580 " [--removeonsuspend <yes|no>]\n"
581 " removeencpassword <id>\n"
582 " removeallencpasswords\n"
583 " changeuartmode<1-N> disconnected|\n"
584 " server <pipe>|\n"
585 " client <pipe>|\n"
586 " tcpserver <port>|\n"
587 " tcpclient <hostname:port>|\n"
588 " file <file>|\n"
589 " <devicename>\n"
590 " vm-process-priority default|flat|low|normal|high\n"
591 " autostart-enabled on|off\n"
592 " autostart-delay <seconds>\n"
593 "\n");
594 }
595
596 if (enmCommand == USAGE_DISCARDSTATE || enmCommand == USAGE_S_ALL)
597 RTStrmPrintf(pStrm,
598 "%s discardstate %s <uuid|vmname>\n"
599 "\n", SEP);
600
601 if (enmCommand == USAGE_ADOPTSTATE || enmCommand == USAGE_S_ALL)
602 RTStrmPrintf(pStrm,
603 "%s adoptstate %s <uuid|vmname> <state_file>\n"
604 "\n", SEP);
605
606 if (enmCommand == USAGE_CLOSEMEDIUM || enmCommand == USAGE_S_ALL)
607 RTStrmPrintf(pStrm,
608 "%s closemedium %s [disk|dvd|floppy] <uuid|filename>\n"
609 " [--delete]\n"
610 "\n", SEP);
611
612 if (enmCommand == USAGE_STORAGEATTACH || enmCommand == USAGE_S_ALL)
613 RTStrmPrintf(pStrm,
614 "%s storageattach %s <uuid|vmname>\n"
615 " --storagectl <name>\n"
616 " [--port <number>]\n"
617 " [--device <number>]\n"
618 " [--type dvddrive|hdd|fdd]\n"
619 " [--medium none|emptydrive|additions|\n"
620 " <uuid|filename>|host:<drive>|iscsi]\n"
621 " [--mtype normal|writethrough|immutable|shareable|\n"
622 " readonly|multiattach]\n"
623 " [--comment <text>]\n"
624 " [--setuuid <uuid>]\n"
625 " [--setparentuuid <uuid>]\n"
626 " [--passthrough on|off]\n"
627 " [--tempeject on|off]\n"
628 " [--nonrotational on|off]\n"
629 " [--discard on|off]\n"
630 " [--hotpluggable on|off]\n"
631 " [--bandwidthgroup <name>]\n"
632 " [--forceunmount]\n"
633 " [--server <name>|<ip>]\n"
634 " [--target <target>]\n"
635 " [--tport <port>]\n"
636 " [--lun <lun>]\n"
637 " [--encodedlun <lun>]\n"
638 " [--username <username>]\n"
639 " [--password <password>]\n"
640 " [--passwordfile <file>]\n"
641 " [--initiator <initiator>]\n"
642 " [--intnet]\n"
643 "\n", SEP);
644
645 if (enmCommand == USAGE_STORAGECONTROLLER || enmCommand == USAGE_S_ALL)
646 RTStrmPrintf(pStrm,
647 "%s storagectl %s <uuid|vmname>\n"
648 " --name <name>\n"
649 " [--add ide|sata|scsi|floppy|sas|usb|pcie|virtio]\n"
650 " [--controller LSILogic|LSILogicSAS|BusLogic|\n"
651 " IntelAHCI|PIIX3|PIIX4|ICH6|I82078|\n"
652 " [ USB|NVMe|VirtIO]\n"
653 " [--portcount <1-n>]\n"
654 " [--hostiocache on|off]\n"
655 " [--bootable on|off]\n"
656 " [--rename <name>]\n"
657 " [--remove]\n"
658 "\n", SEP);
659
660 if (enmCommand == USAGE_BANDWIDTHCONTROL || enmCommand == USAGE_S_ALL)
661 RTStrmPrintf(pStrm,
662 "%s bandwidthctl %s <uuid|vmname>\n"
663 " add <name> --type disk|network\n"
664 " --limit <megabytes per second>[k|m|g|K|M|G] |\n"
665 " set <name>\n"
666 " --limit <megabytes per second>[k|m|g|K|M|G] |\n"
667 " remove <name> |\n"
668 " list [--machinereadable]\n"
669 " (limit units: k=kilobit, m=megabit, g=gigabit,\n"
670 " K=kilobyte, M=megabyte, G=gigabyte)\n"
671 "\n", SEP);
672
673 if (enmCommand == USAGE_SHOWMEDIUMINFO || enmCommand == USAGE_S_ALL)
674 RTStrmPrintf(pStrm,
675 "%s showmediuminfo %s [disk|dvd|floppy] <uuid|filename>\n"
676 "\n", SEP);
677
678 if (enmCommand == USAGE_CREATEMEDIUM || enmCommand == USAGE_S_ALL)
679 RTStrmPrintf(pStrm,
680 "%s createmedium %s [disk|dvd|floppy] --filename <filename>\n"
681 " [--size <megabytes>|--sizebyte <bytes>]\n"
682 " [--diffparent <uuid>|<filename>]\n"
683 " [--format VDI|VMDK|VHD] (default: VDI)]\n"
684 " [--variant Standard,Fixed,Split2G,Stream,ESX,\n"
685 " Formatted,RawDisk]\n"
686 " [[--property <name>=<value>] --property <name>=<value>\n"
687 " --property-file <name>=</path/to/file/with/value>]...\n"
688 "\n", SEP);
689
690 if (enmCommand == USAGE_MODIFYMEDIUM || enmCommand == USAGE_S_ALL)
691 RTStrmPrintf(pStrm,
692 "%s modifymedium %s [disk|dvd|floppy] <uuid|filename>\n"
693 " [--type normal|writethrough|immutable|shareable|\n"
694 " readonly|multiattach]\n"
695 " [--autoreset on|off]\n"
696 " [--property <name=[value]>]\n"
697 " [--compact]\n"
698 " [--resize <megabytes>|--resizebyte <bytes>]\n"
699 " [--move <path>]\n"
700 " [--setlocation <path>]\n"
701 " [--description <description string>]"
702 "\n", SEP);
703
704 if (enmCommand == USAGE_CLONEMEDIUM || enmCommand == USAGE_S_ALL)
705 RTStrmPrintf(pStrm,
706 "%s clonemedium %s [disk|dvd|floppy] <uuid|inputfile> <uuid|outputfile>\n"
707 " [--format VDI|VMDK|VHD|RAW|<other>]\n"
708 " [--variant Standard,Fixed,Split2G,Stream,ESX]\n"
709 " [--existing]\n"
710 "\n", SEP);
711
712 if (enmCommand == USAGE_MEDIUMPROPERTY || enmCommand == USAGE_S_ALL)
713 RTStrmPrintf(pStrm,
714 "%s mediumproperty %s [disk|dvd|floppy] set <uuid|filename>\n"
715 " <property> <value>\n"
716 "\n"
717 " [disk|dvd|floppy] get <uuid|filename>\n"
718 " <property>\n"
719 "\n"
720 " [disk|dvd|floppy] delete <uuid|filename>\n"
721 " <property>\n"
722 "\n", SEP);
723
724 if (enmCommand == USAGE_ENCRYPTMEDIUM || enmCommand == USAGE_S_ALL)
725 RTStrmPrintf(pStrm,
726 "%s encryptmedium %s <uuid|filename>\n"
727 " [--newpassword <file>|-]\n"
728 " [--oldpassword <file>|-]\n"
729 " [--cipher <cipher identifier>]\n"
730 " [--newpasswordid <password identifier>]\n"
731 "\n", SEP);
732
733 if (enmCommand == USAGE_MEDIUMENCCHKPWD || enmCommand == USAGE_S_ALL)
734 RTStrmPrintf(pStrm,
735 "%s checkmediumpwd %s <uuid|filename>\n"
736 " <pwd file>|-\n"
737 "\n", SEP);
738
739 if (enmCommand == USAGE_CONVERTFROMRAW || enmCommand == USAGE_S_ALL)
740 RTStrmPrintf(pStrm,
741 "%s convertfromraw %s <filename> <outputfile>\n"
742 " [--format VDI|VMDK|VHD]\n"
743 " [--variant Standard,Fixed,Split2G,Stream,ESX]\n"
744 " [--uuid <uuid>]\n"
745 "%s convertfromraw %s stdin <outputfile> <bytes>\n"
746 " [--format VDI|VMDK|VHD]\n"
747 " [--variant Standard,Fixed,Split2G,Stream,ESX]\n"
748 " [--uuid <uuid>]\n"
749 "\n", SEP, SEP);
750
751 if (enmCommand == USAGE_GETEXTRADATA || enmCommand == USAGE_S_ALL)
752 RTStrmPrintf(pStrm,
753 "%s getextradata %s global|<uuid|vmname>\n"
754 " <key>|[enumerate]\n"
755 "\n", SEP);
756
757 if (enmCommand == USAGE_SETEXTRADATA || enmCommand == USAGE_S_ALL)
758 RTStrmPrintf(pStrm,
759 "%s setextradata %s global|<uuid|vmname>\n"
760 " <key>\n"
761 " [<value>] (no value deletes key)\n"
762 "\n", SEP);
763
764 if (enmCommand == USAGE_SETPROPERTY || enmCommand == USAGE_S_ALL)
765 RTStrmPrintf(pStrm,
766 "%s setproperty %s machinefolder default|<folder> |\n"
767 " hwvirtexclusive on|off |\n"
768 " vrdeauthlibrary default|<library> |\n"
769 " websrvauthlibrary default|null|<library> |\n"
770 " vrdeextpack null|<library> |\n"
771 " autostartdbpath null|<folder> |\n"
772 " loghistorycount <value>\n"
773 " defaultfrontend default|<name>\n"
774 " logginglevel <log setting>\n"
775 " proxymode system|noproxy|manual\n"
776 " proxyurl <url>\n", SEP);
777#ifdef VBOX_WITH_MAIN_NLS
778 RTStrmPrintf(pStrm,
779 " language <language id>\n");
780#endif
781 RTStrmPrintf(pStrm,
782 "\n");
783
784 if (enmCommand == USAGE_USBFILTER || enmCommand == USAGE_S_ALL)
785 {
786 if (fSubcommandScope & HELP_SCOPE_USBFILTER_ADD)
787 RTStrmPrintf(pStrm,
788 "%s usbfilter %s add <index,0-N>\n"
789 " --target <uuid|vmname>|global\n"
790 " --name <string>\n"
791 " --action ignore|hold (global filters only)\n"
792 " [--active yes|no] (yes)\n"
793 " [--vendorid <XXXX>] (null)\n"
794 " [--productid <XXXX>] (null)\n"
795 " [--revision <IIFF>] (null)\n"
796 " [--manufacturer <string>] (null)\n"
797 " [--product <string>] (null)\n"
798 " [--remote yes|no] (null, VM filters only)\n"
799 " [--serialnumber <string>] (null)\n"
800 " [--maskedinterfaces <XXXXXXXX>]\n"
801 "\n", SEP);
802
803 if (fSubcommandScope & HELP_SCOPE_USBFILTER_MODIFY)
804 RTStrmPrintf(pStrm,
805 "%s usbfilter %s modify <index,0-N>\n"
806 " --target <uuid|vmname>|global\n"
807 " [--name <string>]\n"
808 " [--action ignore|hold] (global filters only)\n"
809 " [--active yes|no]\n"
810 " [--vendorid <XXXX>|\"\"]\n"
811 " [--productid <XXXX>|\"\"]\n"
812 " [--revision <IIFF>|\"\"]\n"
813 " [--manufacturer <string>|\"\"]\n"
814 " [--product <string>|\"\"]\n"
815 " [--remote yes|no] (null, VM filters only)\n"
816 " [--serialnumber <string>|\"\"]\n"
817 " [--maskedinterfaces <XXXXXXXX>]\n"
818 "\n", SEP);
819
820 if (fSubcommandScope & HELP_SCOPE_USBFILTER_REMOVE)
821 RTStrmPrintf(pStrm,
822 "%s usbfilter %s remove <index,0-N>\n"
823 " --target <uuid|vmname>|global\n"
824 "\n", SEP);
825 }
826
827#ifdef VBOX_WITH_GUEST_PROPS
828 if (enmCommand == USAGE_GUESTPROPERTY || enmCommand == USAGE_S_ALL)
829 usageGuestProperty(pStrm, SEP);
830#endif /* VBOX_WITH_GUEST_PROPS defined */
831
832#ifdef VBOX_WITH_GUEST_CONTROL
833 if (enmCommand == USAGE_GUESTCONTROL || enmCommand == USAGE_S_ALL)
834 usageGuestControl(pStrm, SEP, fSubcommandScope);
835#endif /* VBOX_WITH_GUEST_CONTROL defined */
836
837 if (enmCommand == USAGE_METRICS || enmCommand == USAGE_S_ALL)
838 RTStrmPrintf(pStrm,
839 "%s metrics %s list [*|host|<vmname> [<metric_list>]]\n"
840 " (comma-separated)\n\n"
841 "%s metrics %s setup\n"
842 " [--period <seconds>] (default: 1)\n"
843 " [--samples <count>] (default: 1)\n"
844 " [--list]\n"
845 " [*|host|<vmname> [<metric_list>]]\n\n"
846 "%s metrics %s query [*|host|<vmname> [<metric_list>]]\n\n"
847 "%s metrics %s enable\n"
848 " [--list]\n"
849 " [*|host|<vmname> [<metric_list>]]\n\n"
850 "%s metrics %s disable\n"
851 " [--list]\n"
852 " [*|host|<vmname> [<metric_list>]]\n\n"
853 "%s metrics %s collect\n"
854 " [--period <seconds>] (default: 1)\n"
855 " [--samples <count>] (default: 1)\n"
856 " [--list]\n"
857 " [--detach]\n"
858 " [*|host|<vmname> [<metric_list>]]\n"
859 "\n", SEP, SEP, SEP, SEP, SEP, SEP);
860
861#if defined(VBOX_WITH_NAT_SERVICE)
862 if (enmCommand == USAGE_NATNETWORK || enmCommand == USAGE_S_ALL)
863 {
864 RTStrmPrintf(pStrm,
865 "%s natnetwork %s add --netname <name>\n"
866 " --network <network>\n"
867 " [--enable|--disable]\n"
868 " [--dhcp on|off]\n"
869 " [--port-forward-4 <rule>]\n"
870 " [--loopback-4 <rule>]\n"
871 " [--ipv6 on|off]\n"
872 " [--port-forward-6 <rule>]\n"
873 " [--loopback-6 <rule>]\n\n"
874 "%s natnetwork %s remove --netname <name>\n\n"
875 "%s natnetwork %s modify --netname <name>\n"
876 " [--network <network>]\n"
877 " [--enable|--disable]\n"
878 " [--dhcp on|off]\n"
879 " [--port-forward-4 <rule>]\n"
880 " [--loopback-4 <rule>]\n"
881 " [--ipv6 on|off]\n"
882 " [--port-forward-6 <rule>]\n"
883 " [--loopback-6 <rule>]\n\n"
884 "%s natnetwork %s start --netname <name>\n\n"
885 "%s natnetwork %s stop --netname <name>\n\n"
886 "%s natnetwork %s list [<pattern>]\n"
887 "\n", SEP, SEP, SEP, SEP, SEP, SEP);
888
889
890 }
891#endif
892
893#if defined(VBOX_WITH_NETFLT)
894 if (enmCommand == USAGE_HOSTONLYIFS || enmCommand == USAGE_S_ALL)
895 {
896 RTStrmPrintf(pStrm,
897 "%s hostonlyif %s ipconfig <name>\n"
898 " [--dhcp |\n"
899 " --ip <ipv4> [--netmask <ipv4> (def:255.255.255.0)]|\n"
900 " --ipv6 <ipv6> [--netmasklengthv6 <N> (def:64)]]", SEP);
901# if !defined(RT_OS_SOLARIS) || defined(VBOX_ONLY_DOCS)
902 RTStrmPrintf(pStrm,
903 " |\n"
904 " create |\n"
905 " remove <name>\n");
906# else
907 RTStrmPrintf(pStrm,
908 "\n");
909# endif
910 RTStrmPrintf(pStrm,
911 "\n");
912 }
913#endif
914
915 if (enmCommand == USAGE_USBDEVSOURCE || enmCommand == USAGE_S_ALL)
916 {
917 RTStrmPrintf(pStrm,
918 "%s usbdevsource %s add <source name>\n"
919 " --backend <backend>\n"
920 " --address <address>\n"
921 "%s usbdevsource %s remove <source name>\n"
922 "\n", SEP, SEP);
923 }
924
925#ifndef VBOX_ONLY_DOCS /* Converted to man page, not needed. */
926 if (enmCommand == USAGE_S_ALL)
927 {
928 uint32_t cPendingBlankLines = 0;
929 for (uint32_t i = 0; i < g_cHelpEntries; i++)
930 {
931 PCRTMSGREFENTRY pHelp = g_apHelpEntries[i];
932 while (cPendingBlankLines-- > 0)
933 RTStrmPutCh(pStrm, '\n');
934 RTStrmPrintf(pStrm, " %c%s:\n", RT_C_TO_UPPER(pHelp->pszBrief[0]), pHelp->pszBrief + 1);
935 cPendingBlankLines = 0;
936 RTMsgRefEntryPrintStringTable(pStrm, &pHelp->Synopsis, RTMSGREFENTRYSTR_SCOPE_GLOBAL,
937 &cPendingBlankLines, NULL /*pcLinesWritten*/);
938 cPendingBlankLines = RT_MAX(cPendingBlankLines, 1);
939 }
940 }
941#endif
942}
943
944/**
945 * Print a usage synopsis and the syntax error message.
946 * @returns RTEXITCODE_SYNTAX.
947 */
948RTEXITCODE errorSyntax(USAGECATEGORY enmCommand, const char *pszFormat, ...)
949{
950 va_list args;
951 showLogo(g_pStdErr); // show logo even if suppressed
952#ifndef VBOX_ONLY_DOCS
953 if (g_fInternalMode)
954 printUsageInternal(enmCommand, g_pStdErr);
955 else if (g_enmCurCommand == HELP_CMD_VBOXMANAGE_INVALID)
956 printUsage(enmCommand, RTMSGREFENTRYSTR_SCOPE_GLOBAL, g_pStdErr);
957 else
958 printUsage(g_pStdErr);
959#else
960 RT_NOREF_PV(enmCommand);
961#endif
962 va_start(args, pszFormat);
963 RTStrmPrintf(g_pStdErr, Help::tr("\nSyntax error: %N\n"), pszFormat, &args);
964 va_end(args);
965 return RTEXITCODE_SYNTAX;
966}
967
968/**
969 * Print a usage synopsis and the syntax error message.
970 * @returns RTEXITCODE_SYNTAX.
971 */
972RTEXITCODE errorSyntaxEx(USAGECATEGORY enmCommand, uint64_t fSubcommandScope, const char *pszFormat, ...)
973{
974 va_list args;
975 showLogo(g_pStdErr); // show logo even if suppressed
976#ifndef VBOX_ONLY_DOCS
977 if (g_fInternalMode)
978 printUsageInternal(enmCommand, g_pStdErr);
979 else if (g_enmCurCommand == HELP_CMD_VBOXMANAGE_INVALID)
980 printUsage(enmCommand, fSubcommandScope, g_pStdErr);
981 else
982 printUsage(g_pStdErr);
983#else
984 RT_NOREF2(enmCommand, fSubcommandScope);
985#endif
986 va_start(args, pszFormat);
987 RTStrmPrintf(g_pStdErr, Help::tr("\nSyntax error: %N\n"), pszFormat, &args);
988 va_end(args);
989 return RTEXITCODE_SYNTAX;
990}
991
992/**
993 * errorSyntax for RTGetOpt users.
994 *
995 * @returns RTEXITCODE_SYNTAX.
996 *
997 * @param enmCommand The command.
998 * @param fSubcommandScope The subcommand scope, REFENTRYSTR_SCOPE_GLOBAL
999 * for all.
1000 * @param rc The RTGetOpt return code.
1001 * @param pValueUnion The value union.
1002 */
1003RTEXITCODE errorGetOptEx(USAGECATEGORY enmCommand, uint64_t fSubcommandScope, int rc, union RTGETOPTUNION const *pValueUnion)
1004{
1005 /*
1006 * Check if it is an unhandled standard option.
1007 */
1008#ifndef VBOX_ONLY_DOCS
1009 if (rc == 'V')
1010 {
1011 RTPrintf("%sr%d\n", VBOX_VERSION_STRING, RTBldCfgRevision());
1012 return RTEXITCODE_SUCCESS;
1013 }
1014#endif
1015
1016 if (rc == 'h')
1017 {
1018 showLogo(g_pStdErr);
1019#ifndef VBOX_ONLY_DOCS
1020 if (g_fInternalMode)
1021 printUsageInternal(enmCommand, g_pStdOut);
1022 else if (g_enmCurCommand == HELP_CMD_VBOXMANAGE_INVALID)
1023 printUsage(enmCommand, fSubcommandScope, g_pStdOut);
1024 else
1025 printUsage(g_pStdErr);
1026#endif
1027 return RTEXITCODE_SUCCESS;
1028 }
1029
1030 /*
1031 * General failure.
1032 */
1033 showLogo(g_pStdErr); // show logo even if suppressed
1034#ifndef VBOX_ONLY_DOCS
1035 if (g_fInternalMode)
1036 printUsageInternal(enmCommand, g_pStdErr);
1037 else if (g_enmCurCommand == HELP_CMD_VBOXMANAGE_INVALID)
1038 printUsage(enmCommand, fSubcommandScope, g_pStdErr);
1039 else
1040 printUsage(g_pStdErr);
1041#else
1042 RT_NOREF2(enmCommand, fSubcommandScope);
1043#endif
1044
1045 if (rc == VINF_GETOPT_NOT_OPTION)
1046 return RTMsgErrorExit(RTEXITCODE_SYNTAX, Help::tr("Invalid parameter '%s'"), pValueUnion->psz);
1047 if (rc > 0)
1048 {
1049 if (RT_C_IS_PRINT(rc))
1050 return RTMsgErrorExit(RTEXITCODE_SYNTAX, Help::tr("Invalid option -%c"), rc);
1051 return RTMsgErrorExit(RTEXITCODE_SYNTAX, Help::tr("Invalid option case %i"), rc);
1052 }
1053 if (rc == VERR_GETOPT_UNKNOWN_OPTION)
1054 return RTMsgErrorExit(RTEXITCODE_SYNTAX, Help::tr("Unknown option: %s"), pValueUnion->psz);
1055 if (rc == VERR_GETOPT_INVALID_ARGUMENT_FORMAT)
1056 return RTMsgErrorExit(RTEXITCODE_SYNTAX, Help::tr("Invalid argument format: %s"), pValueUnion->psz);
1057 if (pValueUnion->pDef)
1058 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "%s: %Rrs", pValueUnion->pDef->pszLong, rc);
1059 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "%Rrs", rc);
1060}
1061
1062/**
1063 * errorSyntax for RTGetOpt users.
1064 *
1065 * @returns RTEXITCODE_SYNTAX.
1066 *
1067 * @param enmCommand The command.
1068 * @param rc The RTGetOpt return code.
1069 * @param pValueUnion The value union.
1070 */
1071RTEXITCODE errorGetOpt(USAGECATEGORY enmCommand, int rc, union RTGETOPTUNION const *pValueUnion)
1072{
1073 return errorGetOptEx(enmCommand, RTMSGREFENTRYSTR_SCOPE_GLOBAL, rc, pValueUnion);
1074}
1075
1076/**
1077 * Print an error message without the syntax stuff.
1078 *
1079 * @returns RTEXITCODE_SYNTAX.
1080 */
1081RTEXITCODE errorArgument(const char *pszFormat, ...)
1082{
1083 va_list args;
1084 va_start(args, pszFormat);
1085 RTMsgErrorV(pszFormat, args);
1086 va_end(args);
1087 return RTEXITCODE_SYNTAX;
1088}
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