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
This commit is contained in:
parent
9dd442b123
commit
bb5fc20f7c
21
block.c
21
block.c
@ -430,11 +430,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* call the change callback */
|
if (!bdrv_key_required(bs)) {
|
||||||
bs->media_changed = 1;
|
/* call the change callback */
|
||||||
if (bs->change_cb)
|
bs->media_changed = 1;
|
||||||
bs->change_cb(bs->change_opaque);
|
if (bs->change_cb)
|
||||||
|
bs->change_cb(bs->change_opaque);
|
||||||
|
}
|
||||||
return 0;
|
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)
|
if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
|
||||||
return -1;
|
return -1;
|
||||||
ret = bs->drv->bdrv_set_key(bs, key);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +304,11 @@ void term_flush(void);
|
|||||||
void term_print_help(void);
|
void term_print_help(void);
|
||||||
void monitor_suspend(void);
|
void monitor_suspend(void);
|
||||||
void monitor_resume(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 */
|
/* readline.c */
|
||||||
typedef void ReadLineFunc(void *opaque, const char *str);
|
typedef void ReadLineFunc(void *opaque, const char *str);
|
||||||
|
10
hw/usb-msd.c
10
hw/usb-msd.c
@ -514,7 +514,7 @@ static void usb_msd_handle_destroy(USBDevice *dev)
|
|||||||
qemu_free(s);
|
qemu_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)
|
USBDevice *usb_msd_init(const char *filename)
|
||||||
{
|
{
|
||||||
MSDState *s;
|
MSDState *s;
|
||||||
BlockDriverState *bdrv;
|
BlockDriverState *bdrv;
|
||||||
@ -554,7 +554,6 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)
|
|||||||
if (bdrv_open2(bdrv, filename, 0, drv) < 0)
|
if (bdrv_open2(bdrv, filename, 0, drv) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
s->bs = bdrv;
|
s->bs = bdrv;
|
||||||
*pbs = bdrv;
|
|
||||||
|
|
||||||
s->dev.speed = USB_SPEED_FULL;
|
s->dev.speed = USB_SPEED_FULL;
|
||||||
s->dev.handle_packet = usb_generic_handle_packet;
|
s->dev.handle_packet = usb_generic_handle_packet;
|
||||||
@ -574,3 +573,10 @@ USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)
|
|||||||
qemu_free(s);
|
qemu_free(s);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BlockDriverState *usb_msd_get_bdrv(USBDevice *dev)
|
||||||
|
{
|
||||||
|
MSDState *s = (MSDState *)dev;
|
||||||
|
|
||||||
|
return s->bs;
|
||||||
|
}
|
||||||
|
3
hw/usb.h
3
hw/usb.h
@ -253,7 +253,8 @@ USBDevice *usb_keyboard_init(void);
|
|||||||
void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *));
|
void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *));
|
||||||
|
|
||||||
/* usb-msd.c */
|
/* 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 */
|
/* usb-net.c */
|
||||||
USBDevice *usb_net_init(NICInfo *nd);
|
USBDevice *usb_net_init(NICInfo *nd);
|
||||||
|
114
monitor.c
114
monitor.c
@ -74,13 +74,18 @@ static const term_cmd_t info_cmds[];
|
|||||||
|
|
||||||
static uint8_t term_outbuf[1024];
|
static uint8_t term_outbuf[1024];
|
||||||
static int term_outbuf_index;
|
static int term_outbuf_index;
|
||||||
|
static BlockDriverCompletionFunc *password_completion_cb;
|
||||||
|
static void *password_opaque;
|
||||||
|
|
||||||
static void monitor_start_input(void);
|
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 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)
|
void term_flush(void)
|
||||||
{
|
{
|
||||||
int i;
|
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)
|
if (eject_device(bs, 0) < 0)
|
||||||
return;
|
return;
|
||||||
bdrv_open2(bs, filename, 0, drv);
|
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)
|
static void do_change_vnc(const char *target, const char *arg)
|
||||||
{
|
{
|
||||||
if (strcmp(target, "passwd") == 0 ||
|
if (strcmp(target, "passwd") == 0 ||
|
||||||
strcmp(target, "password") == 0) {
|
strcmp(target, "password") == 0) {
|
||||||
char password[9];
|
|
||||||
if (arg) {
|
if (arg) {
|
||||||
|
char password[9];
|
||||||
strncpy(password, arg, sizeof(password));
|
strncpy(password, arg, sizeof(password));
|
||||||
password[sizeof(password) - 1] = '\0';
|
password[sizeof(password) - 1] = '\0';
|
||||||
} else
|
change_vnc_password_cb(NULL, password);
|
||||||
monitor_readline("Password: ", 1, password, sizeof(password));
|
} else {
|
||||||
if (vnc_display_password(NULL, password) < 0)
|
monitor_read_password(change_vnc_password_cb, NULL);
|
||||||
term_printf("could not set VNC server password\n");
|
}
|
||||||
} else {
|
} else {
|
||||||
if (vnc_display_open(NULL, target) < 0)
|
if (vnc_display_open(NULL, target) < 0)
|
||||||
term_printf("could not start VNC server on %s\n", target);
|
term_printf("could not start VNC server on %s\n", target);
|
||||||
@ -496,15 +509,7 @@ static void do_stop(void)
|
|||||||
vm_stop(EXCP_INTERRUPT);
|
vm_stop(EXCP_INTERRUPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
|
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 do_cont(void)
|
static void do_cont(void)
|
||||||
{
|
{
|
||||||
@ -516,6 +521,23 @@ static void do_cont(void)
|
|||||||
vm_start();
|
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
|
#ifdef CONFIG_GDBSTUB
|
||||||
static void do_gdbserver(const char *port)
|
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);
|
monitor_handle_command(cmdline);
|
||||||
if (!monitor_suspended)
|
if (!monitor_suspended)
|
||||||
monitor_start_input();
|
readline_show_prompt();
|
||||||
else
|
else
|
||||||
monitor_suspended = 2;
|
monitor_suspended = 2;
|
||||||
}
|
}
|
||||||
@ -2898,46 +2920,36 @@ void monitor_init(CharDriverState *hd, int show_banner)
|
|||||||
readline_start("", 0, monitor_handle_command1, NULL);
|
readline_start("", 0, monitor_handle_command1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: use threads ? */
|
static void bdrv_password_cb(void *opaque, const char *password)
|
||||||
/* 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)
|
|
||||||
{
|
{
|
||||||
pstrcpy(monitor_readline_buf, monitor_readline_buf_size, input);
|
BlockDriverState *bs = opaque;
|
||||||
monitor_readline_started = 0;
|
int ret = 0;
|
||||||
}
|
|
||||||
|
|
||||||
static void monitor_readline(const char *prompt, int is_password,
|
if (bdrv_set_key(bs, password) != 0) {
|
||||||
char *buf, int buf_size)
|
term_printf("invalid password\n");
|
||||||
{
|
ret = -EPERM;
|
||||||
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 (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];
|
if (!bdrv_key_required(bs)) {
|
||||||
int i;
|
if (completion_cb)
|
||||||
|
completion_cb(opaque, 0);
|
||||||
if (!bdrv_is_encrypted(bs))
|
return;
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
term_printf("%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
|
term_printf("%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
|
||||||
bdrv_get_encrypted_filename(bs));
|
bdrv_get_encrypted_filename(bs));
|
||||||
for(i = 0; i < 3; i++) {
|
|
||||||
monitor_readline("Password: ", 1, password, sizeof(password));
|
password_completion_cb = completion_cb;
|
||||||
if (bdrv_set_key(bs, password) == 0)
|
password_opaque = opaque;
|
||||||
return 0;
|
|
||||||
term_printf("invalid password\n");
|
monitor_read_password(bdrv_password_cb, bs);
|
||||||
}
|
|
||||||
return -EPERM;
|
|
||||||
}
|
}
|
||||||
|
19
vl.c
19
vl.c
@ -2661,6 +2661,16 @@ int usb_device_add_dev(USBDevice *dev)
|
|||||||
return 0;
|
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)
|
static int usb_device_add(const char *devname, int is_hotplug)
|
||||||
{
|
{
|
||||||
const char *p;
|
const char *p;
|
||||||
@ -2680,14 +2690,15 @@ static int usb_device_add(const char *devname, int is_hotplug)
|
|||||||
} else if (strstart(devname, "disk:", &p)) {
|
} else if (strstart(devname, "disk:", &p)) {
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
|
|
||||||
dev = usb_msd_init(p, &bs);
|
dev = usb_msd_init(p);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -1;
|
return -1;
|
||||||
|
bs = usb_msd_get_bdrv(dev);
|
||||||
if (bdrv_key_required(bs)) {
|
if (bdrv_key_required(bs)) {
|
||||||
autostart = 0;
|
autostart = 0;
|
||||||
if (is_hotplug && monitor_read_bdrv_key(bs) < 0) {
|
if (is_hotplug) {
|
||||||
dev->handle_destroy(dev);
|
monitor_read_bdrv_key_start(bs, usb_msd_password_cb, dev);
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!strcmp(devname, "wacom-tablet")) {
|
} else if (!strcmp(devname, "wacom-tablet")) {
|
||||||
|
Loading…
Reference in New Issue
Block a user