2 * vsh.c: common data to be used by clients to exercise the libvirt API
4 * Copyright (C) 2005-2019 Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see
18 * <http://www.gnu.org/licenses/>.
32 /* In order to have proper rl_message declaration with older
33 * versions of readline, we have to declare this. See 9ea3424a178
35 # define HAVE_STDARG_H
36 # include <readline/readline.h>
37 # include <readline/history.h>
41 #include "virbuffer.h"
44 #include "virthread.h"
45 #include "vircommand.h"
46 #include "virstring.h"
50 /* For autocompletion */
51 vshControl
*autoCompleteOpaque
;
54 /* NOTE: It would be much nicer to have these two as part of vshControl
55 * structure, unfortunately readline doesn't support passing opaque data
56 * and only relies on static data accessible from the user-side callback
58 const vshCmdGrp
*cmdGroups
;
62 vshPrettyCapacity(unsigned long long val
, const char **unit
)
73 return val
/ (limit
/ 1024);
78 return val
/ (limit
/ 1024);
83 return val
/ (limit
/ 1024);
88 return val
/ (limit
/ 1024);
93 return val
/ (limit
/ 1024);
97 return val
/ (limit
/ 1024);
102 vshNameSorter(const void *a
, const void *b
)
104 const char **sa
= (const char**)a
;
105 const char **sb
= (const char**)b
;
107 return vshStrcasecmp(*sa
, *sb
);
112 * Convert the strings separated by ',' into array. The returned
113 * array is a NULL terminated string list. The caller has to free
114 * the array using g_strfreev or a similar method.
116 * Returns the length of the filled array on success, or -1
120 vshStringToArray(const char *str
,
123 g_auto(GStrv
) tmp
= NULL
;
128 tmp
= g_strsplit(str
, ",", 0);
130 *array
= g_new0(char *, g_strv_length(tmp
) + 1);
131 (*array
)[ntoks
++] = g_strdup(tmp
[0]);
133 /* undo splitting of comma escape (',,') by concatenating back on empty strings */
134 for (n
= tmp
+ 1; n
[0]; n
++) {
136 g_autofree
char *old
= (*array
)[ntoks
- 1];
138 (*array
)[ntoks
- 1] = g_strconcat(old
, ",", n
[0], NULL
);
143 if (strlen(n
[0]) == 0) {
146 (*array
)[ntoks
++] = g_strdup(n
[0]);
150 /* corner case of ending with a single comma */
152 (*array
)[ntoks
++] = g_strdup("");
157 virErrorPtr last_error
;
160 * Quieten libvirt until we're done with the command.
163 vshErrorHandler(void *opaque G_GNUC_UNUSED
,
164 virErrorPtr error G_GNUC_UNUSED
)
166 virFreeError(last_error
);
167 last_error
= virSaveLastError();
170 /* Store a libvirt error that is from a helper API that doesn't raise errors
171 * so it doesn't get overwritten */
173 vshSaveLibvirtError(void)
175 virFreeError(last_error
);
176 last_error
= virSaveLastError();
180 /* Store libvirt error from helper API but don't overwrite existing errors */
182 vshSaveLibvirtHelperError(void)
187 if (virGetLastErrorCode() == VIR_ERR_OK
)
190 vshSaveLibvirtError();
195 * Reset libvirt error on graceful fallback paths
198 vshResetLibvirtError(void)
200 g_clear_pointer(&last_error
, virFreeError
);
205 * Report an error when a command finishes. This is better than before
206 * (when correct operation would report errors), but it has some
207 * problems: we lose the smarter formatting of virDefaultErrorFunc(),
208 * and it can become harder to debug problems, if errors get reported
209 * twice during one command. This case shouldn't really happen anyway,
210 * and it's IMHO a bug that libvirt does that sometimes.
213 vshReportError(vshControl
*ctl
)
215 if (last_error
== NULL
) {
216 /* Calling directly into libvirt util functions won't trigger the
217 * error callback (which sets last_error), so check it ourselves.
219 * If the returned error has CODE_OK, this most likely means that
220 * no error was ever raised, so just ignore */
221 last_error
= virSaveLastError();
222 if (!last_error
|| last_error
->code
== VIR_ERR_OK
)
226 if (last_error
->code
== VIR_ERR_OK
) {
227 vshError(ctl
, "%s", _("unknown error"));
231 vshError(ctl
, "%s", last_error
->message
);
234 vshResetLibvirtError();
238 * Detection of disconnections and automatic reconnection support
240 static int disconnected
; /* we may have been disconnected */
242 /* Check if the internal command definitions are correct.
243 * None of the errors are to be marked as translatable. */
245 vshCmddefCheckInternals(vshControl
*ctl
,
246 const vshCmdDef
*cmd
,
247 bool missingCompleters
)
250 bool seenOptionalOption
= false;
251 const char *seenOptionalPositionalOption
= NULL
;
252 g_auto(virBuffer
) complbuf
= VIR_BUFFER_INITIALIZER
;
254 /* in order to perform the validation resolve the alias first */
256 const vshCmdDef
*alias
;
258 if (!(alias
= vshCmddefSearch(cmd
->alias
))) {
259 vshError(ctl
, "command alias '%s' is pointing to a non-existent command '%s'",
260 cmd
->name
, cmd
->alias
);
265 vshError(ctl
, "command alias '%s' is pointing to another command alias '%s'",
266 cmd
->name
, cmd
->alias
);
271 vshError(ctl
, "command '%s' has handler set", cmd
->name
);
276 vshError(ctl
, "command '%s' has options set", cmd
->name
);
281 vshError(ctl
, "command '%s' has info set", cmd
->name
);
285 if (cmd
->flags
!= 0) {
286 vshError(ctl
, "command '%s' has multiple flags set", cmd
->name
);
290 /* we don't need to continue as the real command will be checked separately */
294 /* Each command has to provide a non-empty help string. */
295 if (!cmd
->info
|| !cmd
->info
->help
|| !*cmd
->info
->help
) {
296 vshError(ctl
, "command '%s' lacks help", cmd
->name
);
303 for (i
= 0; cmd
->opts
[i
].name
; i
++) {
304 const vshCmdOptDef
*opt
= &cmd
->opts
[i
];
307 vshError(ctl
, "command '%s' has too many options", cmd
->name
);
308 return -1; /* too many options */
311 if (missingCompleters
&& !opt
->completer
) {
315 virBufferStrcat(&complbuf
, opt
->name
, ", ", NULL
);
319 /* only name is completed */
321 /* no point in completing numbers */
323 /* alias is handled in the referenced command */
329 /* allow at most one optional positional option */
330 if (opt
->positional
&& !opt
->required
) {
331 if (seenOptionalPositionalOption
) {
332 vshError(ctl
, "multiple optional positional arguments (%s, %s) of command '%s' are not allowed",
333 seenOptionalPositionalOption
, opt
->name
, cmd
->name
);
337 seenOptionalPositionalOption
= opt
->name
;
340 /* all optional positional arguments must be defined after the required ones */
341 if (seenOptionalPositionalOption
&& opt
->positional
&& opt
->required
) {
342 vshError(ctl
, "required positional argument '%s' declared after an optional positional argument '%s' of command '%s'",
343 opt
->name
, seenOptionalPositionalOption
, cmd
->name
);
347 /* Mandate no completer flags if no completer is specified */
348 if (opt
->completer_flags
!= 0 && !opt
->completer
) {
349 vshError(ctl
, "completer_flags of argument '%s' of command '%s' must be 0 if no completer is used",
350 opt
->name
, cmd
->name
);
354 if (opt
->unwanted_positional
&& opt
->positional
) {
355 vshError(ctl
, "unwanted_positional flag of argument '%s' of command '%s' must not be used together with positional",
356 opt
->name
, cmd
->name
);
362 vshError(ctl
, "invalid type 'NONE' of option '%s' of command '%s'",
363 opt
->name
, cmd
->name
);
367 if (opt
->completer
) {
368 vshError(ctl
, "bool parameter '%s' of command '%s' has completer set",
369 opt
->name
, cmd
->name
);
373 if (opt
->positional
|| opt
->unwanted_positional
) {
374 vshError(ctl
, "boolean parameter '%s' of command '%s' must not be positional",
375 opt
->name
, cmd
->name
);
380 vshError(ctl
, "parameter '%s' of command '%s' misused 'required' flag",
381 opt
->name
, cmd
->name
);
382 return -1; /* bool can't be mandatory */
389 g_autofree
char *name
= NULL
;
394 opt
->unwanted_positional
||
397 vshError(ctl
, "parameter '%s' of command '%s' has incorrect alias option",
398 opt
->name
, cmd
->name
);
401 if ((p
= strchr(opt
->help
, '=')))
402 name
= g_strndup(opt
->help
, p
- opt
->help
);
404 name
= g_strdup(opt
->help
);
405 for (j
= i
+ 1; cmd
->opts
[j
].name
; j
++) {
406 if (STREQ(name
, cmd
->opts
[j
].name
) &&
407 cmd
->opts
[j
].type
!= VSH_OT_ALIAS
)
411 /* If alias comes with value, replacement must not be bool */
412 if (cmd
->opts
[j
].type
== VSH_OT_BOOL
) {
413 vshError(ctl
, "alias '%s' of command '%s' has mismatched alias type",
414 opt
->name
, cmd
->name
);
418 if (!cmd
->opts
[j
].name
) {
419 vshError(ctl
, "alias '%s' of command '%s' has missing alias option",
420 opt
->name
, cmd
->name
);
427 if (cmd
->opts
[i
+ 1].name
) {
428 vshError(ctl
, "parameter '%s' of command '%s' must be listed last",
429 opt
->name
, cmd
->name
);
436 if (opt
->positional
&& seenOptionalOption
) {
437 vshError(ctl
, "parameter '%s' of command '%s' must be listed before optional parameters",
438 opt
->name
, cmd
->name
);
442 seenOptionalOption
= !opt
->required
;
447 virBufferTrim(&complbuf
, ", ");
449 if (missingCompleters
&& virBufferUse(&complbuf
) > 0)
450 vshPrintExtra(ctl
, "%s: %s\n", cmd
->name
, virBufferCurrentContent(&complbuf
));
455 /* Parse the options associated with @cmd, i.e. test whether options are
456 * required or need an argument and fill the appropriate caller-provided bitmaps
459 vshCmddefOptParse(const vshCmdDef
*cmd
,
460 uint64_t *opts_need_arg
,
461 uint64_t *opts_required
)
471 for (i
= 0; cmd
->opts
[i
].name
; i
++) {
472 const vshCmdOptDef
*opt
= &cmd
->opts
[i
];
474 if (opt
->type
== VSH_OT_BOOL
)
477 if (opt
->type
== VSH_OT_ALIAS
)
478 continue; /* skip the alias option */
480 if (opt
->positional
|| opt
->unwanted_positional
)
481 *opts_need_arg
|= 1ULL << i
;
484 *opts_required
|= 1ULL << i
;
488 static vshCmdOptDef helpopt
= {
491 .help
= N_("print help for this function")
494 static const vshCmdOptDef
*
495 vshCmddefGetOption(vshControl
*ctl
,
496 const vshCmdDef
*cmd
,
504 g_autofree
char *alias
= NULL
;
506 if (STREQ(name
, helpopt
.name
))
509 for (i
= 0; cmd
->opts
&& cmd
->opts
[i
].name
; i
++) {
510 const vshCmdOptDef
*opt
= &cmd
->opts
[i
];
512 if (STRNEQ(opt
->name
, name
))
515 if (opt
->type
== VSH_OT_ALIAS
) {
518 /* Two types of replacements:
519 opt->help = "string": straight replacement of name
520 opt->help = "string=value": treat boolean flag as
521 alias of option and its default value */
522 alias
= g_strdup(opt
->help
);
524 if ((value
= strchr(name
, '='))) {
528 vshError(ctl
, _("invalid '=' after option --%1$s"),
532 *optstr
= g_strdup(value
+ 1);
537 if ((*opts_seen
& (1ULL << i
)) && opt
->type
!= VSH_OT_ARGV
) {
539 vshError(ctl
, _("option --%1$s already seen"), name
);
543 *opts_seen
|= 1ULL << i
;
548 /* The 'help' command ignores extra options */
549 if (STRNEQ(cmd
->name
, "help") && report
) {
550 vshError(ctl
, _("command '%1$s' doesn't support option --%2$s"),
556 static const vshCmdOptDef
*
557 vshCmddefGetData(const vshCmdDef
*cmd
, uint64_t *opts_need_arg
,
561 const vshCmdOptDef
*opt
;
566 /* Grab least-significant set bit */
567 i
= __builtin_ffsl(*opts_need_arg
) - 1;
569 if (opt
->type
!= VSH_OT_ARGV
)
570 *opts_need_arg
&= ~(1ULL << i
);
571 *opts_seen
|= 1ULL << i
;
576 * Checks for required options
579 vshCommandCheckOpts(vshControl
*ctl
, const vshCmd
*cmd
, uint64_t opts_required
,
582 const vshCmdDef
*def
= cmd
->def
;
585 opts_required
&= ~opts_seen
;
589 for (i
= 0; def
->opts
[i
].name
; i
++) {
590 if (opts_required
& (1ULL << i
)) {
591 const vshCmdOptDef
*opt
= &def
->opts
[i
];
595 _("command '%1$s' requires <%2$s> option") :
596 _("command '%1$s' requires --%2$s option"),
597 def
->name
, opt
->name
);
604 vshCmddefSearch(const char *cmdname
)
609 for (g
= cmdGroups
; g
->name
; g
++) {
610 for (c
= g
->commands
; c
->name
; c
++) {
611 if (STREQ(c
->name
, cmdname
))
620 vshCmdGrpSearch(const char *grpname
)
624 for (g
= cmdGroups
; g
->name
; g
++) {
625 if (STREQ(g
->name
, grpname
) || STREQ(g
->keyword
, grpname
))
633 vshCmdGrpHelp(vshControl
*ctl
, const vshCmdGrp
*grp
)
635 const vshCmdDef
*cmd
= NULL
;
637 vshPrint(ctl
, _(" %1$s (help keyword '%2$s'):\n"), grp
->name
,
640 for (cmd
= grp
->commands
; cmd
->name
; cmd
++) {
642 cmd
->flags
& VSH_CMD_FLAG_HIDDEN
)
644 vshPrint(ctl
, " %-30s %s\n", cmd
->name
, _(cmd
->info
->help
));
651 vshCmddefHelp(const vshCmdDef
*def
)
653 fputs(_(" NAME\n"), stdout
);
654 fprintf(stdout
, " %s - %s\n", def
->name
, _(def
->info
->help
));
656 fputs(_("\n SYNOPSIS\n"), stdout
);
657 fprintf(stdout
, " %s", def
->name
);
659 const vshCmdOptDef
*opt
;
660 for (opt
= def
->opts
; opt
->name
; opt
++) {
664 fprintf(stdout
, " [--%s]", opt
->name
);
670 fprintf(stdout
, " ");
672 fprintf(stdout
, " [");
675 if (opt
->positional
) {
676 fprintf(stdout
, "<%s>", opt
->name
);
678 if (opt
->type
== VSH_OT_INT
) {
679 fprintf(stdout
, _("--%1$s <number>"), opt
->name
);
681 fprintf(stdout
, _("--%1$s <string>"), opt
->name
);
686 fprintf(stdout
, "]");
690 if (opt
->positional
) {
692 fprintf(stdout
, " <%s>...", opt
->name
);
694 fprintf(stdout
, " [<%s>]...", opt
->name
);
698 fprintf(stdout
, _(" --%1$s <string>..."), opt
->name
);
700 fprintf(stdout
, _(" [--%1$s <string>]..."), opt
->name
);
707 /* aliases are intentionally undocumented */
714 if (def
->info
->desc
&& *def
->info
->desc
) {
715 /* Print the description only if it's not empty. */
716 fputs(_("\n DESCRIPTION\n"), stdout
);
717 fprintf(stdout
, " %s\n", _(def
->info
->desc
));
720 if (def
->opts
&& def
->opts
->name
) {
721 const vshCmdOptDef
*opt
;
722 fputs(_("\n OPTIONS\n"), stdout
);
723 for (opt
= def
->opts
; opt
->name
; opt
++) {
724 g_autofree
char *optstr
= NULL
;
728 optstr
= g_strdup_printf("--%s", opt
->name
);
732 if (opt
->positional
) {
733 optstr
= g_strdup_printf(_("[--%1$s] <number>"), opt
->name
);
735 optstr
= g_strdup_printf(_("--%1$s <number>"), opt
->name
);
740 if (opt
->positional
) {
741 optstr
= g_strdup_printf(_("[--%1$s] <string>"), opt
->name
);
743 optstr
= g_strdup_printf(_("--%1$s <string>"), opt
->name
);
748 if (opt
->positional
) {
749 optstr
= g_strdup_printf(_("[--%1$s] <string>..."), opt
->name
);
751 optstr
= g_strdup_printf(_("--%1$s <string>..."), opt
->name
);
760 fprintf(stdout
, " %-15s %s\n", optstr
, _(opt
->help
));
768 * Utils for work with runtime commands data
772 vshCommandOptFree(vshCmdOpt
* arg
)
782 /* 'argv' doesn't own the strings themselves */
784 g_free(tmp
->argvstr
);
790 vshCommandFree(vshCmd
*cmd
)
799 vshCommandOptFree(tmp
->opts
);
804 G_DEFINE_AUTOPTR_CLEANUP_FUNC(vshCmd
, vshCommandFree
);
808 * @cmd: parsed command line to search
809 * @name: option name to search for
810 * @opt: result of the search
811 * @needData: true if option must be non-boolean
813 * Look up an option passed to CMD by NAME. Returns 1 with *OPT set
814 * to the option if found, 0 with *OPT set to NULL if the name is
815 * valid and the option is not required, -1 with *OPT set to NULL if
816 * the option is required but not present, and assert if NAME is not
817 * valid (which indicates a programming error) unless cmd->skipChecks
818 * is set. No error messages are issued if a value is returned.
821 vshCommandOpt(const vshCmd
*cmd
, const char *name
, vshCmdOpt
**opt
,
824 vshCmdOpt
*candidate
= cmd
->opts
;
825 const vshCmdOptDef
*valid
= cmd
->def
->opts
;
828 /* See if option is valid and/or required. */
831 while (valid
&& valid
->name
) {
832 if (STREQ(name
, valid
->name
))
837 if (!cmd
->skipChecks
)
838 assert(valid
&& (!needData
|| valid
->type
!= VSH_OT_BOOL
));
840 if (valid
&& valid
->required
)
843 /* See if option is present on command line. */
845 if (STREQ(candidate
->def
->name
, name
)) {
850 candidate
= candidate
->next
;
857 * @ctl virtshell control structure
858 * @cmd command reference
862 * Convert option to int.
863 * On error, a message is displayed.
866 * >0 if option found and valid (@value updated)
867 * 0 if option not found and not required (@value untouched)
868 * <0 in all other cases (@value untouched)
871 vshCommandOptInt(vshControl
*ctl
, const vshCmd
*cmd
,
872 const char *name
, int *value
)
877 if ((ret
= vshCommandOpt(cmd
, name
, &arg
, true)) <= 0)
880 if ((ret
= virStrToLong_i(arg
->data
, NULL
, 10, value
)) < 0)
882 _("Numeric value '%1$s' for <%2$s> option is malformed or out of range"),
891 vshCommandOptUIntInternal(vshControl
*ctl
,
900 if ((ret
= vshCommandOpt(cmd
, name
, &arg
, true)) <= 0)
904 ret
= virStrToLong_ui(arg
->data
, NULL
, 10, value
);
906 ret
= virStrToLong_uip(arg
->data
, NULL
, 10, value
);
909 _("Numeric value '%1$s' for <%2$s> option is malformed or out of range"),
919 * @ctl virtshell control structure
920 * @cmd command reference
924 * Convert option to unsigned int, reject negative numbers
925 * See vshCommandOptInt()
928 vshCommandOptUInt(vshControl
*ctl
, const vshCmd
*cmd
,
929 const char *name
, unsigned int *value
)
931 return vshCommandOptUIntInternal(ctl
, cmd
, name
, value
, false);
935 * vshCommandOptUIntWrap:
936 * @ctl virtshell control structure
937 * @cmd command reference
941 * Convert option to unsigned int, wraps negative numbers to positive
942 * See vshCommandOptInt()
945 vshCommandOptUIntWrap(vshControl
*ctl
, const vshCmd
*cmd
,
946 const char *name
, unsigned int *value
)
948 return vshCommandOptUIntInternal(ctl
, cmd
, name
, value
, true);
952 vshCommandOptULInternal(vshControl
*ctl
,
955 unsigned long *value
,
961 if ((ret
= vshCommandOpt(cmd
, name
, &arg
, true)) <= 0)
965 ret
= virStrToLong_ul(arg
->data
, NULL
, 10, value
);
967 ret
= virStrToLong_ulp(arg
->data
, NULL
, 10, value
);
970 _("Numeric value '%1$s' for <%2$s> option is malformed or out of range"),
980 * @ctl virtshell control structure
981 * @cmd command reference
985 * Convert option to unsigned long
986 * See vshCommandOptInt()
989 vshCommandOptUL(vshControl
*ctl
, const vshCmd
*cmd
,
990 const char *name
, unsigned long *value
)
992 return vshCommandOptULInternal(ctl
, cmd
, name
, value
, false);
996 * vshCommandOptULWrap:
997 * @ctl virtshell control structure
998 * @cmd command reference
1002 * Convert option to unsigned long, wraps negative numbers to positive
1003 * See vshCommandOptInt()
1006 vshCommandOptULWrap(vshControl
*ctl
, const vshCmd
*cmd
,
1007 const char *name
, unsigned long *value
)
1009 return vshCommandOptULInternal(ctl
, cmd
, name
, value
, true);
1013 * vshCommandOptStringQuiet:
1014 * @ctl virtshell control structure
1015 * @cmd command reference
1019 * Returns option as STRING. On error -1 is returned but no error is set.
1021 * >0 if option found and valid (@value updated)
1022 * 0 if option not found and not required (@value untouched)
1023 * <0 in all other cases (@value untouched)
1026 vshCommandOptStringQuiet(vshControl
*ctl G_GNUC_UNUSED
, const vshCmd
*cmd
,
1027 const char *name
, const char **value
)
1032 if ((ret
= vshCommandOpt(cmd
, name
, &arg
, true)) <= 0)
1035 if (!arg
->def
->allowEmpty
&& *arg
->data
== '\0')
1042 * vshCommandOptString:
1043 * @ctl virtshell control structure
1044 * @cmd command structure
1046 * @value result (updated to NULL or the option argument)
1048 * Gets a option argument as string.
1050 * Returns 0 on success or when the option is not present and not
1051 * required, *value is set to the option argument. On error -1 is
1052 * returned and error message printed.
1055 vshCommandOptString(vshControl
*ctl
,
1062 const char *error
= NULL
;
1064 /* clear out the value */
1067 ret
= vshCommandOpt(cmd
, name
, &arg
, true);
1068 /* option is not required and not present */
1071 /* this should not be propagated here, just to be sure */
1073 error
= N_("Mandatory option not present");
1074 else if (arg
&& *arg
->data
== '\0' && !arg
->def
->allowEmpty
)
1075 error
= N_("Option argument is empty");
1078 if (!cmd
->skipChecks
)
1079 vshError(ctl
, _("Failed to get option '%1$s': %2$s"), name
, _(error
));
1088 * vshCommandOptLongLong:
1089 * @ctl virtshell control structure
1090 * @cmd command reference
1094 * Returns option as long long
1095 * See vshCommandOptInt()
1098 vshCommandOptLongLong(vshControl
*ctl
, const vshCmd
*cmd
,
1099 const char *name
, long long *value
)
1104 if ((ret
= vshCommandOpt(cmd
, name
, &arg
, true)) <= 0)
1107 if ((ret
= virStrToLong_ll(arg
->data
, NULL
, 10, value
)) < 0)
1109 _("Numeric value '%1$s' for <%2$s> option is malformed or out of range"),
1118 vshCommandOptULongLongInternal(vshControl
*ctl
,
1121 unsigned long long *value
,
1127 if ((ret
= vshCommandOpt(cmd
, name
, &arg
, true)) <= 0)
1131 ret
= virStrToLong_ull(arg
->data
, NULL
, 10, value
);
1133 ret
= virStrToLong_ullp(arg
->data
, NULL
, 10, value
);
1136 _("Numeric value '%1$s' for <%2$s> option is malformed or out of range"),
1145 * vshCommandOptULongLong:
1146 * @ctl virtshell control structure
1147 * @cmd command reference
1151 * Returns option as long long, rejects negative numbers
1152 * See vshCommandOptInt()
1155 vshCommandOptULongLong(vshControl
*ctl
, const vshCmd
*cmd
,
1156 const char *name
, unsigned long long *value
)
1158 return vshCommandOptULongLongInternal(ctl
, cmd
, name
, value
, false);
1162 * vshCommandOptULongLongWrap:
1163 * @ctl virtshell control structure
1164 * @cmd command reference
1168 * Returns option as long long, wraps negative numbers to positive
1169 * See vshCommandOptInt()
1172 vshCommandOptULongLongWrap(vshControl
*ctl
, const vshCmd
*cmd
,
1173 const char *name
, unsigned long long *value
)
1175 return vshCommandOptULongLongInternal(ctl
, cmd
, name
, value
, true);
1179 * vshCommandOptScaledInt:
1180 * @ctl virtshell control structure
1181 * @cmd command reference
1184 * @scale default of 1 or 1024, if no suffix is present
1185 * @max maximum value permitted
1187 * Returns option as long long, scaled according to suffix
1188 * See vshCommandOptInt()
1191 vshCommandOptScaledInt(vshControl
*ctl
, const vshCmd
*cmd
,
1192 const char *name
, unsigned long long *value
,
1193 int scale
, unsigned long long max
)
1199 if ((ret
= vshCommandOpt(cmd
, name
, &arg
, true)) <= 0)
1202 if (virStrToLong_ullp(arg
->data
, &end
, 10, value
) < 0 ||
1203 virScaleInteger(value
, end
, scale
, max
) < 0) {
1205 _("Scaled numeric value '%1$s' for <%2$s> option is malformed or out of range"),
1215 * vshCommandOptBool:
1216 * @cmd command reference
1219 * Returns true/false if the option exists. Note that this does NOT
1220 * validate whether the option is actually boolean, or even whether
1221 * name is legal; so that this can be used to probe whether a data
1222 * option is present without actually using that data.
1225 vshCommandOptBool(const vshCmd
*cmd
, const char *name
)
1229 return vshCommandOpt(cmd
, name
, &dummy
, false) == 1;
1234 vshCommandOptArgvInternal(const vshCmd
*cmd
,
1237 vshCmdOpt
*first
= NULL
;
1240 size_t nargv_alloc
= 0;
1242 for (opt
= cmd
->opts
; opt
; opt
= opt
->next
) {
1243 if (STRNEQ(opt
->def
->name
, name
))
1247 /* Return existing data if we'we already processed it */
1254 /* extra NULL terminator */
1255 VIR_RESIZE_N(first
->argv
, nargv_alloc
, nargv
, 2);
1256 first
->argv
[nargv
++] = opt
->data
;
1260 first
->argvstr
= g_strjoinv(" ", (GStrv
) first
->argv
);
1267 * vshCommandOptArgv:
1268 * @cmd: command reference
1269 * @name: name of argument
1271 * Returns a NULL terminated list of strings of values passed as argument of
1272 * ARGV argument named @name. The returned string list is owned by @cmd and
1273 * caller must not free or modify it.
1276 vshCommandOptArgv(const vshCmd
*cmd
,
1279 vshCmdOpt
*opt
= vshCommandOptArgvInternal(cmd
, name
);
1289 * vshCommandOptArgvString:
1290 * @cmd: command reference
1291 * @name: name of argument
1293 * Returns a string containing all values passed as ARGV argument @name
1294 * delimited/concatenated by adding spaces.
1297 vshCommandOptArgvString(const vshCmd
*cmd
,
1300 vshCmdOpt
*opt
= vshCommandOptArgvInternal(cmd
, name
);
1305 return opt
->argvstr
;
1310 * vshBlockJobOptionBandwidth:
1311 * @ctl: virsh control data
1312 * @cmd: virsh command description
1313 * @bytes: return bandwidth in bytes/s instead of MiB/s
1314 * @bandwidth: return value
1316 * Extracts the value of --bandwidth either as a wrap-able number without scale
1317 * or as a scaled integer. The returned value is checked to fit into a unsigned
1318 * long data type. This is a legacy compatibility function and it should not
1319 * be used for things other the block job APIs.
1321 * Returns 0 on success, -1 on error.
1324 vshBlockJobOptionBandwidth(vshControl
*ctl
,
1327 unsigned long *bandwidth
)
1331 unsigned long long bw
;
1334 if ((ret
= vshCommandOpt(cmd
, "bandwidth", &arg
, true)) <= 0)
1337 /* due to historical reasons we declare to parse negative numbers and wrap
1338 * them to the unsigned data type. */
1339 if (virStrToLong_ul(arg
->data
, NULL
, 10, bandwidth
) < 0) {
1340 /* try to parse the number as scaled size in this case we don't accept
1341 * wrapping since it would be ridiculous. In case of a 32 bit host,
1342 * limit the value to ULONG_MAX */
1343 if (virStrToLong_ullp(arg
->data
, &end
, 10, &bw
) < 0 ||
1344 virScaleInteger(&bw
, end
, 1, ULONG_MAX
) < 0) {
1346 _("Scaled numeric value '%1$s' for <--bandwidth> option is malformed or out of range"),
1362 * Executes command(s) and returns return code from last command
1365 vshCommandRun(vshControl
*ctl
, const vshCmd
*cmd
)
1367 const vshClientHooks
*hooks
= ctl
->hooks
;
1371 gint64 before
, after
;
1372 bool enable_timing
= ctl
->timing
;
1374 before
= g_get_real_time();
1376 if ((cmd
->def
->flags
& VSH_CMD_FLAG_NOCONNECT
) ||
1377 (hooks
&& hooks
->connHandler
&& hooks
->connHandler(ctl
))) {
1378 ret
= cmd
->def
->handler(ctl
, cmd
);
1380 /* connection is not usable, return error */
1384 after
= g_get_real_time();
1386 /* try to automatically catch disconnections */
1388 ((last_error
!= NULL
) &&
1389 (((last_error
->code
== VIR_ERR_SYSTEM_ERROR
) &&
1390 (last_error
->domain
== VIR_FROM_REMOTE
)) ||
1391 (last_error
->code
== VIR_ERR_RPC
) ||
1392 (last_error
->code
== VIR_ERR_NO_CONNECT
) ||
1393 (last_error
->code
== VIR_ERR_INVALID_CONN
))))
1397 vshReportError(ctl
);
1399 if (STREQ(cmd
->def
->name
, "quit") ||
1400 STREQ(cmd
->def
->name
, "exit")) /* hack ... */
1403 if (enable_timing
) {
1404 double diff_ms
= (after
- before
) / 1000.0;
1406 vshPrint(ctl
, _("\n(Time: %1$.3f ms)\n\n"), diff_ms
);
1408 vshPrintExtra(ctl
, "\n");
1421 VSH_TK_ERROR
, /* Failed to parse a token */
1422 VSH_TK_ARG
, /* Arbitrary argument, might be option or empty */
1423 VSH_TK_SUBCMD_END
, /* Separation between commands */
1424 VSH_TK_END
/* No more commands */
1427 typedef struct _vshCommandParser vshCommandParser
;
1428 struct _vshCommandParser
{
1429 vshCommandToken(*getNextArg
)(vshControl
*, vshCommandParser
*,
1431 /* vshCommandStringGetArg() */
1434 /* vshCommandArgvGetArg() */
1440 vshCommandParse(vshControl
*ctl
, vshCommandParser
*parser
, vshCmd
**partial
)
1442 char *tkdata
= NULL
;
1443 vshCmd
*clast
= NULL
;
1444 vshCmdOpt
*first
= NULL
;
1445 vshCmdOpt
*last
= NULL
;
1446 const vshCmdDef
*cmd
= NULL
;
1449 g_clear_pointer(&ctl
->cmd
, vshCommandFree
);
1454 bool data_only
= false;
1455 uint64_t opts_need_arg
= 0;
1456 uint64_t opts_required
= 0;
1457 uint64_t opts_seen
= 0;
1464 g_clear_pointer(partial
, vshCommandFree
);
1468 const vshCmdOptDef
*opt
= NULL
;
1471 tk
= parser
->getNextArg(ctl
, parser
, &tkdata
, true);
1473 if (tk
== VSH_TK_ERROR
)
1475 if (tk
!= VSH_TK_ARG
) {
1481 /* first token must be command name or comment */
1482 if (*tkdata
== '#') {
1485 tk
= parser
->getNextArg(ctl
, parser
, &tkdata
, false);
1486 } while (tk
== VSH_TK_ARG
);
1489 } else if (!(cmd
= vshCmddefSearch(tkdata
))) {
1491 vshError(ctl
, _("unknown command: '%1$s'"), tkdata
);
1492 goto syntaxError
; /* ... or ignore this command only? */
1495 /* aliases need to be resolved to the actual commands */
1498 tkdata
= g_strdup(cmd
->alias
);
1499 if (!(cmd
= vshCmddefSearch(tkdata
))) {
1500 /* self-test ensures that the alias exists */
1501 vshError(ctl
, _("unknown command: '%1$s'"), tkdata
);
1506 vshCmddefOptParse(cmd
, &opts_need_arg
, &opts_required
);
1508 } else if (data_only
) {
1510 } else if (tkdata
[0] == '-' && tkdata
[1] == '-' &&
1511 g_ascii_isalnum(tkdata
[2])) {
1512 char *optstr
= strchr(tkdata
+ 2, '=');
1513 size_t opt_index
= 0;
1516 *optstr
= '\0'; /* convert the '=' to '\0' */
1517 optstr
= g_strdup(optstr
+ 1);
1519 /* Special case 'help' to ignore all spurious options */
1520 if (!(opt
= vshCmddefGetOption(ctl
, cmd
, tkdata
+ 2,
1521 &opts_seen
, &opt_index
,
1522 &optstr
, partial
== NULL
))) {
1524 if (STREQ(cmd
->name
, "help"))
1530 if (opt
->type
!= VSH_OT_BOOL
) {
1535 tk
= parser
->getNextArg(ctl
, parser
, &tkdata
, partial
== NULL
);
1536 if (tk
== VSH_TK_ERROR
)
1538 if (tk
!= VSH_TK_ARG
) {
1540 vshCmdOpt
*arg
= g_new0(vshCmdOpt
, 1);
1542 arg
->data
= g_steal_pointer(&tkdata
);
1552 _("expected syntax: --%1$s <%2$s>"),
1555 VSH_OT_INT
? _("number") : _("string"));
1559 if (opt
->type
!= VSH_OT_ARGV
)
1560 opts_need_arg
&= ~(1ULL << opt_index
);
1565 vshError(ctl
, _("invalid '=' after option --%1$s"),
1571 } else if (tkdata
[0] == '-' && tkdata
[1] == '-' &&
1572 tkdata
[2] == '\0') {
1578 /* Special case 'help' to ignore spurious data */
1579 if (!(opt
= vshCmddefGetData(cmd
, &opts_need_arg
,
1581 STRNEQ(cmd
->name
, "help")) {
1583 vshError(ctl
, _("unexpected data '%1$s'"), tkdata
);
1589 vshCmdOpt
*arg
= g_new0(vshCmdOpt
, 1);
1592 arg
->data
= g_steal_pointer(&tkdata
);
1602 vshDebug(ctl
, VSH_ERR_INFO
, "%s: %s(%s): %s\n",
1605 opt
->type
!= VSH_OT_BOOL
? _("optdata") : _("bool"),
1606 opt
->type
!= VSH_OT_BOOL
? arg
->data
: _("(none)"));
1610 /* command parsed -- allocate new struct for the command */
1612 vshCmd
*c
= g_new0(vshCmd
, 1);
1613 vshCmdOpt
*tmpopt
= first
;
1615 /* if we encountered --help, replace parsed command with
1616 * 'help <cmdname>' */
1617 for (tmpopt
= first
; tmpopt
; tmpopt
= tmpopt
->next
) {
1618 const vshCmdDef
*help
;
1619 if (STRNEQ(tmpopt
->def
->name
, "help"))
1622 /* the self-test code ensures that help exists */
1623 if (!(help
= vshCmddefSearch("help")))
1626 vshCommandOptFree(first
);
1627 first
= g_new0(vshCmdOpt
, 1);
1628 first
->def
= help
->opts
;
1629 first
->data
= g_strdup(cmd
->name
);
1638 c
->opts
= g_steal_pointer(&first
);
1644 vshCommandCheckOpts(ctl
, c
, opts_required
, opts_seen
) < 0) {
1650 vshCommandFree(*partial
);
1661 if (tk
== VSH_TK_END
)
1671 tmp
= g_new0(vshCmd
, 1);
1673 tmp
->lastopt
= last
;
1678 g_clear_pointer(&ctl
->cmd
, vshCommandFree
);
1679 vshCommandOptFree(first
);
1685 /* --------------------
1686 * Command argv parsing
1687 * --------------------
1690 static vshCommandToken
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
1691 vshCommandArgvGetArg(vshControl
*ctl G_GNUC_UNUSED
,
1692 vshCommandParser
*parser
,
1694 bool report G_GNUC_UNUSED
)
1696 if (parser
->arg_pos
== parser
->arg_end
) {
1701 *res
= g_strdup(*parser
->arg_pos
);
1707 vshCommandArgvParse(vshControl
*ctl
, int nargs
, char **argv
)
1709 vshCommandParser parser
= { 0 };
1714 parser
.arg_pos
= argv
;
1715 parser
.arg_end
= argv
+ nargs
;
1716 parser
.getNextArg
= vshCommandArgvGetArg
;
1717 return vshCommandParse(ctl
, &parser
, NULL
);
1720 /* ----------------------
1721 * Command string parsing
1722 * ----------------------
1725 static vshCommandToken
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
1726 vshCommandStringGetArg(vshControl
*ctl
, vshCommandParser
*parser
, char **res
,
1729 bool single_quote
= false;
1730 bool double_quote
= false;
1731 char *p
= parser
->pos
;
1732 char *q
= g_strdup(p
);
1736 while (*p
== ' ' || *p
== '\t' || (*p
== '\\' && p
[1] == '\n'))
1737 p
+= 1 + (*p
== '\\');
1741 if (*p
== ';' || *p
== '\n') {
1742 parser
->pos
= ++p
; /* = \0 or begin of next command */
1743 return VSH_TK_SUBCMD_END
;
1745 if (*p
== '#') { /* Argument starting with # is comment to end of line */
1746 while (*p
&& *p
!= '\n')
1748 parser
->pos
= p
+ !!*p
;
1749 return VSH_TK_SUBCMD_END
;
1753 /* end of token is blank space or ';' */
1754 if (!double_quote
&& !single_quote
&&
1755 (*p
== ' ' || *p
== '\t' || *p
== ';' || *p
== '\n'))
1758 if (!double_quote
&& *p
== '\'') { /* single quote */
1759 single_quote
= !single_quote
;
1762 } else if (!single_quote
&& *p
== '\\') { /* escape */
1764 * The same as in shell, a \ in "" is an escaper,
1765 * but a \ in '' is not an escaper.
1770 vshError(ctl
, "%s", _("dangling \\"));
1771 return VSH_TK_ERROR
;
1772 } else if (*p
== '\n') {
1773 /* Elide backslash-newline entirely */
1777 } else if (!single_quote
&& *p
== '"') { /* double quote */
1778 double_quote
= !double_quote
;
1787 /* We have seen a double quote, but not it's companion
1788 * ending. It's valid though, in case when we're called
1789 * from completer (report = false), but it's not valid
1790 * when parsing real command (report= true). */
1792 vshError(ctl
, "%s", _("missing \""));
1793 return VSH_TK_ERROR
;
1804 * vshCommandStringParse:
1805 * @ctl virsh control structure
1806 * @cmdstr: string to parse
1807 * @partial: store partially parsed command here
1809 * Parse given string @cmdstr as a command and store it under
1810 * @ctl->cmd. For readline completion, if @partial is not NULL on
1811 * the input then errors in parsing are ignored (because user is
1812 * still in progress of writing the command string) and partially
1813 * parsed command is stored at *@partial (caller has to free it
1817 vshCommandStringParse(vshControl
*ctl
,
1821 vshCommandParser parser
= { 0 };
1823 if (cmdstr
== NULL
|| *cmdstr
== '\0')
1826 parser
.pos
= cmdstr
;
1827 parser
.getNextArg
= vshCommandStringGetArg
;
1828 return vshCommandParse(ctl
, &parser
, partial
);
1832 * virshCommandOptTimeoutToMs:
1833 * @ctl virsh control structure
1834 * @cmd command reference
1837 * Parse an optional --timeout parameter in seconds, but store the
1838 * value of the timeout in milliseconds.
1839 * See vshCommandOptInt()
1842 vshCommandOptTimeoutToMs(vshControl
*ctl
, const vshCmd
*cmd
, int *timeout
)
1845 unsigned int utimeout
;
1847 if ((ret
= vshCommandOptUInt(ctl
, cmd
, "timeout", &utimeout
)) <= 0)
1850 /* Ensure that the timeout is not zero and that we can convert
1851 * it from seconds to milliseconds without overflowing. */
1852 if (utimeout
== 0 || utimeout
> INT_MAX
/ 1000) {
1854 _("Numeric value '%1$u' for <%2$s> option is malformed or out of range"),
1859 *timeout
= ((int) utimeout
) * 1000;
1871 /* Return a non-NULL string representation of a typed parameter; exit on
1874 vshGetTypedParamValue(vshControl
*ctl
, virTypedParameterPtr item
)
1876 switch (item
->type
) {
1877 case VIR_TYPED_PARAM_INT
:
1878 return g_strdup_printf("%d", item
->value
.i
);
1881 case VIR_TYPED_PARAM_UINT
:
1882 return g_strdup_printf("%u", item
->value
.ui
);
1885 case VIR_TYPED_PARAM_LLONG
:
1886 return g_strdup_printf("%lld", item
->value
.l
);
1889 case VIR_TYPED_PARAM_ULLONG
:
1890 return g_strdup_printf("%llu", item
->value
.ul
);
1893 case VIR_TYPED_PARAM_DOUBLE
:
1894 return g_strdup_printf("%f", item
->value
.d
);
1897 case VIR_TYPED_PARAM_BOOLEAN
:
1898 return g_strdup(item
->value
.b
? _("yes") : _("no"));
1901 case VIR_TYPED_PARAM_STRING
:
1902 return g_strdup(item
->value
.s
);
1906 vshError(ctl
, _("unimplemented parameter type %1$d"), item
->type
);
1912 vshDebug(vshControl
*ctl
, int level
, const char *format
, ...)
1915 g_autofree
char *str
= NULL
;
1917 /* Aligning log levels to that of libvirt.
1918 * Traces with levels >= user-specified-level
1919 * gets logged into file
1921 if (level
< ctl
->debug
)
1924 va_start(ap
, format
);
1925 vshOutputLogFile(ctl
, level
, format
, ap
);
1928 va_start(ap
, format
);
1929 str
= g_strdup_vprintf(format
, ap
);
1937 vshPrintVa(vshControl
*ctl G_GNUC_UNUSED
,
1941 g_autofree
char *str
= NULL
;
1943 str
= g_strdup_vprintf(format
, ap
);
1950 vshPrintExtra(vshControl
*ctl
,
1956 if (ctl
&& ctl
->quiet
)
1959 va_start(ap
, format
);
1960 vshPrintVa(ctl
, format
, ap
);
1966 vshPrint(vshControl
*ctl
,
1972 va_start(ap
, format
);
1973 vshPrintVa(ctl
, format
, ap
);
1979 vshTTYIsInterruptCharacter(vshControl
*ctl G_GNUC_UNUSED
,
1980 const char chr G_GNUC_UNUSED
)
1984 ctl
->termattr
.c_cc
[VINTR
] == chr
)
1993 vshTTYAvailable(vshControl
*ctl
)
2000 vshTTYDisableInterrupt(vshControl
*ctl G_GNUC_UNUSED
)
2003 struct termios termset
= ctl
->termattr
;
2008 /* check if we need to set the terminal */
2009 if (termset
.c_cc
[VINTR
] == _POSIX_VDISABLE
)
2012 termset
.c_cc
[VINTR
] = _POSIX_VDISABLE
;
2013 termset
.c_lflag
&= ~ICANON
;
2015 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &termset
) < 0)
2024 vshTTYRestore(vshControl
*ctl G_GNUC_UNUSED
)
2030 if (tcsetattr(STDIN_FILENO
, TCSAFLUSH
, &ctl
->termattr
) < 0)
2039 vshTTYMakeRaw(vshControl
*ctl G_GNUC_UNUSED
,
2040 bool report_errors G_GNUC_UNUSED
)
2043 struct termios rawattr
= ctl
->termattr
;
2047 if (report_errors
) {
2049 _("unable to make terminal raw: console isn't a tty"));
2055 cfmakeraw(&rawattr
);
2057 if (tcsetattr(STDIN_FILENO
, TCSAFLUSH
, &rawattr
) < 0) {
2059 vshError(ctl
, _("unable to set tty attributes: %1$s"),
2070 vshError(vshControl
*ctl
, const char *format
, ...)
2073 g_autofree
char *str
= NULL
;
2076 va_start(ap
, format
);
2077 vshOutputLogFile(ctl
, VSH_ERR_ERROR
, format
, ap
);
2081 /* Most output is to stdout, but if someone ran virsh 2>&1, then
2082 * printing to stderr will not interleave correctly with stdout
2083 * unless we flush between every transition between streams. */
2085 fputs(_("error: "), stderr
);
2087 va_start(ap
, format
);
2088 str
= g_strdup_vprintf(format
, ap
);
2091 fprintf(stderr
, "%s\n", NULLSTR(str
));
2097 vshEventLoop(void *opaque
)
2099 vshControl
*ctl
= opaque
;
2103 VIR_WITH_MUTEX_LOCK_GUARD(&ctl
->lock
) {
2110 if (virEventRunDefaultImpl() < 0)
2111 vshReportError(ctl
);
2117 * Helpers for waiting for a libvirt event.
2120 /* We want to use SIGINT to cancel a wait; but as signal handlers
2121 * don't have an opaque argument, we have to use static storage. */
2123 static int vshEventFd
= -1;
2124 static struct sigaction vshEventOldAction
;
2127 /* Signal handler installed in vshEventStart, removed in vshEventCleanup. */
2129 vshEventInt(int sig G_GNUC_UNUSED
,
2130 siginfo_t
*siginfo G_GNUC_UNUSED
,
2131 void *context G_GNUC_UNUSED
)
2133 char reason
= VSH_EVENT_INTERRUPT
;
2134 if (vshEventFd
>= 0)
2135 ignore_value(safewrite(vshEventFd
, &reason
, 1));
2140 /* Event loop handler used to limit length of waiting for any other event. */
2142 vshEventTimeout(int timer G_GNUC_UNUSED
,
2145 vshControl
*ctl
= opaque
;
2146 char reason
= VSH_EVENT_TIMEOUT
;
2148 if (ctl
->eventPipe
[1] >= 0)
2149 ignore_value(safewrite(ctl
->eventPipe
[1], &reason
, 1));
2155 * @ctl vsh command struct
2156 * @timeout_ms max wait time in milliseconds, or 0 for indefinite
2158 * Set up a wait for a libvirt event. The wait can be canceled by
2159 * SIGINT or by calling vshEventDone() in your event handler. If
2160 * @timeout_ms is positive, the wait will also end if the timeout
2161 * expires. Call vshEventWait() to block the main thread (the event
2162 * handler runs in the event loop thread). When done (including if
2163 * there was an error registering for an event), use vshEventCleanup()
2164 * to quit waiting. Returns 0 on success, -1 on failure. */
2166 vshEventStart(vshControl
*ctl
, int timeout_ms
)
2169 struct sigaction action
;
2170 assert(vshEventFd
== -1);
2173 assert(ctl
->eventPipe
[0] == -1 && ctl
->eventPipe
[1] == -1 &&
2174 ctl
->eventTimerId
>= 0);
2175 if (virPipe(ctl
->eventPipe
) < 0) {
2176 vshSaveLibvirtError();
2177 vshReportError(ctl
);
2182 vshEventFd
= ctl
->eventPipe
[1];
2184 action
.sa_sigaction
= vshEventInt
;
2185 action
.sa_flags
= SA_SIGINFO
;
2186 sigemptyset(&action
.sa_mask
);
2187 sigaction(SIGINT
, &action
, &vshEventOldAction
);
2191 virEventUpdateTimeout(ctl
->eventTimerId
, timeout_ms
);
2199 * @ctl vsh command struct
2201 * Call this from an event callback to let the main thread quit
2202 * blocking on further events.
2205 vshEventDone(vshControl
*ctl
)
2207 char reason
= VSH_EVENT_DONE
;
2209 if (ctl
->eventPipe
[1] >= 0)
2210 ignore_value(safewrite(ctl
->eventPipe
[1], &reason
, 1));
2216 * @ctl vsh command struct
2218 * Call this in the main thread after calling vshEventStart() then
2219 * registering for one or more events. This call will block until
2220 * SIGINT, the timeout registered at the start, or until one of your
2221 * event handlers calls vshEventDone(). Returns an enum VSH_EVENT_*
2222 * stating how the wait concluded, or -1 on error.
2225 vshEventWait(vshControl
*ctl
)
2230 assert(ctl
->eventPipe
[0] >= 0);
2231 while ((rv
= read(ctl
->eventPipe
[0], &buf
, 1)) < 0 && errno
== EINTR
);
2235 vshError(ctl
, _("failed to determine loop exit status: %1$s"),
2245 * @ctl vsh control struct
2247 * Call at the end of any function that has used vshEventStart(), to
2248 * tear down any remaining SIGINT or timeout handlers.
2251 vshEventCleanup(vshControl
*ctl
)
2254 if (vshEventFd
>= 0) {
2255 sigaction(SIGINT
, &vshEventOldAction
, NULL
);
2259 VIR_FORCE_CLOSE(ctl
->eventPipe
[0]);
2260 VIR_FORCE_CLOSE(ctl
->eventPipe
[1]);
2261 virEventUpdateTimeout(ctl
->eventTimerId
, -1);
2265 # define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC)
2267 # define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT)
2276 vshOpenLogFile(vshControl
*ctl
)
2278 if (ctl
->logfile
== NULL
)
2281 if ((ctl
->log_fd
= open(ctl
->logfile
, LOGFILE_FLAGS
, FILE_MODE
)) < 0) {
2283 _("failed to open the log file. check the log file path"));
2291 * Outputting an error to log file.
2294 vshOutputLogFile(vshControl
*ctl
, int log_level
, const char *msg_format
,
2297 g_auto(virBuffer
) buf
= VIR_BUFFER_INITIALIZER
;
2298 g_autofree
char *str
= NULL
;
2300 const char *lvl
= "";
2301 g_autoptr(GDateTime
) now
= g_date_time_new_now_local();
2302 g_autofree gchar
*nowstr
= NULL
;
2304 if (ctl
->log_fd
== -1)
2310 * [YYYY.MM.DD HH:MM:SS SIGNATURE PID] LOG_LEVEL message
2312 nowstr
= g_date_time_format(now
, "%Y.%m.%d %H:%M:%S");
2313 virBufferAsprintf(&buf
, "[%s %s %d] ",
2317 switch (log_level
) {
2324 case VSH_ERR_NOTICE
:
2327 case VSH_ERR_WARNING
:
2337 virBufferAsprintf(&buf
, "%s ", lvl
);
2338 virBufferVasprintf(&buf
, msg_format
, ap
);
2339 virBufferTrim(&buf
, "\n");
2340 virBufferAddChar(&buf
, '\n');
2342 str
= virBufferContentAndReset(&buf
);
2346 if (safewrite(ctl
->log_fd
, str
, len
) < 0)
2352 vshCloseLogFile(ctl
);
2353 vshError(ctl
, "%s", _("failed to write the log file"));
2362 vshCloseLogFile(vshControl
*ctl
)
2364 /* log file close */
2365 if (VIR_CLOSE(ctl
->log_fd
) < 0) {
2366 vshError(ctl
, _("%1$s: failed to write log file: %2$s"),
2367 ctl
->logfile
? ctl
->logfile
: "?",
2371 g_clear_pointer(&ctl
->logfile
, g_free
);
2376 vshPrintRaw(vshControl
*ctl
, ...)
2382 while ((key
= va_arg(ap
, char *)) != NULL
)
2383 vshPrint(ctl
, "%s\r\n", key
);
2389 * @msg: Question to ask user
2391 * Ask user if he wants to return to previously
2394 * Returns 'y' if he wants to
2395 * 'n' if he doesn't want to
2396 * 'i' if he wants to try defining it again while ignoring validation
2397 * 'f' if he forcibly wants to
2402 vshAskReedit(vshControl
*ctl
, const char *msg
, bool relax_avail
)
2406 if (!isatty(STDIN_FILENO
))
2409 vshReportError(ctl
);
2411 if (vshTTYMakeRaw(ctl
, false) < 0)
2415 vshPrint(ctl
, "\r%s %s %s: ", msg
, _("Try again?"),
2416 relax_avail
? "[y,n,i,f,?]" : "[y,n,f,?]");
2417 c
= g_ascii_tolower(getchar());
2422 _("y - yes, start editor again"),
2423 _("n - no, throw away my changes"),
2428 _("i - turn off validation and try to redefine again"),
2433 _("f - force, try to redefine again"),
2434 _("? - print this help"),
2437 } else if (c
== 'y' || c
== 'n' || c
== 'f' ||
2438 (relax_avail
&& c
== 'i')) {
2445 vshPrint(ctl
, "\r\n");
2450 vshAskReedit(vshControl
*ctl
,
2451 const char *msg G_GNUC_UNUSED
,
2452 bool relax_avail G_GNUC_UNUSED
)
2454 vshDebug(ctl
, VSH_ERR_WARNING
, "%s", _("This function is not supported on WIN32 platform"));
2461 vshEditUnlinkTempfile(char *file
)
2466 ignore_value(unlink(file
));
2471 /* Common code for the edit / net-edit / pool-edit functions which follow. */
2473 vshEditWriteToTempFile(vshControl
*ctl
, const char *doc
)
2475 g_autofree
char *filename
= NULL
;
2476 g_autoptr(vshTempFile
) ret
= NULL
;
2478 VIR_AUTOCLOSE fd
= -1;
2480 tmpdir
= getenv("TMPDIR");
2483 filename
= g_strdup_printf("%s/virshXXXXXX.xml", tmpdir
);
2484 fd
= g_mkstemp_full(filename
, O_RDWR
| O_CLOEXEC
, S_IRUSR
| S_IWUSR
);
2486 vshError(ctl
, _("g_mkstemp_full: failed to create temporary file: %1$s"),
2491 ret
= g_steal_pointer(&filename
);
2493 if (safewrite(fd
, doc
, strlen(doc
)) == -1) {
2494 vshError(ctl
, _("write: %1$s: failed to write to temporary file: %2$s"),
2495 ret
, g_strerror(errno
));
2498 if (VIR_CLOSE(fd
) < 0) {
2499 vshError(ctl
, _("close: %1$s: failed to write or close temporary file: %2$s"),
2500 ret
, g_strerror(errno
));
2504 /* Temporary filename: caller frees. */
2505 return g_steal_pointer(&ret
);
2508 /* Characters permitted in $EDITOR environment variable and temp filename. */
2509 #define ACCEPTED_CHARS \
2510 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/_.:@"
2512 /* Hard-code default editor used as a fallback if not configured by
2513 * VISUAL or EDITOR environment variables. */
2514 #define DEFAULT_EDITOR "vi"
2517 vshEditFile(vshControl
*ctl
, const char *filename
)
2520 g_autoptr(virCommand
) cmd
= NULL
;
2521 int outfd
= STDOUT_FILENO
;
2522 int errfd
= STDERR_FILENO
;
2524 editor
= getenv("VISUAL");
2526 editor
= getenv("EDITOR");
2528 editor
= DEFAULT_EDITOR
;
2530 /* Check that filename doesn't contain shell meta-characters, and
2531 * if it does, refuse to run. Follow the Unix conventions for
2532 * EDITOR: the user can intentionally specify command options, so
2533 * we don't protect any shell metacharacters there. Lots more
2534 * than virsh will misbehave if EDITOR has bogus contents (which
2535 * is why sudo scrubs it by default). Conversely, if the editor
2536 * is safe, we can run it directly rather than wasting a shell.
2538 if (strspn(editor
, ACCEPTED_CHARS
) != strlen(editor
)) {
2539 if (strspn(filename
, ACCEPTED_CHARS
) != strlen(filename
)) {
2541 _("%1$s: temporary filename contains shell meta or other unacceptable characters (is $TMPDIR wrong?)"),
2545 cmd
= virCommandNewArgList("sh", "-c", NULL
);
2546 virCommandAddArgFormat(cmd
, "%s %s", editor
, filename
);
2548 cmd
= virCommandNewArgList(editor
, filename
, NULL
);
2551 virCommandSetInputFD(cmd
, STDIN_FILENO
);
2552 virCommandSetOutputFD(cmd
, &outfd
);
2553 virCommandSetErrorFD(cmd
, &errfd
);
2554 if (virCommandRunAsync(cmd
, NULL
) < 0 ||
2555 virCommandWait(cmd
, NULL
) < 0) {
2556 vshReportError(ctl
);
2563 vshEditReadBackFile(vshControl
*ctl
, const char *filename
)
2567 if (virFileReadAll(filename
, VSH_MAX_XML_FILE
, &ret
) == -1) {
2569 _("%1$s: failed to read temporary file: %2$s"),
2570 filename
, g_strerror(errno
));
2577 vshEditString(vshControl
*ctl
,
2581 g_autoptr(vshTempFile
) tmp
= NULL
;
2584 /* Create and open the temporary file. */
2585 if (!(tmp
= vshEditWriteToTempFile(ctl
, string
)))
2588 /* Start the editor. */
2589 if (vshEditFile(ctl
, tmp
) == -1)
2592 /* Read back the edited file. */
2593 if (!(*output
= vshEditReadBackFile(ctl
, tmp
)))
2596 /* strip a possible newline at the end of file; some
2597 * editors enforce a newline, this makes editing
2598 * more convenient */
2599 if ((tmpstr
= strrchr(*output
, '\n')) &&
2600 *(tmpstr
+1) == '\0')
2606 /* Tree listing helpers. */
2609 vshTreePrintInternal(vshControl
*ctl
,
2610 vshTreeLookup lookup
,
2619 int nextlastdev
= -1;
2620 const char *dev
= (lookup
)(devid
, false, opaque
);
2622 /* Print this device, with indent if not at root */
2623 vshPrint(ctl
, "%s%s%s\n", virBufferCurrentContent(indent
),
2624 root
? "" : "+- ", dev
);
2626 /* Update indent to show '|' or ' ' for child devices */
2628 virBufferAddChar(indent
, devid
== lastdev
? ' ' : '|');
2629 virBufferAddChar(indent
, ' ');
2632 /* Determine the index of the last child device */
2633 for (i
= 0; i
< num_devices
; i
++) {
2634 const char *parent
= (lookup
)(i
, true, opaque
);
2636 if (parent
&& STREQ(parent
, dev
))
2640 /* If there is a child device, then print another blank line */
2641 if (nextlastdev
!= -1)
2642 vshPrint(ctl
, "%s |\n", virBufferCurrentContent(indent
));
2644 /* Finally print all children */
2645 virBufferAddLit(indent
, " ");
2646 for (i
= 0; i
< num_devices
; i
++) {
2647 const char *parent
= (lookup
)(i
, true, opaque
);
2649 if (parent
&& STREQ(parent
, dev
) &&
2650 vshTreePrintInternal(ctl
, lookup
, opaque
,
2651 num_devices
, i
, nextlastdev
,
2655 virBufferTrim(indent
, " ");
2657 /* If there was no child device, and we're the last in
2658 * a list of devices, then print another blank line */
2659 if (nextlastdev
== -1 && devid
== lastdev
)
2660 vshPrint(ctl
, "%s\n", virBufferCurrentContent(indent
));
2663 virBufferTrimLen(indent
, 2);
2669 vshTreePrint(vshControl
*ctl
, vshTreeLookup lookup
, void *opaque
,
2670 int num_devices
, int devid
)
2673 g_auto(virBuffer
) indent
= VIR_BUFFER_INITIALIZER
;
2675 ret
= vshTreePrintInternal(ctl
, lookup
, opaque
, num_devices
,
2676 devid
, devid
, true, &indent
);
2678 vshError(ctl
, "%s", _("Failed to complete tree listing"));
2684 * vshReadlineCommandGenerator:
2686 * Generator function for command completion. Used also for completing the
2687 * '--command' option of the 'help' command.
2689 * Returns a string list of all commands, or NULL on failure.
2692 vshReadlineCommandGenerator(void)
2694 size_t grp_list_index
= 0;
2695 const vshCmdGrp
*grp
;
2696 size_t ret_size
= 0;
2697 g_auto(GStrv
) ret
= NULL
;
2701 for (grp_list_index
= 0; grp
[grp_list_index
].name
; grp_list_index
++) {
2702 const vshCmdDef
*cmds
= grp
[grp_list_index
].commands
;
2703 size_t cmd_list_index
;
2705 for (cmd_list_index
= 0; cmds
[cmd_list_index
].name
; cmd_list_index
++) {
2706 const char *name
= cmds
[cmd_list_index
].name
;
2708 if (cmds
[cmd_list_index
].alias
||
2709 cmds
[cmd_list_index
].flags
& VSH_CMD_FLAG_HIDDEN
)
2712 VIR_REALLOC_N(ret
, ret_size
+ 2);
2714 ret
[ret_size
] = g_strdup(name
);
2716 /* Terminate the string list properly. */
2717 ret
[ret_size
] = NULL
;
2721 return g_steal_pointer(&ret
);
2727 /* -----------------
2734 vshReadlineOptionsGenerator(const vshCmdDef
*cmd
,
2737 size_t list_index
= 0;
2738 size_t ret_size
= 0;
2739 g_auto(GStrv
) ret
= NULL
;
2747 for (list_index
= 0; cmd
->opts
[list_index
].name
; list_index
++) {
2748 const char *name
= cmd
->opts
[list_index
].name
;
2749 bool exists
= false;
2750 vshCmdOpt
*opt
= last
->opts
;
2752 /* Skip aliases, we do not report them in help output either. */
2753 if (cmd
->opts
[list_index
].type
== VSH_OT_ALIAS
)
2757 if (STREQ(opt
->def
->name
, name
) && opt
->def
->type
!= VSH_OT_ARGV
) {
2768 VIR_REALLOC_N(ret
, ret_size
+ 2);
2770 ret
[ret_size
] = g_strdup_printf("--%s", name
);
2772 /* Terminate the string list properly. */
2773 ret
[ret_size
] = NULL
;
2776 return g_steal_pointer(&ret
);
2781 vshCompleterFilter(char ***list
,
2784 char **newList
= NULL
;
2785 size_t newList_len
= 0;
2789 if (!list
|| !*list
)
2792 list_len
= g_strv_length(*list
);
2793 newList
= g_new0(char *, list_len
+ 1);
2795 for (i
= 0; i
< list_len
; i
++) {
2796 if (!STRPREFIX((*list
)[i
], text
)) {
2797 g_clear_pointer(&(*list
)[i
], g_free
);
2801 newList
[newList_len
] = g_steal_pointer(&(*list
)[i
]);
2805 newList
= g_renew(char *, newList
, newList_len
+ 1);
2813 vshReadlineParse(const char *text
, int state
)
2816 static size_t list_index
;
2819 /* Readline calls this function until NULL is returned. On
2820 * the very first call @state is zero which means we should
2821 * initialize those static variables above. On subsequent
2822 * calls @state is non zero. */
2824 g_autoptr(vshCmd
) partial
= NULL
;
2825 const vshCmdDef
*cmd
= NULL
;
2826 g_autofree
char *line
= g_strdup(rl_line_buffer
);
2828 g_clear_pointer(&list
, g_strfreev
);
2831 *(line
+ rl_point
) = '\0';
2833 vshCommandStringParse(NULL
, line
, &partial
);
2837 partial
->skipChecks
= true;
2840 if (cmd
&& STREQ(cmd
->name
, text
)) {
2841 /* Corner case - some commands share prefix (e.g.
2842 * dump and dumpxml). If user typed 'dump<TAB><TAB>',
2843 * then @text = "dump" and we want to offer command
2844 * completion. If they typed 'dump <TAB><TAB>' then
2845 * @text = "" (the space after the command) and we
2846 * want to offer options completion for dump command.
2852 list
= vshReadlineCommandGenerator();
2854 bool complete_argument
= false;
2856 /* attempt completion only when:
2857 - there is an argument
2858 - it has the 'data' field filled
2859 - it has a completer (rules out booleans)
2861 if (partial
->lastopt
&& partial
->lastopt
->data
&& partial
->lastopt
->def
->completer
) {
2862 /* Furthermore we want to do the completion only at the point of
2863 * user's cursor. This is the case if:
2864 * - value in 'data' is equal to 'text' (last component of the completed command)
2865 * - value in 'data' is a space when 'text' is empty (quirk)
2867 if (STREQ_NULLABLE(partial
->lastopt
->data
, text
))
2868 complete_argument
= true;
2870 if (STREQ_NULLABLE(partial
->lastopt
->data
, " ") && *text
== '\0')
2871 complete_argument
= true;
2874 if (complete_argument
) {
2875 list
= partial
->lastopt
->def
->completer(autoCompleteOpaque
,
2877 partial
->lastopt
->def
->completer_flags
);
2879 list
= vshReadlineOptionsGenerator(cmd
, partial
);
2883 /* Escape completions, if needed (i.e. argument
2884 * we are completing wasn't started with a quote
2885 * character). This also enables filtering done
2886 * below to work properly. */
2888 !rl_completion_quote_character
) {
2891 for (i
= 0; list
[i
]; i
++) {
2892 g_auto(virBuffer
) buf
= VIR_BUFFER_INITIALIZER
;
2894 virBufferEscape(&buf
, '\\', " ", "%s", list
[i
]);
2896 list
[i
] = virBufferContentAndReset(&buf
);
2900 /* For string list returned by completers we have to do
2901 * filtering based on @text because completers returns all
2902 * possible strings. */
2903 if (vshCompleterFilter(&list
, text
) < 0)
2908 ret
= g_strdup(list
[list_index
]);
2914 g_clear_pointer(&list
, g_strfreev
);
2922 vshReadlineCompletion(const char *text
,
2923 int start G_GNUC_UNUSED
,
2924 int end G_GNUC_UNUSED
)
2926 return rl_completion_matches(text
, vshReadlineParse
);
2931 vshReadlineCharIsQuoted(char *line
, int idx
)
2934 line
[idx
- 1] == '\\' &&
2935 !vshReadlineCharIsQuoted(line
, idx
- 1);
2939 # define HISTSIZE_MAX 500000
2942 vshReadlineInit(vshControl
*ctl
)
2944 g_autofree
char *userdir
= NULL
;
2945 int max_history
= 500;
2946 g_autofree
char *histsize_env
= NULL
;
2947 const char *histsize_str
= NULL
;
2948 const char *break_characters
= " \t\n`@$><=;|&{(";
2949 const char *quote_characters
= "\"'";
2951 /* initialize readline stuff only once */
2952 if (ctl
->historydir
)
2955 /* Opaque data for autocomplete callbacks. */
2956 autoCompleteOpaque
= ctl
;
2958 rl_readline_name
= ctl
->name
;
2960 /* Tell the completer that we want a crack first. */
2961 rl_attempted_completion_function
= vshReadlineCompletion
;
2963 rl_basic_word_break_characters
= break_characters
;
2965 rl_completer_quote_characters
= quote_characters
;
2966 rl_char_is_quoted_p
= vshReadlineCharIsQuoted
;
2968 histsize_env
= g_strdup_printf("%s_HISTSIZE", ctl
->env_prefix
);
2970 /* Limit the total size of the history buffer */
2971 if ((histsize_str
= getenv(histsize_env
))) {
2972 if (virStrToLong_i(histsize_str
, NULL
, 10, &max_history
) < 0) {
2973 vshError(ctl
, _("Bad $%1$s value."), histsize_env
);
2975 } else if (max_history
> HISTSIZE_MAX
|| max_history
< 0) {
2976 vshError(ctl
, _("$%1$s value should be between 0 and %2$d"),
2977 histsize_env
, HISTSIZE_MAX
);
2981 stifle_history(max_history
);
2983 /* Prepare to read/write history from/to the
2984 * $XDG_CACHE_HOME/virtshell/history file
2986 userdir
= virGetUserCacheDirectory();
2988 ctl
->historydir
= g_strdup_printf("%s/%s", userdir
, ctl
->name
);
2990 ctl
->historyfile
= g_strdup_printf("%s/history", ctl
->historydir
);
2992 read_history(ctl
->historyfile
);
2997 vshReadlineDeinit(vshControl
*ctl
)
2999 if (ctl
->historyfile
!= NULL
) {
3000 if (g_mkdir_with_parents(ctl
->historydir
, 0755) < 0 &&
3002 vshError(ctl
, _("Failed to create '%1$s': %2$s"),
3003 ctl
->historydir
, g_strerror(errno
));
3005 write_history(ctl
->historyfile
);
3009 g_clear_pointer(&ctl
->historydir
, g_free
);
3010 g_clear_pointer(&ctl
->historyfile
, g_free
);
3014 vshReadline(vshControl
*ctl G_GNUC_UNUSED
, const char *prompt
)
3016 return readline(prompt
);
3020 vshReadlineHistoryAdd(const char *cmd
)
3022 return add_history(cmd
);
3025 #else /* !WITH_READLINE */
3028 vshReadlineInit(vshControl
*ctl G_GNUC_UNUSED
)
3035 vshReadlineDeinit(vshControl
*ctl G_GNUC_UNUSED
)
3041 vshReadline(vshControl
*ctl G_GNUC_UNUSED
,
3048 fputs(prompt
, stdout
);
3050 r
= fgets(line
, sizeof(line
), stdin
);
3051 if (r
== NULL
) return NULL
; /* EOF */
3053 /* Chomp trailing \n */
3055 if (len
> 0 && r
[len
-1] == '\n')
3062 vshReadlineHistoryAdd(const char *cmd G_GNUC_UNUSED
)
3067 #endif /* !WITH_READLINE */
3070 * Initialize debug settings.
3073 vshInitDebug(vshControl
*ctl
)
3075 const char *debugEnv
;
3077 if (ctl
->debug
== VSH_DEBUG_DEFAULT
) {
3078 g_autofree
char *env
= g_strdup_printf("%s_DEBUG", ctl
->env_prefix
);
3080 /* log level not set from commandline, check env variable */
3081 debugEnv
= getenv(env
);
3084 if (virStrToLong_i(debugEnv
, NULL
, 10, &debug
) < 0 ||
3085 debug
< VSH_ERR_DEBUG
|| debug
> VSH_ERR_ERROR
) {
3086 vshError(ctl
, _("%1$s_DEBUG not set with a valid numeric value"),
3094 if (ctl
->logfile
== NULL
) {
3095 g_autofree
char *env
= g_strdup_printf("%s_LOG_FILE", ctl
->env_prefix
);
3097 /* log file not set from cmdline */
3098 debugEnv
= getenv(env
);
3099 if (debugEnv
&& *debugEnv
) {
3100 ctl
->logfile
= g_strdup(debugEnv
);
3101 vshOpenLogFile(ctl
);
3110 * Initialize global data
3113 vshInit(vshControl
*ctl
, const vshCmdGrp
*groups
)
3116 vshError(ctl
, "%s", _("client hooks cannot be NULL"));
3121 vshError(ctl
, "%s", _("command groups must be non-NULL"));
3127 if (vshInitDebug(ctl
) < 0 ||
3128 (ctl
->imode
&& vshReadlineInit(ctl
) < 0))
3135 vshInitReload(vshControl
*ctl
)
3138 vshError(ctl
, "%s", _("command groups is NULL run vshInit before reloading"));
3142 if (vshInitDebug(ctl
) < 0)
3146 vshReadlineDeinit(ctl
);
3147 if (ctl
->imode
&& vshReadlineInit(ctl
) < 0)
3154 vshDeinit(vshControl
*ctl
)
3156 /* NB: Don't make calling of vshReadlineDeinit conditional on active
3157 * interactive mode. */
3158 vshReadlineDeinit(ctl
);
3159 vshCloseLogFile(ctl
);
3162 /* -----------------------------------------------
3163 * Generic commands available to use by any client
3164 * -----------------------------------------------
3168 vshCompleteHelpCommand(vshControl
*ctl G_GNUC_UNUSED
,
3169 const vshCmd
*cmd G_GNUC_UNUSED
,
3170 unsigned int completerflags G_GNUC_UNUSED
)
3172 return vshReadlineCommandGenerator();
3176 const vshCmdOptDef opts_help
[] = {
3178 .type
= VSH_OT_STRING
,
3180 .completer
= vshCompleteHelpCommand
,
3181 .help
= N_("Prints global help, command specific help, or help for a group of related commands")
3186 const vshCmdInfo info_help
= {
3187 .help
= N_("print help"),
3188 .desc
= N_("Prints global help, command specific help, or help for a\n"
3189 " group of related commands"),
3193 cmdHelp(vshControl
*ctl
, const vshCmd
*cmd
)
3195 const vshCmdDef
*def
= NULL
;
3196 const vshCmdGrp
*grp
= NULL
;
3197 const char *name
= NULL
;
3199 if (vshCommandOptStringQuiet(ctl
, cmd
, "command", &name
) <= 0) {
3200 vshPrint(ctl
, "%s", _("Grouped commands:\n\n"));
3202 for (grp
= cmdGroups
; grp
->name
; grp
++) {
3203 vshPrint(ctl
, _(" %1$s (help keyword '%2$s'):\n"), grp
->name
,
3206 for (def
= grp
->commands
; def
->name
; def
++) {
3208 def
->flags
& VSH_CMD_FLAG_HIDDEN
)
3210 vshPrint(ctl
, " %-30s %s\n", def
->name
, _(def
->info
->help
));
3213 vshPrint(ctl
, "\n");
3219 if ((def
= vshCmddefSearch(name
))) {
3221 def
= vshCmddefSearch(def
->alias
);
3225 return vshCmddefHelp(def
);
3226 } else if ((grp
= vshCmdGrpSearch(name
))) {
3227 return vshCmdGrpHelp(ctl
, grp
);
3229 vshError(ctl
, _("command or command group '%1$s' doesn't exist"), name
);
3234 const vshCmdOptDef opts_cd
[] = {
3236 .type
= VSH_OT_STRING
,
3238 .help
= N_("directory to switch to (default: home or else root)")
3243 const vshCmdInfo info_cd
= {
3244 .help
= N_("change the current directory"),
3245 .desc
= N_("Change the current directory."),
3249 cmdCd(vshControl
*ctl
, const vshCmd
*cmd
)
3251 const char *dir
= NULL
;
3252 g_autofree
char *dir_malloced
= NULL
;
3254 if (vshCommandOptStringQuiet(ctl
, cmd
, "dir", &dir
) <= 0)
3255 dir
= dir_malloced
= virGetUserDirectory();
3259 if (chdir(dir
) == -1) {
3260 vshError(ctl
, _("cd: %1$s: %2$s"),
3261 g_strerror(errno
), dir
);
3268 const vshCmdOptDef opts_echo
[] = {
3270 .type
= VSH_OT_BOOL
,
3271 .help
= N_("escape for shell use")
3274 .type
= VSH_OT_BOOL
,
3275 .help
= N_("escape for XML use")
3278 .type
= VSH_OT_BOOL
,
3279 .help
= N_("split each argument on ','; ',,' is an escape sequence")
3282 .type
= VSH_OT_BOOL
,
3283 .help
= N_("output to stderr"),
3286 .type
= VSH_OT_ALIAS
,
3290 .type
= VSH_OT_ALIAS
,
3291 .help
= "string=hello"
3294 .type
= VSH_OT_STRING
,
3295 .help
= N_("prefix the message")
3298 .type
= VSH_OT_ARGV
,
3300 .help
= N_("arguments to echo")
3305 const vshCmdInfo info_echo
= {
3306 .help
= N_("echo arguments. Used for internal testing."),
3307 .desc
= N_("Echo back arguments, possibly with quoting. Used for internal testing."),
3310 /* Exists mainly for debugging virsh, but also handy for adding back
3311 * quotes for later evaluation.
3314 cmdEcho(vshControl
*ctl
, const vshCmd
*cmd
)
3316 bool shell
= vshCommandOptBool(cmd
, "shell");
3317 bool xml
= vshCommandOptBool(cmd
, "xml");
3318 bool err
= vshCommandOptBool(cmd
, "err");
3319 bool split
= vshCommandOptBool(cmd
, "split");
3321 g_autofree
char *arg
= NULL
;
3322 g_auto(virBuffer
) buf
= VIR_BUFFER_INITIALIZER
;
3325 VSH_EXCLUSIVE_OPTIONS_VAR(shell
, xml
);
3326 VSH_EXCLUSIVE_OPTIONS_VAR(shell
, split
);
3327 VSH_EXCLUSIVE_OPTIONS_VAR(xml
, split
);
3329 ignore_value(vshCommandOptString(ctl
, cmd
, "prefix", &prefix
));
3332 virBufferAsprintf(&buf
, "%s ", prefix
);
3334 for (o
= vshCommandOptArgv(cmd
, "string"); o
&& *o
; o
++) {
3335 const char *curr
= *o
;
3338 virBufferEscapeString(&buf
, "%s", curr
);
3340 virBufferEscapeShell(&buf
, curr
);
3342 g_auto(GStrv
) spl
= NULL
;
3345 vshStringToArray(curr
, &spl
);
3347 for (n
= spl
; *n
; n
++)
3348 virBufferAsprintf(&buf
, "%s\n", *n
);
3350 virBufferAdd(&buf
, curr
, -1);
3353 virBufferAddChar(&buf
, ' ');
3356 virBufferTrim(&buf
, " ");
3358 arg
= virBufferContentAndReset(&buf
);
3361 vshError(ctl
, "%s", arg
);
3363 vshPrint(ctl
, "%s", arg
);
3368 const vshCmdInfo info_pwd
= {
3369 .help
= N_("print the current directory"),
3370 .desc
= N_("Print the current directory."),
3374 cmdPwd(vshControl
*ctl
, const vshCmd
*cmd G_GNUC_UNUSED
)
3376 g_autofree
char *cwd
= g_get_current_dir();
3378 vshPrint(ctl
, _("%1$s\n"), cwd
);
3383 const vshCmdInfo info_quit
= {
3384 .help
= N_("quit this interactive terminal"),
3389 cmdQuit(vshControl
*ctl
, const vshCmd
*cmd G_GNUC_UNUSED
)
3395 /* -----------------
3397 * ----------------- */
3399 const vshCmdOptDef opts_selftest
[] = {
3400 {.name
= "completers-missing",
3401 .type
= VSH_OT_BOOL
,
3402 .help
= N_("output the list of options which are missing completers")
3404 {.name
= "dump-help",
3405 .type
= VSH_OT_BOOL
,
3406 .help
= N_("output help for each command")
3410 const vshCmdInfo info_selftest
= {
3411 .help
= N_("internal command for testing virt shells"),
3412 .desc
= N_("internal use only"),
3416 cmdSelfTest(vshControl
*ctl
, const vshCmd
*cmd
)
3418 const vshCmdGrp
*grp
;
3419 const vshCmdDef
*def
;
3420 bool completers
= vshCommandOptBool(cmd
, "completers-missing");
3421 bool dumphelp
= vshCommandOptBool(cmd
, "dump-help");
3423 for (grp
= cmdGroups
; grp
->name
; grp
++) {
3424 for (def
= grp
->commands
; def
->name
; def
++) {
3426 if (dumphelp
&& !def
->alias
)
3429 if (vshCmddefCheckInternals(ctl
, def
, completers
) < 0)
3437 /* ----------------------
3438 * Autocompletion command
3439 * ---------------------- */
3441 const vshCmdOptDef opts_complete
[] = {
3443 .type
= VSH_OT_ARGV
,
3446 .help
= N_("partial string to autocomplete")
3451 const vshCmdInfo info_complete
= {
3452 .help
= N_("internal command for autocompletion"),
3453 .desc
= N_("internal use only"),
3457 #ifdef WITH_READLINE
3459 static virOnceControl vshCmdCompleteCloseStdinOnce
= VIR_ONCE_CONTROL_INITIALIZER
;
3462 vshCmdCompleteCloseStdin(void)
3464 /* In non-interactive mode which is how the 'complete' command is intended
3465 * to be used we need to ensure that any authentication callback will not
3466 * attempt to read any input which would break the completion */
3467 int stdin_fileno
= STDIN_FILENO
;
3469 VIR_FORCE_CLOSE(stdin_fileno
);
3474 cmdComplete(vshControl
*ctl
, const vshCmd
*cmd
)
3476 const vshClientHooks
*hooks
= ctl
->hooks
;
3477 const char *lastArg
= NULL
;
3478 const char **args
= NULL
;
3479 g_auto(GStrv
) matches
= NULL
;
3482 /* The completer needs also the last component */
3483 for (args
= vshCommandOptArgv(cmd
, "string"); args
&& *args
; args
++)
3486 /* This command is flagged VSH_CMD_FLAG_NOCONNECT because we
3487 * need to prevent auth hooks reading any input. Therefore, we
3488 * have to close stdin and then connect ourselves. */
3490 if (virOnce(&vshCmdCompleteCloseStdinOnce
, vshCmdCompleteCloseStdin
) < 0)
3494 if (!(hooks
&& hooks
->connHandler
&& hooks
->connHandler(ctl
)))
3497 vshReadlineInit(ctl
);
3499 if (!(rl_line_buffer
= g_strdup(vshCommandOptArgvString(cmd
, "string"))))
3500 rl_line_buffer
= g_strdup("");
3502 /* rl_point is current cursor position in rl_line_buffer.
3503 * In our case it's at the end of the whole line. */
3504 rl_point
= strlen(rl_line_buffer
);
3506 matches
= vshReadlineCompletion(lastArg
, 0, 0);
3507 g_clear_pointer(&rl_line_buffer
, g_free
);
3512 for (iter
= matches
; *iter
; iter
++) {
3513 if (iter
== matches
&& matches
[1])
3515 printf("%s\n", *iter
);
3522 #else /* !WITH_READLINE */
3526 cmdComplete(vshControl
*ctl G_GNUC_UNUSED
,
3527 const vshCmd
*cmd G_GNUC_UNUSED
)
3531 #endif /* !WITH_READLINE */