summary refs log tree commit diff stats
path: root/monitor.c
diff options
context:
space:
mode:
authoraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2009-03-05 23:01:15 +0000
committeraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2009-03-05 23:01:15 +0000
commitbb5fc20f7c1c65e95030da3629dd0d7a0cce38cd (patch)
tree2cb53fa2bf9b5165b338e1cc85c8dedc5bf25879 /monitor.c
parent9dd442b1234a27375c956e650e49a32c61ff6167 (diff)
downloadfocaccia-qemu-bb5fc20f7c1c65e95030da3629dd0d7a0cce38cd.tar.gz
focaccia-qemu-bb5fc20f7c1c65e95030da3629dd0d7a0cce38cd.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
Diffstat (limited to 'monitor.c')
-rw-r--r--monitor.c114
1 files changed, 63 insertions, 51 deletions
diff --git a/monitor.c b/monitor.c
index 322cf1ae3a..183c846847 100644
--- a/monitor.c
+++ b/monitor.c
@@ -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);
 }