virsh.c 67.9 KB
Newer Older
1
/*
2
 * virsh.c: a Xen shell used to exercise the libvir API
3 4 5 6 7 8
 *
 * Copyright (C) 2005 Red Hat, Inc.
 *
 * See COPYING.LIB for the License of this software
 *
 * Daniel Veillard <veillard@redhat.com>
K
Karel Zak 已提交
9
 * Karel Zak <kzak@redhat.com>
K
Karel Zak 已提交
10 11
 * Daniel P. Berrange <berrange@redhat.com>
 *
K
Karel Zak 已提交
12 13
 *
 * $Id$
14 15
 */

16
#define _GNU_SOURCE             /* isblank() */
K
Karel Zak 已提交
17

18 19
#include "libvirt/libvirt.h"
#include "libvirt/virterror.h"
20
#include <stdio.h>
K
Karel Zak 已提交
21 22 23
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
24
#include <unistd.h>
K
Karel Zak 已提交
25
#include <getopt.h>
26
#include <sys/types.h>
K
Karel Zak 已提交
27
#include <sys/time.h>
K
Karel Zak 已提交
28
#include <ctype.h>
29
#include <fcntl.h>
K
Karel Zak 已提交
30 31 32 33 34

#include <readline/readline.h>
#include <readline/history.h>

#include "config.h"
35
#include "internal.h"
K
Karel Zak 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

static char *progname;

#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

#define VSH_PROMPT_RW    "virsh # "
#define VSH_PROMPT_RO    "virsh > "

#define GETTIMEOFDAY(T) gettimeofday(T, NULL)
#define DIFF_MSEC(T, U) \
        ((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
          ((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)

52 53 54 55
/*
 * The error handler for virtsh
 */
static void
56 57
virshErrorHandler(void *unused, virErrorPtr error)
{
58 59 60 61 62 63 64 65 66 67
    if ((unused != NULL) || (error == NULL))
        return;

    /* Suppress the VIR_ERR_NO_XEN error which fails as non-root */
    if ((error->code == VIR_ERR_NO_XEN) || (error->code == VIR_ERR_OK))
        return;

    virDefaultErrorFunc(error);
}

K
Karel Zak 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80 81
/*
 * virsh command line grammar:
 *
 *    command_line    =     <command>\n | <command>; <command>; ...
 *
 *    command         =    <keyword> <option> <data>
 *
 *    option          =     <bool_option> | <int_option> | <string_option>
 *    data            =     <string>
 *
 *    bool_option     =     --optionname
 *    int_option      =     --optionname <number>
 *    string_option   =     --optionname <string>
 *        
82 83 84
 *    keyword         =     [a-zA-Z]
 *    number          =     [0-9]+
 *    string          =     [^[:blank:]] | "[[:alnum:]]"$
K
Karel Zak 已提交
85 86 87 88 89
 *
 */

/*
 * vshCmdOptType - command option type 
90
 */
K
Karel Zak 已提交
91
typedef enum {
92 93 94 95 96
    VSH_OT_NONE = 0,            /* none */
    VSH_OT_BOOL,                /* boolean option */
    VSH_OT_STRING,              /* string option */
    VSH_OT_INT,                 /* int option */
    VSH_OT_DATA                 /* string data (as non-option) */
K
Karel Zak 已提交
97 98 99 100 101
} vshCmdOptType;

/*
 * Command Option Flags
 */
102 103
#define VSH_OFLAG_NONE    0     /* without flags */
#define VSH_OFLAG_REQ    (1 << 1)       /* option required */
K
Karel Zak 已提交
104 105 106 107 108 109 110 111

/* dummy */
typedef struct __vshControl vshControl;
typedef struct __vshCmd vshCmd;

/*
 * vshCmdInfo -- information about command
 */
112 113 114
typedef struct {
    const char *name;           /* name of information */
    const char *data;           /* information */
K
Karel Zak 已提交
115 116 117 118 119
} vshCmdInfo;

/*
 * vshCmdOptDef - command option definition
 */
120 121 122 123 124
typedef struct {
    const char *name;           /* the name of option */
    vshCmdOptType type;         /* option type */
    int flag;                   /* flags */
    const char *help;           /* help string */
K
Karel Zak 已提交
125 126 127 128 129 130
} vshCmdOptDef;

/*
 * vshCmdOpt - command options
 */
typedef struct vshCmdOpt {
131 132 133
    vshCmdOptDef *def;          /* pointer to relevant option */
    char *data;                 /* allocated data */
    struct vshCmdOpt *next;
K
Karel Zak 已提交
134 135 136 137 138
} vshCmdOpt;

/*
 * vshCmdDef - command definition
 */
139 140 141 142 143
typedef struct {
    const char *name;
    int (*handler) (vshControl *, vshCmd *);    /* command handler */
    vshCmdOptDef *opts;         /* definition of command options */
    vshCmdInfo *info;           /* details about command */
K
Karel Zak 已提交
144 145 146 147 148 149
} vshCmdDef;

/*
 * vshCmd - parsed command
 */
typedef struct __vshCmd {
150 151 152
    vshCmdDef *def;             /* command definition */
    vshCmdOpt *opts;            /* list of command arguments */
    struct __vshCmd *next;      /* next command */
K
Karel Zak 已提交
153 154 155 156 157 158
} __vshCmd;

/*
 * vshControl
 */
typedef struct __vshControl {
K
Karel Zak 已提交
159
    char *name;                 /* connection name */
160 161 162 163 164 165 166 167
    virConnectPtr conn;         /* connection to hypervisor */
    vshCmd *cmd;                /* the current command */
    char *cmdstr;               /* string with command */
    uid_t uid;                  /* process owner */
    int imode;                  /* interactive mode? */
    int quiet;                  /* quiet mode */
    int debug;                  /* print debug messages? */
    int timing;                 /* print timing info? */
K
Karel Zak 已提交
168
} __vshControl;
169

170

K
Karel Zak 已提交
171 172
static vshCmdDef commands[];

173 174 175 176 177
static void vshError(vshControl * ctl, int doexit, const char *format,
                     ...);
static int vshInit(vshControl * ctl);
static int vshDeinit(vshControl * ctl);
static void vshUsage(vshControl * ctl, const char *cmdname);
K
Karel Zak 已提交
178

179
static int vshParseArgv(vshControl * ctl, int argc, char **argv);
K
Karel Zak 已提交
180

181
static const char *vshCmddefGetInfo(vshCmdDef * cmd, const char *info);
K
Karel Zak 已提交
182
static vshCmdDef *vshCmddefSearch(const char *cmdname);
183
static int vshCmddefHelp(vshControl * ctl, const char *name, int withprog);
K
Karel Zak 已提交
184

185 186 187 188 189
static vshCmdOpt *vshCommandOpt(vshCmd * cmd, const char *name);
static int vshCommandOptInt(vshCmd * cmd, const char *name, int *found);
static char *vshCommandOptString(vshCmd * cmd, const char *name,
                                 int *found);
static int vshCommandOptBool(vshCmd * cmd, const char *name);
K
Karel Zak 已提交
190 191 192 193 194 195 196 197 198 199 200 201

#define VSH_DOMBYID     (1 << 1)
#define VSH_DOMBYUUID   (1 << 2)
#define VSH_DOMBYNAME   (1 << 3)

static virDomainPtr vshCommandOptDomainBy(vshControl * ctl, vshCmd * cmd,
                            const char *optname, char **name, int flag);

/* default is lookup by Id, Name and UUID */
#define vshCommandOptDomain(_ctl, _cmd, _optname, _name) \
                            vshCommandOptDomainBy(_ctl, _cmd, _optname, _name,\
                                        VSH_DOMBYID|VSH_DOMBYUUID|VSH_DOMBYNAME)
K
Karel Zak 已提交
202

K
Karel Zak 已提交
203 204
static void vshPrintExtra(vshControl * ctl, const char *format, ...);
static void vshDebug(vshControl * ctl, int level, const char *format, ...);
K
Karel Zak 已提交
205 206

/* XXX: add batch support */
K
Karel Zak 已提交
207
#define vshPrint(_ctl, ...)   fprintf(stdout, __VA_ARGS__)
K
Karel Zak 已提交
208

K
Karel Zak 已提交
209
static const char *vshDomainStateToString(int state);
210
static const char *vshDomainVcpuStateToString(int state);
211 212
static int vshConnectionUsability(vshControl * ctl, virConnectPtr conn,
                                  int showerror);
K
Karel Zak 已提交
213

214 215 216 217 218 219 220 221 222
static void *_vshMalloc(vshControl * ctl, size_t sz, const char *filename, int line);
#define vshMalloc(_ctl, _sz)    _vshMalloc(_ctl, _sz, __FILE__, __LINE__)

static void *_vshCalloc(vshControl * ctl, size_t nmemb, size_t sz, const char *filename, int line);
#define vshCalloc(_ctl, _nmemb, _sz)    _vshCalloc(_ctl, _nmemb, _sz, __FILE__, __LINE__)

static char *_vshStrdup(vshControl * ctl, const char *s, const char *filename, int line);
#define vshStrdup(_ctl, _s)    _vshStrdup(_ctl, _s, __FILE__, __LINE__)

K
Karel Zak 已提交
223 224 225 226 227 228 229 230 231
/* ---------------
 * Commands
 * ---------------
 */

/*
 * "help" command 
 */
static vshCmdInfo info_help[] = {
232
    {"syntax", "help [<command>]"},
233 234 235
    {"help", gettext_noop("print help")},
    {"desc", gettext_noop("Prints global help or command specific help.")},

236
    {NULL, NULL}
K
Karel Zak 已提交
237 238 239
};

static vshCmdOptDef opts_help[] = {
240 241
    {"command", VSH_OT_DATA, 0, "name of command"},
    {NULL, 0, 0, NULL}
K
Karel Zak 已提交
242 243 244
};

static int
245 246
cmdHelp(vshControl * ctl, vshCmd * cmd)
{
K
Karel Zak 已提交
247
    const char *cmdname = vshCommandOptString(cmd, "command", NULL);
K
Karel Zak 已提交
248 249 250

    if (!cmdname) {
        vshCmdDef *def;
251

252
        vshPrint(ctl, _("Commands:\n\n"));
253
        for (def = commands; def->name; def++)
K
Karel Zak 已提交
254
            vshPrint(ctl, "    %-15s %s\n", def->name,
255
                     _N(vshCmddefGetInfo(def, "help")));
K
Karel Zak 已提交
256 257 258 259 260 261 262 263 264
        return TRUE;
    }
    return vshCmddefHelp(ctl, cmdname, FALSE);
}

/*
 * "connect" command 
 */
static vshCmdInfo info_connect[] = {
K
Karel Zak 已提交
265
    {"syntax", "connect [name] [--readonly]"},
266
    {"help", gettext_noop("(re)connect to hypervisor")},
267
    {"desc",
268
     gettext_noop("Connect to local hypervisor. This is built-in command after shell start up.")},
269
    {NULL, NULL}
K
Karel Zak 已提交
270 271 272
};

static vshCmdOptDef opts_connect[] = {
273 274
    {"name",     VSH_OT_DATA, 0, gettext_noop("hypervisor connection URI")},
    {"readonly", VSH_OT_BOOL, 0, gettext_noop("read-only connection")},
275
    {NULL, 0, 0, NULL}
K
Karel Zak 已提交
276 277 278
};

static int
279 280
cmdConnect(vshControl * ctl, vshCmd * cmd)
{
K
Karel Zak 已提交
281
    int ro = vshCommandOptBool(cmd, "readonly");
K
Karel Zak 已提交
282
    
K
Karel Zak 已提交
283
    if (ctl->conn) {
284 285
        if (virConnectClose(ctl->conn) != 0) {
            vshError(ctl, FALSE,
286
                     _("Failed to disconnect from the hypervisor"));
K
Karel Zak 已提交
287 288 289 290
            return FALSE;
        }
        ctl->conn = NULL;
    }
K
Karel Zak 已提交
291 292 293 294 295
    
    if (ctl->name)
        free(ctl->name);
    ctl->name = vshCommandOptString(cmd, "name", NULL);

K
Karel Zak 已提交
296
    if (!ro)
K
Karel Zak 已提交
297
        ctl->conn = virConnectOpen(ctl->name);
K
Karel Zak 已提交
298
    else
K
Karel Zak 已提交
299
        ctl->conn = virConnectOpenReadOnly(ctl->name);
K
Karel Zak 已提交
300 301

    if (!ctl->conn)
302
        vshError(ctl, FALSE, _("Failed to connect to the hypervisor"));
303

K
Karel Zak 已提交
304 305 306 307 308 309 310
    return ctl->conn ? TRUE : FALSE;
}

/*
 * "list" command
 */
static vshCmdInfo info_list[] = {
311
    {"syntax", "list"},
312 313
    {"help", gettext_noop("list domains")},
    {"desc", gettext_noop("Returns list of domains.")},
314
    {NULL, NULL}
K
Karel Zak 已提交
315 316
};

317
static vshCmdOptDef opts_list[] = {
318 319
    {"inactive", VSH_OT_BOOL, 0, gettext_noop("list inactive domains")},
    {"all", VSH_OT_BOOL, 0, gettext_noop("list inactive & active domains")},
320 321 322
    {NULL, 0, 0, NULL}
};

K
Karel Zak 已提交
323

324 325 326 327 328 329 330 331 332 333 334 335 336
static int domidsorter(const void *a, const void *b) {
  const int *ia = (const int *)a;
  const int *ib = (const int *)b;

  if (*ia > *ib)
    return 1;
  else if (*ia < *ib)
    return -1;
  return 0;
}
static int domnamesorter(const void *a, const void *b) {
  const char **sa = (const char**)a;
  const char **sb = (const char**)b;
K
Karel Zak 已提交
337

338 339
  return strcasecmp(*sa, *sb);
}
K
Karel Zak 已提交
340
static int
341 342
cmdList(vshControl * ctl, vshCmd * cmd ATTRIBUTE_UNUSED)
{
343 344 345 346 347 348 349
    int inactive = vshCommandOptBool(cmd, "inactive");
    int all = vshCommandOptBool(cmd, "all");
    int active = !inactive || all ? 1 : 0;
    int *ids = NULL, maxid = 0, i;
    const char **names = NULL;
    int maxname = 0;
    inactive |= all;
K
Karel Zak 已提交
350 351 352

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;
353 354 355 356
    
    if (active) {
      maxid = virConnectNumOfDomains(ctl->conn);
      if (maxid < 0) {
357
        vshError(ctl, FALSE, _("Failed to list active domains"));
K
Karel Zak 已提交
358
        return FALSE;
359 360
      }
      if (maxid) {
361
        ids = vshMalloc(ctl, sizeof(int) * maxid);
362
	
363
        if ((maxid = virConnectListDomains(ctl->conn, &ids[0], maxid)) < 0) {
364
	  vshError(ctl, FALSE, _("Failed to list active domains"));
365 366
	  free(ids);
	  return FALSE;
367
        }
368 369
	
	qsort(&ids[0], maxid, sizeof(int), domidsorter);
370 371 372 373 374
      }
    }
    if (inactive) {
      maxname = virConnectNumOfDefinedDomains(ctl->conn);
      if (maxname < 0) {
375
        vshError(ctl, FALSE, _("Failed to list inactive domains"));
376 377 378 379 380
	if (ids)
	  free(ids);
        return FALSE;
      }
      if (maxname) {
381
        names = vshMalloc(ctl, sizeof(char *) * maxname);
382
	
383
        if ((maxname = virConnectListDefinedDomains(ctl->conn, names, maxname)) < 0) {
384
	  vshError(ctl, FALSE, _("Failed to list inactive domains"));
385 386 387 388 389
	  if (ids)
	    free(ids);
	  free(names);
	  return FALSE;
        }
390 391

	qsort(&names[0], maxname, sizeof(char*), domnamesorter);
392
      }
393
    }
394
    vshPrintExtra(ctl, "%3s %-20s %s\n", _("Id"), _("Name"), _("State"));
K
Karel Zak 已提交
395
    vshPrintExtra(ctl, "----------------------------------\n");
396 397

    for (i = 0; i < maxid; i++) {
K
Karel Zak 已提交
398 399 400
        int ret;
        virDomainInfo info;
        virDomainPtr dom = virDomainLookupByID(ctl->conn, ids[i]);
401 402

        /* this kind of work with domains is not atomic operation */
K
Karel Zak 已提交
403 404 405
        if (!dom)
            continue;
        ret = virDomainGetInfo(dom, &info);
406

K
Karel Zak 已提交
407
        vshPrint(ctl, "%3d %-20s %s\n",
408 409 410
                 virDomainGetID(dom),
                 virDomainGetName(dom),
                 ret <
411
                 0 ? _("no state") : _N(vshDomainStateToString(info.state)));
412
        virDomainFree(dom);
K
Karel Zak 已提交
413
    }
414 415
    for (i = 0; i < maxname; i++) {
        int ret;
416
        unsigned int id;
417 418 419 420 421 422 423
        virDomainInfo info;
        virDomainPtr dom = virDomainLookupByName(ctl->conn, names[i]);

        /* this kind of work with domains is not atomic operation */
        if (!dom)
            continue;
        ret = virDomainGetInfo(dom, &info);
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
	id = virDomainGetID(dom);

	if (id == ((unsigned int)-1)) {
	  vshPrint(ctl, "%3s %-20s %s\n",
		   "-",
		   names[i],
		   ret <
		   0 ? "no state" : vshDomainStateToString(info.state));
	} else {
	  vshPrint(ctl, "%3d %-20s %s\n",
		   id,
		   names[i],
		   ret <
		   0 ? "no state" : vshDomainStateToString(info.state));
	}
439

440 441
        virDomainFree(dom);
    }
442 443
    if (ids)
        free(ids);
444 445
    if (names)
        free(names);
K
Karel Zak 已提交
446 447 448 449
    return TRUE;
}

/*
K
Karel Zak 已提交
450
 * "domstate" command
K
Karel Zak 已提交
451
 */
K
Karel Zak 已提交
452 453
static vshCmdInfo info_domstate[] = {
    {"syntax", "domstate <domain>"},
454 455
    {"help", gettext_noop("domain state")},
    {"desc", gettext_noop("Returns state about a running domain.")},
456
    {NULL, NULL}
K
Karel Zak 已提交
457 458
};

K
Karel Zak 已提交
459
static vshCmdOptDef opts_domstate[] = {
460
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
461
    {NULL, 0, 0, NULL}
K
Karel Zak 已提交
462 463 464
};

static int
K
Karel Zak 已提交
465
cmdDomstate(vshControl * ctl, vshCmd * cmd)
466
{
467
    virDomainInfo info;
K
Karel Zak 已提交
468
    virDomainPtr dom;
K
Karel Zak 已提交
469
    int ret = TRUE;
470

K
Karel Zak 已提交
471 472
    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;
473

K
Karel Zak 已提交
474
    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
K
Karel Zak 已提交
475
        return FALSE;
476 477

    if (virDomainGetInfo(dom, &info) == 0)
K
Karel Zak 已提交
478
        vshPrint(ctl, "%s\n",
479
                 _N(vshDomainStateToString(info.state)));
K
Karel Zak 已提交
480 481
    else
        ret = FALSE;
482

483 484 485 486 487 488 489 490
    virDomainFree(dom);
    return ret;
}

/*
 * "suspend" command
 */
static vshCmdInfo info_suspend[] = {
491
    {"syntax", "suspend <domain>"},
492 493
    {"help", gettext_noop("suspend a domain")},
    {"desc", gettext_noop("Suspend a running domain.")},
494
    {NULL, NULL}
495 496 497
};

static vshCmdOptDef opts_suspend[] = {
498
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
499
    {NULL, 0, 0, NULL}
500 501 502
};

static int
503 504
cmdSuspend(vshControl * ctl, vshCmd * cmd)
{
505
    virDomainPtr dom;
K
Karel Zak 已提交
506 507
    char *name;
    int ret = TRUE;
508

509 510 511
    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

K
Karel Zak 已提交
512
    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
513
        return FALSE;
514 515

    if (virDomainSuspend(dom) == 0) {
516
        vshPrint(ctl, _("Domain %s suspended\n"), name);
517
    } else {
518
        vshError(ctl, FALSE, _("Failed to suspend domain %s"), name);
519 520
        ret = FALSE;
    }
521

522 523 524 525
    virDomainFree(dom);
    return ret;
}

526 527 528 529 530
/*
 * "create" command
 */
static vshCmdInfo info_create[] = {
    {"syntax", "create a domain from an XML <file>"},
531 532
    {"help", gettext_noop("create a domain from an XML file")},
    {"desc", gettext_noop("Create a domain.")},
533 534 535 536
    {NULL, NULL}
};

static vshCmdOptDef opts_create[] = {
537
    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file conatining an XML domain description")},
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
    {NULL, 0, 0, NULL}
};

static int
cmdCreate(vshControl * ctl, vshCmd * cmd)
{
    virDomainPtr dom;
    char *from;
    int found;
    int ret = TRUE;
    char buffer[4096];
    int fd, l;

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

    from = vshCommandOptString(cmd, "file", &found);
    if (!found)
        return FALSE;

    fd = open(from, O_RDONLY);
    if (fd < 0) {
560
        vshError(ctl, FALSE, _("Failed to read description file %s"), from);
561 562 563 564
        return(FALSE);
    }
    l = read(fd, &buffer[0], sizeof(buffer));
    if ((l <= 0) || (l >= (int) sizeof(buffer))) {
565
        vshError(ctl, FALSE, _("Failed to read description file %s"), from);
566 567 568 569 570 571
        close(fd);
        return(FALSE);
    }
    buffer[l] = 0;
    dom = virDomainCreateLinux(ctl->conn, &buffer[0], 0);
    if (dom != NULL) {
572
        vshPrint(ctl, _("Domain %s created from %s\n"),
573 574
                 virDomainGetName(dom), from);
    } else {
575
        vshError(ctl, FALSE, _("Failed to create domain from %s"), from);
576 577 578 579 580
        ret = FALSE;
    }
    return ret;
}

581 582 583 584 585
/*
 * "define" command
 */
static vshCmdInfo info_define[] = {
    {"syntax", "define a domain from an XML <file>"},
586 587
    {"help", gettext_noop("define (but don't start) a domain from an XML file")},
    {"desc", gettext_noop("Define a domain.")},
588 589 590 591
    {NULL, NULL}
};

static vshCmdOptDef opts_define[] = {
592
    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file conatining an XML domain description")},
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
    {NULL, 0, 0, NULL}
};

static int
cmdDefine(vshControl * ctl, vshCmd * cmd)
{
    virDomainPtr dom;
    char *from;
    int found;
    int ret = TRUE;
    char buffer[4096];
    int fd, l;

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

    from = vshCommandOptString(cmd, "file", &found);
    if (!found)
        return FALSE;

    fd = open(from, O_RDONLY);
    if (fd < 0) {
615
        vshError(ctl, FALSE, _("Failed to read description file %s"), from);
616 617 618 619
        return(FALSE);
    }
    l = read(fd, &buffer[0], sizeof(buffer));
    if ((l <= 0) || (l >= (int) sizeof(buffer))) {
620
        vshError(ctl, FALSE, _("Failed to read description file %s"), from);
621 622 623 624 625 626
        close(fd);
        return(FALSE);
    }
    buffer[l] = 0;
    dom = virDomainDefineXML(ctl->conn, &buffer[0]);
    if (dom != NULL) {
627
        vshPrint(ctl, _("Domain %s defined from %s\n"),
628 629
                 virDomainGetName(dom), from);
    } else {
630
        vshError(ctl, FALSE, _("Failed to define domain from %s"), from);
631 632 633 634 635 636 637 638 639 640
        ret = FALSE;
    }
    return ret;
}

/*
 * "undefine" command
 */
static vshCmdInfo info_undefine[] = {
    {"syntax", "undefine <domain>"},
641 642
    {"help", gettext_noop("undefine an inactive domain")},
    {"desc", gettext_noop("Undefine the configuration for an inactive domain.")},
643 644 645 646
    {NULL, NULL}
};

static vshCmdOptDef opts_undefine[] = {
647
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name or uuid")},
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
    {NULL, 0, 0, NULL}
};

static int
cmdUndefine(vshControl * ctl, vshCmd * cmd)
{
    virDomainPtr dom;
    int ret = TRUE;
    char *name;

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
        return FALSE;

    if (virDomainUndefine(dom) == 0) {
665
        vshPrint(ctl, _("Domain %s has been undefined\n"), name);
666
    } else {
667
        vshError(ctl, FALSE, _("Failed to undefine domain %s"), name);
668 669 670 671 672 673 674 675 676 677 678 679
        ret = FALSE;
    }

    return ret;
}


/*
 * "start" command
 */
static vshCmdInfo info_start[] = {
    {"syntax", "start a domain "},
680 681
    {"help", gettext_noop("start a (previously defined) inactive domain")},
    {"desc", gettext_noop("Start a domain.")},
682 683 684 685
    {NULL, NULL}
};

static vshCmdOptDef opts_start[] = {
686
    {"name", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("name of the inactive domain")},
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
    {NULL, 0, 0, NULL}
};

static int
cmdStart(vshControl * ctl, vshCmd * cmd)
{
    virDomainPtr dom;
    char *name;
    int found;
    int ret = TRUE;

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

    name = vshCommandOptString(cmd, "name", &found);
    if (!found)
        return FALSE;

    dom = virDomainLookupByName(ctl->conn, name);
    if (!dom)
        return FALSE;

    if (virDomainGetID(dom) != (unsigned int)-1) {
710
        vshError(ctl, FALSE, _("Domain is already active"));
711 712 713 714
        return FALSE;
    }

    if (virDomainCreate(dom) == 0) {
715
        vshPrint(ctl, _("Domain %s started\n"),
716 717
                 name);
    } else {
718
      vshError(ctl, FALSE, _("Failed to start domain %s"), name);
719 720 721 722 723
        ret = FALSE;
    }
    return ret;
}

724 725 726 727
/*
 * "save" command
 */
static vshCmdInfo info_save[] = {
728
    {"syntax", "save <domain> <file>"},
729 730
    {"help", gettext_noop("save a domain state to a file")},
    {"desc", gettext_noop("Save a running domain.")},
731
    {NULL, NULL}
732 733 734
};

static vshCmdOptDef opts_save[] = {
735 736
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("where to save the data")},
737
    {NULL, 0, 0, NULL}
738 739 740
};

static int
741 742
cmdSave(vshControl * ctl, vshCmd * cmd)
{
743 744 745 746
    virDomainPtr dom;
    char *name;
    char *to;
    int ret = TRUE;
747

748 749 750
    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

751
    if (!(to = vshCommandOptString(cmd, "file", NULL)))
752
        return FALSE;
753

754 755
    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
        return FALSE;
756 757

    if (virDomainSave(dom, to) == 0) {
758
        vshPrint(ctl, _("Domain %s saved to %s\n"), name, to);
759
    } else {
760
        vshError(ctl, FALSE, _("Failed to save domain %s to %s"), name, to);
761 762
        ret = FALSE;
    }
763

764 765 766 767 768 769 770 771
    virDomainFree(dom);
    return ret;
}

/*
 * "restore" command
 */
static vshCmdInfo info_restore[] = {
772
    {"syntax", "restore a domain from <file>"},
773 774
    {"help", gettext_noop("restore a domain from a saved state in a file")},
    {"desc", gettext_noop("Restore a domain.")},
775
    {NULL, NULL}
776 777 778
};

static vshCmdOptDef opts_restore[] = {
779
    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("the state to restore")},
780
    {NULL, 0, 0, NULL}
781 782 783
};

static int
784 785
cmdRestore(vshControl * ctl, vshCmd * cmd)
{
786 787 788
    char *from;
    int found;
    int ret = TRUE;
789

790 791 792 793 794 795
    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

    from = vshCommandOptString(cmd, "file", &found);
    if (!found)
        return FALSE;
796 797

    if (virDomainRestore(ctl->conn, from) == 0) {
798
        vshPrint(ctl, _("Domain restored from %s\n"), from);
799
    } else {
800
        vshError(ctl, FALSE, _("Failed to restore domain from %s"), from);
801 802 803 804 805
        ret = FALSE;
    }
    return ret;
}

806 807 808 809
/*
 * "resume" command
 */
static vshCmdInfo info_resume[] = {
810
    {"syntax", "resume <domain>"},
811 812
    {"help", gettext_noop("resume a domain")},
    {"desc", gettext_noop("Resume a previously suspended domain.")},
813
    {NULL, NULL}
814 815 816
};

static vshCmdOptDef opts_resume[] = {
817
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
818
    {NULL, 0, 0, NULL}
819 820 821
};

static int
822 823
cmdResume(vshControl * ctl, vshCmd * cmd)
{
824
    virDomainPtr dom;
K
Karel Zak 已提交
825 826
    int ret = TRUE;
    char *name;
827

828 829 830
    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

K
Karel Zak 已提交
831
    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
832
        return FALSE;
833 834

    if (virDomainResume(dom) == 0) {
835
        vshPrint(ctl, _("Domain %s resumed\n"), name);
836
    } else {
837
        vshError(ctl, FALSE, _("Failed to resume domain %s"), name);
838 839
        ret = FALSE;
    }
840

841 842 843 844
    virDomainFree(dom);
    return ret;
}

845 846 847 848
/*
 * "shutdown" command
 */
static vshCmdInfo info_shutdown[] = {
849
    {"syntax", "shutdown <domain>"},
850 851
    {"help", gettext_noop("gracefully shutdown a domain")},
    {"desc", gettext_noop("Run shutdown in the target domain.")},
852
    {NULL, NULL}
853 854 855
};

static vshCmdOptDef opts_shutdown[] = {
856
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
857
    {NULL, 0, 0, NULL}
858 859 860
};

static int
861 862
cmdShutdown(vshControl * ctl, vshCmd * cmd)
{
863 864 865
    virDomainPtr dom;
    int ret = TRUE;
    char *name;
866

867 868 869 870 871
    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
        return FALSE;
872 873

    if (virDomainShutdown(dom) == 0) {
874
        vshPrint(ctl, _("Domain %s is being shutdown\n"), name);
875
    } else {
876
        vshError(ctl, FALSE, _("Failed to shutdown domain %s"), name);
877 878
        ret = FALSE;
    }
879

880 881 882 883
    virDomainFree(dom);
    return ret;
}

884 885 886 887 888
/*
 * "reboot" command
 */
static vshCmdInfo info_reboot[] = {
    {"syntax", "reboot <domain>"},
889 890
    {"help", gettext_noop("reboot a domain")},
    {"desc", gettext_noop("Run a reboot command in the target domain.")},
891 892 893 894
    {NULL, NULL}
};

static vshCmdOptDef opts_reboot[] = {
895
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912
    {NULL, 0, 0, NULL}
};

static int
cmdReboot(vshControl * ctl, vshCmd * cmd)
{
    virDomainPtr dom;
    int ret = TRUE;
    char *name;

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
        return FALSE;

    if (virDomainReboot(dom, 0) == 0) {
913
        vshPrint(ctl, _("Domain %s is being rebooted\n"), name);
914
    } else {
915
        vshError(ctl, FALSE, _("Failed to reboot domain %s"), name);
916 917 918 919 920 921 922
        ret = FALSE;
    }

    virDomainFree(dom);
    return ret;
}

923 924 925 926
/*
 * "destroy" command
 */
static vshCmdInfo info_destroy[] = {
927
    {"syntax", "destroy <domain>"},
928 929
    {"help", gettext_noop("destroy a domain")},
    {"desc", gettext_noop("Destroy a given domain.")},
930
    {NULL, NULL}
931 932 933
};

static vshCmdOptDef opts_destroy[] = {
934
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
935
    {NULL, 0, 0, NULL}
936 937 938
};

static int
939 940
cmdDestroy(vshControl * ctl, vshCmd * cmd)
{
941
    virDomainPtr dom;
K
Karel Zak 已提交
942 943
    int ret = TRUE;
    char *name;
944

945 946 947
    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

K
Karel Zak 已提交
948
    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
949
        return FALSE;
950 951

    if (virDomainDestroy(dom) == 0) {
952
        vshPrint(ctl, _("Domain %s destroyed\n"), name);
953
    } else {
954
        vshError(ctl, FALSE, _("Failed to destroy domain %s"), name);
955 956 957
        ret = FALSE;
        virDomainFree(dom);
    }
958

K
Karel Zak 已提交
959 960 961 962
    return ret;
}

/*
963
 * "dominfo" command
K
Karel Zak 已提交
964
 */
965 966
static vshCmdInfo info_dominfo[] = {
    {"syntax", "dominfo <domain>"},
967 968
    {"help", gettext_noop("domain information")},
    {"desc", gettext_noop("Returns basic information about the domain.")},
969
    {NULL, NULL}
K
Karel Zak 已提交
970 971
};

972
static vshCmdOptDef opts_dominfo[] = {
973
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
974
    {NULL, 0, 0, NULL}
K
Karel Zak 已提交
975 976 977
};

static int
978
cmdDominfo(vshControl * ctl, vshCmd * cmd)
979
{
K
Karel Zak 已提交
980 981
    virDomainInfo info;
    virDomainPtr dom;
K
Karel Zak 已提交
982
    int ret = TRUE;
983
    unsigned int id;
K
Karel Zak 已提交
984
    char *str, uuid[37];
985

K
Karel Zak 已提交
986 987 988
    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

K
Karel Zak 已提交
989
    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
K
Karel Zak 已提交
990
        return FALSE;
991

992 993
    id = virDomainGetID(dom);
    if (id == ((unsigned int)-1))
994
      vshPrint(ctl, "%-15s %s\n", _("Id:"), "-");
995
    else
996 997 998
      vshPrint(ctl, "%-15s %d\n", _("Id:"), id);
    vshPrint(ctl, "%-15s %s\n", _("Name:"), virDomainGetName(dom));

K
Karel Zak 已提交
999
    if (virDomainGetUUIDString(dom, &uuid[0])==0)
1000
        vshPrint(ctl, "%-15s %s\n", _("UUID:"), uuid);
1001 1002

    if ((str = virDomainGetOSType(dom))) {
1003
        vshPrint(ctl, "%-15s %s\n", _("OS Type:"), str);
1004 1005 1006 1007
        free(str);
    }

    if (virDomainGetInfo(dom, &info) == 0) {
1008 1009
        vshPrint(ctl, "%-15s %s\n", _("State:"),
                 _N(vshDomainStateToString(info.state)));
1010

1011
        vshPrint(ctl, "%-15s %d\n", _("CPU(s):"), info.nrVirtCpu);
1012 1013

        if (info.cpuTime != 0) {
1014
	    double cpuUsed = info.cpuTime;
1015

1016
            cpuUsed /= 1000000000.0;
1017

1018
            vshPrint(ctl, "%-15s %.1lfs\n", _("CPU time:"), cpuUsed);
K
Karel Zak 已提交
1019
        }
1020

1021
        vshPrint(ctl, "%-15s %lu kB\n", _("Max memory:"),
1022
                 info.maxMem);
1023
	vshPrint(ctl, "%-15s %lu kB\n", _("Used memory:"),
1024 1025
                 info.memory);

K
Karel Zak 已提交
1026 1027 1028
    } else {
        ret = FALSE;
    }
1029

1030
    virDomainFree(dom);
K
Karel Zak 已提交
1031 1032 1033
    return ret;
}

1034 1035 1036 1037 1038
/*
 * "vcpuinfo" command
 */
static vshCmdInfo info_vcpuinfo[] = {
    {"syntax", "vcpuinfo <domain>"},
1039 1040
    {"help", gettext_noop("domain vcpu information")},
    {"desc", gettext_noop("Returns basic information about the domain virtual CPUs.")},
1041 1042 1043 1044
    {NULL, NULL}
};

static vshCmdOptDef opts_vcpuinfo[] = {
1045
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
    {NULL, 0, 0, NULL}
};

static int
cmdVcpuinfo(vshControl * ctl, vshCmd * cmd)
{
    virDomainInfo info;
    virDomainPtr dom;
    virNodeInfo nodeinfo;
    virVcpuInfoPtr cpuinfo;
    unsigned char *cpumap;
    int ncpus;
    size_t cpumaplen;
    int ret = TRUE;

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
        return FALSE;

    if (virNodeGetInfo(ctl->conn, &nodeinfo) != 0) {
        virDomainFree(dom);
	return FALSE;
    }

    if (virDomainGetInfo(dom, &info) != 0) {
        virDomainFree(dom);
        return FALSE;
    }

    cpuinfo = malloc(sizeof(virVcpuInfo)*info.nrVirtCpu);
    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
    cpumap = malloc(info.nrVirtCpu * cpumaplen);

    if ((ncpus = virDomainGetVcpus(dom, 
				   cpuinfo, info.nrVirtCpu,
				   cpumap, cpumaplen)) >= 0) {
        int n;
	for (n = 0 ; n < ncpus ; n++) {
	    unsigned int m;
1087 1088 1089 1090
	    vshPrint(ctl, "%-15s %d\n", _("VCPU:"), n);
	    vshPrint(ctl, "%-15s %d\n", _("CPU:"), cpuinfo[n].cpu);
	    vshPrint(ctl, "%-15s %s\n", _("State:"),
		     _N(vshDomainVcpuStateToString(cpuinfo[n].state)));
1091 1092 1093 1094 1095
	    if (cpuinfo[n].cpuTime != 0) {
	        double cpuUsed = cpuinfo[n].cpuTime;
		
		cpuUsed /= 1000000000.0;
		
1096
		vshPrint(ctl, "%-15s %.1lfs\n", _("CPU time:"), cpuUsed);
1097
	    }
1098
	    vshPrint(ctl, "%-15s ", _("CPU Affinity:"));
1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
	    for (m = 0 ; m < VIR_NODEINFO_MAXCPUS(nodeinfo) ; m++) {
	        vshPrint(ctl, "%c", VIR_CPU_USABLE(cpumap, cpumaplen, n, m) ? 'y' : '-');
	    }
	    vshPrint(ctl, "\n");
	    if (n < (ncpus - 1)) {
	        vshPrint(ctl, "\n");
	    }
	}
    } else {
        ret = FALSE;
    }

    free(cpumap);
    free(cpuinfo);
    virDomainFree(dom);
    return ret;
}

/*
 * "vcpupin" command
 */
static vshCmdInfo info_vcpupin[] = {
    {"syntax", "vcpupin <domain>"},
1122 1123
    {"help", gettext_noop("control domain vcpu affinity")},
    {"desc", gettext_noop("Pin domain VCPUs to host physical CPUs.")},
1124 1125 1126 1127
    {NULL, NULL}
};

static vshCmdOptDef opts_vcpupin[] = {
1128 1129 1130
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
    {"vcpu", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("vcpu number")},
    {"cpulist", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("host cpu number(s) (comma separated)")},
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
    {NULL, 0, 0, NULL}
};

static int
cmdVcpupin(vshControl * ctl, vshCmd * cmd)
{
    virDomainInfo info;
    virDomainPtr dom;
    virNodeInfo nodeinfo;
    int vcpu;
    char *cpulist;
    int ret = TRUE;
    int vcpufound = 0;
    unsigned char *cpumap;
    int cpumaplen;

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
        return FALSE;

    vcpu = vshCommandOptInt(cmd, "vcpu", &vcpufound);
    if (!vcpufound) {
        virDomainFree(dom);
        return FALSE;
    }

    if (!(cpulist = vshCommandOptString(cmd, "cpulist", NULL))) {
        virDomainFree(dom);
        return FALSE;
    }
      
    if (virNodeGetInfo(ctl->conn, &nodeinfo) != 0) {
        virDomainFree(dom);
        return FALSE;
    }

    if (virDomainGetInfo(dom, &info) != 0) {
        virDomainFree(dom);
        return FALSE;
    }

    if (vcpu >= info.nrVirtCpu) {
        virDomainFree(dom);
        return FALSE;
    }

    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
    cpumap = malloc(cpumaplen);
    memset(cpumap, 0, cpumaplen);

    do {
        unsigned int cpu = atoi(cpulist);

        if (cpu < VIR_NODEINFO_MAXCPUS(nodeinfo)) {
            VIR_USE_CPU(cpumap, cpu);
        }
        cpulist = index(cpulist, ',');
        if (cpulist)
            cpulist++;
    } while (cpulist);

    if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) {
        ret = FALSE;
    }

    free(cpumap);
    virDomainFree(dom);
    return ret;
}

1203 1204 1205 1206 1207
/*
 * "setvcpus" command
 */
static vshCmdInfo info_setvcpus[] = {
    {"syntax", "setvcpus <domain> <count>"},
1208 1209
    {"help", gettext_noop("change number of virtual CPUs")},
    {"desc", gettext_noop("Change the number of virtual CPUs active in the guest domain.")},
1210 1211 1212 1213
    {NULL, NULL}
};

static vshCmdOptDef opts_setvcpus[] = {
1214 1215
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
    {"count", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("number of virtual CPUs")},
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250
    {NULL, 0, 0, NULL}
};

static int
cmdSetvcpus(vshControl * ctl, vshCmd * cmd)
{
    virDomainPtr dom;
    int count;
    int ret = TRUE;

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
        return FALSE;

    count = vshCommandOptInt(cmd, "count", &count);
    if (!count) {
        virDomainFree(dom);
        return FALSE;
    }

    if (virDomainSetVcpus(dom, count) != 0) {
        ret = FALSE;
    }

    virDomainFree(dom);
    return ret;
}

/*
 * "setmemory" command
 */
static vshCmdInfo info_setmem[] = {
    {"syntax", "setmem <domain> <bytes>"},
1251 1252
    {"help", gettext_noop("change memory allocation")},
    {"desc", gettext_noop("Change the current memory allocation in the guest domain.")},
1253 1254 1255 1256
    {NULL, NULL}
};

static vshCmdOptDef opts_setmem[] = {
1257 1258
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
    {"bytes", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("number of bytes of memory")},
1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293
    {NULL, 0, 0, NULL}
};

static int
cmdSetmem(vshControl * ctl, vshCmd * cmd)
{
    virDomainPtr dom;
    int bytes;
    int ret = TRUE;

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
        return FALSE;

    bytes = vshCommandOptInt(cmd, "bytes", &bytes);
    if (!bytes) {
        virDomainFree(dom);
        return FALSE;
    }

    if (virDomainSetMemory(dom, bytes) != 0) {
        ret = FALSE;
    }

    virDomainFree(dom);
    return ret;
}

/*
 * "setmaxmem" command
 */
static vshCmdInfo info_setmaxmem[] = {
    {"syntax", "setmaxmem <domain> <bytes>"},
1294 1295
    {"help", gettext_noop("change maximum memory limit")},
    {"desc", gettext_noop("Change the maximum memory allocation limit in the guest domain.")},
1296 1297 1298 1299
    {NULL, NULL}
};

static vshCmdOptDef opts_setmaxmem[] = {
1300 1301
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
    {"bytes", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("maxmimum memory limit in bytes")},
1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331
    {NULL, 0, 0, NULL}
};

static int
cmdSetmaxmem(vshControl * ctl, vshCmd * cmd)
{
    virDomainPtr dom;
    int bytes;
    int ret = TRUE;

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
        return FALSE;

    bytes = vshCommandOptInt(cmd, "bytes", &bytes);
    if (!bytes) {
        virDomainFree(dom);
        return FALSE;
    }

    if (virDomainSetMaxMemory(dom, bytes) != 0) {
        ret = FALSE;
    }

    virDomainFree(dom);
    return ret;
}

1332 1333 1334 1335 1336
/*
 * "nodeinfo" command
 */
static vshCmdInfo info_nodeinfo[] = {
    {"syntax", "nodeinfo"},
1337 1338
    {"help", gettext_noop("node information")},
    {"desc", gettext_noop("Returns basic information about the node.")},
1339 1340 1341 1342 1343 1344 1345
    {NULL, NULL}
};

static int
cmdNodeinfo(vshControl * ctl, vshCmd * cmd ATTRIBUTE_UNUSED)
{
    virNodeInfo info;
1346

1347 1348 1349 1350
    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

    if (virNodeGetInfo(ctl->conn, &info) < 0) {
1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362
        vshError(ctl, FALSE, _("failed to get node information"));
        return FALSE;
    }
    vshPrint(ctl, "%-20s %s\n", _("CPU model:"), info.model);
    vshPrint(ctl, "%-20s %d\n", _("CPU(s):"), info.cpus);
    vshPrint(ctl, "%-20s %d MHz\n", _("CPU frequency:"), info.mhz);
    vshPrint(ctl, "%-20s %d\n", _("CPU socket(s):"), info.sockets);
    vshPrint(ctl, "%-20s %d\n", _("Core(s) per socket:"), info.cores);
    vshPrint(ctl, "%-20s %d\n", _("Thread(s) per core:"), info.threads);
    vshPrint(ctl, "%-20s %d\n", _("NUMA cell(s):"), info.nodes);
    vshPrint(ctl, "%-20s %lu kB\n", _("Memory size:"), info.memory);

1363 1364 1365
    return TRUE;
}

1366 1367 1368 1369
/*
 * "dumpxml" command
 */
static vshCmdInfo info_dumpxml[] = {
1370
    {"syntax", "dumpxml <name>"},
1371 1372
    {"help", gettext_noop("domain information in XML")},
    {"desc", gettext_noop("Ouput the domain information as an XML dump to stdout.")},
1373
    {NULL, NULL}
1374 1375 1376
};

static vshCmdOptDef opts_dumpxml[] = {
1377
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
1378
    {NULL, 0, 0, NULL}
1379 1380 1381
};

static int
1382 1383
cmdDumpXML(vshControl * ctl, vshCmd * cmd)
{
1384
    virDomainPtr dom;
K
Karel Zak 已提交
1385
    int ret = TRUE;
1386
    char *dump;
1387

1388 1389 1390
    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;

K
Karel Zak 已提交
1391
    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
1392
        return FALSE;
1393

1394 1395 1396 1397 1398 1399 1400
    dump = virDomainGetXMLDesc(dom, 0);
    if (dump != NULL) {
        printf("%s", dump);
        free(dump);
    } else {
        ret = FALSE;
    }
1401

1402 1403 1404 1405
    virDomainFree(dom);
    return ret;
}

K
Karel Zak 已提交
1406
/*
K
Karel Zak 已提交
1407
 * "domname" command
K
Karel Zak 已提交
1408
 */
K
Karel Zak 已提交
1409
static vshCmdInfo info_domname[] = {
K
Karel Zak 已提交
1410
    {"syntax", "domname <domain>"},
1411
    {"help", gettext_noop("convert a domain id or UUID to domain name")},
1412
    {NULL, NULL}
K
Karel Zak 已提交
1413 1414
};

K
Karel Zak 已提交
1415
static vshCmdOptDef opts_domname[] = {
1416
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain id or uuid")},
1417
    {NULL, 0, 0, NULL}
K
Karel Zak 已提交
1418 1419 1420
};

static int
K
Karel Zak 已提交
1421
cmdDomname(vshControl * ctl, vshCmd * cmd)
1422
{
K
Karel Zak 已提交
1423 1424 1425 1426
    virDomainPtr dom;

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;
K
Karel Zak 已提交
1427 1428
    if (!(dom = vshCommandOptDomainBy(ctl, cmd, "domain", NULL, 
                                    VSH_DOMBYID|VSH_DOMBYUUID)))
K
Karel Zak 已提交
1429
        return FALSE;
1430

K
Karel Zak 已提交
1431 1432
    vshPrint(ctl, "%s\n", virDomainGetName(dom));
    virDomainFree(dom);
K
Karel Zak 已提交
1433 1434 1435 1436
    return TRUE;
}

/*
K
Karel Zak 已提交
1437
 * "domid" command
K
Karel Zak 已提交
1438
 */
K
Karel Zak 已提交
1439
static vshCmdInfo info_domid[] = {
K
Karel Zak 已提交
1440
    {"syntax", "domid <domain>"},
1441
    {"help", gettext_noop("convert a domain name or UUID to domain id")},
1442
    {NULL, NULL}
K
Karel Zak 已提交
1443 1444
};

K
Karel Zak 已提交
1445
static vshCmdOptDef opts_domid[] = {
1446
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name or uuid")},
1447
    {NULL, 0, 0, NULL}
K
Karel Zak 已提交
1448 1449 1450
};

static int
K
Karel Zak 已提交
1451
cmdDomid(vshControl * ctl, vshCmd * cmd)
1452
{
1453
    virDomainPtr dom;
1454
    unsigned int id;
K
Karel Zak 已提交
1455 1456 1457

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;
K
Karel Zak 已提交
1458 1459
    if (!(dom = vshCommandOptDomainBy(ctl, cmd, "domain", NULL, 
                                    VSH_DOMBYNAME|VSH_DOMBYUUID)))
K
Karel Zak 已提交
1460
        return FALSE;
K
Karel Zak 已提交
1461
    
1462 1463 1464 1465 1466
    id = virDomainGetID(dom);
    if (id == ((unsigned int)-1))
      vshPrint(ctl, "%s\n", "-");
    else
      vshPrint(ctl, "%d\n", id);
K
Karel Zak 已提交
1467 1468 1469
    virDomainFree(dom);
    return TRUE;
}
1470

K
Karel Zak 已提交
1471 1472 1473 1474 1475
/*
 * "domuuid" command
 */
static vshCmdInfo info_domuuid[] = {
    {"syntax", "domuuid <domain>"},
1476
    {"help", gettext_noop("convert a domain name or id to domain UUID")},
K
Karel Zak 已提交
1477 1478 1479 1480
    {NULL, NULL}
};

static vshCmdOptDef opts_domuuid[] = {
1481
    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain id or name")},
K
Karel Zak 已提交
1482 1483 1484 1485 1486 1487 1488 1489 1490 1491
    {NULL, 0, 0, NULL}
};

static int
cmdDomuuid(vshControl * ctl, vshCmd * cmd)
{
    virDomainPtr dom;
    char uuid[37];

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
K
Karel Zak 已提交
1492
        return FALSE;
1493
    if (!(dom = vshCommandOptDomainBy(ctl, cmd, "domain", NULL,
K
Karel Zak 已提交
1494 1495
                                    VSH_DOMBYNAME|VSH_DOMBYID)))
        return FALSE;
1496

K
Karel Zak 已提交
1497 1498 1499
    if (virDomainGetUUIDString(dom, uuid) != -1)
        vshPrint(ctl, "%s\n", uuid);
    else
1500 1501
        vshError(ctl, FALSE, _("failed to get domain UUID"));

K
Karel Zak 已提交
1502 1503 1504
    return TRUE;
}

K
Karel Zak 已提交
1505

1506 1507 1508 1509
/*
 * "version" command
 */
static vshCmdInfo info_version[] = {
1510
    {"syntax", "version"},
1511 1512
    {"help", gettext_noop("show version")},
    {"desc", gettext_noop("Display the system version information.")},
1513
    {NULL, NULL}
1514 1515 1516 1517
};


static int
1518 1519
cmdVersion(vshControl * ctl, vshCmd * cmd ATTRIBUTE_UNUSED)
{
1520 1521
    unsigned long hvVersion;
    const char *hvType;
1522 1523 1524 1525 1526 1527 1528
    unsigned long libVersion;
    unsigned long includeVersion;
    unsigned long apiVersion;
    int ret;
    unsigned int major;
    unsigned int minor;
    unsigned int rel;
1529 1530 1531

    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
        return FALSE;
1532

1533 1534
    hvType = virConnectGetType(ctl->conn);
    if (hvType == NULL) {
1535
        vshError(ctl, FALSE, _("failed to get hypervisor type"));
1536 1537 1538
        return FALSE;
    }

1539 1540 1541 1542 1543
    includeVersion = LIBVIR_VERSION_NUMBER;
    major = includeVersion / 1000000;
    includeVersion %= 1000000;
    minor = includeVersion / 1000;
    rel = includeVersion % 1000;
1544
    vshPrint(ctl, _("Compiled against library: libvir %d.%d.%d\n"),
1545 1546 1547 1548
             major, minor, rel);

    ret = virGetVersion(&libVersion, hvType, &apiVersion);
    if (ret < 0) {
1549
        vshError(ctl, FALSE, _("failed to get the library version"));
1550 1551 1552 1553 1554 1555
        return FALSE;
    }
    major = libVersion / 1000000;
    libVersion %= 1000000;
    minor = libVersion / 1000;
    rel = libVersion % 1000;
1556
    vshPrint(ctl, _("Using library: libvir %d.%d.%d\n"),
1557
             major, minor, rel);
1558

1559 1560 1561 1562
    major = apiVersion / 1000000;
    apiVersion %= 1000000;
    minor = apiVersion / 1000;
    rel = apiVersion % 1000;
1563
    vshPrint(ctl, _("Using API: %s %d.%d.%d\n"), hvType,
1564 1565
             major, minor, rel);

1566
    ret = virConnectGetVersion(ctl->conn, &hvVersion);
1567
    if (ret < 0) {
1568
        vshError(ctl, FALSE, _("failed to get the hypervisor version"));
1569 1570 1571
        return FALSE;
    }
    if (hvVersion == 0) {
K
Karel Zak 已提交
1572
        vshPrint(ctl,
1573
                 _("Cannot extract running %s hypervisor version\n"), hvType);
1574
    } else {
1575
        major = hvVersion / 1000000;
1576
        hvVersion %= 1000000;
1577 1578
        minor = hvVersion / 1000;
        rel = hvVersion % 1000;
1579

1580
        vshPrint(ctl, _("Running hypervisor: %s %d.%d.%d\n"),
1581
                 hvType, major, minor, rel);
1582 1583 1584 1585
    }
    return TRUE;
}

K
Karel Zak 已提交
1586 1587 1588 1589
/*
 * "quit" command
 */
static vshCmdInfo info_quit[] = {
1590
    {"syntax", "quit"},
1591
    {"help", gettext_noop("quit this interactive terminal")},
1592
    {NULL, NULL}
K
Karel Zak 已提交
1593 1594 1595
};

static int
1596 1597
cmdQuit(vshControl * ctl, vshCmd * cmd ATTRIBUTE_UNUSED)
{
K
Karel Zak 已提交
1598 1599 1600 1601 1602 1603 1604 1605
    ctl->imode = FALSE;
    return TRUE;
}

/*
 * Commands
 */
static vshCmdDef commands[] = {
1606
    {"connect", cmdConnect, opts_connect, info_connect},
1607
    {"create", cmdCreate, opts_create, info_create},
1608
    {"start", cmdStart, opts_start, info_start},
K
Karel Zak 已提交
1609
    {"destroy", cmdDestroy, opts_destroy, info_destroy},
1610
    {"define", cmdDefine, opts_define, info_define},
K
Karel Zak 已提交
1611
    {"domid", cmdDomid, opts_domid, info_domid},
K
Karel Zak 已提交
1612
    {"domuuid", cmdDomuuid, opts_domuuid, info_domuuid},
1613
    {"dominfo", cmdDominfo, opts_dominfo, info_dominfo},
K
Karel Zak 已提交
1614 1615
    {"domname", cmdDomname, opts_domname, info_domname},
    {"domstate", cmdDomstate, opts_domstate, info_domstate},
1616
    {"dumpxml", cmdDumpXML, opts_dumpxml, info_dumpxml},
K
Karel Zak 已提交
1617
    {"help", cmdHelp, opts_help, info_help},
1618
    {"list", cmdList, opts_list, info_list},
K
Karel Zak 已提交
1619 1620 1621 1622
    {"nodeinfo", cmdNodeinfo, NULL, info_nodeinfo},
    {"quit", cmdQuit, NULL, info_quit},
    {"reboot", cmdReboot, opts_reboot, info_reboot},
    {"restore", cmdRestore, opts_restore, info_restore},
1623 1624 1625
    {"resume", cmdResume, opts_resume, info_resume},
    {"save", cmdSave, opts_save, info_save},
    {"shutdown", cmdShutdown, opts_shutdown, info_shutdown},
1626 1627 1628
    {"setmem", cmdSetmem, opts_setmem, info_setmem},
    {"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem},
    {"setvcpus", cmdSetvcpus, opts_setvcpus, info_setvcpus},
K
Karel Zak 已提交
1629
    {"suspend", cmdSuspend, opts_suspend, info_suspend},
1630
    {"undefine", cmdUndefine, opts_undefine, info_undefine},
1631 1632
    {"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo},
    {"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin},
1633 1634
    {"version", cmdVersion, NULL, info_version},
    {NULL, NULL, NULL, NULL}
K
Karel Zak 已提交
1635 1636 1637 1638 1639 1640
};

/* ---------------
 * Utils for work with command definition
 * ---------------
 */
K
Karel Zak 已提交
1641
static const char *
1642 1643
vshCmddefGetInfo(vshCmdDef * cmd, const char *name)
{
K
Karel Zak 已提交
1644
    vshCmdInfo *info;
1645

K
Karel Zak 已提交
1646
    for (info = cmd->info; info && info->name; info++) {
1647
        if (strcmp(info->name, name) == 0)
K
Karel Zak 已提交
1648 1649 1650 1651 1652 1653
            return info->data;
    }
    return NULL;
}

static vshCmdOptDef *
1654 1655
vshCmddefGetOption(vshCmdDef * cmd, const char *name)
{
K
Karel Zak 已提交
1656
    vshCmdOptDef *opt;
1657

K
Karel Zak 已提交
1658
    for (opt = cmd->opts; opt && opt->name; opt++)
1659
        if (strcmp(opt->name, name) == 0)
K
Karel Zak 已提交
1660 1661 1662 1663 1664
            return opt;
    return NULL;
}

static vshCmdOptDef *
1665 1666
vshCmddefGetData(vshCmdDef * cmd, int data_ct)
{
K
Karel Zak 已提交
1667 1668
    vshCmdOptDef *opt;

1669
    for (opt = cmd->opts; opt && opt->name; opt++) {
1670 1671
        if (opt->type == VSH_OT_DATA) {
            if (data_ct == 0)
1672 1673 1674 1675 1676
                return opt;
            else
                data_ct--;
        }
    }
K
Karel Zak 已提交
1677 1678 1679
    return NULL;
}

1680 1681 1682
/*
 * Checks for required options
 */
1683 1684
static int
vshCommandCheckOpts(vshControl * ctl, vshCmd * cmd)
1685 1686 1687
{
    vshCmdDef *def = cmd->def;
    vshCmdOptDef *d;
1688
    int err = 0;
1689 1690 1691 1692

    for (d = def->opts; d && d->name; d++) {
        if (d->flag & VSH_OFLAG_REQ) {
            vshCmdOpt *o = cmd->opts;
1693 1694 1695
            int ok = 0;

            while (o && ok == 0) {
1696
                if (o->def == d)
1697
                    ok = 1;
1698 1699 1700
                o = o->next;
            }
            if (!ok) {
1701 1702
                vshError(ctl, FALSE,
                         d->type == VSH_OT_DATA ?
1703 1704
                         _("command '%s' requires <%s> option") :
			 _("command '%s' requires --%s option"),
1705
                         def->name, d->name);
1706 1707
                err = 1;
            }
1708

1709 1710 1711 1712 1713
        }
    }
    return !err;
}

K
Karel Zak 已提交
1714
static vshCmdDef *
1715 1716
vshCmddefSearch(const char *cmdname)
{
K
Karel Zak 已提交
1717
    vshCmdDef *c;
1718

K
Karel Zak 已提交
1719
    for (c = commands; c->name; c++)
1720
        if (strcmp(c->name, cmdname) == 0)
K
Karel Zak 已提交
1721 1722 1723 1724 1725
            return c;
    return NULL;
}

static int
1726 1727
vshCmddefHelp(vshControl * ctl, const char *cmdname, int withprog)
{
K
Karel Zak 已提交
1728
    vshCmdDef *def = vshCmddefSearch(cmdname);
1729

K
Karel Zak 已提交
1730
    if (!def) {
1731
        vshError(ctl, FALSE, _("command '%s' doesn't exist"), cmdname);
1732 1733
        return FALSE;
    } else {
K
Karel Zak 已提交
1734
        vshCmdOptDef *opt;
1735 1736
        const char *desc = _N(vshCmddefGetInfo(def, "desc"));
        const char *help = _N(vshCmddefGetInfo(def, "help"));
K
Karel Zak 已提交
1737
        const char *syntax = vshCmddefGetInfo(def, "syntax");
K
Karel Zak 已提交
1738

1739
        fputs(_("  NAME\n"), stdout);
1740 1741
        fprintf(stdout, "    %s - %s\n", def->name, help);

K
Karel Zak 已提交
1742
        if (syntax) {
1743
            fputs(("\n  SYNOPSIS\n"), stdout);
K
Karel Zak 已提交
1744 1745 1746 1747 1748 1749
            if (!withprog)
                fprintf(stdout, "    %s\n", syntax);
            else
                fprintf(stdout, "    %s %s\n", progname, syntax);
        }
        if (desc) {
1750
            fputs(_("\n  DESCRIPTION\n"), stdout);
K
Karel Zak 已提交
1751 1752 1753
            fprintf(stdout, "    %s\n", desc);
        }
        if (def->opts) {
1754
            fputs(_("\n  OPTIONS\n"), stdout);
1755
            for (opt = def->opts; opt->name; opt++) {
K
Karel Zak 已提交
1756
                char buf[256];
1757 1758

                if (opt->type == VSH_OT_BOOL)
K
Karel Zak 已提交
1759
                    snprintf(buf, sizeof(buf), "--%s", opt->name);
1760
                else if (opt->type == VSH_OT_INT)
1761
                    snprintf(buf, sizeof(buf), _("--%s <number>"), opt->name);
1762
                else if (opt->type == VSH_OT_STRING)
1763
                    snprintf(buf, sizeof(buf), _("--%s <string>"), opt->name);
1764
                else if (opt->type == VSH_OT_DATA)
K
Karel Zak 已提交
1765
                    snprintf(buf, sizeof(buf), "<%s>", opt->name);
1766

K
Karel Zak 已提交
1767
                fprintf(stdout, "    %-15s  %s\n", buf, opt->help);
1768
            }
K
Karel Zak 已提交
1769 1770 1771 1772 1773 1774 1775 1776 1777 1778
        }
        fputc('\n', stdout);
    }
    return TRUE;
}

/* ---------------
 * Utils for work with runtime commands data
 * ---------------
 */
1779 1780 1781
static void
vshCommandOptFree(vshCmdOpt * arg)
{
K
Karel Zak 已提交
1782 1783
    vshCmdOpt *a = arg;

1784
    while (a) {
K
Karel Zak 已提交
1785
        vshCmdOpt *tmp = a;
1786

K
Karel Zak 已提交
1787 1788 1789 1790 1791 1792 1793 1794 1795
        a = a->next;

        if (tmp->data)
            free(tmp->data);
        free(tmp);
    }
}

static void
1796 1797
vshCommandFree(vshCmd * cmd)
{
K
Karel Zak 已提交
1798 1799
    vshCmd *c = cmd;

1800
    while (c) {
K
Karel Zak 已提交
1801
        vshCmd *tmp = c;
1802

K
Karel Zak 已提交
1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814
        c = c->next;

        if (tmp->opts)
            vshCommandOptFree(tmp->opts);
        free(tmp);
    }
}

/*
 * Returns option by name
 */
static vshCmdOpt *
1815 1816
vshCommandOpt(vshCmd * cmd, const char *name)
{
K
Karel Zak 已提交
1817
    vshCmdOpt *opt = cmd->opts;
1818 1819 1820

    while (opt) {
        if (opt->def && strcmp(opt->def->name, name) == 0)
K
Karel Zak 已提交
1821 1822 1823 1824 1825 1826 1827 1828 1829 1830
            return opt;
        opt = opt->next;
    }
    return NULL;
}

/*
 * Returns option as INT
 */
static int
1831 1832
vshCommandOptInt(vshCmd * cmd, const char *name, int *found)
{
K
Karel Zak 已提交
1833 1834
    vshCmdOpt *arg = vshCommandOpt(cmd, name);
    int res = 0;
1835

K
Karel Zak 已提交
1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846
    if (arg)
        res = atoi(arg->data);
    if (found)
        *found = arg ? TRUE : FALSE;
    return res;
}

/*
 * Returns option as STRING
 */
static char *
1847 1848
vshCommandOptString(vshCmd * cmd, const char *name, int *found)
{
K
Karel Zak 已提交
1849
    vshCmdOpt *arg = vshCommandOpt(cmd, name);
1850

K
Karel Zak 已提交
1851 1852
    if (found)
        *found = arg ? TRUE : FALSE;
1853 1854

    return arg && arg->data && *arg->data ? arg->data : NULL;
K
Karel Zak 已提交
1855 1856 1857 1858 1859 1860
}

/*
 * Returns TRUE/FALSE if the option exists
 */
static int
1861 1862
vshCommandOptBool(vshCmd * cmd, const char *name)
{
K
Karel Zak 已提交
1863 1864 1865
    return vshCommandOpt(cmd, name) ? TRUE : FALSE;
}

1866

K
Karel Zak 已提交
1867
static virDomainPtr
K
Karel Zak 已提交
1868 1869
vshCommandOptDomainBy(vshControl * ctl, vshCmd * cmd, const char *optname,
                    char **name, int flag)
1870
{
K
Karel Zak 已提交
1871 1872 1873
    virDomainPtr dom = NULL;
    char *n, *end = NULL;
    int id;
1874

K
Karel Zak 已提交
1875
    if (!(n = vshCommandOptString(cmd, optname, NULL))) {
1876
        vshError(ctl, FALSE, _("undefined domain name or id"));
1877
        return NULL;
K
Karel Zak 已提交
1878
    }
1879

K
Karel Zak 已提交
1880
    vshDebug(ctl, 5, "%s: found option <%s>: %s\n",
1881 1882
             cmd->def->name, optname, n);

K
Karel Zak 已提交
1883 1884
    if (name)
        *name = n;
1885

K
Karel Zak 已提交
1886
    /* try it by ID */
K
Karel Zak 已提交
1887 1888 1889 1890 1891 1892 1893
    if (flag & VSH_DOMBYID) {
        id = (int) strtol(n, &end, 10);
        if (id >= 0 && end && *end == '\0') {
            vshDebug(ctl, 5, "%s: <%s> seems like domain ID\n",
                     cmd->def->name, optname);
            dom = virDomainLookupByID(ctl->conn, id);
        }
1894
    }
K
Karel Zak 已提交
1895
    /* try it by UUID */
K
Karel Zak 已提交
1896
    if (dom==NULL && (flag & VSH_DOMBYUUID) && strlen(n)==36) {
K
Karel Zak 已提交
1897 1898
        vshDebug(ctl, 5, "%s: <%s> tring as domain UUID\n",
                cmd->def->name, optname);
K
Karel Zak 已提交
1899
        dom = virDomainLookupByUUIDString(ctl->conn, n);
K
Karel Zak 已提交
1900
    }
K
Karel Zak 已提交
1901
    /* try it by NAME */
K
Karel Zak 已提交
1902
    if (dom==NULL && (flag & VSH_DOMBYNAME)) {
K
Karel Zak 已提交
1903
        vshDebug(ctl, 5, "%s: <%s> tring as domain NAME\n",
1904
                 cmd->def->name, optname);
K
Karel Zak 已提交
1905
        dom = virDomainLookupByName(ctl->conn, n);
1906
    }
K
Karel Zak 已提交
1907

1908
    if (!dom)
1909
        vshError(ctl, FALSE, _("failed to get domain '%s'"), n);
1910

K
Karel Zak 已提交
1911 1912 1913
    return dom;
}

K
Karel Zak 已提交
1914 1915 1916 1917
/*
 * Executes command(s) and returns return code from last command
 */
static int
1918 1919
vshCommandRun(vshControl * ctl, vshCmd * cmd)
{
K
Karel Zak 已提交
1920
    int ret = TRUE;
1921 1922

    while (cmd) {
K
Karel Zak 已提交
1923
        struct timeval before, after;
1924

K
Karel Zak 已提交
1925 1926
        if (ctl->timing)
            GETTIMEOFDAY(&before);
1927

K
Karel Zak 已提交
1928 1929 1930 1931
        ret = cmd->def->handler(ctl, cmd);

        if (ctl->timing)
            GETTIMEOFDAY(&after);
1932 1933

        if (strcmp(cmd->def->name, "quit") == 0)        /* hack ... */
K
Karel Zak 已提交
1934 1935 1936
            return ret;

        if (ctl->timing)
1937
            vshPrint(ctl, _("\n(Time: %.3f ms)\n\n"),
1938 1939
                     DIFF_MSEC(&after, &before));
        else
K
Karel Zak 已提交
1940
            vshPrintExtra(ctl, "\n");
K
Karel Zak 已提交
1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955
        cmd = cmd->next;
    }
    return ret;
}

/* ---------------
 * Command string parsing
 * ---------------
 */
#define VSH_TK_ERROR    -1
#define VSH_TK_NONE    0
#define VSH_TK_OPTION    1
#define VSH_TK_DATA    2
#define VSH_TK_END    3

1956 1957 1958
static int
vshCommandGetToken(vshControl * ctl, char *str, char **end, char **res)
{
K
Karel Zak 已提交
1959 1960 1961 1962 1963
    int tk = VSH_TK_NONE;
    int quote = FALSE;
    int sz = 0;
    char *p = str;
    char *tkstr = NULL;
1964

K
Karel Zak 已提交
1965
    *end = NULL;
1966 1967

    while (p && *p && isblank((unsigned char) *p))
K
Karel Zak 已提交
1968
        p++;
1969 1970

    if (p == NULL || *p == '\0')
K
Karel Zak 已提交
1971
        return VSH_TK_END;
1972 1973
    if (*p == ';') {
        *end = ++p;             /* = \0 or begi of next command */
K
Karel Zak 已提交
1974 1975
        return VSH_TK_END;
    }
1976
    while (*p) {
K
Karel Zak 已提交
1977
        /* end of token is blank space or ';' */
1978
        if ((quote == FALSE && isblank((unsigned char) *p)) || *p == ';')
K
Karel Zak 已提交
1979
            break;
1980

1981
        /* end of option name could be '=' */
1982 1983
        if (tk == VSH_TK_OPTION && *p == '=') {
            p++;                /* skip '=' */
1984 1985
            break;
        }
1986 1987 1988 1989

        if (tk == VSH_TK_NONE) {
            if (*p == '-' && *(p + 1) == '-' && *(p + 2)
                && isalnum((unsigned char) *(p + 2))) {
K
Karel Zak 已提交
1990
                tk = VSH_TK_OPTION;
1991
                p += 2;
K
Karel Zak 已提交
1992 1993
            } else {
                tk = VSH_TK_DATA;
1994 1995
                if (*p == '"') {
                    quote = TRUE;
K
Karel Zak 已提交
1996 1997 1998 1999 2000
                    p++;
                } else {
                    quote = FALSE;
                }
            }
2001 2002
            tkstr = p;          /* begin of token */
        } else if (quote && *p == '"') {
K
Karel Zak 已提交
2003 2004
            quote = FALSE;
            p++;
2005
            break;              /* end of "..." token */
K
Karel Zak 已提交
2006 2007 2008 2009 2010
        }
        p++;
        sz++;
    }
    if (quote) {
2011
        vshError(ctl, FALSE, _("missing \""));
K
Karel Zak 已提交
2012 2013
        return VSH_TK_ERROR;
    }
2014
    if (tkstr == NULL || *tkstr == '\0' || p == NULL)
K
Karel Zak 已提交
2015
        return VSH_TK_END;
2016
    if (sz == 0)
K
Karel Zak 已提交
2017
        return VSH_TK_END;
2018

2019
    *res = vshMalloc(ctl, sz + 1);
K
Karel Zak 已提交
2020
    memcpy(*res, tkstr, sz);
2021
    *(*res + sz) = '\0';
K
Karel Zak 已提交
2022 2023 2024 2025 2026 2027

    *end = p;
    return tk;
}

static int
2028 2029
vshCommandParse(vshControl * ctl, char *cmdstr)
{
K
Karel Zak 已提交
2030 2031 2032 2033
    char *str;
    char *tkdata = NULL;
    vshCmd *clast = NULL;
    vshCmdOpt *first = NULL;
2034

K
Karel Zak 已提交
2035 2036 2037 2038
    if (ctl->cmd) {
        vshCommandFree(ctl->cmd);
        ctl->cmd = NULL;
    }
2039 2040

    if (cmdstr == NULL || *cmdstr == '\0')
K
Karel Zak 已提交
2041
        return FALSE;
2042

K
Karel Zak 已提交
2043
    str = cmdstr;
2044
    while (str && *str) {
K
Karel Zak 已提交
2045 2046 2047
        vshCmdOpt *last = NULL;
        vshCmdDef *cmd = NULL;
        int tk = VSH_TK_NONE;
2048
        int data_ct = 0;
2049

K
Karel Zak 已提交
2050
        first = NULL;
2051 2052

        while (tk != VSH_TK_END) {
K
Karel Zak 已提交
2053 2054
            char *end = NULL;
            vshCmdOptDef *opt = NULL;
2055

K
Karel Zak 已提交
2056
            tkdata = NULL;
2057

K
Karel Zak 已提交
2058 2059
            /* get token */
            tk = vshCommandGetToken(ctl, str, &end, &tkdata);
2060

K
Karel Zak 已提交
2061
            str = end;
2062 2063

            if (tk == VSH_TK_END)
K
Karel Zak 已提交
2064
                break;
2065
            if (tk == VSH_TK_ERROR)
K
Karel Zak 已提交
2066
                goto syntaxError;
2067 2068

            if (cmd == NULL) {
K
Karel Zak 已提交
2069
                /* first token must be command name */
2070 2071
                if (tk != VSH_TK_DATA) {
                    vshError(ctl, FALSE,
2072
                             _("unexpected token (command name): '%s'"),
2073
                             tkdata);
K
Karel Zak 已提交
2074 2075 2076
                    goto syntaxError;
                }
                if (!(cmd = vshCmddefSearch(tkdata))) {
2077
                    vshError(ctl, FALSE, _("unknown command: '%s'"), tkdata);
2078
                    goto syntaxError;   /* ... or ignore this command only? */
K
Karel Zak 已提交
2079 2080
                }
                free(tkdata);
2081
            } else if (tk == VSH_TK_OPTION) {
K
Karel Zak 已提交
2082 2083
                if (!(opt = vshCmddefGetOption(cmd, tkdata))) {
                    vshError(ctl, FALSE,
2084
                             _("command '%s' doesn't support option --%s"),
2085
                             cmd->name, tkdata);
K
Karel Zak 已提交
2086 2087
                    goto syntaxError;
                }
2088
                free(tkdata);   /* option name */
K
Karel Zak 已提交
2089 2090 2091 2092 2093
                tkdata = NULL;

                if (opt->type != VSH_OT_BOOL) {
                    /* option data */
                    tk = vshCommandGetToken(ctl, str, &end, &tkdata);
2094 2095
                    str = end;
                    if (tk == VSH_TK_ERROR)
K
Karel Zak 已提交
2096
                        goto syntaxError;
2097
                    if (tk != VSH_TK_DATA) {
K
Karel Zak 已提交
2098
                        vshError(ctl, FALSE,
2099
                                 _("expected syntax: --%s <%s>"),
2100 2101
                                 opt->name,
                                 opt->type ==
2102
                                 VSH_OT_INT ? _("number") : _("string"));
K
Karel Zak 已提交
2103 2104 2105
                        goto syntaxError;
                    }
                }
2106
            } else if (tk == VSH_TK_DATA) {
2107
                if (!(opt = vshCmddefGetData(cmd, data_ct++))) {
2108
                    vshError(ctl, FALSE, _("unexpected data '%s'"), tkdata);
K
Karel Zak 已提交
2109 2110 2111 2112 2113
                    goto syntaxError;
                }
            }
            if (opt) {
                /* save option */
2114
                vshCmdOpt *arg = vshMalloc(ctl, sizeof(vshCmdOpt));
2115

K
Karel Zak 已提交
2116 2117 2118 2119
                arg->def = opt;
                arg->data = tkdata;
                arg->next = NULL;
                tkdata = NULL;
2120

K
Karel Zak 已提交
2121 2122 2123 2124 2125
                if (!first)
                    first = arg;
                if (last)
                    last->next = arg;
                last = arg;
2126

K
Karel Zak 已提交
2127
                vshDebug(ctl, 4, "%s: %s(%s): %s\n",
2128 2129
                         cmd->name,
                         opt->name,
2130
                         tk == VSH_TK_OPTION ? _("OPTION") : _("DATA"),
2131
                         arg->data);
K
Karel Zak 已提交
2132 2133 2134 2135
            }
            if (!str)
                break;
        }
2136

K
Karel Zak 已提交
2137 2138
        /* commad parsed -- allocate new struct for the command */
        if (cmd) {
2139
            vshCmd *c = vshMalloc(ctl, sizeof(vshCmd));
2140

K
Karel Zak 已提交
2141 2142 2143 2144
            c->opts = first;
            c->def = cmd;
            c->next = NULL;

2145 2146
            if (!vshCommandCheckOpts(ctl, c))
                goto syntaxError;
2147

K
Karel Zak 已提交
2148 2149 2150 2151 2152 2153 2154
            if (!ctl->cmd)
                ctl->cmd = c;
            if (clast)
                clast->next = c;
            clast = c;
        }
    }
2155

K
Karel Zak 已提交
2156 2157
    return TRUE;

2158
  syntaxError:
K
Karel Zak 已提交
2159 2160 2161 2162 2163 2164
    if (ctl->cmd)
        vshCommandFree(ctl->cmd);
    if (first)
        vshCommandOptFree(first);
    if (tkdata)
        free(tkdata);
2165
    return FALSE;
K
Karel Zak 已提交
2166 2167 2168 2169 2170 2171 2172
}


/* ---------------
 * Misc utils  
 * ---------------
 */
K
Karel Zak 已提交
2173
static const char *
2174 2175
vshDomainStateToString(int state)
{
K
Karel Zak 已提交
2176 2177
    switch (state) {
        case VIR_DOMAIN_RUNNING:
2178
            return gettext_noop("running");
K
Karel Zak 已提交
2179
        case VIR_DOMAIN_BLOCKED:
2180
            return gettext_noop("blocked");
K
Karel Zak 已提交
2181
        case VIR_DOMAIN_PAUSED:
2182
            return gettext_noop("paused");
K
Karel Zak 已提交
2183
        case VIR_DOMAIN_SHUTDOWN:
2184
            return gettext_noop("in shutdown");
K
Karel Zak 已提交
2185
        case VIR_DOMAIN_SHUTOFF:
2186
            return gettext_noop("shut off");
K
Karel Zak 已提交
2187
        case VIR_DOMAIN_CRASHED:
2188
            return gettext_noop("crashed");
K
Karel Zak 已提交
2189
        default:
2190
            return gettext_noop("no state");  /* = dom0 state */
K
Karel Zak 已提交
2191 2192 2193 2194
    }
    return NULL;
}

2195 2196 2197 2198 2199
static const char *
vshDomainVcpuStateToString(int state)
{
    switch (state) {
        case VIR_VCPU_OFFLINE:
2200
            return gettext_noop("offline");
2201
        case VIR_VCPU_BLOCKED:
2202
            return gettext_noop("blocked");
2203
        case VIR_VCPU_RUNNING:
2204
            return gettext_noop("running");
2205
        default:
2206
            return gettext_noop("no state");
2207 2208 2209 2210
    }
    return NULL;
}

K
Karel Zak 已提交
2211
static int
2212 2213
vshConnectionUsability(vshControl * ctl, virConnectPtr conn, int showerror)
{
K
Karel Zak 已提交
2214 2215 2216 2217 2218
    /* TODO: use something like virConnectionState() to 
     *       check usability of the connection 
     */
    if (!conn) {
        if (showerror)
2219
            vshError(ctl, FALSE, _("no valid connection"));
K
Karel Zak 已提交
2220 2221 2222 2223 2224
        return FALSE;
    }
    return TRUE;
}

K
Karel Zak 已提交
2225 2226
static void
vshDebug(vshControl * ctl, int level, const char *format, ...)
2227
{
K
Karel Zak 已提交
2228 2229 2230 2231 2232 2233 2234 2235
    va_list ap;

    if (level > ctl->debug)
        return;

    va_start(ap, format);
    vfprintf(stdout, format, ap);
    va_end(ap);
K
Karel Zak 已提交
2236 2237 2238
}

static void
K
Karel Zak 已提交
2239
vshPrintExtra(vshControl * ctl, const char *format, ...)
2240
{
K
Karel Zak 已提交
2241
    va_list ap;
2242

K
Karel Zak 已提交
2243
    if (ctl->quiet == TRUE)
K
Karel Zak 已提交
2244
        return;
2245

K
Karel Zak 已提交
2246
    va_start(ap, format);
2247
    vfprintf(stdout, format, ap);
K
Karel Zak 已提交
2248 2249 2250
    va_end(ap);
}

K
Karel Zak 已提交
2251

K
Karel Zak 已提交
2252
static void
2253 2254
vshError(vshControl * ctl, int doexit, const char *format, ...)
{
K
Karel Zak 已提交
2255
    va_list ap;
2256

K
Karel Zak 已提交
2257
    if (doexit)
2258
        fprintf(stderr, _("%s: error: "), progname);
K
Karel Zak 已提交
2259
    else
2260
        fputs(_("error: "), stderr);
2261

K
Karel Zak 已提交
2262 2263 2264 2265 2266
    va_start(ap, format);
    vfprintf(stderr, format, ap);
    va_end(ap);

    fputc('\n', stderr);
2267

K
Karel Zak 已提交
2268
    if (doexit) {
2269 2270
        if (ctl)
            vshDeinit(ctl);
K
Karel Zak 已提交
2271 2272 2273 2274
        exit(EXIT_FAILURE);
    }
}

2275 2276 2277 2278 2279 2280 2281
static void *
_vshMalloc(vshControl * ctl, size_t size, const char *filename, int line)
{
    void *x;

    if ((x = malloc(size)))
        return x;
2282 2283
    vshError(ctl, TRUE, _("%s: %d: failed to allocate %d bytes"),
	     filename, line, (int) size);
2284 2285 2286 2287 2288 2289 2290 2291 2292 2293
    return NULL;
}

static void *
_vshCalloc(vshControl * ctl, size_t nmemb, size_t size, const char *filename, int line)
{
    void *x;

    if ((x = calloc(nmemb, size)))
        return x;
2294 2295
    vshError(ctl, TRUE, _("%s: %d: failed to allocate %d bytes"),
	     filename, line, (int) (size*nmemb));
2296 2297 2298 2299 2300 2301 2302 2303 2304 2305
    return NULL;
}

static char *
_vshStrdup(vshControl * ctl, const char *s, const char *filename, int line)
{
    char *x;

    if ((x = strdup(s)))
        return x;
2306 2307
    vshError(ctl, TRUE, _("%s: %d: failed to allocate %d bytes"),
	     filename, line, strlen(s));
2308 2309 2310
    return NULL;
}

K
Karel Zak 已提交
2311 2312 2313 2314
/*
 * Initialize vistsh
 */
static int
2315 2316
vshInit(vshControl * ctl)
{
K
Karel Zak 已提交
2317 2318 2319 2320
    if (ctl->conn)
        return FALSE;

    ctl->uid = getuid();
2321

2322 2323
    /* set up the library error handler */
    virSetErrorFunc(NULL, virshErrorHandler);
2324

2325 2326 2327 2328
    /* basic connection to hypervisor, for Xen connections unless
       we're root open a read only connections. Allow 'test' HV
       to be RW all the time though */
    if (ctl->uid == 0 || (ctl->name && !strncmp(ctl->name, "test", 4)))
K
Karel Zak 已提交
2329
        ctl->conn = virConnectOpen(ctl->name);
K
Karel Zak 已提交
2330
    else
K
Karel Zak 已提交
2331
        ctl->conn = virConnectOpenReadOnly(ctl->name);
2332

K
Karel Zak 已提交
2333
    if (!ctl->conn)
2334
        vshError(ctl, TRUE, _("failed to connect to the hypervisor"));
K
Karel Zak 已提交
2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349

    return TRUE;
}

/* -----------------
 * Readline stuff
 * -----------------
 */

/* 
 * Generator function for command completion.  STATE lets us
 * know whether to start from scratch; without any state
 * (i.e. STATE == 0), then we start at the top of the list. 
 */
static char *
2350 2351
vshReadlineCommandGenerator(const char *text, int state)
{
K
Karel Zak 已提交
2352
    static int list_index, len;
K
Karel Zak 已提交
2353
    const char *name;
K
Karel Zak 已提交
2354 2355 2356 2357 2358 2359 2360

    /* If this is a new word to complete, initialize now.  This
     * includes saving the length of TEXT for efficiency, and
     * initializing the index variable to 0. 
     */
    if (!state) {
        list_index = 0;
2361
        len = strlen(text);
K
Karel Zak 已提交
2362 2363 2364 2365 2366
    }

    /* Return the next name which partially matches from the
     * command list. 
     */
K
Karel Zak 已提交
2367
    while ((name = commands[list_index].name)) {
K
Karel Zak 已提交
2368
        list_index++;
2369
        if (strncmp(name, text, len) == 0)
2370
            return vshStrdup(NULL, name);
K
Karel Zak 已提交
2371 2372 2373 2374 2375 2376 2377
    }

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

static char *
2378 2379
vshReadlineOptionsGenerator(const char *text, int state)
{
K
Karel Zak 已提交
2380 2381
    static int list_index, len;
    static vshCmdDef *cmd = NULL;
K
Karel Zak 已提交
2382
    const char *name;
K
Karel Zak 已提交
2383 2384 2385 2386 2387 2388 2389 2390 2391

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

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

2392
        cmdname = vshCalloc(NULL, (p - rl_line_buffer) + 1, 1);
2393
        memcpy(cmdname, rl_line_buffer, p - rl_line_buffer);
K
Karel Zak 已提交
2394 2395 2396

        cmd = vshCmddefSearch(cmdname);
        list_index = 0;
2397
        len = strlen(text);
K
Karel Zak 已提交
2398 2399 2400 2401 2402
        free(cmdname);
    }

    if (!cmd)
        return NULL;
2403

K
Karel Zak 已提交
2404
    while ((name = cmd->opts[list_index].name)) {
K
Karel Zak 已提交
2405 2406
        vshCmdOptDef *opt = &cmd->opts[list_index];
        char *res;
2407

K
Karel Zak 已提交
2408
        list_index++;
2409

K
Karel Zak 已提交
2410
        if (opt->type == VSH_OT_DATA)
K
Karel Zak 已提交
2411 2412
            /* ignore non --option */
            continue;
2413

K
Karel Zak 已提交
2414
        if (len > 2) {
2415
            if (strncmp(name, text + 2, len - 2))
K
Karel Zak 已提交
2416 2417
                continue;
        }
2418
        res = vshMalloc(NULL, strlen(name) + 3);
K
Karel Zak 已提交
2419 2420 2421 2422 2423 2424 2425 2426 2427
        sprintf(res, "--%s", name);
        return res;
    }

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

static char **
2428 2429 2430
vshReadlineCompletion(const char *text, int start,
                      int end ATTRIBUTE_UNUSED)
{
K
Karel Zak 已提交
2431 2432
    char **matches = (char **) NULL;

2433
    if (start == 0)
K
Karel Zak 已提交
2434
        /* command name generator */
2435
        matches = rl_completion_matches(text, vshReadlineCommandGenerator);
K
Karel Zak 已提交
2436 2437
    else
        /* commands options */
2438
        matches = rl_completion_matches(text, vshReadlineOptionsGenerator);
K
Karel Zak 已提交
2439 2440 2441 2442 2443
    return matches;
}


static void
2444 2445
vshReadlineInit(void)
{
K
Karel Zak 已提交
2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456
    /* 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;
}

/*
 * Deinitliaze virsh
 */
static int
2457 2458
vshDeinit(vshControl * ctl)
{
K
Karel Zak 已提交
2459
    if (ctl->conn) {
2460 2461 2462 2463
        if (virConnectClose(ctl->conn) != 0) {
            ctl->conn = NULL;   /* prevent recursive call from vshError() */
            vshError(ctl, TRUE,
                     "failed to disconnect from the hypervisor");
K
Karel Zak 已提交
2464 2465 2466 2467
        }
    }
    return TRUE;
}
2468

K
Karel Zak 已提交
2469 2470 2471 2472
/*
 * Print usage
 */
static void
2473 2474
vshUsage(vshControl * ctl, const char *cmdname)
{
K
Karel Zak 已提交
2475
    vshCmdDef *cmd;
2476

K
Karel Zak 已提交
2477 2478
    /* global help */
    if (!cmdname) {
2479 2480 2481 2482 2483 2484 2485 2486 2487
        fprintf(stdout, _("\n%s [options] [commands]\n\n"
			  "  options:\n"
			  "    -c | --connect <uri>    hypervisor connection URI\n"
			  "    -d | --debug <num>      debug level [0-5]\n"
			  "    -h | --help             this help\n"
			  "    -q | --quiet            quiet mode\n"
			  "    -t | --timing           print timing information\n"
			  "    -v | --version          program version\n\n"
			  "  commands (non interactive mode):\n"), progname);
2488 2489 2490

        for (cmd = commands; cmd->name; cmd++)
            fprintf(stdout,
2491 2492
                    "    %-15s %s\n", cmd->name, _N(vshCmddefGetInfo(cmd,
								     "help")));
2493 2494

        fprintf(stdout,
2495
                _("\n  (specify --help <command> for details about the command)\n\n"));
K
Karel Zak 已提交
2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506
        return;
    }
    if (!vshCmddefHelp(ctl, cmdname, TRUE))
        exit(EXIT_FAILURE);
}

/*
 * argv[]:  virsh [options] [command]
 *
 */
static int
2507 2508
vshParseArgv(vshControl * ctl, int argc, char **argv)
{
K
Karel Zak 已提交
2509 2510
    char *last = NULL;
    int i, end = 0, help = 0;
2511
    int arg, idx = 0;
K
Karel Zak 已提交
2512
    struct option opt[] = {
2513 2514 2515 2516 2517
        {"debug", 1, 0, 'd'},
        {"help", 0, 0, 'h'},
        {"quiet", 0, 0, 'q'},
        {"timing", 0, 0, 't'},
        {"version", 0, 0, 'v'},
K
Karel Zak 已提交
2518
        {"connect", 1, 0, 'c'},
K
Karel Zak 已提交
2519
        {0, 0, 0, 0}
2520 2521
    };

K
Karel Zak 已提交
2522 2523

    if (argc < 2)
K
Karel Zak 已提交
2524
        return TRUE;
2525

2526
    /* look for begin of the command, for example:
K
Karel Zak 已提交
2527 2528 2529 2530
     *   ./virsh --debug 5 -q command --cmdoption
     *                  <--- ^ --->
     *        getopt() stuff | command suff
     */
2531
    for (i = 1; i < argc; i++) {
K
Karel Zak 已提交
2532 2533
        if (*argv[i] != '-') {
            int valid = FALSE;
2534

K
Karel Zak 已提交
2535 2536 2537 2538
            /* non "--option" argv, is it command? */
            if (last) {
                struct option *o;
                int sz = strlen(last);
2539 2540 2541

                for (o = opt; o->name; o++) {
                    if (sz == 2 && *(last + 1) == o->val)
K
Karel Zak 已提交
2542 2543
                        /* valid virsh short option */
                        valid = TRUE;
2544
                    else if (sz > 2 && strcmp(o->name, last + 2) == 0)
K
Karel Zak 已提交
2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556
                        /* valid virsh long option */
                        valid = TRUE;
                }
            }
            if (!valid) {
                end = i;
                break;
            }
        }
        last = argv[i];
    }
    end = end ? : argc;
2557

K
Karel Zak 已提交
2558
    /* standard (non-command) options */
2559 2560
    while ((arg = getopt_long(end, argv, "d:hqtv", opt, &idx)) != -1) {
        switch (arg) {
K
Karel Zak 已提交
2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572
            case 'd':
                ctl->debug = atoi(optarg);
                break;
            case 'h':
                help = 1;
                break;
            case 'q':
                ctl->quiet = TRUE;
                break;
            case 't':
                ctl->timing = TRUE;
                break;
K
Karel Zak 已提交
2573 2574 2575
            case 'c':
                ctl->name = vshStrdup(ctl, optarg);
                break;
K
Karel Zak 已提交
2576 2577 2578 2579
            case 'v':
                fprintf(stdout, "%s\n", VERSION);
                exit(EXIT_SUCCESS);
            default:
2580
                vshError(ctl, TRUE,
2581
			 _("unsupported option '-%c'. See --help."), arg);
K
Karel Zak 已提交
2582 2583 2584 2585 2586 2587 2588 2589
                break;
        }
    }

    if (help) {
        /* global or command specific help */
        vshUsage(ctl, argc > end ? argv[end] : NULL);
        exit(EXIT_SUCCESS);
2590 2591
    }

K
Karel Zak 已提交
2592 2593 2594
    if (argc > end) {
        /* parse command */
        char *cmdstr;
2595 2596
        int sz = 0, ret;

K
Karel Zak 已提交
2597 2598
        ctl->imode = FALSE;

2599 2600 2601
        for (i = end; i < argc; i++)
            sz += strlen(argv[i]) + 1;  /* +1 is for blank space between items */

2602
        cmdstr = vshCalloc(ctl, sz + 1, 1);
2603 2604

        for (i = end; i < argc; i++) {
K
Karel Zak 已提交
2605 2606 2607 2608
            strncat(cmdstr, argv[i], sz);
            sz -= strlen(argv[i]);
            strncat(cmdstr, " ", sz--);
        }
K
Karel Zak 已提交
2609
        vshDebug(ctl, 2, "command: \"%s\"\n", cmdstr);
K
Karel Zak 已提交
2610
        ret = vshCommandParse(ctl, cmdstr);
2611

K
Karel Zak 已提交
2612 2613 2614 2615 2616 2617
        free(cmdstr);
        return ret;
    }
    return TRUE;
}

2618 2619 2620 2621
int
main(int argc, char **argv)
{
    vshControl _ctl, *ctl = &_ctl;
2622
    char *defaultConn;
K
Karel Zak 已提交
2623 2624
    int ret = TRUE;

2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637
    if (!setlocale(LC_ALL, "")) {
        perror("setlocale");
	return -1;
    }
    if (!bindtextdomain(GETTEXT_PACKAGE, LOCALEBASEDIR)) {
        perror("bindtextdomain");
	return -1;
    }
    if (!textdomain(GETTEXT_PACKAGE)) {
        perror("textdomain");
	return -1;
    }

2638
    if (!(progname = strrchr(argv[0], '/')))
K
Karel Zak 已提交
2639 2640 2641
        progname = argv[0];
    else
        progname++;
2642

K
Karel Zak 已提交
2643
    memset(ctl, 0, sizeof(vshControl));
2644
    ctl->imode = TRUE;          /* default is interactive mode */
K
Karel Zak 已提交
2645

2646 2647 2648 2649
    if ((defaultConn = getenv("VIRSH_DEFAULT_CONNECT_URI"))) {
      ctl->name = strdup(defaultConn);
    }

K
Karel Zak 已提交
2650 2651
    if (!vshParseArgv(ctl, argc, argv))
        exit(EXIT_FAILURE);
2652

K
Karel Zak 已提交
2653 2654
    if (!vshInit(ctl))
        exit(EXIT_FAILURE);
2655

K
Karel Zak 已提交
2656
    if (!ctl->imode) {
2657
        ret = vshCommandRun(ctl, ctl->cmd);
2658
    } else {
K
Karel Zak 已提交
2659 2660
        /* interactive mode */
        if (!ctl->quiet) {
K
Karel Zak 已提交
2661
            vshPrint(ctl,
2662
                     _("Welcome to %s, the virtualization interactive terminal.\n\n"),
2663
                     progname);
K
Karel Zak 已提交
2664
            vshPrint(ctl,
2665 2666
                     _("Type:  'help' for help with commands\n"
		       "       'quit' to quit\n\n"));
K
Karel Zak 已提交
2667
        }
K
Karel Zak 已提交
2668
        vshReadlineInit();
K
Karel Zak 已提交
2669
        do {
2670 2671 2672 2673
            ctl->cmdstr =
                readline(ctl->uid == 0 ? VSH_PROMPT_RW : VSH_PROMPT_RO);
            if (ctl->cmdstr == NULL)
                break;          /* EOF */
K
Karel Zak 已提交
2674 2675 2676 2677 2678 2679 2680
            if (*ctl->cmdstr) {
                add_history(ctl->cmdstr);
                if (vshCommandParse(ctl, ctl->cmdstr))
                    vshCommandRun(ctl, ctl->cmd);
            }
            free(ctl->cmdstr);
            ctl->cmdstr = NULL;
2681
        } while (ctl->imode);
K
Karel Zak 已提交
2682

2683 2684
        if (ctl->cmdstr == NULL)
            fputc('\n', stdout);        /* line break after alone prompt */
K
Karel Zak 已提交
2685
    }
2686

K
Karel Zak 已提交
2687 2688
    vshDeinit(ctl);
    exit(ret ? EXIT_SUCCESS : EXIT_FAILURE);
2689
}
K
Karel Zak 已提交
2690 2691 2692 2693 2694 2695

/*
 * vim: set tabstop=4:
 * vim: set shiftwidth=4:
 * vim: set expandtab:
 */