# include "threads.h"
# include "virterror_internal.h"
-
-/* ie Ctrl-] as per telnet */
-# define CTRL_CLOSE_BRACKET '\35'
+/*
+ * Convert given character to control character.
+ * Basically, we assume ASCII, and take lower 6 bits.
+ */
+# define CONTROL(c) ((c) ^ 0x40)
# define VIR_FROM_THIS VIR_FROM_NONE
struct virConsoleBuffer streamToTerminal;
struct virConsoleBuffer terminalToStream;
+
+ char escapeChar;
};
static int got_signal = 0;
virConsoleShutdown(con);
return;
}
- if (con->terminalToStream.data[con->terminalToStream.offset] == CTRL_CLOSE_BRACKET) {
+ if (con->terminalToStream.data[con->terminalToStream.offset] == con->escapeChar) {
virConsoleShutdown(con);
return;
}
}
-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;
struct termios ttyattr, rawattr;
goto cleanup;
}
+ con->escapeChar = vshGetEscapeChar(escape_seq);
con->st = virStreamNew(virDomainGetConnect(dom),
VIR_STREAM_NONBLOCK);
if (!con->st)
((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)
+/* Default escape char Ctrl-] as per telnet */
+#define CTRL_CLOSE_BRACKET "^]"
+
/**
* The log configuration
*/
virMutex lock;
bool eventLoopStarted;
bool quit;
+
+ const char *escapeChar; /* String representation of
+ console escape character */
} __vshControl;
typedef struct vshCmdGrp {
}
vshPrintExtra(ctl, _("Connected to domain %s\n"), virDomainGetName(dom));
- vshPrintExtra(ctl, "%s", _("Escape character is ^]\n"));
- if (vshRunConsole(dom, name) == 0)
+ vshPrintExtra(ctl, _("Escape character is %s\n"), ctl->escapeChar);
+ if (vshRunConsole(dom, name, ctl->escapeChar) == 0)
ret = true;
cleanup:
fprintf(stdout, _("\n%s [options]... [<command_string>]"
"\n%s [options]... <command> [args...]\n\n"
" options:\n"
- " -c | --connect <uri> hypervisor connection URI\n"
+ " -c | --connect=URI hypervisor connection URI\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"
" -q | --quiet quiet mode\n"
" -t | --timing print timing information\n"
- " -l | --log <file> output logging to file\n"
- " -v | --version[=short] program version\n"
- " -V | --version=long version and full options\n\n"
+ " -l | --log=FILE output logging to file\n"
+ " -v short version\n"
+ " -V long version\n"
+ " --version[=TYPE] version, TYPE is short or long (default short)\n"
+ " -e | --escape <char> set escape sequence for console\n\n"
" commands (non interactive mode):\n\n"), progname, progname);
for (grp = cmdGroups; grp->name; grp++) {
vshParseArgv(vshControl *ctl, int argc, char **argv)
{
bool help = false;
- int arg;
+ int arg, len;
struct option opt[] = {
{"debug", required_argument, NULL, 'd'},
{"help", no_argument, NULL, 'h'},
{"connect", required_argument, NULL, 'c'},
{"readonly", no_argument, NULL, 'r'},
{"log", required_argument, NULL, 'l'},
+ {"escape", required_argument, NULL, 'e'},
{NULL, 0, NULL, 0}
};
/* Standard (non-command) options. The leading + ensures that no
* argument reordering takes place, so that command options are
* not confused with top-level virsh options. */
- while ((arg = getopt_long(argc, argv, "+d:hqtc:vVrl:", opt, NULL)) != -1) {
+ while ((arg = getopt_long(argc, argv, "+d:hqtc:vVrl:e:", opt, NULL)) != -1) {
switch (arg) {
case 'd':
if (virStrToLong_i(optarg, NULL, 10, &ctl->debug) < 0) {
case 'l':
ctl->logfile = vshStrdup(ctl, optarg);
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:
vshError(ctl, _("unsupported option '-%c'. See --help."), arg);
exit(EXIT_FAILURE);
ctl->imode = true; /* default is interactive mode */
ctl->log_fd = -1; /* Initialize log file descriptor */
ctl->debug = VSH_DEBUG_DEFAULT;
+ ctl->escapeChar = CTRL_CLOSE_BRACKET;
+
if (!setlocale(LC_ALL, "")) {
perror("setlocale");