Commit bb5fc20f7c1c65e95030da3629dd0d7a0cce38cd
1 parent
9dd442b1
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
Showing
6 changed files
with
108 additions
and
65 deletions
block.c
| @@ -430,11 +430,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, | @@ -430,11 +430,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, | ||
| 430 | } | 430 | } |
| 431 | } | 431 | } |
| 432 | 432 | ||
| 433 | - /* call the change callback */ | ||
| 434 | - bs->media_changed = 1; | ||
| 435 | - if (bs->change_cb) | ||
| 436 | - bs->change_cb(bs->change_opaque); | ||
| 437 | - | 433 | + if (!bdrv_key_required(bs)) { |
| 434 | + /* call the change callback */ | ||
| 435 | + bs->media_changed = 1; | ||
| 436 | + if (bs->change_cb) | ||
| 437 | + bs->change_cb(bs->change_opaque); | ||
| 438 | + } | ||
| 438 | return 0; | 439 | return 0; |
| 439 | } | 440 | } |
| 440 | 441 | ||
| @@ -989,7 +990,15 @@ int bdrv_set_key(BlockDriverState *bs, const char *key) | @@ -989,7 +990,15 @@ int bdrv_set_key(BlockDriverState *bs, const char *key) | ||
| 989 | if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key) | 990 | if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key) |
| 990 | return -1; | 991 | return -1; |
| 991 | ret = bs->drv->bdrv_set_key(bs, key); | 992 | ret = bs->drv->bdrv_set_key(bs, key); |
| 992 | - bs->valid_key = (ret == 0); | 993 | + if (ret < 0) { |
| 994 | + bs->valid_key = 0; | ||
| 995 | + } else if (!bs->valid_key) { | ||
| 996 | + bs->valid_key = 1; | ||
| 997 | + /* call the change callback now, we skipped it on open */ | ||
| 998 | + bs->media_changed = 1; | ||
| 999 | + if (bs->change_cb) | ||
| 1000 | + bs->change_cb(bs->change_opaque); | ||
| 1001 | + } | ||
| 993 | return ret; | 1002 | return ret; |
| 994 | } | 1003 | } |
| 995 | 1004 |
console.h
| @@ -304,7 +304,11 @@ void term_flush(void); | @@ -304,7 +304,11 @@ void term_flush(void); | ||
| 304 | void term_print_help(void); | 304 | void term_print_help(void); |
| 305 | void monitor_suspend(void); | 305 | void monitor_suspend(void); |
| 306 | void monitor_resume(void); | 306 | void monitor_resume(void); |
| 307 | -int monitor_read_bdrv_key(BlockDriverState *bs); | 307 | + |
| 308 | +#include "block.h" | ||
| 309 | +void monitor_read_bdrv_key_start(BlockDriverState *bs, | ||
| 310 | + BlockDriverCompletionFunc *completion_cb, | ||
| 311 | + void *opaque); | ||
| 308 | 312 | ||
| 309 | /* readline.c */ | 313 | /* readline.c */ |
| 310 | typedef void ReadLineFunc(void *opaque, const char *str); | 314 | typedef void ReadLineFunc(void *opaque, const char *str); |
hw/usb-msd.c
| @@ -514,7 +514,7 @@ static void usb_msd_handle_destroy(USBDevice *dev) | @@ -514,7 +514,7 @@ static void usb_msd_handle_destroy(USBDevice *dev) | ||
| 514 | qemu_free(s); | 514 | qemu_free(s); |
| 515 | } | 515 | } |
| 516 | 516 | ||
| 517 | -USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) | 517 | +USBDevice *usb_msd_init(const char *filename) |
| 518 | { | 518 | { |
| 519 | MSDState *s; | 519 | MSDState *s; |
| 520 | BlockDriverState *bdrv; | 520 | BlockDriverState *bdrv; |
| @@ -554,7 +554,6 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) | @@ -554,7 +554,6 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) | ||
| 554 | if (bdrv_open2(bdrv, filename, 0, drv) < 0) | 554 | if (bdrv_open2(bdrv, filename, 0, drv) < 0) |
| 555 | goto fail; | 555 | goto fail; |
| 556 | s->bs = bdrv; | 556 | s->bs = bdrv; |
| 557 | - *pbs = bdrv; | ||
| 558 | 557 | ||
| 559 | s->dev.speed = USB_SPEED_FULL; | 558 | s->dev.speed = USB_SPEED_FULL; |
| 560 | s->dev.handle_packet = usb_generic_handle_packet; | 559 | s->dev.handle_packet = usb_generic_handle_packet; |
| @@ -574,3 +573,10 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) | @@ -574,3 +573,10 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs) | ||
| 574 | qemu_free(s); | 573 | qemu_free(s); |
| 575 | return NULL; | 574 | return NULL; |
| 576 | } | 575 | } |
| 576 | + | ||
| 577 | +BlockDriverState *usb_msd_get_bdrv(USBDevice *dev) | ||
| 578 | +{ | ||
| 579 | + MSDState *s = (MSDState *)dev; | ||
| 580 | + | ||
| 581 | + return s->bs; | ||
| 582 | +} |
hw/usb.h
| @@ -253,7 +253,8 @@ USBDevice *usb_keyboard_init(void); | @@ -253,7 +253,8 @@ USBDevice *usb_keyboard_init(void); | ||
| 253 | void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *)); | 253 | void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *)); |
| 254 | 254 | ||
| 255 | /* usb-msd.c */ | 255 | /* usb-msd.c */ |
| 256 | -USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs); | 256 | +USBDevice *usb_msd_init(const char *filename); |
| 257 | +BlockDriverState *usb_msd_get_bdrv(USBDevice *dev); | ||
| 257 | 258 | ||
| 258 | /* usb-net.c */ | 259 | /* usb-net.c */ |
| 259 | USBDevice *usb_net_init(NICInfo *nd); | 260 | USBDevice *usb_net_init(NICInfo *nd); |
monitor.c
| @@ -74,13 +74,18 @@ static const term_cmd_t info_cmds[]; | @@ -74,13 +74,18 @@ static const term_cmd_t info_cmds[]; | ||
| 74 | 74 | ||
| 75 | static uint8_t term_outbuf[1024]; | 75 | static uint8_t term_outbuf[1024]; |
| 76 | static int term_outbuf_index; | 76 | static int term_outbuf_index; |
| 77 | +static BlockDriverCompletionFunc *password_completion_cb; | ||
| 78 | +static void *password_opaque; | ||
| 77 | 79 | ||
| 78 | static void monitor_start_input(void); | 80 | static void monitor_start_input(void); |
| 79 | -static void monitor_readline(const char *prompt, int is_password, | ||
| 80 | - char *buf, int buf_size); | ||
| 81 | 81 | ||
| 82 | static CPUState *mon_cpu = NULL; | 82 | static CPUState *mon_cpu = NULL; |
| 83 | 83 | ||
| 84 | +static void monitor_read_password(ReadLineFunc *readline_func, void *opaque) | ||
| 85 | +{ | ||
| 86 | + readline_start("Password: ", 1, readline_func, opaque); | ||
| 87 | +} | ||
| 88 | + | ||
| 84 | void term_flush(void) | 89 | void term_flush(void) |
| 85 | { | 90 | { |
| 86 | int i; | 91 | int i; |
| @@ -435,21 +440,29 @@ static void do_change_block(const char *device, const char *filename, const char | @@ -435,21 +440,29 @@ static void do_change_block(const char *device, const char *filename, const char | ||
| 435 | if (eject_device(bs, 0) < 0) | 440 | if (eject_device(bs, 0) < 0) |
| 436 | return; | 441 | return; |
| 437 | bdrv_open2(bs, filename, 0, drv); | 442 | bdrv_open2(bs, filename, 0, drv); |
| 438 | - monitor_read_bdrv_key(bs); | 443 | + monitor_read_bdrv_key_start(bs, NULL, NULL); |
| 444 | +} | ||
| 445 | + | ||
| 446 | +static void change_vnc_password_cb(void *opaque, const char *password) | ||
| 447 | +{ | ||
| 448 | + if (vnc_display_password(NULL, password) < 0) | ||
| 449 | + term_printf("could not set VNC server password\n"); | ||
| 450 | + | ||
| 451 | + monitor_start_input(); | ||
| 439 | } | 452 | } |
| 440 | 453 | ||
| 441 | static void do_change_vnc(const char *target, const char *arg) | 454 | static void do_change_vnc(const char *target, const char *arg) |
| 442 | { | 455 | { |
| 443 | if (strcmp(target, "passwd") == 0 || | 456 | if (strcmp(target, "passwd") == 0 || |
| 444 | strcmp(target, "password") == 0) { | 457 | strcmp(target, "password") == 0) { |
| 445 | - char password[9]; | ||
| 446 | if (arg) { | 458 | if (arg) { |
| 459 | + char password[9]; | ||
| 447 | strncpy(password, arg, sizeof(password)); | 460 | strncpy(password, arg, sizeof(password)); |
| 448 | password[sizeof(password) - 1] = '\0'; | 461 | password[sizeof(password) - 1] = '\0'; |
| 449 | - } else | ||
| 450 | - monitor_readline("Password: ", 1, password, sizeof(password)); | ||
| 451 | - if (vnc_display_password(NULL, password) < 0) | ||
| 452 | - term_printf("could not set VNC server password\n"); | 462 | + change_vnc_password_cb(NULL, password); |
| 463 | + } else { | ||
| 464 | + monitor_read_password(change_vnc_password_cb, NULL); | ||
| 465 | + } | ||
| 453 | } else { | 466 | } else { |
| 454 | if (vnc_display_open(NULL, target) < 0) | 467 | if (vnc_display_open(NULL, target) < 0) |
| 455 | term_printf("could not start VNC server on %s\n", target); | 468 | term_printf("could not start VNC server on %s\n", target); |
| @@ -496,15 +509,7 @@ static void do_stop(void) | @@ -496,15 +509,7 @@ static void do_stop(void) | ||
| 496 | vm_stop(EXCP_INTERRUPT); | 509 | vm_stop(EXCP_INTERRUPT); |
| 497 | } | 510 | } |
| 498 | 511 | ||
| 499 | -static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs) | ||
| 500 | -{ | ||
| 501 | - int *err = opaque; | ||
| 502 | - | ||
| 503 | - if (bdrv_key_required(bs)) | ||
| 504 | - *err = monitor_read_bdrv_key(bs); | ||
| 505 | - else | ||
| 506 | - *err = 0; | ||
| 507 | -} | 512 | +static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs); |
| 508 | 513 | ||
| 509 | static void do_cont(void) | 514 | static void do_cont(void) |
| 510 | { | 515 | { |
| @@ -516,6 +521,23 @@ static void do_cont(void) | @@ -516,6 +521,23 @@ static void do_cont(void) | ||
| 516 | vm_start(); | 521 | vm_start(); |
| 517 | } | 522 | } |
| 518 | 523 | ||
| 524 | +static void bdrv_key_cb(void *opaque, int err) | ||
| 525 | +{ | ||
| 526 | + /* another key was set successfully, retry to continue */ | ||
| 527 | + if (!err) | ||
| 528 | + do_cont(); | ||
| 529 | +} | ||
| 530 | + | ||
| 531 | +static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs) | ||
| 532 | +{ | ||
| 533 | + int *err = opaque; | ||
| 534 | + | ||
| 535 | + if (!*err && bdrv_key_required(bs)) { | ||
| 536 | + *err = -EBUSY; | ||
| 537 | + monitor_read_bdrv_key_start(bs, bdrv_key_cb, NULL); | ||
| 538 | + } | ||
| 539 | +} | ||
| 540 | + | ||
| 519 | #ifdef CONFIG_GDBSTUB | 541 | #ifdef CONFIG_GDBSTUB |
| 520 | static void do_gdbserver(const char *port) | 542 | static void do_gdbserver(const char *port) |
| 521 | { | 543 | { |
| @@ -2835,7 +2857,7 @@ static void monitor_handle_command1(void *opaque, const char *cmdline) | @@ -2835,7 +2857,7 @@ static void monitor_handle_command1(void *opaque, const char *cmdline) | ||
| 2835 | { | 2857 | { |
| 2836 | monitor_handle_command(cmdline); | 2858 | monitor_handle_command(cmdline); |
| 2837 | if (!monitor_suspended) | 2859 | if (!monitor_suspended) |
| 2838 | - monitor_start_input(); | 2860 | + readline_show_prompt(); |
| 2839 | else | 2861 | else |
| 2840 | monitor_suspended = 2; | 2862 | monitor_suspended = 2; |
| 2841 | } | 2863 | } |
| @@ -2898,46 +2920,36 @@ void monitor_init(CharDriverState *hd, int show_banner) | @@ -2898,46 +2920,36 @@ void monitor_init(CharDriverState *hd, int show_banner) | ||
| 2898 | readline_start("", 0, monitor_handle_command1, NULL); | 2920 | readline_start("", 0, monitor_handle_command1, NULL); |
| 2899 | } | 2921 | } |
| 2900 | 2922 | ||
| 2901 | -/* XXX: use threads ? */ | ||
| 2902 | -/* modal monitor readline */ | ||
| 2903 | -static int monitor_readline_started; | ||
| 2904 | -static char *monitor_readline_buf; | ||
| 2905 | -static int monitor_readline_buf_size; | ||
| 2906 | - | ||
| 2907 | -static void monitor_readline_cb(void *opaque, const char *input) | 2923 | +static void bdrv_password_cb(void *opaque, const char *password) |
| 2908 | { | 2924 | { |
| 2909 | - pstrcpy(monitor_readline_buf, monitor_readline_buf_size, input); | ||
| 2910 | - monitor_readline_started = 0; | ||
| 2911 | -} | 2925 | + BlockDriverState *bs = opaque; |
| 2926 | + int ret = 0; | ||
| 2912 | 2927 | ||
| 2913 | -static void monitor_readline(const char *prompt, int is_password, | ||
| 2914 | - char *buf, int buf_size) | ||
| 2915 | -{ | ||
| 2916 | - readline_start(prompt, is_password, monitor_readline_cb, NULL); | ||
| 2917 | - readline_show_prompt(); | ||
| 2918 | - monitor_readline_buf = buf; | ||
| 2919 | - monitor_readline_buf_size = buf_size; | ||
| 2920 | - monitor_readline_started = 1; | ||
| 2921 | - while (monitor_readline_started) { | ||
| 2922 | - main_loop_wait(10); | 2928 | + if (bdrv_set_key(bs, password) != 0) { |
| 2929 | + term_printf("invalid password\n"); | ||
| 2930 | + ret = -EPERM; | ||
| 2923 | } | 2931 | } |
| 2932 | + if (password_completion_cb) | ||
| 2933 | + password_completion_cb(password_opaque, ret); | ||
| 2934 | + | ||
| 2935 | + monitor_start_input(); | ||
| 2924 | } | 2936 | } |
| 2925 | 2937 | ||
| 2926 | -int monitor_read_bdrv_key(BlockDriverState *bs) | 2938 | +void monitor_read_bdrv_key_start(BlockDriverState *bs, |
| 2939 | + BlockDriverCompletionFunc *completion_cb, | ||
| 2940 | + void *opaque) | ||
| 2927 | { | 2941 | { |
| 2928 | - char password[256]; | ||
| 2929 | - int i; | ||
| 2930 | - | ||
| 2931 | - if (!bdrv_is_encrypted(bs)) | ||
| 2932 | - return 0; | 2942 | + if (!bdrv_key_required(bs)) { |
| 2943 | + if (completion_cb) | ||
| 2944 | + completion_cb(opaque, 0); | ||
| 2945 | + return; | ||
| 2946 | + } | ||
| 2933 | 2947 | ||
| 2934 | term_printf("%s (%s) is encrypted.\n", bdrv_get_device_name(bs), | 2948 | term_printf("%s (%s) is encrypted.\n", bdrv_get_device_name(bs), |
| 2935 | bdrv_get_encrypted_filename(bs)); | 2949 | bdrv_get_encrypted_filename(bs)); |
| 2936 | - for(i = 0; i < 3; i++) { | ||
| 2937 | - monitor_readline("Password: ", 1, password, sizeof(password)); | ||
| 2938 | - if (bdrv_set_key(bs, password) == 0) | ||
| 2939 | - return 0; | ||
| 2940 | - term_printf("invalid password\n"); | ||
| 2941 | - } | ||
| 2942 | - return -EPERM; | 2950 | + |
| 2951 | + password_completion_cb = completion_cb; | ||
| 2952 | + password_opaque = opaque; | ||
| 2953 | + | ||
| 2954 | + monitor_read_password(bdrv_password_cb, bs); | ||
| 2943 | } | 2955 | } |
vl.c
| @@ -2661,6 +2661,16 @@ int usb_device_add_dev(USBDevice *dev) | @@ -2661,6 +2661,16 @@ int usb_device_add_dev(USBDevice *dev) | ||
| 2661 | return 0; | 2661 | return 0; |
| 2662 | } | 2662 | } |
| 2663 | 2663 | ||
| 2664 | +static void usb_msd_password_cb(void *opaque, int err) | ||
| 2665 | +{ | ||
| 2666 | + USBDevice *dev = opaque; | ||
| 2667 | + | ||
| 2668 | + if (!err) | ||
| 2669 | + usb_device_add_dev(dev); | ||
| 2670 | + else | ||
| 2671 | + dev->handle_destroy(dev); | ||
| 2672 | +} | ||
| 2673 | + | ||
| 2664 | static int usb_device_add(const char *devname, int is_hotplug) | 2674 | static int usb_device_add(const char *devname, int is_hotplug) |
| 2665 | { | 2675 | { |
| 2666 | const char *p; | 2676 | const char *p; |
| @@ -2680,14 +2690,15 @@ static int usb_device_add(const char *devname, int is_hotplug) | @@ -2680,14 +2690,15 @@ static int usb_device_add(const char *devname, int is_hotplug) | ||
| 2680 | } else if (strstart(devname, "disk:", &p)) { | 2690 | } else if (strstart(devname, "disk:", &p)) { |
| 2681 | BlockDriverState *bs; | 2691 | BlockDriverState *bs; |
| 2682 | 2692 | ||
| 2683 | - dev = usb_msd_init(p, &bs); | 2693 | + dev = usb_msd_init(p); |
| 2684 | if (!dev) | 2694 | if (!dev) |
| 2685 | return -1; | 2695 | return -1; |
| 2696 | + bs = usb_msd_get_bdrv(dev); | ||
| 2686 | if (bdrv_key_required(bs)) { | 2697 | if (bdrv_key_required(bs)) { |
| 2687 | autostart = 0; | 2698 | autostart = 0; |
| 2688 | - if (is_hotplug && monitor_read_bdrv_key(bs) < 0) { | ||
| 2689 | - dev->handle_destroy(dev); | ||
| 2690 | - return -1; | 2699 | + if (is_hotplug) { |
| 2700 | + monitor_read_bdrv_key_start(bs, usb_msd_password_cb, dev); | ||
| 2701 | + return 0; | ||
| 2691 | } | 2702 | } |
| 2692 | } | 2703 | } |
| 2693 | } else if (!strcmp(devname, "wacom-tablet")) { | 2704 | } else if (!strcmp(devname, "wacom-tablet")) { |