diff options
author | aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162> | 2009-03-05 23:01:15 +0000 |
---|---|---|
committer | aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162> | 2009-03-05 23:01:15 +0000 |
commit | 379a6ae8083af9436540e1dad1f282daa86a0ae7 (patch) | |
tree | 2cb53fa2bf9b5165b338e1cc85c8dedc5bf25879 | |
parent | bf12623527dda8847375e7066eedfeb3740f6cd7 (diff) | |
download | qemu-379a6ae8083af9436540e1dad1f282daa86a0ae7.tar.gz qemu-379a6ae8083af9436540e1dad1f282daa86a0ae7.tar.bz2 qemu-379a6ae8083af9436540e1dad1f282daa86a0ae7.zip |
monitor: Rework modal password input (Jan Kiszka)
Currently, waiting for the user to type in some password blocks the
whole VM because monitor_readline starts its own I/O loop. And this loop
also screws up reading passwords from virtual console.
Patch below fixes the shortcomings by using normal I/O processing also
for waiting on a password. To keep to modal property for the monitor
terminal, the command handler is temporarily replaced by a password
handler and a callback infrastructure is established to process the
result before switching back to command mode.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6710 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | block.c | 21 | ||||
-rw-r--r-- | console.h | 6 | ||||
-rw-r--r-- | hw/usb-msd.c | 10 | ||||
-rw-r--r-- | hw/usb.h | 3 | ||||
-rw-r--r-- | monitor.c | 114 | ||||
-rw-r--r-- | vl.c | 19 |
6 files changed, 108 insertions, 65 deletions
@@ -430,11 +430,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, } } - /* call the change callback */ - bs->media_changed = 1; - if (bs->change_cb) - bs->change_cb(bs->change_opaque); - + if (!bdrv_key_required(bs)) { + /* call the change callback */ + bs->media_changed = 1; + if (bs->change_cb) + bs->change_cb(bs->change_opaque); + } return 0; } @@ -989,7 +990,15 @@ int bdrv_set_key(BlockDriverState *bs, const char *key) if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key) return -1; ret = bs->drv->bdrv_set_key(bs, key); - bs->valid_key = (ret == 0); + if (ret < 0) { + bs->valid_key = 0; + } else if (!bs->valid_key) { + bs->valid_key = 1; + /* call the change callback now, we skipped it on open */ + bs->media_changed = 1; + if (bs->change_cb) + bs->change_cb(bs->change_opaque); + } return ret; } @@ -304,7 +304,11 @@ void term_flush(void); void term_print_help(void); void monitor_suspend(void); void monitor_resume(void); -int monitor_read_bdrv_key(BlockDriverState *bs); + +#include "block.h" +void monitor_read_bdrv_key_start(BlockDriverState *bs, + BlockDriverCompletionFunc *completion_cb, + void *opaque); /* readline.c */ typedef void ReadLineFunc(void *opaque, const char *str); diff --git a/hw/usb-msd.c b/hw/usb-msd.c index 0c8d9cca83..41c92c3f1d 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -514,7 +514,7 @@ static void usb_msd_handle_destroy(USBDevice *dev) qemu_free(s); } -USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) +USBDevice *usb_msd_init(const char *filename) { MSDState *s; BlockDriverState *bdrv; @@ -554,7 +554,6 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) if (bdrv_open2(bdrv, filename, 0, drv) < 0) goto fail; s->bs = bdrv; - *pbs = bdrv; s->dev.speed = USB_SPEED_FULL; s->dev.handle_packet = usb_generic_handle_packet; @@ -574,3 +573,10 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) qemu_free(s); return NULL; } + +BlockDriverState *usb_msd_get_bdrv(USBDevice *dev) +{ + MSDState *s = (MSDState *)dev; + + return s->bs; +} @@ -253,7 +253,8 @@ USBDevice *usb_keyboard_init(void); void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *)); /* usb-msd.c */ -USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs); +USBDevice *usb_msd_init(const char *filename); +BlockDriverState *usb_msd_get_bdrv(USBDevice *dev); /* usb-net.c */ USBDevice *usb_net_init(NICInfo *nd); @@ -74,13 +74,18 @@ static const term_cmd_t info_cmds[]; static uint8_t term_outbuf[1024]; static int term_outbuf_index; +static BlockDriverCompletionFunc *password_completion_cb; +static void *password_opaque; static void monitor_start_input(void); -static void monitor_readline(const char *prompt, int is_password, - char *buf, int buf_size); static CPUState *mon_cpu = NULL; +static void monitor_read_password(ReadLineFunc *readline_func, void *opaque) +{ + readline_start("Password: ", 1, readline_func, opaque); +} + void term_flush(void) { int i; @@ -435,21 +440,29 @@ static void do_change_block(const char *device, const char *filename, const char if (eject_device(bs, 0) < 0) return; bdrv_open2(bs, filename, 0, drv); - monitor_read_bdrv_key(bs); + monitor_read_bdrv_key_start(bs, NULL, NULL); +} + +static void change_vnc_password_cb(void *opaque, const char *password) +{ + if (vnc_display_password(NULL, password) < 0) + term_printf("could not set VNC server password\n"); + + monitor_start_input(); } static void do_change_vnc(const char *target, const char *arg) { if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) { - char password[9]; if (arg) { + char password[9]; strncpy(password, arg, sizeof(password)); password[sizeof(password) - 1] = '\0'; - } else - monitor_readline("Password: ", 1, password, sizeof(password)); - if (vnc_display_password(NULL, password) < 0) - term_printf("could not set VNC server password\n"); + change_vnc_password_cb(NULL, password); + } else { + monitor_read_password(change_vnc_password_cb, NULL); + } } else { if (vnc_display_open(NULL, target) < 0) term_printf("could not start VNC server on %s\n", target); @@ -496,15 +509,7 @@ static void do_stop(void) vm_stop(EXCP_INTERRUPT); } -static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs) -{ - int *err = opaque; - - if (bdrv_key_required(bs)) - *err = monitor_read_bdrv_key(bs); - else - *err = 0; -} +static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs); static void do_cont(void) { @@ -516,6 +521,23 @@ static void do_cont(void) vm_start(); } +static void bdrv_key_cb(void *opaque, int err) +{ + /* another key was set successfully, retry to continue */ + if (!err) + do_cont(); +} + +static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs) +{ + int *err = opaque; + + if (!*err && bdrv_key_required(bs)) { + *err = -EBUSY; + monitor_read_bdrv_key_start(bs, bdrv_key_cb, NULL); + } +} + #ifdef CONFIG_GDBSTUB static void do_gdbserver(const char *port) { @@ -2835,7 +2857,7 @@ static void monitor_handle_command1(void *opaque, const char *cmdline) { monitor_handle_command(cmdline); if (!monitor_suspended) - monitor_start_input(); + readline_show_prompt(); else monitor_suspended = 2; } @@ -2898,46 +2920,36 @@ void monitor_init(CharDriverState *hd, int show_banner) readline_start("", 0, monitor_handle_command1, NULL); } -/* XXX: use threads ? */ -/* modal monitor readline */ -static int monitor_readline_started; -static char *monitor_readline_buf; -static int monitor_readline_buf_size; - -static void monitor_readline_cb(void *opaque, const char *input) +static void bdrv_password_cb(void *opaque, const char *password) { - pstrcpy(monitor_readline_buf, monitor_readline_buf_size, input); - monitor_readline_started = 0; -} + BlockDriverState *bs = opaque; + int ret = 0; -static void monitor_readline(const char *prompt, int is_password, - char *buf, int buf_size) -{ - readline_start(prompt, is_password, monitor_readline_cb, NULL); - readline_show_prompt(); - monitor_readline_buf = buf; - monitor_readline_buf_size = buf_size; - monitor_readline_started = 1; - while (monitor_readline_started) { - main_loop_wait(10); + if (bdrv_set_key(bs, password) != 0) { + term_printf("invalid password\n"); + ret = -EPERM; } + if (password_completion_cb) + password_completion_cb(password_opaque, ret); + + monitor_start_input(); } -int monitor_read_bdrv_key(BlockDriverState *bs) +void monitor_read_bdrv_key_start(BlockDriverState *bs, + BlockDriverCompletionFunc *completion_cb, + void *opaque) { - char password[256]; - int i; - - if (!bdrv_is_encrypted(bs)) - return 0; + if (!bdrv_key_required(bs)) { + if (completion_cb) + completion_cb(opaque, 0); + return; + } term_printf("%s (%s) is encrypted.\n", bdrv_get_device_name(bs), bdrv_get_encrypted_filename(bs)); - for(i = 0; i < 3; i++) { - monitor_readline("Password: ", 1, password, sizeof(password)); - if (bdrv_set_key(bs, password) == 0) - return 0; - term_printf("invalid password\n"); - } - return -EPERM; + + password_completion_cb = completion_cb; + password_opaque = opaque; + + monitor_read_password(bdrv_password_cb, bs); } @@ -2661,6 +2661,16 @@ int usb_device_add_dev(USBDevice *dev) return 0; } +static void usb_msd_password_cb(void *opaque, int err) +{ + USBDevice *dev = opaque; + + if (!err) + usb_device_add_dev(dev); + else + dev->handle_destroy(dev); +} + static int usb_device_add(const char *devname, int is_hotplug) { const char *p; @@ -2680,14 +2690,15 @@ static int usb_device_add(const char *devname, int is_hotplug) } else if (strstart(devname, "disk:", &p)) { BlockDriverState *bs; - dev = usb_msd_init(p, &bs); + dev = usb_msd_init(p); if (!dev) return -1; + bs = usb_msd_get_bdrv(dev); if (bdrv_key_required(bs)) { autostart = 0; - if (is_hotplug && monitor_read_bdrv_key(bs) < 0) { - dev->handle_destroy(dev); - return -1; + if (is_hotplug) { + monitor_read_bdrv_key_start(bs, usb_msd_password_cb, dev); + return 0; } } } else if (!strcmp(devname, "wacom-tablet")) { |