virsh.c 82.9 KB
Newer Older
1
/*
2
 * virsh.c: a shell to exercise the libvirt API
3
 *
4
 * Copyright (C) 2005, 2007-2013 Red Hat, Inc.
5
 *
O
Osier Yang 已提交
6 7 8 9 10 11 12 13 14 15 16
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library.  If not, see
O
Osier Yang 已提交
18
 * <http://www.gnu.org/licenses/>.
19 20
 *
 * Daniel Veillard <veillard@redhat.com>
K
Karel Zak 已提交
21
 * Karel Zak <kzak@redhat.com>
K
Karel Zak 已提交
22
 * Daniel P. Berrange <berrange@redhat.com>
23 24
 */

25
#include <config.h>
E
Eric Blake 已提交
26
#include "virsh.h"
27

28
#include <assert.h>
29
#include <stdio.h>
K
Karel Zak 已提交
30 31 32
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
33
#include <unistd.h>
34
#include <errno.h>
K
Karel Zak 已提交
35
#include <getopt.h>
K
Karel Zak 已提交
36
#include <sys/time.h>
J
Jim Meyering 已提交
37
#include "c-ctype.h"
38
#include <fcntl.h>
39
#include <locale.h>
40
#include <time.h>
41
#include <limits.h>
42
#include <sys/stat.h>
43
#include <inttypes.h>
E
Eric Blake 已提交
44
#include <strings.h>
K
Karel Zak 已提交
45

46 47 48
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
49
#include <libxml/xmlsave.h>
50

51
#ifdef HAVE_READLINE_READLINE_H
52 53
# include <readline/readline.h>
# include <readline/history.h>
54
#endif
K
Karel Zak 已提交
55

56
#include "internal.h"
57
#include "virerror.h"
58
#include "base64.h"
59
#include "virbuffer.h"
60
#include "console.h"
61
#include "viralloc.h"
62
#include "virxml.h"
63 64
#include <libvirt/libvirt-qemu.h>
#include <libvirt/libvirt-lxc.h>
E
Eric Blake 已提交
65
#include "virfile.h"
66
#include "configmake.h"
67
#include "virthread.h"
68
#include "vircommand.h"
69
#include "virkeycode.h"
70
#include "virnetdevbandwidth.h"
71
#include "virbitmap.h"
H
Hu Tao 已提交
72
#include "conf/domain_conf.h"
73
#include "virtypedparam.h"
74
#include "virstring.h"
K
Karel Zak 已提交
75

E
Eric Blake 已提交
76
#include "virsh-domain.h"
77
#include "virsh-domain-monitor.h"
E
Eric Blake 已提交
78
#include "virsh-host.h"
E
Eric Blake 已提交
79
#include "virsh-interface.h"
E
Eric Blake 已提交
80
#include "virsh-network.h"
E
Eric Blake 已提交
81
#include "virsh-nodedev.h"
E
Eric Blake 已提交
82
#include "virsh-nwfilter.h"
E
Eric Blake 已提交
83
#include "virsh-pool.h"
E
Eric Blake 已提交
84
#include "virsh-secret.h"
E
Eric Blake 已提交
85
#include "virsh-snapshot.h"
E
Eric Blake 已提交
86
#include "virsh-volume.h"
E
Eric Blake 已提交
87

K
Karel Zak 已提交
88 89
static char *progname;

90
static const vshCmdGrp cmdGroups[];
K
Karel Zak 已提交
91

E
Eric Blake 已提交
92 93
/* Bypass header poison */
#undef strdup
94

E
Eric Blake 已提交
95
void *
E
Eric Blake 已提交
96 97
_vshMalloc(vshControl *ctl, size_t size, const char *filename, int line)
{
E
Eric Blake 已提交
98
    char *x;
E
Eric Blake 已提交
99

E
Eric Blake 已提交
100
    if (VIR_ALLOC_N(x, size) == 0)
E
Eric Blake 已提交
101 102 103 104 105 106
        return x;
    vshError(ctl, _("%s: %d: failed to allocate %d bytes"),
             filename, line, (int) size);
    exit(EXIT_FAILURE);
}

E
Eric Blake 已提交
107 108 109
void *
_vshCalloc(vshControl *ctl, size_t nmemb, size_t size, const char *filename,
           int line)
E
Eric Blake 已提交
110
{
E
Eric Blake 已提交
111
    char *x;
E
Eric Blake 已提交
112

E
Eric Blake 已提交
113 114
    if (!xalloc_oversized(nmemb, size) &&
        VIR_ALLOC_N(x, nmemb * size) == 0)
E
Eric Blake 已提交
115 116 117 118 119 120
        return x;
    vshError(ctl, _("%s: %d: failed to allocate %d bytes"),
             filename, line, (int) (size*nmemb));
    exit(EXIT_FAILURE);
}

E
Eric Blake 已提交
121
char *
E
Eric Blake 已提交
122 123 124 125
_vshStrdup(vshControl *ctl, const char *s, const char *filename, int line)
{
    char *x;

126
    if (VIR_STRDUP(x, s) >= 0)
E
Eric Blake 已提交
127 128 129 130 131 132 133 134
        return x;
    vshError(ctl, _("%s: %d: failed to allocate %lu bytes"),
             filename, line, (unsigned long)strlen(s));
    exit(EXIT_FAILURE);
}

/* Poison the raw allocating identifiers in favor of our vsh variants.  */
#define strdup use_vshStrdup_instead_of_strdup
135

136
int
137 138 139 140
vshNameSorter(const void *a, const void *b)
{
    const char **sa = (const char**)a;
    const char **sb = (const char**)b;
141

142
    return vshStrcasecmp(*sa, *sb);
143 144
}

E
Eric Blake 已提交
145
double
E
Eric Blake 已提交
146
vshPrettyCapacity(unsigned long long val, const char **unit)
E
Eric Blake 已提交
147
{
148
    if (val < 1024) {
149
        *unit = "B";
150 151
        return (double)val;
    } else if (val < (1024.0l * 1024.0l)) {
152
        *unit = "KiB";
153 154
        return (((double)val / 1024.0l));
    } else if (val < (1024.0l * 1024.0l * 1024.0l)) {
155
        *unit = "MiB";
156
        return (double)val / (1024.0l * 1024.0l);
157
    } else if (val < (1024.0l * 1024.0l * 1024.0l * 1024.0l)) {
158
        *unit = "GiB";
159
        return (double)val / (1024.0l * 1024.0l * 1024.0l);
160
    } else {
161
        *unit = "TiB";
162
        return (double)val / (1024.0l * 1024.0l * 1024.0l * 1024.0l);
163 164 165
    }
}

166
/*
167 168 169
 * Convert the strings separated by ',' into array. The returned
 * array is a NULL terminated string list. The caller has to free
 * the array using virStringFreeList or a similar method.
170 171 172 173 174
 *
 * Returns the length of the filled array on success, or -1
 * on error.
 */
int
175
vshStringToArray(const char *str,
176 177
                 char ***array)
{
178
    char *str_copied = vshStrdup(NULL, str);
179
    char *str_tok = NULL;
E
Eric Blake 已提交
180
    char *tmp;
181 182
    unsigned int nstr_tokens = 0;
    char **arr = NULL;
E
Eric Blake 已提交
183
    size_t len = strlen(str_copied);
184

E
Eric Blake 已提交
185 186
    /* tokenize the string from user and save its parts into an array */
    nstr_tokens = 1;
187

E
Eric Blake 已提交
188 189 190 191 192
    /* count the delimiters, recognizing ,, as an escape for a
     * literal comma */
    str_tok = str_copied;
    while ((str_tok = strchr(str_tok, ','))) {
        if (str_tok[1] == ',')
193
            str_tok++;
E
Eric Blake 已提交
194 195 196 197
        else
            nstr_tokens++;
        str_tok++;
    }
198

199 200
    /* reserve the NULL element at the end */
    if (VIR_ALLOC_N(arr, nstr_tokens + 1) < 0) {
E
Eric Blake 已提交
201 202 203
        VIR_FREE(str_copied);
        return -1;
    }
204

E
Eric Blake 已提交
205 206 207 208 209 210 211 212 213 214 215
    /* tokenize the input string, while treating ,, as a literal comma */
    nstr_tokens = 0;
    tmp = str_tok = str_copied;
    while ((tmp = strchr(tmp, ','))) {
        if (tmp[1] == ',') {
            memmove(&tmp[1], &tmp[2], len - (tmp - str_copied) - 2 + 1);
            len--;
            tmp++;
            continue;
        }
        *tmp++ = '\0';
216
        arr[nstr_tokens++] = vshStrdup(NULL, str_tok);
E
Eric Blake 已提交
217
        str_tok = tmp;
218
    }
219
    arr[nstr_tokens++] = vshStrdup(NULL, str_tok);
220 221

    *array = arr;
222
    VIR_FREE(str_copied);
223 224
    return nstr_tokens;
}
225

E
Eric Blake 已提交
226
virErrorPtr last_error;
J
John Levon 已提交
227 228 229 230 231 232 233 234 235 236 237 238 239

/*
 * Quieten libvirt until we're done with the command.
 */
static void
virshErrorHandler(void *unused ATTRIBUTE_UNUSED, virErrorPtr error)
{
    virFreeError(last_error);
    last_error = virSaveLastError();
    if (getenv("VIRSH_DEBUG") != NULL)
        virDefaultErrorFunc(error);
}

240 241 242 243 244 245 246 247 248
/* Store a libvirt error that is from a helper API that doesn't raise errors
 * so it doesn't get overwritten */
void
vshSaveLibvirtError(void)
{
    virFreeError(last_error);
    last_error = virSaveLastError();
}

249 250 251
/*
 * Reset libvirt error on graceful fallback paths
 */
E
Eric Blake 已提交
252
void
253 254 255 256 257 258
vshResetLibvirtError(void)
{
    virFreeError(last_error);
    last_error = NULL;
}

J
John Levon 已提交
259 260 261 262 263 264 265 266
/*
 * Report an error when a command finishes.  This is better than before
 * (when correct operation would report errors), but it has some
 * problems: we lose the smarter formatting of virDefaultErrorFunc(),
 * and it can become harder to debug problems, if errors get reported
 * twice during one command.  This case shouldn't really happen anyway,
 * and it's IMHO a bug that libvirt does that sometimes.
 */
E
Eric Blake 已提交
267
void
E
Eric Blake 已提交
268
vshReportError(vshControl *ctl)
J
John Levon 已提交
269
{
270 271 272 273 274 275 276 277
    if (last_error == NULL) {
        /* Calling directly into libvirt util functions won't trigger the
         * error callback (which sets last_error), so check it ourselves.
         *
         * If the returned error has CODE_OK, this most likely means that
         * no error was ever raised, so just ignore */
        last_error = virSaveLastError();
        if (!last_error || last_error->code == VIR_ERR_OK)
278
            goto out;
279
    }
J
John Levon 已提交
280 281

    if (last_error->code == VIR_ERR_OK) {
282
        vshError(ctl, "%s", _("unknown error"));
J
John Levon 已提交
283 284 285
        goto out;
    }

286
    vshError(ctl, "%s", last_error->message);
J
John Levon 已提交
287 288

out:
289
    vshResetLibvirtError();
J
John Levon 已提交
290 291
}

292 293 294 295 296 297 298 299
/*
 * Detection of disconnections and automatic reconnection support
 */
static int disconnected = 0; /* we may have been disconnected */

/*
 * vshCatchDisconnect:
 *
300 301
 * We get here when the connection was closed.  We can't do much in the
 * handler, just save the fact it was raised.
302
 */
L
Laine Stump 已提交
303
static void
304 305 306 307 308 309
vshCatchDisconnect(virConnectPtr conn ATTRIBUTE_UNUSED,
                   int reason,
                   void *opaque ATTRIBUTE_UNUSED)
{
    if (reason != VIR_CONNECT_CLOSE_REASON_CLIENT)
        disconnected++;
310 311 312 313 314
}

/*
 * vshReconnect:
 *
L
Laine Stump 已提交
315
 * Reconnect after a disconnect from libvirtd
316 317
 *
 */
L
Laine Stump 已提交
318
static void
319 320 321 322
vshReconnect(vshControl *ctl)
{
    bool connected = false;

323 324 325
    if (ctl->conn) {
        int ret;

326
        connected = true;
327 328 329 330 331 332 333 334

        virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect);
        ret = virConnectClose(ctl->conn);
        if (ret < 0)
            vshError(ctl, "%s", _("Failed to disconnect from the hypervisor"));
        else if (ret > 0)
            vshError(ctl, "%s", _("One or more references were leaked after "
                                  "disconnect from the hypervisor"));
335
    }
336 337 338 339

    ctl->conn = virConnectOpenAuth(ctl->name,
                                   virConnectAuthPtrDefault,
                                   ctl->readonly ? VIR_CONNECT_RO : 0);
340
    if (!ctl->conn) {
341 342 343 344
        if (disconnected)
            vshError(ctl, "%s", _("Failed to reconnect to the hypervisor"));
        else
            vshError(ctl, "%s", _("failed to connect to the hypervisor"));
345 346 347 348 349 350 351
    } else {
        if (virConnectRegisterCloseCallback(ctl->conn, vshCatchDisconnect,
                                            NULL, NULL) < 0)
            vshError(ctl, "%s", _("Unable to register disconnect callback"));
        if (connected)
            vshError(ctl, "%s", _("Reconnected to the hypervisor"));
    }
352
    disconnected = 0;
353
    ctl->useGetInfo = false;
354
    ctl->useSnapshotOld = false;
355
}
356

357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392

/*
 * "connect" command
 */
static const vshCmdInfo info_connect[] = {
    {.name = "help",
     .data = N_("(re)connect to hypervisor")
    },
    {.name = "desc",
     .data = N_("Connect to local hypervisor. This is built-in "
                "command after shell start up.")
    },
    {.name = NULL}
};

static const vshCmdOptDef opts_connect[] = {
    {.name = "name",
     .type = VSH_OT_DATA,
     .flags = VSH_OFLAG_EMPTY_OK,
     .help = N_("hypervisor connection URI")
    },
    {.name = "readonly",
     .type = VSH_OT_BOOL,
     .help = N_("read-only connection")
    },
    {.name = NULL}
};

static bool
cmdConnect(vshControl *ctl, const vshCmd *cmd)
{
    bool ro = vshCommandOptBool(cmd, "readonly");
    const char *name = NULL;

    if (ctl->conn) {
        int ret;
393 394 395 396 397 398 399 400

        virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect);
        ret = virConnectClose(ctl->conn);
        if (ret < 0)
            vshError(ctl, "%s", _("Failed to disconnect from the hypervisor"));
        else if (ret > 0)
            vshError(ctl, "%s", _("One or more references were leaked after "
                                  "disconnect from the hypervisor"));
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
        ctl->conn = NULL;
    }

    VIR_FREE(ctl->name);
    if (vshCommandOptStringReq(ctl, cmd, "name", &name) < 0)
        return false;

    ctl->name = vshStrdup(ctl, name);

    ctl->useGetInfo = false;
    ctl->useSnapshotOld = false;
    ctl->readonly = ro;

    ctl->conn = virConnectOpenAuth(ctl->name, virConnectAuthPtrDefault,
                                   ctl->readonly ? VIR_CONNECT_RO : 0);

417
    if (!ctl->conn) {
418
        vshError(ctl, "%s", _("Failed to connect to the hypervisor"));
419 420 421 422 423 424
        return false;
    }

    if (virConnectRegisterCloseCallback(ctl->conn, vshCatchDisconnect,
                                        NULL, NULL) < 0)
        vshError(ctl, "%s", _("Unable to register disconnect callback"));
425

426
    return true;
427 428 429
}


430
#ifndef WIN32
431 432 433 434 435 436 437 438 439 440 441 442 443
static void
vshPrintRaw(vshControl *ctl, ...)
{
    va_list ap;
    char *key;

    va_start(ap, ctl);
    while ((key = va_arg(ap, char *)) != NULL) {
        vshPrint(ctl, "%s\r\n", key);
    }
    va_end(ap);
}

444 445 446 447 448 449 450 451 452 453 454 455 456
/**
 * vshAskReedit:
 * @msg: Question to ask user
 *
 * Ask user if he wants to return to previously
 * edited file.
 *
 * Returns 'y' if he wants to
 *         'f' if he forcibly wants to
 *         'n' if he doesn't want to
 *         -1  on error
 *          0  otherwise
 */
E
Eric Blake 已提交
457
int
458 459 460 461 462 463 464 465
vshAskReedit(vshControl *ctl, const char *msg)
{
    int c = -1;
    struct termios ttyattr;

    if (!isatty(STDIN_FILENO))
        return -1;

E
Eric Blake 已提交
466
    vshReportError(ctl);
467 468 469 470 471 472 473 474 475 476 477

    if (vshMakeStdinRaw(&ttyattr, false) < 0)
        return -1;

    while (true) {
        /* TRANSLATORS: For now, we aren't using LC_MESSAGES, and the user
         * choices really are limited to just 'y', 'n', 'f' and '?'  */
        vshPrint(ctl, "\r%s %s", msg, _("Try again? [y,n,f,?]:"));
        c = c_tolower(getchar());

        if (c == '?') {
478 479 480 481 482 483 484
            vshPrintRaw(ctl,
                        "",
                        _("y - yes, start editor again"),
                        _("n - no, throw away my changes"),
                        _("f - force, try to redefine again"),
                        _("? - print this help"),
                        NULL);
485 486 487 488 489 490 491 492 493 494
            continue;
        } else if (c == 'y' || c == 'n' || c == 'f') {
            break;
        }
    }

    tcsetattr(STDIN_FILENO, TCSAFLUSH, &ttyattr);

    vshPrint(ctl, "\r\n");
    return c;
495 496
}
#else /* WIN32 */
497
int
498 499
vshAskReedit(vshControl *ctl, const char *msg ATTRIBUTE_UNUSED)
{
500 501 502 503
    vshDebug(ctl, VSH_ERR_WARNING, "%s", _("This function is not "
                                           "supported on WIN32 platform"));
    return 0;
}
504
#endif /* WIN32 */
505

E
Eric Blake 已提交
506 507
int vshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED,
                  const char *bytes, size_t nbytes, void *opaque)
508 509 510 511 512 513
{
    int *fd = opaque;

    return safewrite(*fd, bytes, nbytes);
}

K
Karel Zak 已提交
514 515 516 517 518 519
/* ---------------
 * Commands
 * ---------------
 */

/*
520
 * "help" command
K
Karel Zak 已提交
521
 */
522
static const vshCmdInfo info_help[] = {
523 524 525 526 527 528 529 530
    {.name = "help",
     .data = N_("print help")
    },
    {.name = "desc",
     .data = N_("Prints global help, command specific help, or help for a\n"
                "    group of related commands")
    },
    {.name = NULL}
K
Karel Zak 已提交
531 532
};

533
static const vshCmdOptDef opts_help[] = {
534 535 536 537 538
    {.name = "command",
     .type = VSH_OT_DATA,
     .help = N_("Prints global help, command specific help, or help for a group of related commands")
    },
    {.name = NULL}
K
Karel Zak 已提交
539 540
};

E
Eric Blake 已提交
541
static bool
542
cmdHelp(vshControl *ctl, const vshCmd *cmd)
543
 {
544
    const char *name = NULL;
545

546
    if (vshCommandOptString(cmd, "command", &name) <= 0) {
547
        const vshCmdGrp *grp;
548
        const vshCmdDef *def;
549

550 551 552 553 554 555
        vshPrint(ctl, "%s", _("Grouped commands:\n\n"));

        for (grp = cmdGroups; grp->name; grp++) {
            vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name,
                     grp->keyword);

556 557 558
            for (def = grp->commands; def->name; def++) {
                if (def->flags & VSH_CMD_FLAG_ALIAS)
                    continue;
559 560
                vshPrint(ctl, "    %-30s %s\n", def->name,
                         _(vshCmddefGetInfo(def, "help")));
561
            }
562 563 564 565

            vshPrint(ctl, "\n");
        }

E
Eric Blake 已提交
566
        return true;
567
    }
568

E
Eric Blake 已提交
569
    if (vshCmddefSearch(name)) {
570
        return vshCmddefHelp(ctl, name);
E
Eric Blake 已提交
571
    } else if (vshCmdGrpSearch(name)) {
572 573 574
        return vshCmdGrpHelp(ctl, name);
    } else {
        vshError(ctl, _("command or command group '%s' doesn't exist"), name);
E
Eric Blake 已提交
575
        return false;
K
Karel Zak 已提交
576 577 578
    }
}

579 580 581 582 583 584 585 586 587 588 589
/* Tree listing helpers.  */

static int
vshTreePrintInternal(vshControl *ctl,
                     vshTreeLookup lookup,
                     void *opaque,
                     int num_devices,
                     int devid,
                     int lastdev,
                     bool root,
                     virBufferPtr indent)
590
{
591
    size_t i;
592 593 594
    int nextlastdev = -1;
    int ret = -1;
    const char *dev = (lookup)(devid, false, opaque);
595

596
    if (virBufferError(indent))
597 598
        goto cleanup;

599 600 601 602 603 604 605 606 607 608
    /* Print this device, with indent if not at root */
    vshPrint(ctl, "%s%s%s\n", virBufferCurrentContent(indent),
             root ? "" : "+- ", dev);

    /* Update indent to show '|' or ' ' for child devices */
    if (!root) {
        virBufferAddChar(indent, devid == lastdev ? ' ' : '|');
        virBufferAddChar(indent, ' ');
        if (virBufferError(indent))
            goto cleanup;
609 610
    }

611
    /* Determine the index of the last child device */
612
    for (i = 0; i < num_devices; i++) {
613
        const char *parent = (lookup)(i, true, opaque);
614

615 616 617
        if (parent && STREQ(parent, dev))
            nextlastdev = i;
    }
618

619 620 621
    /* If there is a child device, then print another blank line */
    if (nextlastdev != -1)
        vshPrint(ctl, "%s  |\n", virBufferCurrentContent(indent));
622

623 624
    /* Finally print all children */
    virBufferAddLit(indent, "  ");
625 626
    if (virBufferError(indent))
        goto cleanup;
627
    for (i = 0; i < num_devices; i++) {
628
        const char *parent = (lookup)(i, true, opaque);
629

630 631 632 633 634
        if (parent && STREQ(parent, dev) &&
            vshTreePrintInternal(ctl, lookup, opaque,
                                 num_devices, i, nextlastdev,
                                 false, indent) < 0)
            goto cleanup;
635
    }
J
Ján Tomko 已提交
636
    virBufferTrim(indent, "  ", -1);
637

638 639 640 641
    /* If there was no child device, and we're the last in
     * a list of devices, then print another blank line */
    if (nextlastdev == -1 && devid == lastdev)
        vshPrint(ctl, "%s\n", virBufferCurrentContent(indent));
642

J
Ján Tomko 已提交
643 644
    if (!root)
        virBufferTrim(indent, NULL, 2);
645
    ret = 0;
646 647 648 649
cleanup:
    return ret;
}

E
Eric Blake 已提交
650
int
651 652
vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque,
             int num_devices, int devid)
653
{
654 655
    int ret;
    virBuffer indent = VIR_BUFFER_INITIALIZER;
656

657 658 659 660 661
    ret = vshTreePrintInternal(ctl, lookup, opaque, num_devices,
                               devid, devid, true, &indent);
    if (ret < 0)
        vshError(ctl, "%s", _("Failed to complete tree listing"));
    virBufferFreeAndReset(&indent);
662
    return ret;
663
}
664

665
/* Common code for the edit / net-edit / pool-edit functions which follow. */
E
Eric Blake 已提交
666
char *
E
Eric Blake 已提交
667
vshEditWriteToTempFile(vshControl *ctl, const char *doc)
668 669 670 671
{
    char *ret;
    const char *tmpdir;
    int fd;
672
    char ebuf[1024];
673

674
    tmpdir = getenv("TMPDIR");
675
    if (!tmpdir) tmpdir = "/tmp";
676 677 678 679
    if (virAsprintf(&ret, "%s/virshXXXXXX.xml", tmpdir) < 0) {
        vshError(ctl, "%s", _("out of memory"));
        return NULL;
    }
680
    fd = mkostemps(ret, 4, O_CLOEXEC);
681
    if (fd == -1) {
682
        vshError(ctl, _("mkostemps: failed to create temporary file: %s"),
683
                 virStrerror(errno, ebuf, sizeof(ebuf)));
684
        VIR_FREE(ret);
685 686 687
        return NULL;
    }

688
    if (safewrite(fd, doc, strlen(doc)) == -1) {
689
        vshError(ctl, _("write: %s: failed to write to temporary file: %s"),
690
                 ret, virStrerror(errno, ebuf, sizeof(ebuf)));
S
Stefan Berger 已提交
691
        VIR_FORCE_CLOSE(fd);
692
        unlink(ret);
693
        VIR_FREE(ret);
694 695
        return NULL;
    }
S
Stefan Berger 已提交
696
    if (VIR_CLOSE(fd) < 0) {
697
        vshError(ctl, _("close: %s: failed to write or close temporary file: %s"),
698
                 ret, virStrerror(errno, ebuf, sizeof(ebuf)));
699
        unlink(ret);
700
        VIR_FREE(ret);
701 702 703 704 705 706 707 708 709 710 711
        return NULL;
    }

    /* Temporary filename: caller frees. */
    return ret;
}

/* Characters permitted in $EDITOR environment variable and temp filename. */
#define ACCEPTED_CHARS \
  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/_.:@"

E
Eric Blake 已提交
712
int
E
Eric Blake 已提交
713
vshEditFile(vshControl *ctl, const char *filename)
714 715
{
    const char *editor;
E
Eric Blake 已提交
716 717 718 719
    virCommandPtr cmd;
    int ret = -1;
    int outfd = STDOUT_FILENO;
    int errfd = STDERR_FILENO;
720

721
    editor = getenv("VISUAL");
E
Eric Blake 已提交
722
    if (!editor)
723
        editor = getenv("EDITOR");
E
Eric Blake 已提交
724 725
    if (!editor)
        editor = "vi"; /* could be cruel & default to ed(1) here */
726

727 728 729 730 731
    /* Check that filename doesn't contain shell meta-characters, and
     * if it does, refuse to run.  Follow the Unix conventions for
     * EDITOR: the user can intentionally specify command options, so
     * we don't protect any shell metacharacters there.  Lots more
     * than virsh will misbehave if EDITOR has bogus contents (which
E
Eric Blake 已提交
732 733
     * is why sudo scrubs it by default).  Conversely, if the editor
     * is safe, we can run it directly rather than wasting a shell.
734
     */
735 736
    if (strspn(editor, ACCEPTED_CHARS) != strlen(editor)) {
        if (strspn(filename, ACCEPTED_CHARS) != strlen(filename)) {
E
Eric Blake 已提交
737 738 739 740 741 742 743 744 745 746
            vshError(ctl,
                     _("%s: temporary filename contains shell meta or other "
                       "unacceptable characters (is $TMPDIR wrong?)"),
                     filename);
            return -1;
        }
        cmd = virCommandNewArgList("sh", "-c", NULL);
        virCommandAddArgFormat(cmd, "%s %s", editor, filename);
    } else {
        cmd = virCommandNewArgList(editor, filename, NULL);
747 748
    }

E
Eric Blake 已提交
749 750 751 752 753
    virCommandSetInputFD(cmd, STDIN_FILENO);
    virCommandSetOutputFD(cmd, &outfd);
    virCommandSetErrorFD(cmd, &errfd);
    if (virCommandRunAsync(cmd, NULL) < 0 ||
        virCommandWait(cmd, NULL) < 0) {
E
Eric Blake 已提交
754
        vshReportError(ctl);
E
Eric Blake 已提交
755
        goto cleanup;
756
    }
E
Eric Blake 已提交
757
    ret = 0;
758

E
Eric Blake 已提交
759 760 761
cleanup:
    virCommandFree(cmd);
    return ret;
762 763
}

E
Eric Blake 已提交
764
char *
E
Eric Blake 已提交
765
vshEditReadBackFile(vshControl *ctl, const char *filename)
766 767
{
    char *ret;
768
    char ebuf[1024];
769

E
Eric Blake 已提交
770
    if (virFileReadAll(filename, VSH_MAX_XML_FILE, &ret) == -1) {
771
        vshError(ctl,
772
                 _("%s: failed to read temporary file: %s"),
773
                 filename, virStrerror(errno, ebuf, sizeof(ebuf)));
774 775 776 777 778
        return NULL;
    }
    return ret;
}

779

P
Paolo Bonzini 已提交
780 781 782 783
/*
 * "cd" command
 */
static const vshCmdInfo info_cd[] = {
784 785 786 787 788 789 790
    {.name = "help",
     .data = N_("change the current directory")
    },
    {.name = "desc",
     .data = N_("Change the current directory.")
    },
    {.name = NULL}
P
Paolo Bonzini 已提交
791 792 793
};

static const vshCmdOptDef opts_cd[] = {
794 795 796 797 798
    {.name = "dir",
     .type = VSH_OT_DATA,
     .help = N_("directory to switch to (default: home or else root)")
    },
    {.name = NULL}
P
Paolo Bonzini 已提交
799 800
};

E
Eric Blake 已提交
801
static bool
802
cmdCd(vshControl *ctl, const vshCmd *cmd)
P
Paolo Bonzini 已提交
803
{
804
    const char *dir = NULL;
805
    char *dir_malloced = NULL;
E
Eric Blake 已提交
806
    bool ret = true;
807
    char ebuf[1024];
P
Paolo Bonzini 已提交
808 809

    if (!ctl->imode) {
810
        vshError(ctl, "%s", _("cd: command valid only in interactive mode"));
E
Eric Blake 已提交
811
        return false;
P
Paolo Bonzini 已提交
812 813
    }

814
    if (vshCommandOptString(cmd, "dir", &dir) <= 0) {
815
        dir = dir_malloced = virGetUserDirectory();
P
Paolo Bonzini 已提交
816 817 818 819
    }
    if (!dir)
        dir = "/";

P
Phil Petty 已提交
820
    if (chdir(dir) == -1) {
821 822
        vshError(ctl, _("cd: %s: %s"),
                 virStrerror(errno, ebuf, sizeof(ebuf)), dir);
E
Eric Blake 已提交
823
        ret = false;
P
Paolo Bonzini 已提交
824 825
    }

826
    VIR_FREE(dir_malloced);
P
Phil Petty 已提交
827
    return ret;
P
Paolo Bonzini 已提交
828 829 830 831 832 833
}

/*
 * "pwd" command
 */
static const vshCmdInfo info_pwd[] = {
834 835 836 837 838 839 840
    {.name = "help",
     .data = N_("print the current directory")
    },
    {.name = "desc",
     .data = N_("Print the current directory.")
    },
    {.name = NULL}
P
Paolo Bonzini 已提交
841 842
};

E
Eric Blake 已提交
843
static bool
P
Paolo Bonzini 已提交
844 845 846
cmdPwd(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
    char *cwd;
847
    bool ret = true;
848
    char ebuf[1024];
P
Paolo Bonzini 已提交
849

850 851
    cwd = getcwd(NULL, 0);
    if (!cwd) {
852
        vshError(ctl, _("pwd: cannot get current directory: %s"),
853
                 virStrerror(errno, ebuf, sizeof(ebuf)));
854 855
        ret = false;
    } else {
856
        vshPrint(ctl, _("%s\n"), cwd);
857 858
        VIR_FREE(cwd);
    }
P
Paolo Bonzini 已提交
859

860
    return ret;
P
Paolo Bonzini 已提交
861 862
}

E
Eric Blake 已提交
863 864 865 866
/*
 * "echo" command
 */
static const vshCmdInfo info_echo[] = {
867 868 869 870 871 872 873
    {.name = "help",
     .data = N_("echo arguments")
    },
    {.name = "desc",
     .data = N_("Echo back arguments, possibly with quoting.")
    },
    {.name = NULL}
E
Eric Blake 已提交
874 875 876
};

static const vshCmdOptDef opts_echo[] = {
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
    {.name = "shell",
     .type = VSH_OT_BOOL,
     .help = N_("escape for shell use")
    },
    {.name = "xml",
     .type = VSH_OT_BOOL,
     .help = N_("escape for XML use")
    },
    {.name = "str",
     .type = VSH_OT_ALIAS,
     .help = "string"
    },
    {.name = "string",
     .type = VSH_OT_ARGV,
     .help = N_("arguments to echo")
    },
    {.name = NULL}
E
Eric Blake 已提交
894 895 896 897 898
};

/* Exists mainly for debugging virsh, but also handy for adding back
 * quotes for later evaluation.
 */
E
Eric Blake 已提交
899
static bool
900
cmdEcho(vshControl *ctl, const vshCmd *cmd)
E
Eric Blake 已提交
901 902 903 904
{
    bool shell = false;
    bool xml = false;
    int count = 0;
905
    const vshCmdOpt *opt = NULL;
E
Eric Blake 已提交
906 907 908 909 910 911 912 913
    char *arg;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (vshCommandOptBool(cmd, "shell"))
        shell = true;
    if (vshCommandOptBool(cmd, "xml"))
        xml = true;

914
    while ((opt = vshCommandOptArgv(cmd, opt))) {
915 916
        char *str;
        virBuffer xmlbuf = VIR_BUFFER_INITIALIZER;
E
Eric Blake 已提交
917

918
        arg = opt->data;
919

E
Eric Blake 已提交
920 921
        if (count)
            virBufferAddChar(&buf, ' ');
922

E
Eric Blake 已提交
923
        if (xml) {
924 925 926 927
            virBufferEscapeString(&xmlbuf, "%s", arg);
            if (virBufferError(&buf)) {
                vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
                return false;
E
Eric Blake 已提交
928
            }
929 930 931
            str = virBufferContentAndReset(&xmlbuf);
        } else {
            str = vshStrdup(ctl, arg);
E
Eric Blake 已提交
932
        }
933 934 935 936 937

        if (shell)
            virBufferEscapeShell(&buf, str);
        else
            virBufferAdd(&buf, str, -1);
E
Eric Blake 已提交
938
        count++;
939
        VIR_FREE(str);
E
Eric Blake 已提交
940 941 942 943
    }

    if (virBufferError(&buf)) {
        vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
E
Eric Blake 已提交
944
        return false;
E
Eric Blake 已提交
945 946 947 948 949
    }
    arg = virBufferContentAndReset(&buf);
    if (arg)
        vshPrint(ctl, "%s", arg);
    VIR_FREE(arg);
E
Eric Blake 已提交
950
    return true;
E
Eric Blake 已提交
951 952
}

K
Karel Zak 已提交
953 954 955
/*
 * "quit" command
 */
956
static const vshCmdInfo info_quit[] = {
957 958 959 960 961 962 963
    {.name = "help",
     .data = N_("quit this interactive terminal")
    },
    {.name = "desc",
     .data = ""
    },
    {.name = NULL}
K
Karel Zak 已提交
964 965
};

E
Eric Blake 已提交
966
static bool
967
cmdQuit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
968
{
E
Eric Blake 已提交
969 970
    ctl->imode = false;
    return true;
K
Karel Zak 已提交
971 972
}

973 974 975 976
/* ---------------
 * Utils for work with command definition
 * ---------------
 */
E
Eric Blake 已提交
977
const char *
978 979 980
vshCmddefGetInfo(const vshCmdDef * cmd, const char *name)
{
    const vshCmdInfo *info;
981

982 983 984 985 986 987
    for (info = cmd->info; info && info->name; info++) {
        if (STREQ(info->name, name))
            return info->data;
    }
    return NULL;
}
988

989 990 991 992 993
/* Validate that the options associated with cmd can be parsed.  */
static int
vshCmddefOptParse(const vshCmdDef *cmd, uint32_t *opts_need_arg,
                  uint32_t *opts_required)
{
994
    size_t i;
995
    bool optional = false;
996

997 998
    *opts_need_arg = 0;
    *opts_required = 0;
999

1000 1001
    if (!cmd->opts)
        return 0;
1002

1003 1004
    for (i = 0; cmd->opts[i].name; i++) {
        const vshCmdOptDef *opt = &cmd->opts[i];
1005 1006 1007 1008

        if (i > 31)
            return -1; /* too many options */
        if (opt->type == VSH_OT_BOOL) {
E
Eric Blake 已提交
1009
            if (opt->flags & VSH_OFLAG_REQ)
1010 1011 1012
                return -1; /* bool options can't be mandatory */
            continue;
        }
E
Eric Blake 已提交
1013
        if (opt->type == VSH_OT_ALIAS) {
1014
            size_t j;
E
Eric Blake 已提交
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
            if (opt->flags || !opt->help)
                return -1; /* alias options are tracked by the original name */
            for (j = i + 1; cmd->opts[j].name; j++) {
                if (STREQ(opt->help, cmd->opts[j].name))
                    break;
            }
            if (!cmd->opts[j].name)
                return -1; /* alias option must map to a later option name */
            continue;
        }
E
Eric Blake 已提交
1025 1026
        if (opt->flags & VSH_OFLAG_REQ_OPT) {
            if (opt->flags & VSH_OFLAG_REQ)
L
Lai Jiangshan 已提交
1027 1028 1029 1030
                *opts_required |= 1 << i;
            continue;
        }

1031
        *opts_need_arg |= 1 << i;
E
Eric Blake 已提交
1032
        if (opt->flags & VSH_OFLAG_REQ) {
1033 1034 1035 1036 1037 1038
            if (optional)
                return -1; /* mandatory options must be listed first */
            *opts_required |= 1 << i;
        } else {
            optional = true;
        }
1039 1040 1041

        if (opt->type == VSH_OT_ARGV && cmd->opts[i + 1].name)
            return -1; /* argv option must be listed last */
1042 1043 1044 1045
    }
    return 0;
}

1046 1047 1048 1049 1050
static vshCmdOptDef helpopt = {
    .name = "help",
    .type = VSH_OT_BOOL,
    .help = N_("print help for this function")
};
1051
static const vshCmdOptDef *
1052
vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name,
1053
                   uint32_t *opts_seen, int *opt_index)
1054
{
1055
    size_t i;
1056

1057 1058 1059 1060
    if (STREQ(name, helpopt.name)) {
        return &helpopt;
    }

1061 1062
    for (i = 0; cmd->opts && cmd->opts[i].name; i++) {
        const vshCmdOptDef *opt = &cmd->opts[i];
1063

1064
        if (STREQ(opt->name, name)) {
E
Eric Blake 已提交
1065 1066 1067 1068
            if (opt->type == VSH_OT_ALIAS) {
                name = opt->help;
                continue;
            }
1069
            if ((*opts_seen & (1 << i)) && opt->type != VSH_OT_ARGV) {
1070 1071 1072
                vshError(ctl, _("option --%s already seen"), name);
                return NULL;
            }
1073 1074
            *opts_seen |= 1 << i;
            *opt_index = i;
K
Karel Zak 已提交
1075
            return opt;
1076 1077 1078
        }
    }

1079 1080 1081 1082
    if (STRNEQ(cmd->name, "help")) {
        vshError(ctl, _("command '%s' doesn't support option --%s"),
                 cmd->name, name);
    }
K
Karel Zak 已提交
1083 1084 1085
    return NULL;
}

1086
static const vshCmdOptDef *
1087 1088
vshCmddefGetData(const vshCmdDef *cmd, uint32_t *opts_need_arg,
                 uint32_t *opts_seen)
1089
{
1090
    size_t i;
1091
    const vshCmdOptDef *opt;
K
Karel Zak 已提交
1092

1093 1094 1095 1096
    if (!*opts_need_arg)
        return NULL;

    /* Grab least-significant set bit */
E
Eric Blake 已提交
1097
    i = ffs(*opts_need_arg) - 1;
1098
    opt = &cmd->opts[i];
1099
    if (opt->type != VSH_OT_ARGV)
1100
        *opts_need_arg &= ~(1 << i);
1101
    *opts_seen |= 1 << i;
1102
    return opt;
K
Karel Zak 已提交
1103 1104
}

1105 1106 1107
/*
 * Checks for required options
 */
1108
static int
1109 1110
vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd, uint32_t opts_required,
                    uint32_t opts_seen)
1111
{
1112
    const vshCmdDef *def = cmd->def;
1113
    size_t i;
1114 1115 1116 1117 1118 1119 1120 1121

    opts_required &= ~opts_seen;
    if (!opts_required)
        return 0;

    for (i = 0; def->opts[i].name; i++) {
        if (opts_required & (1 << i)) {
            const vshCmdOptDef *opt = &def->opts[i];
1122

1123
            vshError(ctl,
1124
                     opt->type == VSH_OT_DATA || opt->type == VSH_OT_ARGV ?
1125 1126 1127
                     _("command '%s' requires <%s> option") :
                     _("command '%s' requires --%s option"),
                     def->name, opt->name);
1128 1129
        }
    }
1130
    return -1;
1131 1132
}

E
Eric Blake 已提交
1133
const vshCmdDef *
1134 1135
vshCmddefSearch(const char *cmdname)
{
1136
    const vshCmdGrp *g;
1137
    const vshCmdDef *c;
1138

1139 1140
    for (g = cmdGroups; g->name; g++) {
        for (c = g->commands; c->name; c++) {
1141
            if (STREQ(c->name, cmdname))
1142 1143 1144 1145
                return c;
        }
    }

K
Karel Zak 已提交
1146 1147 1148
    return NULL;
}

E
Eric Blake 已提交
1149
const vshCmdGrp *
1150 1151 1152 1153 1154
vshCmdGrpSearch(const char *grpname)
{
    const vshCmdGrp *g;

    for (g = cmdGroups; g->name; g++) {
1155
        if (STREQ(g->name, grpname) || STREQ(g->keyword, grpname))
1156 1157 1158 1159 1160 1161
            return g;
    }

    return NULL;
}

E
Eric Blake 已提交
1162
bool
1163 1164 1165 1166 1167 1168 1169
vshCmdGrpHelp(vshControl *ctl, const char *grpname)
{
    const vshCmdGrp *grp = vshCmdGrpSearch(grpname);
    const vshCmdDef *cmd = NULL;

    if (!grp) {
        vshError(ctl, _("command group '%s' doesn't exist"), grpname);
E
Eric Blake 已提交
1170
        return false;
1171 1172 1173 1174 1175
    } else {
        vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name,
                 grp->keyword);

        for (cmd = grp->commands; cmd->name; cmd++) {
1176 1177
            if (cmd->flags & VSH_CMD_FLAG_ALIAS)
                continue;
1178 1179 1180 1181 1182
            vshPrint(ctl, "    %-30s %s\n", cmd->name,
                     _(vshCmddefGetInfo(cmd, "help")));
        }
    }

E
Eric Blake 已提交
1183
    return true;
1184 1185
}

E
Eric Blake 已提交
1186
bool
1187
vshCmddefHelp(vshControl *ctl, const char *cmdname)
1188
{
1189
    const vshCmdDef *def = vshCmddefSearch(cmdname);
1190

K
Karel Zak 已提交
1191
    if (!def) {
1192
        vshError(ctl, _("command '%s' doesn't exist"), cmdname);
E
Eric Blake 已提交
1193
        return false;
1194
    } else {
E
Eric Blake 已提交
1195 1196
        /* Don't translate desc if it is "".  */
        const char *desc = vshCmddefGetInfo(def, "desc");
E
Eric Blake 已提交
1197
        const char *help = _(vshCmddefGetInfo(def, "help"));
1198
        char buf[256];
1199 1200
        uint32_t opts_need_arg;
        uint32_t opts_required;
1201
        bool shortopt = false; /* true if 'arg' works instead of '--opt arg' */
1202 1203 1204 1205

        if (vshCmddefOptParse(def, &opts_need_arg, &opts_required)) {
            vshError(ctl, _("internal error: bad options in command: '%s'"),
                     def->name);
E
Eric Blake 已提交
1206
            return false;
1207
        }
K
Karel Zak 已提交
1208

1209
        fputs(_("  NAME\n"), stdout);
1210 1211
        fprintf(stdout, "    %s - %s\n", def->name, help);

1212 1213 1214 1215 1216
        fputs(_("\n  SYNOPSIS\n"), stdout);
        fprintf(stdout, "    %s", def->name);
        if (def->opts) {
            const vshCmdOptDef *opt;
            for (opt = def->opts; opt->name; opt++) {
1217
                const char *fmt = "%s";
1218 1219
                switch (opt->type) {
                case VSH_OT_BOOL:
1220
                    fmt = "[--%s]";
1221 1222
                    break;
                case VSH_OT_INT:
E
Eric Blake 已提交
1223
                    /* xgettext:c-format */
E
Eric Blake 已提交
1224
                    fmt = ((opt->flags & VSH_OFLAG_REQ) ? "<%s>"
1225
                           : _("[--%s <number>]"));
1226 1227
                    if (!(opt->flags & VSH_OFLAG_REQ_OPT))
                        shortopt = true;
1228 1229
                    break;
                case VSH_OT_STRING:
E
Eric Blake 已提交
1230 1231
                    /* xgettext:c-format */
                    fmt = _("[--%s <string>]");
1232 1233
                    if (!(opt->flags & VSH_OFLAG_REQ_OPT))
                        shortopt = true;
1234 1235
                    break;
                case VSH_OT_DATA:
E
Eric Blake 已提交
1236
                    fmt = ((opt->flags & VSH_OFLAG_REQ) ? "<%s>" : "[<%s>]");
1237 1238
                    if (!(opt->flags & VSH_OFLAG_REQ_OPT))
                        shortopt = true;
1239 1240 1241
                    break;
                case VSH_OT_ARGV:
                    /* xgettext:c-format */
1242 1243 1244 1245 1246 1247 1248 1249
                    if (shortopt) {
                        fmt = (opt->flags & VSH_OFLAG_REQ)
                            ? _("{[--%s] <string>}...")
                            : _("[[--%s] <string>]...");
                    } else {
                        fmt = (opt->flags & VSH_OFLAG_REQ) ? _("<%s>...")
                            : _("[<%s>]...");
                    }
1250
                    break;
E
Eric Blake 已提交
1251 1252 1253
                case VSH_OT_ALIAS:
                    /* aliases are intentionally undocumented */
                    continue;
1254
                }
1255
                fputc(' ', stdout);
E
Eric Blake 已提交
1256
                fprintf(stdout, fmt, opt->name);
1257
            }
K
Karel Zak 已提交
1258
        }
1259 1260 1261
        fputc('\n', stdout);

        if (desc[0]) {
1262
            /* Print the description only if it's not empty.  */
1263
            fputs(_("\n  DESCRIPTION\n"), stdout);
E
Eric Blake 已提交
1264
            fprintf(stdout, "    %s\n", _(desc));
K
Karel Zak 已提交
1265
        }
1266

1267
        if (def->opts && def->opts->name) {
1268
            const vshCmdOptDef *opt;
1269
            fputs(_("\n  OPTIONS\n"), stdout);
1270
            for (opt = def->opts; opt->name; opt++) {
1271 1272
                switch (opt->type) {
                case VSH_OT_BOOL:
K
Karel Zak 已提交
1273
                    snprintf(buf, sizeof(buf), "--%s", opt->name);
1274 1275
                    break;
                case VSH_OT_INT:
1276
                    snprintf(buf, sizeof(buf),
E
Eric Blake 已提交
1277
                             (opt->flags & VSH_OFLAG_REQ) ? _("[--%s] <number>")
1278
                             : _("--%s <number>"), opt->name);
1279 1280
                    break;
                case VSH_OT_STRING:
1281
                    /* OT_STRING should never be VSH_OFLAG_REQ */
1282
                    snprintf(buf, sizeof(buf), _("--%s <string>"), opt->name);
1283 1284
                    break;
                case VSH_OT_DATA:
1285 1286
                    snprintf(buf, sizeof(buf), _("[--%s] <string>"),
                             opt->name);
1287 1288
                    break;
                case VSH_OT_ARGV:
1289 1290 1291
                    snprintf(buf, sizeof(buf),
                             shortopt ? _("[--%s] <string>") : _("<%s>"),
                             opt->name);
1292
                    break;
E
Eric Blake 已提交
1293 1294
                case VSH_OT_ALIAS:
                    continue;
1295
                }
1296

E
Eric Blake 已提交
1297
                fprintf(stdout, "    %-15s  %s\n", buf, _(opt->help));
1298
            }
K
Karel Zak 已提交
1299 1300 1301
        }
        fputc('\n', stdout);
    }
E
Eric Blake 已提交
1302
    return true;
K
Karel Zak 已提交
1303 1304 1305 1306 1307 1308
}

/* ---------------
 * Utils for work with runtime commands data
 * ---------------
 */
1309 1310 1311
static void
vshCommandOptFree(vshCmdOpt * arg)
{
K
Karel Zak 已提交
1312 1313
    vshCmdOpt *a = arg;

1314
    while (a) {
K
Karel Zak 已提交
1315
        vshCmdOpt *tmp = a;
1316

K
Karel Zak 已提交
1317 1318
        a = a->next;

1319 1320
        VIR_FREE(tmp->data);
        VIR_FREE(tmp);
K
Karel Zak 已提交
1321 1322 1323 1324
    }
}

static void
1325
vshCommandFree(vshCmd *cmd)
1326
{
K
Karel Zak 已提交
1327 1328
    vshCmd *c = cmd;

1329
    while (c) {
K
Karel Zak 已提交
1330
        vshCmd *tmp = c;
1331

K
Karel Zak 已提交
1332 1333 1334 1335
        c = c->next;

        if (tmp->opts)
            vshCommandOptFree(tmp->opts);
1336
        VIR_FREE(tmp);
K
Karel Zak 已提交
1337 1338 1339
    }
}

E
Eric Blake 已提交
1340 1341 1342 1343 1344
/**
 * vshCommandOpt:
 * @cmd: parsed command line to search
 * @name: option name to search for
 * @opt: result of the search
1345
 * @needData: true if option must be non-boolean
E
Eric Blake 已提交
1346 1347 1348 1349
 *
 * Look up an option passed to CMD by NAME.  Returns 1 with *OPT set
 * to the option if found, 0 with *OPT set to NULL if the name is
 * valid and the option is not required, -1 with *OPT set to NULL if
1350 1351 1352
 * the option is required but not present, and assert if NAME is not
 * valid (which indicates a programming error).  No error messages are
 * issued if a value is returned.
K
Karel Zak 已提交
1353
 */
1354 1355 1356
static int
vshCommandOpt(const vshCmd *cmd, const char *name, vshCmdOpt **opt,
              bool needData)
1357
{
E
Eric Blake 已提交
1358 1359
    vshCmdOpt *candidate = cmd->opts;
    const vshCmdOptDef *valid = cmd->def->opts;
1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372
    int ret = 0;

    /* See if option is valid and/or required.  */
    *opt = NULL;
    while (valid) {
        assert(valid->name);
        if (STREQ(name, valid->name))
            break;
        valid++;
    }
    assert(!needData || valid->type != VSH_OT_BOOL);
    if (valid->flags & VSH_OFLAG_REQ)
        ret = -1;
1373

E
Eric Blake 已提交
1374 1375 1376 1377
    /* See if option is present on command line.  */
    while (candidate) {
        if (STREQ(candidate->def->name, name)) {
            *opt = candidate;
1378 1379
            ret = 1;
            break;
E
Eric Blake 已提交
1380 1381
        }
        candidate = candidate->next;
K
Karel Zak 已提交
1382
    }
1383
    return ret;
K
Karel Zak 已提交
1384 1385
}

E
Eric Blake 已提交
1386 1387
/**
 * vshCommandOptInt:
1388 1389 1390 1391 1392 1393 1394
 * @cmd command reference
 * @name option name
 * @value result
 *
 * Convert option to int
 * Return value:
 * >0 if option found and valid (@value updated)
E
Eric Blake 已提交
1395
 * 0 if option not found and not required (@value untouched)
1396
 * <0 in all other cases (@value untouched)
K
Karel Zak 已提交
1397
 */
E
Eric Blake 已提交
1398
int
1399
vshCommandOptInt(const vshCmd *cmd, const char *name, int *value)
1400
{
E
Eric Blake 已提交
1401 1402
    vshCmdOpt *arg;
    int ret;
1403

1404
    ret = vshCommandOpt(cmd, name, &arg, true);
E
Eric Blake 已提交
1405 1406 1407
    if (ret <= 0)
        return ret;

E
Eric Blake 已提交
1408 1409 1410
    if (virStrToLong_i(arg->data, NULL, 10, value) < 0)
        return -1;
    return 1;
K
Karel Zak 已提交
1411 1412
}

1413

E
Eric Blake 已提交
1414 1415 1416 1417 1418 1419
/**
 * vshCommandOptUInt:
 * @cmd command reference
 * @name option name
 * @value result
 *
1420 1421 1422
 * Convert option to unsigned int
 * See vshCommandOptInt()
 */
E
Eric Blake 已提交
1423
int
1424 1425
vshCommandOptUInt(const vshCmd *cmd, const char *name, unsigned int *value)
{
E
Eric Blake 已提交
1426 1427
    vshCmdOpt *arg;
    int ret;
1428

1429
    ret = vshCommandOpt(cmd, name, &arg, true);
E
Eric Blake 已提交
1430 1431 1432
    if (ret <= 0)
        return ret;

E
Eric Blake 已提交
1433 1434 1435
    if (virStrToLong_ui(arg->data, NULL, 10, value) < 0)
        return -1;
    return 1;
1436 1437 1438
}


1439
/*
E
Eric Blake 已提交
1440 1441 1442 1443 1444
 * vshCommandOptUL:
 * @cmd command reference
 * @name option name
 * @value result
 *
1445 1446 1447
 * Convert option to unsigned long
 * See vshCommandOptInt()
 */
E
Eric Blake 已提交
1448
int
1449
vshCommandOptUL(const vshCmd *cmd, const char *name, unsigned long *value)
1450
{
E
Eric Blake 已提交
1451 1452
    vshCmdOpt *arg;
    int ret;
1453

1454
    ret = vshCommandOpt(cmd, name, &arg, true);
E
Eric Blake 已提交
1455 1456 1457
    if (ret <= 0)
        return ret;

E
Eric Blake 已提交
1458 1459 1460
    if (virStrToLong_ul(arg->data, NULL, 10, value) < 0)
        return -1;
    return 1;
1461 1462
}

E
Eric Blake 已提交
1463 1464 1465 1466 1467 1468
/**
 * vshCommandOptString:
 * @cmd command reference
 * @name option name
 * @value result
 *
K
Karel Zak 已提交
1469
 * Returns option as STRING
E
Eric Blake 已提交
1470 1471 1472 1473
 * Return value:
 * >0 if option found and valid (@value updated)
 * 0 if option not found and not required (@value untouched)
 * <0 in all other cases (@value untouched)
K
Karel Zak 已提交
1474
 */
E
Eric Blake 已提交
1475
int
1476
vshCommandOptString(const vshCmd *cmd, const char *name, const char **value)
1477
{
E
Eric Blake 已提交
1478 1479 1480
    vshCmdOpt *arg;
    int ret;

1481
    ret = vshCommandOpt(cmd, name, &arg, true);
E
Eric Blake 已提交
1482 1483
    if (ret <= 0)
        return ret;
1484

E
Eric Blake 已提交
1485
    if (!*arg->data && !(arg->def->flags & VSH_OFLAG_EMPTY_OK)) {
E
Eric Blake 已提交
1486 1487 1488 1489
        return -1;
    }
    *value = arg->data;
    return 1;
K
Karel Zak 已提交
1490 1491
}

1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517
/**
 * vshCommandOptStringReq:
 * @ctl virsh control structure
 * @cmd command structure
 * @name option name
 * @value result (updated to NULL or the option argument)
 *
 * Gets a option argument as string.
 *
 * Returns 0 on success or when the option is not present and not
 * required, *value is set to the option argument. On error -1 is
 * returned and error message printed.
 */
int
vshCommandOptStringReq(vshControl *ctl,
                       const vshCmd *cmd,
                       const char *name,
                       const char **value)
{
    vshCmdOpt *arg;
    int ret;
    const char *error = NULL;

    /* clear out the value */
    *value = NULL;

1518
    ret = vshCommandOpt(cmd, name, &arg, true);
1519 1520 1521 1522 1523 1524
    /* option is not required and not present */
    if (ret == 0)
        return 0;
    /* this should not be propagated here, just to be sure */
    if (ret == -1)
        error = N_("Mandatory option not present");
1525
    else if (!*arg->data && !(arg->def->flags & VSH_OFLAG_EMPTY_OK))
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536
        error = N_("Option argument is empty");

    if (error) {
        vshError(ctl, _("Failed to get option '%s': %s"), name, _(error));
        return -1;
    }

    *value = arg->data;
    return 0;
}

E
Eric Blake 已提交
1537 1538 1539 1540 1541 1542
/**
 * vshCommandOptLongLong:
 * @cmd command reference
 * @name option name
 * @value result
 *
1543
 * Returns option as long long
1544
 * See vshCommandOptInt()
1545
 */
E
Eric Blake 已提交
1546
int
1547 1548
vshCommandOptLongLong(const vshCmd *cmd, const char *name,
                      long long *value)
1549
{
E
Eric Blake 已提交
1550 1551
    vshCmdOpt *arg;
    int ret;
1552

1553
    ret = vshCommandOpt(cmd, name, &arg, true);
E
Eric Blake 已提交
1554 1555 1556
    if (ret <= 0)
        return ret;

E
Eric Blake 已提交
1557 1558 1559
    if (virStrToLong_ll(arg->data, NULL, 10, value) < 0)
        return -1;
    return 1;
1560 1561
}

E
Eric Blake 已提交
1562 1563 1564 1565 1566 1567 1568 1569 1570
/**
 * vshCommandOptULongLong:
 * @cmd command reference
 * @name option name
 * @value result
 *
 * Returns option as long long
 * See vshCommandOptInt()
 */
E
Eric Blake 已提交
1571
int
1572 1573 1574
vshCommandOptULongLong(const vshCmd *cmd, const char *name,
                       unsigned long long *value)
{
E
Eric Blake 已提交
1575 1576
    vshCmdOpt *arg;
    int ret;
1577

1578
    ret = vshCommandOpt(cmd, name, &arg, true);
E
Eric Blake 已提交
1579 1580 1581
    if (ret <= 0)
        return ret;

E
Eric Blake 已提交
1582 1583 1584
    if (virStrToLong_ull(arg->data, NULL, 10, value) < 0)
        return -1;
    return 1;
1585 1586 1587
}


E
Eric Blake 已提交
1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598
/**
 * vshCommandOptScaledInt:
 * @cmd command reference
 * @name option name
 * @value result
 * @scale default of 1 or 1024, if no suffix is present
 * @max maximum value permitted
 *
 * Returns option as long long, scaled according to suffix
 * See vshCommandOptInt()
 */
E
Eric Blake 已提交
1599
int
E
Eric Blake 已提交
1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617
vshCommandOptScaledInt(const vshCmd *cmd, const char *name,
                       unsigned long long *value, int scale,
                       unsigned long long max)
{
    const char *str;
    int ret;
    char *end;

    ret = vshCommandOptString(cmd, name, &str);
    if (ret <= 0)
        return ret;
    if (virStrToLong_ull(str, &end, 10, value) < 0 ||
        virScaleInteger(value, end, scale, max) < 0)
        return -1;
    return 1;
}


E
Eric Blake 已提交
1618 1619 1620 1621 1622 1623 1624 1625 1626
/**
 * vshCommandOptBool:
 * @cmd command reference
 * @name option name
 *
 * Returns true/false if the option exists.  Note that this does NOT
 * validate whether the option is actually boolean, or even whether
 * name is legal; so that this can be used to probe whether a data
 * option is present without actually using that data.
K
Karel Zak 已提交
1627
 */
E
Eric Blake 已提交
1628
bool
1629
vshCommandOptBool(const vshCmd *cmd, const char *name)
1630
{
E
Eric Blake 已提交
1631 1632
    vshCmdOpt *dummy;

1633
    return vshCommandOpt(cmd, name, &dummy, false) == 1;
K
Karel Zak 已提交
1634 1635
}

E
Eric Blake 已提交
1636 1637 1638 1639 1640
/**
 * vshCommandOptArgv:
 * @cmd command reference
 * @opt starting point for the search
 *
1641 1642
 * Returns the next argv argument after OPT (or the first one if OPT
 * is NULL), or NULL if no more are present.
1643
 *
1644
 * Requires that a VSH_OT_ARGV option be last in the
1645 1646
 * list of supported options in CMD->def->opts.
 */
E
Eric Blake 已提交
1647
const vshCmdOpt *
1648
vshCommandOptArgv(const vshCmd *cmd, const vshCmdOpt *opt)
1649
{
1650
    opt = opt ? opt->next : cmd->opts;
1651 1652

    while (opt) {
E
Eric Blake 已提交
1653
        if (opt->def->type == VSH_OT_ARGV) {
1654
            return opt;
1655 1656 1657 1658 1659 1660
        }
        opt = opt->next;
    }
    return NULL;
}

J
Jim Meyering 已提交
1661 1662 1663
/* Determine whether CMD->opts includes an option with name OPTNAME.
   If not, give a diagnostic and return false.
   If so, return true.  */
1664 1665
bool
vshCmdHasOption(vshControl *ctl, const vshCmd *cmd, const char *optname)
J
Jim Meyering 已提交
1666 1667 1668 1669 1670 1671
{
    /* Iterate through cmd->opts, to ensure that there is an entry
       with name OPTNAME and type VSH_OT_DATA. */
    bool found = false;
    const vshCmdOpt *opt;
    for (opt = cmd->opts; opt; opt = opt->next) {
1672
        if (STREQ(opt->def->name, optname) && opt->def->type == VSH_OT_DATA) {
J
Jim Meyering 已提交
1673 1674 1675 1676 1677 1678
            found = true;
            break;
        }
    }

    if (!found)
1679
        vshError(ctl, _("internal error: virsh %s: no %s VSH_OT_DATA option"),
J
Jim Meyering 已提交
1680 1681 1682
                 cmd->def->name, optname);
    return found;
}
1683

1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700
static bool
vshConnectionUsability(vshControl *ctl, virConnectPtr conn)
{
    if (!conn ||
        virConnectIsAlive(conn) == 0) {
        vshError(ctl, "%s", _("no valid connection"));
        return false;
    }

    /* The connection is considered dead only if
     * virConnectIsAlive() successfuly says so.
     */
    vshResetLibvirtError();

    return true;
}

K
Karel Zak 已提交
1701 1702 1703
/*
 * Executes command(s) and returns return code from last command
 */
E
Eric Blake 已提交
1704
static bool
1705
vshCommandRun(vshControl *ctl, const vshCmd *cmd)
1706
{
E
Eric Blake 已提交
1707
    bool ret = true;
1708 1709

    while (cmd) {
K
Karel Zak 已提交
1710
        struct timeval before, after;
1711
        bool enable_timing = ctl->timing;
1712

1713 1714
        if ((ctl->conn == NULL || disconnected) &&
            !(cmd->def->flags & VSH_CMD_FLAG_NOCONNECT))
1715 1716
            vshReconnect(ctl);

1717 1718 1719
        if (enable_timing)
            GETTIMEOFDAY(&before);

1720 1721 1722 1723 1724 1725 1726
        if ((cmd->def->flags & VSH_CMD_FLAG_NOCONNECT) ||
            vshConnectionUsability(ctl, ctl->conn)) {
            ret = cmd->def->handler(ctl, cmd);
        } else {
            /* connection is not usable, return error */
            ret = false;
        }
1727

1728 1729 1730
        if (enable_timing)
            GETTIMEOFDAY(&after);

1731 1732 1733 1734 1735 1736 1737 1738 1739 1740
        /* try to automatically catch disconnections */
        if (!ret &&
            ((last_error != NULL) &&
             (((last_error->code == VIR_ERR_SYSTEM_ERROR) &&
               (last_error->domain == VIR_FROM_REMOTE)) ||
              (last_error->code == VIR_ERR_RPC) ||
              (last_error->code == VIR_ERR_NO_CONNECT) ||
              (last_error->code == VIR_ERR_INVALID_CONN))))
            disconnected++;

1741
        if (!ret)
E
Eric Blake 已提交
1742
            vshReportError(ctl);
J
John Levon 已提交
1743

1744
        if (!ret && disconnected != 0)
1745 1746
            vshReconnect(ctl);

1747
        if (STREQ(cmd->def->name, "quit"))        /* hack ... */
K
Karel Zak 已提交
1748 1749
            return ret;

E
Eric Blake 已提交
1750
        if (enable_timing) {
1751
            double diff_ms = (((after.tv_sec - before.tv_sec) * 1000.0) +
E
Eric Blake 已提交
1752 1753 1754 1755
                              ((after.tv_usec - before.tv_usec) / 1000.0));

            vshPrint(ctl, _("\n(Time: %.3f ms)\n\n"), diff_ms);
        } else {
K
Karel Zak 已提交
1756
            vshPrintExtra(ctl, "\n");
E
Eric Blake 已提交
1757
        }
K
Karel Zak 已提交
1758 1759 1760 1761 1762 1763
        cmd = cmd->next;
    }
    return ret;
}

/* ---------------
1764
 * Command parsing
K
Karel Zak 已提交
1765 1766 1767
 * ---------------
 */

1768 1769 1770 1771 1772 1773 1774
typedef enum {
    VSH_TK_ERROR, /* Failed to parse a token */
    VSH_TK_ARG, /* Arbitrary argument, might be option or empty */
    VSH_TK_SUBCMD_END, /* Separation between commands */
    VSH_TK_END /* No more commands */
} vshCommandToken;

E
Eric Blake 已提交
1775 1776 1777 1778
typedef struct _vshCommandParser vshCommandParser;
struct _vshCommandParser {
    vshCommandToken(*getNextArg)(vshControl *, vshCommandParser *,
                                 char **);
L
Lai Jiangshan 已提交
1779
    /* vshCommandStringGetArg() */
1780
    char *pos;
L
Lai Jiangshan 已提交
1781 1782 1783
    /* vshCommandArgvGetArg() */
    char **arg_pos;
    char **arg_end;
E
Eric Blake 已提交
1784
};
1785

E
Eric Blake 已提交
1786
static bool
1787
vshCommandParse(vshControl *ctl, vshCommandParser *parser)
1788
{
K
Karel Zak 已提交
1789 1790 1791
    char *tkdata = NULL;
    vshCmd *clast = NULL;
    vshCmdOpt *first = NULL;
1792

K
Karel Zak 已提交
1793 1794 1795 1796
    if (ctl->cmd) {
        vshCommandFree(ctl->cmd);
        ctl->cmd = NULL;
    }
1797

1798
    while (1) {
K
Karel Zak 已提交
1799
        vshCmdOpt *last = NULL;
1800
        const vshCmdDef *cmd = NULL;
1801
        vshCommandToken tk;
L
Lai Jiangshan 已提交
1802
        bool data_only = false;
1803 1804 1805
        uint32_t opts_need_arg = 0;
        uint32_t opts_required = 0;
        uint32_t opts_seen = 0;
1806

K
Karel Zak 已提交
1807
        first = NULL;
1808

1809
        while (1) {
1810
            const vshCmdOptDef *opt = NULL;
1811

K
Karel Zak 已提交
1812
            tkdata = NULL;
1813
            tk = parser->getNextArg(ctl, parser, &tkdata);
1814 1815

            if (tk == VSH_TK_ERROR)
K
Karel Zak 已提交
1816
                goto syntaxError;
H
Hu Tao 已提交
1817 1818
            if (tk != VSH_TK_ARG) {
                VIR_FREE(tkdata);
1819
                break;
H
Hu Tao 已提交
1820
            }
1821 1822

            if (cmd == NULL) {
K
Karel Zak 已提交
1823 1824
                /* first token must be command name */
                if (!(cmd = vshCmddefSearch(tkdata))) {
1825
                    vshError(ctl, _("unknown command: '%s'"), tkdata);
1826
                    goto syntaxError;   /* ... or ignore this command only? */
K
Karel Zak 已提交
1827
                }
1828 1829 1830 1831 1832 1833 1834
                if (vshCmddefOptParse(cmd, &opts_need_arg,
                                      &opts_required) < 0) {
                    vshError(ctl,
                             _("internal error: bad options in command: '%s'"),
                             tkdata);
                    goto syntaxError;
                }
1835
                VIR_FREE(tkdata);
L
Lai Jiangshan 已提交
1836 1837 1838 1839
            } else if (data_only) {
                goto get_data;
            } else if (tkdata[0] == '-' && tkdata[1] == '-' &&
                       c_isalnum(tkdata[2])) {
1840
                char *optstr = strchr(tkdata + 2, '=');
C
Cole Robinson 已提交
1841
                int opt_index = 0;
1842

1843 1844 1845 1846
                if (optstr) {
                    *optstr = '\0'; /* convert the '=' to '\0' */
                    optstr = vshStrdup(ctl, optstr + 1);
                }
1847
                /* Special case 'help' to ignore all spurious options */
1848
                if (!(opt = vshCmddefGetOption(ctl, cmd, tkdata + 2,
1849
                                               &opts_seen, &opt_index))) {
1850
                    VIR_FREE(optstr);
1851 1852
                    if (STREQ(cmd->name, "help"))
                        continue;
K
Karel Zak 已提交
1853 1854
                    goto syntaxError;
                }
1855
                VIR_FREE(tkdata);
K
Karel Zak 已提交
1856 1857 1858

                if (opt->type != VSH_OT_BOOL) {
                    /* option data */
1859 1860 1861
                    if (optstr)
                        tkdata = optstr;
                    else
1862
                        tk = parser->getNextArg(ctl, parser, &tkdata);
1863
                    if (tk == VSH_TK_ERROR)
K
Karel Zak 已提交
1864
                        goto syntaxError;
1865
                    if (tk != VSH_TK_ARG) {
1866
                        vshError(ctl,
1867
                                 _("expected syntax: --%s <%s>"),
1868 1869
                                 opt->name,
                                 opt->type ==
1870
                                 VSH_OT_INT ? _("number") : _("string"));
K
Karel Zak 已提交
1871 1872
                        goto syntaxError;
                    }
1873 1874
                    if (opt->type != VSH_OT_ARGV)
                        opts_need_arg &= ~(1 << opt_index);
1875 1876 1877 1878 1879 1880 1881 1882
                } else {
                    tkdata = NULL;
                    if (optstr) {
                        vshError(ctl, _("invalid '=' after option --%s"),
                                opt->name);
                        VIR_FREE(optstr);
                        goto syntaxError;
                    }
K
Karel Zak 已提交
1883
                }
L
Lai Jiangshan 已提交
1884 1885 1886 1887
            } else if (tkdata[0] == '-' && tkdata[1] == '-' &&
                       tkdata[2] == '\0') {
                data_only = true;
                continue;
1888
            } else {
L
Lai Jiangshan 已提交
1889
get_data:
1890
                /* Special case 'help' to ignore spurious data */
1891
                if (!(opt = vshCmddefGetData(cmd, &opts_need_arg,
1892 1893
                                             &opts_seen)) &&
                     STRNEQ(cmd->name, "help")) {
1894
                    vshError(ctl, _("unexpected data '%s'"), tkdata);
K
Karel Zak 已提交
1895 1896 1897 1898 1899
                    goto syntaxError;
                }
            }
            if (opt) {
                /* save option */
1900
                vshCmdOpt *arg = vshMalloc(ctl, sizeof(vshCmdOpt));
1901

K
Karel Zak 已提交
1902 1903 1904 1905
                arg->def = opt;
                arg->data = tkdata;
                arg->next = NULL;
                tkdata = NULL;
1906

K
Karel Zak 已提交
1907 1908 1909 1910 1911
                if (!first)
                    first = arg;
                if (last)
                    last->next = arg;
                last = arg;
1912

1913
                vshDebug(ctl, VSH_ERR_INFO, "%s: %s(%s): %s\n",
1914 1915
                         cmd->name,
                         opt->name,
1916 1917
                         opt->type != VSH_OT_BOOL ? _("optdata") : _("bool"),
                         opt->type != VSH_OT_BOOL ? arg->data : _("(none)"));
K
Karel Zak 已提交
1918 1919
            }
        }
1920

D
Daniel Veillard 已提交
1921
        /* command parsed -- allocate new struct for the command */
K
Karel Zak 已提交
1922
        if (cmd) {
1923
            vshCmd *c = vshMalloc(ctl, sizeof(vshCmd));
1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942
            vshCmdOpt *tmpopt = first;

            /* if we encountered --help, replace parsed command with
             * 'help <cmdname>' */
            for (tmpopt = first; tmpopt; tmpopt = tmpopt->next) {
                if (STRNEQ(tmpopt->def->name, "help"))
                    continue;

                vshCommandOptFree(first);
                first = vshMalloc(ctl, sizeof(vshCmdOpt));
                first->def = &(opts_help[0]);
                first->data = vshStrdup(ctl, cmd->name);
                first->next = NULL;

                cmd = vshCmddefSearch("help");
                opts_required = 0;
                opts_seen = 0;
                break;
            }
1943

K
Karel Zak 已提交
1944 1945 1946 1947
            c->opts = first;
            c->def = cmd;
            c->next = NULL;

1948
            if (vshCommandCheckOpts(ctl, c, opts_required, opts_seen) < 0) {
1949
                VIR_FREE(c);
1950
                goto syntaxError;
1951
            }
1952

K
Karel Zak 已提交
1953 1954 1955 1956 1957 1958
            if (!ctl->cmd)
                ctl->cmd = c;
            if (clast)
                clast->next = c;
            clast = c;
        }
1959 1960 1961

        if (tk == VSH_TK_END)
            break;
K
Karel Zak 已提交
1962
    }
1963

E
Eric Blake 已提交
1964
    return true;
K
Karel Zak 已提交
1965

1966
 syntaxError:
1967
    if (ctl->cmd) {
K
Karel Zak 已提交
1968
        vshCommandFree(ctl->cmd);
1969 1970
        ctl->cmd = NULL;
    }
K
Karel Zak 已提交
1971 1972
    if (first)
        vshCommandOptFree(first);
1973
    VIR_FREE(tkdata);
E
Eric Blake 已提交
1974
    return false;
K
Karel Zak 已提交
1975 1976
}

1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994
/* --------------------
 * Command argv parsing
 * --------------------
 */

static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
vshCommandArgvGetArg(vshControl *ctl, vshCommandParser *parser, char **res)
{
    if (parser->arg_pos == parser->arg_end) {
        *res = NULL;
        return VSH_TK_END;
    }

    *res = vshStrdup(ctl, *parser->arg_pos);
    parser->arg_pos++;
    return VSH_TK_ARG;
}

E
Eric Blake 已提交
1995 1996
static bool
vshCommandArgvParse(vshControl *ctl, int nargs, char **argv)
1997 1998 1999 2000
{
    vshCommandParser parser;

    if (nargs <= 0)
E
Eric Blake 已提交
2001
        return false;
2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073

    parser.arg_pos = argv;
    parser.arg_end = argv + nargs;
    parser.getNextArg = vshCommandArgvGetArg;
    return vshCommandParse(ctl, &parser);
}

/* ----------------------
 * Command string parsing
 * ----------------------
 */

static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res)
{
    bool single_quote = false;
    bool double_quote = false;
    int sz = 0;
    char *p = parser->pos;
    char *q = vshStrdup(ctl, p);

    *res = q;

    while (*p && (*p == ' ' || *p == '\t'))
        p++;

    if (*p == '\0')
        return VSH_TK_END;
    if (*p == ';') {
        parser->pos = ++p;             /* = \0 or begin of next command */
        return VSH_TK_SUBCMD_END;
    }

    while (*p) {
        /* end of token is blank space or ';' */
        if (!double_quote && !single_quote &&
            (*p == ' ' || *p == '\t' || *p == ';'))
            break;

        if (!double_quote && *p == '\'') { /* single quote */
            single_quote = !single_quote;
            p++;
            continue;
        } else if (!single_quote && *p == '\\') { /* escape */
            /*
             * The same as the bash, a \ in "" is an escaper,
             * but a \ in '' is not an escaper.
             */
            p++;
            if (*p == '\0') {
                vshError(ctl, "%s", _("dangling \\"));
                return VSH_TK_ERROR;
            }
        } else if (!single_quote && *p == '"') { /* double quote */
            double_quote = !double_quote;
            p++;
            continue;
        }

        *q++ = *p++;
        sz++;
    }
    if (double_quote) {
        vshError(ctl, "%s", _("missing \""));
        return VSH_TK_ERROR;
    }

    *q = '\0';
    parser->pos = p;
    return VSH_TK_ARG;
}

E
Eric Blake 已提交
2074 2075
static bool
vshCommandStringParse(vshControl *ctl, char *cmdstr)
2076 2077 2078 2079
{
    vshCommandParser parser;

    if (cmdstr == NULL || *cmdstr == '\0')
E
Eric Blake 已提交
2080
        return false;
2081 2082 2083 2084 2085 2086

    parser.pos = cmdstr;
    parser.getNextArg = vshCommandStringGetArg;
    return vshCommandParse(ctl, &parser);
}

K
Karel Zak 已提交
2087
/* ---------------
2088
 * Misc utils
K
Karel Zak 已提交
2089 2090
 * ---------------
 */
E
Eric Blake 已提交
2091
int
2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118
vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason)
{
    virDomainInfo info;

    if (reason)
        *reason = -1;

    if (!ctl->useGetInfo) {
        int state;
        if (virDomainGetState(dom, &state, reason, 0) < 0) {
            virErrorPtr err = virGetLastError();
            if (err && err->code == VIR_ERR_NO_SUPPORT)
                ctl->useGetInfo = true;
            else
                return -1;
        } else {
            return state;
        }
    }

    /* fall back to virDomainGetInfo if virDomainGetState is not supported */
    if (virDomainGetInfo(dom, &info) < 0)
        return -1;
    else
        return info.state;
}

2119 2120
/* Return a non-NULL string representation of a typed parameter; exit
 * if we are out of memory.  */
E
Eric Blake 已提交
2121
char *
2122 2123 2124 2125 2126
vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item)
{
    int ret = 0;
    char *str = NULL;

2127
    switch (item->type) {
2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148
    case VIR_TYPED_PARAM_INT:
        ret = virAsprintf(&str, "%d", item->value.i);
        break;

    case VIR_TYPED_PARAM_UINT:
        ret = virAsprintf(&str, "%u", item->value.ui);
        break;

    case VIR_TYPED_PARAM_LLONG:
        ret = virAsprintf(&str, "%lld", item->value.l);
        break;

    case VIR_TYPED_PARAM_ULLONG:
        ret = virAsprintf(&str, "%llu", item->value.ul);
        break;

    case VIR_TYPED_PARAM_DOUBLE:
        ret = virAsprintf(&str, "%f", item->value.d);
        break;

    case VIR_TYPED_PARAM_BOOLEAN:
E
Eric Blake 已提交
2149
        str = vshStrdup(ctl, item->value.b ? _("yes") : _("no"));
2150 2151
        break;

2152 2153 2154 2155
    case VIR_TYPED_PARAM_STRING:
        str = vshStrdup(ctl, item->value.s);
        break;

2156
    default:
2157
        vshError(ctl, _("unimplemented parameter type %d"), item->type);
2158 2159
    }

2160
    if (ret < 0) {
2161
        vshError(ctl, "%s", _("Out of memory"));
2162 2163
        exit(EXIT_FAILURE);
    }
2164 2165 2166
    return str;
}

E
Eric Blake 已提交
2167
void
2168
vshDebug(vshControl *ctl, int level, const char *format, ...)
2169
{
K
Karel Zak 已提交
2170
    va_list ap;
2171
    char *str;
K
Karel Zak 已提交
2172

2173 2174 2175 2176 2177 2178 2179
    /* Aligning log levels to that of libvirt.
     * Traces with levels >=  user-specified-level
     * gets logged into file
     */
    if (level < ctl->debug)
        return;

2180
    va_start(ap, format);
2181
    vshOutputLogFile(ctl, level, format, ap);
2182 2183
    va_end(ap);

K
Karel Zak 已提交
2184
    va_start(ap, format);
2185 2186 2187 2188 2189
    if (virVasprintf(&str, format, ap) < 0) {
        /* Skip debug messages on low memory */
        va_end(ap);
        return;
    }
K
Karel Zak 已提交
2190
    va_end(ap);
2191 2192
    fputs(str, stdout);
    VIR_FREE(str);
K
Karel Zak 已提交
2193 2194
}

E
Eric Blake 已提交
2195
void
2196
vshPrintExtra(vshControl *ctl, const char *format, ...)
2197
{
K
Karel Zak 已提交
2198
    va_list ap;
2199
    char *str;
2200

2201
    if (ctl && ctl->quiet)
K
Karel Zak 已提交
2202
        return;
2203

K
Karel Zak 已提交
2204
    va_start(ap, format);
2205 2206 2207 2208 2209
    if (virVasprintf(&str, format, ap) < 0) {
        vshError(ctl, "%s", _("Out of memory"));
        va_end(ap);
        return;
    }
K
Karel Zak 已提交
2210
    va_end(ap);
2211
    fputs(str, stdout);
2212
    VIR_FREE(str);
K
Karel Zak 已提交
2213 2214
}

K
Karel Zak 已提交
2215

E
Eric Blake 已提交
2216
void
2217
vshError(vshControl *ctl, const char *format, ...)
2218
{
K
Karel Zak 已提交
2219
    va_list ap;
2220
    char *str;
2221

2222 2223 2224 2225 2226
    if (ctl != NULL) {
        va_start(ap, format);
        vshOutputLogFile(ctl, VSH_ERR_ERROR, format, ap);
        va_end(ap);
    }
2227

2228 2229 2230 2231
    /* Most output is to stdout, but if someone ran virsh 2>&1, then
     * printing to stderr will not interleave correctly with stdout
     * unless we flush between every transition between streams.  */
    fflush(stdout);
2232
    fputs(_("error: "), stderr);
2233

K
Karel Zak 已提交
2234
    va_start(ap, format);
2235 2236 2237
    /* We can't recursively call vshError on an OOM situation, so ignore
       failure here. */
    ignore_value(virVasprintf(&str, format, ap));
K
Karel Zak 已提交
2238 2239
    va_end(ap);

2240
    fprintf(stderr, "%s\n", NULLSTR(str));
2241
    fflush(stderr);
2242
    VIR_FREE(str);
K
Karel Zak 已提交
2243 2244
}

2245

J
Jiri Denemark 已提交
2246 2247 2248 2249 2250
static void
vshEventLoop(void *opaque)
{
    vshControl *ctl = opaque;

2251 2252 2253 2254 2255 2256 2257 2258 2259 2260
    while (1) {
        bool quit;
        virMutexLock(&ctl->lock);
        quit = ctl->quit;
        virMutexUnlock(&ctl->lock);

        if (quit)
            break;

        if (virEventRunDefaultImpl() < 0)
E
Eric Blake 已提交
2261
            vshReportError(ctl);
J
Jiri Denemark 已提交
2262 2263 2264 2265
    }
}


K
Karel Zak 已提交
2266
/*
M
Martin Kletzander 已提交
2267
 * Initialize debug settings.
K
Karel Zak 已提交
2268
 */
M
Martin Kletzander 已提交
2269 2270
static void
vshInitDebug(vshControl *ctl)
2271
{
2272 2273
    char *debugEnv;

J
Jiri Denemark 已提交
2274
    if (ctl->debug == VSH_DEBUG_DEFAULT) {
2275 2276 2277
        /* log level not set from commandline, check env variable */
        debugEnv = getenv("VIRSH_DEBUG");
        if (debugEnv) {
J
Jiri Denemark 已提交
2278 2279 2280
            int debug;
            if (virStrToLong_i(debugEnv, NULL, 10, &debug) < 0 ||
                debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR) {
2281 2282
                vshError(ctl, "%s",
                         _("VIRSH_DEBUG not set with a valid numeric value"));
J
Jiri Denemark 已提交
2283 2284
            } else {
                ctl->debug = debug;
2285 2286 2287 2288 2289 2290 2291 2292 2293
            }
        }
    }

    if (ctl->logfile == NULL) {
        /* log file not set from cmdline */
        debugEnv = getenv("VIRSH_LOG_FILE");
        if (debugEnv && *debugEnv) {
            ctl->logfile = vshStrdup(ctl, debugEnv);
M
Martin Kletzander 已提交
2294
            vshOpenLogFile(ctl);
2295 2296
        }
    }
M
Martin Kletzander 已提交
2297 2298 2299 2300 2301 2302 2303 2304
}

/*
 * Initialize connection.
 */
static bool
vshInit(vshControl *ctl)
{
M
Martin Kletzander 已提交
2305 2306 2307 2308
    /* Since we have the commandline arguments parsed, we need to
     * re-initialize all the debugging to make it work properly */
    vshInitDebug(ctl);

M
Martin Kletzander 已提交
2309 2310
    if (ctl->conn)
        return false;
2311

2312 2313
    /* set up the library error handler */
    virSetErrorFunc(NULL, virshErrorHandler);
2314

2315
    if (virEventRegisterDefaultImpl() < 0)
E
Eric Blake 已提交
2316
        return false;
2317

J
Jiri Denemark 已提交
2318 2319 2320 2321
    if (virThreadCreate(&ctl->eventLoop, true, vshEventLoop, ctl) < 0)
        return false;
    ctl->eventLoopStarted = true;

2322
    if (ctl->name) {
2323
        vshReconnect(ctl);
2324 2325 2326 2327 2328 2329 2330
        /* Connecting to a named connection must succeed, but we delay
         * connecting to the default connection until we need it
         * (since the first command might be 'connect' which allows a
         * non-default connection, or might be 'help' which needs no
         * connection).
         */
        if (!ctl->conn) {
E
Eric Blake 已提交
2331
            vshReportError(ctl);
2332 2333
            return false;
        }
2334
    }
K
Karel Zak 已提交
2335

E
Eric Blake 已提交
2336
    return true;
K
Karel Zak 已提交
2337 2338
}

2339 2340
#define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC)

2341 2342 2343 2344 2345
/**
 * vshOpenLogFile:
 *
 * Open log file.
 */
E
Eric Blake 已提交
2346
void
2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359
vshOpenLogFile(vshControl *ctl)
{
    struct stat st;

    if (ctl->logfile == NULL)
        return;

    /* check log file */
    if (stat(ctl->logfile, &st) == -1) {
        switch (errno) {
            case ENOENT:
                break;
            default:
2360
                vshError(ctl, "%s",
J
Jim Meyering 已提交
2361
                         _("failed to get the log file information"));
2362
                exit(EXIT_FAILURE);
2363 2364 2365
        }
    } else {
        if (!S_ISREG(st.st_mode)) {
2366 2367
            vshError(ctl, "%s", _("the log path is not a file"));
            exit(EXIT_FAILURE);
2368 2369 2370 2371
        }
    }

    /* log file open */
2372
    if ((ctl->log_fd = open(ctl->logfile, LOGFILE_FLAGS, FILE_MODE)) < 0) {
2373
        vshError(ctl, "%s",
J
Jim Meyering 已提交
2374
                 _("failed to open the log file. check the log file path"));
2375
        exit(EXIT_FAILURE);
2376 2377 2378 2379 2380 2381 2382 2383
    }
}

/**
 * vshOutputLogFile:
 *
 * Outputting an error to log file.
 */
E
Eric Blake 已提交
2384
void
2385 2386
vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format,
                 va_list ap)
2387
{
2388
    virBuffer buf = VIR_BUFFER_INITIALIZER;
J
John Ferlan 已提交
2389
    char *str = NULL;
2390
    size_t len;
2391
    const char *lvl = "";
2392
    time_t stTime;
2393
    struct tm stTm;
2394 2395 2396 2397 2398 2399 2400 2401 2402

    if (ctl->log_fd == -1)
        return;

    /**
     * create log format
     *
     * [YYYY.MM.DD HH:MM:SS SIGNATURE PID] LOG_LEVEL message
    */
2403 2404
    time(&stTime);
    localtime_r(&stTime, &stTm);
2405
    virBufferAsprintf(&buf, "[%d.%02d.%02d %02d:%02d:%02d %s %d] ",
2406 2407 2408 2409 2410 2411
                      (1900 + stTm.tm_year),
                      (1 + stTm.tm_mon),
                      stTm.tm_mday,
                      stTm.tm_hour,
                      stTm.tm_min,
                      stTm.tm_sec,
2412 2413
                      SIGN_NAME,
                      (int) getpid());
2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433
    switch (log_level) {
        case VSH_ERR_DEBUG:
            lvl = LVL_DEBUG;
            break;
        case VSH_ERR_INFO:
            lvl = LVL_INFO;
            break;
        case VSH_ERR_NOTICE:
            lvl = LVL_INFO;
            break;
        case VSH_ERR_WARNING:
            lvl = LVL_WARNING;
            break;
        case VSH_ERR_ERROR:
            lvl = LVL_ERROR;
            break;
        default:
            lvl = LVL_DEBUG;
            break;
    }
2434 2435 2436
    virBufferAsprintf(&buf, "%s ", lvl);
    virBufferVasprintf(&buf, msg_format, ap);
    virBufferAddChar(&buf, '\n');
2437

2438 2439
    if (virBufferError(&buf))
        goto error;
2440

2441 2442 2443 2444 2445
    str = virBufferContentAndReset(&buf);
    len = strlen(str);
    if (len > 1 && str[len - 2] == '\n') {
        str[len - 1] = '\0';
        len--;
2446
    }
2447

2448 2449 2450 2451
    /* write log */
    if (safewrite(ctl->log_fd, str, len) < 0)
        goto error;

2452
    VIR_FREE(str);
2453 2454 2455 2456 2457 2458 2459
    return;

error:
    vshCloseLogFile(ctl);
    vshError(ctl, "%s", _("failed to write the log file"));
    virBufferFreeAndReset(&buf);
    VIR_FREE(str);
2460 2461 2462 2463 2464 2465 2466
}

/**
 * vshCloseLogFile:
 *
 * Close log file.
 */
E
Eric Blake 已提交
2467
void
2468 2469
vshCloseLogFile(vshControl *ctl)
{
2470 2471
    char ebuf[1024];

2472
    /* log file close */
2473 2474
    if (VIR_CLOSE(ctl->log_fd) < 0) {
        vshError(ctl, _("%s: failed to write log file: %s"),
2475 2476
                 ctl->logfile ? ctl->logfile : "?",
                 virStrerror(errno, ebuf, sizeof(ebuf)));
2477 2478 2479
    }

    if (ctl->logfile) {
2480
        VIR_FREE(ctl->logfile);
2481 2482 2483 2484
        ctl->logfile = NULL;
    }
}

2485
#ifdef USE_READLINE
2486

K
Karel Zak 已提交
2487 2488 2489 2490 2491
/* -----------------
 * Readline stuff
 * -----------------
 */

2492
/*
K
Karel Zak 已提交
2493 2494
 * Generator function for command completion.  STATE lets us
 * know whether to start from scratch; without any state
2495
 * (i.e. STATE == 0), then we start at the top of the list.
K
Karel Zak 已提交
2496 2497
 */
static char *
2498 2499
vshReadlineCommandGenerator(const char *text, int state)
{
2500
    static int grp_list_index, cmd_list_index, len;
K
Karel Zak 已提交
2501
    const char *name;
2502 2503
    const vshCmdGrp *grp;
    const vshCmdDef *cmds;
K
Karel Zak 已提交
2504 2505

    if (!state) {
2506 2507
        grp_list_index = 0;
        cmd_list_index = 0;
2508
        len = strlen(text);
K
Karel Zak 已提交
2509 2510
    }

2511 2512
    grp = cmdGroups;

K
Karel Zak 已提交
2513
    /* Return the next name which partially matches from the
2514
     * command list.
K
Karel Zak 已提交
2515
     */
2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529
    while (grp[grp_list_index].name) {
        cmds = grp[grp_list_index].commands;

        if (cmds[cmd_list_index].name) {
            while ((name = cmds[cmd_list_index].name)) {
                cmd_list_index++;

                if (STREQLEN(name, text, len))
                    return vshStrdup(NULL, name);
            }
        } else {
            cmd_list_index = 0;
            grp_list_index++;
        }
K
Karel Zak 已提交
2530 2531 2532 2533 2534 2535 2536
    }

    /* If no names matched, then return NULL. */
    return NULL;
}

static char *
2537 2538
vshReadlineOptionsGenerator(const char *text, int state)
{
K
Karel Zak 已提交
2539
    static int list_index, len;
2540
    static const vshCmdDef *cmd = NULL;
K
Karel Zak 已提交
2541
    const char *name;
K
Karel Zak 已提交
2542 2543 2544 2545 2546 2547 2548 2549 2550

    if (!state) {
        /* determine command name */
        char *p;
        char *cmdname;

        if (!(p = strchr(rl_line_buffer, ' ')))
            return NULL;

2551
        cmdname = vshCalloc(NULL, (p - rl_line_buffer) + 1, 1);
2552
        memcpy(cmdname, rl_line_buffer, p - rl_line_buffer);
K
Karel Zak 已提交
2553 2554 2555

        cmd = vshCmddefSearch(cmdname);
        list_index = 0;
2556
        len = strlen(text);
2557
        VIR_FREE(cmdname);
K
Karel Zak 已提交
2558 2559 2560 2561
    }

    if (!cmd)
        return NULL;
2562

2563 2564 2565
    if (!cmd->opts)
        return NULL;

K
Karel Zak 已提交
2566
    while ((name = cmd->opts[list_index].name)) {
2567
        const vshCmdOptDef *opt = &cmd->opts[list_index];
K
Karel Zak 已提交
2568
        char *res;
2569

K
Karel Zak 已提交
2570
        list_index++;
2571

2572
        if (opt->type == VSH_OT_DATA || opt->type == VSH_OT_ARGV)
K
Karel Zak 已提交
2573 2574
            /* ignore non --option */
            continue;
2575

K
Karel Zak 已提交
2576
        if (len > 2) {
2577
            if (STRNEQLEN(name, text + 2, len - 2))
K
Karel Zak 已提交
2578 2579
                continue;
        }
2580
        res = vshMalloc(NULL, strlen(name) + 3);
2581
        snprintf(res, strlen(name) + 3,  "--%s", name);
K
Karel Zak 已提交
2582 2583 2584 2585 2586 2587 2588 2589
        return res;
    }

    /* If no names matched, then return NULL. */
    return NULL;
}

static char **
2590 2591 2592
vshReadlineCompletion(const char *text, int start,
                      int end ATTRIBUTE_UNUSED)
{
K
Karel Zak 已提交
2593 2594
    char **matches = (char **) NULL;

2595
    if (start == 0)
K
Karel Zak 已提交
2596
        /* command name generator */
2597
        matches = rl_completion_matches(text, vshReadlineCommandGenerator);
K
Karel Zak 已提交
2598 2599
    else
        /* commands options */
2600
        matches = rl_completion_matches(text, vshReadlineOptionsGenerator);
K
Karel Zak 已提交
2601 2602 2603 2604
    return matches;
}


2605 2606
static int
vshReadlineInit(vshControl *ctl)
2607
{
2608 2609
    char *userdir = NULL;

K
Karel Zak 已提交
2610 2611 2612 2613 2614
    /* Allow conditional parsing of the ~/.inputrc file. */
    rl_readline_name = "virsh";

    /* Tell the completer that we want a crack first. */
    rl_attempted_completion_function = vshReadlineCompletion;
2615 2616 2617

    /* Limit the total size of the history buffer */
    stifle_history(500);
2618

2619
    /* Prepare to read/write history from/to the $XDG_CACHE_HOME/virsh/history file */
2620
    userdir = virGetUserCacheDirectory();
2621

2622 2623
    if (userdir == NULL) {
        vshError(ctl, "%s", _("Could not determine home directory"));
2624
        return -1;
2625
    }
2626

2627
    if (virAsprintf(&ctl->historydir, "%s/virsh", userdir) < 0) {
2628
        vshError(ctl, "%s", _("Out of memory"));
2629
        VIR_FREE(userdir);
2630 2631 2632 2633 2634
        return -1;
    }

    if (virAsprintf(&ctl->historyfile, "%s/history", ctl->historydir) < 0) {
        vshError(ctl, "%s", _("Out of memory"));
2635
        VIR_FREE(userdir);
2636 2637 2638
        return -1;
    }

2639
    VIR_FREE(userdir);
2640 2641 2642 2643 2644 2645 2646

    read_history(ctl->historyfile);

    return 0;
}

static void
2647
vshReadlineDeinit(vshControl *ctl)
2648 2649
{
    if (ctl->historyfile != NULL) {
2650 2651
        if (virFileMakePathWithMode(ctl->historydir, 0755) < 0 &&
            errno != EEXIST) {
2652 2653
            char ebuf[1024];
            vshError(ctl, _("Failed to create '%s': %s"),
2654
                     ctl->historydir, virStrerror(errno, ebuf, sizeof(ebuf)));
E
Eric Blake 已提交
2655
        } else {
2656
            write_history(ctl->historyfile);
E
Eric Blake 已提交
2657
        }
2658 2659
    }

2660 2661
    VIR_FREE(ctl->historydir);
    VIR_FREE(ctl->historyfile);
K
Karel Zak 已提交
2662 2663
}

2664
static char *
2665
vshReadline(vshControl *ctl ATTRIBUTE_UNUSED, const char *prompt)
2666
{
2667
    return readline(prompt);
2668 2669
}

2670
#else /* !USE_READLINE */
2671

2672
static int
2673
vshReadlineInit(vshControl *ctl ATTRIBUTE_UNUSED)
2674 2675 2676 2677 2678
{
    /* empty */
    return 0;
}

2679
static void
2680
vshReadlineDeinit(vshControl *ctl ATTRIBUTE_UNUSED)
2681 2682 2683 2684 2685
{
    /* empty */
}

static char *
2686
vshReadline(vshControl *ctl, const char *prompt)
2687 2688 2689 2690 2691
{
    char line[1024];
    char *r;
    int len;

2692 2693
    fputs(prompt, stdout);
    r = fgets(line, sizeof(line), stdin);
2694 2695 2696
    if (r == NULL) return NULL; /* EOF */

    /* Chomp trailing \n */
2697
    len = strlen(r);
2698 2699 2700
    if (len > 0 && r[len-1] == '\n')
        r[len-1] = '\0';

2701
    return vshStrdup(ctl, r);
2702 2703
}

2704
#endif /* !USE_READLINE */
2705

2706 2707 2708 2709 2710 2711
static void
vshDeinitTimer(int timer ATTRIBUTE_UNUSED, void *opaque ATTRIBUTE_UNUSED)
{
    /* nothing to be done here */
}

K
Karel Zak 已提交
2712
/*
J
Jim Meyering 已提交
2713
 * Deinitialize virsh
K
Karel Zak 已提交
2714
 */
E
Eric Blake 已提交
2715
static bool
2716
vshDeinit(vshControl *ctl)
2717
{
2718
    vshReadlineDeinit(ctl);
2719
    vshCloseLogFile(ctl);
2720
    VIR_FREE(ctl->name);
K
Karel Zak 已提交
2721
    if (ctl->conn) {
2722
        int ret;
2723 2724 2725 2726 2727 2728 2729
        virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect);
        ret = virConnectClose(ctl->conn);
        if (ret < 0)
            vshError(ctl, "%s", _("Failed to disconnect from the hypervisor"));
        else if (ret > 0)
            vshError(ctl, "%s", _("One or more references were leaked after "
                                  "disconnect from the hypervisor"));
K
Karel Zak 已提交
2730
    }
D
Daniel P. Berrange 已提交
2731 2732
    virResetLastError();

J
Jiri Denemark 已提交
2733
    if (ctl->eventLoopStarted) {
2734 2735 2736 2737
        int timer;

        virMutexLock(&ctl->lock);
        ctl->quit = true;
J
Jiri Denemark 已提交
2738
        /* HACK: Add a dummy timeout to break event loop */
2739 2740 2741 2742 2743
        timer = virEventAddTimeout(0, vshDeinitTimer, NULL, NULL);
        virMutexUnlock(&ctl->lock);

        virThreadJoin(&ctl->eventLoop);

J
Jiri Denemark 已提交
2744 2745 2746 2747 2748 2749
        if (timer != -1)
            virEventRemoveTimeout(timer);

        ctl->eventLoopStarted = false;
    }

2750 2751
    virMutexDestroy(&ctl->lock);

E
Eric Blake 已提交
2752
    return true;
K
Karel Zak 已提交
2753
}
2754

K
Karel Zak 已提交
2755 2756 2757
/*
 * Print usage
 */
E
Eric Blake 已提交
2758
static void
2759
vshUsage(void)
2760
{
2761
    const vshCmdGrp *grp;
2762
    const vshCmdDef *cmd;
2763

L
Lai Jiangshan 已提交
2764 2765
    fprintf(stdout, _("\n%s [options]... [<command_string>]"
                      "\n%s [options]... <command> [args...]\n\n"
2766
                      "  options:\n"
2767
                      "    -c | --connect=URI      hypervisor connection URI\n"
2768
                      "    -r | --readonly         connect readonly\n"
2769
                      "    -d | --debug=NUM        debug level [0-4]\n"
2770 2771 2772
                      "    -h | --help             this help\n"
                      "    -q | --quiet            quiet mode\n"
                      "    -t | --timing           print timing information\n"
2773 2774 2775 2776 2777
                      "    -l | --log=FILE         output logging to file\n"
                      "    -v                      short version\n"
                      "    -V                      long version\n"
                      "         --version[=TYPE]   version, TYPE is short or long (default short)\n"
                      "    -e | --escape <char>    set escape sequence for console\n\n"
2778
                      "  commands (non interactive mode):\n\n"), progname, progname);
2779

2780
    for (grp = cmdGroups; grp->name; grp++) {
E
Eric Blake 已提交
2781 2782 2783 2784 2785
        fprintf(stdout, _(" %s (help keyword '%s')\n"),
                grp->name, grp->keyword);
        for (cmd = grp->commands; cmd->name; cmd++) {
            if (cmd->flags & VSH_CMD_FLAG_ALIAS)
                continue;
2786
            fprintf(stdout,
E
Eric Blake 已提交
2787 2788 2789
                    "    %-30s %s\n", cmd->name,
                    _(vshCmddefGetInfo(cmd, "help")));
        }
2790 2791 2792 2793 2794
        fprintf(stdout, "\n");
    }

    fprintf(stdout, "%s",
            _("\n  (specify help <group> for details about the commands in the group)\n"));
2795 2796 2797
    fprintf(stdout, "%s",
            _("\n  (specify help <command> for details about the command)\n\n"));
    return;
K
Karel Zak 已提交
2798 2799
}

2800 2801 2802 2803 2804 2805 2806 2807 2808 2809
/*
 * Show version and options compiled in
 */
static void
vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED)
{
    /* FIXME - list a copyright blurb, as in GNU programs?  */
    vshPrint(ctl, _("Virsh command line tool of libvirt %s\n"), VERSION);
    vshPrint(ctl, _("See web site at %s\n\n"), "http://libvirt.org/");

L
Laine Stump 已提交
2810 2811
    vshPrint(ctl, "%s", _("Compiled with support for:\n"));
    vshPrint(ctl, "%s", _(" Hypervisors:"));
2812
#ifdef WITH_QEMU
2813
    vshPrint(ctl, " QEMU/KVM");
2814
#endif
D
Doug Goldstein 已提交
2815 2816 2817
#ifdef WITH_LXC
    vshPrint(ctl, " LXC");
#endif
2818 2819 2820
#ifdef WITH_UML
    vshPrint(ctl, " UML");
#endif
D
Doug Goldstein 已提交
2821 2822 2823 2824 2825 2826
#ifdef WITH_XEN
    vshPrint(ctl, " Xen");
#endif
#ifdef WITH_LIBXL
    vshPrint(ctl, " LibXL");
#endif
2827 2828 2829
#ifdef WITH_OPENVZ
    vshPrint(ctl, " OpenVZ");
#endif
D
Doug Goldstein 已提交
2830 2831
#ifdef WITH_VMWARE
    vshPrint(ctl, " VMWare");
2832
#endif
D
Doug Goldstein 已提交
2833 2834
#ifdef WITH_PHYP
    vshPrint(ctl, " PHYP");
2835
#endif
D
Doug Goldstein 已提交
2836 2837
#ifdef WITH_VBOX
    vshPrint(ctl, " VirtualBox");
2838 2839 2840 2841
#endif
#ifdef WITH_ESX
    vshPrint(ctl, " ESX");
#endif
D
Doug Goldstein 已提交
2842 2843
#ifdef WITH_HYPERV
    vshPrint(ctl, " Hyper-V");
2844
#endif
D
Doug Goldstein 已提交
2845 2846
#ifdef WITH_XENAPI
    vshPrint(ctl, " XenAPI");
2847 2848 2849 2850 2851 2852
#endif
#ifdef WITH_TEST
    vshPrint(ctl, " Test");
#endif
    vshPrint(ctl, "\n");

L
Laine Stump 已提交
2853
    vshPrint(ctl, "%s", _(" Networking:"));
2854 2855 2856 2857 2858 2859 2860 2861 2862
#ifdef WITH_REMOTE
    vshPrint(ctl, " Remote");
#endif
#ifdef WITH_NETWORK
    vshPrint(ctl, " Network");
#endif
#ifdef WITH_BRIDGE
    vshPrint(ctl, " Bridging");
#endif
2863
#if defined(WITH_INTERFACE)
D
Doug Goldstein 已提交
2864
    vshPrint(ctl, " Interface");
2865 2866
# if defined(WITH_NETCF)
    vshPrint(ctl, " netcf");
2867
# elif defined(WITH_UDEV)
2868
    vshPrint(ctl, " udev");
2869
# endif
2870 2871 2872 2873 2874 2875 2876 2877 2878
#endif
#ifdef WITH_NWFILTER
    vshPrint(ctl, " Nwfilter");
#endif
#ifdef WITH_VIRTUALPORT
    vshPrint(ctl, " VirtualPort");
#endif
    vshPrint(ctl, "\n");

L
Laine Stump 已提交
2879
    vshPrint(ctl, "%s", _(" Storage:"));
2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899
#ifdef WITH_STORAGE_DIR
    vshPrint(ctl, " Dir");
#endif
#ifdef WITH_STORAGE_DISK
    vshPrint(ctl, " Disk");
#endif
#ifdef WITH_STORAGE_FS
    vshPrint(ctl, " Filesystem");
#endif
#ifdef WITH_STORAGE_SCSI
    vshPrint(ctl, " SCSI");
#endif
#ifdef WITH_STORAGE_MPATH
    vshPrint(ctl, " Multipath");
#endif
#ifdef WITH_STORAGE_ISCSI
    vshPrint(ctl, " iSCSI");
#endif
#ifdef WITH_STORAGE_LVM
    vshPrint(ctl, " LVM");
2900 2901 2902
#endif
#ifdef WITH_STORAGE_RBD
    vshPrint(ctl, " RBD");
2903 2904 2905
#endif
#ifdef WITH_STORAGE_SHEEPDOG
    vshPrint(ctl, " Sheepdog");
2906 2907 2908
#endif
    vshPrint(ctl, "\n");

2909
    vshPrint(ctl, "%s", _(" Miscellaneous:"));
2910 2911 2912
#ifdef WITH_LIBVIRTD
    vshPrint(ctl, " Daemon");
#endif
2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953
#ifdef WITH_NODE_DEVICES
    vshPrint(ctl, " Nodedev");
#endif
#ifdef WITH_SECDRIVER_APPARMOR
    vshPrint(ctl, " AppArmor");
#endif
#ifdef WITH_SECDRIVER_SELINUX
    vshPrint(ctl, " SELinux");
#endif
#ifdef WITH_SECRETS
    vshPrint(ctl, " Secrets");
#endif
#ifdef ENABLE_DEBUG
    vshPrint(ctl, " Debug");
#endif
#ifdef WITH_DTRACE_PROBES
    vshPrint(ctl, " DTrace");
#endif
#ifdef USE_READLINE
    vshPrint(ctl, " Readline");
#endif
#ifdef WITH_DRIVER_MODULES
    vshPrint(ctl, " Modular");
#endif
    vshPrint(ctl, "\n");
}

static bool
vshAllowedEscapeChar(char c)
{
    /* Allowed escape characters:
     * a-z A-Z @ [ \ ] ^ _
     */
    return ('a' <= c && c <= 'z') ||
        ('@' <= c && c <= '_');
}

/*
 * argv[]:  virsh [options] [command]
 *
 */
E
Eric Blake 已提交
2954
static bool
2955 2956
vshParseArgv(vshControl *ctl, int argc, char **argv)
{
2957 2958
    int arg, len, debug;
    size_t i;
2959
    int longindex = -1;
2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975
    struct option opt[] = {
        {"debug", required_argument, NULL, 'd'},
        {"help", no_argument, NULL, 'h'},
        {"quiet", no_argument, NULL, 'q'},
        {"timing", no_argument, NULL, 't'},
        {"version", optional_argument, NULL, 'v'},
        {"connect", required_argument, NULL, 'c'},
        {"readonly", no_argument, NULL, 'r'},
        {"log", required_argument, NULL, 'l'},
        {"escape", required_argument, NULL, 'e'},
        {NULL, 0, NULL, 0}
    };

    /* Standard (non-command) options. The leading + ensures that no
     * argument reordering takes place, so that command options are
     * not confused with top-level virsh options. */
2976
    while ((arg = getopt_long(argc, argv, "+:d:hqtc:vVrl:e:", opt, &longindex)) != -1) {
2977 2978
        switch (arg) {
        case 'd':
2979
            if (virStrToLong_i(optarg, NULL, 10, &debug) < 0) {
2980 2981
                vshError(ctl, _("option %s takes a numeric argument"),
                         longindex == -1 ? "-d" : "--debug");
2982 2983
                exit(EXIT_FAILURE);
            }
2984 2985 2986 2987 2988
            if (debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR)
                vshError(ctl, _("ignoring debug level %d out of range [%d-%d]"),
                         debug, VSH_ERR_DEBUG, VSH_ERR_ERROR);
            else
                ctl->debug = debug;
2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000
            break;
        case 'h':
            vshUsage();
            exit(EXIT_SUCCESS);
            break;
        case 'q':
            ctl->quiet = true;
            break;
        case 't':
            ctl->timing = true;
            break;
        case 'c':
M
Martin Kletzander 已提交
3001
            VIR_FREE(ctl->name);
3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016
            ctl->name = vshStrdup(ctl, optarg);
            break;
        case 'v':
            if (STRNEQ_NULLABLE(optarg, "long")) {
                puts(VERSION);
                exit(EXIT_SUCCESS);
            }
            /* fall through */
        case 'V':
            vshShowVersion(ctl);
            exit(EXIT_SUCCESS);
        case 'r':
            ctl->readonly = true;
            break;
        case 'l':
M
Martin Kletzander 已提交
3017
            vshCloseLogFile(ctl);
3018
            ctl->logfile = vshStrdup(ctl, optarg);
M
Martin Kletzander 已提交
3019
            vshOpenLogFile(ctl);
3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033
            break;
        case 'e':
            len = strlen(optarg);

            if ((len == 2 && *optarg == '^' &&
                 vshAllowedEscapeChar(optarg[1])) ||
                (len == 1 && *optarg != '^')) {
                ctl->escapeChar = optarg;
            } else {
                vshError(ctl, _("Invalid string '%s' for escape sequence"),
                         optarg);
                exit(EXIT_FAILURE);
            }
            break;
3034
        case ':':
3035
            for (i = 0; opt[i].name != NULL; i++) {
3036 3037
                if (opt[i].val == optopt)
                    break;
3038
            }
3039 3040 3041 3042 3043 3044
            if (opt[i].name)
                vshError(ctl, _("option '-%c'/'--%s' requires an argument"),
                         optopt, opt[i].name);
            else
                vshError(ctl, _("option '-%c' requires an argument"), optopt);
            exit(EXIT_FAILURE);
3045
        case '?':
3046 3047 3048 3049
            if (optopt)
                vshError(ctl, _("unsupported option '-%c'. See --help."), optopt);
            else
                vshError(ctl, _("unsupported option '%s'. See --help."), argv[optind - 1]);
3050
            exit(EXIT_FAILURE);
3051
        default:
3052
            vshError(ctl, _("unknown option"));
3053 3054
            exit(EXIT_FAILURE);
        }
3055
        longindex = -1;
3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071
    }

    if (argc > optind) {
        /* parse command */
        ctl->imode = false;
        if (argc - optind == 1) {
            vshDebug(ctl, VSH_ERR_INFO, "commands: \"%s\"\n", argv[optind]);
            return vshCommandStringParse(ctl, argv[optind]);
        } else {
            return vshCommandArgvParse(ctl, argc - optind, argv + optind);
        }
    }
    return true;
}

static const vshCmdDef virshCmds[] = {
3072 3073 3074 3075 3076
    {.name = "cd",
     .handler = cmdCd,
     .opts = opts_cd,
     .info = info_cd,
     .flags = VSH_CMD_FLAG_NOCONNECT
3077 3078 3079 3080 3081 3082
    },
    {.name = "connect",
     .handler = cmdConnect,
     .opts = opts_connect,
     .info = info_connect,
     .flags = VSH_CMD_FLAG_NOCONNECT
3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114
    },
    {.name = "echo",
     .handler = cmdEcho,
     .opts = opts_echo,
     .info = info_echo,
     .flags = VSH_CMD_FLAG_NOCONNECT
    },
    {.name = "exit",
     .handler = cmdQuit,
     .opts = NULL,
     .info = info_quit,
     .flags = VSH_CMD_FLAG_NOCONNECT
    },
    {.name = "help",
     .handler = cmdHelp,
     .opts = opts_help,
     .info = info_help,
     .flags = VSH_CMD_FLAG_NOCONNECT
    },
    {.name = "pwd",
     .handler = cmdPwd,
     .opts = NULL,
     .info = info_pwd,
     .flags = VSH_CMD_FLAG_NOCONNECT
    },
    {.name = "quit",
     .handler = cmdQuit,
     .opts = NULL,
     .info = info_quit,
     .flags = VSH_CMD_FLAG_NOCONNECT
    },
    {.name = NULL}
3115
};
3116

3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131
static const vshCmdGrp cmdGroups[] = {
    {VSH_CMD_GRP_DOM_MANAGEMENT, "domain", domManagementCmds},
    {VSH_CMD_GRP_DOM_MONITORING, "monitor", domMonitoringCmds},
    {VSH_CMD_GRP_HOST_AND_HV, "host", hostAndHypervisorCmds},
    {VSH_CMD_GRP_IFACE, "interface", ifaceCmds},
    {VSH_CMD_GRP_NWFILTER, "filter", nwfilterCmds},
    {VSH_CMD_GRP_NETWORK, "network", networkCmds},
    {VSH_CMD_GRP_NODEDEV, "nodedev", nodedevCmds},
    {VSH_CMD_GRP_SECRET, "secret", secretCmds},
    {VSH_CMD_GRP_SNAPSHOT, "snapshot", snapshotCmds},
    {VSH_CMD_GRP_STORAGE_POOL, "pool", storagePoolCmds},
    {VSH_CMD_GRP_STORAGE_VOL, "volume", storageVolCmds},
    {VSH_CMD_GRP_VIRSH, "virsh", virshCmds},
    {NULL, NULL, NULL}
};
K
Karel Zak 已提交
3132

3133 3134 3135 3136
int
main(int argc, char **argv)
{
    vshControl _ctl, *ctl = &_ctl;
3137
    char *defaultConn;
E
Eric Blake 已提交
3138
    bool ret = true;
K
Karel Zak 已提交
3139

3140 3141 3142
    memset(ctl, 0, sizeof(vshControl));
    ctl->imode = true;          /* default is interactive mode */
    ctl->log_fd = -1;           /* Initialize log file descriptor */
J
Jiri Denemark 已提交
3143
    ctl->debug = VSH_DEBUG_DEFAULT;
E
Eric Blake 已提交
3144
    ctl->escapeChar = "^]";     /* Same default as telnet */
3145

3146

3147 3148
    if (!setlocale(LC_ALL, "")) {
        perror("setlocale");
3149
        /* failure to setup locale is not fatal */
3150
    }
3151
    if (!bindtextdomain(PACKAGE, LOCALEDIR)) {
3152
        perror("bindtextdomain");
E
Eric Blake 已提交
3153
        return EXIT_FAILURE;
3154
    }
3155
    if (!textdomain(PACKAGE)) {
3156
        perror("textdomain");
E
Eric Blake 已提交
3157
        return EXIT_FAILURE;
3158 3159
    }

3160 3161 3162 3163 3164
    if (virMutexInit(&ctl->lock) < 0) {
        vshError(ctl, "%s", _("Failed to initialize mutex"));
        return EXIT_FAILURE;
    }

3165 3166 3167 3168 3169
    if (virInitialize() < 0) {
        vshError(ctl, "%s", _("Failed to initialize libvirt"));
        return EXIT_FAILURE;
    }

3170
    if (!(progname = strrchr(argv[0], '/')))
K
Karel Zak 已提交
3171 3172 3173
        progname = argv[0];
    else
        progname++;
3174

3175
    if ((defaultConn = getenv("VIRSH_DEFAULT_CONNECT_URI"))) {
E
Eric Blake 已提交
3176
        ctl->name = vshStrdup(ctl, defaultConn);
3177 3178
    }

M
Martin Kletzander 已提交
3179
    vshInitDebug(ctl);
3180

M
Martin Kletzander 已提交
3181 3182
    if (!vshParseArgv(ctl, argc, argv) ||
        !vshInit(ctl)) {
D
Daniel P. Berrange 已提交
3183
        vshDeinit(ctl);
K
Karel Zak 已提交
3184
        exit(EXIT_FAILURE);
D
Daniel P. Berrange 已提交
3185
    }
3186

K
Karel Zak 已提交
3187
    if (!ctl->imode) {
3188
        ret = vshCommandRun(ctl, ctl->cmd);
3189
    } else {
K
Karel Zak 已提交
3190 3191
        /* interactive mode */
        if (!ctl->quiet) {
K
Karel Zak 已提交
3192
            vshPrint(ctl,
3193
                     _("Welcome to %s, the virtualization interactive terminal.\n\n"),
3194
                     progname);
J
Jim Meyering 已提交
3195
            vshPrint(ctl, "%s",
3196
                     _("Type:  'help' for help with commands\n"
3197
                       "       'quit' to quit\n\n"));
K
Karel Zak 已提交
3198
        }
3199 3200 3201 3202 3203 3204

        if (vshReadlineInit(ctl) < 0) {
            vshDeinit(ctl);
            exit(EXIT_FAILURE);
        }

K
Karel Zak 已提交
3205
        do {
3206
            const char *prompt = ctl->readonly ? VSH_PROMPT_RO : VSH_PROMPT_RW;
3207
            ctl->cmdstr =
3208
                vshReadline(ctl, prompt);
3209 3210
            if (ctl->cmdstr == NULL)
                break;          /* EOF */
K
Karel Zak 已提交
3211
            if (*ctl->cmdstr) {
3212
#if USE_READLINE
K
Karel Zak 已提交
3213
                add_history(ctl->cmdstr);
3214
#endif
3215
                if (vshCommandStringParse(ctl, ctl->cmdstr))
K
Karel Zak 已提交
3216 3217
                    vshCommandRun(ctl, ctl->cmd);
            }
3218
            VIR_FREE(ctl->cmdstr);
3219
        } while (ctl->imode);
K
Karel Zak 已提交
3220

3221 3222
        if (ctl->cmdstr == NULL)
            fputc('\n', stdout);        /* line break after alone prompt */
K
Karel Zak 已提交
3223
    }
3224

K
Karel Zak 已提交
3225 3226
    vshDeinit(ctl);
    exit(ret ? EXIT_SUCCESS : EXIT_FAILURE);
3227
}