X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/08683cb53286848913d4b58afb3f975a29d93535..28c9457df08755ef7d98eb58b17e0e0898553b41:/qemu-io.c diff --git a/qemu-io.c b/qemu-io.c index 3b3340ab1b..9fcd72bb10 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -18,20 +18,22 @@ #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" #define CMD_NOFILE_OK 0x01 -char *progname; +static char *progname; -BlockDriverState *qemuio_bs; -extern int qemuio_misalign; +static BlockDriverState *qemuio_bs; /* qemu-io commands passed using -c */ static int ncmdline; static char **cmdline; +static ReadLineState *readline_state; + static int close_f(BlockDriverState *bs, int argc, char **argv) { bdrv_unref(bs); @@ -56,16 +58,20 @@ 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_open(&qemuio_bs, name, NULL, opts, flags | BDRV_O_PROTOCOL, + NULL, &local_err)) + { fprintf(stderr, "%s: can't open device %s: %s\n", progname, name, error_get_pretty(local_err)); error_free(local_err); return 1; } } else { - qemuio_bs = bdrv_new("hda"); + qemuio_bs = bdrv_new("hda", &error_abort); - if (bdrv_open(qemuio_bs, name, opts, flags, NULL, &local_err) < 0) { + if (bdrv_open(&qemuio_bs, name, NULL, opts, flags, NULL, &local_err) + < 0) + { fprintf(stderr, "%s: can't open device %s: %s\n", progname, name, error_get_pretty(local_err)); error_free(local_err); @@ -160,11 +166,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) @@ -185,10 +193,11 @@ static const cmdinfo_t quit_cmd = { static void usage(const char *name) { printf( -"Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n" +"Usage: %s [-h] [-V] [-rsnm] [-c STRING] ... [file]\n" "QEMU Disk exerciser\n" "\n" -" -c, --cmd command to execute\n" +" -c, --cmd STRING execute command with its arguments\n" +" from the given string\n" " -r, --read-only export read-only\n" " -s, --snapshot use snapshot file\n" " -n, --nocache disable host cache\n" @@ -199,18 +208,12 @@ static void usage(const char *name) " -T, --trace FILE enable trace events listed in the given file\n" " -h, --help display this help and exit\n" " -V, --version output version information and exit\n" +"\n" +"See '%s -c help' for information on available commands." "\n", - name); + 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 +225,54 @@ static char *get_prompt(void) return prompt; } -#if defined(ENABLE_READLINE) -static char *fetchline(void) +static void GCC_FMT_ATTR(2, 3) 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 completion_match(const char *cmd, void *opaque) +{ + readline_add_completion(readline_state, cmd); +} + +static void readline_completion_func(void *opaque, const char *str) +{ + readline_set_completion_index(readline_state, strlen(str)); + qemuio_complete_command(str, completion_match, NULL); +} + +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 +288,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 +352,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; @@ -369,6 +387,7 @@ int main(int argc, char **argv) #endif progname = basename(argv[0]); + qemu_init_exec_dir(argv[0]); while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { switch (c) { @@ -391,7 +410,7 @@ int main(int argc, char **argv) readonly = 1; break; case 'm': - qemuio_misalign = 1; + qemuio_misalign = true; break; case 'g': growable = 1; @@ -435,6 +454,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 +481,6 @@ int main(int argc, char **argv) if (qemuio_bs) { bdrv_unref(qemuio_bs); } + g_free(readline_state); return 0; }