[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 12/17] monitor: Rework modal password input
From: |
Jan Kiszka |
Subject: |
[Qemu-devel] [PATCH 12/17] monitor: Rework modal password input |
Date: |
Sat, 07 Feb 2009 19:16:29 +0100 |
User-agent: |
StGIT/0.14.2 |
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 <address@hidden>
---
block.c | 21 ++++++++---
hw/usb-msd.c | 10 ++++-
hw/usb.h | 3 +-
monitor.c | 111 ++++++++++++++++++++++++++++++++--------------------------
monitor.h | 4 ++
vl.c | 19 ++++++++--
6 files changed, 105 insertions(+), 63 deletions(-)
diff --git a/block.c b/block.c
index 3481988..5a455e3 100644
--- a/block.c
+++ b/block.c
@@ -429,11 +429,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;
}
@@ -944,7 +945,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;
}
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 2b0338d..1594bb0 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;
+}
diff --git a/hw/usb.h b/hw/usb.h
index 4cd832d..a5e0d44 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -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);
diff --git a/monitor.c b/monitor.c
index e187412..51e6d9f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -79,13 +79,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 monitor_flush(void)
{
MonitorTerm *term;
@@ -445,21 +450,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)
+ monitor_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)
- monitor_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)
monitor_printf("could not start VNC server on %s\n", target);
@@ -506,15 +519,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)
{
@@ -526,6 +531,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)
{
@@ -2858,45 +2880,36 @@ void monitor_init(CharDriverState *chr)
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);
- 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) {
+ monitor_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;
+ }
monitor_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;
- monitor_printf("invalid password\n");
- }
- return -EPERM;
+
+ password_completion_cb = completion_cb;
+ password_opaque = opaque;
+
+ monitor_read_password(bdrv_password_cb, bs);
}
diff --git a/monitor.h b/monitor.h
index ae79a68..4b35a25 100644
--- a/monitor.h
+++ b/monitor.h
@@ -8,7 +8,9 @@ void monitor_init(CharDriverState *chr);
void monitor_suspend(void);
void monitor_resume(void);
-int monitor_read_bdrv_key(BlockDriverState *bs);
+void monitor_read_bdrv_key_start(BlockDriverState *bs,
+ BlockDriverCompletionFunc *completion_cb,
+ void *opaque);
void monitor_vprintf(const char *fmt, va_list ap);
void monitor_printf(const char *fmt, ...)
diff --git a/vl.c b/vl.c
index 4b25080..f5b6171 100644
--- a/vl.c
+++ b/vl.c
@@ -2603,6 +2603,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;
@@ -2622,14 +2632,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")) {
- [Qemu-devel] [PATCH 15/17] monitor: Improve mux'ed console experience, (continued)
- [Qemu-devel] [PATCH 15/17] monitor: Improve mux'ed console experience, Jan Kiszka, 2009/02/07
- [Qemu-devel] [PATCH 16/17] monitor: Introduce MONITOR_USE_READLINE flag, Jan Kiszka, 2009/02/07
- [Qemu-devel] [PATCH 14/17] monitor: Decouple terminals, Jan Kiszka, 2009/02/07
- [Qemu-devel] [PATCH 17/17] monitor: Pass-through for gdbstub, Jan Kiszka, 2009/02/07
- [Qemu-devel] [PATCH 13/17] monitor: Introduce ReadLineState, Jan Kiszka, 2009/02/07
- [Qemu-devel] [PATCH 07/17] monitor: Introduce monitor.h and readline.h, Jan Kiszka, 2009/02/07
- [Qemu-devel] [PATCH 12/17] monitor: Rework modal password input,
Jan Kiszka <=
- [Qemu-devel] [PATCH 06/17] char-mux: Use separate input buffers, Jan Kiszka, 2009/02/07
- [Qemu-devel] [PATCH 11/17] monitor: Drop banner hiding, Jan Kiszka, 2009/02/07