virsh.c 77.6 KB
Newer Older
1
/*
2
 * virsh.c: a shell to exercise the libvirt API
3
 *
4
 * Copyright (C) 2005, 2007-2012 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 <stdio.h>
K
Karel Zak 已提交
29 30 31
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
32
#include <unistd.h>
33
#include <errno.h>
K
Karel Zak 已提交
34
#include <getopt.h>
K
Karel Zak 已提交
35
#include <sys/time.h>
J
Jim Meyering 已提交
36
#include "c-ctype.h"
37
#include <fcntl.h>
38
#include <locale.h>
39
#include <time.h>
40
#include <limits.h>
41
#include <assert.h>
42
#include <sys/stat.h>
43
#include <inttypes.h>
E
Eric Blake 已提交
44
#include <strings.h>
45
#include <termios.h>
K
Karel Zak 已提交
46

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

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

57
#include "internal.h"
58
#include "virterror_internal.h"
59
#include "base64.h"
60
#include "buf.h"
61
#include "console.h"
62
#include "util.h"
63
#include "memory.h"
64
#include "xml.h"
65
#include "libvirt/libvirt-qemu.h"
E
Eric Blake 已提交
66
#include "virfile.h"
67
#include "event_poll.h"
68
#include "configmake.h"
69
#include "threads.h"
E
Eric Blake 已提交
70
#include "command.h"
71
#include "virkeycode.h"
72
#include "virnetdevbandwidth.h"
73
#include "util/bitmap.h"
H
Hu Tao 已提交
74
#include "conf/domain_conf.h"
75
#include "virtypedparam.h"
K
Karel Zak 已提交
76

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

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

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

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

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

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

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

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

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

    if (s == NULL)
128
        return NULL;
E
Eric Blake 已提交
129 130 131 132 133 134 135 136 137
    if ((x = strdup(s)))
        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
138

139
int
140 141 142 143
vshNameSorter(const void *a, const void *b)
{
    const char **sa = (const char**)a;
    const char **sb = (const char**)b;
144

145
    return vshStrcasecmp(*sa, *sb);
146 147
}

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

169 170 171 172 173 174 175 176
/*
 * Convert the strings separated by ',' into array. The caller
 * must free the returned array after use.
 *
 * Returns the length of the filled array on success, or -1
 * on error.
 */
int
177
vshStringToArray(const char *str,
178 179
                 char ***array)
{
180
    char *str_copied = vshStrdup(NULL, str);
181 182 183 184 185
    char *str_tok = NULL;
    unsigned int nstr_tokens = 0;
    char **arr = NULL;

    /* tokenize the string from user and save it's parts into an array */
186
    if (str_copied) {
187 188 189
        nstr_tokens = 1;

        /* count the delimiters */
190
        str_tok = str_copied;
191 192 193 194 195 196 197 198
        while (*str_tok) {
            if (*str_tok == ',')
                nstr_tokens++;
            str_tok++;
        }

        if (VIR_ALLOC_N(arr, nstr_tokens) < 0) {
            virReportOOMError();
199
            VIR_FREE(str_copied);
200 201 202 203 204
            return -1;
        }

        /* tokenize the input string */
        nstr_tokens = 0;
205
        str_tok = str_copied;
206 207 208 209 210 211 212 213 214
        do {
            arr[nstr_tokens] = strsep(&str_tok, ",");
            nstr_tokens++;
        } while (str_tok);
    }

    *array = arr;
    return nstr_tokens;
}
215

E
Eric Blake 已提交
216
virErrorPtr last_error;
J
John Levon 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229

/*
 * 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);
}

230 231 232
/*
 * Reset libvirt error on graceful fallback paths
 */
E
Eric Blake 已提交
233
void
234 235 236 237 238 239
vshResetLibvirtError(void)
{
    virFreeError(last_error);
    last_error = NULL;
}

J
John Levon 已提交
240 241 242 243 244 245 246 247
/*
 * 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 已提交
248
void
E
Eric Blake 已提交
249
vshReportError(vshControl *ctl)
J
John Levon 已提交
250
{
251 252 253 254 255 256 257 258
    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)
259
            goto out;
260
    }
J
John Levon 已提交
261 262

    if (last_error->code == VIR_ERR_OK) {
263
        vshError(ctl, "%s", _("unknown error"));
J
John Levon 已提交
264 265 266
        goto out;
    }

267
    vshError(ctl, "%s", last_error->message);
J
John Levon 已提交
268 269

out:
270
    vshResetLibvirtError();
J
John Levon 已提交
271 272
}

273 274 275 276 277 278 279 280
/*
 * Detection of disconnections and automatic reconnection support
 */
static int disconnected = 0; /* we may have been disconnected */

/*
 * vshCatchDisconnect:
 *
281 282
 * We get here when the connection was closed.  We can't do much in the
 * handler, just save the fact it was raised.
283
 */
L
Laine Stump 已提交
284
static void
285 286 287 288 289 290
vshCatchDisconnect(virConnectPtr conn ATTRIBUTE_UNUSED,
                   int reason,
                   void *opaque ATTRIBUTE_UNUSED)
{
    if (reason != VIR_CONNECT_CLOSE_REASON_CLIENT)
        disconnected++;
291 292 293 294 295
}

/*
 * vshReconnect:
 *
L
Laine Stump 已提交
296
 * Reconnect after a disconnect from libvirtd
297 298
 *
 */
L
Laine Stump 已提交
299
static void
300 301 302 303 304 305
vshReconnect(vshControl *ctl)
{
    bool connected = false;

    if (ctl->conn != NULL) {
        connected = true;
306
        virConnectClose(ctl->conn);
307
    }
308 309 310 311

    ctl->conn = virConnectOpenAuth(ctl->name,
                                   virConnectAuthPtrDefault,
                                   ctl->readonly ? VIR_CONNECT_RO : 0);
312
    if (!ctl->conn) {
313
        vshError(ctl, "%s", _("Failed to reconnect to the hypervisor"));
314 315 316 317 318 319 320
    } 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"));
    }
321
    disconnected = 0;
322
    ctl->useGetInfo = false;
323
    ctl->useSnapshotOld = false;
324
}
325

326
#ifndef WIN32
327 328 329 330 331 332 333 334 335 336 337 338 339
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);
}

340 341 342 343 344 345 346 347 348 349 350 351 352
/**
 * 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 已提交
353
int
354 355 356 357 358 359 360 361
vshAskReedit(vshControl *ctl, const char *msg)
{
    int c = -1;
    struct termios ttyattr;

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

E
Eric Blake 已提交
362
    vshReportError(ctl);
363 364 365 366 367 368 369 370 371 372 373

    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 == '?') {
374 375 376 377 378 379 380
            vshPrintRaw(ctl,
                        "",
                        _("y - yes, start editor again"),
                        _("n - no, throw away my changes"),
                        _("f - force, try to redefine again"),
                        _("? - print this help"),
                        NULL);
381 382 383 384 385 386 387 388 389 390
            continue;
        } else if (c == 'y' || c == 'n' || c == 'f') {
            break;
        }
    }

    tcsetattr(STDIN_FILENO, TCSAFLUSH, &ttyattr);

    vshPrint(ctl, "\r\n");
    return c;
391 392
}
#else /* WIN32 */
393
int
394 395
vshAskReedit(vshControl *ctl, const char *msg ATTRIBUTE_UNUSED)
{
396 397 398 399
    vshDebug(ctl, VSH_ERR_WARNING, "%s", _("This function is not "
                                           "supported on WIN32 platform"));
    return 0;
}
400
#endif /* WIN32 */
401

E
Eric Blake 已提交
402 403
int vshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED,
                  const char *bytes, size_t nbytes, void *opaque)
404 405 406 407 408 409
{
    int *fd = opaque;

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

K
Karel Zak 已提交
410 411 412 413 414 415
/* ---------------
 * Commands
 * ---------------
 */

/*
416
 * "help" command
K
Karel Zak 已提交
417
 */
418
static const vshCmdInfo info_help[] = {
419
    {"help", N_("print help")},
420 421
    {"desc", N_("Prints global help, command specific help, or help for a\n"
                "    group of related commands")},
422

423
    {NULL, NULL}
K
Karel Zak 已提交
424 425
};

426
static const vshCmdOptDef opts_help[] = {
427
    {"command", VSH_OT_DATA, 0, N_("Prints global help, command specific help, or help for a group of related commands")},
428
    {NULL, 0, 0, NULL}
K
Karel Zak 已提交
429 430
};

E
Eric Blake 已提交
431
static bool
432
cmdHelp(vshControl *ctl, const vshCmd *cmd)
433
 {
434
    const char *name = NULL;
435

436
    if (vshCommandOptString(cmd, "command", &name) <= 0) {
437
        const vshCmdGrp *grp;
438
        const vshCmdDef *def;
439

440 441 442 443 444 445
        vshPrint(ctl, "%s", _("Grouped commands:\n\n"));

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

446 447 448
            for (def = grp->commands; def->name; def++) {
                if (def->flags & VSH_CMD_FLAG_ALIAS)
                    continue;
449 450
                vshPrint(ctl, "    %-30s %s\n", def->name,
                         _(vshCmddefGetInfo(def, "help")));
451
            }
452 453 454 455

            vshPrint(ctl, "\n");
        }

E
Eric Blake 已提交
456
        return true;
457
    }
458

E
Eric Blake 已提交
459
    if (vshCmddefSearch(name)) {
460
        return vshCmddefHelp(ctl, name);
E
Eric Blake 已提交
461
    } else if (vshCmdGrpSearch(name)) {
462 463 464
        return vshCmdGrpHelp(ctl, name);
    } else {
        vshError(ctl, _("command or command group '%s' doesn't exist"), name);
E
Eric Blake 已提交
465
        return false;
K
Karel Zak 已提交
466 467 468
    }
}

469 470 471 472 473 474 475 476 477 478 479
/* Tree listing helpers.  */

static int
vshTreePrintInternal(vshControl *ctl,
                     vshTreeLookup lookup,
                     void *opaque,
                     int num_devices,
                     int devid,
                     int lastdev,
                     bool root,
                     virBufferPtr indent)
480
{
481 482 483 484
    int i;
    int nextlastdev = -1;
    int ret = -1;
    const char *dev = (lookup)(devid, false, opaque);
485

486
    if (virBufferError(indent))
487 488
        goto cleanup;

489 490 491 492 493 494 495 496 497 498
    /* 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;
499 500
    }

501 502 503
    /* Determine the index of the last child device */
    for (i = 0 ; i < num_devices ; i++) {
        const char *parent = (lookup)(i, true, opaque);
504

505 506 507
        if (parent && STREQ(parent, dev))
            nextlastdev = i;
    }
508

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

513 514 515 516
    /* Finally print all children */
    virBufferAddLit(indent, "  ");
    for (i = 0 ; i < num_devices ; i++) {
        const char *parent = (lookup)(i, true, opaque);
517

518 519 520 521 522
        if (parent && STREQ(parent, dev) &&
            vshTreePrintInternal(ctl, lookup, opaque,
                                 num_devices, i, nextlastdev,
                                 false, indent) < 0)
            goto cleanup;
523
    }
524
    virBufferTrim(indent, "  ", -1);
525

526 527 528 529
    /* 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));
530

531 532 533
    if (!root)
        virBufferTrim(indent, NULL, 2);
    ret = 0;
534 535 536 537
cleanup:
    return ret;
}

E
Eric Blake 已提交
538
int
539 540
vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque,
             int num_devices, int devid)
541
{
542 543
    int ret;
    virBuffer indent = VIR_BUFFER_INITIALIZER;
544

545 546 547 548 549
    ret = vshTreePrintInternal(ctl, lookup, opaque, num_devices,
                               devid, devid, true, &indent);
    if (ret < 0)
        vshError(ctl, "%s", _("Failed to complete tree listing"));
    virBufferFreeAndReset(&indent);
550
    return ret;
551
}
552

553
/* Common code for the edit / net-edit / pool-edit functions which follow. */
E
Eric Blake 已提交
554
char *
E
Eric Blake 已提交
555
vshEditWriteToTempFile(vshControl *ctl, const char *doc)
556 557 558 559
{
    char *ret;
    const char *tmpdir;
    int fd;
560
    char ebuf[1024];
561 562 563

    tmpdir = getenv ("TMPDIR");
    if (!tmpdir) tmpdir = "/tmp";
564 565 566 567
    if (virAsprintf(&ret, "%s/virshXXXXXX.xml", tmpdir) < 0) {
        vshError(ctl, "%s", _("out of memory"));
        return NULL;
    }
568
    fd = mkostemps(ret, 4, O_CLOEXEC);
569
    if (fd == -1) {
570
        vshError(ctl, _("mkostemps: failed to create temporary file: %s"),
571
                 virStrerror(errno, ebuf, sizeof(ebuf)));
572
        VIR_FREE(ret);
573 574 575
        return NULL;
    }

576
    if (safewrite(fd, doc, strlen(doc)) == -1) {
577
        vshError(ctl, _("write: %s: failed to write to temporary file: %s"),
578
                 ret, virStrerror(errno, ebuf, sizeof(ebuf)));
S
Stefan Berger 已提交
579
        VIR_FORCE_CLOSE(fd);
580
        unlink(ret);
581
        VIR_FREE(ret);
582 583
        return NULL;
    }
S
Stefan Berger 已提交
584
    if (VIR_CLOSE(fd) < 0) {
585
        vshError(ctl, _("close: %s: failed to write or close temporary file: %s"),
586
                 ret, virStrerror(errno, ebuf, sizeof(ebuf)));
587
        unlink(ret);
588
        VIR_FREE(ret);
589 590 591 592 593 594 595 596 597 598 599
        return NULL;
    }

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

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

E
Eric Blake 已提交
600
int
E
Eric Blake 已提交
601
vshEditFile(vshControl *ctl, const char *filename)
602 603
{
    const char *editor;
E
Eric Blake 已提交
604 605 606 607
    virCommandPtr cmd;
    int ret = -1;
    int outfd = STDOUT_FILENO;
    int errfd = STDERR_FILENO;
608

609
    editor = getenv("VISUAL");
E
Eric Blake 已提交
610
    if (!editor)
611
        editor = getenv("EDITOR");
E
Eric Blake 已提交
612 613
    if (!editor)
        editor = "vi"; /* could be cruel & default to ed(1) here */
614

615 616 617 618 619
    /* 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 已提交
620 621
     * is why sudo scrubs it by default).  Conversely, if the editor
     * is safe, we can run it directly rather than wasting a shell.
622
     */
623 624
    if (strspn(editor, ACCEPTED_CHARS) != strlen(editor)) {
        if (strspn(filename, ACCEPTED_CHARS) != strlen(filename)) {
E
Eric Blake 已提交
625 626 627 628 629 630 631 632 633 634
            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);
635 636
    }

E
Eric Blake 已提交
637 638 639 640 641
    virCommandSetInputFD(cmd, STDIN_FILENO);
    virCommandSetOutputFD(cmd, &outfd);
    virCommandSetErrorFD(cmd, &errfd);
    if (virCommandRunAsync(cmd, NULL) < 0 ||
        virCommandWait(cmd, NULL) < 0) {
E
Eric Blake 已提交
642
        vshReportError(ctl);
E
Eric Blake 已提交
643
        goto cleanup;
644
    }
E
Eric Blake 已提交
645
    ret = 0;
646

E
Eric Blake 已提交
647 648 649
cleanup:
    virCommandFree(cmd);
    return ret;
650 651
}

E
Eric Blake 已提交
652
char *
E
Eric Blake 已提交
653
vshEditReadBackFile(vshControl *ctl, const char *filename)
654 655
{
    char *ret;
656
    char ebuf[1024];
657

E
Eric Blake 已提交
658
    if (virFileReadAll(filename, VSH_MAX_XML_FILE, &ret) == -1) {
659
        vshError(ctl,
660
                 _("%s: failed to read temporary file: %s"),
661
                 filename, virStrerror(errno, ebuf, sizeof(ebuf)));
662 663 664 665 666
        return NULL;
    }
    return ret;
}

667

P
Paolo Bonzini 已提交
668 669 670 671
/*
 * "cd" command
 */
static const vshCmdInfo info_cd[] = {
672 673
    {"help", N_("change the current directory")},
    {"desc", N_("Change the current directory.")},
P
Paolo Bonzini 已提交
674 675 676 677
    {NULL, NULL}
};

static const vshCmdOptDef opts_cd[] = {
678
    {"dir", VSH_OT_DATA, 0, N_("directory to switch to (default: home or else root)")},
P
Paolo Bonzini 已提交
679 680 681
    {NULL, 0, 0, NULL}
};

E
Eric Blake 已提交
682
static bool
683
cmdCd(vshControl *ctl, const vshCmd *cmd)
P
Paolo Bonzini 已提交
684
{
685
    const char *dir = NULL;
686
    char *dir_malloced = NULL;
E
Eric Blake 已提交
687
    bool ret = true;
688
    char ebuf[1024];
P
Paolo Bonzini 已提交
689 690

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

695
    if (vshCommandOptString(cmd, "dir", &dir) <= 0) {
696
        dir = dir_malloced = virGetUserDirectory();
P
Paolo Bonzini 已提交
697 698 699 700
    }
    if (!dir)
        dir = "/";

P
Phil Petty 已提交
701
    if (chdir(dir) == -1) {
702 703
        vshError(ctl, _("cd: %s: %s"),
                 virStrerror(errno, ebuf, sizeof(ebuf)), dir);
E
Eric Blake 已提交
704
        ret = false;
P
Paolo Bonzini 已提交
705 706
    }

707
    VIR_FREE(dir_malloced);
P
Phil Petty 已提交
708
    return ret;
P
Paolo Bonzini 已提交
709 710 711 712 713 714
}

/*
 * "pwd" command
 */
static const vshCmdInfo info_pwd[] = {
715 716
    {"help", N_("print the current directory")},
    {"desc", N_("Print the current directory.")},
P
Paolo Bonzini 已提交
717 718 719
    {NULL, NULL}
};

E
Eric Blake 已提交
720
static bool
P
Paolo Bonzini 已提交
721 722 723
cmdPwd(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
    char *cwd;
724
    bool ret = true;
725
    char ebuf[1024];
P
Paolo Bonzini 已提交
726

727 728
    cwd = getcwd(NULL, 0);
    if (!cwd) {
729
        vshError(ctl, _("pwd: cannot get current directory: %s"),
730
                 virStrerror(errno, ebuf, sizeof(ebuf)));
731 732
        ret = false;
    } else {
733
        vshPrint(ctl, _("%s\n"), cwd);
734 735
        VIR_FREE(cwd);
    }
P
Paolo Bonzini 已提交
736

737
    return ret;
P
Paolo Bonzini 已提交
738 739
}

E
Eric Blake 已提交
740 741 742 743 744 745 746 747 748 749 750 751
/*
 * "echo" command
 */
static const vshCmdInfo info_echo[] = {
    {"help", N_("echo arguments")},
    {"desc", N_("Echo back arguments, possibly with quoting.")},
    {NULL, NULL}
};

static const vshCmdOptDef opts_echo[] = {
    {"shell", VSH_OT_BOOL, 0, N_("escape for shell use")},
    {"xml", VSH_OT_BOOL, 0, N_("escape for XML use")},
E
Eric Blake 已提交
752
    {"str", VSH_OT_ALIAS, 0, "string"},
753
    {"string", VSH_OT_ARGV, 0, N_("arguments to echo")},
E
Eric Blake 已提交
754 755 756 757 758 759
    {NULL, 0, 0, NULL}
};

/* Exists mainly for debugging virsh, but also handy for adding back
 * quotes for later evaluation.
 */
E
Eric Blake 已提交
760
static bool
761
cmdEcho(vshControl *ctl, const vshCmd *cmd)
E
Eric Blake 已提交
762 763 764 765
{
    bool shell = false;
    bool xml = false;
    int count = 0;
766
    const vshCmdOpt *opt = NULL;
E
Eric Blake 已提交
767 768 769 770 771 772 773 774
    char *arg;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

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

775
    while ((opt = vshCommandOptArgv(cmd, opt))) {
776 777
        char *str;
        virBuffer xmlbuf = VIR_BUFFER_INITIALIZER;
E
Eric Blake 已提交
778

779
        arg = opt->data;
780

E
Eric Blake 已提交
781 782
        if (count)
            virBufferAddChar(&buf, ' ');
783

E
Eric Blake 已提交
784
        if (xml) {
785 786 787 788
            virBufferEscapeString(&xmlbuf, "%s", arg);
            if (virBufferError(&buf)) {
                vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
                return false;
E
Eric Blake 已提交
789
            }
790 791 792
            str = virBufferContentAndReset(&xmlbuf);
        } else {
            str = vshStrdup(ctl, arg);
E
Eric Blake 已提交
793
        }
794 795 796 797 798

        if (shell)
            virBufferEscapeShell(&buf, str);
        else
            virBufferAdd(&buf, str, -1);
E
Eric Blake 已提交
799
        count++;
800
        VIR_FREE(str);
E
Eric Blake 已提交
801 802 803 804
    }

    if (virBufferError(&buf)) {
        vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
E
Eric Blake 已提交
805
        return false;
E
Eric Blake 已提交
806 807 808 809 810
    }
    arg = virBufferContentAndReset(&buf);
    if (arg)
        vshPrint(ctl, "%s", arg);
    VIR_FREE(arg);
E
Eric Blake 已提交
811
    return true;
E
Eric Blake 已提交
812 813
}

K
Karel Zak 已提交
814 815 816
/*
 * "quit" command
 */
817
static const vshCmdInfo info_quit[] = {
818
    {"help", N_("quit this interactive terminal")},
819
    {"desc", ""},
820
    {NULL, NULL}
K
Karel Zak 已提交
821 822
};

E
Eric Blake 已提交
823
static bool
824
cmdQuit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
825
{
E
Eric Blake 已提交
826 827
    ctl->imode = false;
    return true;
K
Karel Zak 已提交
828 829
}

830 831 832 833
/* ---------------
 * Utils for work with command definition
 * ---------------
 */
E
Eric Blake 已提交
834
const char *
835 836 837
vshCmddefGetInfo(const vshCmdDef * cmd, const char *name)
{
    const vshCmdInfo *info;
838

839 840 841 842 843 844
    for (info = cmd->info; info && info->name; info++) {
        if (STREQ(info->name, name))
            return info->data;
    }
    return NULL;
}
845

846 847 848 849 850 851 852
/* 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)
{
    int i;
    bool optional = false;
853

854 855
    *opts_need_arg = 0;
    *opts_required = 0;
856

857 858
    if (!cmd->opts)
        return 0;
859

860 861
    for (i = 0; cmd->opts[i].name; i++) {
        const vshCmdOptDef *opt = &cmd->opts[i];
862 863 864 865

        if (i > 31)
            return -1; /* too many options */
        if (opt->type == VSH_OT_BOOL) {
E
Eric Blake 已提交
866
            if (opt->flags & VSH_OFLAG_REQ)
867 868 869
                return -1; /* bool options can't be mandatory */
            continue;
        }
E
Eric Blake 已提交
870 871 872 873 874 875 876 877 878 879 880 881
        if (opt->type == VSH_OT_ALIAS) {
            int j;
            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 已提交
882 883
        if (opt->flags & VSH_OFLAG_REQ_OPT) {
            if (opt->flags & VSH_OFLAG_REQ)
L
Lai Jiangshan 已提交
884 885 886 887
                *opts_required |= 1 << i;
            continue;
        }

888
        *opts_need_arg |= 1 << i;
E
Eric Blake 已提交
889
        if (opt->flags & VSH_OFLAG_REQ) {
890 891 892 893 894 895
            if (optional)
                return -1; /* mandatory options must be listed first */
            *opts_required |= 1 << i;
        } else {
            optional = true;
        }
896 897 898

        if (opt->type == VSH_OT_ARGV && cmd->opts[i + 1].name)
            return -1; /* argv option must be listed last */
899 900 901 902
    }
    return 0;
}

903 904
static vshCmdOptDef helpopt = {"help", VSH_OT_BOOL, 0,
                               N_("print help for this function")};
905
static const vshCmdOptDef *
906
vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name,
907
                   uint32_t *opts_seen, int *opt_index)
908
{
909 910
    int i;

911 912 913 914
    if (STREQ(name, helpopt.name)) {
        return &helpopt;
    }

915 916
    for (i = 0; cmd->opts && cmd->opts[i].name; i++) {
        const vshCmdOptDef *opt = &cmd->opts[i];
917

918
        if (STREQ(opt->name, name)) {
E
Eric Blake 已提交
919 920 921 922
            if (opt->type == VSH_OT_ALIAS) {
                name = opt->help;
                continue;
            }
923
            if ((*opts_seen & (1 << i)) && opt->type != VSH_OT_ARGV) {
924 925 926
                vshError(ctl, _("option --%s already seen"), name);
                return NULL;
            }
927 928
            *opts_seen |= 1 << i;
            *opt_index = i;
K
Karel Zak 已提交
929
            return opt;
930 931 932
        }
    }

933 934 935 936
    if (STRNEQ(cmd->name, "help")) {
        vshError(ctl, _("command '%s' doesn't support option --%s"),
                 cmd->name, name);
    }
K
Karel Zak 已提交
937 938 939
    return NULL;
}

940
static const vshCmdOptDef *
941 942
vshCmddefGetData(const vshCmdDef *cmd, uint32_t *opts_need_arg,
                 uint32_t *opts_seen)
943
{
944
    int i;
945
    const vshCmdOptDef *opt;
K
Karel Zak 已提交
946

947 948 949 950
    if (!*opts_need_arg)
        return NULL;

    /* Grab least-significant set bit */
E
Eric Blake 已提交
951
    i = ffs(*opts_need_arg) - 1;
952
    opt = &cmd->opts[i];
953
    if (opt->type != VSH_OT_ARGV)
954
        *opts_need_arg &= ~(1 << i);
955
    *opts_seen |= 1 << i;
956
    return opt;
K
Karel Zak 已提交
957 958
}

959 960 961
/*
 * Checks for required options
 */
962
static int
963 964
vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd, uint32_t opts_required,
                    uint32_t opts_seen)
965
{
966
    const vshCmdDef *def = cmd->def;
967 968 969 970 971 972 973 974 975
    int i;

    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];
976

977
            vshError(ctl,
978
                     opt->type == VSH_OT_DATA || opt->type == VSH_OT_ARGV ?
979 980 981
                     _("command '%s' requires <%s> option") :
                     _("command '%s' requires --%s option"),
                     def->name, opt->name);
982 983
        }
    }
984
    return -1;
985 986
}

E
Eric Blake 已提交
987
const vshCmdDef *
988 989
vshCmddefSearch(const char *cmdname)
{
990
    const vshCmdGrp *g;
991
    const vshCmdDef *c;
992

993 994
    for (g = cmdGroups; g->name; g++) {
        for (c = g->commands; c->name; c++) {
995
            if (STREQ(c->name, cmdname))
996 997 998 999
                return c;
        }
    }

K
Karel Zak 已提交
1000 1001 1002
    return NULL;
}

E
Eric Blake 已提交
1003
const vshCmdGrp *
1004 1005 1006 1007 1008
vshCmdGrpSearch(const char *grpname)
{
    const vshCmdGrp *g;

    for (g = cmdGroups; g->name; g++) {
1009
        if (STREQ(g->name, grpname) || STREQ(g->keyword, grpname))
1010 1011 1012 1013 1014 1015
            return g;
    }

    return NULL;
}

E
Eric Blake 已提交
1016
bool
1017 1018 1019 1020 1021 1022 1023
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 已提交
1024
        return false;
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
    } else {
        vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name,
                 grp->keyword);

        for (cmd = grp->commands; cmd->name; cmd++) {
            vshPrint(ctl, "    %-30s %s\n", cmd->name,
                     _(vshCmddefGetInfo(cmd, "help")));
        }
    }

E
Eric Blake 已提交
1035
    return true;
1036 1037
}

E
Eric Blake 已提交
1038
bool
1039
vshCmddefHelp(vshControl *ctl, const char *cmdname)
1040
{
1041
    const vshCmdDef *def = vshCmddefSearch(cmdname);
1042

K
Karel Zak 已提交
1043
    if (!def) {
1044
        vshError(ctl, _("command '%s' doesn't exist"), cmdname);
E
Eric Blake 已提交
1045
        return false;
1046
    } else {
E
Eric Blake 已提交
1047 1048
        /* Don't translate desc if it is "".  */
        const char *desc = vshCmddefGetInfo(def, "desc");
E
Eric Blake 已提交
1049
        const char *help = _(vshCmddefGetInfo(def, "help"));
1050
        char buf[256];
1051 1052
        uint32_t opts_need_arg;
        uint32_t opts_required;
1053
        bool shortopt = false; /* true if 'arg' works instead of '--opt arg' */
1054 1055 1056 1057

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

1061
        fputs(_("  NAME\n"), stdout);
1062 1063
        fprintf(stdout, "    %s - %s\n", def->name, help);

1064 1065 1066 1067 1068
        fputs(_("\n  SYNOPSIS\n"), stdout);
        fprintf(stdout, "    %s", def->name);
        if (def->opts) {
            const vshCmdOptDef *opt;
            for (opt = def->opts; opt->name; opt++) {
1069
                const char *fmt = "%s";
1070 1071
                switch (opt->type) {
                case VSH_OT_BOOL:
1072
                    fmt = "[--%s]";
1073 1074
                    break;
                case VSH_OT_INT:
E
Eric Blake 已提交
1075
                    /* xgettext:c-format */
E
Eric Blake 已提交
1076
                    fmt = ((opt->flags & VSH_OFLAG_REQ) ? "<%s>"
1077
                           : _("[--%s <number>]"));
1078 1079
                    if (!(opt->flags & VSH_OFLAG_REQ_OPT))
                        shortopt = true;
1080 1081
                    break;
                case VSH_OT_STRING:
E
Eric Blake 已提交
1082 1083
                    /* xgettext:c-format */
                    fmt = _("[--%s <string>]");
1084 1085
                    if (!(opt->flags & VSH_OFLAG_REQ_OPT))
                        shortopt = true;
1086 1087
                    break;
                case VSH_OT_DATA:
E
Eric Blake 已提交
1088
                    fmt = ((opt->flags & VSH_OFLAG_REQ) ? "<%s>" : "[<%s>]");
1089 1090
                    if (!(opt->flags & VSH_OFLAG_REQ_OPT))
                        shortopt = true;
1091 1092 1093
                    break;
                case VSH_OT_ARGV:
                    /* xgettext:c-format */
1094 1095 1096 1097 1098 1099 1100 1101
                    if (shortopt) {
                        fmt = (opt->flags & VSH_OFLAG_REQ)
                            ? _("{[--%s] <string>}...")
                            : _("[[--%s] <string>]...");
                    } else {
                        fmt = (opt->flags & VSH_OFLAG_REQ) ? _("<%s>...")
                            : _("[<%s>]...");
                    }
1102
                    break;
E
Eric Blake 已提交
1103 1104 1105
                case VSH_OT_ALIAS:
                    /* aliases are intentionally undocumented */
                    continue;
1106
                default:
1107
                    assert(0);
1108
                }
1109
                fputc(' ', stdout);
E
Eric Blake 已提交
1110
                fprintf(stdout, fmt, opt->name);
1111
            }
K
Karel Zak 已提交
1112
        }
1113 1114 1115
        fputc('\n', stdout);

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

K
Karel Zak 已提交
1121
        if (def->opts) {
1122
            const vshCmdOptDef *opt;
1123
            fputs(_("\n  OPTIONS\n"), stdout);
1124
            for (opt = def->opts; opt->name; opt++) {
1125 1126
                switch (opt->type) {
                case VSH_OT_BOOL:
K
Karel Zak 已提交
1127
                    snprintf(buf, sizeof(buf), "--%s", opt->name);
1128 1129
                    break;
                case VSH_OT_INT:
1130
                    snprintf(buf, sizeof(buf),
E
Eric Blake 已提交
1131
                             (opt->flags & VSH_OFLAG_REQ) ? _("[--%s] <number>")
1132
                             : _("--%s <number>"), opt->name);
1133 1134
                    break;
                case VSH_OT_STRING:
1135
                    /* OT_STRING should never be VSH_OFLAG_REQ */
1136
                    snprintf(buf, sizeof(buf), _("--%s <string>"), opt->name);
1137 1138
                    break;
                case VSH_OT_DATA:
1139 1140
                    snprintf(buf, sizeof(buf), _("[--%s] <string>"),
                             opt->name);
1141 1142
                    break;
                case VSH_OT_ARGV:
1143 1144 1145
                    snprintf(buf, sizeof(buf),
                             shortopt ? _("[--%s] <string>") : _("<%s>"),
                             opt->name);
1146
                    break;
E
Eric Blake 已提交
1147 1148
                case VSH_OT_ALIAS:
                    continue;
1149 1150 1151
                default:
                    assert(0);
                }
1152

E
Eric Blake 已提交
1153
                fprintf(stdout, "    %-15s  %s\n", buf, _(opt->help));
1154
            }
K
Karel Zak 已提交
1155 1156 1157
        }
        fputc('\n', stdout);
    }
E
Eric Blake 已提交
1158
    return true;
K
Karel Zak 已提交
1159 1160 1161 1162 1163 1164
}

/* ---------------
 * Utils for work with runtime commands data
 * ---------------
 */
1165 1166 1167
static void
vshCommandOptFree(vshCmdOpt * arg)
{
K
Karel Zak 已提交
1168 1169
    vshCmdOpt *a = arg;

1170
    while (a) {
K
Karel Zak 已提交
1171
        vshCmdOpt *tmp = a;
1172

K
Karel Zak 已提交
1173 1174
        a = a->next;

1175 1176
        VIR_FREE(tmp->data);
        VIR_FREE(tmp);
K
Karel Zak 已提交
1177 1178 1179 1180
    }
}

static void
1181
vshCommandFree(vshCmd *cmd)
1182
{
K
Karel Zak 已提交
1183 1184
    vshCmd *c = cmd;

1185
    while (c) {
K
Karel Zak 已提交
1186
        vshCmd *tmp = c;
1187

K
Karel Zak 已提交
1188 1189 1190 1191
        c = c->next;

        if (tmp->opts)
            vshCommandOptFree(tmp->opts);
1192
        VIR_FREE(tmp);
K
Karel Zak 已提交
1193 1194 1195
    }
}

E
Eric Blake 已提交
1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
/**
 * vshCommandOpt:
 * @cmd: parsed command line to search
 * @name: option name to search for
 * @opt: result of the search
 *
 * 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
 * the option is required but not present, and -2 if NAME is not valid
 * (-2 indicates a programming error).  No error messages are issued.
K
Karel Zak 已提交
1207
 */
E
Eric Blake 已提交
1208
int
E
Eric Blake 已提交
1209
vshCommandOpt(const vshCmd *cmd, const char *name, vshCmdOpt **opt)
1210
{
E
Eric Blake 已提交
1211 1212
    vshCmdOpt *candidate = cmd->opts;
    const vshCmdOptDef *valid = cmd->def->opts;
1213

E
Eric Blake 已提交
1214 1215 1216 1217 1218 1219 1220
    /* See if option is present on command line.  */
    while (candidate) {
        if (STREQ(candidate->def->name, name)) {
            *opt = candidate;
            return 1;
        }
        candidate = candidate->next;
K
Karel Zak 已提交
1221
    }
E
Eric Blake 已提交
1222 1223 1224 1225 1226 1227 1228

    /* Option not present, see if command requires it.  */
    *opt = NULL;
    while (valid) {
        if (!valid->name)
            break;
        if (STREQ(name, valid->name))
E
Eric Blake 已提交
1229
            return (valid->flags & VSH_OFLAG_REQ) == 0 ? 0 : -1;
E
Eric Blake 已提交
1230 1231 1232 1233
        valid++;
    }
    /* If we got here, the name is unknown.  */
    return -2;
K
Karel Zak 已提交
1234 1235
}

E
Eric Blake 已提交
1236 1237
/**
 * vshCommandOptInt:
1238 1239 1240 1241 1242 1243 1244
 * @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 已提交
1245
 * 0 if option not found and not required (@value untouched)
1246
 * <0 in all other cases (@value untouched)
K
Karel Zak 已提交
1247
 */
E
Eric Blake 已提交
1248
int
1249
vshCommandOptInt(const vshCmd *cmd, const char *name, int *value)
1250
{
E
Eric Blake 已提交
1251 1252
    vshCmdOpt *arg;
    int ret;
1253

E
Eric Blake 已提交
1254 1255 1256 1257 1258 1259 1260
    ret = vshCommandOpt(cmd, name, &arg);
    if (ret <= 0)
        return ret;
    if (!arg->data) {
        /* only possible on bool, but if name is bool, this is a
         * programming bug */
        return -2;
1261
    }
E
Eric Blake 已提交
1262

E
Eric Blake 已提交
1263 1264 1265
    if (virStrToLong_i(arg->data, NULL, 10, value) < 0)
        return -1;
    return 1;
K
Karel Zak 已提交
1266 1267
}

1268

E
Eric Blake 已提交
1269 1270 1271 1272 1273 1274
/**
 * vshCommandOptUInt:
 * @cmd command reference
 * @name option name
 * @value result
 *
1275 1276 1277
 * Convert option to unsigned int
 * See vshCommandOptInt()
 */
E
Eric Blake 已提交
1278
int
1279 1280
vshCommandOptUInt(const vshCmd *cmd, const char *name, unsigned int *value)
{
E
Eric Blake 已提交
1281 1282
    vshCmdOpt *arg;
    int ret;
1283

E
Eric Blake 已提交
1284 1285 1286 1287 1288 1289 1290
    ret = vshCommandOpt(cmd, name, &arg);
    if (ret <= 0)
        return ret;
    if (!arg->data) {
        /* only possible on bool, but if name is bool, this is a
         * programming bug */
        return -2;
1291
    }
E
Eric Blake 已提交
1292

E
Eric Blake 已提交
1293 1294 1295
    if (virStrToLong_ui(arg->data, NULL, 10, value) < 0)
        return -1;
    return 1;
1296 1297 1298
}


1299
/*
E
Eric Blake 已提交
1300 1301 1302 1303 1304
 * vshCommandOptUL:
 * @cmd command reference
 * @name option name
 * @value result
 *
1305 1306 1307
 * Convert option to unsigned long
 * See vshCommandOptInt()
 */
E
Eric Blake 已提交
1308
int
1309
vshCommandOptUL(const vshCmd *cmd, const char *name, unsigned long *value)
1310
{
E
Eric Blake 已提交
1311 1312
    vshCmdOpt *arg;
    int ret;
1313

E
Eric Blake 已提交
1314 1315 1316 1317 1318 1319 1320
    ret = vshCommandOpt(cmd, name, &arg);
    if (ret <= 0)
        return ret;
    if (!arg->data) {
        /* only possible on bool, but if name is bool, this is a
         * programming bug */
        return -2;
1321
    }
E
Eric Blake 已提交
1322

E
Eric Blake 已提交
1323 1324 1325
    if (virStrToLong_ul(arg->data, NULL, 10, value) < 0)
        return -1;
    return 1;
1326 1327
}

E
Eric Blake 已提交
1328 1329 1330 1331 1332 1333
/**
 * vshCommandOptString:
 * @cmd command reference
 * @name option name
 * @value result
 *
K
Karel Zak 已提交
1334
 * Returns option as STRING
E
Eric Blake 已提交
1335 1336 1337 1338
 * 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 已提交
1339
 */
E
Eric Blake 已提交
1340
int
1341
vshCommandOptString(const vshCmd *cmd, const char *name, const char **value)
1342
{
E
Eric Blake 已提交
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352
    vshCmdOpt *arg;
    int ret;

    ret = vshCommandOpt(cmd, name, &arg);
    if (ret <= 0)
        return ret;
    if (!arg->data) {
        /* only possible on bool, but if name is bool, this is a
         * programming bug */
        return -2;
1353
    }
1354

E
Eric Blake 已提交
1355
    if (!*arg->data && !(arg->def->flags & VSH_OFLAG_EMPTY_OK)) {
E
Eric Blake 已提交
1356 1357 1358 1359
        return -1;
    }
    *value = arg->data;
    return 1;
K
Karel Zak 已提交
1360 1361
}

E
Eric Blake 已提交
1362 1363 1364 1365 1366 1367
/**
 * vshCommandOptLongLong:
 * @cmd command reference
 * @name option name
 * @value result
 *
1368
 * Returns option as long long
1369
 * See vshCommandOptInt()
1370
 */
E
Eric Blake 已提交
1371
int
1372 1373
vshCommandOptLongLong(const vshCmd *cmd, const char *name,
                      long long *value)
1374
{
E
Eric Blake 已提交
1375 1376
    vshCmdOpt *arg;
    int ret;
1377

E
Eric Blake 已提交
1378 1379 1380 1381 1382 1383 1384
    ret = vshCommandOpt(cmd, name, &arg);
    if (ret <= 0)
        return ret;
    if (!arg->data) {
        /* only possible on bool, but if name is bool, this is a
         * programming bug */
        return -2;
1385
    }
E
Eric Blake 已提交
1386

E
Eric Blake 已提交
1387 1388 1389
    if (virStrToLong_ll(arg->data, NULL, 10, value) < 0)
        return -1;
    return 1;
1390 1391
}

E
Eric Blake 已提交
1392 1393 1394 1395 1396 1397 1398 1399 1400
/**
 * vshCommandOptULongLong:
 * @cmd command reference
 * @name option name
 * @value result
 *
 * Returns option as long long
 * See vshCommandOptInt()
 */
E
Eric Blake 已提交
1401
int
1402 1403 1404
vshCommandOptULongLong(const vshCmd *cmd, const char *name,
                       unsigned long long *value)
{
E
Eric Blake 已提交
1405 1406
    vshCmdOpt *arg;
    int ret;
1407

E
Eric Blake 已提交
1408 1409 1410 1411 1412 1413 1414
    ret = vshCommandOpt(cmd, name, &arg);
    if (ret <= 0)
        return ret;
    if (!arg->data) {
        /* only possible on bool, but if name is bool, this is a
         * programming bug */
        return -2;
1415
    }
E
Eric Blake 已提交
1416

E
Eric Blake 已提交
1417 1418 1419
    if (virStrToLong_ull(arg->data, NULL, 10, value) < 0)
        return -1;
    return 1;
1420 1421 1422
}


E
Eric Blake 已提交
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433
/**
 * 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 已提交
1434
int
E
Eric Blake 已提交
1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452
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 已提交
1453 1454 1455 1456 1457 1458 1459 1460 1461
/**
 * 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 已提交
1462
 */
E
Eric Blake 已提交
1463
bool
1464
vshCommandOptBool(const vshCmd *cmd, const char *name)
1465
{
E
Eric Blake 已提交
1466 1467 1468
    vshCmdOpt *dummy;

    return vshCommandOpt(cmd, name, &dummy) == 1;
K
Karel Zak 已提交
1469 1470
}

E
Eric Blake 已提交
1471 1472 1473 1474 1475
/**
 * vshCommandOptArgv:
 * @cmd command reference
 * @opt starting point for the search
 *
1476 1477
 * Returns the next argv argument after OPT (or the first one if OPT
 * is NULL), or NULL if no more are present.
1478
 *
1479
 * Requires that a VSH_OT_ARGV option be last in the
1480 1481
 * list of supported options in CMD->def->opts.
 */
E
Eric Blake 已提交
1482
const vshCmdOpt *
1483
vshCommandOptArgv(const vshCmd *cmd, const vshCmdOpt *opt)
1484
{
1485
    opt = opt ? opt->next : cmd->opts;
1486 1487

    while (opt) {
E
Eric Blake 已提交
1488
        if (opt->def->type == VSH_OT_ARGV) {
1489
            return opt;
1490 1491 1492 1493 1494 1495
        }
        opt = opt->next;
    }
    return NULL;
}

J
Jim Meyering 已提交
1496 1497 1498
/* Determine whether CMD->opts includes an option with name OPTNAME.
   If not, give a diagnostic and return false.
   If so, return true.  */
1499 1500
bool
vshCmdHasOption(vshControl *ctl, const vshCmd *cmd, const char *optname)
J
Jim Meyering 已提交
1501 1502 1503 1504 1505 1506
{
    /* 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) {
1507
        if (STREQ(opt->def->name, optname) && opt->def->type == VSH_OT_DATA) {
J
Jim Meyering 已提交
1508 1509 1510 1511 1512 1513
            found = true;
            break;
        }
    }

    if (!found)
1514
        vshError(ctl, _("internal error: virsh %s: no %s VSH_OT_DATA option"),
J
Jim Meyering 已提交
1515 1516 1517
                 cmd->def->name, optname);
    return found;
}
1518

1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535
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 已提交
1536 1537 1538
/*
 * Executes command(s) and returns return code from last command
 */
E
Eric Blake 已提交
1539
static bool
1540
vshCommandRun(vshControl *ctl, const vshCmd *cmd)
1541
{
E
Eric Blake 已提交
1542
    bool ret = true;
1543 1544

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

1548 1549
        if ((ctl->conn == NULL || disconnected) &&
            !(cmd->def->flags & VSH_CMD_FLAG_NOCONNECT))
1550 1551
            vshReconnect(ctl);

1552 1553 1554 1555
        if ((cmd->def->flags & VSH_CMD_FLAG_NOCONNECT) ||
            vshConnectionUsability(ctl, ctl->conn)) {
            if (enable_timing)
                GETTIMEOFDAY(&before);
1556

1557
            ret = cmd->def->handler(ctl, cmd);
K
Karel Zak 已提交
1558

1559 1560 1561 1562 1563 1564
            if (enable_timing)
                GETTIMEOFDAY(&after);
        } else {
            /* connection is not usable, return error */
            ret = false;
        }
1565

1566 1567 1568 1569 1570 1571 1572 1573 1574 1575
        /* 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++;

1576
        if (!ret)
E
Eric Blake 已提交
1577
            vshReportError(ctl);
J
John Levon 已提交
1578

1579
        if (!ret && disconnected != 0)
1580 1581
            vshReconnect(ctl);

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

E
Eric Blake 已提交
1585
        if (enable_timing) {
1586
            double diff_ms = (((after.tv_sec - before.tv_sec) * 1000.0) +
E
Eric Blake 已提交
1587 1588 1589 1590
                              ((after.tv_usec - before.tv_usec) / 1000.0));

            vshPrint(ctl, _("\n(Time: %.3f ms)\n\n"), diff_ms);
        } else {
K
Karel Zak 已提交
1591
            vshPrintExtra(ctl, "\n");
E
Eric Blake 已提交
1592
        }
K
Karel Zak 已提交
1593 1594 1595 1596 1597 1598
        cmd = cmd->next;
    }
    return ret;
}

/* ---------------
1599
 * Command parsing
K
Karel Zak 已提交
1600 1601 1602
 * ---------------
 */

1603 1604 1605 1606 1607 1608 1609
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 已提交
1610 1611 1612 1613
typedef struct _vshCommandParser vshCommandParser;
struct _vshCommandParser {
    vshCommandToken(*getNextArg)(vshControl *, vshCommandParser *,
                                 char **);
L
Lai Jiangshan 已提交
1614
    /* vshCommandStringGetArg() */
1615
    char *pos;
L
Lai Jiangshan 已提交
1616 1617 1618
    /* vshCommandArgvGetArg() */
    char **arg_pos;
    char **arg_end;
E
Eric Blake 已提交
1619
};
1620

E
Eric Blake 已提交
1621
static bool
1622
vshCommandParse(vshControl *ctl, vshCommandParser *parser)
1623
{
K
Karel Zak 已提交
1624 1625 1626
    char *tkdata = NULL;
    vshCmd *clast = NULL;
    vshCmdOpt *first = NULL;
1627

K
Karel Zak 已提交
1628 1629 1630 1631
    if (ctl->cmd) {
        vshCommandFree(ctl->cmd);
        ctl->cmd = NULL;
    }
1632

1633
    while (1) {
K
Karel Zak 已提交
1634
        vshCmdOpt *last = NULL;
1635
        const vshCmdDef *cmd = NULL;
1636
        vshCommandToken tk;
L
Lai Jiangshan 已提交
1637
        bool data_only = false;
1638 1639 1640
        uint32_t opts_need_arg = 0;
        uint32_t opts_required = 0;
        uint32_t opts_seen = 0;
1641

K
Karel Zak 已提交
1642
        first = NULL;
1643

1644
        while (1) {
1645
            const vshCmdOptDef *opt = NULL;
1646

K
Karel Zak 已提交
1647
            tkdata = NULL;
1648
            tk = parser->getNextArg(ctl, parser, &tkdata);
1649 1650

            if (tk == VSH_TK_ERROR)
K
Karel Zak 已提交
1651
                goto syntaxError;
H
Hu Tao 已提交
1652 1653
            if (tk != VSH_TK_ARG) {
                VIR_FREE(tkdata);
1654
                break;
H
Hu Tao 已提交
1655
            }
1656 1657

            if (cmd == NULL) {
K
Karel Zak 已提交
1658 1659
                /* first token must be command name */
                if (!(cmd = vshCmddefSearch(tkdata))) {
1660
                    vshError(ctl, _("unknown command: '%s'"), tkdata);
1661
                    goto syntaxError;   /* ... or ignore this command only? */
K
Karel Zak 已提交
1662
                }
1663 1664 1665 1666 1667 1668 1669
                if (vshCmddefOptParse(cmd, &opts_need_arg,
                                      &opts_required) < 0) {
                    vshError(ctl,
                             _("internal error: bad options in command: '%s'"),
                             tkdata);
                    goto syntaxError;
                }
1670
                VIR_FREE(tkdata);
L
Lai Jiangshan 已提交
1671 1672 1673 1674
            } else if (data_only) {
                goto get_data;
            } else if (tkdata[0] == '-' && tkdata[1] == '-' &&
                       c_isalnum(tkdata[2])) {
1675
                char *optstr = strchr(tkdata + 2, '=');
C
Cole Robinson 已提交
1676
                int opt_index = 0;
1677

1678 1679 1680 1681
                if (optstr) {
                    *optstr = '\0'; /* convert the '=' to '\0' */
                    optstr = vshStrdup(ctl, optstr + 1);
                }
1682
                /* Special case 'help' to ignore all spurious options */
1683
                if (!(opt = vshCmddefGetOption(ctl, cmd, tkdata + 2,
1684
                                               &opts_seen, &opt_index))) {
1685
                    VIR_FREE(optstr);
1686 1687
                    if (STREQ(cmd->name, "help"))
                        continue;
K
Karel Zak 已提交
1688 1689
                    goto syntaxError;
                }
1690
                VIR_FREE(tkdata);
K
Karel Zak 已提交
1691 1692 1693

                if (opt->type != VSH_OT_BOOL) {
                    /* option data */
1694 1695 1696
                    if (optstr)
                        tkdata = optstr;
                    else
1697
                        tk = parser->getNextArg(ctl, parser, &tkdata);
1698
                    if (tk == VSH_TK_ERROR)
K
Karel Zak 已提交
1699
                        goto syntaxError;
1700
                    if (tk != VSH_TK_ARG) {
1701
                        vshError(ctl,
1702
                                 _("expected syntax: --%s <%s>"),
1703 1704
                                 opt->name,
                                 opt->type ==
1705
                                 VSH_OT_INT ? _("number") : _("string"));
K
Karel Zak 已提交
1706 1707
                        goto syntaxError;
                    }
1708 1709
                    if (opt->type != VSH_OT_ARGV)
                        opts_need_arg &= ~(1 << opt_index);
1710 1711 1712 1713 1714 1715 1716 1717
                } else {
                    tkdata = NULL;
                    if (optstr) {
                        vshError(ctl, _("invalid '=' after option --%s"),
                                opt->name);
                        VIR_FREE(optstr);
                        goto syntaxError;
                    }
K
Karel Zak 已提交
1718
                }
L
Lai Jiangshan 已提交
1719 1720 1721 1722
            } else if (tkdata[0] == '-' && tkdata[1] == '-' &&
                       tkdata[2] == '\0') {
                data_only = true;
                continue;
1723
            } else {
L
Lai Jiangshan 已提交
1724
get_data:
1725
                /* Special case 'help' to ignore spurious data */
1726
                if (!(opt = vshCmddefGetData(cmd, &opts_need_arg,
1727 1728
                                             &opts_seen)) &&
                     STRNEQ(cmd->name, "help")) {
1729
                    vshError(ctl, _("unexpected data '%s'"), tkdata);
K
Karel Zak 已提交
1730 1731 1732 1733 1734
                    goto syntaxError;
                }
            }
            if (opt) {
                /* save option */
1735
                vshCmdOpt *arg = vshMalloc(ctl, sizeof(vshCmdOpt));
1736

K
Karel Zak 已提交
1737 1738 1739 1740
                arg->def = opt;
                arg->data = tkdata;
                arg->next = NULL;
                tkdata = NULL;
1741

K
Karel Zak 已提交
1742 1743 1744 1745 1746
                if (!first)
                    first = arg;
                if (last)
                    last->next = arg;
                last = arg;
1747

1748
                vshDebug(ctl, VSH_ERR_INFO, "%s: %s(%s): %s\n",
1749 1750
                         cmd->name,
                         opt->name,
1751 1752
                         opt->type != VSH_OT_BOOL ? _("optdata") : _("bool"),
                         opt->type != VSH_OT_BOOL ? arg->data : _("(none)"));
K
Karel Zak 已提交
1753 1754
            }
        }
1755

D
Daniel Veillard 已提交
1756
        /* command parsed -- allocate new struct for the command */
K
Karel Zak 已提交
1757
        if (cmd) {
1758
            vshCmd *c = vshMalloc(ctl, sizeof(vshCmd));
1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777
            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;
            }
1778

K
Karel Zak 已提交
1779 1780 1781 1782
            c->opts = first;
            c->def = cmd;
            c->next = NULL;

1783
            if (vshCommandCheckOpts(ctl, c, opts_required, opts_seen) < 0) {
1784
                VIR_FREE(c);
1785
                goto syntaxError;
1786
            }
1787

K
Karel Zak 已提交
1788 1789 1790 1791 1792 1793
            if (!ctl->cmd)
                ctl->cmd = c;
            if (clast)
                clast->next = c;
            clast = c;
        }
1794 1795 1796

        if (tk == VSH_TK_END)
            break;
K
Karel Zak 已提交
1797
    }
1798

E
Eric Blake 已提交
1799
    return true;
K
Karel Zak 已提交
1800

1801
 syntaxError:
1802
    if (ctl->cmd) {
K
Karel Zak 已提交
1803
        vshCommandFree(ctl->cmd);
1804 1805
        ctl->cmd = NULL;
    }
K
Karel Zak 已提交
1806 1807
    if (first)
        vshCommandOptFree(first);
1808
    VIR_FREE(tkdata);
E
Eric Blake 已提交
1809
    return false;
K
Karel Zak 已提交
1810 1811
}

1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829
/* --------------------
 * 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 已提交
1830 1831
static bool
vshCommandArgvParse(vshControl *ctl, int nargs, char **argv)
1832 1833 1834 1835
{
    vshCommandParser parser;

    if (nargs <= 0)
E
Eric Blake 已提交
1836
        return false;
1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908

    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 已提交
1909 1910
static bool
vshCommandStringParse(vshControl *ctl, char *cmdstr)
1911 1912 1913 1914
{
    vshCommandParser parser;

    if (cmdstr == NULL || *cmdstr == '\0')
E
Eric Blake 已提交
1915
        return false;
1916 1917 1918 1919 1920 1921

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

K
Karel Zak 已提交
1922
/* ---------------
1923
 * Misc utils
K
Karel Zak 已提交
1924 1925
 * ---------------
 */
E
Eric Blake 已提交
1926
int
1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953
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;
}

1954 1955
/* Return a non-NULL string representation of a typed parameter; exit
 * if we are out of memory.  */
E
Eric Blake 已提交
1956
char *
1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986
vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item)
{
    int ret = 0;
    char *str = NULL;

    switch(item->type) {
    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:
        ret = virAsprintf(&str, "%s", item->value.b ? _("yes") : _("no"));
        break;

1987 1988 1989 1990
    case VIR_TYPED_PARAM_STRING:
        str = vshStrdup(ctl, item->value.s);
        break;

1991
    default:
1992
        vshError(ctl, _("unimplemented parameter type %d"), item->type);
1993 1994
    }

1995
    if (ret < 0) {
1996
        vshError(ctl, "%s", _("Out of memory"));
1997 1998
        exit(EXIT_FAILURE);
    }
1999 2000 2001
    return str;
}

E
Eric Blake 已提交
2002
virTypedParameterPtr
2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021
vshFindTypedParamByName(const char *name, virTypedParameterPtr list, int count)
{
    int i = count;
    virTypedParameterPtr found = list;

    if (!list || !name)
        return NULL;

    while (i-- > 0) {
        if (STREQ(name, found->field))
            return found;

        found++; /* go to next struct in array */
    }

    /* not found */
    return NULL;
}

E
Eric Blake 已提交
2022
void
2023
vshDebug(vshControl *ctl, int level, const char *format, ...)
2024
{
K
Karel Zak 已提交
2025
    va_list ap;
2026
    char *str;
K
Karel Zak 已提交
2027

2028 2029 2030 2031 2032 2033 2034
    /* Aligning log levels to that of libvirt.
     * Traces with levels >=  user-specified-level
     * gets logged into file
     */
    if (level < ctl->debug)
        return;

2035
    va_start(ap, format);
2036
    vshOutputLogFile(ctl, level, format, ap);
2037 2038
    va_end(ap);

K
Karel Zak 已提交
2039
    va_start(ap, format);
2040 2041 2042 2043 2044
    if (virVasprintf(&str, format, ap) < 0) {
        /* Skip debug messages on low memory */
        va_end(ap);
        return;
    }
K
Karel Zak 已提交
2045
    va_end(ap);
2046 2047
    fputs(str, stdout);
    VIR_FREE(str);
K
Karel Zak 已提交
2048 2049
}

E
Eric Blake 已提交
2050
void
2051
vshPrintExtra(vshControl *ctl, const char *format, ...)
2052
{
K
Karel Zak 已提交
2053
    va_list ap;
2054
    char *str;
2055

2056
    if (ctl && ctl->quiet)
K
Karel Zak 已提交
2057
        return;
2058

K
Karel Zak 已提交
2059
    va_start(ap, format);
2060 2061 2062 2063 2064
    if (virVasprintf(&str, format, ap) < 0) {
        vshError(ctl, "%s", _("Out of memory"));
        va_end(ap);
        return;
    }
K
Karel Zak 已提交
2065
    va_end(ap);
2066
    fputs(str, stdout);
2067
    VIR_FREE(str);
K
Karel Zak 已提交
2068 2069
}

K
Karel Zak 已提交
2070

E
Eric Blake 已提交
2071
void
2072
vshError(vshControl *ctl, const char *format, ...)
2073
{
K
Karel Zak 已提交
2074
    va_list ap;
2075
    char *str;
2076

2077 2078 2079 2080 2081
    if (ctl != NULL) {
        va_start(ap, format);
        vshOutputLogFile(ctl, VSH_ERR_ERROR, format, ap);
        va_end(ap);
    }
2082

2083 2084 2085 2086
    /* 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);
2087
    fputs(_("error: "), stderr);
2088

K
Karel Zak 已提交
2089
    va_start(ap, format);
2090 2091 2092
    /* We can't recursively call vshError on an OOM situation, so ignore
       failure here. */
    ignore_value(virVasprintf(&str, format, ap));
K
Karel Zak 已提交
2093 2094
    va_end(ap);

2095
    fprintf(stderr, "%s\n", NULLSTR(str));
2096
    fflush(stderr);
2097
    VIR_FREE(str);
K
Karel Zak 已提交
2098 2099
}

2100

J
Jiri Denemark 已提交
2101 2102 2103 2104 2105
static void
vshEventLoop(void *opaque)
{
    vshControl *ctl = opaque;

2106 2107 2108 2109 2110 2111 2112 2113 2114 2115
    while (1) {
        bool quit;
        virMutexLock(&ctl->lock);
        quit = ctl->quit;
        virMutexUnlock(&ctl->lock);

        if (quit)
            break;

        if (virEventRunDefaultImpl() < 0)
E
Eric Blake 已提交
2116
            vshReportError(ctl);
J
Jiri Denemark 已提交
2117 2118 2119 2120
    }
}


K
Karel Zak 已提交
2121
/*
2122
 * Initialize connection.
K
Karel Zak 已提交
2123
 */
E
Eric Blake 已提交
2124
static bool
2125
vshInit(vshControl *ctl)
2126
{
2127 2128
    char *debugEnv;

K
Karel Zak 已提交
2129
    if (ctl->conn)
E
Eric Blake 已提交
2130
        return false;
K
Karel Zak 已提交
2131

J
Jiri Denemark 已提交
2132
    if (ctl->debug == VSH_DEBUG_DEFAULT) {
2133 2134 2135
        /* log level not set from commandline, check env variable */
        debugEnv = getenv("VIRSH_DEBUG");
        if (debugEnv) {
J
Jiri Denemark 已提交
2136 2137 2138
            int debug;
            if (virStrToLong_i(debugEnv, NULL, 10, &debug) < 0 ||
                debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR) {
2139 2140
                vshError(ctl, "%s",
                         _("VIRSH_DEBUG not set with a valid numeric value"));
J
Jiri Denemark 已提交
2141 2142
            } else {
                ctl->debug = debug;
2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154
            }
        }
    }

    if (ctl->logfile == NULL) {
        /* log file not set from cmdline */
        debugEnv = getenv("VIRSH_LOG_FILE");
        if (debugEnv && *debugEnv) {
            ctl->logfile = vshStrdup(ctl, debugEnv);
        }
    }

2155 2156
    vshOpenLogFile(ctl);

2157 2158
    /* set up the library error handler */
    virSetErrorFunc(NULL, virshErrorHandler);
2159

2160
    if (virEventRegisterDefaultImpl() < 0)
E
Eric Blake 已提交
2161
        return false;
2162

J
Jiri Denemark 已提交
2163 2164 2165 2166
    if (virThreadCreate(&ctl->eventLoop, true, vshEventLoop, ctl) < 0)
        return false;
    ctl->eventLoopStarted = true;

2167 2168 2169 2170
    if (ctl->name) {
        ctl->conn = virConnectOpenAuth(ctl->name,
                                       virConnectAuthPtrDefault,
                                       ctl->readonly ? VIR_CONNECT_RO : 0);
2171

2172 2173 2174 2175 2176 2177 2178
        /* 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 已提交
2179
            vshReportError(ctl);
2180 2181 2182
            vshError(ctl, "%s", _("failed to connect to the hypervisor"));
            return false;
        }
2183
    }
K
Karel Zak 已提交
2184

E
Eric Blake 已提交
2185
    return true;
K
Karel Zak 已提交
2186 2187
}

2188 2189
#define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC)

2190 2191 2192 2193 2194
/**
 * vshOpenLogFile:
 *
 * Open log file.
 */
E
Eric Blake 已提交
2195
void
2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208
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:
2209
                vshError(ctl, "%s",
J
Jim Meyering 已提交
2210
                         _("failed to get the log file information"));
2211
                exit(EXIT_FAILURE);
2212 2213 2214
        }
    } else {
        if (!S_ISREG(st.st_mode)) {
2215 2216
            vshError(ctl, "%s", _("the log path is not a file"));
            exit(EXIT_FAILURE);
2217 2218 2219 2220
        }
    }

    /* log file open */
2221
    if ((ctl->log_fd = open(ctl->logfile, LOGFILE_FLAGS, FILE_MODE)) < 0) {
2222
        vshError(ctl, "%s",
J
Jim Meyering 已提交
2223
                 _("failed to open the log file. check the log file path"));
2224
        exit(EXIT_FAILURE);
2225 2226 2227 2228 2229 2230 2231 2232
    }
}

/**
 * vshOutputLogFile:
 *
 * Outputting an error to log file.
 */
E
Eric Blake 已提交
2233
void
2234 2235
vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format,
                 va_list ap)
2236
{
2237 2238 2239
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *str;
    size_t len;
2240
    const char *lvl = "";
2241
    time_t stTime;
2242
    struct tm stTm;
2243 2244 2245 2246 2247 2248 2249 2250 2251

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

    /**
     * create log format
     *
     * [YYYY.MM.DD HH:MM:SS SIGNATURE PID] LOG_LEVEL message
    */
2252 2253
    time(&stTime);
    localtime_r(&stTime, &stTm);
2254
    virBufferAsprintf(&buf, "[%d.%02d.%02d %02d:%02d:%02d %s %d] ",
2255 2256 2257 2258 2259 2260
                      (1900 + stTm.tm_year),
                      (1 + stTm.tm_mon),
                      stTm.tm_mday,
                      stTm.tm_hour,
                      stTm.tm_min,
                      stTm.tm_sec,
2261 2262
                      SIGN_NAME,
                      (int) getpid());
2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282
    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;
    }
2283 2284 2285
    virBufferAsprintf(&buf, "%s ", lvl);
    virBufferVasprintf(&buf, msg_format, ap);
    virBufferAddChar(&buf, '\n');
2286

2287 2288
    if (virBufferError(&buf))
        goto error;
2289

2290 2291 2292 2293 2294
    str = virBufferContentAndReset(&buf);
    len = strlen(str);
    if (len > 1 && str[len - 2] == '\n') {
        str[len - 1] = '\0';
        len--;
2295
    }
2296

2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307
    /* write log */
    if (safewrite(ctl->log_fd, str, len) < 0)
        goto error;

    return;

error:
    vshCloseLogFile(ctl);
    vshError(ctl, "%s", _("failed to write the log file"));
    virBufferFreeAndReset(&buf);
    VIR_FREE(str);
2308 2309 2310 2311 2312 2313 2314
}

/**
 * vshCloseLogFile:
 *
 * Close log file.
 */
E
Eric Blake 已提交
2315
void
2316 2317
vshCloseLogFile(vshControl *ctl)
{
2318 2319
    char ebuf[1024];

2320
    /* log file close */
2321 2322
    if (VIR_CLOSE(ctl->log_fd) < 0) {
        vshError(ctl, _("%s: failed to write log file: %s"),
2323 2324
                 ctl->logfile ? ctl->logfile : "?",
                 virStrerror(errno, ebuf, sizeof(ebuf)));
2325 2326 2327
    }

    if (ctl->logfile) {
2328
        VIR_FREE(ctl->logfile);
2329 2330 2331 2332
        ctl->logfile = NULL;
    }
}

2333
#ifdef USE_READLINE
2334

K
Karel Zak 已提交
2335 2336 2337 2338 2339
/* -----------------
 * Readline stuff
 * -----------------
 */

2340
/*
K
Karel Zak 已提交
2341 2342
 * Generator function for command completion.  STATE lets us
 * know whether to start from scratch; without any state
2343
 * (i.e. STATE == 0), then we start at the top of the list.
K
Karel Zak 已提交
2344 2345
 */
static char *
2346 2347
vshReadlineCommandGenerator(const char *text, int state)
{
2348
    static int grp_list_index, cmd_list_index, len;
K
Karel Zak 已提交
2349
    const char *name;
2350 2351
    const vshCmdGrp *grp;
    const vshCmdDef *cmds;
K
Karel Zak 已提交
2352 2353

    if (!state) {
2354 2355
        grp_list_index = 0;
        cmd_list_index = 0;
2356
        len = strlen(text);
K
Karel Zak 已提交
2357 2358
    }

2359 2360
    grp = cmdGroups;

K
Karel Zak 已提交
2361
    /* Return the next name which partially matches from the
2362
     * command list.
K
Karel Zak 已提交
2363
     */
2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377
    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 已提交
2378 2379 2380 2381 2382 2383 2384
    }

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

static char *
2385 2386
vshReadlineOptionsGenerator(const char *text, int state)
{
K
Karel Zak 已提交
2387
    static int list_index, len;
2388
    static const vshCmdDef *cmd = NULL;
K
Karel Zak 已提交
2389
    const char *name;
K
Karel Zak 已提交
2390 2391 2392 2393 2394 2395 2396 2397 2398

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

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

2399
        cmdname = vshCalloc(NULL, (p - rl_line_buffer) + 1, 1);
2400
        memcpy(cmdname, rl_line_buffer, p - rl_line_buffer);
K
Karel Zak 已提交
2401 2402 2403

        cmd = vshCmddefSearch(cmdname);
        list_index = 0;
2404
        len = strlen(text);
2405
        VIR_FREE(cmdname);
K
Karel Zak 已提交
2406 2407 2408 2409
    }

    if (!cmd)
        return NULL;
2410

2411 2412 2413
    if (!cmd->opts)
        return NULL;

K
Karel Zak 已提交
2414
    while ((name = cmd->opts[list_index].name)) {
2415
        const vshCmdOptDef *opt = &cmd->opts[list_index];
K
Karel Zak 已提交
2416
        char *res;
2417

K
Karel Zak 已提交
2418
        list_index++;
2419

2420
        if (opt->type == VSH_OT_DATA || opt->type == VSH_OT_ARGV)
K
Karel Zak 已提交
2421 2422
            /* ignore non --option */
            continue;
2423

K
Karel Zak 已提交
2424
        if (len > 2) {
2425
            if (STRNEQLEN(name, text + 2, len - 2))
K
Karel Zak 已提交
2426 2427
                continue;
        }
2428
        res = vshMalloc(NULL, strlen(name) + 3);
2429
        snprintf(res, strlen(name) + 3,  "--%s", name);
K
Karel Zak 已提交
2430 2431 2432 2433 2434 2435 2436 2437
        return res;
    }

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

static char **
2438 2439 2440
vshReadlineCompletion(const char *text, int start,
                      int end ATTRIBUTE_UNUSED)
{
K
Karel Zak 已提交
2441 2442
    char **matches = (char **) NULL;

2443
    if (start == 0)
K
Karel Zak 已提交
2444
        /* command name generator */
2445
        matches = rl_completion_matches(text, vshReadlineCommandGenerator);
K
Karel Zak 已提交
2446 2447
    else
        /* commands options */
2448
        matches = rl_completion_matches(text, vshReadlineOptionsGenerator);
K
Karel Zak 已提交
2449 2450 2451 2452
    return matches;
}


2453 2454
static int
vshReadlineInit(vshControl *ctl)
2455
{
2456 2457
    char *userdir = NULL;

K
Karel Zak 已提交
2458 2459 2460 2461 2462
    /* 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;
2463 2464 2465

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

2467
    /* Prepare to read/write history from/to the $XDG_CACHE_HOME/virsh/history file */
2468
    userdir = virGetUserCacheDirectory();
2469

2470 2471
    if (userdir == NULL) {
        vshError(ctl, "%s", _("Could not determine home directory"));
2472
        return -1;
2473
    }
2474

2475
    if (virAsprintf(&ctl->historydir, "%s/virsh", userdir) < 0) {
2476
        vshError(ctl, "%s", _("Out of memory"));
2477
        VIR_FREE(userdir);
2478 2479 2480 2481 2482
        return -1;
    }

    if (virAsprintf(&ctl->historyfile, "%s/history", ctl->historydir) < 0) {
        vshError(ctl, "%s", _("Out of memory"));
2483
        VIR_FREE(userdir);
2484 2485 2486
        return -1;
    }

2487
    VIR_FREE(userdir);
2488 2489 2490 2491 2492 2493 2494

    read_history(ctl->historyfile);

    return 0;
}

static void
2495
vshReadlineDeinit(vshControl *ctl)
2496 2497
{
    if (ctl->historyfile != NULL) {
2498 2499
        if (virFileMakePathWithMode(ctl->historydir, 0755) < 0 &&
            errno != EEXIST) {
2500 2501
            char ebuf[1024];
            vshError(ctl, _("Failed to create '%s': %s"),
2502
                     ctl->historydir, virStrerror(errno, ebuf, sizeof(ebuf)));
E
Eric Blake 已提交
2503
        } else {
2504
            write_history(ctl->historyfile);
E
Eric Blake 已提交
2505
        }
2506 2507
    }

2508 2509
    VIR_FREE(ctl->historydir);
    VIR_FREE(ctl->historyfile);
K
Karel Zak 已提交
2510 2511
}

2512
static char *
2513
vshReadline(vshControl *ctl ATTRIBUTE_UNUSED, const char *prompt)
2514
{
2515
    return readline(prompt);
2516 2517
}

2518
#else /* !USE_READLINE */
2519

2520
static int
2521
vshReadlineInit(vshControl *ctl ATTRIBUTE_UNUSED)
2522 2523 2524 2525 2526
{
    /* empty */
    return 0;
}

2527
static void
2528
vshReadlineDeinit(vshControl *ctl ATTRIBUTE_UNUSED)
2529 2530 2531 2532 2533
{
    /* empty */
}

static char *
2534
vshReadline(vshControl *ctl, const char *prompt)
2535 2536 2537 2538 2539
{
    char line[1024];
    char *r;
    int len;

2540 2541
    fputs(prompt, stdout);
    r = fgets(line, sizeof(line), stdin);
2542 2543 2544
    if (r == NULL) return NULL; /* EOF */

    /* Chomp trailing \n */
2545
    len = strlen(r);
2546 2547 2548
    if (len > 0 && r[len-1] == '\n')
        r[len-1] = '\0';

2549
    return vshStrdup(ctl, r);
2550 2551
}

2552
#endif /* !USE_READLINE */
2553

2554 2555 2556 2557 2558 2559
static void
vshDeinitTimer(int timer ATTRIBUTE_UNUSED, void *opaque ATTRIBUTE_UNUSED)
{
    /* nothing to be done here */
}

K
Karel Zak 已提交
2560
/*
J
Jim Meyering 已提交
2561
 * Deinitialize virsh
K
Karel Zak 已提交
2562
 */
E
Eric Blake 已提交
2563
static bool
2564
vshDeinit(vshControl *ctl)
2565
{
2566
    vshReadlineDeinit(ctl);
2567
    vshCloseLogFile(ctl);
2568
    VIR_FREE(ctl->name);
K
Karel Zak 已提交
2569
    if (ctl->conn) {
2570 2571 2572
        int ret;
        if ((ret = virConnectClose(ctl->conn)) != 0) {
            vshError(ctl, _("Failed to disconnect from the hypervisor, %d leaked reference(s)"), ret);
K
Karel Zak 已提交
2573 2574
        }
    }
D
Daniel P. Berrange 已提交
2575 2576
    virResetLastError();

J
Jiri Denemark 已提交
2577
    if (ctl->eventLoopStarted) {
2578 2579 2580 2581
        int timer;

        virMutexLock(&ctl->lock);
        ctl->quit = true;
J
Jiri Denemark 已提交
2582
        /* HACK: Add a dummy timeout to break event loop */
2583 2584 2585 2586 2587
        timer = virEventAddTimeout(0, vshDeinitTimer, NULL, NULL);
        virMutexUnlock(&ctl->lock);

        virThreadJoin(&ctl->eventLoop);

J
Jiri Denemark 已提交
2588 2589 2590 2591 2592 2593
        if (timer != -1)
            virEventRemoveTimeout(timer);

        ctl->eventLoopStarted = false;
    }

2594 2595
    virMutexDestroy(&ctl->lock);

E
Eric Blake 已提交
2596
    return true;
K
Karel Zak 已提交
2597
}
2598

K
Karel Zak 已提交
2599 2600 2601
/*
 * Print usage
 */
E
Eric Blake 已提交
2602
static void
2603
vshUsage(void)
2604
{
2605
    const vshCmdGrp *grp;
2606
    const vshCmdDef *cmd;
2607

L
Lai Jiangshan 已提交
2608 2609
    fprintf(stdout, _("\n%s [options]... [<command_string>]"
                      "\n%s [options]... <command> [args...]\n\n"
2610
                      "  options:\n"
2611
                      "    -c | --connect=URI      hypervisor connection URI\n"
2612
                      "    -r | --readonly         connect readonly\n"
2613
                      "    -d | --debug=NUM        debug level [0-4]\n"
2614 2615 2616
                      "    -h | --help             this help\n"
                      "    -q | --quiet            quiet mode\n"
                      "    -t | --timing           print timing information\n"
2617 2618 2619 2620 2621
                      "    -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"
2622
                      "  commands (non interactive mode):\n\n"), progname, progname);
2623

2624
    for (grp = cmdGroups; grp->name; grp++) {
E
Eric Blake 已提交
2625 2626 2627 2628 2629
        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;
2630
            fprintf(stdout,
E
Eric Blake 已提交
2631 2632 2633
                    "    %-30s %s\n", cmd->name,
                    _(vshCmddefGetInfo(cmd, "help")));
        }
2634 2635 2636 2637 2638
        fprintf(stdout, "\n");
    }

    fprintf(stdout, "%s",
            _("\n  (specify help <group> for details about the commands in the group)\n"));
2639 2640 2641
    fprintf(stdout, "%s",
            _("\n  (specify help <command> for details about the command)\n\n"));
    return;
K
Karel Zak 已提交
2642 2643
}

2644 2645 2646 2647 2648 2649 2650 2651 2652 2653
/*
 * 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 已提交
2654 2655
    vshPrint(ctl, "%s", _("Compiled with support for:\n"));
    vshPrint(ctl, "%s", _(" Hypervisors:"));
2656
#ifdef WITH_QEMU
2657
    vshPrint(ctl, " QEMU/KVM");
2658
#endif
D
Doug Goldstein 已提交
2659 2660 2661
#ifdef WITH_LXC
    vshPrint(ctl, " LXC");
#endif
2662 2663 2664
#ifdef WITH_UML
    vshPrint(ctl, " UML");
#endif
D
Doug Goldstein 已提交
2665 2666 2667 2668 2669 2670
#ifdef WITH_XEN
    vshPrint(ctl, " Xen");
#endif
#ifdef WITH_LIBXL
    vshPrint(ctl, " LibXL");
#endif
2671 2672 2673
#ifdef WITH_OPENVZ
    vshPrint(ctl, " OpenVZ");
#endif
D
Doug Goldstein 已提交
2674 2675
#ifdef WITH_VMWARE
    vshPrint(ctl, " VMWare");
2676
#endif
D
Doug Goldstein 已提交
2677 2678
#ifdef WITH_PHYP
    vshPrint(ctl, " PHYP");
2679
#endif
D
Doug Goldstein 已提交
2680 2681
#ifdef WITH_VBOX
    vshPrint(ctl, " VirtualBox");
2682 2683 2684 2685
#endif
#ifdef WITH_ESX
    vshPrint(ctl, " ESX");
#endif
D
Doug Goldstein 已提交
2686 2687
#ifdef WITH_HYPERV
    vshPrint(ctl, " Hyper-V");
2688
#endif
D
Doug Goldstein 已提交
2689 2690
#ifdef WITH_XENAPI
    vshPrint(ctl, " XenAPI");
2691 2692 2693 2694 2695 2696
#endif
#ifdef WITH_TEST
    vshPrint(ctl, " Test");
#endif
    vshPrint(ctl, "\n");

L
Laine Stump 已提交
2697
    vshPrint(ctl, "%s", _(" Networking:"));
2698 2699 2700 2701 2702 2703 2704 2705 2706
#ifdef WITH_REMOTE
    vshPrint(ctl, " Remote");
#endif
#ifdef WITH_NETWORK
    vshPrint(ctl, " Network");
#endif
#ifdef WITH_BRIDGE
    vshPrint(ctl, " Bridging");
#endif
2707
#if defined(WITH_INTERFACE)
D
Doug Goldstein 已提交
2708
    vshPrint(ctl, " Interface");
2709 2710
# if defined(WITH_NETCF)
    vshPrint(ctl, " netcf");
2711 2712
# elif defined(HAVE_UDEV)
    vshPrint(ctl, " udev");
2713
# endif
2714 2715 2716 2717 2718 2719 2720 2721 2722
#endif
#ifdef WITH_NWFILTER
    vshPrint(ctl, " Nwfilter");
#endif
#ifdef WITH_VIRTUALPORT
    vshPrint(ctl, " VirtualPort");
#endif
    vshPrint(ctl, "\n");

L
Laine Stump 已提交
2723
    vshPrint(ctl, "%s", _(" Storage:"));
2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743
#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");
2744 2745 2746
#endif
#ifdef WITH_STORAGE_RBD
    vshPrint(ctl, " RBD");
2747 2748 2749
#endif
#ifdef WITH_STORAGE_SHEEPDOG
    vshPrint(ctl, " Sheepdog");
2750 2751 2752
#endif
    vshPrint(ctl, "\n");

2753
    vshPrint(ctl, "%s", _(" Miscellaneous:"));
2754 2755 2756
#ifdef WITH_LIBVIRTD
    vshPrint(ctl, " Daemon");
#endif
2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797
#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 已提交
2798
static bool
2799 2800
vshParseArgv(vshControl *ctl, int argc, char **argv)
{
2801
    int arg, len, debug;
2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820
    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. */
    while ((arg = getopt_long(argc, argv, "+d:hqtc:vVrl:e:", opt, NULL)) != -1) {
        switch (arg) {
        case 'd':
2821
            if (virStrToLong_i(optarg, NULL, 10, &debug) < 0) {
2822 2823 2824
                vshError(ctl, "%s", _("option -d takes a numeric argument"));
                exit(EXIT_FAILURE);
            }
2825 2826 2827 2828 2829
            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;
2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899
            break;
        case 'h':
            vshUsage();
            exit(EXIT_SUCCESS);
            break;
        case 'q':
            ctl->quiet = true;
            break;
        case 't':
            ctl->timing = true;
            break;
        case 'c':
            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':
            ctl->logfile = vshStrdup(ctl, optarg);
            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;
        default:
            vshError(ctl, _("unsupported option '-%c'. See --help."), arg);
            exit(EXIT_FAILURE);
        }
    }

    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[] = {
    {"cd", cmdCd, opts_cd, info_cd, VSH_CMD_FLAG_NOCONNECT},
    {"echo", cmdEcho, opts_echo, info_echo, VSH_CMD_FLAG_NOCONNECT},
    {"exit", cmdQuit, NULL, info_quit, VSH_CMD_FLAG_NOCONNECT},
    {"help", cmdHelp, opts_help, info_help, VSH_CMD_FLAG_NOCONNECT},
    {"pwd", cmdPwd, NULL, info_pwd, VSH_CMD_FLAG_NOCONNECT},
    {"quit", cmdQuit, NULL, info_quit, VSH_CMD_FLAG_NOCONNECT},
    {NULL, NULL, NULL, NULL, 0}
};
2900

2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915
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 已提交
2916

2917 2918 2919 2920
int
main(int argc, char **argv)
{
    vshControl _ctl, *ctl = &_ctl;
2921
    char *defaultConn;
E
Eric Blake 已提交
2922
    bool ret = true;
K
Karel Zak 已提交
2923

2924 2925 2926
    memset(ctl, 0, sizeof(vshControl));
    ctl->imode = true;          /* default is interactive mode */
    ctl->log_fd = -1;           /* Initialize log file descriptor */
J
Jiri Denemark 已提交
2927
    ctl->debug = VSH_DEBUG_DEFAULT;
E
Eric Blake 已提交
2928
    ctl->escapeChar = "^]";     /* Same default as telnet */
2929

2930

2931 2932
    if (!setlocale(LC_ALL, "")) {
        perror("setlocale");
2933
        /* failure to setup locale is not fatal */
2934
    }
2935
    if (!bindtextdomain(PACKAGE, LOCALEDIR)) {
2936
        perror("bindtextdomain");
E
Eric Blake 已提交
2937
        return EXIT_FAILURE;
2938
    }
2939
    if (!textdomain(PACKAGE)) {
2940
        perror("textdomain");
E
Eric Blake 已提交
2941
        return EXIT_FAILURE;
2942 2943
    }

2944 2945 2946 2947 2948
    if (virMutexInit(&ctl->lock) < 0) {
        vshError(ctl, "%s", _("Failed to initialize mutex"));
        return EXIT_FAILURE;
    }

2949 2950 2951 2952 2953
    if (virInitialize() < 0) {
        vshError(ctl, "%s", _("Failed to initialize libvirt"));
        return EXIT_FAILURE;
    }

2954
    if (!(progname = strrchr(argv[0], '/')))
K
Karel Zak 已提交
2955 2956 2957
        progname = argv[0];
    else
        progname++;
2958

2959
    if ((defaultConn = getenv("VIRSH_DEFAULT_CONNECT_URI"))) {
E
Eric Blake 已提交
2960
        ctl->name = vshStrdup(ctl, defaultConn);
2961 2962
    }

D
Daniel P. Berrange 已提交
2963 2964
    if (!vshParseArgv(ctl, argc, argv)) {
        vshDeinit(ctl);
K
Karel Zak 已提交
2965
        exit(EXIT_FAILURE);
D
Daniel P. Berrange 已提交
2966
    }
2967

D
Daniel P. Berrange 已提交
2968 2969
    if (!vshInit(ctl)) {
        vshDeinit(ctl);
K
Karel Zak 已提交
2970
        exit(EXIT_FAILURE);
D
Daniel P. Berrange 已提交
2971
    }
2972

K
Karel Zak 已提交
2973
    if (!ctl->imode) {
2974
        ret = vshCommandRun(ctl, ctl->cmd);
2975
    } else {
K
Karel Zak 已提交
2976 2977
        /* interactive mode */
        if (!ctl->quiet) {
K
Karel Zak 已提交
2978
            vshPrint(ctl,
2979
                     _("Welcome to %s, the virtualization interactive terminal.\n\n"),
2980
                     progname);
J
Jim Meyering 已提交
2981
            vshPrint(ctl, "%s",
2982
                     _("Type:  'help' for help with commands\n"
2983
                       "       'quit' to quit\n\n"));
K
Karel Zak 已提交
2984
        }
2985 2986 2987 2988 2989 2990

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

K
Karel Zak 已提交
2991
        do {
2992
            const char *prompt = ctl->readonly ? VSH_PROMPT_RO : VSH_PROMPT_RW;
2993
            ctl->cmdstr =
2994
                vshReadline(ctl, prompt);
2995 2996
            if (ctl->cmdstr == NULL)
                break;          /* EOF */
K
Karel Zak 已提交
2997
            if (*ctl->cmdstr) {
2998
#if USE_READLINE
K
Karel Zak 已提交
2999
                add_history(ctl->cmdstr);
3000
#endif
3001
                if (vshCommandStringParse(ctl, ctl->cmdstr))
K
Karel Zak 已提交
3002 3003
                    vshCommandRun(ctl, ctl->cmd);
            }
3004
            VIR_FREE(ctl->cmdstr);
3005
        } while (ctl->imode);
K
Karel Zak 已提交
3006

3007 3008
        if (ctl->cmdstr == NULL)
            fputc('\n', stdout);        /* line break after alone prompt */
K
Karel Zak 已提交
3009
    }
3010

K
Karel Zak 已提交
3011 3012
    vshDeinit(ctl);
    exit(ret ? EXIT_SUCCESS : EXIT_FAILURE);
3013
}