From 0cf17e181798063c3824c8200ba46f25f54faa1a Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 14 Nov 2013 11:54:17 +0100 Subject: qemu-io: use readline.c Use readline.c for command-line history. There was support for GNU Readline and BSD Editline but it was never compiled in. Since QEMU has its own readline.c, just use that when qemu-io runs with stdin attached to a terminal. Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- qemu-io.c | 103 +++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 58 insertions(+), 45 deletions(-) (limited to 'qemu-io.c') diff --git a/qemu-io.c b/qemu-io.c index 3b3340a..d7c26d3 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -18,6 +18,7 @@ #include "qemu/main-loop.h" #include "qemu/option.h" #include "qemu/config-file.h" +#include "qemu/readline.h" #include "block/block_int.h" #include "trace/control.h" @@ -32,6 +33,8 @@ extern int qemuio_misalign; static int ncmdline; static char **cmdline; +static ReadLineState *readline_state; + static int close_f(BlockDriverState *bs, int argc, char **argv) { bdrv_unref(bs); @@ -203,14 +206,6 @@ static void usage(const char *name) name); } - -#if defined(ENABLE_READLINE) -# include -# include -#elif defined(ENABLE_EDITLINE) -# include -#endif - static char *get_prompt(void) { static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ]; @@ -222,52 +217,47 @@ static char *get_prompt(void) return prompt; } -#if defined(ENABLE_READLINE) -static char *fetchline(void) +static void readline_printf_func(void *opaque, const char *fmt, ...) { - char *line = readline(get_prompt()); - if (line && *line) { - add_history(line); - } - return line; + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); } -#elif defined(ENABLE_EDITLINE) -static char *el_get_prompt(EditLine *e) + +static void readline_flush_func(void *opaque) { - return get_prompt(); + fflush(stdout); } -static char *fetchline(void) +static void readline_func(void *opaque, const char *str, void *readline_opaque) { - static EditLine *el; - static History *hist; - HistEvent hevent; - char *line; - int count; - - if (!el) { - hist = history_init(); - history(hist, &hevent, H_SETSIZE, 100); - el = el_init(progname, stdin, stdout, stderr); - el_source(el, NULL); - el_set(el, EL_SIGNAL, 1); - el_set(el, EL_PROMPT, el_get_prompt); - el_set(el, EL_HIST, history, (const char *)hist); - } - line = strdup(el_gets(el, &count)); - if (line) { - if (count > 0) { - line[count-1] = '\0'; - } - if (*line) { - history(hist, &hevent, H_ENTER, line); + char **line = readline_opaque; + *line = g_strdup(str); +} + +static void readline_completion_func(void *opaque, const char *str) +{ + /* No command or argument completion implemented yet */ +} + +static char *fetchline_readline(void) +{ + char *line = NULL; + + readline_start(readline_state, get_prompt(), 0, readline_func, &line); + while (!line) { + int ch = getchar(); + if (ch == EOF) { + break; } + readline_handle_byte(readline_state, ch); } return line; } -#else -# define MAXREADLINESZ 1024 -static char *fetchline(void) + +#define MAXREADLINESZ 1024 +static char *fetchline_fgets(void) { char *p, *line = g_malloc(MAXREADLINESZ); @@ -283,7 +273,15 @@ static char *fetchline(void) return line; } -#endif + +static char *fetchline(void) +{ + if (readline_state) { + return fetchline_readline(); + } else { + return fetchline_fgets(); + } +} static void prep_fetchline(void *opaque) { @@ -339,6 +337,11 @@ static void add_user_command(char *optarg) cmdline[ncmdline-1] = optarg; } +static void reenable_tty_echo(void) +{ + qemu_set_tty_echo(STDIN_FILENO, true); +} + int main(int argc, char **argv) { int readonly = 0; @@ -435,6 +438,15 @@ int main(int argc, char **argv) qemuio_add_command(&open_cmd); qemuio_add_command(&close_cmd); + if (isatty(STDIN_FILENO)) { + readline_state = readline_init(readline_printf_func, + readline_flush_func, + NULL, + readline_completion_func); + qemu_set_tty_echo(STDIN_FILENO, false); + atexit(reenable_tty_echo); + } + /* open the device */ if (!readonly) { flags |= BDRV_O_RDWR; @@ -453,5 +465,6 @@ int main(int argc, char **argv) if (qemuio_bs) { bdrv_unref(qemuio_bs); } + g_free(readline_state); return 0; } -- cgit v1.1 From 4694020d3c0d21f02408d5cc6f44b8fb55b4ee15 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 14 Nov 2013 11:54:18 +0100 Subject: qemu-io: add command completion Autocomplete qemu-io commands at the interactive prompt. Note this only completes command names and not their options. Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- qemu-io.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'qemu-io.c') diff --git a/qemu-io.c b/qemu-io.c index d7c26d3..fdc46a9 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -236,9 +236,15 @@ static void readline_func(void *opaque, const char *str, void *readline_opaque) *line = g_strdup(str); } +static void completion_match(const char *cmd, void *opaque) +{ + readline_add_completion(readline_state, cmd); +} + static void readline_completion_func(void *opaque, const char *str) { - /* No command or argument completion implemented yet */ + readline_set_completion_index(readline_state, strlen(str)); + qemuio_complete_command(str, completion_match, NULL); } static char *fetchline_readline(void) -- cgit v1.1 From 72daa72eeecb6b2ee06ab7d836ac3aa01ad7e6df Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Fri, 20 Dec 2013 19:28:08 +0100 Subject: block: Allow reference for bdrv_file_open() Allow specifying a reference to an existing block device (by name) for bdrv_file_open() instead of a filename and/or options. Signed-off-by: Max Reitz Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- qemu-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'qemu-io.c') diff --git a/qemu-io.c b/qemu-io.c index fdc46a9..bfb773e 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -59,7 +59,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts) } if (growable) { - if (bdrv_file_open(&qemuio_bs, name, opts, flags, &local_err)) { + if (bdrv_file_open(&qemuio_bs, name, NULL, opts, flags, &local_err)) { fprintf(stderr, "%s: can't open device %s: %s\n", progname, name, error_get_pretty(local_err)); error_free(local_err); -- cgit v1.1 From fd0fee34b5ae7699dc558c12ddc3663bdb580060 Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Fri, 20 Dec 2013 19:28:20 +0100 Subject: qemu-io: Make filename optional Giving a filename is actually not essential, since it can be specified through the options as well - on the contrary: Sometimes a filename must not be given. Signed-off-by: Max Reitz Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- qemu-io.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'qemu-io.c') diff --git a/qemu-io.c b/qemu-io.c index bfb773e..d669028 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -163,11 +163,13 @@ static int open_f(BlockDriverState *bs, int argc, char **argv) flags |= BDRV_O_RDWR; } - if (optind != argc - 1) { + if (optind == argc - 1) { + return openfile(argv[optind], flags, growable, opts); + } else if (optind == argc) { + return openfile(NULL, flags, growable, opts); + } else { return qemuio_command_usage(&open_cmd); } - - return openfile(argv[optind], flags, growable, opts); } static int quit_f(BlockDriverState *bs, int argc, char **argv) -- cgit v1.1