Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
libvirt
提交
0d804357
L
libvirt
项目概览
openeuler
/
libvirt
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
libvirt
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
0d804357
编写于
12月 08, 2005
作者:
K
Karel Zak
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
virsh is more sexy now
上级
5a3d0500
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
1375 addition
and
98 deletion
+1375
-98
ChangeLog
ChangeLog
+4
-0
configure.in
configure.in
+11
-0
src/Makefile.am
src/Makefile.am
+2
-1
src/virsh.c
src/virsh.c
+1358
-97
未找到文件。
ChangeLog
浏览文件 @
0d804357
Thu Dec 8 11:19:48 CET 2005 Karel Zak <kzak@redhat.com>
* src/Makefile.am src/virsh.c configure.in: adding readline support,
and implement basic commands to virsh.
Thu Dec 8 11:12:36 CET 2005 Daniel Veillard <veillard@redhat.com>
* src/libvir.c src/xen_internal.c: fixed the new Xen hypervisor call
...
...
configure.in
浏览文件 @
0d804357
...
...
@@ -77,4 +77,15 @@ AC_SUBST(STATIC_BINARIES)
dnl search for the low level Xen library
AC_SEARCH_LIBS(xs_read, [xenstore], [], [AC_MSG_ERROR([Xen store library not found])])
dnl virsh libraries
AC_CHECK_LIB(curses, initscr,
[VIRSH_LIBS="$VIRSH_LIBS -lcurses"],
[AC_MSG_ERROR([curses library not found])],
[$VIRSH_LIBS])
AC_CHECK_LIB(readline, main,
[VIRSH_LIBS="$VIRSH_LIBS -lreadline"],
[AC_MSG_ERROR([readline library not found])],
[$VIRSH_LIBS])
AC_SUBST(VIRSH_LIBS)
AC_OUTPUT(Makefile src/Makefile include/Makefile docs/Makefile libvir.pc libvir.spec)
src/Makefile.am
浏览文件 @
0d804357
...
...
@@ -3,6 +3,7 @@
INCLUDES
=
-I
$(top_builddir)
/include
-I
@srcdir@/include
DEPS
=
libvir.la
LDADDS
=
@STATIC_BINARIES@ libvir.la
VIRSH_LIBS
=
@VIRSH_LIBS@
EXTRA_DIST
=
libvir_sym.version
...
...
@@ -20,5 +21,5 @@ noinst_PROGRAMS=virsh
virsh_SOURCES
=
virsh.c
virsh_LDFLAGS
=
virsh_DEPENDENCIES
=
$(DEPS)
virsh_LDADD
=
$(LDADDS)
virsh_LDADD
=
$(LDADDS)
$(VIRSH_LIBS)
src/virsh.c
浏览文件 @
0d804357
...
...
@@ -8,113 +8,1374 @@
* Daniel Veillard <veillard@redhat.com>
*/
#define _GNU_SOURCE
/* isblank() */
#include "libvir.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/types.h>
#include <ctype.h>
#include <readline/readline.h>
#include <readline/history.h>
#include "config.h"
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)
typedef
enum
{
VSH_MESG
,
/* standard output */
VSH_HEADER
,
/* header for standard output */
VSH_FOOTER
,
/* timing, last command state, or whatever */
VSH_DEBUG1
,
/* debugN where 'N' = level */
VSH_DEBUG2
,
VSH_DEBUG3
,
VSH_DEBUG4
,
VSH_DEBUG5
}
vshOutType
;
/*
* 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>
*
* keyword = [a-zA-Z]
* number = [0-9]+
* string = [^[:blank:]] | "[[:alnum:]]"$
*
* Note: only one <data> token per command is supported. It means:
* "command aaa bbb" is unsupported and you have to use any option, like:
* "command --aaa <data> bbb" or whatever.
*/
/*
* vshCmdOptType - command option type
*/
typedef
enum
{
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) */
}
vshCmdOptType
;
/*
* Command Option Flags
*/
#define VSH_OFLAG_NONE 0
/* without flags */
#define VSH_OFLAG_REQ (1 << 1)
/* option required */
/* dummy */
typedef
struct
__vshControl
vshControl
;
typedef
struct
__vshCmd
vshCmd
;
/*
* vshCmdInfo -- information about command
*/
typedef
struct
{
char
*
name
;
/* name of information */
char
*
data
;
/* information */
}
vshCmdInfo
;
/*
* vshCmdOptDef - command option definition
*/
typedef
struct
{
char
*
name
;
/* the name of option */
vshCmdOptType
type
;
/* option type */
int
flag
;
/* flags */
char
*
help
;
/* help string */
}
vshCmdOptDef
;
/*
* vshCmdOpt - command options
*/
typedef
struct
vshCmdOpt
{
vshCmdOptDef
*
def
;
/* pointer to relevant option */
char
*
data
;
/* allocated data */
struct
vshCmdOpt
*
next
;
}
vshCmdOpt
;
/*
* vshCmdDef - command definition
*/
typedef
struct
{
char
*
name
;
int
(
*
handler
)(
vshControl
*
,
vshCmd
*
);
/* command handler */
vshCmdOptDef
*
opts
;
/* definition of command options */
vshCmdInfo
*
info
;
/* details about command */
}
vshCmdDef
;
/*
* vshCmd - parsed command
*/
typedef
struct
__vshCmd
{
vshCmdDef
*
def
;
/* command definition */
vshCmdOpt
*
opts
;
/* list of command arguments */
struct
__vshCmd
*
next
;
/* next command */
}
__vshCmd
;
/*
* vshControl
*/
typedef
struct
__vshControl
{
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? */
}
__vshControl
;
#define MAX_DOM 100
int
errcode
=
0
;
virConnectPtr
conn
;
virDomainPtr
dom0
;
int
ids
[
MAX_DOM
];
static
void
printDomain
(
virDomainPtr
dom
)
{
static
vshCmdDef
commands
[];
static
void
vshError
(
vshControl
*
ctl
,
int
doexit
,
char
*
format
,
...);
static
int
vshInit
(
vshControl
*
ctl
);
static
int
vshDeinit
(
vshControl
*
ctl
);
static
void
vshUsage
(
vshControl
*
ctl
,
char
*
cmdname
);
static
int
vshParseArgv
(
vshControl
*
ctl
,
int
argc
,
char
**
argv
);
static
char
*
vshCmddefGetInfo
(
vshCmdDef
*
cmd
,
char
*
info
);
static
vshCmdDef
*
vshCmddefSearch
(
char
*
cmdname
);
static
int
vshCmddefHelp
(
vshControl
*
ctl
,
char
*
name
,
int
withprog
);
static
vshCmdOpt
*
vshCommandOpt
(
vshCmd
*
cmd
,
char
*
name
);
static
int
vshCommandOptInt
(
vshCmd
*
cmd
,
char
*
name
,
int
*
found
);
static
char
*
vshCommandOptString
(
vshCmd
*
cmd
,
char
*
name
,
int
*
found
);
static
int
vshCommandOptBool
(
vshCmd
*
cmd
,
char
*
name
);
static
void
vshPrint
(
vshControl
*
ctl
,
vshOutType
out
,
char
*
format
,
...);
static
char
*
vshDomainStateToString
(
int
state
);
static
int
vshConnectionUsability
(
vshControl
*
ctl
,
virConnectPtr
conn
,
int
showerror
);
/* ---------------
* Commands
* ---------------
*/
/*
* "help" command
*/
static
vshCmdInfo
info_help
[]
=
{
{
"syntax"
,
"help [<command>]"
},
{
"help"
,
"print help"
},
{
"desc"
,
"Prints global help or command specific help."
},
{
NULL
,
NULL
}
};
static
vshCmdOptDef
opts_help
[]
=
{
{
"command"
,
VSH_OT_DATA
,
0
,
"name of command"
},
{
NULL
,
0
,
0
,
NULL
}
};
static
int
cmdHelp
(
vshControl
*
ctl
,
vshCmd
*
cmd
)
{
char
*
cmdname
=
vshCommandOptString
(
cmd
,
"command"
,
NULL
);
if
(
!
cmdname
)
{
vshCmdDef
*
def
;
vshPrint
(
ctl
,
VSH_HEADER
,
"Commands:
\n\n
"
);
for
(
def
=
commands
;
def
->
name
;
def
++
)
vshPrint
(
ctl
,
VSH_MESG
,
" %-15s %s
\n
"
,
def
->
name
,
vshCmddefGetInfo
(
def
,
"help"
));
return
TRUE
;
}
return
vshCmddefHelp
(
ctl
,
cmdname
,
FALSE
);
}
/*
* "connect" command
*/
static
vshCmdInfo
info_connect
[]
=
{
{
"syntax"
,
"connect [--readonly]"
},
{
"help"
,
"(re)connect to hypervisor"
},
{
"desc"
,
"Connect to local hypervisor. This is build-in command after shell start up."
},
{
NULL
,
NULL
}
};
static
vshCmdOptDef
opts_connect
[]
=
{
{
"readonly"
,
VSH_OT_BOOL
,
0
,
"read-only connection"
},
{
NULL
,
0
,
0
,
NULL
}
};
static
int
cmdConnect
(
vshControl
*
ctl
,
vshCmd
*
cmd
)
{
int
ro
=
vshCommandOptBool
(
cmd
,
"readonly"
);
if
(
ctl
->
conn
)
{
if
(
virConnectClose
(
ctl
->
conn
)
!=
0
)
{
vshError
(
ctl
,
FALSE
,
"failed to disconnect from the hypervisor"
);
return
FALSE
;
}
ctl
->
conn
=
NULL
;
}
if
(
!
ro
)
ctl
->
conn
=
virConnectOpen
(
NULL
);
else
ctl
->
conn
=
virConnectOpenReadOnly
(
NULL
);
if
(
!
ctl
->
conn
)
vshError
(
ctl
,
FALSE
,
"failed to connect to the hypervisor"
);
return
ctl
->
conn
?
TRUE
:
FALSE
;
}
/*
* "list" command
*/
static
vshCmdInfo
info_list
[]
=
{
{
"syntax"
,
"list"
},
{
"help"
,
"list domains"
},
{
"desc"
,
"Returns list of domains."
},
{
NULL
,
NULL
}
};
static
int
cmdList
(
vshControl
*
ctl
,
vshCmd
*
cmd
)
{
int
*
ids
,
maxid
,
i
;
if
(
!
vshConnectionUsability
(
ctl
,
ctl
->
conn
,
TRUE
))
return
FALSE
;
maxid
=
virConnectNumOfDomains
(
ctl
->
conn
);
if
(
maxid
<=
0
)
{
/* strange, there should be at least dom0... */
vshError
(
ctl
,
FALSE
,
"failed to list active domains."
);
return
FALSE
;
}
ids
=
malloc
(
sizeof
(
int
)
*
maxid
);
virConnectListDomains
(
ctl
->
conn
,
&
ids
[
0
],
maxid
);
vshPrint
(
ctl
,
VSH_HEADER
,
"%3s %-20s %s
\n
"
,
"Id"
,
"Name"
,
"State"
);
vshPrint
(
ctl
,
VSH_HEADER
,
"----------------------------------
\n
"
);
for
(
i
=
0
;
i
<
maxid
;
i
++
)
{
int
ret
;
virDomainInfo
info
;
virDomainPtr
dom
=
virDomainLookupByID
(
ctl
->
conn
,
ids
[
i
]);
/* this kind of work with domains is not atomic operation */
if
(
!
dom
)
continue
;
ret
=
virDomainGetInfo
(
dom
,
&
info
);
vshPrint
(
ctl
,
VSH_MESG
,
"%3d %-20s %s
\n
"
,
virDomainGetID
(
dom
),
virDomainGetName
(
dom
),
ret
<
0
?
"no state"
:
vshDomainStateToString
(
info
.
state
));
/*TODO: virDomainFree(dom); */
}
free
(
ids
);
return
TRUE
;
}
/*
* "dstate" command
*/
static
vshCmdInfo
info_dstate
[]
=
{
{
"syntax"
,
"dstate [--id <number> | --name <string> ]"
},
{
"help"
,
"domain state"
},
{
"desc"
,
"Returns state about the domain."
},
{
NULL
,
NULL
}
};
static
vshCmdOptDef
opts_dstate
[]
=
{
{
"name"
,
VSH_OT_STRING
,
0
,
"domain name"
},
{
"id"
,
VSH_OT_INT
,
0
,
"domain id"
},
{
NULL
,
0
,
0
,
NULL
}
};
static
int
cmdDstate
(
vshControl
*
ctl
,
vshCmd
*
cmd
)
{
virDomainInfo
info
;
virDomainPtr
dom
;
int
found
,
ret
=
TRUE
;
char
*
name
=
vshCommandOptString
(
cmd
,
"name"
,
NULL
);
int
id
=
vshCommandOptInt
(
cmd
,
"id"
,
&
found
);
if
(
!
vshConnectionUsability
(
ctl
,
ctl
->
conn
,
TRUE
))
return
FALSE
;
printf
(
"id %d: name %s, "
,
virDomainGetID
(
dom
),
virDomainGetName
(
dom
));
virDomainGetInfo
(
dom
,
&
info
);
if
(
virDomainGetInfo
(
dom
,
&
info
)
<
0
)
{
printf
(
"failed to get informations
\n
"
);
if
(
found
)
{
if
(
!
(
dom
=
virDomainLookupByID
(
ctl
->
conn
,
id
)))
vshError
(
ctl
,
FALSE
,
"failed to get domain '%d'"
,
id
);
}
else
{
float
mem
,
maxMem
;
switch
(
info
.
state
)
{
case
VIR_DOMAIN_RUNNING
:
printf
(
"running "
);
break
;
case
VIR_DOMAIN_BLOCKED
:
printf
(
"blocked "
);
break
;
case
VIR_DOMAIN_PAUSED
:
printf
(
"paused "
);
break
;
case
VIR_DOMAIN_SHUTDOWN
:
printf
(
"in shutdown "
);
break
;
case
VIR_DOMAIN_SHUTOFF
:
printf
(
"shut off "
);
break
;
default:
break
;
}
printf
(
"%d vCPU, "
,
info
.
nrVirtCpu
);
if
(
info
.
cpuTime
!=
0
)
{
float
cpuUsed
=
info
.
cpuTime
;
cpuUsed
/=
1000000000
;
printf
(
"%.1fs time, "
,
cpuUsed
);
}
mem
=
info
.
memory
;
mem
/=
1024
;
maxMem
=
info
.
maxMem
;
maxMem
/=
1024
;
printf
(
"%.0f MB mem used, %.0f MB max_mem
\n
"
,
mem
,
maxMem
);
}
}
int
main
(
int
argc
,
char
**
argv
)
{
int
ret
,
i
;
if
(
!
(
dom
=
virDomainLookupByName
(
ctl
->
conn
,
name
)))
vshError
(
ctl
,
FALSE
,
"failed to get domain '%s'"
,
name
);
}
if
(
!
dom
)
return
FALSE
;
if
(
virDomainGetInfo
(
dom
,
&
info
)
==
0
)
vshPrint
(
ctl
,
VSH_MESG
,
"%s
\n
"
,
vshDomainStateToString
(
info
.
state
));
else
ret
=
FALSE
;
/*TODO: virDomainFree(dom); */
return
ret
;
}
/*
* "dinfo" command
*/
static
vshCmdInfo
info_dinfo
[]
=
{
{
"syntax"
,
"dinfo [--id <number> | --name <string> ]"
},
{
"help"
,
"domain information"
},
{
"desc"
,
"Returns basic information about the domain."
},
{
NULL
,
NULL
}
};
static
vshCmdOptDef
opts_dinfo
[]
=
{
{
"name"
,
VSH_OT_STRING
,
0
,
"domain name"
},
{
"id"
,
VSH_OT_INT
,
0
,
"domain id"
},
{
NULL
,
0
,
0
,
NULL
}
};
static
int
cmdDinfo
(
vshControl
*
ctl
,
vshCmd
*
cmd
)
{
virDomainInfo
info
;
virDomainPtr
dom
;
int
found
,
ret
=
TRUE
;
char
*
name
=
vshCommandOptString
(
cmd
,
"name"
,
NULL
);
int
id
=
vshCommandOptInt
(
cmd
,
"id"
,
&
found
);
if
(
!
vshConnectionUsability
(
ctl
,
ctl
->
conn
,
TRUE
))
return
FALSE
;
if
(
found
)
{
if
(
!
(
dom
=
virDomainLookupByID
(
ctl
->
conn
,
id
)))
vshError
(
ctl
,
FALSE
,
"failed to get domain '%d'"
,
id
);
}
else
{
if
(
!
(
dom
=
virDomainLookupByName
(
ctl
->
conn
,
name
)))
vshError
(
ctl
,
FALSE
,
"failed to get domain '%s'"
,
name
);
}
if
(
!
dom
)
return
FALSE
;
if
(
virDomainGetInfo
(
dom
,
&
info
)
==
0
)
{
vshPrint
(
ctl
,
VSH_MESG
,
"%-15s %d
\n
"
,
"Id:"
,
virDomainGetID
(
dom
));
vshPrint
(
ctl
,
VSH_MESG
,
"%-15s %s
\n
"
,
"Name:"
,
virDomainGetName
(
dom
));
vshPrint
(
ctl
,
VSH_MESG
,
"%-15s %s
\n
"
,
"State:"
,
vshDomainStateToString
(
info
.
state
));
vshPrint
(
ctl
,
VSH_MESG
,
"%-15s %d
\n
"
,
"CPU(s):"
,
info
.
nrVirtCpu
);
if
(
info
.
cpuTime
!=
0
)
{
float
cpuUsed
=
info
.
cpuTime
;
cpuUsed
/=
1000000000
;
vshPrint
(
ctl
,
VSH_MESG
,
"%-15s %.1fs
\n
"
,
"CPU time:"
,
cpuUsed
);
}
vshPrint
(
ctl
,
VSH_MESG
,
"%-15s %lu kB
\n
"
,
"Max memory:"
,
info
.
maxMem
);
vshPrint
(
ctl
,
VSH_MESG
,
"%-15s %lu kB
\n
"
,
"Used memory:"
,
info
.
memory
);
}
else
{
ret
=
FALSE
;
}
/*TODO: virDomainFree(dom); */
return
ret
;
}
/*
* "nameof" command
*/
static
vshCmdInfo
info_nameof
[]
=
{
{
"syntax"
,
"nameof <id>"
},
{
"help"
,
"convert domain Id to domain name"
},
{
NULL
,
NULL
}
};
static
vshCmdOptDef
opts_nameof
[]
=
{
{
"id"
,
VSH_OT_DATA
,
0
,
"domain Id"
},
{
NULL
,
0
,
0
,
NULL
}
};
static
int
cmdNameof
(
vshControl
*
ctl
,
vshCmd
*
cmd
)
{
int
found
;
int
id
=
vshCommandOptInt
(
cmd
,
"id"
,
&
found
);
virDomainPtr
dom
;
if
(
!
vshConnectionUsability
(
ctl
,
ctl
->
conn
,
TRUE
))
return
FALSE
;
if
(
!
found
)
return
FALSE
;
dom
=
virDomainLookupByID
(
ctl
->
conn
,
id
);
if
(
dom
)
{
vshPrint
(
ctl
,
VSH_MESG
,
"%s
\n
"
,
virDomainGetName
(
dom
));
/*TODO: virDomainFree(dom); */
}
else
{
vshError
(
ctl
,
FALSE
,
"failed to get domain '%d'"
,
id
);
return
FALSE
;
}
return
TRUE
;
}
/*
* "idof" command
*/
static
vshCmdInfo
info_idof
[]
=
{
{
"syntax"
,
"idof <name>"
},
{
"help"
,
"convert domain name to domain Id"
},
{
NULL
,
NULL
}
};
static
vshCmdOptDef
opts_idof
[]
=
{
{
"name"
,
VSH_OT_DATA
,
0
,
"domain name"
},
{
NULL
,
0
,
0
,
NULL
}
};
static
int
cmdIdof
(
vshControl
*
ctl
,
vshCmd
*
cmd
)
{
char
*
name
=
vshCommandOptString
(
cmd
,
"name"
,
NULL
);
virDomainPtr
dom
;
if
(
!
vshConnectionUsability
(
ctl
,
ctl
->
conn
,
TRUE
))
return
FALSE
;
if
(
!
name
)
return
FALSE
;
dom
=
virDomainLookupByName
(
ctl
->
conn
,
name
);
if
(
dom
)
{
vshPrint
(
ctl
,
VSH_MESG
,
"%s
\n
"
,
virDomainGetID
(
dom
));
/*TODO: virDomainFree(dom); */
}
else
{
vshError
(
ctl
,
FALSE
,
"failed to get domain '%s'"
,
name
);
return
FALSE
;
}
return
TRUE
;
}
/*
* "quit" command
*/
static
vshCmdInfo
info_quit
[]
=
{
{
"syntax"
,
"quit"
},
{
"help"
,
"quit this interactive terminal"
},
{
NULL
,
NULL
}
};
static
int
cmdQuit
(
vshControl
*
ctl
,
vshCmd
*
cmd
)
{
ctl
->
imode
=
FALSE
;
return
TRUE
;
}
/*
* Commands
*/
static
vshCmdDef
commands
[]
=
{
{
"connect"
,
cmdConnect
,
opts_connect
,
info_connect
},
{
"dinfo"
,
cmdDinfo
,
opts_dinfo
,
info_dinfo
},
{
"dstate"
,
cmdDstate
,
opts_dstate
,
info_dstate
},
{
"help"
,
cmdHelp
,
opts_help
,
info_help
},
{
"idof"
,
cmdIdof
,
opts_idof
,
info_idof
},
{
"list"
,
cmdList
,
NULL
,
info_list
},
{
"nameof"
,
cmdNameof
,
opts_nameof
,
info_nameof
},
{
"quit"
,
cmdQuit
,
NULL
,
info_quit
},
{
NULL
,
NULL
,
NULL
,
NULL
}
};
/* ---------------
* Utils for work with command definition
* ---------------
*/
static
char
*
vshCmddefGetInfo
(
vshCmdDef
*
cmd
,
char
*
name
)
{
vshCmdInfo
*
info
;
for
(
info
=
cmd
->
info
;
info
&&
info
->
name
;
info
++
)
{
if
(
strcmp
(
info
->
name
,
name
)
==
0
)
return
info
->
data
;
}
return
NULL
;
}
static
vshCmdOptDef
*
vshCmddefGetOption
(
vshCmdDef
*
cmd
,
char
*
name
)
{
vshCmdOptDef
*
opt
;
for
(
opt
=
cmd
->
opts
;
opt
&&
opt
->
name
;
opt
++
)
if
(
strcmp
(
opt
->
name
,
name
)
==
0
)
return
opt
;
return
NULL
;
}
static
vshCmdOptDef
*
vshCmddefGetData
(
vshCmdDef
*
cmd
)
{
vshCmdOptDef
*
opt
;
for
(
opt
=
cmd
->
opts
;
opt
&&
opt
->
name
;
opt
++
)
if
(
opt
->
type
==
VSH_OT_DATA
)
return
opt
;
return
NULL
;
}
static
vshCmdDef
*
vshCmddefSearch
(
char
*
cmdname
)
{
vshCmdDef
*
c
;
for
(
c
=
commands
;
c
->
name
;
c
++
)
if
(
strcmp
(
c
->
name
,
cmdname
)
==
0
)
return
c
;
return
NULL
;
}
static
int
vshCmddefHelp
(
vshControl
*
ctl
,
char
*
cmdname
,
int
withprog
)
{
vshCmdDef
*
def
=
vshCmddefSearch
(
cmdname
);
if
(
!
def
)
{
vshError
(
ctl
,
FALSE
,
"command '%s' doesn't exist"
,
cmdname
);
return
FALSE
;
}
else
{
vshCmdOptDef
*
opt
;
char
*
desc
=
vshCmddefGetInfo
(
def
,
"desc"
);
char
*
help
=
vshCmddefGetInfo
(
def
,
"help"
);
char
*
syntax
=
vshCmddefGetInfo
(
def
,
"syntax"
);
fputs
(
" NAME
\n
"
,
stdout
);
fprintf
(
stdout
,
" %s - %s
\n
"
,
def
->
name
,
help
);
if
(
syntax
)
{
fputs
(
"
\n
SYNOPSIS
\n
"
,
stdout
);
if
(
!
withprog
)
fprintf
(
stdout
,
" %s
\n
"
,
syntax
);
else
fprintf
(
stdout
,
" %s %s
\n
"
,
progname
,
syntax
);
}
if
(
desc
)
{
fputs
(
"
\n
DESCRIPTION
\n
"
,
stdout
);
fprintf
(
stdout
,
" %s
\n
"
,
desc
);
}
if
(
def
->
opts
)
{
fputs
(
"
\n
OPTIONS
\n
"
,
stdout
);
for
(
opt
=
def
->
opts
;
opt
->
name
;
opt
++
)
{
char
buf
[
256
];
if
(
opt
->
type
==
VSH_OT_BOOL
)
snprintf
(
buf
,
sizeof
(
buf
),
"--%s"
,
opt
->
name
);
else
if
(
opt
->
type
==
VSH_OT_INT
)
snprintf
(
buf
,
sizeof
(
buf
),
"--%s <number>"
,
opt
->
name
);
else
if
(
opt
->
type
==
VSH_OT_STRING
)
snprintf
(
buf
,
sizeof
(
buf
),
"--%s <string>"
,
opt
->
name
);
else
if
(
opt
->
type
==
VSH_OT_DATA
)
snprintf
(
buf
,
sizeof
(
buf
),
"<%s>"
,
opt
->
name
);
fprintf
(
stdout
,
" %-15s %s
\n
"
,
buf
,
opt
->
help
);
}
}
fputc
(
'\n'
,
stdout
);
}
return
TRUE
;
}
/* ---------------
* Utils for work with runtime commands data
* ---------------
*/
static
void
vshCommandOptFree
(
vshCmdOpt
*
arg
)
{
vshCmdOpt
*
a
=
arg
;
while
(
a
)
{
vshCmdOpt
*
tmp
=
a
;
a
=
a
->
next
;
if
(
tmp
->
data
)
free
(
tmp
->
data
);
free
(
tmp
);
}
}
static
void
vshCommandFree
(
vshCmd
*
cmd
)
{
vshCmd
*
c
=
cmd
;
while
(
c
)
{
vshCmd
*
tmp
=
c
;
c
=
c
->
next
;
if
(
tmp
->
opts
)
vshCommandOptFree
(
tmp
->
opts
);
free
(
tmp
);
}
}
/*
* Returns option by name
*/
static
vshCmdOpt
*
vshCommandOpt
(
vshCmd
*
cmd
,
char
*
name
)
{
vshCmdOpt
*
opt
=
cmd
->
opts
;
while
(
opt
)
{
if
(
opt
->
def
&&
strcmp
(
opt
->
def
->
name
,
name
)
==
0
)
return
opt
;
opt
=
opt
->
next
;
}
return
NULL
;
}
/*
* Returns option as INT
*/
static
int
vshCommandOptInt
(
vshCmd
*
cmd
,
char
*
name
,
int
*
found
)
{
vshCmdOpt
*
arg
=
vshCommandOpt
(
cmd
,
name
);
int
res
=
0
;
if
(
arg
)
res
=
atoi
(
arg
->
data
);
if
(
found
)
*
found
=
arg
?
TRUE
:
FALSE
;
return
res
;
}
/*
* Returns option as STRING
*/
static
char
*
vshCommandOptString
(
vshCmd
*
cmd
,
char
*
name
,
int
*
found
)
{
vshCmdOpt
*
arg
=
vshCommandOpt
(
cmd
,
name
);
if
(
found
)
*
found
=
arg
?
TRUE
:
FALSE
;
return
arg
?
arg
->
data
:
NULL
;
}
/*
* Returns TRUE/FALSE if the option exists
*/
static
int
vshCommandOptBool
(
vshCmd
*
cmd
,
char
*
name
)
{
return
vshCommandOpt
(
cmd
,
name
)
?
TRUE
:
FALSE
;
}
/*
* Executes command(s) and returns return code from last command
*/
static
int
vshCommandRun
(
vshControl
*
ctl
,
vshCmd
*
cmd
)
{
int
ret
=
TRUE
;
while
(
cmd
)
{
struct
timeval
before
,
after
;
if
(
ctl
->
timing
)
GETTIMEOFDAY
(
&
before
);
ret
=
cmd
->
def
->
handler
(
ctl
,
cmd
);
if
(
ctl
->
timing
)
GETTIMEOFDAY
(
&
after
);
if
(
strcmp
(
cmd
->
def
->
name
,
"quit"
)
==
0
)
/* hack ... */
return
ret
;
if
(
ctl
->
timing
)
vshPrint
(
ctl
,
VSH_MESG
,
"
\n
(Time: %.3f ms)
\n\n
"
,
DIFF_MSEC
(
&
after
,
&
before
));
else
vshPrint
(
ctl
,
VSH_FOOTER
,
"
\n
"
);
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
static
int
vshCommandGetToken
(
vshControl
*
ctl
,
char
*
str
,
char
**
end
,
char
**
res
)
{
int
tk
=
VSH_TK_NONE
;
int
quote
=
FALSE
;
int
sz
=
0
;
char
*
p
=
str
;
char
*
tkstr
=
NULL
;
*
end
=
NULL
;
while
(
p
&&
*
p
&&
isblank
((
unsigned
char
)
*
p
))
p
++
;
if
(
getuid
()
==
0
)
{
conn
=
virConnectOpen
(
NULL
);
if
(
p
==
NULL
||
*
p
==
'\0'
)
return
VSH_TK_END
;
if
(
*
p
==
';'
)
{
*
end
=
++
p
;
/* = \0 or begi of next command */
return
VSH_TK_END
;
}
while
(
*
p
)
{
/* end of token is blank space or ';' */
if
((
quote
==
FALSE
&&
isblank
((
unsigned
char
)
*
p
))
||
*
p
==
';'
)
break
;
if
(
tk
==
VSH_TK_NONE
)
{
if
(
*
p
==
'-'
&&
*
(
p
+
1
)
==
'-'
&&
*
(
p
+
2
)
&&
isalnum
((
unsigned
char
)
*
(
p
+
2
)))
{
tk
=
VSH_TK_OPTION
;
p
+=
2
;
}
else
{
tk
=
VSH_TK_DATA
;
if
(
*
p
==
'"'
)
{
quote
=
TRUE
;
p
++
;
}
else
{
quote
=
FALSE
;
}
}
tkstr
=
p
;
/* begin of token */
}
else
if
(
quote
&&
*
p
==
'"'
)
{
quote
=
FALSE
;
p
++
;
break
;
/* end of "..." token */
}
p
++
;
sz
++
;
}
if
(
quote
)
{
vshError
(
ctl
,
FALSE
,
"missing
\"
"
);
return
VSH_TK_ERROR
;
}
if
(
tkstr
==
NULL
||
*
tkstr
==
'\0'
||
p
==
NULL
)
return
VSH_TK_END
;
if
(
sz
==
0
)
return
VSH_TK_END
;
*
res
=
malloc
(
sz
+
1
);
memcpy
(
*
res
,
tkstr
,
sz
);
*
(
*
res
+
sz
)
=
'\0'
;
*
end
=
p
;
return
tk
;
}
static
int
vshCommandParse
(
vshControl
*
ctl
,
char
*
cmdstr
)
{
char
*
str
;
char
*
tkdata
=
NULL
;
vshCmd
*
clast
=
NULL
;
vshCmdOpt
*
first
=
NULL
;
if
(
ctl
->
cmd
)
{
vshCommandFree
(
ctl
->
cmd
);
ctl
->
cmd
=
NULL
;
}
if
(
cmdstr
==
NULL
||
*
cmdstr
==
'\0'
)
return
FALSE
;
str
=
cmdstr
;
while
(
str
&&
*
str
)
{
vshCmdOpt
*
last
=
NULL
;
vshCmdDef
*
cmd
=
NULL
;
int
tk
=
VSH_TK_NONE
;
first
=
NULL
;
while
(
tk
!=
VSH_TK_END
)
{
char
*
end
=
NULL
;
vshCmdOptDef
*
opt
=
NULL
;
tkdata
=
NULL
;
/* get token */
tk
=
vshCommandGetToken
(
ctl
,
str
,
&
end
,
&
tkdata
);
str
=
end
;
if
(
tk
==
VSH_TK_END
)
break
;
if
(
tk
==
VSH_TK_ERROR
)
goto
syntaxError
;
if
(
cmd
==
NULL
)
{
/* first token must be command name */
if
(
tk
!=
VSH_TK_DATA
)
{
vshError
(
ctl
,
FALSE
,
"unexpected token (command name): '%s'"
,
tkdata
);
goto
syntaxError
;
}
if
(
!
(
cmd
=
vshCmddefSearch
(
tkdata
)))
{
vshError
(
ctl
,
FALSE
,
"unknown command: '%s'"
,
tkdata
);
goto
syntaxError
;
/* ... or ignore this command only? */
}
free
(
tkdata
);
}
else
if
(
tk
==
VSH_TK_OPTION
)
{
if
(
!
(
opt
=
vshCmddefGetOption
(
cmd
,
tkdata
)))
{
vshError
(
ctl
,
FALSE
,
"command '%s' doesn't support option --%s"
,
cmd
->
name
,
tkdata
);
goto
syntaxError
;
}
free
(
tkdata
);
/* option name */
tkdata
=
NULL
;
if
(
opt
->
type
!=
VSH_OT_BOOL
)
{
/* option data */
tk
=
vshCommandGetToken
(
ctl
,
str
,
&
end
,
&
tkdata
);
str
=
end
;
if
(
tk
==
VSH_TK_ERROR
)
goto
syntaxError
;
if
(
tk
!=
VSH_TK_DATA
)
{
vshError
(
ctl
,
FALSE
,
"expected syntax: --%s <%s>"
,
opt
->
name
,
opt
->
type
==
VSH_OT_INT
?
"number"
:
"string"
);
goto
syntaxError
;
}
}
}
else
if
(
tk
==
VSH_TK_DATA
)
{
if
(
!
(
opt
=
vshCmddefGetData
(
cmd
)))
{
vshError
(
ctl
,
FALSE
,
"unexpected data '%s'"
,
tkdata
);
goto
syntaxError
;
}
}
if
(
opt
)
{
/* save option */
vshCmdOpt
*
arg
=
malloc
(
sizeof
(
vshCmdOpt
));
arg
->
def
=
opt
;
arg
->
data
=
tkdata
;
arg
->
next
=
NULL
;
tkdata
=
NULL
;
if
(
!
first
)
first
=
arg
;
if
(
last
)
last
->
next
=
arg
;
last
=
arg
;
vshPrint
(
ctl
,
VSH_DEBUG4
,
"%s: %s(%s): %s
\n
"
,
cmd
->
name
,
opt
->
name
,
tk
==
VSH_TK_OPTION
?
"OPTION"
:
"DATA"
,
arg
->
data
);
}
if
(
!
str
)
break
;
}
/* commad parsed -- allocate new struct for the command */
if
(
cmd
)
{
vshCmd
*
c
=
malloc
(
sizeof
(
vshCmd
));
c
->
opts
=
first
;
c
->
def
=
cmd
;
c
->
next
=
NULL
;
if
(
!
ctl
->
cmd
)
ctl
->
cmd
=
c
;
if
(
clast
)
clast
->
next
=
c
;
clast
=
c
;
}
}
return
TRUE
;
syntaxError:
if
(
ctl
->
cmd
)
vshCommandFree
(
ctl
->
cmd
);
if
(
first
)
vshCommandOptFree
(
first
);
if
(
tkdata
)
free
(
tkdata
);
return
FALSE
;
}
/* ---------------
* Misc utils
* ---------------
*/
static
char
*
vshDomainStateToString
(
int
state
)
{
switch
(
state
)
{
case
VIR_DOMAIN_RUNNING
:
return
"running "
;
case
VIR_DOMAIN_BLOCKED
:
return
"blocked "
;
case
VIR_DOMAIN_PAUSED
:
return
"paused "
;
case
VIR_DOMAIN_SHUTDOWN
:
return
"in shutdown"
;
case
VIR_DOMAIN_SHUTOFF
:
return
"shut off"
;
default:
return
"no state"
;
/* = dom0 state */
}
return
NULL
;
}
static
int
vshConnectionUsability
(
vshControl
*
ctl
,
virConnectPtr
conn
,
int
showerror
)
{
/* TODO: use something like virConnectionState() to
* check usability of the connection
*/
if
(
!
conn
)
{
if
(
showerror
)
vshError
(
ctl
,
FALSE
,
"no valid connection."
);
return
FALSE
;
}
return
TRUE
;
}
static
int
vshWantedDebug
(
vshOutType
type
,
int
mode
)
{
switch
(
type
)
{
case
VSH_DEBUG5
:
if
(
mode
<
5
)
return
FALSE
;
return
TRUE
;
case
VSH_DEBUG4
:
if
(
mode
<
4
)
return
FALSE
;
return
TRUE
;
case
VSH_DEBUG3
:
if
(
mode
<
3
)
return
FALSE
;
return
TRUE
;
case
VSH_DEBUG2
:
if
(
mode
<
2
)
return
FALSE
;
return
TRUE
;
case
VSH_DEBUG1
:
if
(
mode
<
1
)
return
FALSE
;
return
TRUE
;
default:
/* it's right, all others types have to pass */
return
TRUE
;
}
return
FALSE
;
}
static
void
vshPrint
(
vshControl
*
ctl
,
vshOutType
type
,
char
*
format
,
...)
{
va_list
ap
;
if
(
ctl
->
quiet
==
TRUE
&&
(
type
==
VSH_HEADER
||
type
==
VSH_FOOTER
))
return
;
if
(
!
vshWantedDebug
(
type
,
ctl
->
debug
))
return
;
va_start
(
ap
,
format
);
vfprintf
(
stderr
,
format
,
ap
);
va_end
(
ap
);
}
static
void
vshError
(
vshControl
*
ctl
,
int
doexit
,
char
*
format
,
...)
{
va_list
ap
;
if
(
doexit
)
fprintf
(
stderr
,
"%s: error: "
,
progname
);
else
fputs
(
"error: "
,
stderr
);
va_start
(
ap
,
format
);
vfprintf
(
stderr
,
format
,
ap
);
va_end
(
ap
);
fputc
(
'\n'
,
stderr
);
if
(
doexit
)
{
vshDeinit
(
ctl
);
exit
(
EXIT_FAILURE
);
}
}
/*
* Initialize vistsh
*/
static
int
vshInit
(
vshControl
*
ctl
)
{
if
(
ctl
->
conn
)
return
FALSE
;
ctl
->
uid
=
getuid
();
/* basic connection to hypervisor */
if
(
ctl
->
uid
==
0
)
ctl
->
conn
=
virConnectOpen
(
NULL
);
else
ctl
->
conn
=
virConnectOpenReadOnly
(
NULL
);
if
(
!
ctl
->
conn
)
vshError
(
ctl
,
TRUE
,
"failed to connect to the hypervisor"
);
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
*
vshReadlineCommandGenerator
(
const
char
*
text
,
int
state
)
{
static
int
list_index
,
len
;
char
*
name
;
/* 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
;
len
=
strlen
(
text
);
}
/* Return the next name which partially matches from the
* command list.
*/
while
(
name
=
commands
[
list_index
].
name
)
{
list_index
++
;
if
(
strncmp
(
name
,
text
,
len
)
==
0
)
return
strdup
(
name
);
}
/* If no names matched, then return NULL. */
return
NULL
;
}
static
char
*
vshReadlineOptionsGenerator
(
const
char
*
text
,
int
state
)
{
static
int
list_index
,
len
;
static
vshCmdDef
*
cmd
=
NULL
;
char
*
name
;
if
(
!
state
)
{
/* determine command name */
char
*
p
;
char
*
cmdname
;
if
(
!
(
p
=
strchr
(
rl_line_buffer
,
' '
)))
return
NULL
;
cmdname
=
calloc
((
p
-
rl_line_buffer
)
+
1
,
1
);
memcpy
(
cmdname
,
rl_line_buffer
,
p
-
rl_line_buffer
);
cmd
=
vshCmddefSearch
(
cmdname
);
list_index
=
0
;
len
=
strlen
(
text
);
free
(
cmdname
);
}
if
(
!
cmd
)
return
NULL
;
while
(
name
=
cmd
->
opts
[
list_index
].
name
)
{
vshCmdOptDef
*
opt
=
&
cmd
->
opts
[
list_index
];
char
*
res
;
list_index
++
;
if
(
cmd
->
opts
[
list_index
].
type
==
VSH_OT_DATA
)
/* ignore non --option */
continue
;
if
(
len
>
2
)
{
if
(
strncmp
(
name
,
text
+
2
,
len
-
2
))
continue
;
}
res
=
malloc
(
strlen
(
name
)
+
3
);
sprintf
(
res
,
"--%s"
,
name
);
return
res
;
}
/* If no names matched, then return NULL. */
return
NULL
;
}
static
char
**
vshReadlineCompletion
(
const
char
*
text
,
int
start
,
int
end
)
{
char
**
matches
=
(
char
**
)
NULL
;
if
(
start
==
0
)
/* command name generator */
matches
=
rl_completion_matches
(
text
,
vshReadlineCommandGenerator
);
else
/* commands options */
matches
=
rl_completion_matches
(
text
,
vshReadlineOptionsGenerator
);
return
matches
;
}
static
void
vshReadlineInit
(
vshControl
*
ctl
)
{
/* 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
vshDeinit
(
vshControl
*
ctl
)
{
if
(
ctl
->
conn
)
{
if
(
virConnectClose
(
ctl
->
conn
)
!=
0
)
{
ctl
->
conn
=
NULL
;
/* prevent recursive call from vshError() */
vshError
(
ctl
,
TRUE
,
"failed to disconnect from the hypervisor"
);
}
}
return
TRUE
;
}
/*
* Print usage
*/
static
void
vshUsage
(
vshControl
*
ctl
,
char
*
cmdname
)
{
vshCmdDef
*
cmd
;
/* global help */
if
(
!
cmdname
)
{
fprintf
(
stdout
,
"
\n
%s [options] [commands]
\n\n
"
" options:
\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
);
for
(
cmd
=
commands
;
cmd
->
name
;
cmd
++
)
fprintf
(
stdout
,
" %-15s %s
\n
"
,
cmd
->
name
,
vshCmddefGetInfo
(
cmd
,
"help"
));
fprintf
(
stdout
,
"
\n
(specify --help <command> for details about the command)
\n\n
"
);
return
;
}
if
(
!
vshCmddefHelp
(
ctl
,
cmdname
,
TRUE
))
exit
(
EXIT_FAILURE
);
}
/*
* argv[]: virsh [options] [command]
*
*/
static
int
vshParseArgv
(
vshControl
*
ctl
,
int
argc
,
char
**
argv
)
{
char
*
last
=
NULL
;
int
i
,
end
=
0
,
help
=
0
;
int
arg
,
idx
=
0
;
struct
option
opt
[]
=
{
{
"debug"
,
1
,
0
,
'd'
},
{
"help"
,
0
,
0
,
'h'
},
{
"quiet"
,
0
,
0
,
'q'
},
{
"timing"
,
0
,
0
,
't'
},
{
"version"
,
0
,
0
,
'v'
},
{
0
,
0
,
0
,
0
}
};
if
(
argc
<
2
)
return
;
/* look for begin of command, for example:
* ./virsh --debug 5 -q command --cmdoption
* <--- ^ --->
* getopt() stuff | command suff
*/
for
(
i
=
1
;
i
<
argc
;
i
++
)
{
if
(
*
argv
[
i
]
!=
'-'
)
{
int
valid
=
FALSE
;
/* non "--option" argv, is it command? */
if
(
last
)
{
struct
option
*
o
;
int
sz
=
strlen
(
last
);
for
(
o
=
opt
;
o
->
name
;
o
++
)
{
if
(
sz
==
2
&&
*
(
last
+
1
)
==
o
->
val
)
/* valid virsh short option */
valid
=
TRUE
;
else
if
(
sz
>
2
&&
strcmp
(
o
->
name
,
last
+
2
)
==
0
)
/* valid virsh long option */
valid
=
TRUE
;
}
}
if
(
!
valid
)
{
end
=
i
;
break
;
}
}
last
=
argv
[
i
];
}
end
=
end
?
:
argc
;
/* standard (non-command) options */
while
((
arg
=
getopt_long
(
end
,
argv
,
"d:hqtv"
,
opt
,
&
idx
))
!=
-
1
)
{
switch
(
arg
)
{
case
'd'
:
ctl
->
debug
=
atoi
(
optarg
);
break
;
case
'h'
:
help
=
1
;
break
;
case
'q'
:
ctl
->
quiet
=
TRUE
;
break
;
case
't'
:
ctl
->
timing
=
TRUE
;
break
;
case
'v'
:
fprintf
(
stdout
,
"%s
\n
"
,
VERSION
);
exit
(
EXIT_SUCCESS
);
default:
vshError
(
ctl
,
TRUE
,
"unsupported option '-%c'. See --help."
,
arg
);
break
;
}
}
if
(
help
)
{
/* global or command specific help */
vshUsage
(
ctl
,
argc
>
end
?
argv
[
end
]
:
NULL
);
exit
(
EXIT_SUCCESS
);
}
if
(
argc
>
end
)
{
/* parse command */
char
*
cmdstr
;
int
sz
=
0
,
i
,
ret
;
ctl
->
imode
=
FALSE
;
for
(
i
=
end
;
i
<
argc
;
i
++
)
sz
+=
strlen
(
argv
[
i
])
+
1
;
/* +1 is for blank space between items */
cmdstr
=
calloc
(
sz
+
1
,
1
);
for
(
i
=
end
;
i
<
argc
;
i
++
)
{
strncat
(
cmdstr
,
argv
[
i
],
sz
);
sz
-=
strlen
(
argv
[
i
]);
strncat
(
cmdstr
,
" "
,
sz
--
);
}
vshPrint
(
ctl
,
VSH_DEBUG2
,
"command:
\"
%s
\"\n
"
,
cmdstr
);
ret
=
vshCommandParse
(
ctl
,
cmdstr
);
free
(
cmdstr
);
return
ret
;
}
return
TRUE
;
}
int
main
(
int
argc
,
char
**
argv
)
{
vshControl
_ctl
,
*
ctl
=&
_ctl
;
int
ret
=
TRUE
;
if
(
!
(
progname
=
strrchr
(
argv
[
0
],
'/'
)))
progname
=
argv
[
0
];
else
progname
++
;
memset
(
ctl
,
0
,
sizeof
(
vshControl
));
ctl
->
imode
=
TRUE
;
/* default is interactive mode */
if
(
!
vshParseArgv
(
ctl
,
argc
,
argv
))
exit
(
EXIT_FAILURE
);
if
(
!
vshInit
(
ctl
))
exit
(
EXIT_FAILURE
);
if
(
!
ctl
->
imode
)
{
ret
=
vshCommandRun
(
ctl
,
ctl
->
cmd
);
}
else
{
conn
=
virConnectOpenReadOnly
(
NULL
);
}
if
(
conn
==
NULL
)
{
fprintf
(
stderr
,
"Failed to connect to the hypervisor
\n
"
);
errcode
=
1
;
goto
done
;
}
dom0
=
virDomainLookupByID
(
conn
,
0
);
if
(
dom0
==
NULL
)
{
fprintf
(
stderr
,
"Failed to get domain 0 informations
\n
"
);
errcode
=
2
;
goto
done
;
}
printf
(
"Dom0: "
);
printDomain
(
dom0
);
ret
=
virConnectListDomains
(
conn
,
&
ids
[
0
],
MAX_DOM
);
if
(
ret
<
0
)
{
fprintf
(
stderr
,
"Failed to list active domains
\n
"
);
errcode
=
3
;
goto
done
;
}
printf
(
"Found %d more active domains
\n
"
,
ret
-
1
);
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
if
(
ids
[
i
]
==
0
)
continue
;
printf
(
" "
);
dom
=
virDomainLookupByID
(
conn
,
ids
[
i
]);
if
(
dom
==
NULL
)
{
printf
(
"domain %d disapeared
\n
"
,
ids
[
i
]);
}
else
{
printDomain
(
dom
);
}
}
done:
if
(
conn
!=
NULL
)
{
ret
=
virConnectClose
(
conn
);
if
(
ret
!=
0
)
{
fprintf
(
stderr
,
"Failed to connect to the hypervisor
\n
"
);
if
(
errcode
==
0
)
errcode
=
1
;
}
}
return
(
errcode
);
/* interactive mode */
if
(
!
ctl
->
quiet
)
{
vshPrint
(
ctl
,
VSH_MESG
,
"Welcome to %s, the virtualization interactive terminal.
\n\n
"
,
progname
);
vshPrint
(
ctl
,
VSH_MESG
,
"Type: 'help' for help with commands
\n
"
" 'quit' to quit
\n\n
"
);
}
vshReadlineInit
(
ctl
);
do
{
ctl
->
cmdstr
=
readline
(
ctl
->
uid
==
0
?
VSH_PROMPT_RW
:
VSH_PROMPT_RO
);
if
(
ctl
->
cmdstr
==
NULL
)
break
;
/* EOF */
if
(
*
ctl
->
cmdstr
)
{
add_history
(
ctl
->
cmdstr
);
if
(
vshCommandParse
(
ctl
,
ctl
->
cmdstr
))
vshCommandRun
(
ctl
,
ctl
->
cmd
);
}
free
(
ctl
->
cmdstr
);
ctl
->
cmdstr
=
NULL
;
}
while
(
ctl
->
imode
);
if
(
ctl
->
cmdstr
==
NULL
)
fputc
(
'\n'
,
stdout
);
/* line break after alone prompt */
}
vshDeinit
(
ctl
);
exit
(
ret
?
EXIT_SUCCESS
:
EXIT_FAILURE
);
}
/*
* vim: set tabstop=4:
* vim: set shiftwidth=4:
* vim: set expandtab:
*/
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录