mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 03:12:22 +00:00
virsh: Allow other escape characters for console
Currently virsh supports only ^] as escape character for console. However, some users might want to use something else. This patch creates such ability by specifying '-e' switch on virsh command line.
This commit is contained in:
parent
0763a26dfe
commit
7a79648532
@ -44,9 +44,11 @@
|
|||||||
# include "threads.h"
|
# include "threads.h"
|
||||||
# include "virterror_internal.h"
|
# include "virterror_internal.h"
|
||||||
|
|
||||||
|
/*
|
||||||
/* ie Ctrl-] as per telnet */
|
* Convert given character to control character.
|
||||||
# define CTRL_CLOSE_BRACKET '\35'
|
* Basically, we assume ASCII, and take lower 6 bits.
|
||||||
|
*/
|
||||||
|
# define CONTROL(c) ((c) ^ 0x40)
|
||||||
|
|
||||||
# define VIR_FROM_THIS VIR_FROM_NONE
|
# define VIR_FROM_THIS VIR_FROM_NONE
|
||||||
|
|
||||||
@ -69,6 +71,8 @@ struct virConsole {
|
|||||||
|
|
||||||
struct virConsoleBuffer streamToTerminal;
|
struct virConsoleBuffer streamToTerminal;
|
||||||
struct virConsoleBuffer terminalToStream;
|
struct virConsoleBuffer terminalToStream;
|
||||||
|
|
||||||
|
char escapeChar;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int got_signal = 0;
|
static int got_signal = 0;
|
||||||
@ -219,7 +223,7 @@ virConsoleEventOnStdin(int watch ATTRIBUTE_UNUSED,
|
|||||||
virConsoleShutdown(con);
|
virConsoleShutdown(con);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (con->terminalToStream.data[con->terminalToStream.offset] == CTRL_CLOSE_BRACKET) {
|
if (con->terminalToStream.data[con->terminalToStream.offset] == con->escapeChar) {
|
||||||
virConsoleShutdown(con);
|
virConsoleShutdown(con);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -282,7 +286,18 @@ virConsoleEventOnStdout(int watch ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int vshRunConsole(virDomainPtr dom, const char *dev_name)
|
static char
|
||||||
|
vshGetEscapeChar(const char *s)
|
||||||
|
{
|
||||||
|
if (*s == '^')
|
||||||
|
return CONTROL(s[1]);
|
||||||
|
|
||||||
|
return *s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vshRunConsole(virDomainPtr dom,
|
||||||
|
const char *dev_name,
|
||||||
|
const char *escape_seq)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct termios ttyattr, rawattr;
|
struct termios ttyattr, rawattr;
|
||||||
@ -330,6 +345,7 @@ int vshRunConsole(virDomainPtr dom, const char *dev_name)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
con->escapeChar = vshGetEscapeChar(escape_seq);
|
||||||
con->st = virStreamNew(virDomainGetConnect(dom),
|
con->st = virStreamNew(virDomainGetConnect(dom),
|
||||||
VIR_STREAM_NONBLOCK);
|
VIR_STREAM_NONBLOCK);
|
||||||
if (!con->st)
|
if (!con->st)
|
||||||
|
@ -25,7 +25,9 @@
|
|||||||
|
|
||||||
# ifndef WIN32
|
# ifndef WIN32
|
||||||
|
|
||||||
int vshRunConsole(virDomainPtr dom, const char *dev_name);
|
int vshRunConsole(virDomainPtr dom,
|
||||||
|
const char *dev_name,
|
||||||
|
const char *escape_seq);
|
||||||
|
|
||||||
# endif /* !WIN32 */
|
# endif /* !WIN32 */
|
||||||
|
|
||||||
|
@ -76,6 +76,9 @@ static char *progname;
|
|||||||
((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
|
((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
|
||||||
((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)
|
((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)
|
||||||
|
|
||||||
|
/* Default escape char Ctrl-] as per telnet */
|
||||||
|
#define CTRL_CLOSE_BRACKET "^]"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The log configuration
|
* The log configuration
|
||||||
*/
|
*/
|
||||||
@ -254,6 +257,9 @@ typedef struct __vshControl {
|
|||||||
virMutex lock;
|
virMutex lock;
|
||||||
bool eventLoopStarted;
|
bool eventLoopStarted;
|
||||||
bool quit;
|
bool quit;
|
||||||
|
|
||||||
|
const char *escapeChar; /* String representation of
|
||||||
|
console escape character */
|
||||||
} __vshControl;
|
} __vshControl;
|
||||||
|
|
||||||
typedef struct vshCmdGrp {
|
typedef struct vshCmdGrp {
|
||||||
@ -801,8 +807,8 @@ cmdRunConsole(vshControl *ctl, virDomainPtr dom, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
vshPrintExtra(ctl, _("Connected to domain %s\n"), virDomainGetName(dom));
|
vshPrintExtra(ctl, _("Connected to domain %s\n"), virDomainGetName(dom));
|
||||||
vshPrintExtra(ctl, "%s", _("Escape character is ^]\n"));
|
vshPrintExtra(ctl, _("Escape character is %s\n"), ctl->escapeChar);
|
||||||
if (vshRunConsole(dom, name) == 0)
|
if (vshRunConsole(dom, name, ctl->escapeChar) == 0)
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@ -17544,15 +17550,17 @@ vshUsage(void)
|
|||||||
fprintf(stdout, _("\n%s [options]... [<command_string>]"
|
fprintf(stdout, _("\n%s [options]... [<command_string>]"
|
||||||
"\n%s [options]... <command> [args...]\n\n"
|
"\n%s [options]... <command> [args...]\n\n"
|
||||||
" options:\n"
|
" options:\n"
|
||||||
" -c | --connect <uri> hypervisor connection URI\n"
|
" -c | --connect=URI hypervisor connection URI\n"
|
||||||
" -r | --readonly connect readonly\n"
|
" -r | --readonly connect readonly\n"
|
||||||
" -d | --debug <num> debug level [0-4]\n"
|
" -d | --debug=NUM debug level [0-4]\n"
|
||||||
" -h | --help this help\n"
|
" -h | --help this help\n"
|
||||||
" -q | --quiet quiet mode\n"
|
" -q | --quiet quiet mode\n"
|
||||||
" -t | --timing print timing information\n"
|
" -t | --timing print timing information\n"
|
||||||
" -l | --log <file> output logging to file\n"
|
" -l | --log=FILE output logging to file\n"
|
||||||
" -v | --version[=short] program version\n"
|
" -v short version\n"
|
||||||
" -V | --version=long version and full options\n\n"
|
" -V long version\n"
|
||||||
|
" --version[=TYPE] version, TYPE is short or long (default short)\n"
|
||||||
|
" -e | --escape <char> set escape sequence for console\n\n"
|
||||||
" commands (non interactive mode):\n\n"), progname, progname);
|
" commands (non interactive mode):\n\n"), progname, progname);
|
||||||
|
|
||||||
for (grp = cmdGroups; grp->name; grp++) {
|
for (grp = cmdGroups; grp->name; grp++) {
|
||||||
@ -17703,7 +17711,7 @@ static bool
|
|||||||
vshParseArgv(vshControl *ctl, int argc, char **argv)
|
vshParseArgv(vshControl *ctl, int argc, char **argv)
|
||||||
{
|
{
|
||||||
bool help = false;
|
bool help = false;
|
||||||
int arg;
|
int arg, len;
|
||||||
struct option opt[] = {
|
struct option opt[] = {
|
||||||
{"debug", required_argument, NULL, 'd'},
|
{"debug", required_argument, NULL, 'd'},
|
||||||
{"help", no_argument, NULL, 'h'},
|
{"help", no_argument, NULL, 'h'},
|
||||||
@ -17713,13 +17721,14 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
|
|||||||
{"connect", required_argument, NULL, 'c'},
|
{"connect", required_argument, NULL, 'c'},
|
||||||
{"readonly", no_argument, NULL, 'r'},
|
{"readonly", no_argument, NULL, 'r'},
|
||||||
{"log", required_argument, NULL, 'l'},
|
{"log", required_argument, NULL, 'l'},
|
||||||
|
{"escape", required_argument, NULL, 'e'},
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Standard (non-command) options. The leading + ensures that no
|
/* Standard (non-command) options. The leading + ensures that no
|
||||||
* argument reordering takes place, so that command options are
|
* argument reordering takes place, so that command options are
|
||||||
* not confused with top-level virsh options. */
|
* not confused with top-level virsh options. */
|
||||||
while ((arg = getopt_long(argc, argv, "+d:hqtc:vVrl:", opt, NULL)) != -1) {
|
while ((arg = getopt_long(argc, argv, "+d:hqtc:vVrl:e:", opt, NULL)) != -1) {
|
||||||
switch (arg) {
|
switch (arg) {
|
||||||
case 'd':
|
case 'd':
|
||||||
if (virStrToLong_i(optarg, NULL, 10, &ctl->debug) < 0) {
|
if (virStrToLong_i(optarg, NULL, 10, &ctl->debug) < 0) {
|
||||||
@ -17754,6 +17763,18 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
|
|||||||
case 'l':
|
case 'l':
|
||||||
ctl->logfile = vshStrdup(ctl, optarg);
|
ctl->logfile = vshStrdup(ctl, optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'e':
|
||||||
|
len = strlen(optarg);
|
||||||
|
|
||||||
|
if ((len == 2 && *optarg == '^') ||
|
||||||
|
(len == 1 && *optarg != '^')) {
|
||||||
|
ctl->escapeChar = optarg;
|
||||||
|
} else {
|
||||||
|
vshError(ctl, _("Invalid string '%s' for escape sequence"),
|
||||||
|
optarg);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
vshError(ctl, _("unsupported option '-%c'. See --help."), arg);
|
vshError(ctl, _("unsupported option '-%c'. See --help."), arg);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -17795,6 +17816,8 @@ main(int argc, char **argv)
|
|||||||
ctl->imode = true; /* default is interactive mode */
|
ctl->imode = true; /* default is interactive mode */
|
||||||
ctl->log_fd = -1; /* Initialize log file descriptor */
|
ctl->log_fd = -1; /* Initialize log file descriptor */
|
||||||
ctl->debug = VSH_DEBUG_DEFAULT;
|
ctl->debug = VSH_DEBUG_DEFAULT;
|
||||||
|
ctl->escapeChar = CTRL_CLOSE_BRACKET;
|
||||||
|
|
||||||
|
|
||||||
if (!setlocale(LC_ALL, "")) {
|
if (!setlocale(LC_ALL, "")) {
|
||||||
perror("setlocale");
|
perror("setlocale");
|
||||||
|
@ -92,6 +92,11 @@ option of the B<connect> command.
|
|||||||
|
|
||||||
Output elapsed time information for each command.
|
Output elapsed time information for each command.
|
||||||
|
|
||||||
|
=item B<-e>, B<--escape> I<string>
|
||||||
|
|
||||||
|
Set alternative escape sequence for I<console> command. By default,
|
||||||
|
telnet's B<^]> is used.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head1 NOTES
|
=head1 NOTES
|
||||||
|
Loading…
x
Reference in New Issue
Block a user