docs: Update documentation for spapr-vio addresses
[libvirt/ericb.git] / tools / vsh.c
blobf2486498c9210bbd59d050fd11951d79c011202d
1 /*
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/>.
21 #include <config.h>
22 #include "vsh.h"
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <unistd.h>
27 #include <sys/time.h>
28 #include "c-ctype.h"
29 #include <fcntl.h>
30 #include <time.h>
31 #include <sys/stat.h>
32 #include <inttypes.h>
33 #include <signal.h>
35 #if WITH_READLINE
36 # include <readline/readline.h>
37 # include <readline/history.h>
38 #endif
40 #include "internal.h"
41 #include "virerror.h"
42 #include "virbuffer.h"
43 #include "viralloc.h"
44 #include <libvirt/libvirt-qemu.h>
45 #include <libvirt/libvirt-lxc.h>
46 #include "virfile.h"
47 #include "virthread.h"
48 #include "vircommand.h"
49 #include "conf/domain_conf.h"
50 #include "virtypedparam.h"
51 #include "virstring.h"
53 /* Gnulib doesn't guarantee SA_SIGINFO support. */
54 #ifndef SA_SIGINFO
55 # define SA_SIGINFO 0
56 #endif
58 #ifdef WITH_READLINE
59 /* For autocompletion */
60 vshControl *autoCompleteOpaque;
61 #endif
63 /* NOTE: It would be much nicer to have these two as part of vshControl
64 * structure, unfortunately readline doesn't support passing opaque data
65 * and only relies on static data accessible from the user-side callback
67 const vshCmdGrp *cmdGroups;
68 const vshCmdDef *cmdSet;
71 /* simple handler for oom conditions */
72 static void
73 vshErrorOOM(void)
75 fflush(stdout);
76 fputs(_("error: Out of memory\n"), stderr);
77 fflush(stderr);
78 exit(EXIT_FAILURE);
82 double
83 vshPrettyCapacity(unsigned long long val, const char **unit)
85 double limit = 1024;
87 if (val < limit) {
88 *unit = "B";
89 return val;
91 limit *= 1024;
92 if (val < limit) {
93 *unit = "KiB";
94 return val / (limit / 1024);
96 limit *= 1024;
97 if (val < limit) {
98 *unit = "MiB";
99 return val / (limit / 1024);
101 limit *= 1024;
102 if (val < limit) {
103 *unit = "GiB";
104 return val / (limit / 1024);
106 limit *= 1024;
107 if (val < limit) {
108 *unit = "TiB";
109 return val / (limit / 1024);
111 limit *= 1024;
112 if (val < limit) {
113 *unit = "PiB";
114 return val / (limit / 1024);
116 limit *= 1024;
117 *unit = "EiB";
118 return val / (limit / 1024);
122 void *
123 _vshMalloc(vshControl *ctl, size_t size, const char *filename, int line)
125 char *x;
127 if (VIR_ALLOC_N(x, size) == 0)
128 return x;
129 vshError(ctl, _("%s: %d: failed to allocate %d bytes"),
130 filename, line, (int) size);
131 exit(EXIT_FAILURE);
134 void *
135 _vshCalloc(vshControl *ctl, size_t nmemb, size_t size, const char *filename,
136 int line)
138 char *x;
140 if (!xalloc_oversized(nmemb, size) &&
141 VIR_ALLOC_N(x, nmemb * size) == 0)
142 return x;
143 vshError(ctl, _("%s: %d: failed to allocate %d bytes"),
144 filename, line, (int) (size*nmemb));
145 exit(EXIT_FAILURE);
148 char *
149 _vshStrdup(vshControl *ctl, const char *s, const char *filename, int line)
151 char *x;
153 if (VIR_STRDUP(x, s) >= 0)
154 return x;
155 vshError(ctl, _("%s: %d: failed to allocate %lu bytes"),
156 filename, line, (unsigned long)strlen(s));
157 exit(EXIT_FAILURE);
161 vshNameSorter(const void *a, const void *b)
163 const char **sa = (const char**)a;
164 const char **sb = (const char**)b;
166 return vshStrcasecmp(*sa, *sb);
171 * Convert the strings separated by ',' into array. The returned
172 * array is a NULL terminated string list. The caller has to free
173 * the array using virStringListFree or a similar method.
175 * Returns the length of the filled array on success, or -1
176 * on error.
179 vshStringToArray(const char *str,
180 char ***array)
182 char *str_copied = vshStrdup(NULL, str);
183 char *str_tok = NULL;
184 char *tmp;
185 unsigned int nstr_tokens = 0;
186 char **arr = NULL;
187 size_t len = strlen(str_copied);
189 /* tokenize the string from user and save its parts into an array */
190 nstr_tokens = 1;
192 /* count the delimiters, recognizing ,, as an escape for a
193 * literal comma */
194 str_tok = str_copied;
195 while ((str_tok = strchr(str_tok, ','))) {
196 if (str_tok[1] == ',')
197 str_tok++;
198 else
199 nstr_tokens++;
200 str_tok++;
203 /* reserve the NULL element at the end */
204 if (VIR_ALLOC_N(arr, nstr_tokens + 1) < 0) {
205 VIR_FREE(str_copied);
206 return -1;
209 /* tokenize the input string, while treating ,, as a literal comma */
210 nstr_tokens = 0;
211 tmp = str_tok = str_copied;
212 while ((tmp = strchr(tmp, ','))) {
213 if (tmp[1] == ',') {
214 memmove(&tmp[1], &tmp[2], len - (tmp - str_copied) - 2 + 1);
215 len--;
216 tmp++;
217 continue;
219 *tmp++ = '\0';
220 arr[nstr_tokens++] = vshStrdup(NULL, str_tok);
221 str_tok = tmp;
223 arr[nstr_tokens++] = vshStrdup(NULL, str_tok);
225 *array = arr;
226 VIR_FREE(str_copied);
227 return nstr_tokens;
230 virErrorPtr last_error;
233 * Quieten libvirt until we're done with the command.
235 void
236 vshErrorHandler(void *opaque ATTRIBUTE_UNUSED,
237 virErrorPtr error ATTRIBUTE_UNUSED)
239 virFreeError(last_error);
240 last_error = virSaveLastError();
243 /* Store a libvirt error that is from a helper API that doesn't raise errors
244 * so it doesn't get overwritten */
245 void
246 vshSaveLibvirtError(void)
248 virFreeError(last_error);
249 last_error = virSaveLastError();
253 /* Store libvirt error from helper API but don't overwrite existing errors */
254 void
255 vshSaveLibvirtHelperError(void)
257 if (last_error)
258 return;
260 if (virGetLastErrorCode() == VIR_ERR_OK)
261 return;
263 vshSaveLibvirtError();
268 * Reset libvirt error on graceful fallback paths
270 void
271 vshResetLibvirtError(void)
273 virFreeError(last_error);
274 last_error = NULL;
275 virResetLastError();
279 * Report an error when a command finishes. This is better than before
280 * (when correct operation would report errors), but it has some
281 * problems: we lose the smarter formatting of virDefaultErrorFunc(),
282 * and it can become harder to debug problems, if errors get reported
283 * twice during one command. This case shouldn't really happen anyway,
284 * and it's IMHO a bug that libvirt does that sometimes.
286 void
287 vshReportError(vshControl *ctl)
289 if (last_error == NULL) {
290 /* Calling directly into libvirt util functions won't trigger the
291 * error callback (which sets last_error), so check it ourselves.
293 * If the returned error has CODE_OK, this most likely means that
294 * no error was ever raised, so just ignore */
295 last_error = virSaveLastError();
296 if (!last_error || last_error->code == VIR_ERR_OK)
297 goto out;
300 if (last_error->code == VIR_ERR_OK) {
301 vshError(ctl, "%s", _("unknown error"));
302 goto out;
305 vshError(ctl, "%s", last_error->message);
307 out:
308 vshResetLibvirtError();
312 * Detection of disconnections and automatic reconnection support
314 static int disconnected; /* we may have been disconnected */
316 /* ---------------
317 * Utils for work with command definition
318 * ---------------
320 const char *
321 vshCmddefGetInfo(const vshCmdDef * cmd, const char *name)
323 const vshCmdInfo *info;
325 for (info = cmd->info; info && info->name; info++) {
326 if (STREQ(info->name, name))
327 return info->data;
329 return NULL;
332 /* Check if the internal command definitions are correct */
333 static int
334 vshCmddefCheckInternals(vshControl *ctl,
335 const vshCmdDef *cmd)
337 size_t i;
338 const char *help = NULL;
340 /* in order to perform the validation resolve the alias first */
341 if (cmd->flags & VSH_CMD_FLAG_ALIAS) {
342 if (!cmd->alias) {
343 vshError(ctl, _("command '%s' has inconsistent alias"), cmd->name);
344 return -1;
346 cmd = vshCmddefSearch(cmd->alias);
349 /* Each command has to provide a non-empty help string. */
350 if (!(help = vshCmddefGetInfo(cmd, "help")) || !*help) {
351 vshError(ctl, _("command '%s' lacks help"), cmd->name);
352 return -1;
355 if (!cmd->opts)
356 return 0;
358 for (i = 0; cmd->opts[i].name; i++) {
359 const vshCmdOptDef *opt = &cmd->opts[i];
361 if (i > 63) {
362 vshError(ctl, _("command '%s' has too many options"), cmd->name);
363 return -1; /* too many options */
366 switch (opt->type) {
367 case VSH_OT_STRING:
368 case VSH_OT_BOOL:
369 if (opt->flags & VSH_OFLAG_REQ) {
370 vshError(ctl, _("command '%s' misused VSH_OFLAG_REQ"),
371 cmd->name);
372 return -1; /* neither bool nor string options can be mandatory */
374 break;
376 case VSH_OT_ALIAS: {
377 size_t j;
378 char *name = (char *)opt->help; /* cast away const */
379 char *p;
381 if (opt->flags || !opt->help) {
382 vshError(ctl, _("command '%s' has incorrect alias option"),
383 cmd->name);
384 return -1; /* alias options are tracked by the original name */
386 if ((p = strchr(name, '=')) &&
387 VIR_STRNDUP(name, name, p - name) < 0)
388 vshErrorOOM();
389 for (j = i + 1; cmd->opts[j].name; j++) {
390 if (STREQ(name, cmd->opts[j].name) &&
391 cmd->opts[j].type != VSH_OT_ALIAS)
392 break;
394 if (name != opt->help) {
395 VIR_FREE(name);
396 /* If alias comes with value, replacement must not be bool */
397 if (cmd->opts[j].type == VSH_OT_BOOL) {
398 vshError(ctl, _("command '%s' has mismatched alias type"),
399 cmd->name);
400 return -1;
403 if (!cmd->opts[j].name) {
404 vshError(ctl, _("command '%s' has missing alias option"),
405 cmd->name);
406 return -1; /* alias option must map to a later option name */
409 break;
410 case VSH_OT_ARGV:
411 if (cmd->opts[i + 1].name) {
412 vshError(ctl, _("command '%s' does not list argv option last"),
413 cmd->name);
414 return -1; /* argv option must be listed last */
416 break;
418 case VSH_OT_DATA:
419 if (!(opt->flags & VSH_OFLAG_REQ)) {
420 vshError(ctl, _("command '%s' has non-required VSH_OT_DATA"),
421 cmd->name);
422 return -1; /* OT_DATA should always be required. */
424 break;
426 case VSH_OT_INT:
427 break;
430 return 0;
433 /* Parse the options associated with @cmd, i.e. test whether options are
434 * required or need an argument.
436 * Returns -1 on error or 0 on success, filling the caller-provided bitmaps
437 * which keep track of required options and options needing an argument.
439 static int
440 vshCmddefOptParse(const vshCmdDef *cmd, uint64_t *opts_need_arg,
441 uint64_t *opts_required)
443 size_t i;
444 bool optional = false;
446 *opts_need_arg = 0;
447 *opts_required = 0;
449 if (!cmd->opts)
450 return 0;
452 for (i = 0; cmd->opts[i].name; i++) {
453 const vshCmdOptDef *opt = &cmd->opts[i];
455 if (opt->type == VSH_OT_BOOL) {
456 optional = true;
457 continue;
460 if (opt->flags & VSH_OFLAG_REQ_OPT) {
461 if (opt->flags & VSH_OFLAG_REQ)
462 *opts_required |= 1ULL << i;
463 else
464 optional = true;
465 continue;
468 if (opt->type == VSH_OT_ALIAS)
469 continue; /* skip the alias option */
471 *opts_need_arg |= 1ULL << i;
472 if (opt->flags & VSH_OFLAG_REQ) {
473 if (optional && opt->type != VSH_OT_ARGV)
474 return -1; /* mandatory options must be listed first */
475 *opts_required |= 1ULL << i;
476 } else {
477 optional = true;
481 return 0;
484 static vshCmdOptDef helpopt = {
485 .name = "help",
486 .type = VSH_OT_BOOL,
487 .help = N_("print help for this function")
489 static const vshCmdOptDef *
490 vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name,
491 uint64_t *opts_seen, size_t *opt_index, char **optstr,
492 bool report)
494 size_t i;
495 const vshCmdOptDef *ret = NULL;
496 char *alias = NULL;
498 if (STREQ(name, helpopt.name))
499 return &helpopt;
501 for (i = 0; cmd->opts && cmd->opts[i].name; i++) {
502 const vshCmdOptDef *opt = &cmd->opts[i];
504 if (STREQ(opt->name, name)) {
505 if (opt->type == VSH_OT_ALIAS) {
506 char *value;
508 /* Two types of replacements:
509 opt->help = "string": straight replacement of name
510 opt->help = "string=value": treat boolean flag as
511 alias of option and its default value */
512 sa_assert(!alias);
513 if (VIR_STRDUP(alias, opt->help) < 0)
514 goto cleanup;
515 name = alias;
516 if ((value = strchr(name, '='))) {
517 *value = '\0';
518 if (*optstr) {
519 if (report)
520 vshError(ctl, _("invalid '=' after option --%s"),
521 opt->name);
522 goto cleanup;
524 if (VIR_STRDUP(*optstr, value + 1) < 0)
525 goto cleanup;
527 continue;
529 if ((*opts_seen & (1ULL << i)) && opt->type != VSH_OT_ARGV) {
530 if (report)
531 vshError(ctl, _("option --%s already seen"), name);
532 goto cleanup;
534 *opts_seen |= 1ULL << i;
535 *opt_index = i;
536 ret = opt;
537 goto cleanup;
541 if (STRNEQ(cmd->name, "help") && report) {
542 vshError(ctl, _("command '%s' doesn't support option --%s"),
543 cmd->name, name);
545 cleanup:
546 VIR_FREE(alias);
547 return ret;
550 static const vshCmdOptDef *
551 vshCmddefGetData(const vshCmdDef *cmd, uint64_t *opts_need_arg,
552 uint64_t *opts_seen)
554 size_t i;
555 const vshCmdOptDef *opt;
557 if (!*opts_need_arg)
558 return NULL;
560 /* Grab least-significant set bit */
561 i = ffsl(*opts_need_arg) - 1;
562 opt = &cmd->opts[i];
563 if (opt->type != VSH_OT_ARGV)
564 *opts_need_arg &= ~(1ULL << i);
565 *opts_seen |= 1ULL << i;
566 return opt;
570 * Checks for required options
572 static int
573 vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd, uint64_t opts_required,
574 uint64_t opts_seen)
576 const vshCmdDef *def = cmd->def;
577 size_t i;
579 opts_required &= ~opts_seen;
580 if (!opts_required)
581 return 0;
583 for (i = 0; def->opts[i].name; i++) {
584 if (opts_required & (1ULL << i)) {
585 const vshCmdOptDef *opt = &def->opts[i];
587 vshError(ctl,
588 opt->type == VSH_OT_DATA || opt->type == VSH_OT_ARGV ?
589 _("command '%s' requires <%s> option") :
590 _("command '%s' requires --%s option"),
591 def->name, opt->name);
594 return -1;
597 static const vshCmdDef *
598 vshCmdDefSearchGrp(const char *cmdname)
600 const vshCmdGrp *g;
601 const vshCmdDef *c;
603 for (g = cmdGroups; g->name; g++) {
604 for (c = g->commands; c->name; c++) {
605 if (STREQ(c->name, cmdname))
606 return c;
610 return NULL;
613 static const vshCmdDef *
614 vshCmdDefSearchSet(const char *cmdname)
616 const vshCmdDef *s;
618 for (s = cmdSet; s->name; s++) {
619 if (STREQ(s->name, cmdname))
620 return s;
623 return NULL;
626 const vshCmdDef *
627 vshCmddefSearch(const char *cmdname)
629 if (cmdGroups)
630 return vshCmdDefSearchGrp(cmdname);
631 else
632 return vshCmdDefSearchSet(cmdname);
635 const vshCmdGrp *
636 vshCmdGrpSearch(const char *grpname)
638 const vshCmdGrp *g;
640 for (g = cmdGroups; g->name; g++) {
641 if (STREQ(g->name, grpname) || STREQ(g->keyword, grpname))
642 return g;
645 return NULL;
648 bool
649 vshCmdGrpHelp(vshControl *ctl, const vshCmdGrp *grp)
651 const vshCmdDef *cmd = NULL;
653 vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name,
654 grp->keyword);
656 for (cmd = grp->commands; cmd->name; cmd++) {
657 if (cmd->flags & VSH_CMD_FLAG_ALIAS)
658 continue;
659 vshPrint(ctl, " %-30s %s\n", cmd->name,
660 _(vshCmddefGetInfo(cmd, "help")));
663 return true;
666 bool
667 vshCmddefHelp(vshControl *ctl, const vshCmdDef *def)
669 const char *desc = NULL;
670 char buf[256];
671 uint64_t opts_need_arg;
672 uint64_t opts_required;
673 bool shortopt = false; /* true if 'arg' works instead of '--opt arg' */
675 if (vshCmddefOptParse(def, &opts_need_arg, &opts_required)) {
676 vshError(ctl, _("internal error: bad options in command: '%s'"),
677 def->name);
678 return false;
681 fputs(_(" NAME\n"), stdout);
682 fprintf(stdout, " %s - %s\n", def->name,
683 _(vshCmddefGetInfo(def, "help")));
685 fputs(_("\n SYNOPSIS\n"), stdout);
686 fprintf(stdout, " %s", def->name);
687 if (def->opts) {
688 const vshCmdOptDef *opt;
689 for (opt = def->opts; opt->name; opt++) {
690 const char *fmt = "%s";
691 switch (opt->type) {
692 case VSH_OT_BOOL:
693 fmt = "[--%s]";
694 break;
695 case VSH_OT_INT:
696 /* xgettext:c-format */
697 fmt = ((opt->flags & VSH_OFLAG_REQ) ? "<%s>"
698 : _("[--%s <number>]"));
699 if (!(opt->flags & VSH_OFLAG_REQ_OPT))
700 shortopt = true;
701 break;
702 case VSH_OT_STRING:
703 /* xgettext:c-format */
704 fmt = _("[--%s <string>]");
705 if (!(opt->flags & VSH_OFLAG_REQ_OPT))
706 shortopt = true;
707 break;
708 case VSH_OT_DATA:
709 fmt = ((opt->flags & VSH_OFLAG_REQ) ? "<%s>" : "[<%s>]");
710 if (!(opt->flags & VSH_OFLAG_REQ_OPT))
711 shortopt = true;
712 break;
713 case VSH_OT_ARGV:
714 /* xgettext:c-format */
715 if (shortopt) {
716 fmt = (opt->flags & VSH_OFLAG_REQ)
717 ? _("{[--%s] <string>}...")
718 : _("[[--%s] <string>]...");
719 } else {
720 fmt = (opt->flags & VSH_OFLAG_REQ) ? _("<%s>...")
721 : _("[<%s>]...");
723 break;
724 case VSH_OT_ALIAS:
725 /* aliases are intentionally undocumented */
726 continue;
728 fputc(' ', stdout);
729 fprintf(stdout, fmt, opt->name);
732 fputc('\n', stdout);
734 desc = vshCmddefGetInfo(def, "desc");
735 if (*desc) {
736 /* Print the description only if it's not empty. */
737 fputs(_("\n DESCRIPTION\n"), stdout);
738 fprintf(stdout, " %s\n", _(desc));
741 if (def->opts && def->opts->name) {
742 const vshCmdOptDef *opt;
743 fputs(_("\n OPTIONS\n"), stdout);
744 for (opt = def->opts; opt->name; opt++) {
745 switch (opt->type) {
746 case VSH_OT_BOOL:
747 snprintf(buf, sizeof(buf), "--%s", opt->name);
748 break;
749 case VSH_OT_INT:
750 snprintf(buf, sizeof(buf),
751 (opt->flags & VSH_OFLAG_REQ) ? _("[--%s] <number>")
752 : _("--%s <number>"), opt->name);
753 break;
754 case VSH_OT_STRING:
755 snprintf(buf, sizeof(buf), _("--%s <string>"), opt->name);
756 break;
757 case VSH_OT_DATA:
758 snprintf(buf, sizeof(buf), _("[--%s] <string>"),
759 opt->name);
760 break;
761 case VSH_OT_ARGV:
762 snprintf(buf, sizeof(buf),
763 shortopt ? _("[--%s] <string>") : _("<%s>"),
764 opt->name);
765 break;
766 case VSH_OT_ALIAS:
767 continue;
770 fprintf(stdout, " %-15s %s\n", buf, _(opt->help));
773 fputc('\n', stdout);
775 return true;
778 /* ---------------
779 * Utils for work with runtime commands data
780 * ---------------
782 static void
783 vshCommandOptFree(vshCmdOpt * arg)
785 vshCmdOpt *a = arg;
787 while (a) {
788 vshCmdOpt *tmp = a;
790 a = a->next;
792 VIR_FREE(tmp->data);
793 VIR_FREE(tmp);
797 static void
798 vshCommandFree(vshCmd *cmd)
800 vshCmd *c = cmd;
802 while (c) {
803 vshCmd *tmp = c;
805 c = c->next;
807 vshCommandOptFree(tmp->opts);
808 VIR_FREE(tmp);
813 * vshCommandOpt:
814 * @cmd: parsed command line to search
815 * @name: option name to search for
816 * @opt: result of the search
817 * @needData: true if option must be non-boolean
819 * Look up an option passed to CMD by NAME. Returns 1 with *OPT set
820 * to the option if found, 0 with *OPT set to NULL if the name is
821 * valid and the option is not required, -1 with *OPT set to NULL if
822 * the option is required but not present, and assert if NAME is not
823 * valid (which indicates a programming error) unless cmd->skipChecks
824 * is set. No error messages are issued if a value is returned.
826 static int
827 vshCommandOpt(const vshCmd *cmd, const char *name, vshCmdOpt **opt,
828 bool needData)
830 vshCmdOpt *candidate = cmd->opts;
831 const vshCmdOptDef *valid = cmd->def->opts;
832 int ret = 0;
834 /* See if option is valid and/or required. */
835 *opt = NULL;
837 while (valid && valid->name) {
838 if (STREQ(name, valid->name))
839 break;
840 valid++;
843 if (!cmd->skipChecks)
844 assert(valid && (!needData || valid->type != VSH_OT_BOOL));
846 if (valid && valid->flags & VSH_OFLAG_REQ)
847 ret = -1;
849 /* See if option is present on command line. */
850 while (candidate) {
851 if (STREQ(candidate->def->name, name)) {
852 *opt = candidate;
853 ret = 1;
854 break;
856 candidate = candidate->next;
858 return ret;
862 * vshCommandOptInt:
863 * @ctl virtshell control structure
864 * @cmd command reference
865 * @name option name
866 * @value result
868 * Convert option to int.
869 * On error, a message is displayed.
871 * Return value:
872 * >0 if option found and valid (@value updated)
873 * 0 if option not found and not required (@value untouched)
874 * <0 in all other cases (@value untouched)
877 vshCommandOptInt(vshControl *ctl, const vshCmd *cmd,
878 const char *name, int *value)
880 vshCmdOpt *arg;
881 int ret;
883 if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
884 return ret;
886 if ((ret = virStrToLong_i(arg->data, NULL, 10, value)) < 0)
887 vshError(ctl,
888 _("Numeric value '%s' for <%s> option is malformed or out of range"),
889 arg->data, name);
890 else
891 ret = 1;
893 return ret;
896 static int
897 vshCommandOptUIntInternal(vshControl *ctl,
898 const vshCmd *cmd,
899 const char *name,
900 unsigned int *value,
901 bool wrap)
903 vshCmdOpt *arg;
904 int ret;
906 if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
907 return ret;
909 if (wrap)
910 ret = virStrToLong_ui(arg->data, NULL, 10, value);
911 else
912 ret = virStrToLong_uip(arg->data, NULL, 10, value);
913 if (ret < 0)
914 vshError(ctl,
915 _("Numeric value '%s' for <%s> option is malformed or out of range"),
916 arg->data, name);
917 else
918 ret = 1;
920 return ret;
924 * vshCommandOptUInt:
925 * @ctl virtshell control structure
926 * @cmd command reference
927 * @name option name
928 * @value result
930 * Convert option to unsigned int, reject negative numbers
931 * See vshCommandOptInt()
934 vshCommandOptUInt(vshControl *ctl, const vshCmd *cmd,
935 const char *name, unsigned int *value)
937 return vshCommandOptUIntInternal(ctl, cmd, name, value, false);
941 * vshCommandOptUIntWrap:
942 * @ctl virtshell control structure
943 * @cmd command reference
944 * @name option name
945 * @value result
947 * Convert option to unsigned int, wraps negative numbers to positive
948 * See vshCommandOptInt()
951 vshCommandOptUIntWrap(vshControl *ctl, const vshCmd *cmd,
952 const char *name, unsigned int *value)
954 return vshCommandOptUIntInternal(ctl, cmd, name, value, true);
957 static int
958 vshCommandOptULInternal(vshControl *ctl,
959 const vshCmd *cmd,
960 const char *name,
961 unsigned long *value,
962 bool wrap)
964 vshCmdOpt *arg;
965 int ret;
967 if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
968 return ret;
970 if (wrap)
971 ret = virStrToLong_ul(arg->data, NULL, 10, value);
972 else
973 ret = virStrToLong_ulp(arg->data, NULL, 10, value);
974 if (ret < 0)
975 vshError(ctl,
976 _("Numeric value '%s' for <%s> option is malformed or out of range"),
977 arg->data, name);
978 else
979 ret = 1;
981 return ret;
985 * vshCommandOptUL:
986 * @ctl virtshell control structure
987 * @cmd command reference
988 * @name option name
989 * @value result
991 * Convert option to unsigned long
992 * See vshCommandOptInt()
995 vshCommandOptUL(vshControl *ctl, const vshCmd *cmd,
996 const char *name, unsigned long *value)
998 return vshCommandOptULInternal(ctl, cmd, name, value, false);
1002 * vshCommandOptULWrap:
1003 * @ctl virtshell control structure
1004 * @cmd command reference
1005 * @name option name
1006 * @value result
1008 * Convert option to unsigned long, wraps negative numbers to positive
1009 * See vshCommandOptInt()
1012 vshCommandOptULWrap(vshControl *ctl, const vshCmd *cmd,
1013 const char *name, unsigned long *value)
1015 return vshCommandOptULInternal(ctl, cmd, name, value, true);
1019 * vshCommandOptStringQuiet:
1020 * @ctl virtshell control structure
1021 * @cmd command reference
1022 * @name option name
1023 * @value result
1025 * Returns option as STRING. On error -1 is returned but no error is set.
1026 * Return value:
1027 * >0 if option found and valid (@value updated)
1028 * 0 if option not found and not required (@value untouched)
1029 * <0 in all other cases (@value untouched)
1032 vshCommandOptStringQuiet(vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd,
1033 const char *name, const char **value)
1035 vshCmdOpt *arg;
1036 int ret;
1038 if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
1039 return ret;
1041 if (!*arg->data && !(arg->def->flags & VSH_OFLAG_EMPTY_OK))
1042 return -1;
1043 *value = arg->data;
1044 return 1;
1048 * vshCommandOptStringReq:
1049 * @ctl virtshell control structure
1050 * @cmd command structure
1051 * @name option name
1052 * @value result (updated to NULL or the option argument)
1054 * Gets a option argument as string.
1056 * Returns 0 on success or when the option is not present and not
1057 * required, *value is set to the option argument. On error -1 is
1058 * returned and error message printed.
1061 vshCommandOptStringReq(vshControl *ctl,
1062 const vshCmd *cmd,
1063 const char *name,
1064 const char **value)
1066 vshCmdOpt *arg;
1067 int ret;
1068 const char *error = NULL;
1070 /* clear out the value */
1071 *value = NULL;
1073 ret = vshCommandOpt(cmd, name, &arg, true);
1074 /* option is not required and not present */
1075 if (ret == 0)
1076 return 0;
1077 /* this should not be propagated here, just to be sure */
1078 if (ret == -1)
1079 error = N_("Mandatory option not present");
1080 else if (!*arg->data && !(arg->def->flags & VSH_OFLAG_EMPTY_OK))
1081 error = N_("Option argument is empty");
1083 if (error) {
1084 if (!cmd->skipChecks)
1085 vshError(ctl, _("Failed to get option '%s': %s"), name, _(error));
1086 return -1;
1089 *value = arg->data;
1090 return 0;
1094 * vshCommandOptLongLong:
1095 * @ctl virtshell control structure
1096 * @cmd command reference
1097 * @name option name
1098 * @value result
1100 * Returns option as long long
1101 * See vshCommandOptInt()
1104 vshCommandOptLongLong(vshControl *ctl, const vshCmd *cmd,
1105 const char *name, long long *value)
1107 vshCmdOpt *arg;
1108 int ret;
1110 if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
1111 return ret;
1113 if ((ret = virStrToLong_ll(arg->data, NULL, 10, value)) < 0)
1114 vshError(ctl,
1115 _("Numeric value '%s' for <%s> option is malformed or out of range"),
1116 arg->data, name);
1117 else
1118 ret = 1;
1120 return ret;
1123 static int
1124 vshCommandOptULongLongInternal(vshControl *ctl,
1125 const vshCmd *cmd,
1126 const char *name,
1127 unsigned long long *value,
1128 bool wrap)
1130 vshCmdOpt *arg;
1131 int ret;
1133 if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
1134 return ret;
1136 if (wrap)
1137 ret = virStrToLong_ull(arg->data, NULL, 10, value);
1138 else
1139 ret = virStrToLong_ullp(arg->data, NULL, 10, value);
1140 if (ret < 0)
1141 vshError(ctl,
1142 _("Numeric value '%s' for <%s> option is malformed or out of range"),
1143 arg->data, name);
1144 else
1145 ret = 1;
1147 return ret;
1151 * vshCommandOptULongLong:
1152 * @ctl virtshell control structure
1153 * @cmd command reference
1154 * @name option name
1155 * @value result
1157 * Returns option as long long, rejects negative numbers
1158 * See vshCommandOptInt()
1161 vshCommandOptULongLong(vshControl *ctl, const vshCmd *cmd,
1162 const char *name, unsigned long long *value)
1164 return vshCommandOptULongLongInternal(ctl, cmd, name, value, false);
1168 * vshCommandOptULongLongWrap:
1169 * @ctl virtshell control structure
1170 * @cmd command reference
1171 * @name option name
1172 * @value result
1174 * Returns option as long long, wraps negative numbers to positive
1175 * See vshCommandOptInt()
1178 vshCommandOptULongLongWrap(vshControl *ctl, const vshCmd *cmd,
1179 const char *name, unsigned long long *value)
1181 return vshCommandOptULongLongInternal(ctl, cmd, name, value, true);
1185 * vshCommandOptScaledInt:
1186 * @ctl virtshell control structure
1187 * @cmd command reference
1188 * @name option name
1189 * @value result
1190 * @scale default of 1 or 1024, if no suffix is present
1191 * @max maximum value permitted
1193 * Returns option as long long, scaled according to suffix
1194 * See vshCommandOptInt()
1197 vshCommandOptScaledInt(vshControl *ctl, const vshCmd *cmd,
1198 const char *name, unsigned long long *value,
1199 int scale, unsigned long long max)
1201 vshCmdOpt *arg;
1202 char *end;
1203 int ret;
1205 if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0)
1206 return ret;
1208 if (virStrToLong_ullp(arg->data, &end, 10, value) < 0 ||
1209 virScaleInteger(value, end, scale, max) < 0) {
1210 vshError(ctl,
1211 _("Scaled numeric value '%s' for <%s> option is malformed or "
1212 "out of range"), arg->data, name);
1213 return -1;
1216 return 1;
1221 * vshCommandOptBool:
1222 * @cmd command reference
1223 * @name option name
1225 * Returns true/false if the option exists. Note that this does NOT
1226 * validate whether the option is actually boolean, or even whether
1227 * name is legal; so that this can be used to probe whether a data
1228 * option is present without actually using that data.
1230 bool
1231 vshCommandOptBool(const vshCmd *cmd, const char *name)
1233 vshCmdOpt *dummy;
1235 return vshCommandOpt(cmd, name, &dummy, false) == 1;
1239 * vshCommandOptArgv:
1240 * @ctl virtshell control structure
1241 * @cmd command reference
1242 * @opt starting point for the search
1244 * Returns the next argv argument after OPT (or the first one if OPT
1245 * is NULL), or NULL if no more are present.
1247 * Requires that a VSH_OT_ARGV option be last in the
1248 * list of supported options in CMD->def->opts.
1250 const vshCmdOpt *
1251 vshCommandOptArgv(vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd,
1252 const vshCmdOpt *opt)
1254 opt = opt ? opt->next : cmd->opts;
1256 while (opt) {
1257 if (opt->def->type == VSH_OT_ARGV)
1258 return opt;
1259 opt = opt->next;
1261 return NULL;
1266 * vshBlockJobOptionBandwidth:
1267 * @ctl: virsh control data
1268 * @cmd: virsh command description
1269 * @bytes: return bandwidth in bytes/s instead of MiB/s
1270 * @bandwidth: return value
1272 * Extracts the value of --bandwidth either as a wrap-able number without scale
1273 * or as a scaled integer. The returned value is checked to fit into a unsigned
1274 * long data type. This is a legacy compatibility function and it should not
1275 * be used for things other the block job APIs.
1277 * Returns 0 on success, -1 on error.
1280 vshBlockJobOptionBandwidth(vshControl *ctl,
1281 const vshCmd *cmd,
1282 bool bytes,
1283 unsigned long *bandwidth)
1285 vshCmdOpt *arg;
1286 char *end;
1287 unsigned long long bw;
1288 int ret;
1290 if ((ret = vshCommandOpt(cmd, "bandwidth", &arg, true)) <= 0)
1291 return ret;
1293 /* due to historical reasons we declare to parse negative numbers and wrap
1294 * them to the unsigned data type. */
1295 if (virStrToLong_ul(arg->data, NULL, 10, bandwidth) < 0) {
1296 /* try to parse the number as scaled size in this case we don't accept
1297 * wrapping since it would be ridiculous. In case of a 32 bit host,
1298 * limit the value to ULONG_MAX */
1299 if (virStrToLong_ullp(arg->data, &end, 10, &bw) < 0 ||
1300 virScaleInteger(&bw, end, 1, ULONG_MAX) < 0) {
1301 vshError(ctl,
1302 _("Scaled numeric value '%s' for <--bandwidth> option is "
1303 "malformed or out of range"), arg->data);
1304 return -1;
1307 if (!bytes)
1308 bw >>= 20;
1310 *bandwidth = bw;
1313 return 0;
1318 * Executes command(s) and returns return code from last command
1320 bool
1321 vshCommandRun(vshControl *ctl, const vshCmd *cmd)
1323 const vshClientHooks *hooks = ctl->hooks;
1324 bool ret = true;
1326 while (cmd) {
1327 struct timeval before, after;
1328 bool enable_timing = ctl->timing;
1330 if (enable_timing)
1331 GETTIMEOFDAY(&before);
1333 if ((cmd->def->flags & VSH_CMD_FLAG_NOCONNECT) ||
1334 (hooks && hooks->connHandler && hooks->connHandler(ctl))) {
1335 ret = cmd->def->handler(ctl, cmd);
1336 } else {
1337 /* connection is not usable, return error */
1338 ret = false;
1341 if (enable_timing)
1342 GETTIMEOFDAY(&after);
1344 /* try to automatically catch disconnections */
1345 if (!ret &&
1346 ((last_error != NULL) &&
1347 (((last_error->code == VIR_ERR_SYSTEM_ERROR) &&
1348 (last_error->domain == VIR_FROM_REMOTE)) ||
1349 (last_error->code == VIR_ERR_RPC) ||
1350 (last_error->code == VIR_ERR_NO_CONNECT) ||
1351 (last_error->code == VIR_ERR_INVALID_CONN))))
1352 disconnected++;
1354 if (!ret)
1355 vshReportError(ctl);
1357 if (STREQ(cmd->def->name, "quit") ||
1358 STREQ(cmd->def->name, "exit")) /* hack ... */
1359 return ret;
1361 if (enable_timing) {
1362 double diff_ms = (((after.tv_sec - before.tv_sec) * 1000.0) +
1363 ((after.tv_usec - before.tv_usec) / 1000.0));
1365 vshPrint(ctl, _("\n(Time: %.3f ms)\n\n"), diff_ms);
1366 } else {
1367 vshPrintExtra(ctl, "\n");
1369 cmd = cmd->next;
1371 return ret;
1374 /* ---------------
1375 * Command parsing
1376 * ---------------
1379 typedef enum {
1380 VSH_TK_ERROR, /* Failed to parse a token */
1381 VSH_TK_ARG, /* Arbitrary argument, might be option or empty */
1382 VSH_TK_SUBCMD_END, /* Separation between commands */
1383 VSH_TK_END /* No more commands */
1384 } vshCommandToken;
1386 typedef struct _vshCommandParser vshCommandParser;
1387 struct _vshCommandParser {
1388 vshCommandToken(*getNextArg)(vshControl *, vshCommandParser *,
1389 char **, bool);
1390 /* vshCommandStringGetArg() */
1391 char *pos;
1392 /* vshCommandArgvGetArg() */
1393 char **arg_pos;
1394 char **arg_end;
1397 static bool
1398 vshCommandParse(vshControl *ctl, vshCommandParser *parser, vshCmd **partial)
1400 char *tkdata = NULL;
1401 vshCmd *clast = NULL;
1402 vshCmdOpt *first = NULL;
1403 const vshCmdDef *cmd = NULL;
1405 if (!partial) {
1406 vshCommandFree(ctl->cmd);
1407 ctl->cmd = NULL;
1410 while (1) {
1411 vshCmdOpt *last = NULL;
1412 vshCommandToken tk;
1413 bool data_only = false;
1414 uint64_t opts_need_arg = 0;
1415 uint64_t opts_required = 0;
1416 uint64_t opts_seen = 0;
1418 cmd = NULL;
1419 first = NULL;
1421 if (partial) {
1422 vshCommandFree(*partial);
1423 *partial = NULL;
1426 while (1) {
1427 const vshCmdOptDef *opt = NULL;
1429 tkdata = NULL;
1430 tk = parser->getNextArg(ctl, parser, &tkdata, true);
1432 if (tk == VSH_TK_ERROR)
1433 goto syntaxError;
1434 if (tk != VSH_TK_ARG) {
1435 VIR_FREE(tkdata);
1436 break;
1439 if (cmd == NULL) {
1440 /* first token must be command name or comment */
1441 if (*tkdata == '#') {
1442 do {
1443 VIR_FREE(tkdata);
1444 tk = parser->getNextArg(ctl, parser, &tkdata, false);
1445 } while (tk == VSH_TK_ARG);
1446 VIR_FREE(tkdata);
1447 break;
1448 } else if (!(cmd = vshCmddefSearch(tkdata))) {
1449 if (!partial)
1450 vshError(ctl, _("unknown command: '%s'"), tkdata);
1451 goto syntaxError; /* ... or ignore this command only? */
1454 /* aliases need to be resolved to the actual commands */
1455 if (cmd->flags & VSH_CMD_FLAG_ALIAS) {
1456 VIR_FREE(tkdata);
1457 tkdata = vshStrdup(ctl, cmd->alias);
1458 cmd = vshCmddefSearch(tkdata);
1460 if (vshCmddefOptParse(cmd, &opts_need_arg,
1461 &opts_required) < 0) {
1462 if (!partial)
1463 vshError(ctl,
1464 _("internal error: bad options in command: '%s'"),
1465 tkdata);
1466 goto syntaxError;
1468 VIR_FREE(tkdata);
1469 } else if (data_only) {
1470 goto get_data;
1471 } else if (tkdata[0] == '-' && tkdata[1] == '-' &&
1472 c_isalnum(tkdata[2])) {
1473 char *optstr = strchr(tkdata + 2, '=');
1474 size_t opt_index = 0;
1476 if (optstr) {
1477 *optstr = '\0'; /* convert the '=' to '\0' */
1478 optstr = vshStrdup(ctl, optstr + 1);
1480 /* Special case 'help' to ignore all spurious options */
1481 if (!(opt = vshCmddefGetOption(ctl, cmd, tkdata + 2,
1482 &opts_seen, &opt_index,
1483 &optstr, partial == NULL))) {
1484 VIR_FREE(optstr);
1485 if (STREQ(cmd->name, "help"))
1486 continue;
1487 goto syntaxError;
1489 VIR_FREE(tkdata);
1491 if (opt->type != VSH_OT_BOOL) {
1492 /* option data */
1493 if (optstr)
1494 tkdata = optstr;
1495 else
1496 tk = parser->getNextArg(ctl, parser, &tkdata, true);
1497 if (tk == VSH_TK_ERROR)
1498 goto syntaxError;
1499 if (tk != VSH_TK_ARG) {
1500 if (partial) {
1501 vshCmdOpt *arg = vshMalloc(ctl, sizeof(vshCmdOpt));
1502 arg->def = opt;
1503 arg->data = tkdata;
1504 tkdata = NULL;
1505 arg->next = NULL;
1506 if (!first)
1507 first = arg;
1508 if (last)
1509 last->next = arg;
1510 last = arg;
1511 } else {
1512 vshError(ctl,
1513 _("expected syntax: --%s <%s>"),
1514 opt->name,
1515 opt->type ==
1516 VSH_OT_INT ? _("number") : _("string"));
1518 goto syntaxError;
1520 if (opt->type != VSH_OT_ARGV)
1521 opts_need_arg &= ~(1ULL << opt_index);
1522 } else {
1523 tkdata = NULL;
1524 if (optstr) {
1525 if (!partial)
1526 vshError(ctl, _("invalid '=' after option --%s"),
1527 opt->name);
1528 VIR_FREE(optstr);
1529 goto syntaxError;
1532 } else if (tkdata[0] == '-' && tkdata[1] == '-' &&
1533 tkdata[2] == '\0') {
1534 VIR_FREE(tkdata);
1535 data_only = true;
1536 continue;
1537 } else {
1538 get_data:
1539 /* Special case 'help' to ignore spurious data */
1540 if (!(opt = vshCmddefGetData(cmd, &opts_need_arg,
1541 &opts_seen)) &&
1542 STRNEQ(cmd->name, "help")) {
1543 if (!partial)
1544 vshError(ctl, _("unexpected data '%s'"), tkdata);
1545 goto syntaxError;
1548 if (opt) {
1549 /* save option */
1550 vshCmdOpt *arg = vshMalloc(ctl, sizeof(vshCmdOpt));
1552 arg->def = opt;
1553 arg->data = tkdata;
1554 arg->next = NULL;
1555 tkdata = NULL;
1557 if (!first)
1558 first = arg;
1559 if (last)
1560 last->next = arg;
1561 last = arg;
1563 if (!partial)
1564 vshDebug(ctl, VSH_ERR_INFO, "%s: %s(%s): %s\n",
1565 cmd->name,
1566 opt->name,
1567 opt->type != VSH_OT_BOOL ? _("optdata") : _("bool"),
1568 opt->type != VSH_OT_BOOL ? arg->data : _("(none)"));
1572 /* command parsed -- allocate new struct for the command */
1573 if (cmd) {
1574 vshCmd *c = vshMalloc(ctl, sizeof(vshCmd));
1575 vshCmdOpt *tmpopt = first;
1577 /* if we encountered --help, replace parsed command with
1578 * 'help <cmdname>' */
1579 for (tmpopt = first; tmpopt; tmpopt = tmpopt->next) {
1580 const vshCmdDef *help;
1581 if (STRNEQ(tmpopt->def->name, "help"))
1582 continue;
1584 help = vshCmddefSearch("help");
1585 vshCommandOptFree(first);
1586 first = vshMalloc(ctl, sizeof(vshCmdOpt));
1587 first->def = help->opts;
1588 first->data = vshStrdup(ctl, cmd->name);
1589 first->next = NULL;
1591 cmd = help;
1592 opts_required = 0;
1593 opts_seen = 0;
1594 break;
1597 c->opts = first;
1598 c->def = cmd;
1599 c->next = NULL;
1600 first = NULL;
1602 if (!partial &&
1603 vshCommandCheckOpts(ctl, c, opts_required, opts_seen) < 0) {
1604 VIR_FREE(c);
1605 goto syntaxError;
1608 if (partial) {
1609 vshCommandFree(*partial);
1610 *partial = c;
1611 } else {
1612 if (!ctl->cmd)
1613 ctl->cmd = c;
1614 if (clast)
1615 clast->next = c;
1616 clast = c;
1620 if (tk == VSH_TK_END)
1621 break;
1624 return true;
1626 syntaxError:
1627 if (partial) {
1628 vshCmd *tmp;
1630 tmp = vshMalloc(ctl, sizeof(*tmp));
1631 tmp->opts = first;
1632 tmp->def = cmd;
1634 *partial = tmp;
1635 } else {
1636 vshCommandFree(ctl->cmd);
1637 ctl->cmd = NULL;
1638 vshCommandOptFree(first);
1640 VIR_FREE(tkdata);
1641 return false;
1644 /* --------------------
1645 * Command argv parsing
1646 * --------------------
1649 static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
1650 vshCommandArgvGetArg(vshControl *ctl, vshCommandParser *parser, char **res,
1651 bool report ATTRIBUTE_UNUSED)
1653 if (parser->arg_pos == parser->arg_end) {
1654 *res = NULL;
1655 return VSH_TK_END;
1658 *res = vshStrdup(ctl, *parser->arg_pos);
1659 parser->arg_pos++;
1660 return VSH_TK_ARG;
1663 bool
1664 vshCommandArgvParse(vshControl *ctl, int nargs, char **argv)
1666 vshCommandParser parser;
1668 if (nargs <= 0)
1669 return false;
1671 parser.arg_pos = argv;
1672 parser.arg_end = argv + nargs;
1673 parser.getNextArg = vshCommandArgvGetArg;
1674 return vshCommandParse(ctl, &parser, NULL);
1677 /* ----------------------
1678 * Command string parsing
1679 * ----------------------
1682 static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
1683 vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res,
1684 bool report)
1686 bool single_quote = false;
1687 bool double_quote = false;
1688 int sz = 0;
1689 char *p = parser->pos;
1690 char *q = vshStrdup(ctl, p);
1692 *res = q;
1694 while (*p == ' ' || *p == '\t' || (*p == '\\' && p[1] == '\n'))
1695 p += 1 + (*p == '\\');
1697 if (*p == '\0')
1698 return VSH_TK_END;
1699 if (*p == ';' || *p == '\n') {
1700 parser->pos = ++p; /* = \0 or begin of next command */
1701 return VSH_TK_SUBCMD_END;
1703 if (*p == '#') { /* Argument starting with # is comment to end of line */
1704 while (*p && *p != '\n')
1705 p++;
1706 parser->pos = p + !!*p;
1707 return VSH_TK_SUBCMD_END;
1710 while (*p) {
1711 /* end of token is blank space or ';' */
1712 if (!double_quote && !single_quote &&
1713 (*p == ' ' || *p == '\t' || *p == ';' || *p == '\n'))
1714 break;
1716 if (!double_quote && *p == '\'') { /* single quote */
1717 single_quote = !single_quote;
1718 p++;
1719 continue;
1720 } else if (!single_quote && *p == '\\') { /* escape */
1722 * The same as in shell, a \ in "" is an escaper,
1723 * but a \ in '' is not an escaper.
1725 p++;
1726 if (*p == '\0') {
1727 if (report)
1728 vshError(ctl, "%s", _("dangling \\"));
1729 return VSH_TK_ERROR;
1730 } else if (*p == '\n') {
1731 /* Elide backslash-newline entirely */
1732 p++;
1733 continue;
1735 } else if (!single_quote && *p == '"') { /* double quote */
1736 double_quote = !double_quote;
1737 p++;
1738 continue;
1741 *q++ = *p++;
1742 sz++;
1744 if (double_quote) {
1745 if (report)
1746 vshError(ctl, "%s", _("missing \""));
1747 return VSH_TK_ERROR;
1750 *q = '\0';
1751 parser->pos = p;
1752 return VSH_TK_ARG;
1755 bool
1756 vshCommandStringParse(vshControl *ctl, char *cmdstr, vshCmd **partial)
1758 vshCommandParser parser;
1760 if (cmdstr == NULL || *cmdstr == '\0')
1761 return false;
1763 parser.pos = cmdstr;
1764 parser.getNextArg = vshCommandStringGetArg;
1765 return vshCommandParse(ctl, &parser, partial);
1769 * virshCommandOptTimeoutToMs:
1770 * @ctl virsh control structure
1771 * @cmd command reference
1772 * @timeout result
1774 * Parse an optional --timeout parameter in seconds, but store the
1775 * value of the timeout in milliseconds.
1776 * See vshCommandOptInt()
1779 vshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout)
1781 int ret;
1782 unsigned int utimeout;
1784 if ((ret = vshCommandOptUInt(ctl, cmd, "timeout", &utimeout)) <= 0)
1785 return ret;
1787 /* Ensure that the timeout is not zero and that we can convert
1788 * it from seconds to milliseconds without overflowing. */
1789 if (utimeout == 0 || utimeout > INT_MAX / 1000) {
1790 vshError(ctl,
1791 _("Numeric value '%u' for <%s> option is malformed or out of range"),
1792 utimeout,
1793 "timeout");
1794 ret = -1;
1795 } else {
1796 *timeout = ((int) utimeout) * 1000;
1799 return ret;
1803 /* ---------------
1804 * Misc utils
1805 * ---------------
1808 /* Return a non-NULL string representation of a typed parameter; exit
1809 * if we are out of memory. */
1810 char *
1811 vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item)
1813 int ret = 0;
1814 char *str = NULL;
1816 switch (item->type) {
1817 case VIR_TYPED_PARAM_INT:
1818 ret = virAsprintf(&str, "%d", item->value.i);
1819 break;
1821 case VIR_TYPED_PARAM_UINT:
1822 ret = virAsprintf(&str, "%u", item->value.ui);
1823 break;
1825 case VIR_TYPED_PARAM_LLONG:
1826 ret = virAsprintf(&str, "%lld", item->value.l);
1827 break;
1829 case VIR_TYPED_PARAM_ULLONG:
1830 ret = virAsprintf(&str, "%llu", item->value.ul);
1831 break;
1833 case VIR_TYPED_PARAM_DOUBLE:
1834 ret = virAsprintf(&str, "%f", item->value.d);
1835 break;
1837 case VIR_TYPED_PARAM_BOOLEAN:
1838 str = vshStrdup(ctl, item->value.b ? _("yes") : _("no"));
1839 break;
1841 case VIR_TYPED_PARAM_STRING:
1842 str = vshStrdup(ctl, item->value.s);
1843 break;
1845 default:
1846 vshError(ctl, _("unimplemented parameter type %d"), item->type);
1849 if (ret < 0) {
1850 vshError(ctl, "%s", _("Out of memory"));
1851 exit(EXIT_FAILURE);
1853 return str;
1856 void
1857 vshDebug(vshControl *ctl, int level, const char *format, ...)
1859 va_list ap;
1860 char *str;
1862 /* Aligning log levels to that of libvirt.
1863 * Traces with levels >= user-specified-level
1864 * gets logged into file
1866 if (level < ctl->debug)
1867 return;
1869 va_start(ap, format);
1870 vshOutputLogFile(ctl, level, format, ap);
1871 va_end(ap);
1873 va_start(ap, format);
1874 if (virVasprintf(&str, format, ap) < 0) {
1875 /* Skip debug messages on low memory */
1876 va_end(ap);
1877 return;
1879 va_end(ap);
1880 fputs(str, stdout);
1881 VIR_FREE(str);
1884 void
1885 vshPrintExtra(vshControl *ctl, const char *format, ...)
1887 va_list ap;
1888 char *str;
1890 if (ctl && ctl->quiet)
1891 return;
1893 va_start(ap, format);
1894 if (virVasprintfQuiet(&str, format, ap) < 0)
1895 vshErrorOOM();
1896 va_end(ap);
1897 fputs(str, stdout);
1898 VIR_FREE(str);
1902 void
1903 vshPrint(vshControl *ctl ATTRIBUTE_UNUSED, const char *format, ...)
1905 va_list ap;
1906 char *str;
1908 va_start(ap, format);
1909 if (virVasprintfQuiet(&str, format, ap) < 0)
1910 vshErrorOOM();
1911 va_end(ap);
1912 fputs(str, stdout);
1913 VIR_FREE(str);
1917 bool
1918 vshTTYIsInterruptCharacter(vshControl *ctl ATTRIBUTE_UNUSED,
1919 const char chr ATTRIBUTE_UNUSED)
1921 #ifndef WIN32
1922 if (ctl->istty &&
1923 ctl->termattr.c_cc[VINTR] == chr)
1924 return true;
1925 #endif
1927 return false;
1931 bool
1932 vshTTYAvailable(vshControl *ctl)
1934 return ctl->istty;
1939 vshTTYDisableInterrupt(vshControl *ctl ATTRIBUTE_UNUSED)
1941 #ifndef WIN32
1942 struct termios termset = ctl->termattr;
1944 if (!ctl->istty)
1945 return -1;
1947 /* check if we need to set the terminal */
1948 if (termset.c_cc[VINTR] == _POSIX_VDISABLE)
1949 return 0;
1951 termset.c_cc[VINTR] = _POSIX_VDISABLE;
1952 termset.c_lflag &= ~ICANON;
1954 if (tcsetattr(STDIN_FILENO, TCSANOW, &termset) < 0)
1955 return -1;
1956 #endif
1958 return 0;
1963 vshTTYRestore(vshControl *ctl ATTRIBUTE_UNUSED)
1965 #ifndef WIN32
1966 if (!ctl->istty)
1967 return 0;
1969 if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &ctl->termattr) < 0)
1970 return -1;
1971 #endif
1973 return 0;
1977 #if !defined(WIN32) && !defined(HAVE_CFMAKERAW)
1978 /* provide fallback in case cfmakeraw isn't available */
1979 static void
1980 cfmakeraw(struct termios *attr)
1982 attr->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
1983 | INLCR | IGNCR | ICRNL | IXON);
1984 attr->c_oflag &= ~OPOST;
1985 attr->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
1986 attr->c_cflag &= ~(CSIZE | PARENB);
1987 attr->c_cflag |= CS8;
1989 #endif /* !WIN32 && !HAVE_CFMAKERAW */
1993 vshTTYMakeRaw(vshControl *ctl ATTRIBUTE_UNUSED,
1994 bool report_errors ATTRIBUTE_UNUSED)
1996 #ifndef WIN32
1997 struct termios rawattr = ctl->termattr;
1998 char ebuf[1024];
2000 if (!ctl->istty) {
2001 if (report_errors) {
2002 vshError(ctl, "%s",
2003 _("unable to make terminal raw: console isn't a tty"));
2006 return -1;
2009 cfmakeraw(&rawattr);
2011 if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) {
2012 if (report_errors)
2013 vshError(ctl, _("unable to set tty attributes: %s"),
2014 virStrerror(errno, ebuf, sizeof(ebuf)));
2015 return -1;
2017 #endif
2019 return 0;
2023 void
2024 vshError(vshControl *ctl, const char *format, ...)
2026 va_list ap;
2027 char *str;
2029 if (ctl != NULL) {
2030 va_start(ap, format);
2031 vshOutputLogFile(ctl, VSH_ERR_ERROR, format, ap);
2032 va_end(ap);
2035 /* Most output is to stdout, but if someone ran virsh 2>&1, then
2036 * printing to stderr will not interleave correctly with stdout
2037 * unless we flush between every transition between streams. */
2038 fflush(stdout);
2039 fputs(_("error: "), stderr);
2041 va_start(ap, format);
2042 /* We can't recursively call vshError on an OOM situation, so ignore
2043 failure here. */
2044 ignore_value(virVasprintf(&str, format, ap));
2045 va_end(ap);
2047 fprintf(stderr, "%s\n", NULLSTR(str));
2048 fflush(stderr);
2049 VIR_FREE(str);
2053 void
2054 vshEventLoop(void *opaque)
2056 vshControl *ctl = opaque;
2058 while (1) {
2059 bool quit;
2060 virMutexLock(&ctl->lock);
2061 quit = ctl->quit;
2062 virMutexUnlock(&ctl->lock);
2064 if (quit)
2065 break;
2067 if (virEventRunDefaultImpl() < 0)
2068 vshReportError(ctl);
2074 * Helpers for waiting for a libvirt event.
2077 /* We want to use SIGINT to cancel a wait; but as signal handlers
2078 * don't have an opaque argument, we have to use static storage. */
2079 static int vshEventFd = -1;
2080 static struct sigaction vshEventOldAction;
2083 /* Signal handler installed in vshEventStart, removed in vshEventCleanup. */
2084 static void
2085 vshEventInt(int sig ATTRIBUTE_UNUSED,
2086 siginfo_t *siginfo ATTRIBUTE_UNUSED,
2087 void *context ATTRIBUTE_UNUSED)
2089 char reason = VSH_EVENT_INTERRUPT;
2090 if (vshEventFd >= 0)
2091 ignore_value(safewrite(vshEventFd, &reason, 1));
2095 /* Event loop handler used to limit length of waiting for any other event. */
2096 void
2097 vshEventTimeout(int timer ATTRIBUTE_UNUSED,
2098 void *opaque)
2100 vshControl *ctl = opaque;
2101 char reason = VSH_EVENT_TIMEOUT;
2103 if (ctl->eventPipe[1] >= 0)
2104 ignore_value(safewrite(ctl->eventPipe[1], &reason, 1));
2109 * vshEventStart:
2110 * @ctl vsh command struct
2111 * @timeout_ms max wait time in milliseconds, or 0 for indefinite
2113 * Set up a wait for a libvirt event. The wait can be canceled by
2114 * SIGINT or by calling vshEventDone() in your event handler. If
2115 * @timeout_ms is positive, the wait will also end if the timeout
2116 * expires. Call vshEventWait() to block the main thread (the event
2117 * handler runs in the event loop thread). When done (including if
2118 * there was an error registering for an event), use vshEventCleanup()
2119 * to quit waiting. Returns 0 on success, -1 on failure. */
2121 vshEventStart(vshControl *ctl, int timeout_ms)
2123 struct sigaction action;
2125 assert(ctl->eventPipe[0] == -1 && ctl->eventPipe[1] == -1 &&
2126 vshEventFd == -1 && ctl->eventTimerId >= 0);
2127 if (pipe2(ctl->eventPipe, O_CLOEXEC) < 0) {
2128 char ebuf[1024];
2130 vshError(ctl, _("failed to create pipe: %s"),
2131 virStrerror(errno, ebuf, sizeof(ebuf)));
2132 return -1;
2134 vshEventFd = ctl->eventPipe[1];
2136 action.sa_sigaction = vshEventInt;
2137 action.sa_flags = SA_SIGINFO;
2138 sigemptyset(&action.sa_mask);
2139 sigaction(SIGINT, &action, &vshEventOldAction);
2141 if (timeout_ms)
2142 virEventUpdateTimeout(ctl->eventTimerId, timeout_ms);
2144 return 0;
2149 * vshEventDone:
2150 * @ctl vsh command struct
2152 * Call this from an event callback to let the main thread quit
2153 * blocking on further events.
2155 void
2156 vshEventDone(vshControl *ctl)
2158 char reason = VSH_EVENT_DONE;
2160 if (ctl->eventPipe[1] >= 0)
2161 ignore_value(safewrite(ctl->eventPipe[1], &reason, 1));
2166 * vshEventWait:
2167 * @ctl vsh command struct
2169 * Call this in the main thread after calling vshEventStart() then
2170 * registering for one or more events. This call will block until
2171 * SIGINT, the timeout registered at the start, or until one of your
2172 * event handlers calls vshEventDone(). Returns an enum VSH_EVENT_*
2173 * stating how the wait concluded, or -1 on error.
2176 vshEventWait(vshControl *ctl)
2178 char buf;
2179 int rv;
2181 assert(ctl->eventPipe[0] >= 0);
2182 while ((rv = read(ctl->eventPipe[0], &buf, 1)) < 0 && errno == EINTR);
2183 if (rv != 1) {
2184 char ebuf[1024];
2186 if (!rv)
2187 errno = EPIPE;
2188 vshError(ctl, _("failed to determine loop exit status: %s"),
2189 virStrerror(errno, ebuf, sizeof(ebuf)));
2190 return -1;
2192 return buf;
2197 * vshEventCleanup:
2198 * @ctl vsh control struct
2200 * Call at the end of any function that has used vshEventStart(), to
2201 * tear down any remaining SIGINT or timeout handlers.
2203 void
2204 vshEventCleanup(vshControl *ctl)
2206 if (vshEventFd >= 0) {
2207 sigaction(SIGINT, &vshEventOldAction, NULL);
2208 vshEventFd = -1;
2210 VIR_FORCE_CLOSE(ctl->eventPipe[0]);
2211 VIR_FORCE_CLOSE(ctl->eventPipe[1]);
2212 virEventUpdateTimeout(ctl->eventTimerId, -1);
2215 #define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC)
2218 * vshOpenLogFile:
2220 * Open log file.
2222 void
2223 vshOpenLogFile(vshControl *ctl)
2225 if (ctl->logfile == NULL)
2226 return;
2228 if ((ctl->log_fd = open(ctl->logfile, LOGFILE_FLAGS, FILE_MODE)) < 0) {
2229 vshError(ctl, "%s",
2230 _("failed to open the log file. check the log file path"));
2231 exit(EXIT_FAILURE);
2236 * vshOutputLogFile:
2238 * Outputting an error to log file.
2240 void
2241 vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format,
2242 va_list ap)
2244 virBuffer buf = VIR_BUFFER_INITIALIZER;
2245 char *str = NULL;
2246 size_t len;
2247 const char *lvl = "";
2248 time_t stTime;
2249 struct tm stTm;
2251 if (ctl->log_fd == -1)
2252 return;
2255 * create log format
2257 * [YYYY.MM.DD HH:MM:SS SIGNATURE PID] LOG_LEVEL message
2259 time(&stTime);
2260 localtime_r(&stTime, &stTm);
2261 virBufferAsprintf(&buf, "[%d.%02d.%02d %02d:%02d:%02d %s %d] ",
2262 (1900 + stTm.tm_year),
2263 (1 + stTm.tm_mon),
2264 stTm.tm_mday,
2265 stTm.tm_hour,
2266 stTm.tm_min,
2267 stTm.tm_sec,
2268 ctl->progname,
2269 (int) getpid());
2270 switch (log_level) {
2271 case VSH_ERR_DEBUG:
2272 lvl = LVL_DEBUG;
2273 break;
2274 case VSH_ERR_INFO:
2275 lvl = LVL_INFO;
2276 break;
2277 case VSH_ERR_NOTICE:
2278 lvl = LVL_INFO;
2279 break;
2280 case VSH_ERR_WARNING:
2281 lvl = LVL_WARNING;
2282 break;
2283 case VSH_ERR_ERROR:
2284 lvl = LVL_ERROR;
2285 break;
2286 default:
2287 lvl = LVL_DEBUG;
2288 break;
2290 virBufferAsprintf(&buf, "%s ", lvl);
2291 virBufferVasprintf(&buf, msg_format, ap);
2292 virBufferTrim(&buf, "\n", -1);
2293 virBufferAddChar(&buf, '\n');
2295 if (virBufferError(&buf))
2296 goto error;
2298 str = virBufferContentAndReset(&buf);
2299 len = strlen(str);
2301 /* write log */
2302 if (safewrite(ctl->log_fd, str, len) < 0)
2303 goto error;
2305 VIR_FREE(str);
2306 return;
2308 error:
2309 vshCloseLogFile(ctl);
2310 vshError(ctl, "%s", _("failed to write the log file"));
2311 virBufferFreeAndReset(&buf);
2312 VIR_FREE(str);
2316 * vshCloseLogFile:
2318 * Close log file.
2320 void
2321 vshCloseLogFile(vshControl *ctl)
2323 char ebuf[1024];
2325 /* log file close */
2326 if (VIR_CLOSE(ctl->log_fd) < 0) {
2327 vshError(ctl, _("%s: failed to write log file: %s"),
2328 ctl->logfile ? ctl->logfile : "?",
2329 virStrerror(errno, ebuf, sizeof(ebuf)));
2332 if (ctl->logfile) {
2333 VIR_FREE(ctl->logfile);
2334 ctl->logfile = NULL;
2338 #ifndef WIN32
2339 static void
2340 vshPrintRaw(vshControl *ctl, ...)
2342 va_list ap;
2343 char *key;
2345 va_start(ap, ctl);
2346 while ((key = va_arg(ap, char *)) != NULL)
2347 vshPrint(ctl, "%s\r\n", key);
2348 va_end(ap);
2352 * vshAskReedit:
2353 * @msg: Question to ask user
2355 * Ask user if he wants to return to previously
2356 * edited file.
2358 * Returns 'y' if he wants to
2359 * 'n' if he doesn't want to
2360 * 'i' if he wants to try defining it again while ignoring validation
2361 * 'f' if he forcibly wants to
2362 * -1 on error
2363 * 0 otherwise
2366 vshAskReedit(vshControl *ctl, const char *msg, bool relax_avail)
2368 int c = -1;
2370 if (!isatty(STDIN_FILENO))
2371 return -1;
2373 vshReportError(ctl);
2375 if (vshTTYMakeRaw(ctl, false) < 0)
2376 return -1;
2378 while (true) {
2379 vshPrint(ctl, "\r%s %s %s: ", msg, _("Try again?"),
2380 relax_avail ? "[y,n,i,f,?]" : "[y,n,f,?]");
2381 c = c_tolower(getchar());
2383 if (c == '?') {
2384 vshPrintRaw(ctl,
2386 _("y - yes, start editor again"),
2387 _("n - no, throw away my changes"),
2388 NULL);
2390 if (relax_avail) {
2391 vshPrintRaw(ctl,
2392 _("i - turn off validation and try to redefine "
2393 "again"),
2394 NULL);
2397 vshPrintRaw(ctl,
2398 _("f - force, try to redefine again"),
2399 _("? - print this help"),
2400 NULL);
2401 continue;
2402 } else if (c == 'y' || c == 'n' || c == 'f' ||
2403 (relax_avail && c == 'i')) {
2404 break;
2408 vshTTYRestore(ctl);
2410 vshPrint(ctl, "\r\n");
2411 return c;
2413 #else /* WIN32 */
2415 vshAskReedit(vshControl *ctl,
2416 const char *msg ATTRIBUTE_UNUSED,
2417 bool relax_avail ATTRIBUTE_UNUSED)
2419 vshDebug(ctl, VSH_ERR_WARNING, "%s", _("This function is not "
2420 "supported on WIN32 platform"));
2421 return 0;
2423 #endif /* WIN32 */
2426 /* Common code for the edit / net-edit / pool-edit functions which follow. */
2427 char *
2428 vshEditWriteToTempFile(vshControl *ctl, const char *doc)
2430 char *ret;
2431 const char *tmpdir;
2432 int fd;
2433 char ebuf[1024];
2435 tmpdir = virGetEnvBlockSUID("TMPDIR");
2436 if (!tmpdir) tmpdir = "/tmp";
2437 if (virAsprintf(&ret, "%s/virshXXXXXX.xml", tmpdir) < 0) {
2438 vshError(ctl, "%s", _("out of memory"));
2439 return NULL;
2441 fd = mkostemps(ret, 4, O_CLOEXEC);
2442 if (fd == -1) {
2443 vshError(ctl, _("mkostemps: failed to create temporary file: %s"),
2444 virStrerror(errno, ebuf, sizeof(ebuf)));
2445 VIR_FREE(ret);
2446 return NULL;
2449 if (safewrite(fd, doc, strlen(doc)) == -1) {
2450 vshError(ctl, _("write: %s: failed to write to temporary file: %s"),
2451 ret, virStrerror(errno, ebuf, sizeof(ebuf)));
2452 VIR_FORCE_CLOSE(fd);
2453 unlink(ret);
2454 VIR_FREE(ret);
2455 return NULL;
2457 if (VIR_CLOSE(fd) < 0) {
2458 vshError(ctl, _("close: %s: failed to write or close temporary file: %s"),
2459 ret, virStrerror(errno, ebuf, sizeof(ebuf)));
2460 unlink(ret);
2461 VIR_FREE(ret);
2462 return NULL;
2465 /* Temporary filename: caller frees. */
2466 return ret;
2469 /* Characters permitted in $EDITOR environment variable and temp filename. */
2470 #define ACCEPTED_CHARS \
2471 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/_.:@"
2474 vshEditFile(vshControl *ctl, const char *filename)
2476 const char *editor;
2477 virCommandPtr cmd;
2478 int ret = -1;
2479 int outfd = STDOUT_FILENO;
2480 int errfd = STDERR_FILENO;
2482 editor = virGetEnvBlockSUID("VISUAL");
2483 if (!editor)
2484 editor = virGetEnvBlockSUID("EDITOR");
2485 if (!editor)
2486 editor = DEFAULT_EDITOR;
2488 /* Check that filename doesn't contain shell meta-characters, and
2489 * if it does, refuse to run. Follow the Unix conventions for
2490 * EDITOR: the user can intentionally specify command options, so
2491 * we don't protect any shell metacharacters there. Lots more
2492 * than virsh will misbehave if EDITOR has bogus contents (which
2493 * is why sudo scrubs it by default). Conversely, if the editor
2494 * is safe, we can run it directly rather than wasting a shell.
2496 if (strspn(editor, ACCEPTED_CHARS) != strlen(editor)) {
2497 if (strspn(filename, ACCEPTED_CHARS) != strlen(filename)) {
2498 vshError(ctl,
2499 _("%s: temporary filename contains shell meta or other "
2500 "unacceptable characters (is $TMPDIR wrong?)"),
2501 filename);
2502 return -1;
2504 cmd = virCommandNewArgList("sh", "-c", NULL);
2505 virCommandAddArgFormat(cmd, "%s %s", editor, filename);
2506 } else {
2507 cmd = virCommandNewArgList(editor, filename, NULL);
2510 virCommandSetInputFD(cmd, STDIN_FILENO);
2511 virCommandSetOutputFD(cmd, &outfd);
2512 virCommandSetErrorFD(cmd, &errfd);
2513 if (virCommandRunAsync(cmd, NULL) < 0 ||
2514 virCommandWait(cmd, NULL) < 0) {
2515 vshReportError(ctl);
2516 goto cleanup;
2518 ret = 0;
2520 cleanup:
2521 virCommandFree(cmd);
2522 return ret;
2525 char *
2526 vshEditReadBackFile(vshControl *ctl, const char *filename)
2528 char *ret;
2529 char ebuf[1024];
2531 if (virFileReadAll(filename, VSH_MAX_XML_FILE, &ret) == -1) {
2532 vshError(ctl,
2533 _("%s: failed to read temporary file: %s"),
2534 filename, virStrerror(errno, ebuf, sizeof(ebuf)));
2535 return NULL;
2537 return ret;
2541 /* Tree listing helpers. */
2543 static int
2544 vshTreePrintInternal(vshControl *ctl,
2545 vshTreeLookup lookup,
2546 void *opaque,
2547 int num_devices,
2548 int devid,
2549 int lastdev,
2550 bool root,
2551 virBufferPtr indent)
2553 size_t i;
2554 int nextlastdev = -1;
2555 int ret = -1;
2556 const char *dev = (lookup)(devid, false, opaque);
2558 if (virBufferError(indent))
2559 goto cleanup;
2561 /* Print this device, with indent if not at root */
2562 vshPrint(ctl, "%s%s%s\n", virBufferCurrentContent(indent),
2563 root ? "" : "+- ", dev);
2565 /* Update indent to show '|' or ' ' for child devices */
2566 if (!root) {
2567 virBufferAddChar(indent, devid == lastdev ? ' ' : '|');
2568 virBufferAddChar(indent, ' ');
2569 if (virBufferError(indent))
2570 goto cleanup;
2573 /* Determine the index of the last child device */
2574 for (i = 0; i < num_devices; i++) {
2575 const char *parent = (lookup)(i, true, opaque);
2577 if (parent && STREQ(parent, dev))
2578 nextlastdev = i;
2581 /* If there is a child device, then print another blank line */
2582 if (nextlastdev != -1)
2583 vshPrint(ctl, "%s |\n", virBufferCurrentContent(indent));
2585 /* Finally print all children */
2586 virBufferAddLit(indent, " ");
2587 if (virBufferError(indent))
2588 goto cleanup;
2589 for (i = 0; i < num_devices; i++) {
2590 const char *parent = (lookup)(i, true, opaque);
2592 if (parent && STREQ(parent, dev) &&
2593 vshTreePrintInternal(ctl, lookup, opaque,
2594 num_devices, i, nextlastdev,
2595 false, indent) < 0)
2596 goto cleanup;
2598 virBufferTrim(indent, " ", -1);
2600 /* If there was no child device, and we're the last in
2601 * a list of devices, then print another blank line */
2602 if (nextlastdev == -1 && devid == lastdev)
2603 vshPrint(ctl, "%s\n", virBufferCurrentContent(indent));
2605 if (!root)
2606 virBufferTrim(indent, NULL, 2);
2607 ret = 0;
2608 cleanup:
2609 return ret;
2613 vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque,
2614 int num_devices, int devid)
2616 int ret;
2617 virBuffer indent = VIR_BUFFER_INITIALIZER;
2619 ret = vshTreePrintInternal(ctl, lookup, opaque, num_devices,
2620 devid, devid, true, &indent);
2621 if (ret < 0)
2622 vshError(ctl, "%s", _("Failed to complete tree listing"));
2623 virBufferFreeAndReset(&indent);
2624 return ret;
2627 #if WITH_READLINE
2629 /* -----------------
2630 * Readline stuff
2631 * -----------------
2635 * vshReadlineCommandGenerator:
2636 * @text: optional command prefix
2638 * Generator function for command completion.
2640 * Returns a string list of commands with @text prefix,
2641 * NULL if there's no such command.
2643 static char **
2644 vshReadlineCommandGenerator(const char *text)
2646 size_t grp_list_index = 0, cmd_list_index = 0;
2647 size_t len = strlen(text);
2648 const char *name;
2649 const vshCmdGrp *grp;
2650 const vshCmdDef *cmds;
2651 size_t ret_size = 0;
2652 char **ret = NULL;
2654 grp = cmdGroups;
2656 /* Return the next name which partially matches from the
2657 * command list.
2659 while (grp[grp_list_index].name) {
2660 cmds = grp[grp_list_index].commands;
2662 if (cmds[cmd_list_index].name) {
2663 while ((name = cmds[cmd_list_index].name)) {
2664 if (cmds[cmd_list_index++].flags & VSH_CMD_FLAG_ALIAS)
2665 continue;
2667 if (STREQLEN(name, text, len)) {
2668 if (VIR_REALLOC_N(ret, ret_size + 2) < 0) {
2669 virStringListFree(ret);
2670 return NULL;
2672 ret[ret_size] = vshStrdup(NULL, name);
2673 ret_size++;
2674 /* Terminate the string list properly. */
2675 ret[ret_size] = NULL;
2678 } else {
2679 cmd_list_index = 0;
2680 grp_list_index++;
2684 return ret;
2687 static char **
2688 vshReadlineOptionsGenerator(const char *text,
2689 const vshCmdDef *cmd,
2690 vshCmd *last)
2692 size_t list_index = 0;
2693 size_t len = strlen(text);
2694 const char *name;
2695 size_t ret_size = 0;
2696 char **ret = NULL;
2698 if (!cmd)
2699 return NULL;
2701 if (!cmd->opts)
2702 return NULL;
2704 while ((name = cmd->opts[list_index].name)) {
2705 bool exists = false;
2706 vshCmdOpt *opt = last->opts;
2707 size_t name_len;
2709 list_index++;
2711 if (len > 2) {
2712 /* provide auto-complete only when the text starts with -- */
2713 if (STRNEQLEN(text, "--", 2))
2714 return NULL;
2715 if (STRNEQLEN(name, text + 2, len - 2))
2716 continue;
2717 } else if (STRNEQLEN(text, "--", len)) {
2718 return NULL;
2721 while (opt) {
2722 if (STREQ(opt->def->name, name) && opt->def->type != VSH_OT_ARGV) {
2723 exists = true;
2724 break;
2727 opt = opt->next;
2730 if (exists)
2731 continue;
2733 if (VIR_REALLOC_N(ret, ret_size + 2) < 0) {
2734 virStringListFree(ret);
2735 return NULL;
2738 name_len = strlen(name);
2739 ret[ret_size] = vshMalloc(NULL, name_len + 3);
2740 snprintf(ret[ret_size], name_len + 3, "--%s", name);
2741 ret_size++;
2742 /* Terminate the string list properly. */
2743 ret[ret_size] = NULL;
2746 return ret;
2750 static const vshCmdOptDef *
2751 vshReadlineCommandFindOpt(const vshCmd *partial,
2752 const char *text)
2754 const vshCmd *tmp = partial;
2756 while (tmp && tmp->next) {
2757 if (tmp->def == tmp->next->def &&
2758 !tmp->next->opts)
2759 break;
2760 tmp = tmp->next;
2763 if (tmp && tmp->opts) {
2764 const vshCmdOpt *opt = tmp->opts;
2766 while (opt) {
2767 if (STREQ_NULLABLE(opt->data, text) ||
2768 STREQ_NULLABLE(opt->data, " "))
2769 return opt->def;
2771 opt = opt->next;
2775 return NULL;
2779 static int
2780 vshCompleterFilter(char ***list,
2781 const char *text)
2783 char **newList = NULL;
2784 size_t newList_len = 0;
2785 size_t list_len;
2786 size_t i;
2788 if (!list || !*list)
2789 return -1;
2791 list_len = virStringListLength((const char **) *list);
2793 if (VIR_ALLOC_N(newList, list_len + 1) < 0)
2794 return -1;
2796 for (i = 0; i < list_len; i++) {
2797 if (!STRPREFIX((*list)[i], text)) {
2798 VIR_FREE((*list)[i]);
2799 continue;
2802 VIR_STEAL_PTR(newList[newList_len], (*list)[i]);
2803 newList_len++;
2806 ignore_value(VIR_REALLOC_N_QUIET(newList, newList_len + 1));
2807 VIR_FREE(*list);
2808 *list = newList;
2809 return 0;
2813 static char *
2814 vshReadlineParse(const char *text, int state)
2816 static vshCmd *partial;
2817 static char **list;
2818 static size_t list_index;
2819 const vshCmdDef *cmd = NULL;
2820 const vshCmdOptDef *opt = NULL;
2821 char *ret = NULL;
2823 if (!state) {
2824 char *buf = vshStrdup(NULL, rl_line_buffer);
2826 vshCommandFree(partial);
2827 partial = NULL;
2828 virStringListFree(list);
2829 list = NULL;
2830 list_index = 0;
2832 *(buf + rl_point) = '\0';
2834 vshCommandStringParse(NULL, buf, &partial);
2836 VIR_FREE(buf);
2838 if (partial) {
2839 cmd = partial->def;
2840 partial->skipChecks = true;
2843 if (cmd && STREQ(cmd->name, text)) {
2844 /* Corner case - some commands share prefix (e.g.
2845 * dump and dumpxml). If user typed 'dump<TAB><TAB>',
2846 * then @text = "dump" and we want to offer command
2847 * completion. If they typed 'dump <TAB><TAB>' then
2848 * @text = "" (the space after the command) and we
2849 * want to offer options completion for dump command.
2851 cmd = NULL;
2854 opt = vshReadlineCommandFindOpt(partial, text);
2857 if (!list) {
2858 if (!cmd) {
2859 list = vshReadlineCommandGenerator(text);
2860 } else {
2861 if (!opt || (opt->type != VSH_OT_DATA &&
2862 opt->type != VSH_OT_STRING &&
2863 opt->type != VSH_OT_ARGV))
2864 list = vshReadlineOptionsGenerator(text, cmd, partial);
2866 if (opt && opt->completer) {
2867 char **completer_list = opt->completer(autoCompleteOpaque,
2868 partial,
2869 opt->completer_flags);
2871 /* For string list returned by completer we have to do
2872 * filtering based on @text because completer returns all
2873 * possible strings. */
2875 if (completer_list &&
2876 (vshCompleterFilter(&completer_list, text) < 0 ||
2877 virStringListMerge(&list, &completer_list) < 0)) {
2878 virStringListFree(completer_list);
2879 goto cleanup;
2885 if (list) {
2886 ret = vshStrdup(NULL, list[list_index]);
2887 list_index++;
2890 if (ret &&
2891 !rl_completion_quote_character) {
2892 virBuffer buf = VIR_BUFFER_INITIALIZER;
2893 virBufferEscapeShell(&buf, ret);
2894 VIR_FREE(ret);
2895 ret = virBufferContentAndReset(&buf);
2898 cleanup:
2899 if (!ret) {
2900 vshCommandFree(partial);
2901 partial = NULL;
2902 virStringListFree(list);
2903 list = NULL;
2904 list_index = 0;
2907 return ret;
2911 static char **
2912 vshReadlineCompletion(const char *text,
2913 int start ATTRIBUTE_UNUSED,
2914 int end ATTRIBUTE_UNUSED)
2916 char **matches = (char **) NULL;
2918 matches = rl_completion_matches(text, vshReadlineParse);
2919 return matches;
2923 static int
2924 vshReadlineCharIsQuoted(char *line, int idx)
2926 return idx > 0 &&
2927 line[idx - 1] == '\\' &&
2928 !vshReadlineCharIsQuoted(line, idx - 1);
2932 # define HISTSIZE_MAX 500000
2934 static int
2935 vshReadlineInit(vshControl *ctl)
2937 char *userdir = NULL;
2938 int max_history = 500;
2939 int ret = -1;
2940 char *histsize_env = NULL;
2941 const char *histsize_str = NULL;
2942 const char *break_characters = " \t\n\\`@$><=;|&{(";
2943 const char *quote_characters = "\"'";
2945 /* Opaque data for autocomplete callbacks. */
2946 autoCompleteOpaque = ctl;
2948 rl_readline_name = ctl->name;
2950 /* Tell the completer that we want a crack first. */
2951 rl_attempted_completion_function = vshReadlineCompletion;
2953 rl_basic_word_break_characters = break_characters;
2955 rl_completer_quote_characters = quote_characters;
2956 rl_char_is_quoted_p = vshReadlineCharIsQuoted;
2958 if (virAsprintf(&histsize_env, "%s_HISTSIZE", ctl->env_prefix) < 0)
2959 goto cleanup;
2961 /* Limit the total size of the history buffer */
2962 if ((histsize_str = virGetEnvBlockSUID(histsize_env))) {
2963 if (virStrToLong_i(histsize_str, NULL, 10, &max_history) < 0) {
2964 vshError(ctl, _("Bad $%s value."), histsize_env);
2965 goto cleanup;
2966 } else if (max_history > HISTSIZE_MAX || max_history < 0) {
2967 vshError(ctl, _("$%s value should be between 0 "
2968 "and %d"),
2969 histsize_env, HISTSIZE_MAX);
2970 goto cleanup;
2973 stifle_history(max_history);
2975 /* Prepare to read/write history from/to the
2976 * $XDG_CACHE_HOME/virtshell/history file
2978 userdir = virGetUserCacheDirectory();
2980 if (userdir == NULL) {
2981 vshError(ctl, "%s", _("Could not determine home directory"));
2982 goto cleanup;
2985 if (virAsprintf(&ctl->historydir, "%s/%s", userdir, ctl->name) < 0) {
2986 vshError(ctl, "%s", _("Out of memory"));
2987 goto cleanup;
2990 if (virAsprintf(&ctl->historyfile, "%s/history", ctl->historydir) < 0) {
2991 vshError(ctl, "%s", _("Out of memory"));
2992 goto cleanup;
2995 read_history(ctl->historyfile);
2996 ret = 0;
2998 cleanup:
2999 VIR_FREE(userdir);
3000 VIR_FREE(histsize_env);
3001 return ret;
3004 static void
3005 vshReadlineDeinit(vshControl *ctl)
3007 if (ctl->historyfile != NULL) {
3008 if (virFileMakePathWithMode(ctl->historydir, 0755) < 0 &&
3009 errno != EEXIST) {
3010 char ebuf[1024];
3011 vshError(ctl, _("Failed to create '%s': %s"),
3012 ctl->historydir, virStrerror(errno, ebuf, sizeof(ebuf)));
3013 } else {
3014 write_history(ctl->historyfile);
3018 VIR_FREE(ctl->historydir);
3019 VIR_FREE(ctl->historyfile);
3022 char *
3023 vshReadline(vshControl *ctl ATTRIBUTE_UNUSED, const char *prompt)
3025 return readline(prompt);
3028 #else /* !WITH_READLINE */
3030 static int
3031 vshReadlineInit(vshControl *ctl ATTRIBUTE_UNUSED)
3033 /* empty */
3034 return 0;
3037 static void
3038 vshReadlineDeinit(vshControl *ctl ATTRIBUTE_UNUSED)
3040 /* empty */
3043 char *
3044 vshReadline(vshControl *ctl, const char *prompt)
3046 char line[1024];
3047 char *r;
3048 int len;
3050 fputs(prompt, stdout);
3051 r = fgets(line, sizeof(line), stdin);
3052 if (r == NULL) return NULL; /* EOF */
3054 /* Chomp trailing \n */
3055 len = strlen(r);
3056 if (len > 0 && r[len-1] == '\n')
3057 r[len-1] = '\0';
3059 return vshStrdup(ctl, r);
3062 #endif /* !WITH_READLINE */
3065 * Initialize debug settings.
3067 static int
3068 vshInitDebug(vshControl *ctl)
3070 const char *debugEnv;
3071 char *env = NULL;
3073 if (ctl->debug == VSH_DEBUG_DEFAULT) {
3074 if (virAsprintf(&env, "%s_DEBUG", ctl->env_prefix) < 0)
3075 return -1;
3077 /* log level not set from commandline, check env variable */
3078 debugEnv = virGetEnvAllowSUID(env);
3079 if (debugEnv) {
3080 int debug;
3081 if (virStrToLong_i(debugEnv, NULL, 10, &debug) < 0 ||
3082 debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR) {
3083 vshError(ctl, _("%s_DEBUG not set with a valid numeric value"),
3084 ctl->env_prefix);
3085 } else {
3086 ctl->debug = debug;
3089 VIR_FREE(env);
3092 if (ctl->logfile == NULL) {
3093 if (virAsprintf(&env, "%s_LOG_FILE", ctl->env_prefix) < 0)
3094 return -1;
3096 /* log file not set from cmdline */
3097 debugEnv = virGetEnvBlockSUID(env);
3098 if (debugEnv && *debugEnv) {
3099 ctl->logfile = vshStrdup(ctl, debugEnv);
3100 vshOpenLogFile(ctl);
3102 VIR_FREE(env);
3105 return 0;
3110 * Initialize global data
3112 bool
3113 vshInit(vshControl *ctl, const vshCmdGrp *groups, const vshCmdDef *set)
3115 if (!ctl->hooks) {
3116 vshError(ctl, "%s", _("client hooks cannot be NULL"));
3117 return false;
3120 if (!groups && !set) {
3121 vshError(ctl, "%s", _("command groups and command set "
3122 "cannot both be NULL"));
3123 return false;
3126 cmdGroups = groups;
3127 cmdSet = set;
3129 if (vshInitDebug(ctl) < 0 ||
3130 (ctl->imode && vshReadlineInit(ctl) < 0))
3131 return false;
3133 return true;
3136 bool
3137 vshInitReload(vshControl *ctl)
3139 if (!cmdGroups && !cmdSet) {
3140 vshError(ctl, "%s", _("command groups and command are both NULL "
3141 "run vshInit before reloading"));
3142 return false;
3145 if (vshInitDebug(ctl) < 0)
3146 return false;
3148 if (ctl->imode)
3149 vshReadlineDeinit(ctl);
3150 if (ctl->imode && vshReadlineInit(ctl) < 0)
3151 return false;
3153 return true;
3156 void
3157 vshDeinit(vshControl *ctl)
3159 /* NB: Don't make calling of vshReadlineDeinit conditional on active
3160 * interactive mode. */
3161 vshReadlineDeinit(ctl);
3162 vshCloseLogFile(ctl);
3165 /* -----------------------------------------------
3166 * Generic commands available to use by any client
3167 * -----------------------------------------------
3169 const vshCmdOptDef opts_help[] = {
3170 {.name = "command",
3171 .type = VSH_OT_STRING,
3172 .help = N_("Prints global help, command specific help, or help for a group of related commands")
3174 {.name = NULL}
3177 const vshCmdInfo info_help[] = {
3178 {.name = "help",
3179 .data = N_("print help")
3181 {.name = "desc",
3182 .data = N_("Prints global help, command specific help, or help for a\n"
3183 " group of related commands")
3185 {.name = NULL}
3188 bool
3189 cmdHelp(vshControl *ctl, const vshCmd *cmd)
3191 const vshCmdDef *def = NULL;
3192 const vshCmdGrp *grp = NULL;
3193 const char *name = NULL;
3195 if (vshCommandOptStringQuiet(ctl, cmd, "command", &name) <= 0) {
3196 vshPrint(ctl, "%s", _("Grouped commands:\n\n"));
3198 for (grp = cmdGroups; grp->name; grp++) {
3199 vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name,
3200 grp->keyword);
3202 for (def = grp->commands; def->name; def++) {
3203 if (def->flags & VSH_CMD_FLAG_ALIAS)
3204 continue;
3205 vshPrint(ctl, " %-30s %s\n", def->name,
3206 _(vshCmddefGetInfo(def, "help")));
3209 vshPrint(ctl, "\n");
3212 return true;
3215 if ((def = vshCmddefSearch(name))) {
3216 if (def->flags & VSH_CMD_FLAG_ALIAS)
3217 def = vshCmddefSearch(def->alias);
3218 return vshCmddefHelp(ctl, def);
3219 } else if ((grp = vshCmdGrpSearch(name))) {
3220 return vshCmdGrpHelp(ctl, grp);
3221 } else {
3222 vshError(ctl, _("command or command group '%s' doesn't exist"), name);
3223 return false;
3227 const vshCmdOptDef opts_cd[] = {
3228 {.name = "dir",
3229 .type = VSH_OT_STRING,
3230 .help = N_("directory to switch to (default: home or else root)")
3232 {.name = NULL}
3235 const vshCmdInfo info_cd[] = {
3236 {.name = "help",
3237 .data = N_("change the current directory")
3239 {.name = "desc",
3240 .data = N_("Change the current directory.")
3242 {.name = NULL}
3245 bool
3246 cmdCd(vshControl *ctl, const vshCmd *cmd)
3248 const char *dir = NULL;
3249 char *dir_malloced = NULL;
3250 bool ret = true;
3251 char ebuf[1024];
3253 if (!ctl->imode) {
3254 vshError(ctl, "%s", _("cd: command valid only in interactive mode"));
3255 return false;
3258 if (vshCommandOptStringQuiet(ctl, cmd, "dir", &dir) <= 0)
3259 dir = dir_malloced = virGetUserDirectory();
3260 if (!dir)
3261 dir = "/";
3263 if (chdir(dir) == -1) {
3264 vshError(ctl, _("cd: %s: %s"),
3265 virStrerror(errno, ebuf, sizeof(ebuf)), dir);
3266 ret = false;
3269 VIR_FREE(dir_malloced);
3270 return ret;
3273 const vshCmdOptDef opts_echo[] = {
3274 {.name = "shell",
3275 .type = VSH_OT_BOOL,
3276 .help = N_("escape for shell use")
3278 {.name = "xml",
3279 .type = VSH_OT_BOOL,
3280 .help = N_("escape for XML use")
3282 {.name = "err",
3283 .type = VSH_OT_BOOL,
3284 .help = N_("output to stderr"),
3286 {.name = "str",
3287 .type = VSH_OT_ALIAS,
3288 .help = "string"
3290 {.name = "hi",
3291 .type = VSH_OT_ALIAS,
3292 .help = "string=hello"
3294 {.name = "string",
3295 .type = VSH_OT_ARGV,
3296 .help = N_("arguments to echo")
3298 {.name = NULL}
3301 const vshCmdInfo info_echo[] = {
3302 {.name = "help",
3303 .data = N_("echo arguments")
3305 {.name = "desc",
3306 .data = N_("Echo back arguments, possibly with quoting.")
3308 {.name = NULL}
3311 /* Exists mainly for debugging virsh, but also handy for adding back
3312 * quotes for later evaluation.
3314 bool
3315 cmdEcho(vshControl *ctl, const vshCmd *cmd)
3317 bool shell = false;
3318 bool xml = false;
3319 bool err = false;
3320 int count = 0;
3321 const vshCmdOpt *opt = NULL;
3322 char *arg;
3323 virBuffer buf = VIR_BUFFER_INITIALIZER;
3325 if (vshCommandOptBool(cmd, "shell"))
3326 shell = true;
3327 if (vshCommandOptBool(cmd, "xml"))
3328 xml = true;
3329 if (vshCommandOptBool(cmd, "err"))
3330 err = true;
3332 while ((opt = vshCommandOptArgv(ctl, cmd, opt))) {
3333 char *str;
3334 virBuffer xmlbuf = VIR_BUFFER_INITIALIZER;
3336 arg = opt->data;
3338 if (count)
3339 virBufferAddChar(&buf, ' ');
3341 if (xml) {
3342 virBufferEscapeString(&xmlbuf, "%s", arg);
3343 if (virBufferError(&xmlbuf)) {
3344 vshError(ctl, "%s", _("Failed to allocate XML buffer"));
3345 return false;
3347 str = virBufferContentAndReset(&xmlbuf);
3348 } else {
3349 str = vshStrdup(ctl, arg);
3352 if (shell)
3353 virBufferEscapeShell(&buf, str);
3354 else
3355 virBufferAdd(&buf, str, -1);
3356 count++;
3357 VIR_FREE(str);
3360 if (virBufferError(&buf)) {
3361 vshError(ctl, "%s", _("Failed to allocate XML buffer"));
3362 return false;
3364 arg = virBufferContentAndReset(&buf);
3365 if (arg) {
3366 if (err)
3367 vshError(ctl, "%s", arg);
3368 else
3369 vshPrint(ctl, "%s", arg);
3371 VIR_FREE(arg);
3372 return true;
3375 const vshCmdInfo info_pwd[] = {
3376 {.name = "help",
3377 .data = N_("print the current directory")
3379 {.name = "desc",
3380 .data = N_("Print the current directory.")
3382 {.name = NULL}
3385 bool
3386 cmdPwd(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
3388 char *cwd;
3389 bool ret = true;
3390 char ebuf[1024];
3392 cwd = getcwd(NULL, 0);
3393 if (!cwd) {
3394 vshError(ctl, _("pwd: cannot get current directory: %s"),
3395 virStrerror(errno, ebuf, sizeof(ebuf)));
3396 ret = false;
3397 } else {
3398 vshPrint(ctl, _("%s\n"), cwd);
3399 VIR_FREE(cwd);
3402 return ret;
3405 const vshCmdInfo info_quit[] = {
3406 {.name = "help",
3407 .data = N_("quit this interactive terminal")
3409 {.name = "desc",
3410 .data = ""
3412 {.name = NULL}
3415 bool
3416 cmdQuit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
3418 ctl->imode = false;
3419 return true;
3422 /* -----------------
3423 * Command self-test
3424 * ----------------- */
3426 const vshCmdInfo info_selftest[] = {
3427 {.name = "help",
3428 .data = N_("internal command for testing virt shells")
3430 {.name = "desc",
3431 .data = N_("internal use only")
3433 {.name = NULL}
3436 /* Prints help for every command.
3437 * That runs vshCmddefOptParse which validates
3438 * the per-command options structure. */
3439 bool
3440 cmdSelfTest(vshControl *ctl,
3441 const vshCmd *cmd ATTRIBUTE_UNUSED)
3443 const vshCmdGrp *grp;
3444 const vshCmdDef *def;
3446 for (grp = cmdGroups; grp->name; grp++) {
3447 for (def = grp->commands; def->name; def++) {
3448 if (vshCmddefCheckInternals(ctl, def) < 0)
3449 return false;
3453 return true;
3456 /* ----------------------
3457 * Autocompletion command
3458 * ---------------------- */
3460 const vshCmdOptDef opts_complete[] = {
3461 {.name = "string",
3462 .type = VSH_OT_ARGV,
3463 .flags = VSH_OFLAG_EMPTY_OK,
3464 .help = N_("partial string to autocomplete")
3466 {.name = NULL}
3469 const vshCmdInfo info_complete[] = {
3470 {.name = "help",
3471 .data = N_("internal command for autocompletion")
3473 {.name = "desc",
3474 .data = N_("internal use only")
3476 {.name = NULL}
3480 #ifdef WITH_READLINE
3481 bool
3482 cmdComplete(vshControl *ctl, const vshCmd *cmd)
3484 bool ret = false;
3485 const vshClientHooks *hooks = ctl->hooks;
3486 int stdin_fileno = STDIN_FILENO;
3487 const char *arg = "";
3488 const vshCmdOpt *opt = NULL;
3489 char **matches = NULL, **iter;
3490 virBuffer buf = VIR_BUFFER_INITIALIZER;
3492 if (vshCommandOptStringQuiet(ctl, cmd, "string", &arg) <= 0)
3493 goto cleanup;
3495 /* This command is flagged VSH_CMD_FLAG_NOCONNECT because we
3496 * need to prevent auth hooks reading any input. Therefore, we
3497 * have to close stdin and then connect ourselves. */
3498 VIR_FORCE_CLOSE(stdin_fileno);
3500 if (!(hooks && hooks->connHandler && hooks->connHandler(ctl)))
3501 goto cleanup;
3503 while ((opt = vshCommandOptArgv(ctl, cmd, opt))) {
3504 if (virBufferUse(&buf) != 0)
3505 virBufferAddChar(&buf, ' ');
3506 virBufferAddStr(&buf, opt->data);
3507 arg = opt->data;
3510 if (virBufferCheckError(&buf) < 0)
3511 goto cleanup;
3513 vshReadlineInit(ctl);
3515 if (!(rl_line_buffer = virBufferContentAndReset(&buf)) &&
3516 VIR_STRDUP(rl_line_buffer, "") < 0)
3517 goto cleanup;
3519 /* rl_point is current cursor position in rl_line_buffer.
3520 * In our case it's at the end of the whole line. */
3521 rl_point = strlen(rl_line_buffer);
3523 if (!(matches = vshReadlineCompletion(arg, 0, 0)))
3524 goto cleanup;
3526 for (iter = matches; *iter; iter++) {
3527 if (iter == matches && matches[1])
3528 continue;
3529 printf("%s\n", *iter);
3532 ret = true;
3533 cleanup:
3534 virBufferFreeAndReset(&buf);
3535 virStringListFree(matches);
3536 return ret;
3540 #else /* !WITH_READLINE */
3543 bool
3544 cmdComplete(vshControl *ctl ATTRIBUTE_UNUSED,
3545 const vshCmd *cmd ATTRIBUTE_UNUSED)
3547 return false;
3549 #endif /* !WITH_READLINE */