qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 00/19] monitor rework
@ 2009-02-21 18:29 Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 01/19] char: Fix initial reset Jan Kiszka
                   ` (19 more replies)
  0 siblings, 20 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

Looks like each round of this series makes it longer and longer... :)

Changes in this version:
 o consequent rework of the monitor API (as Anthony suggested)
    - introduce mon argument to monitor services
    - pass mon to monitor command handlers
 o fix for broken initial CHR_EVENT_RESET
 o proper monitor default size
 o more testing, various fixes
   (e.g. telnet monitors didn't work with v1)

To recall the major contributions of this series:
 o complete fix for early disk password inquiry
 o non-VM-blocking password inquiry
 o unlimited and fully decoupled monitor terminals
 o monitor pass-through via gdb
 o improved usability of mux'ed monitor terminals

Ideally, the series would go in before the upcoming release. But if
there are concerns regarding its intrusiveness and potential
regressions, at least the first 8 patches should be merged (as they
mostly contain bug fixes).


Find the patches also at git://git.kiszka.org/qemu.git queues/monitor

Jan Kiszka (19):
      char: Fix initial reset
      char-mux: Use separate input buffers
      block: Polish error handling of brdv_open2
      block: Improve bdrv_iterate
      block: Introduce bdrv_get_encrypted_filename
      monitor: Use reasonable default virtual console size
      monitor: Report encrypted disks in snapshot mode
      monitor: Rework early disk password inquiry
      monitor: Simplify password input mode
      monitor: Break out readline_show_prompt
      monitor: Rework modal password input
      monitor: Rework API
      monitor: Rework terminal management
      monitor: Drop banner hiding
      monitor: Introduce ReadLineState
      monitor: Decouple terminals
      monitor: Improve mux'ed console experience
      monitor: Introduce MONITOR_USE_READLINE flag
      monitor: Pass-through for gdbstub

 audio/audio.c      |    6 +-
 audio/wavcapture.c |   21 +-
 block.c            |  160 +++++----
 block.h            |   12 +-
 block_int.h        |    1 +
 console.h          |   33 +--
 disas.c            |   17 +-
 disas.h            |    8 +-
 gdbstub.c          |   54 +++-
 hw/an5206.c        |    5 +-
 hw/arm_pic.c       |    5 +-
 hw/etraxfs_pic.c   |    5 +-
 hw/i8259.c         |   21 +-
 hw/pc.c            |    9 +-
 hw/pc.h            |    7 +-
 hw/pci-hotplug.c   |   51 ++--
 hw/pci.c           |   32 +-
 hw/pci.h           |    4 +-
 hw/pcmcia.h        |    4 +-
 hw/shix.c          |    5 +-
 hw/slavio_intctl.c |   20 +-
 hw/sun4c_intctl.c  |   16 +-
 hw/sun4m.c         |    8 +-
 hw/sun4m.h         |   10 +-
 hw/usb-msd.c       |   10 +-
 hw/usb.h           |    6 +-
 migration-exec.c   |   12 +-
 migration-tcp.c    |   12 +-
 migration.c        |   42 ++-
 migration.h        |   14 +-
 monitor.c          |  966 +++++++++++++++++++++++++++++-----------------------
 monitor.h          |   29 ++
 net.c              |   30 +-
 net.h              |    8 +-
 qemu-char.c        |   62 +++-
 qemu-char.h        |   13 +-
 qemu-common.h      |    3 +
 qemu-tool.c        |    8 +-
 readline.c         |  410 +++++++++++-----------
 readline.h         |   55 +++
 savevm.c           |   83 +++---
 slirp/misc.c       |    4 +-
 sysemu.h           |   25 +-
 usb-linux.c        |   35 ++-
 vl.c               |  132 ++++----
 vnc.c              |   20 +-
 46 files changed, 1402 insertions(+), 1091 deletions(-)
 create mode 100644 monitor.h
 create mode 100644 readline.h

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 01/19] char: Fix initial reset
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-03-05 23:01   ` Anthony Liguori
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 08/19] monitor: Rework early disk password inquiry Jan Kiszka
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

Recent changes to the graphical console initialization broke the initial
CHR_EVENT_RESET distribution. The reset BHs generated on char device
initialization are now already consumed during machine init (ide init
... -> qemu_aio_wait -> qemu_bh_poll). Therefore, this patch moves the
initial qemu_chr_reset calls into a separate funtion which is called
after machine init.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 qemu-char.c |   20 ++++++++++++++++----
 qemu-char.h |    1 +
 vl.c        |    1 +
 3 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index 7cdeffd..1332863 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -101,6 +101,10 @@
 /***********************************************************/
 /* character device */
 
+static TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
+    TAILQ_HEAD_INITIALIZER(chardevs);
+static int initial_reset_issued;
+
 static void qemu_chr_event(CharDriverState *s, int event)
 {
     if (!s->chr_event)
@@ -118,12 +122,23 @@ static void qemu_chr_reset_bh(void *opaque)
 
 void qemu_chr_reset(CharDriverState *s)
 {
-    if (s->bh == NULL) {
+    if (s->bh == NULL && initial_reset_issued) {
 	s->bh = qemu_bh_new(qemu_chr_reset_bh, s);
 	qemu_bh_schedule(s->bh);
     }
 }
 
+void qemu_chr_initial_reset(void)
+{
+    CharDriverState *chr;
+
+    initial_reset_issued = 1;
+
+    TAILQ_FOREACH(chr, &chardevs, next) {
+        qemu_chr_reset(chr);
+    }
+}
+
 int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
 {
     return s->chr_write(s, buf, len);
@@ -2076,9 +2091,6 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
     return NULL;
 }
 
-static TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs
-= TAILQ_HEAD_INITIALIZER(chardevs);
-
 CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s))
 {
     const char *p;
diff --git a/qemu-char.h b/qemu-char.h
index bc0fcf3..9ff6b99 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -74,6 +74,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
                            void *opaque);
 int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg);
 void qemu_chr_reset(CharDriverState *s);
+void qemu_chr_initial_reset(void);
 int qemu_chr_can_read(CharDriverState *s);
 void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len);
 void qemu_chr_accept_input(CharDriverState *s);
diff --git a/vl.c b/vl.c
index b653056..16353f5 100644
--- a/vl.c
+++ b/vl.c
@@ -5667,6 +5667,7 @@ int main(int argc, char **argv, char **envp)
     }
 
     text_consoles_set_display(display_state);
+    qemu_chr_initial_reset();
 
     if (monitor_device && monitor_hd)
         monitor_init(monitor_hd, !nographic);

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 02/19] char-mux: Use separate input buffers
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (3 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 04/19] block: Improve bdrv_iterate Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 07/19] monitor: Report encrypted disks in snapshot mode Jan Kiszka
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

Currently, the intermediate input buffer of mux'ed character devices
records data across all sub-devices. This has the side effect that we
easily leak data recorded over one sub-devices to another once we switch
the focus. Avoid data loss and confusion by defining exclusive buffers.

Note: In contrast to the original author's claim, the buffering concept
still breaks down when the fifo of the currently active sub-device is
full. As we cannot accept futher data from this point on without risking
to loose it, we will also miss escape sequences, just like without all
that buffering. In short: There is no reliable escape sequence handling
without infinite buffers or the risk of loosing some data.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 qemu-char.c |   24 ++++++++++++++----------
 1 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index 1332863..1fd3aef 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -225,12 +225,15 @@ typedef struct {
     IOEventHandler *chr_event[MAX_MUX];
     void *ext_opaque[MAX_MUX];
     CharDriverState *drv;
-    unsigned char buffer[MUX_BUFFER_SIZE];
-    int prod;
-    int cons;
     int mux_cnt;
     int term_got_escape;
     int max_size;
+    /* Intermediate input buffer allows to catch escape sequences even if the
+       currently active device is not accepting any input - but only until it
+       is full as well. */
+    unsigned char buffer[MAX_MUX][MUX_BUFFER_SIZE];
+    int prod[MAX_MUX];
+    int cons[MAX_MUX];
 } MuxDriver;
 
 
@@ -360,11 +363,11 @@ static void mux_chr_accept_input(CharDriverState *chr)
     int m = chr->focus;
     MuxDriver *d = chr->opaque;
 
-    while (d->prod != d->cons &&
+    while (d->prod[m] != d->cons[m] &&
            d->chr_can_read[m] &&
            d->chr_can_read[m](d->ext_opaque[m])) {
         d->chr_read[m](d->ext_opaque[m],
-                       &d->buffer[d->cons++ & MUX_BUFFER_MASK], 1);
+                       &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1);
     }
 }
 
@@ -372,11 +375,12 @@ static int mux_chr_can_read(void *opaque)
 {
     CharDriverState *chr = opaque;
     MuxDriver *d = chr->opaque;
+    int m = chr->focus;
 
-    if ((d->prod - d->cons) < MUX_BUFFER_SIZE)
+    if ((d->prod[m] - d->cons[m]) < MUX_BUFFER_SIZE)
         return 1;
-    if (d->chr_can_read[chr->focus])
-        return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]);
+    if (d->chr_can_read[m])
+        return d->chr_can_read[m](d->ext_opaque[m]);
     return 0;
 }
 
@@ -391,12 +395,12 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
 
     for(i = 0; i < size; i++)
         if (mux_proc_byte(chr, d, buf[i])) {
-            if (d->prod == d->cons &&
+            if (d->prod[m] == d->cons[m] &&
                 d->chr_can_read[m] &&
                 d->chr_can_read[m](d->ext_opaque[m]))
                 d->chr_read[m](d->ext_opaque[m], &buf[i], 1);
             else
-                d->buffer[d->prod++ & MUX_BUFFER_MASK] = buf[i];
+                d->buffer[m][d->prod[m]++ & MUX_BUFFER_MASK] = buf[i];
         }
 }
 

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 04/19] block: Improve bdrv_iterate
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (2 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 05/19] block: Introduce bdrv_get_encrypted_filename Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 02/19] char-mux: Use separate input buffers Jan Kiszka
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

Make bdrv_iterate more useful by passing the BlockDriverState to the
iterator instead of the device name.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 block.c   |    4 ++--
 block.h   |    3 ++-
 monitor.c |    3 ++-
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/block.c b/block.c
index 330317a..d12a9aa 100644
--- a/block.c
+++ b/block.c
@@ -966,12 +966,12 @@ BlockDriverState *bdrv_find(const char *name)
     return NULL;
 }
 
-void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
+void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque)
 {
     BlockDriverState *bs;
 
     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
-        it(opaque, bs->device_name);
+        it(opaque, bs);
     }
 }
 
diff --git a/block.h b/block.h
index e1927dd..aa26ef3 100644
--- a/block.h
+++ b/block.h
@@ -141,7 +141,8 @@ void bdrv_set_change_cb(BlockDriverState *bs,
                         void (*change_cb)(void *opaque), void *opaque);
 void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
 BlockDriverState *bdrv_find(const char *name);
-void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque);
+void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs),
+                  void *opaque);
 int bdrv_is_encrypted(BlockDriverState *bs);
 int bdrv_set_key(BlockDriverState *bs, const char *key);
 void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
diff --git a/monitor.c b/monitor.c
index 35f014d..90dbdca 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2648,8 +2648,9 @@ static void file_completion(const char *input)
     closedir(ffs);
 }
 
-static void block_completion_it(void *opaque, const char *name)
+static void block_completion_it(void *opaque, BlockDriverState *bs)
 {
+    const char *name = bdrv_get_device_name(bs);
     const char *input = opaque;
 
     if (input[0] == '\0' ||

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 06/19] monitor: Use reasonable default virtual console size
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (6 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 10/19] monitor: Break out readline_show_prompt Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 03/19] block: Polish error handling of brdv_open2 Jan Kiszka
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

If a target uses a tiny display (like the MusicPal), the default monitor
is currently set to the same size. Fix this by applying the same
defaults like already used serial and virtio consoles.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 vl.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/vl.c b/vl.c
index 16353f5..1c5878b 100644
--- a/vl.c
+++ b/vl.c
@@ -4679,7 +4679,7 @@ int main(int argc, char **argv, char **envp)
     kernel_cmdline = "";
     cyls = heads = secs = 0;
     translation = BIOS_ATA_TRANSLATION_AUTO;
-    monitor_device = "vc";
+    monitor_device = "vc:80Cx24C";
 
     serial_devices[0] = "vc:80Cx24C";
     for(i = 1; i < MAX_SERIAL_PORTS; i++)

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 05/19] block: Introduce bdrv_get_encrypted_filename
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 01/19] char: Fix initial reset Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 08/19] monitor: Rework early disk password inquiry Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 04/19] block: Improve bdrv_iterate Jan Kiszka
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

Introduce bdrv_get_encrypted_filename service to allow more informative
password prompting.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 block.c |   10 ++++++++++
 block.h |    1 +
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/block.c b/block.c
index d12a9aa..78982f4 100644
--- a/block.c
+++ b/block.c
@@ -1089,6 +1089,16 @@ void bdrv_info_stats (void)
     }
 }
 
+const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
+{
+    if (bs->backing_hd && bs->backing_hd->encrypted)
+        return bs->backing_file;
+    else if (bs->encrypted)
+        return bs->filename;
+    else
+        return NULL;
+}
+
 void bdrv_get_backing_filename(BlockDriverState *bs,
                                char *filename, int filename_size)
 {
diff --git a/block.h b/block.h
index aa26ef3..a01fa31 100644
--- a/block.h
+++ b/block.h
@@ -152,6 +152,7 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
                           const uint8_t *buf, int nb_sectors);
 int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
 
+const char *bdrv_get_encrypted_filename(BlockDriverState *bs);
 void bdrv_get_backing_filename(BlockDriverState *bs,
                                char *filename, int filename_size);
 int bdrv_snapshot_create(BlockDriverState *bs,

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 09/19] monitor: Simplify password input mode
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (8 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 03/19] block: Polish error handling of brdv_open2 Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 11/19] monitor: Rework modal password input Jan Kiszka
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

Drop the hack to query passwords on all monitor terminals now that they
are requested when the user initially enters 'continue'.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 monitor.c |   20 --------------------
 1 files changed, 0 insertions(+), 20 deletions(-)

diff --git a/monitor.c b/monitor.c
index ae3af5e..c5234ba 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2881,20 +2881,6 @@ static void monitor_readline_cb(void *opaque, const char *input)
 static void monitor_readline(const char *prompt, int is_password,
                              char *buf, int buf_size)
 {
-    int i;
-    int old_focus[MAX_MON];
-
-    if (is_password) {
-        for (i = 0; i < MAX_MON; i++) {
-            old_focus[i] = 0;
-            if (monitor_hd[i]) {
-                old_focus[i] = monitor_hd[i]->focus;
-                monitor_hd[i]->focus = 0;
-                qemu_chr_send_event(monitor_hd[i], CHR_EVENT_FOCUS);
-            }
-        }
-    }
-
     readline_start(prompt, is_password, monitor_readline_cb, NULL);
     monitor_readline_buf = buf;
     monitor_readline_buf_size = buf_size;
@@ -2902,12 +2888,6 @@ static void monitor_readline(const char *prompt, int is_password,
     while (monitor_readline_started) {
         main_loop_wait(10);
     }
-    /* restore original focus */
-    if (is_password) {
-        for (i = 0; i < MAX_MON; i++)
-            if (old_focus[i])
-                monitor_hd[i]->focus = old_focus[i];
-    }
 }
 
 int monitor_read_bdrv_key(BlockDriverState *bs)

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 08/19] monitor: Rework early disk password inquiry
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 01/19] char: Fix initial reset Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 05/19] block: Introduce bdrv_get_encrypted_filename Jan Kiszka
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

Reading the passwords for encrypted hard disks during early startup is
broken (I guess for quiet a while now):
 - No monitor terminal is ready for input at this point
 - Forcing all mux'ed terminals into monitor mode can confuse other
   users of that channels

To overcome these issues and to lay the ground for a clean decoupling of
monitor terminals, this patch changes the initial password inquiry as
follows:
 - Prevent autostart if there is some encrypted disk
 - Once the user tries to resume the VM, prompt for all missing
   passwords
 - Only resume if all passwords were accepted

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 block.c      |   14 ++++++++++-
 block.h      |    4 ++-
 block_int.h  |    1 +
 console.h    |    3 +-
 hw/usb-msd.c |    6 ++---
 hw/usb.h     |    5 +++-
 monitor.c    |   44 ++++++++++++++++++++++++++++++++---
 vl.c         |   73 +++++++++++++++++-----------------------------------------
 8 files changed, 85 insertions(+), 65 deletions(-)

diff --git a/block.c b/block.c
index fe58b89..52d1448 100644
--- a/block.c
+++ b/block.c
@@ -335,6 +335,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
     bs->read_only = 0;
     bs->is_temporary = 0;
     bs->encrypted = 0;
+    bs->valid_key = 0;
 
     if (flags & BDRV_O_SNAPSHOT) {
         BlockDriverState *bs1;
@@ -921,6 +922,15 @@ int bdrv_is_encrypted(BlockDriverState *bs)
     return bs->encrypted;
 }
 
+int bdrv_key_required(BlockDriverState *bs)
+{
+    BlockDriverState *backing_hd = bs->backing_hd;
+
+    if (backing_hd && backing_hd->encrypted && !backing_hd->valid_key)
+        return 1;
+    return (bs->encrypted && !bs->valid_key);
+}
+
 int bdrv_set_key(BlockDriverState *bs, const char *key)
 {
     int ret;
@@ -933,7 +943,9 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
     }
     if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
         return -1;
-    return bs->drv->bdrv_set_key(bs, key);
+    ret = bs->drv->bdrv_set_key(bs, key);
+    bs->valid_key = (ret == 0);
+    return ret;
 }
 
 void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
diff --git a/block.h b/block.h
index a01fa31..5c6eaf9 100644
--- a/block.h
+++ b/block.h
@@ -103,8 +103,6 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
                                  BlockDriverCompletionFunc *cb, void *opaque);
 void bdrv_aio_cancel(BlockDriverAIOCB *acb);
 
-int qemu_key_check(BlockDriverState *bs, const char *name);
-
 /* Ensure contents are flushed to disk.  */
 void bdrv_flush(BlockDriverState *bs);
 void bdrv_flush_all(void);
@@ -144,7 +142,9 @@ BlockDriverState *bdrv_find(const char *name);
 void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs),
                   void *opaque);
 int bdrv_is_encrypted(BlockDriverState *bs);
+int bdrv_key_required(BlockDriverState *bs);
 int bdrv_set_key(BlockDriverState *bs, const char *key);
+int bdrv_query_missing_keys(void);
 void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
                          void *opaque);
 const char *bdrv_get_device_name(BlockDriverState *bs);
diff --git a/block_int.h b/block_int.h
index 781789c..57ca18a 100644
--- a/block_int.h
+++ b/block_int.h
@@ -96,6 +96,7 @@ struct BlockDriverState {
     int removable; /* if true, the media can be removed */
     int locked;    /* if true, the media cannot temporarily be ejected */
     int encrypted; /* if true, the media is encrypted */
+    int valid_key; /* if true, a valid encryption key has been set */
     int sg;        /* if true, the device is a /dev/sg* */
     /* event callback when inserting/removing */
     void (*change_cb)(void *opaque);
diff --git a/console.h b/console.h
index 4a2f06f..1402067 100644
--- a/console.h
+++ b/console.h
@@ -305,10 +305,9 @@ void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1
 void term_print_filename(const char *filename);
 void term_flush(void);
 void term_print_help(void);
-void monitor_readline(const char *prompt, int is_password,
-                      char *buf, int buf_size);
 void monitor_suspend(void);
 void monitor_resume(void);
+int monitor_read_bdrv_key(BlockDriverState *bs);
 
 /* readline.c */
 typedef void ReadLineFunc(void *opaque, const char *str);
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 342b0e8..0c8d9cc 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -11,6 +11,7 @@
 #include "usb.h"
 #include "block.h"
 #include "scsi-disk.h"
+#include "console.h"
 
 //#define DEBUG_MSD
 
@@ -513,7 +514,7 @@ static void usb_msd_handle_destroy(USBDevice *dev)
     qemu_free(s);
 }
 
-USBDevice *usb_msd_init(const char *filename)
+USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)
 {
     MSDState *s;
     BlockDriverState *bdrv;
@@ -552,9 +553,8 @@ USBDevice *usb_msd_init(const char *filename)
     bdrv = bdrv_new("usb");
     if (bdrv_open2(bdrv, filename, 0, drv) < 0)
         goto fail;
-    if (qemu_key_check(bdrv, filename))
-        goto fail;
     s->bs = bdrv;
+    *pbs = bdrv;
 
     s->dev.speed = USB_SPEED_FULL;
     s->dev.handle_packet = usb_generic_handle_packet;
diff --git a/hw/usb.h b/hw/usb.h
index 4204808..4cd832d 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -21,6 +21,9 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
+#include "block.h"
+
 #define USB_TOKEN_SETUP 0x2d
 #define USB_TOKEN_IN    0x69 /* device -> host */
 #define USB_TOKEN_OUT   0xe1 /* host -> device */
@@ -250,7 +253,7 @@ 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);
+USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs);
 
 /* usb-net.c */
 USBDevice *usb_net_init(NICInfo *nd);
diff --git a/monitor.c b/monitor.c
index 90dbdca..ae3af5e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -76,6 +76,8 @@ static uint8_t term_outbuf[1024];
 static int term_outbuf_index;
 
 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;
 
@@ -433,7 +435,7 @@ 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);
-    qemu_key_check(bs, filename);
+    monitor_read_bdrv_key(bs);
 }
 
 static void do_change_vnc(const char *target, const char *arg)
@@ -494,9 +496,24 @@ 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 do_cont(void)
 {
-    vm_start();
+    int err = 0;
+
+    bdrv_iterate(encrypted_bdrv_it, &err);
+    /* only resume the vm if all keys are set and valid */
+    if (!err)
+        vm_start();
 }
 
 #ifdef CONFIG_GDBSTUB
@@ -2861,8 +2878,8 @@ static void monitor_readline_cb(void *opaque, const char *input)
     monitor_readline_started = 0;
 }
 
-void monitor_readline(const char *prompt, int is_password,
-                      char *buf, int buf_size)
+static void monitor_readline(const char *prompt, int is_password,
+                             char *buf, int buf_size)
 {
     int i;
     int old_focus[MAX_MON];
@@ -2892,3 +2909,22 @@ void monitor_readline(const char *prompt, int is_password,
                 monitor_hd[i]->focus = old_focus[i];
     }
 }
+
+int monitor_read_bdrv_key(BlockDriverState *bs)
+{
+    char password[256];
+    int i;
+
+    if (!bdrv_is_encrypted(bs))
+        return 0;
+
+    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;
+}
diff --git a/vl.c b/vl.c
index 1c5878b..a195b80 100644
--- a/vl.c
+++ b/vl.c
@@ -200,6 +200,7 @@ ram_addr_t ram_size;
 int nb_nics;
 NICInfo nd_table[MAX_NICS];
 int vm_running;
+static int autostart;
 static int rtc_utc = 1;
 static int rtc_date_offset = -1; /* -1 means no change */
 int cirrus_vga_enabled = 1;
@@ -2606,11 +2607,13 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
         bdrv_flags |= BDRV_O_CACHE_WB;
     else if (cache == 3) /* not specified */
         bdrv_flags |= BDRV_O_CACHE_DEF;
-    if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0 || qemu_key_check(bdrv, file)) {
+    if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0) {
         fprintf(stderr, "qemu: could not open disk image %s\n",
                         file);
         return -1;
     }
+    if (bdrv_key_required(bdrv))
+        autostart = 0;
     return drives_table_idx;
 }
 
@@ -2657,7 +2660,7 @@ int usb_device_add_dev(USBDevice *dev)
     return 0;
 }
 
-static int usb_device_add(const char *devname)
+static int usb_device_add(const char *devname, int is_hotplug)
 {
     const char *p;
     USBDevice *dev;
@@ -2674,7 +2677,18 @@ static int usb_device_add(const char *devname)
     } else if (!strcmp(devname, "keyboard")) {
         dev = usb_keyboard_init();
     } else if (strstart(devname, "disk:", &p)) {
-        dev = usb_msd_init(p);
+        BlockDriverState *bs;
+
+        dev = usb_msd_init(p, &bs);
+        if (!dev)
+            return -1;
+        if (bdrv_key_required(bs)) {
+            autostart = 0;
+            if (is_hotplug && monitor_read_bdrv_key(bs) < 0) {
+                dev->handle_destroy(dev);
+                return -1;
+            }
+        }
     } else if (!strcmp(devname, "wacom-tablet")) {
         dev = usb_wacom_init();
     } else if (strstart(devname, "serial:", &p)) {
@@ -2755,7 +2769,7 @@ static int usb_device_del(const char *devname)
 
 void do_usb_add(const char *devname)
 {
-    usb_device_add(devname);
+    usb_device_add(devname, 1);
 }
 
 void do_usb_del(const char *devname)
@@ -4321,45 +4335,6 @@ static const QEMUOption qemu_options[] = {
     { NULL },
 };
 
-/* password input */
-
-int qemu_key_check(BlockDriverState *bs, const char *name)
-{
-    char password[256];
-    int i;
-
-    if (!bdrv_is_encrypted(bs))
-        return 0;
-
-    term_printf("%s is encrypted.\n", name);
-    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;
-}
-
-static BlockDriverState *get_bdrv(int index)
-{
-    if (index > nb_drives)
-        return NULL;
-    return drives_table[index].bdrv;
-}
-
-static void read_passwords(void)
-{
-    BlockDriverState *bs;
-    int i;
-
-    for(i = 0; i < 6; i++) {
-        bs = get_bdrv(i);
-        if (bs)
-            qemu_key_check(bs, bdrv_get_device_name(bs));
-    }
-}
-
 #ifdef HAS_AUDIO
 struct soundhw soundhw[] = {
 #ifdef HAS_AUDIO_CHOICE
@@ -4626,7 +4601,6 @@ int main(int argc, char **argv, char **envp)
     int fds[2];
     int tb_size;
     const char *pid_file = NULL;
-    int autostart;
     const char *incoming = NULL;
 
     qemu_cache_utils_init(envp);
@@ -5611,7 +5585,7 @@ int main(int argc, char **argv, char **envp)
     /* init USB devices */
     if (usb_enabled) {
         for(i = 0; i < usb_devices_index; i++) {
-            if (usb_device_add(usb_devices[i]) < 0) {
+            if (usb_device_add(usb_devices[i], 0) < 0) {
                 fprintf(stderr, "Warning: could not add USB device %s\n",
                         usb_devices[i]);
             }
@@ -5722,13 +5696,8 @@ int main(int argc, char **argv, char **envp)
         qemu_start_incoming_migration(incoming);
     }
 
-    {
-        /* XXX: simplify init */
-        read_passwords();
-        if (autostart) {
-            vm_start();
-        }
-    }
+    if (autostart)
+        vm_start();
 
     if (daemonize) {
 	uint8_t status = 0;

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 03/19] block: Polish error handling of brdv_open2
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (7 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 06/19] monitor: Use reasonable default virtual console size Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 09/19] monitor: Simplify password input mode Jan Kiszka
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

Make sure that we always delete temporary disk images on error, remove
obsolete malloc error checks and return proper error codes.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 block.c |   46 +++++++++++++++++++++-------------------------
 1 files changed, 21 insertions(+), 25 deletions(-)

diff --git a/block.c b/block.c
index 4f4bf7c..330317a 100644
--- a/block.c
+++ b/block.c
@@ -311,8 +311,6 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
     int ret;
 
     bs = bdrv_new("");
-    if (!bs)
-        return -ENOMEM;
     ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
     if (ret < 0) {
         bdrv_delete(bs);
@@ -348,12 +346,10 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
 
         /* if there is a backing file, use it */
         bs1 = bdrv_new("");
-        if (!bs1) {
-            return -ENOMEM;
-        }
-        if (bdrv_open(bs1, filename, 0) < 0) {
+        ret = bdrv_open(bs1, filename, 0);
+        if (ret < 0) {
             bdrv_delete(bs1);
-            return -1;
+            return ret;
         }
         total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
 
@@ -371,9 +367,10 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
         else
             realpath(filename, backing_filename);
 
-        if (bdrv_create(&bdrv_qcow2, tmp_filename,
-                        total_size, backing_filename, 0) < 0) {
-            return -1;
+        ret = bdrv_create(&bdrv_qcow2, tmp_filename,
+                          total_size, backing_filename, 0);
+        if (ret < 0) {
+            return ret;
         }
         filename = tmp_filename;
         bs->is_temporary = 1;
@@ -382,14 +379,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
     pstrcpy(bs->filename, sizeof(bs->filename), filename);
     if (flags & BDRV_O_FILE) {
         drv = find_protocol(filename);
-        if (!drv)
-            return -ENOENT;
-    } else {
-        if (!drv) {
-            drv = find_image_format(filename);
-            if (!drv)
-                return -1;
-        }
+    } else if (!drv) {
+        drv = find_image_format(filename);
+    }
+    if (!drv) {
+        ret = -ENOENT;
+        goto unlink_and_fail;
     }
     bs->drv = drv;
     bs->opaque = qemu_mallocz(drv->instance_size);
@@ -408,6 +403,9 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
         qemu_free(bs->opaque);
         bs->opaque = NULL;
         bs->drv = NULL;
+    unlink_and_fail:
+        if (bs->is_temporary)
+            unlink(filename);
         return ret;
     }
     if (drv->bdrv_getlength) {
@@ -421,15 +419,13 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
     if (bs->backing_file[0] != '\0') {
         /* if there is a backing file, use it */
         bs->backing_hd = bdrv_new("");
-        if (!bs->backing_hd) {
-        fail:
-            bdrv_close(bs);
-            return -ENOMEM;
-        }
         path_combine(backing_filename, sizeof(backing_filename),
                      filename, bs->backing_file);
-        if (bdrv_open(bs->backing_hd, backing_filename, open_flags) < 0)
-            goto fail;
+        ret = bdrv_open(bs->backing_hd, backing_filename, open_flags);
+        if (ret < 0) {
+            bdrv_close(bs);
+            return ret;
+        }
     }
 
     /* call the change callback */

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 07/19] monitor: Report encrypted disks in snapshot mode
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (4 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 02/19] char-mux: Use separate input buffers Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 10/19] monitor: Break out readline_show_prompt Jan Kiszka
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

If the backing file is encrypted, 'info block' currently does not report
the disk as encrypted. Fix this by using the standard API to check disk
encryption mode. Moreover, switch to a canonical output format.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 block.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/block.c b/block.c
index 78982f4..fe58b89 100644
--- a/block.c
+++ b/block.c
@@ -1056,8 +1056,7 @@ void bdrv_info(void)
 	    }
             term_printf(" ro=%d", bs->read_only);
             term_printf(" drv=%s", bs->drv->format_name);
-            if (bs->encrypted)
-                term_printf(" encrypted");
+            term_printf(" encrypted=%d", bdrv_is_encrypted(bs));
         } else {
             term_printf(" [not inserted]");
         }

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 11/19] monitor: Rework modal password input
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (9 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 09/19] monitor: Simplify password input mode Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 12/19] monitor: Rework API Jan Kiszka
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

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>
---

 block.c      |   21 ++++++++---
 console.h    |    6 +++
 hw/usb-msd.c |   10 ++++-
 hw/usb.h     |    3 +-
 monitor.c    |  114 ++++++++++++++++++++++++++++++++--------------------------
 vl.c         |   19 ++++++++--
 6 files changed, 108 insertions(+), 65 deletions(-)

diff --git a/block.c b/block.c
index 52d1448..1ec77c2 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/console.h b/console.h
index dc80755..782f6dd 100644
--- a/console.h
+++ b/console.h
@@ -307,7 +307,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 0c8d9cc..41c92c3 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 de5205e..2dd1c19 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)
 {
@@ -2804,7 +2826,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;
 }
@@ -2867,46 +2889,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);
 }
diff --git a/vl.c b/vl.c
index a195b80..89883c3 100644
--- a/vl.c
+++ b/vl.c
@@ -2660,6 +2660,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;
@@ -2679,14 +2689,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")) {

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 10/19] monitor: Break out readline_show_prompt
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (5 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 07/19] monitor: Report encrypted disks in snapshot mode Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 06/19] monitor: Use reasonable default virtual console size Jan Kiszka
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

Break readline_show_prompt out of readline_start so that (re-)printing
the prompt can be controlled in a more fine-grained way.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 console.h  |    1 +
 monitor.c  |    2 ++
 readline.c |   14 ++++----------
 3 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/console.h b/console.h
index 1402067..dc80755 100644
--- a/console.h
+++ b/console.h
@@ -319,5 +319,6 @@ void readline_find_completion(const char *cmdline);
 const char *readline_get_history(unsigned int index);
 void readline_start(const char *prompt, int is_password,
                     ReadLineFunc *readline_func, void *opaque);
+void readline_show_prompt(void);
 
 #endif
diff --git a/monitor.c b/monitor.c
index c5234ba..de5205e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2824,6 +2824,7 @@ void monitor_resume(void)
 static void monitor_start_input(void)
 {
     readline_start("(qemu) ", 0, monitor_handle_command1, NULL);
+    readline_show_prompt();
 }
 
 static void term_event(void *opaque, int event)
@@ -2882,6 +2883,7 @@ 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;
diff --git a/readline.c b/readline.c
index 8572841..5a089be 100644
--- a/readline.c
+++ b/readline.c
@@ -57,7 +57,7 @@ static int term_is_password;
 static char term_prompt[256];
 static void *term_readline_opaque;
 
-static void term_show_prompt2(void)
+void readline_show_prompt(void)
 {
     term_printf("%s", term_prompt);
     term_flush();
@@ -66,13 +66,6 @@ static void term_show_prompt2(void)
     term_esc_state = IS_NORM;
 }
 
-static void term_show_prompt(void)
-{
-    term_show_prompt2();
-    term_cmd_buf_index = 0;
-    term_cmd_buf_size = 0;
-}
-
 /* update the displayed command line */
 static void term_update(void)
 {
@@ -360,7 +353,7 @@ static void term_completion(void)
                 j = 0;
             }
         }
-        term_show_prompt2();
+        readline_show_prompt();
     }
 }
 
@@ -473,7 +466,8 @@ void readline_start(const char *prompt, int is_password,
     term_readline_func = readline_func;
     term_readline_opaque = opaque;
     term_is_password = is_password;
-    term_show_prompt();
+    term_cmd_buf_index = 0;
+    term_cmd_buf_size = 0;
 }
 
 const char *readline_get_history(unsigned int index)

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 14/19] monitor: Drop banner hiding
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (14 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 15/19] monitor: Introduce ReadLineState Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 18/19] monitor: Introduce MONITOR_USE_READLINE flag Jan Kiszka
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

There is no use for the hide/show banner option, and it is applied
inconsistently anyway (or what makes the difference between
-serial mon:stdio and -nographic for the monitor?). So drop this mode.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 monitor.c   |   10 +++-------
 monitor.h   |    2 +-
 qemu-char.c |    2 +-
 vl.c        |    2 +-
 4 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/monitor.c b/monitor.c
index dad9c66..3115a67 100644
--- a/monitor.c
+++ b/monitor.c
@@ -73,7 +73,6 @@ struct Monitor {
 };
 
 static LIST_HEAD(mon_list, Monitor) mon_list;
-static int hide_banner;
 
 static const mon_cmd_t mon_cmds[];
 static const mon_cmd_t info_cmds[];
@@ -2886,15 +2885,14 @@ static void term_event(void *opaque, int event)
     if (event != CHR_EVENT_RESET)
 	return;
 
-    if (!hide_banner)
-        monitor_printf(mon, "QEMU %s monitor - type 'help' for more "
-                       "information\n", QEMU_VERSION);
+    monitor_printf(mon, "QEMU %s monitor - type 'help' for more information\n",
+                   QEMU_VERSION);
     monitor_start_input();
 }
 
 static int is_first_init = 1;
 
-void monitor_init(CharDriverState *chr, int show_banner)
+void monitor_init(CharDriverState *chr)
 {
     Monitor *mon;
 
@@ -2905,8 +2903,6 @@ void monitor_init(CharDriverState *chr, int show_banner)
 
     mon = qemu_mallocz(sizeof(*mon));
 
-    hide_banner = !show_banner;
-
     mon->chr = chr;
 
     qemu_chr_add_handlers(chr, term_can_read, term_read, term_event, mon);
diff --git a/monitor.h b/monitor.h
index d06e2d8..abe7193 100644
--- a/monitor.h
+++ b/monitor.h
@@ -7,7 +7,7 @@
 
 extern Monitor *cur_mon;
 
-void monitor_init(CharDriverState *chr, int show_banner);
+void monitor_init(CharDriverState *chr);
 
 void monitor_suspend(Monitor *mon);
 void monitor_resume(Monitor *mon);
diff --git a/qemu-char.c b/qemu-char.c
index d4ff367..bb50337 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2123,7 +2123,7 @@ CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*i
         chr = qemu_chr_open(label, p, NULL);
         if (chr) {
             chr = qemu_chr_open_mux(chr);
-            monitor_init(chr, !nographic);
+            monitor_init(chr);
         } else {
             printf("Unable to open driver: %s\n", p);
         }
diff --git a/vl.c b/vl.c
index 1de2f00..bbf96e0 100644
--- a/vl.c
+++ b/vl.c
@@ -5658,7 +5658,7 @@ int main(int argc, char **argv, char **envp)
     qemu_chr_initial_reset();
 
     if (monitor_device && monitor_hd)
-        monitor_init(monitor_hd, !nographic);
+        monitor_init(monitor_hd);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         const char *devname = serial_devices[i];

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 19/19] monitor: Pass-through for gdbstub
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (17 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 16/19] monitor: Decouple terminals Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-27 17:43 ` [Qemu-devel] [PATCH v2 00/19] monitor rework Anthony Liguori
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

Create a monitor terminal and pass it through the gdbstub. This allows
to use gdb's monitor command to access the QEMU monitor. Works for all
commands except for non-detached migration and password retrieval (user
will receive error messages instead).

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 gdbstub.c |   54 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 53 insertions(+), 1 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 239f2e0..27e887e 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -30,6 +30,7 @@
 
 #include "qemu.h"
 #else
+#include "monitor.h"
 #include "qemu-char.h"
 #include "sysemu.h"
 #include "gdbstub.h"
@@ -285,6 +286,7 @@ typedef struct GDBState {
     int running_state;
 #else
     CharDriverState *chr;
+    CharDriverState *mon_chr;
 #endif
 } GDBState;
 
@@ -1819,7 +1821,22 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
             put_packet(s, buf);
             break;
         }
-#endif
+#else /* !CONFIG_LINUX_USER */
+        else if (strncmp(p, "Rcmd,", 5) == 0) {
+            int len = strlen(p + 5);
+
+            if ((len % 2) != 0) {
+                put_packet(s, "E01");
+                break;
+            }
+            hextomem(mem_buf, p + 5, len);
+            len = len / 2;
+            mem_buf[len++] = 0;
+            qemu_chr_read(s->mon_chr, mem_buf, len);
+            put_packet(s, "OK");
+            break;
+        }
+#endif /* !CONFIG_LINUX_USER */
         if (strncmp(p, "Supported", 9) == 0) {
             snprintf(buf, sizeof(buf), "PacketSize=%x", MAX_PACKET_LENGTH);
 #ifdef GDB_CORE_XML
@@ -2282,6 +2299,35 @@ static void gdb_chr_event(void *opaque, int event)
     }
 }
 
+static void gdb_monitor_output(GDBState *s, const char *msg, int len)
+{
+    char buf[MAX_PACKET_LENGTH];
+
+    buf[0] = 'O';
+    if (len > (MAX_PACKET_LENGTH/2) - 1)
+        len = (MAX_PACKET_LENGTH/2) - 1;
+    memtohex(buf + 1, (uint8_t *)msg, len);
+    put_packet(s, buf);
+}
+
+static int gdb_monitor_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+    const char *p = (const char *)buf;
+    int max_sz;
+
+    max_sz = (sizeof(gdbserver_state->last_packet) - 2) / 2;
+    for (;;) {
+        if (len <= max_sz) {
+            gdb_monitor_output(gdbserver_state, p, len);
+            break;
+        }
+        gdb_monitor_output(gdbserver_state, p, max_sz);
+        p += max_sz;
+        len -= max_sz;
+    }
+    return len;
+}
+
 int gdbserver_start(const char *port)
 {
     GDBState *s;
@@ -2313,6 +2359,12 @@ int gdbserver_start(const char *port)
     qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
                           gdb_chr_event, NULL);
     qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL);
+
+    /* Initialize a monitor terminal for gdb */
+    s->mon_chr = qemu_mallocz(sizeof(*s->mon_chr));
+    s->mon_chr->chr_write = gdb_monitor_write;
+    monitor_init(s->mon_chr, 0);
+
     return 0;
 }
 #endif

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 13/19] monitor: Rework terminal management
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (11 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 12/19] monitor: Rework API Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 17/19] monitor: Improve mux'ed console experience Jan Kiszka
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

Remove the static MAX_MON limit by managing monitor terminals in a
linked list.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 monitor.c |   43 +++++++++++++++++++++++--------------------
 1 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/monitor.c b/monitor.c
index 2936222..dad9c66 100644
--- a/monitor.c
+++ b/monitor.c
@@ -67,8 +67,12 @@ typedef struct mon_cmd_t {
     const char *help;
 } mon_cmd_t;
 
-#define MAX_MON 4
-static CharDriverState *monitor_hd[MAX_MON];
+struct Monitor {
+    CharDriverState *chr;
+    LIST_ENTRY(Monitor) entry;
+};
+
+static LIST_HEAD(mon_list, Monitor) mon_list;
 static int hide_banner;
 
 static const mon_cmd_t mon_cmds[];
@@ -79,7 +83,7 @@ static int term_outbuf_index;
 static BlockDriverCompletionFunc *password_completion_cb;
 static void *password_opaque;
 
-Monitor *cur_mon;
+Monitor *cur_mon = NULL;
 
 static void monitor_start_input(void);
 
@@ -93,11 +97,13 @@ static void monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
 
 void monitor_flush(Monitor *mon)
 {
-    int i;
+    Monitor *m;
+
     if (term_outbuf_index > 0) {
-        for (i = 0; i < MAX_MON; i++)
-            if (monitor_hd[i] && monitor_hd[i]->focus == 0)
-                qemu_chr_write(monitor_hd[i], term_outbuf, term_outbuf_index);
+        LIST_FOREACH(m, &mon_list, entry) {
+            if (m->chr->focus == 0)
+                qemu_chr_write(m->chr, term_outbuf, term_outbuf_index);
+        }
         term_outbuf_index = 0;
     }
 }
@@ -2890,27 +2896,24 @@ static int is_first_init = 1;
 
 void monitor_init(CharDriverState *chr, int show_banner)
 {
-    int i;
+    Monitor *mon;
 
     if (is_first_init) {
         key_timer = qemu_new_timer(vm_clock, release_keys, NULL);
-        if (!key_timer)
-            return;
-        for (i = 0; i < MAX_MON; i++) {
-            monitor_hd[i] = NULL;
-        }
         is_first_init = 0;
     }
-    for (i = 0; i < MAX_MON; i++) {
-        if (monitor_hd[i] == NULL) {
-            monitor_hd[i] = chr;
-            break;
-        }
-    }
+
+    mon = qemu_mallocz(sizeof(*mon));
 
     hide_banner = !show_banner;
 
-    qemu_chr_add_handlers(chr, term_can_read, term_read, term_event, cur_mon);
+    mon->chr = chr;
+
+    qemu_chr_add_handlers(chr, term_can_read, term_read, term_event, mon);
+
+    LIST_INSERT_HEAD(&mon_list, mon, entry);
+    if (!cur_mon)
+        cur_mon = mon;
 
     readline_start("", 0, monitor_command_cb, NULL);
 }

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 16/19] monitor: Decouple terminals
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (16 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 18/19] monitor: Introduce MONITOR_USE_READLINE flag Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 19/19] monitor: Pass-through for gdbstub Jan Kiszka
  2009-02-27 17:43 ` [Qemu-devel] [PATCH v2 00/19] monitor rework Anthony Liguori
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

Currently all registered (and activate) monitor terminals work in
broadcast mode: Everyone sees what someone else types on some other
terminal and what the monitor reports back. This model is broken when
you have a management monitor terminal that is automatically operated
and some other terminal used for independent guest inspection. Such
additional terminals can be multiplexed device channels or a gdb
frontend connected to QEMU's stub.

Therefore, this patch decouples the buffers and states of all monitor
terminals, allowing the user to operate them independently. It finally
starts to use the 'mon' parameter that was introduced earlier with the
API rework. It also defines the default monitor: the first instantance
that has the MONITOR_IS_DEFAULT flag set, and that is the monitor
created via the "-monitor" command line switch (or "vc" if none is
given).

As the patch requires to rework the monitor suspension interface, it
also takes the freedom to make it "truely" suspending (so far suspending
meant suppressing the prompt, but inputs were still processed).

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 migration-exec.c |   12 +---
 migration-tcp.c  |   12 +---
 migration.c      |   13 +++--
 migration.h      |    4 +
 monitor.c        |  146 ++++++++++++++++++++++++++++--------------------------
 monitor.h        |    5 +-
 qemu-char.c      |    2 -
 vl.c             |    2 -
 8 files changed, 101 insertions(+), 95 deletions(-)

diff --git a/migration-exec.c b/migration-exec.c
index e2e6e89..f0869a1 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -18,7 +18,6 @@
 #include "migration.h"
 #include "qemu-char.h"
 #include "sysemu.h"
-#include "monitor.h"
 #include "buffered_file.h"
 #include "block.h"
 
@@ -55,7 +54,7 @@ static int exec_close(FdMigrationState *s)
 
 MigrationState *exec_start_outgoing_migration(const char *command,
                                              int64_t bandwidth_limit,
-                                             int async)
+                                             int detach)
 {
     FdMigrationState *s;
     FILE *f;
@@ -89,14 +88,11 @@ MigrationState *exec_start_outgoing_migration(const char *command,
     s->mig_state.release = migrate_fd_release;
 
     s->state = MIG_STATE_ACTIVE;
-    s->detach = !async;
+    s->mon_resume = NULL;
     s->bandwidth_limit = bandwidth_limit;
 
-    if (s->detach == 1) {
-        dprintf("detaching from monitor\n");
-        monitor_suspend(cur_mon);
-        s->detach = 2;
-    }
+    if (!detach)
+        migrate_fd_monitor_suspend(s);
 
     migrate_fd_connect(s);
     return &s->mig_state;
diff --git a/migration-tcp.c b/migration-tcp.c
index 7f67fd9..d9c4c98 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -16,7 +16,6 @@
 #include "migration.h"
 #include "qemu-char.h"
 #include "sysemu.h"
-#include "monitor.h"
 #include "buffered_file.h"
 #include "block.h"
 
@@ -79,7 +78,7 @@ static void tcp_wait_for_connect(void *opaque)
 
 MigrationState *tcp_start_outgoing_migration(const char *host_port,
                                              int64_t bandwidth_limit,
-                                             int async)
+                                             int detach)
 {
     struct sockaddr_in addr;
     FdMigrationState *s;
@@ -98,7 +97,7 @@ MigrationState *tcp_start_outgoing_migration(const char *host_port,
     s->mig_state.release = migrate_fd_release;
 
     s->state = MIG_STATE_ACTIVE;
-    s->detach = !async;
+    s->mon_resume = NULL;
     s->bandwidth_limit = bandwidth_limit;
     s->fd = socket(PF_INET, SOCK_STREAM, 0);
     if (s->fd == -1) {
@@ -108,11 +107,8 @@ MigrationState *tcp_start_outgoing_migration(const char *host_port,
 
     socket_set_nonblock(s->fd);
 
-    if (s->detach == 1) {
-        dprintf("detaching from monitor\n");
-        monitor_suspend(cur_mon);
-        s->detach = 2;
-    }
+    if (!detach)
+        migrate_fd_monitor_suspend(s);
 
     do {
         ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
diff --git a/migration.c b/migration.c
index cf69bbe..15639c1 100644
--- a/migration.c
+++ b/migration.c
@@ -125,6 +125,13 @@ void do_info_migrate(Monitor *mon)
 
 /* shared migration helpers */
 
+void migrate_fd_monitor_suspend(FdMigrationState *s)
+{
+    s->mon_resume = cur_mon;
+    monitor_suspend(cur_mon);
+    dprintf("suspending monitor\n");
+}
+
 void migrate_fd_error(FdMigrationState *s)
 {
     dprintf("setting error state\n");
@@ -145,10 +152,8 @@ void migrate_fd_cleanup(FdMigrationState *s)
         close(s->fd);
 
     /* Don't resume monitor until we've flushed all of the buffers */
-    if (s->detach == 2) {
-        monitor_resume(cur_mon);
-        s->detach = 0;
-    }
+    if (s->mon_resume)
+        monitor_resume(s->mon_resume);
 
     s->fd = -1;
 }
diff --git a/migration.h b/migration.h
index 32f5a72..696618d 100644
--- a/migration.h
+++ b/migration.h
@@ -39,7 +39,7 @@ struct FdMigrationState
     int64_t bandwidth_limit;
     QEMUFile *file;
     int fd;
-    int detach;
+    Monitor *mon_resume;
     int state;
     int (*get_error)(struct FdMigrationState*);
     int (*close)(struct FdMigrationState*);
@@ -69,6 +69,8 @@ MigrationState *tcp_start_outgoing_migration(const char *host_port,
 					     int64_t bandwidth_limit,
 					     int detach);
 
+void migrate_fd_monitor_suspend(FdMigrationState *s);
+
 void migrate_fd_error(FdMigrationState *s);
 
 void migrate_fd_cleanup(FdMigrationState *s);
diff --git a/monitor.c b/monitor.c
index 6940031..ba0e9a8 100644
--- a/monitor.c
+++ b/monitor.c
@@ -69,6 +69,14 @@ typedef struct mon_cmd_t {
 
 struct Monitor {
     CharDriverState *chr;
+    int flags;
+    int suspend_cnt;
+    uint8_t outbuf[1024];
+    int outbuf_index;
+    ReadLineState *rs;
+    CPUState *mon_cpu;
+    BlockDriverCompletionFunc *password_completion_cb;
+    void *password_opaque;
     LIST_ENTRY(Monitor) entry;
 };
 
@@ -77,34 +85,30 @@ static LIST_HEAD(mon_list, Monitor) mon_list;
 static const mon_cmd_t mon_cmds[];
 static const mon_cmd_t info_cmds[];
 
-static uint8_t term_outbuf[1024];
-static int term_outbuf_index;
-static BlockDriverCompletionFunc *password_completion_cb;
-static void *password_opaque;
-ReadLineState *rs;
-
 Monitor *cur_mon = NULL;
 
-static void monitor_start_input(void);
+static void monitor_command_cb(Monitor *mon, const char *cmdline,
+                               void *opaque);
 
-static CPUState *mon_cpu = NULL;
+static void monitor_read_command(Monitor *mon, int show_prompt)
+{
+    readline_start(mon->rs, "(qemu) ", 0, monitor_command_cb, NULL);
+    if (show_prompt)
+        readline_show_prompt(mon->rs);
+}
 
 static void monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
                                   void *opaque)
 {
-    readline_start(rs, "Password: ", 1, readline_func, opaque);
+    readline_start(mon->rs, "Password: ", 1, readline_func, opaque);
+    /* prompt is printed on return from the command handler */
 }
 
 void monitor_flush(Monitor *mon)
 {
-    Monitor *m;
-
-    if (term_outbuf_index > 0) {
-        LIST_FOREACH(m, &mon_list, entry) {
-            if (m->chr->focus == 0)
-                qemu_chr_write(m->chr, term_outbuf, term_outbuf_index);
-        }
-        term_outbuf_index = 0;
+    if (mon && mon->outbuf_index != 0 && mon->chr->focus == 0) {
+        qemu_chr_write(mon->chr, mon->outbuf, mon->outbuf_index);
+        mon->outbuf_index = 0;
     }
 }
 
@@ -112,15 +116,19 @@ void monitor_flush(Monitor *mon)
 static void monitor_puts(Monitor *mon, const char *str)
 {
     char c;
+
+    if (!mon)
+        return;
+
     for(;;) {
         c = *str++;
         if (c == '\0')
             break;
         if (c == '\n')
-            term_outbuf[term_outbuf_index++] = '\r';
-        term_outbuf[term_outbuf_index++] = c;
-        if (term_outbuf_index >= (sizeof(term_outbuf) - 1) ||
-            c == '\n')
+            mon->outbuf[mon->outbuf_index++] = '\r';
+        mon->outbuf[mon->outbuf_index++] = c;
+        if (mon->outbuf_index >= (sizeof(mon->outbuf) - 1)
+            || c == '\n')
             monitor_flush(mon);
     }
 }
@@ -291,7 +299,7 @@ static int mon_set_cpu(int cpu_index)
 
     for(env = first_cpu; env != NULL; env = env->next_cpu) {
         if (env->cpu_index == cpu_index) {
-            mon_cpu = env;
+            cur_mon->mon_cpu = env;
             return 0;
         }
     }
@@ -300,10 +308,10 @@ static int mon_set_cpu(int cpu_index)
 
 static CPUState *mon_get_cpu(void)
 {
-    if (!mon_cpu) {
+    if (!cur_mon->mon_cpu) {
         mon_set_cpu(0);
     }
-    return mon_cpu;
+    return cur_mon->mon_cpu;
 }
 
 static void do_info_registers(Monitor *mon)
@@ -330,7 +338,7 @@ static void do_info_cpus(Monitor *mon)
 
     for(env = first_cpu; env != NULL; env = env->next_cpu) {
         monitor_printf(mon, "%c CPU #%d:",
-                       (env == mon_cpu) ? '*' : ' ',
+                       (env == mon->mon_cpu) ? '*' : ' ',
                        env->cpu_index);
 #if defined(TARGET_I386)
         monitor_printf(mon, " pc=0x" TARGET_FMT_lx,
@@ -367,7 +375,7 @@ static void do_info_history(Monitor *mon)
 
     i = 0;
     for(;;) {
-        str = readline_get_history(rs, i);
+        str = readline_get_history(mon->rs, i);
         if (!str)
             break;
         monitor_printf(mon, "%d: '%s'\n", i, str);
@@ -451,7 +459,7 @@ static void change_vnc_password_cb(Monitor *mon, const char *password,
     if (vnc_display_password(NULL, password) < 0)
         monitor_printf(mon, "could not set VNC server password\n");
 
-    monitor_start_input();
+    monitor_read_command(mon, 1);
 }
 
 static void do_change_vnc(Monitor *mon, const char *target, const char *arg)
@@ -2657,7 +2665,7 @@ static void cmd_completion(const char *name, const char *list)
         memcpy(cmd, pstart, len);
         cmd[len] = '\0';
         if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
-            readline_add_completion(rs, cmd);
+            readline_add_completion(cur_mon->rs, cmd);
         }
         if (*p == '\0')
             break;
@@ -2710,7 +2718,7 @@ static void file_completion(const char *input)
             stat(file, &sb);
             if(S_ISDIR(sb.st_mode))
                 pstrcat(file, sizeof(file), "/");
-            readline_add_completion(rs, file);
+            readline_add_completion(cur_mon->rs, file);
         }
     }
     closedir(ffs);
@@ -2723,7 +2731,7 @@ static void block_completion_it(void *opaque, BlockDriverState *bs)
 
     if (input[0] == '\0' ||
         !strncmp(name, (char *)input, strlen(input))) {
-        readline_add_completion(rs, name);
+        readline_add_completion(cur_mon->rs, name);
     }
 }
 
@@ -2783,7 +2791,7 @@ static void monitor_find_completion(const char *cmdline)
             cmdname = "";
         else
             cmdname = args[0];
-        readline_set_completion_index(rs, strlen(cmdname));
+        readline_set_completion_index(cur_mon->rs, strlen(cmdname));
         for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
             cmd_completion(cmdname, cmd->name);
         }
@@ -2807,23 +2815,23 @@ static void monitor_find_completion(const char *cmdline)
         switch(*ptype) {
         case 'F':
             /* file completion */
-            readline_set_completion_index(rs, strlen(str));
+            readline_set_completion_index(cur_mon->rs, strlen(str));
             file_completion(str);
             break;
         case 'B':
             /* block device name completion */
-            readline_set_completion_index(rs, strlen(str));
+            readline_set_completion_index(cur_mon->rs, strlen(str));
             bdrv_iterate(block_completion_it, (void *)str);
             break;
         case 's':
             /* XXX: more generic ? */
             if (!strcmp(cmd->name, "info")) {
-                readline_set_completion_index(rs, strlen(str));
+                readline_set_completion_index(cur_mon->rs, strlen(str));
                 for(cmd = info_cmds; cmd->name != NULL; cmd++) {
                     cmd_completion(str, cmd->name);
                 }
             } else if (!strcmp(cmd->name, "sendkey")) {
-                readline_set_completion_index(rs, strlen(str));
+                readline_set_completion_index(cur_mon->rs, strlen(str));
                 for(key = key_defs; key->name != NULL; key++) {
                     cmd_completion(str, key->name);
                 }
@@ -2837,49 +2845,45 @@ static void monitor_find_completion(const char *cmdline)
         qemu_free(args[i]);
 }
 
-static int term_can_read(void *opaque)
+static int monitor_can_read(void *opaque)
 {
-    return 128;
+    Monitor *mon = opaque;
+
+    return (mon->suspend_cnt == 0) ? 128 : 0;
 }
 
-static void term_read(void *opaque, const uint8_t *buf, int size)
+static void monitor_read(void *opaque, const uint8_t *buf, int size)
 {
+    Monitor *old_mon = cur_mon;
     int i;
 
-    for(i = 0; i < size; i++)
-        readline_handle_byte(rs, buf[i]);
-}
+    cur_mon = opaque;
+
+    for (i = 0; i < size; i++)
+        readline_handle_byte(cur_mon->rs, buf[i]);
 
-static int monitor_suspended;
+    cur_mon = old_mon;
+}
 
 static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque)
 {
+    monitor_suspend(mon);
     monitor_handle_command(mon, cmdline);
-    if (!monitor_suspended)
-        readline_show_prompt(rs);
-    else
-        monitor_suspended = 2;
+    monitor_resume(mon);
 }
 
 void monitor_suspend(Monitor *mon)
 {
-    monitor_suspended = 1;
+    mon->suspend_cnt++;
 }
 
 void monitor_resume(Monitor *mon)
 {
-    if (monitor_suspended == 2)
-        monitor_start_input();
-    monitor_suspended = 0;
+    if (--mon->suspend_cnt == 0)
+        readline_show_prompt(mon->rs);
 }
 
-static void monitor_start_input(void)
-{
-    readline_start(rs, "(qemu) ", 0, monitor_command_cb, NULL);
-    readline_show_prompt(rs);
-}
-
-static void term_event(void *opaque, int event)
+static void monitor_event(void *opaque, int event)
 {
     Monitor *mon = opaque;
 
@@ -2888,13 +2892,12 @@ static void term_event(void *opaque, int event)
 
     monitor_printf(mon, "QEMU %s monitor - type 'help' for more information\n",
                    QEMU_VERSION);
-    monitor_start_input();
+    readline_show_prompt(mon->rs);
 }
 
-static int is_first_init = 1;
-
-void monitor_init(CharDriverState *chr)
+void monitor_init(CharDriverState *chr, int flags)
 {
+    static int is_first_init = 1;
     Monitor *mon;
 
     if (is_first_init) {
@@ -2905,15 +2908,16 @@ void monitor_init(CharDriverState *chr)
     mon = qemu_mallocz(sizeof(*mon));
 
     mon->chr = chr;
-    rs = readline_init(mon, monitor_find_completion);
+    mon->flags = flags;
+    mon->rs = readline_init(mon, monitor_find_completion);
+    monitor_read_command(mon, 0);
 
-    qemu_chr_add_handlers(chr, term_can_read, term_read, term_event, mon);
+    qemu_chr_add_handlers(chr, monitor_can_read, monitor_read, monitor_event,
+                          mon);
 
     LIST_INSERT_HEAD(&mon_list, mon, entry);
-    if (!cur_mon)
+    if (!cur_mon || (flags & MONITOR_IS_DEFAULT))
         cur_mon = mon;
-
-    readline_start(rs, "", 0, monitor_command_cb, NULL);
 }
 
 static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
@@ -2925,10 +2929,10 @@ static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
         monitor_printf(mon, "invalid password\n");
         ret = -EPERM;
     }
-    if (password_completion_cb)
-        password_completion_cb(password_opaque, ret);
+    if (mon->password_completion_cb)
+        mon->password_completion_cb(mon->password_opaque, ret);
 
-    monitor_start_input();
+    monitor_read_command(mon, 1);
 }
 
 void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
@@ -2944,8 +2948,8 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
     monitor_printf(mon, "%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
                    bdrv_get_encrypted_filename(bs));
 
-    password_completion_cb = completion_cb;
-    password_opaque = opaque;
+    mon->password_completion_cb = completion_cb;
+    mon->password_opaque = opaque;
 
     monitor_read_password(mon, bdrv_password_cb, bs);
 }
diff --git a/monitor.h b/monitor.h
index abe7193..95a4060 100644
--- a/monitor.h
+++ b/monitor.h
@@ -7,7 +7,10 @@
 
 extern Monitor *cur_mon;
 
-void monitor_init(CharDriverState *chr);
+/* flags for monitor_init */
+#define MONITOR_IS_DEFAULT    0x01
+
+void monitor_init(CharDriverState *chr, int flags);
 
 void monitor_suspend(Monitor *mon);
 void monitor_resume(Monitor *mon);
diff --git a/qemu-char.c b/qemu-char.c
index bb50337..f815646 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2123,7 +2123,7 @@ CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*i
         chr = qemu_chr_open(label, p, NULL);
         if (chr) {
             chr = qemu_chr_open_mux(chr);
-            monitor_init(chr);
+            monitor_init(chr, 0);
         } else {
             printf("Unable to open driver: %s\n", p);
         }
diff --git a/vl.c b/vl.c
index bbf96e0..4c2a448 100644
--- a/vl.c
+++ b/vl.c
@@ -5658,7 +5658,7 @@ int main(int argc, char **argv, char **envp)
     qemu_chr_initial_reset();
 
     if (monitor_device && monitor_hd)
-        monitor_init(monitor_hd);
+        monitor_init(monitor_hd, MONITOR_IS_DEFAULT);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         const char *devname = serial_devices[i];

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 18/19] monitor: Introduce MONITOR_USE_READLINE flag
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (15 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 14/19] monitor: Drop banner hiding Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 16/19] monitor: Decouple terminals Jan Kiszka
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

This allows to create monitor terminals that do not make use of the
interactive readline back-end but rather send complete commands. The
pass-through monitor interface of the gdbstub will be an example.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 migration.c |    7 +++++--
 monitor.c   |   47 +++++++++++++++++++++++++++++++++++++----------
 monitor.h   |    3 ++-
 qemu-char.c |    2 +-
 vl.c        |    2 +-
 5 files changed, 46 insertions(+), 15 deletions(-)

diff --git a/migration.c b/migration.c
index 15639c1..b3904b2 100644
--- a/migration.c
+++ b/migration.c
@@ -128,8 +128,11 @@ void do_info_migrate(Monitor *mon)
 void migrate_fd_monitor_suspend(FdMigrationState *s)
 {
     s->mon_resume = cur_mon;
-    monitor_suspend(cur_mon);
-    dprintf("suspending monitor\n");
+    if (monitor_suspend(cur_mon) == 0)
+        dprintf("suspending monitor\n");
+    else
+        monitor_printf(cur_mon, "terminal does not allow synchronous "
+                       "migration, continuing detached\n");
 }
 
 void migrate_fd_error(FdMigrationState *s)
diff --git a/monitor.c b/monitor.c
index 7cae863..a7f1cc1 100644
--- a/monitor.c
+++ b/monitor.c
@@ -97,11 +97,17 @@ static void monitor_read_command(Monitor *mon, int show_prompt)
         readline_show_prompt(mon->rs);
 }
 
-static void monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
-                                  void *opaque)
+static int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
+                                 void *opaque)
 {
-    readline_start(mon->rs, "Password: ", 1, readline_func, opaque);
-    /* prompt is printed on return from the command handler */
+    if (mon->rs) {
+        readline_start(mon->rs, "Password: ", 1, readline_func, opaque);
+        /* prompt is printed on return from the command handler */
+        return 0;
+    } else {
+        monitor_printf(mon, "terminal does not support password prompting\n");
+        return -ENOTTY;
+    }
 }
 
 void monitor_flush(Monitor *mon)
@@ -373,6 +379,8 @@ static void do_info_history(Monitor *mon)
     int i;
     const char *str;
 
+    if (!mon->rs)
+        return;
     i = 0;
     for(;;) {
         str = readline_get_history(mon->rs, i);
@@ -2859,8 +2867,15 @@ static void monitor_read(void *opaque, const uint8_t *buf, int size)
 
     cur_mon = opaque;
 
-    for (i = 0; i < size; i++)
-        readline_handle_byte(cur_mon->rs, buf[i]);
+    if (cur_mon->rs) {
+        for (i = 0; i < size; i++)
+            readline_handle_byte(cur_mon->rs, buf[i]);
+    } else {
+        if (size == 0 || buf[size - 1] != 0)
+            monitor_printf(cur_mon, "corrupted command\n");
+        else
+            monitor_handle_command(cur_mon, (char *)buf);
+    }
 
     cur_mon = old_mon;
 }
@@ -2872,13 +2887,18 @@ static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque)
     monitor_resume(mon);
 }
 
-void monitor_suspend(Monitor *mon)
+int monitor_suspend(Monitor *mon)
 {
+    if (!mon->rs)
+        return -ENOTTY;
     mon->suspend_cnt++;
+    return 0;
 }
 
 void monitor_resume(Monitor *mon)
 {
+    if (!mon->rs)
+        return;
     if (--mon->suspend_cnt == 0)
         readline_show_prompt(mon->rs);
 }
@@ -2926,8 +2946,10 @@ void monitor_init(CharDriverState *chr, int flags)
     mon->flags = flags;
     if (mon->chr->focus != 0)
         mon->suspend_cnt = 1; /* mux'ed monitors start suspended */
-    mon->rs = readline_init(mon, monitor_find_completion);
-    monitor_read_command(mon, 0);
+    if (flags & MONITOR_USE_READLINE) {
+        mon->rs = readline_init(mon, monitor_find_completion);
+        monitor_read_command(mon, 0);
+    }
 
     qemu_chr_add_handlers(chr, monitor_can_read, monitor_read, monitor_event,
                           mon);
@@ -2956,6 +2978,8 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
                                  BlockDriverCompletionFunc *completion_cb,
                                  void *opaque)
 {
+    int err;
+
     if (!bdrv_key_required(bs)) {
         if (completion_cb)
             completion_cb(opaque, 0);
@@ -2968,5 +2992,8 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
     mon->password_completion_cb = completion_cb;
     mon->password_opaque = opaque;
 
-    monitor_read_password(mon, bdrv_password_cb, bs);
+    err = monitor_read_password(mon, bdrv_password_cb, bs);
+
+    if (err && completion_cb)
+        completion_cb(opaque, err);
 }
diff --git a/monitor.h b/monitor.h
index 95a4060..13e8cc7 100644
--- a/monitor.h
+++ b/monitor.h
@@ -9,10 +9,11 @@ extern Monitor *cur_mon;
 
 /* flags for monitor_init */
 #define MONITOR_IS_DEFAULT    0x01
+#define MONITOR_USE_READLINE  0x02
 
 void monitor_init(CharDriverState *chr, int flags);
 
-void monitor_suspend(Monitor *mon);
+int monitor_suspend(Monitor *mon);
 void monitor_resume(Monitor *mon);
 
 void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
diff --git a/qemu-char.c b/qemu-char.c
index 8c5544c..26e8825 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2130,7 +2130,7 @@ CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*i
         chr = qemu_chr_open(label, p, NULL);
         if (chr) {
             chr = qemu_chr_open_mux(chr);
-            monitor_init(chr, 0);
+            monitor_init(chr, MONITOR_USE_READLINE);
         } else {
             printf("Unable to open driver: %s\n", p);
         }
diff --git a/vl.c b/vl.c
index 4c2a448..0b55051 100644
--- a/vl.c
+++ b/vl.c
@@ -5658,7 +5658,7 @@ int main(int argc, char **argv, char **envp)
     qemu_chr_initial_reset();
 
     if (monitor_device && monitor_hd)
-        monitor_init(monitor_hd, MONITOR_IS_DEFAULT);
+        monitor_init(monitor_hd, MONITOR_USE_READLINE | MONITOR_IS_DEFAULT);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         const char *devname = serial_devices[i];

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 15/19] monitor: Introduce ReadLineState
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (13 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 17/19] monitor: Improve mux'ed console experience Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 14/19] monitor: Drop banner hiding Jan Kiszka
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

As another step towards decoupled monitor terminals encapsulate the
state of the readline processor in a separate data structure called
ReadLineState and adapt all interfaces appropriately. For now the
monitor continues to instantiate just a single readline state.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 monitor.c  |   36 +++--
 readline.c |  396 +++++++++++++++++++++++++++++-------------------------------
 readline.h |   48 ++++++-
 3 files changed, 249 insertions(+), 231 deletions(-)

diff --git a/monitor.c b/monitor.c
index 3115a67..6940031 100644
--- a/monitor.c
+++ b/monitor.c
@@ -81,6 +81,7 @@ static uint8_t term_outbuf[1024];
 static int term_outbuf_index;
 static BlockDriverCompletionFunc *password_completion_cb;
 static void *password_opaque;
+ReadLineState *rs;
 
 Monitor *cur_mon = NULL;
 
@@ -91,7 +92,7 @@ static CPUState *mon_cpu = NULL;
 static void monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
                                   void *opaque)
 {
-    readline_start("Password: ", 1, readline_func, opaque);
+    readline_start(rs, "Password: ", 1, readline_func, opaque);
 }
 
 void monitor_flush(Monitor *mon)
@@ -366,7 +367,7 @@ static void do_info_history(Monitor *mon)
 
     i = 0;
     for(;;) {
-        str = readline_get_history(i);
+        str = readline_get_history(rs, i);
         if (!str)
             break;
         monitor_printf(mon, "%d: '%s'\n", i, str);
@@ -2656,7 +2657,7 @@ static void cmd_completion(const char *name, const char *list)
         memcpy(cmd, pstart, len);
         cmd[len] = '\0';
         if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
-            readline_add_completion(cmd);
+            readline_add_completion(rs, cmd);
         }
         if (*p == '\0')
             break;
@@ -2709,7 +2710,7 @@ static void file_completion(const char *input)
             stat(file, &sb);
             if(S_ISDIR(sb.st_mode))
                 pstrcat(file, sizeof(file), "/");
-            readline_add_completion(file);
+            readline_add_completion(rs, file);
         }
     }
     closedir(ffs);
@@ -2722,7 +2723,7 @@ static void block_completion_it(void *opaque, BlockDriverState *bs)
 
     if (input[0] == '\0' ||
         !strncmp(name, (char *)input, strlen(input))) {
-        readline_add_completion(name);
+        readline_add_completion(rs, name);
     }
 }
 
@@ -2752,7 +2753,7 @@ static void parse_cmdline(const char *cmdline,
     *pnb_args = nb_args;
 }
 
-void readline_find_completion(const char *cmdline)
+static void monitor_find_completion(const char *cmdline)
 {
     const char *cmdname;
     char *args[MAX_ARGS];
@@ -2782,7 +2783,7 @@ void readline_find_completion(const char *cmdline)
             cmdname = "";
         else
             cmdname = args[0];
-        readline_set_completion_index(strlen(cmdname));
+        readline_set_completion_index(rs, strlen(cmdname));
         for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
             cmd_completion(cmdname, cmd->name);
         }
@@ -2806,23 +2807,23 @@ void readline_find_completion(const char *cmdline)
         switch(*ptype) {
         case 'F':
             /* file completion */
-            readline_set_completion_index(strlen(str));
+            readline_set_completion_index(rs, strlen(str));
             file_completion(str);
             break;
         case 'B':
             /* block device name completion */
-            readline_set_completion_index(strlen(str));
+            readline_set_completion_index(rs, strlen(str));
             bdrv_iterate(block_completion_it, (void *)str);
             break;
         case 's':
             /* XXX: more generic ? */
             if (!strcmp(cmd->name, "info")) {
-                readline_set_completion_index(strlen(str));
+                readline_set_completion_index(rs, strlen(str));
                 for(cmd = info_cmds; cmd->name != NULL; cmd++) {
                     cmd_completion(str, cmd->name);
                 }
             } else if (!strcmp(cmd->name, "sendkey")) {
-                readline_set_completion_index(strlen(str));
+                readline_set_completion_index(rs, strlen(str));
                 for(key = key_defs; key->name != NULL; key++) {
                     cmd_completion(str, key->name);
                 }
@@ -2845,8 +2846,8 @@ static void term_read(void *opaque, const uint8_t *buf, int size)
 {
     int i;
 
-    for (i = 0; i < size; i++)
-        readline_handle_byte(buf[i]);
+    for(i = 0; i < size; i++)
+        readline_handle_byte(rs, buf[i]);
 }
 
 static int monitor_suspended;
@@ -2855,7 +2856,7 @@ static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque)
 {
     monitor_handle_command(mon, cmdline);
     if (!monitor_suspended)
-        readline_show_prompt();
+        readline_show_prompt(rs);
     else
         monitor_suspended = 2;
 }
@@ -2874,8 +2875,8 @@ void monitor_resume(Monitor *mon)
 
 static void monitor_start_input(void)
 {
-    readline_start("(qemu) ", 0, monitor_command_cb, NULL);
-    readline_show_prompt();
+    readline_start(rs, "(qemu) ", 0, monitor_command_cb, NULL);
+    readline_show_prompt(rs);
 }
 
 static void term_event(void *opaque, int event)
@@ -2904,6 +2905,7 @@ void monitor_init(CharDriverState *chr)
     mon = qemu_mallocz(sizeof(*mon));
 
     mon->chr = chr;
+    rs = readline_init(mon, monitor_find_completion);
 
     qemu_chr_add_handlers(chr, term_can_read, term_read, term_event, mon);
 
@@ -2911,7 +2913,7 @@ void monitor_init(CharDriverState *chr)
     if (!cur_mon)
         cur_mon = mon;
 
-    readline_start("", 0, monitor_command_cb, NULL);
+    readline_start(rs, "", 0, monitor_command_cb, NULL);
 }
 
 static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
diff --git a/readline.c b/readline.c
index ffa5424..1868b10 100644
--- a/readline.c
+++ b/readline.c
@@ -24,148 +24,118 @@
 #include "readline.h"
 #include "monitor.h"
 
-#define TERM_CMD_BUF_SIZE 4095
-#define TERM_MAX_CMDS 64
-#define NB_COMPLETIONS_MAX 256
-
 #define IS_NORM 0
 #define IS_ESC  1
 #define IS_CSI  2
 
 #define printf do_not_use_printf
 
-static char term_cmd_buf[TERM_CMD_BUF_SIZE + 1];
-static int term_cmd_buf_index;
-static int term_cmd_buf_size;
-
-static char term_last_cmd_buf[TERM_CMD_BUF_SIZE + 1];
-static int term_last_cmd_buf_index;
-static int term_last_cmd_buf_size;
-
-static int term_esc_state;
-static int term_esc_param;
-
-static char *term_history[TERM_MAX_CMDS];
-static int term_hist_entry = -1;
-
-static int nb_completions;
-static int completion_index;
-static char *completions[NB_COMPLETIONS_MAX];
-
-static ReadLineFunc *term_readline_func;
-static int term_is_password;
-static char term_prompt[256];
-static void *term_readline_opaque;
-
-void readline_show_prompt(void)
+void readline_show_prompt(ReadLineState *rs)
 {
-    Monitor *mon = cur_mon;
-
-    monitor_printf(mon, "%s", term_prompt);
-    monitor_flush(mon);
-    term_last_cmd_buf_index = 0;
-    term_last_cmd_buf_size = 0;
-    term_esc_state = IS_NORM;
+    monitor_printf(rs->mon, "%s", rs->prompt);
+    monitor_flush(rs->mon);
+    rs->last_cmd_buf_index = 0;
+    rs->last_cmd_buf_size = 0;
+    rs->esc_state = IS_NORM;
 }
 
 /* update the displayed command line */
-static void term_update(void)
+static void readline_update(ReadLineState *rs)
 {
-    Monitor *mon = cur_mon;
     int i, delta, len;
 
-    if (term_cmd_buf_size != term_last_cmd_buf_size ||
-        memcmp(term_cmd_buf, term_last_cmd_buf, term_cmd_buf_size) != 0) {
-        for(i = 0; i < term_last_cmd_buf_index; i++) {
-            monitor_printf(mon, "\033[D");
+    if (rs->cmd_buf_size != rs->last_cmd_buf_size ||
+        memcmp(rs->cmd_buf, rs->last_cmd_buf, rs->cmd_buf_size) != 0) {
+        for(i = 0; i < rs->last_cmd_buf_index; i++) {
+            monitor_printf(rs->mon, "\033[D");
         }
-        term_cmd_buf[term_cmd_buf_size] = '\0';
-        if (term_is_password) {
-            len = strlen(term_cmd_buf);
+        rs->cmd_buf[rs->cmd_buf_size] = '\0';
+        if (rs->read_password) {
+            len = strlen(rs->cmd_buf);
             for(i = 0; i < len; i++)
-                monitor_printf(mon, "*");
+                monitor_printf(rs->mon, "*");
         } else {
-            monitor_printf(mon, "%s", term_cmd_buf);
+            monitor_printf(rs->mon, "%s", rs->cmd_buf);
         }
-        monitor_printf(mon, "\033[K");
-        memcpy(term_last_cmd_buf, term_cmd_buf, term_cmd_buf_size);
-        term_last_cmd_buf_size = term_cmd_buf_size;
-        term_last_cmd_buf_index = term_cmd_buf_size;
+        monitor_printf(rs->mon, "\033[K");
+        memcpy(rs->last_cmd_buf, rs->cmd_buf, rs->cmd_buf_size);
+        rs->last_cmd_buf_size = rs->cmd_buf_size;
+        rs->last_cmd_buf_index = rs->cmd_buf_size;
     }
-    if (term_cmd_buf_index != term_last_cmd_buf_index) {
-        delta = term_cmd_buf_index - term_last_cmd_buf_index;
+    if (rs->cmd_buf_index != rs->last_cmd_buf_index) {
+        delta = rs->cmd_buf_index - rs->last_cmd_buf_index;
         if (delta > 0) {
             for(i = 0;i < delta; i++) {
-                monitor_printf(mon, "\033[C");
+                monitor_printf(rs->mon, "\033[C");
             }
         } else {
             delta = -delta;
             for(i = 0;i < delta; i++) {
-                monitor_printf(mon, "\033[D");
+                monitor_printf(rs->mon, "\033[D");
             }
         }
-        term_last_cmd_buf_index = term_cmd_buf_index;
+        rs->last_cmd_buf_index = rs->cmd_buf_index;
     }
-    monitor_flush(mon);
+    monitor_flush(rs->mon);
 }
 
-static void term_insert_char(int ch)
+static void readline_insert_char(ReadLineState *rs, int ch)
 {
-    if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) {
-        memmove(term_cmd_buf + term_cmd_buf_index + 1,
-                term_cmd_buf + term_cmd_buf_index,
-                term_cmd_buf_size - term_cmd_buf_index);
-        term_cmd_buf[term_cmd_buf_index] = ch;
-        term_cmd_buf_size++;
-        term_cmd_buf_index++;
+    if (rs->cmd_buf_index < READLINE_CMD_BUF_SIZE) {
+        memmove(rs->cmd_buf + rs->cmd_buf_index + 1,
+                rs->cmd_buf + rs->cmd_buf_index,
+                rs->cmd_buf_size - rs->cmd_buf_index);
+        rs->cmd_buf[rs->cmd_buf_index] = ch;
+        rs->cmd_buf_size++;
+        rs->cmd_buf_index++;
     }
 }
 
-static void term_backward_char(void)
+static void readline_backward_char(ReadLineState *rs)
 {
-    if (term_cmd_buf_index > 0) {
-        term_cmd_buf_index--;
+    if (rs->cmd_buf_index > 0) {
+        rs->cmd_buf_index--;
     }
 }
 
-static void term_forward_char(void)
+static void readline_forward_char(ReadLineState *rs)
 {
-    if (term_cmd_buf_index < term_cmd_buf_size) {
-        term_cmd_buf_index++;
+    if (rs->cmd_buf_index < rs->cmd_buf_size) {
+        rs->cmd_buf_index++;
     }
 }
 
-static void term_delete_char(void)
+static void readline_delete_char(ReadLineState *rs)
 {
-    if (term_cmd_buf_index < term_cmd_buf_size) {
-        memmove(term_cmd_buf + term_cmd_buf_index,
-                term_cmd_buf + term_cmd_buf_index + 1,
-                term_cmd_buf_size - term_cmd_buf_index - 1);
-        term_cmd_buf_size--;
+    if (rs->cmd_buf_index < rs->cmd_buf_size) {
+        memmove(rs->cmd_buf + rs->cmd_buf_index,
+                rs->cmd_buf + rs->cmd_buf_index + 1,
+                rs->cmd_buf_size - rs->cmd_buf_index - 1);
+        rs->cmd_buf_size--;
     }
 }
 
-static void term_backspace(void)
+static void readline_backspace(ReadLineState *rs)
 {
-    if (term_cmd_buf_index > 0) {
-        term_backward_char();
-        term_delete_char();
+    if (rs->cmd_buf_index > 0) {
+        readline_backward_char(rs);
+        readline_delete_char(rs);
     }
 }
 
-static void term_backword(void)
+static void readline_backword(ReadLineState *rs)
 {
     int start;
 
-    if (term_cmd_buf_index == 0 || term_cmd_buf_index > term_cmd_buf_size) {
+    if (rs->cmd_buf_index == 0 || rs->cmd_buf_index > rs->cmd_buf_size) {
         return;
     }
 
-    start = term_cmd_buf_index - 1;
+    start = rs->cmd_buf_index - 1;
 
     /* find first word (backwards) */
     while (start > 0) {
-        if (!qemu_isspace(term_cmd_buf[start])) {
+        if (!qemu_isspace(rs->cmd_buf[start])) {
             break;
         }
 
@@ -174,7 +144,7 @@ static void term_backword(void)
 
     /* find first space (backwards) */
     while (start > 0) {
-        if (qemu_isspace(term_cmd_buf[start])) {
+        if (qemu_isspace(rs->cmd_buf[start])) {
             ++start;
             break;
         }
@@ -183,61 +153,61 @@ static void term_backword(void)
     }
 
     /* remove word */
-    if (start < term_cmd_buf_index) {
-        memmove(term_cmd_buf + start,
-                term_cmd_buf + term_cmd_buf_index,
-                term_cmd_buf_size - term_cmd_buf_index);
-        term_cmd_buf_size -= term_cmd_buf_index - start;
-        term_cmd_buf_index = start;
+    if (start < rs->cmd_buf_index) {
+        memmove(rs->cmd_buf + start,
+                rs->cmd_buf + rs->cmd_buf_index,
+                rs->cmd_buf_size - rs->cmd_buf_index);
+        rs->cmd_buf_size -= rs->cmd_buf_index - start;
+        rs->cmd_buf_index = start;
     }
 }
 
-static void term_bol(void)
+static void readline_bol(ReadLineState *rs)
 {
-    term_cmd_buf_index = 0;
+    rs->cmd_buf_index = 0;
 }
 
-static void term_eol(void)
+static void readline_eol(ReadLineState *rs)
 {
-    term_cmd_buf_index = term_cmd_buf_size;
+    rs->cmd_buf_index = rs->cmd_buf_size;
 }
 
-static void term_up_char(void)
+static void readline_up_char(ReadLineState *rs)
 {
     int idx;
 
-    if (term_hist_entry == 0)
+    if (rs->hist_entry == 0)
 	return;
-    if (term_hist_entry == -1) {
+    if (rs->hist_entry == -1) {
 	/* Find latest entry */
-	for (idx = 0; idx < TERM_MAX_CMDS; idx++) {
-	    if (term_history[idx] == NULL)
+	for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
+	    if (rs->history[idx] == NULL)
 		break;
 	}
-	term_hist_entry = idx;
+	rs->hist_entry = idx;
     }
-    term_hist_entry--;
-    if (term_hist_entry >= 0) {
-	pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),
-                term_history[term_hist_entry]);
-	term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);
+    rs->hist_entry--;
+    if (rs->hist_entry >= 0) {
+	pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
+                rs->history[rs->hist_entry]);
+	rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
     }
 }
 
-static void term_down_char(void)
+static void readline_down_char(ReadLineState *rs)
 {
-    if (term_hist_entry == TERM_MAX_CMDS - 1 || term_hist_entry == -1)
+    if (rs->hist_entry == READLINE_MAX_CMDS - 1 || rs->hist_entry == -1)
 	return;
-    if (term_history[++term_hist_entry] != NULL) {
-	pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),
-                term_history[term_hist_entry]);
+    if (rs->history[++rs->hist_entry] != NULL) {
+	pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
+                rs->history[rs->hist_entry]);
     } else {
-	term_hist_entry = -1;
+	rs->hist_entry = -1;
     }
-    term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);
+    rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
 }
 
-static void term_hist_add(const char *cmdline)
+static void readline_hist_add(ReadLineState *rs, const char *cmdline)
 {
     char *hist_entry, *new_entry;
     int idx;
@@ -245,99 +215,99 @@ static void term_hist_add(const char *cmdline)
     if (cmdline[0] == '\0')
 	return;
     new_entry = NULL;
-    if (term_hist_entry != -1) {
+    if (rs->hist_entry != -1) {
 	/* We were editing an existing history entry: replace it */
-	hist_entry = term_history[term_hist_entry];
-	idx = term_hist_entry;
+	hist_entry = rs->history[rs->hist_entry];
+	idx = rs->hist_entry;
 	if (strcmp(hist_entry, cmdline) == 0) {
 	    goto same_entry;
 	}
     }
     /* Search cmdline in history buffers */
-    for (idx = 0; idx < TERM_MAX_CMDS; idx++) {
-	hist_entry = term_history[idx];
+    for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
+	hist_entry = rs->history[idx];
 	if (hist_entry == NULL)
 	    break;
 	if (strcmp(hist_entry, cmdline) == 0) {
 	same_entry:
 	    new_entry = hist_entry;
 	    /* Put this entry at the end of history */
-	    memmove(&term_history[idx], &term_history[idx + 1],
-		    (TERM_MAX_CMDS - idx + 1) * sizeof(char *));
-	    term_history[TERM_MAX_CMDS - 1] = NULL;
-	    for (; idx < TERM_MAX_CMDS; idx++) {
-		if (term_history[idx] == NULL)
+	    memmove(&rs->history[idx], &rs->history[idx + 1],
+		    (READLINE_MAX_CMDS - idx + 1) * sizeof(char *));
+	    rs->history[READLINE_MAX_CMDS - 1] = NULL;
+	    for (; idx < READLINE_MAX_CMDS; idx++) {
+		if (rs->history[idx] == NULL)
 		    break;
 	    }
 	    break;
 	}
     }
-    if (idx == TERM_MAX_CMDS) {
+    if (idx == READLINE_MAX_CMDS) {
 	/* Need to get one free slot */
-	free(term_history[0]);
-	memcpy(term_history, &term_history[1],
-	       (TERM_MAX_CMDS - 1) * sizeof(char *));
-	term_history[TERM_MAX_CMDS - 1] = NULL;
-	idx = TERM_MAX_CMDS - 1;
+	free(rs->history[0]);
+	memcpy(rs->history, &rs->history[1],
+	       (READLINE_MAX_CMDS - 1) * sizeof(char *));
+	rs->history[READLINE_MAX_CMDS - 1] = NULL;
+	idx = READLINE_MAX_CMDS - 1;
     }
     if (new_entry == NULL)
 	new_entry = strdup(cmdline);
-    term_history[idx] = new_entry;
-    term_hist_entry = -1;
+    rs->history[idx] = new_entry;
+    rs->hist_entry = -1;
 }
 
 /* completion support */
 
-void readline_add_completion(const char *str)
+void readline_add_completion(ReadLineState *rs, const char *str)
 {
-    if (nb_completions < NB_COMPLETIONS_MAX) {
-        completions[nb_completions++] = qemu_strdup(str);
+    if (rs->nb_completions < READLINE_MAX_COMPLETIONS) {
+        rs->completions[rs->nb_completions++] = qemu_strdup(str);
     }
 }
 
-void readline_set_completion_index(int index)
+void readline_set_completion_index(ReadLineState *rs, int index)
 {
-    completion_index = index;
+    rs->completion_index = index;
 }
 
-static void term_completion(void)
+static void readline_completion(ReadLineState *rs)
 {
     Monitor *mon = cur_mon;
     int len, i, j, max_width, nb_cols, max_prefix;
     char *cmdline;
 
-    nb_completions = 0;
+    rs->nb_completions = 0;
 
-    cmdline = qemu_malloc(term_cmd_buf_index + 1);
-    memcpy(cmdline, term_cmd_buf, term_cmd_buf_index);
-    cmdline[term_cmd_buf_index] = '\0';
-    readline_find_completion(cmdline);
+    cmdline = qemu_malloc(rs->cmd_buf_index + 1);
+    memcpy(cmdline, rs->cmd_buf, rs->cmd_buf_index);
+    cmdline[rs->cmd_buf_index] = '\0';
+    rs->completion_finder(cmdline);
     qemu_free(cmdline);
 
     /* no completion found */
-    if (nb_completions <= 0)
+    if (rs->nb_completions <= 0)
         return;
-    if (nb_completions == 1) {
-        len = strlen(completions[0]);
-        for(i = completion_index; i < len; i++) {
-            term_insert_char(completions[0][i]);
+    if (rs->nb_completions == 1) {
+        len = strlen(rs->completions[0]);
+        for(i = rs->completion_index; i < len; i++) {
+            readline_insert_char(rs, rs->completions[0][i]);
         }
         /* extra space for next argument. XXX: make it more generic */
-        if (len > 0 && completions[0][len - 1] != '/')
-            term_insert_char(' ');
+        if (len > 0 && rs->completions[0][len - 1] != '/')
+            readline_insert_char(rs, ' ');
     } else {
         monitor_printf(mon, "\n");
         max_width = 0;
         max_prefix = 0;	
-        for(i = 0; i < nb_completions; i++) {
-            len = strlen(completions[i]);
+        for(i = 0; i < rs->nb_completions; i++) {
+            len = strlen(rs->completions[i]);
             if (i==0) {
                 max_prefix = len;
             } else {
                 if (len < max_prefix)
                     max_prefix = len;
                 for(j=0; j<max_prefix; j++) {
-                    if (completions[i][j] != completions[0][j])
+                    if (rs->completions[i][j] != rs->completions[0][j])
                         max_prefix = j;
                 }
             }
@@ -345,8 +315,8 @@ static void term_completion(void)
                 max_width = len;
         }
         if (max_prefix > 0) 
-            for(i = completion_index; i < max_prefix; i++) {
-                term_insert_char(completions[0][i]);
+            for(i = rs->completion_index; i < max_prefix; i++) {
+                readline_insert_char(rs, rs->completions[0][i]);
             }
         max_width += 2;
         if (max_width < 10)
@@ -355,135 +325,147 @@ static void term_completion(void)
             max_width = 80;
         nb_cols = 80 / max_width;
         j = 0;
-        for(i = 0; i < nb_completions; i++) {
-            monitor_printf(mon, "%-*s", max_width, completions[i]);
-            if (++j == nb_cols || i == (nb_completions - 1)) {
-                monitor_printf(mon, "\n");
+        for(i = 0; i < rs->nb_completions; i++) {
+            monitor_printf(rs->mon, "%-*s", max_width, rs->completions[i]);
+            if (++j == nb_cols || i == (rs->nb_completions - 1)) {
+                monitor_printf(rs->mon, "\n");
                 j = 0;
             }
         }
-        readline_show_prompt();
+        readline_show_prompt(rs);
     }
 }
 
 /* return true if command handled */
-void readline_handle_byte(int ch)
+void readline_handle_byte(ReadLineState *rs, int ch)
 {
-    Monitor *mon = cur_mon;
-
-    switch(term_esc_state) {
+    switch(rs->esc_state) {
     case IS_NORM:
         switch(ch) {
         case 1:
-            term_bol();
+            readline_bol(rs);
             break;
         case 4:
-            term_delete_char();
+            readline_delete_char(rs);
             break;
         case 5:
-            term_eol();
+            readline_eol(rs);
             break;
         case 9:
-            term_completion();
+            readline_completion(rs);
             break;
         case 10:
         case 13:
-            term_cmd_buf[term_cmd_buf_size] = '\0';
-            if (!term_is_password)
-                term_hist_add(term_cmd_buf);
-            monitor_printf(mon, "\n");
-            term_cmd_buf_index = 0;
-            term_cmd_buf_size = 0;
-            term_last_cmd_buf_index = 0;
-            term_last_cmd_buf_size = 0;
-            /* NOTE: readline_start can be called here */
-            term_readline_func(mon, term_cmd_buf, term_readline_opaque);
+            rs->cmd_buf[rs->cmd_buf_size] = '\0';
+            if (!rs->read_password)
+                readline_hist_add(rs, rs->cmd_buf);
+            monitor_printf(rs->mon, "\n");
+            rs->cmd_buf_index = 0;
+            rs->cmd_buf_size = 0;
+            rs->last_cmd_buf_index = 0;
+            rs->last_cmd_buf_size = 0;
+            rs->readline_func(rs->mon, rs->cmd_buf, rs->readline_opaque);
             break;
         case 23:
             /* ^W */
-            term_backword();
+            readline_backword(rs);
             break;
         case 27:
-            term_esc_state = IS_ESC;
+            rs->esc_state = IS_ESC;
             break;
         case 127:
         case 8:
-            term_backspace();
+            readline_backspace(rs);
             break;
 	case 155:
-            term_esc_state = IS_CSI;
+            rs->esc_state = IS_CSI;
 	    break;
         default:
             if (ch >= 32) {
-                term_insert_char(ch);
+                readline_insert_char(rs, ch);
             }
             break;
         }
         break;
     case IS_ESC:
         if (ch == '[') {
-            term_esc_state = IS_CSI;
-            term_esc_param = 0;
+            rs->esc_state = IS_CSI;
+            rs->esc_param = 0;
         } else {
-            term_esc_state = IS_NORM;
+            rs->esc_state = IS_NORM;
         }
         break;
     case IS_CSI:
         switch(ch) {
 	case 'A':
 	case 'F':
-	    term_up_char();
+	    readline_up_char(rs);
 	    break;
 	case 'B':
 	case 'E':
-	    term_down_char();
+	    readline_down_char(rs);
 	    break;
         case 'D':
-            term_backward_char();
+            readline_backward_char(rs);
             break;
         case 'C':
-            term_forward_char();
+            readline_forward_char(rs);
             break;
         case '0' ... '9':
-            term_esc_param = term_esc_param * 10 + (ch - '0');
+            rs->esc_param = rs->esc_param * 10 + (ch - '0');
             goto the_end;
         case '~':
-            switch(term_esc_param) {
+            switch(rs->esc_param) {
             case 1:
-                term_bol();
+                readline_bol(rs);
                 break;
             case 3:
-                term_delete_char();
+                readline_delete_char(rs);
                 break;
             case 4:
-                term_eol();
+                readline_eol(rs);
                 break;
             }
             break;
         default:
             break;
         }
-        term_esc_state = IS_NORM;
+        rs->esc_state = IS_NORM;
     the_end:
         break;
     }
-    term_update();
+    readline_update(rs);
 }
 
-void readline_start(const char *prompt, int is_password,
+void readline_start(ReadLineState *rs, const char *prompt, int read_password,
                     ReadLineFunc *readline_func, void *opaque)
 {
-    pstrcpy(term_prompt, sizeof(term_prompt), prompt);
-    term_readline_func = readline_func;
-    term_readline_opaque = opaque;
-    term_is_password = is_password;
-    term_cmd_buf_index = 0;
-    term_cmd_buf_size = 0;
+    pstrcpy(rs->prompt, sizeof(rs->prompt), prompt);
+    rs->readline_func = readline_func;
+    rs->readline_opaque = opaque;
+    rs->read_password = read_password;
+    rs->cmd_buf_index = 0;
+    rs->cmd_buf_size = 0;
 }
 
-const char *readline_get_history(unsigned int index)
+const char *readline_get_history(ReadLineState *rs, unsigned int index)
 {
-    if (index >= TERM_MAX_CMDS)
+    if (index >= READLINE_MAX_CMDS)
         return NULL;
-    return term_history[index];
+    return rs->history[index];
+}
+
+ReadLineState *readline_init(Monitor *mon,
+                             ReadLineCompletionFunc *completion_finder)
+{
+    ReadLineState *rs = qemu_mallocz(sizeof(*rs));
+
+    if (!rs)
+        return NULL;
+
+    rs->hist_entry = -1;
+    rs->mon = mon;
+    rs->completion_finder = completion_finder;
+
+    return rs;
 }
diff --git a/readline.h b/readline.h
index c5c10d6..fcf0f33 100644
--- a/readline.h
+++ b/readline.h
@@ -3,18 +3,52 @@
 
 #include "qemu-common.h"
 
+#define READLINE_CMD_BUF_SIZE 4095
+#define READLINE_MAX_CMDS 64
+#define READLINE_MAX_COMPLETIONS 256
+
 typedef void ReadLineFunc(Monitor *mon, const char *str, void *opaque);
+typedef void ReadLineCompletionFunc(const char *cmdline);
+
+typedef struct ReadLineState {
+    char cmd_buf[READLINE_CMD_BUF_SIZE + 1];
+    int cmd_buf_index;
+    int cmd_buf_size;
+
+    char last_cmd_buf[READLINE_CMD_BUF_SIZE + 1];
+    int last_cmd_buf_index;
+    int last_cmd_buf_size;
+
+    int esc_state;
+    int esc_param;
 
-void readline_add_completion(const char *str);
-void readline_set_completion_index(int index);
-void readline_find_completion(const char *cmdline);
+    char *history[READLINE_MAX_CMDS];
+    int hist_entry;
 
-const char *readline_get_history(unsigned int index);
+    ReadLineCompletionFunc *completion_finder;
+    char *completions[READLINE_MAX_COMPLETIONS];
+    int nb_completions;
+    int completion_index;
 
-void readline_handle_byte(int ch);
+    ReadLineFunc *readline_func;
+    void *readline_opaque;
+    int read_password;
+    char prompt[256];
+    Monitor *mon;
+} ReadLineState;
 
-void readline_start(const char *prompt, int is_password,
+void readline_add_completion(ReadLineState *rs, const char *str);
+void readline_set_completion_index(ReadLineState *rs, int completion_index);
+
+const char *readline_get_history(ReadLineState *rs, unsigned int index);
+
+void readline_handle_byte(ReadLineState *rs, int ch);
+
+void readline_start(ReadLineState *rs, const char *prompt, int read_password,
                     ReadLineFunc *readline_func, void *opaque);
-void readline_show_prompt(void);
+void readline_show_prompt(ReadLineState *rs);
+
+ReadLineState *readline_init(Monitor *mon,
+                             ReadLineCompletionFunc *completion_finder);
 
 #endif /* !READLINE_H */

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 12/19] monitor: Rework API
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (10 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 11/19] monitor: Rework modal password input Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 13/19] monitor: Rework terminal management Jan Kiszka
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

Refactor the monitor API and prepare it for decoupled terminals:
term_print functions are renamed to monitor_* and all monitor services
gain a new parameter (mon) that will once refer to the monitor instance
the output is supposed to appear on. However, the argument remains
unused for now. All monitor command callbacks are also extended by a mon
parameter so that command handlers are able to pass an appropriate
reference to monitor output services.

For the case that monitor outputs so far happen without clearly
identifiable context, the global variable cur_mon is introduced that
shall once provide a pointer either to the current active monitor (while
processing commands) or to the default one. On the mid or long term,
those use case will be obsoleted so that this variable can be removed
again.

Due to the broad usage of the monitor interface, this patch mostly deals
with converting users of the monitor API. A few of them are already
extended to pass 'mon' from the command handler further down to internal
functions that invoke monitor_printf.

At this chance, monitor-related prototypes are moved from console.h to
a new monitor.h. The same is done for the readline API.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 audio/audio.c      |    6 
 audio/wavcapture.c |   21 +-
 block.c            |   66 ++---
 block.h            |    4 
 console.h          |   37 ---
 disas.c            |   17 +
 disas.h            |    8 +
 hw/an5206.c        |    5 
 hw/arm_pic.c       |    5 
 hw/etraxfs_pic.c   |    5 
 hw/i8259.c         |   21 +-
 hw/pc.c            |    9 -
 hw/pc.h            |    7 -
 hw/pci-hotplug.c   |   51 ++--
 hw/pci.c           |   32 +-
 hw/pci.h           |    4 
 hw/pcmcia.h        |    4 
 hw/shix.c          |    5 
 hw/slavio_intctl.c |   20 +
 hw/sun4c_intctl.c  |   16 +
 hw/sun4m.c         |    8 -
 hw/sun4m.h         |   10 -
 hw/usb.h           |    2 
 migration-exec.c   |    4 
 migration-tcp.c    |    4 
 migration.c        |   28 +-
 migration.h        |   10 -
 monitor.c          |  724 +++++++++++++++++++++++++++-------------------------
 monitor.h          |   25 ++
 net.c              |   30 +-
 net.h              |    8 -
 qemu-char.c        |    5 
 qemu-char.h        |    4 
 qemu-common.h      |    3 
 qemu-tool.c        |    8 -
 readline.c         |   47 ++-
 readline.h         |   20 +
 savevm.c           |   83 +++---
 slirp/misc.c       |    4 
 sysemu.h           |   25 +-
 usb-linux.c        |   35 ++-
 vl.c               |   47 ++-
 vnc.c              |   20 +
 43 files changed, 802 insertions(+), 695 deletions(-)
 create mode 100644 monitor.h
 create mode 100644 readline.h

diff --git a/audio/audio.c b/audio/audio.c
index a2636cb..3c311d7 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -23,7 +23,7 @@
  */
 #include "hw/hw.h"
 #include "audio.h"
-#include "console.h"
+#include "monitor.h"
 #include "qemu-timer.h"
 #include "sysemu.h"
 
@@ -328,10 +328,10 @@ void AUD_vlog (const char *cap, const char *fmt, va_list ap)
 {
     if (conf.log_to_monitor) {
         if (cap) {
-            term_printf ("%s: ", cap);
+            monitor_printf(cur_mon, "%s: ", cap);
         }
 
-        term_vprintf (fmt, ap);
+        monitor_vprintf(cur_mon, fmt, ap);
     }
     else {
         if (cap) {
diff --git a/audio/wavcapture.c b/audio/wavcapture.c
index 6d1c441..bead458 100644
--- a/audio/wavcapture.c
+++ b/audio/wavcapture.c
@@ -1,5 +1,5 @@
 #include "hw/hw.h"
-#include "console.h"
+#include "monitor.h"
 #include "audio.h"
 
 typedef struct {
@@ -71,9 +71,9 @@ static void wav_capture_info (void *opaque)
     WAVState *wav = opaque;
     char *path = wav->path;
 
-    term_printf ("Capturing audio(%d,%d,%d) to %s: %d bytes\n",
-                 wav->freq, wav->bits, wav->nchannels,
-                 path ? path : "<not available>", wav->bytes);
+    monitor_printf(cur_mon, "Capturing audio(%d,%d,%d) to %s: %d bytes\n",
+                   wav->freq, wav->bits, wav->nchannels,
+                   path ? path : "<not available>", wav->bytes);
 }
 
 static struct capture_ops wav_capture_ops = {
@@ -84,6 +84,7 @@ static struct capture_ops wav_capture_ops = {
 int wav_start_capture (CaptureState *s, const char *path, int freq,
                        int bits, int nchannels)
 {
+    Monitor *mon = cur_mon;
     WAVState *wav;
     uint8_t hdr[] = {
         0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
@@ -97,13 +98,13 @@ int wav_start_capture (CaptureState *s, const char *path, int freq,
     CaptureVoiceOut *cap;
 
     if (bits != 8 && bits != 16) {
-        term_printf ("incorrect bit count %d, must be 8 or 16\n", bits);
+        monitor_printf(mon, "incorrect bit count %d, must be 8 or 16\n", bits);
         return -1;
     }
 
     if (nchannels != 1 && nchannels != 2) {
-        term_printf ("incorrect channel count %d, must be 1 or 2\n",
-                     nchannels);
+        monitor_printf(mon, "incorrect channel count %d, must be 1 or 2\n",
+                       nchannels);
         return -1;
     }
 
@@ -131,8 +132,8 @@ int wav_start_capture (CaptureState *s, const char *path, int freq,
 
     wav->f = qemu_fopen (path, "wb");
     if (!wav->f) {
-        term_printf ("Failed to open wave file `%s'\nReason: %s\n",
-                     path, strerror (errno));
+        monitor_printf(mon, "Failed to open wave file `%s'\nReason: %s\n",
+                       path, strerror (errno));
         qemu_free (wav);
         return -1;
     }
@@ -146,7 +147,7 @@ int wav_start_capture (CaptureState *s, const char *path, int freq,
 
     cap = AUD_add_capture (NULL, &as, &ops, wav);
     if (!cap) {
-        term_printf ("Failed to add audio capture\n");
+        monitor_printf(mon, "Failed to add audio capture\n");
         qemu_free (wav->path);
         qemu_fclose (wav->f);
         qemu_free (wav);
diff --git a/block.c b/block.c
index 1ec77c2..91ebdee 100644
--- a/block.c
+++ b/block.c
@@ -28,7 +28,7 @@
 #endif
 
 #include "qemu-common.h"
-#include "console.h"
+#include "monitor.h"
 #include "block_int.h"
 
 #ifdef _BSD
@@ -1046,66 +1046,66 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
     return bs->drv->bdrv_is_allocated(bs, sector_num, nb_sectors, pnum);
 }
 
-void bdrv_info(void)
+void bdrv_info(Monitor *mon)
 {
     BlockDriverState *bs;
 
     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
-        term_printf("%s:", bs->device_name);
-        term_printf(" type=");
+        monitor_printf(mon, "%s:", bs->device_name);
+        monitor_printf(mon, " type=");
         switch(bs->type) {
         case BDRV_TYPE_HD:
-            term_printf("hd");
+            monitor_printf(mon, "hd");
             break;
         case BDRV_TYPE_CDROM:
-            term_printf("cdrom");
+            monitor_printf(mon, "cdrom");
             break;
         case BDRV_TYPE_FLOPPY:
-            term_printf("floppy");
+            monitor_printf(mon, "floppy");
             break;
         }
-        term_printf(" removable=%d", bs->removable);
+        monitor_printf(mon, " removable=%d", bs->removable);
         if (bs->removable) {
-            term_printf(" locked=%d", bs->locked);
+            monitor_printf(mon, " locked=%d", bs->locked);
         }
         if (bs->drv) {
-            term_printf(" file=");
-	    term_print_filename(bs->filename);
+            monitor_printf(mon, " file=");
+            monitor_print_filename(mon, bs->filename);
             if (bs->backing_file[0] != '\0') {
-                term_printf(" backing_file=");
-		term_print_filename(bs->backing_file);
-	    }
-            term_printf(" ro=%d", bs->read_only);
-            term_printf(" drv=%s", bs->drv->format_name);
-            term_printf(" encrypted=%d", bdrv_is_encrypted(bs));
+                monitor_printf(mon, " backing_file=");
+                monitor_print_filename(mon, bs->backing_file);
+            }
+            monitor_printf(mon, " ro=%d", bs->read_only);
+            monitor_printf(mon, " drv=%s", bs->drv->format_name);
+            monitor_printf(mon, " encrypted=%d", bdrv_is_encrypted(bs));
         } else {
-            term_printf(" [not inserted]");
+            monitor_printf(mon, " [not inserted]");
         }
-        term_printf("\n");
+        monitor_printf(mon, "\n");
     }
 }
 
 /* The "info blockstats" command. */
-void bdrv_info_stats (void)
+void bdrv_info_stats(Monitor *mon)
 {
     BlockDriverState *bs;
     BlockDriverInfo bdi;
 
     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
-	term_printf ("%s:"
-		     " rd_bytes=%" PRIu64
-		     " wr_bytes=%" PRIu64
-		     " rd_operations=%" PRIu64
-		     " wr_operations=%" PRIu64
-                     ,
-		     bs->device_name,
-		     bs->rd_bytes, bs->wr_bytes,
-		     bs->rd_ops, bs->wr_ops);
+        monitor_printf(mon, "%s:"
+                       " rd_bytes=%" PRIu64
+                       " wr_bytes=%" PRIu64
+                       " rd_operations=%" PRIu64
+                       " wr_operations=%" PRIu64
+                       ,
+                       bs->device_name,
+                       bs->rd_bytes, bs->wr_bytes,
+                       bs->rd_ops, bs->wr_ops);
         if (bdrv_get_info(bs, &bdi) == 0)
-            term_printf(" high=%" PRId64
-                        " bytes_free=%" PRId64,
-                        bdi.highest_alloc, bdi.num_free_bytes);
-        term_printf("\n");
+            monitor_printf(mon, " high=%" PRId64
+                           " bytes_free=%" PRId64,
+                           bdi.highest_alloc, bdi.num_free_bytes);
+        monitor_printf(mon, "\n");
     }
 }
 
diff --git a/block.h b/block.h
index 5c6eaf9..50757a5 100644
--- a/block.h
+++ b/block.h
@@ -56,8 +56,8 @@ typedef struct QEMUSnapshotInfo {
 
 #define BDRV_O_CACHE_MASK  (BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_CACHE_DEF)
 
-void bdrv_info(void);
-void bdrv_info_stats(void);
+void bdrv_info(Monitor *mon);
+void bdrv_info_stats(Monitor *mon);
 
 void bdrv_init(void);
 BlockDriver *bdrv_find_format(const char *format_name);
diff --git a/console.h b/console.h
index 782f6dd..4995c40 100644
--- a/console.h
+++ b/console.h
@@ -43,8 +43,8 @@ struct mouse_transform_info_s {
     int a[7];
 };
 
-void do_info_mice(void);
-void do_mouse_set(int index);
+void do_info_mice(Monitor *mon);
+void do_mouse_set(Monitor *mon, int index);
 
 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
    constants) */
@@ -287,42 +287,11 @@ void vnc_display_init(DisplayState *ds);
 void vnc_display_close(DisplayState *ds);
 int vnc_display_open(DisplayState *ds, const char *display);
 int vnc_display_password(DisplayState *ds, const char *password);
-void do_info_vnc(void);
+void do_info_vnc(Monitor *mon);
 
 /* curses.c */
 void curses_display_init(DisplayState *ds, int full_screen);
 
 /* x_keymap.c */
 extern uint8_t _translate_keycode(const int key);
-
-/* FIXME: term_printf et al should probably go elsewhere so everything
-   does not need to include console.h  */
-/* monitor.c */
-void monitor_init(CharDriverState *hd, int show_banner);
-void term_puts(const char *str);
-void term_vprintf(const char *fmt, va_list ap);
-void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
-void term_print_filename(const char *filename);
-void term_flush(void);
-void term_print_help(void);
-void monitor_suspend(void);
-void monitor_resume(void);
-
-#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);
-
-extern int completion_index;
-void add_completion(const char *str);
-void readline_handle_byte(int ch);
-void readline_find_completion(const char *cmdline);
-const char *readline_get_history(unsigned int index);
-void readline_start(const char *prompt, int is_password,
-                    ReadLineFunc *readline_func, void *opaque);
-void readline_show_prompt(void);
-
 #endif
diff --git a/disas.c b/disas.c
index a8cd11c..6bf7592 100644
--- a/disas.c
+++ b/disas.c
@@ -308,8 +308,7 @@ const char *lookup_symbol(target_ulong orig_addr)
 
 #if !defined(CONFIG_USER_ONLY)
 
-void term_vprintf(const char *fmt, va_list ap);
-void term_printf(const char *fmt, ...);
+#include "monitor.h"
 
 static int monitor_disas_is_physical;
 static CPUState *monitor_disas_env;
@@ -330,19 +329,19 @@ static int monitor_fprintf(FILE *stream, const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
-    term_vprintf(fmt, ap);
+    monitor_vprintf((Monitor *)stream, fmt, ap);
     va_end(ap);
     return 0;
 }
 
-void monitor_disas(CPUState *env,
+void monitor_disas(Monitor *mon, CPUState *env,
                    target_ulong pc, int nb_insn, int is_physical, int flags)
 {
     int count, i;
     struct disassemble_info disasm_info;
     int (*print_insn)(bfd_vma pc, disassemble_info *info);
 
-    INIT_DISASSEMBLE_INFO(disasm_info, NULL, monitor_fprintf);
+    INIT_DISASSEMBLE_INFO(disasm_info, (FILE *)mon, monitor_fprintf);
 
     monitor_disas_env = env;
     monitor_disas_is_physical = is_physical;
@@ -388,15 +387,15 @@ void monitor_disas(CPUState *env,
     print_insn = print_insn_little_mips;
 #endif
 #else
-    term_printf("0x" TARGET_FMT_lx
-		": Asm output not supported on this arch\n", pc);
+    monitor_printf(mon, "0x" TARGET_FMT_lx
+                   ": Asm output not supported on this arch\n", pc);
     return;
 #endif
 
     for(i = 0; i < nb_insn; i++) {
-	term_printf("0x" TARGET_FMT_lx ":  ", pc);
+	monitor_printf(mon, "0x" TARGET_FMT_lx ":  ", pc);
 	count = print_insn(pc, &disasm_info);
-	term_printf("\n");
+	monitor_printf(mon, "\n");
 	if (count < 0)
 	    break;
         pc += count;
diff --git a/disas.h b/disas.h
index 13c2aa3..0789b57 100644
--- a/disas.h
+++ b/disas.h
@@ -1,11 +1,17 @@
 #ifndef _QEMU_DISAS_H
 #define _QEMU_DISAS_H
 
+#include "qemu-common.h"
+
 /* Disassemble this for me please... (debugging). */
 void disas(FILE *out, void *code, unsigned long size);
 void target_disas(FILE *out, target_ulong code, target_ulong size, int flags);
-void monitor_disas(CPUState *env,
+
+/* The usual mess... FIXME: Remove this condition once dyngen-exec.h is gone */
+#ifndef __DYNGEN_EXEC_H__
+void monitor_disas(Monitor *mon, CPUState *env,
                    target_ulong pc, int nb_insn, int is_physical, int flags);
+#endif
 
 /* Look up symbol for debugging purpose.  Returns "" if unknown. */
 const char *lookup_symbol(target_ulong orig_addr);
diff --git a/hw/an5206.c b/hw/an5206.c
index 419d416..83078aa 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -7,6 +7,7 @@
  */
 
 #include "hw.h"
+#include "pc.h"
 #include "mcf.h"
 #include "sysemu.h"
 #include "boards.h"
@@ -16,11 +17,11 @@
 #define AN5206_RAMBAR_ADDR 0x20000000
 
 /* Stub functions for hardware that doesn't exist.  */
-void pic_info(void)
+void pic_info(Monitor *mon)
 {
 }
 
-void irq_info(void)
+void irq_info(Monitor *mon)
 {
 }
 
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index 1fe55b7..c9f3cad 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -8,14 +8,15 @@
  */
 
 #include "hw.h"
+#include "pc.h"
 #include "arm-misc.h"
 
 /* Stub functions for hardware that doesn't exist.  */
-void pic_info(void)
+void pic_info(Monitor *mon)
 {
 }
 
-void irq_info(void)
+void irq_info(Monitor *mon)
 {
 }
 
diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c
index 7aa0568..f32b302 100644
--- a/hw/etraxfs_pic.c
+++ b/hw/etraxfs_pic.c
@@ -24,6 +24,7 @@
 
 #include <stdio.h>
 #include "hw.h"
+#include "pc.h"
 #include "etraxfs.h"
 
 #define D(x)
@@ -135,11 +136,11 @@ static CPUWriteMemoryFunc *pic_write[] = {
 	&pic_writel,
 };
 
-void pic_info(void)
+void pic_info(Monitor *mon)
 {
 }
 
-void irq_info(void)
+void irq_info(Monitor *mon)
 {
 }
 
diff --git a/hw/i8259.c b/hw/i8259.c
index 933289b..f813525 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -24,7 +24,7 @@
 #include "hw.h"
 #include "pc.h"
 #include "isa.h"
-#include "console.h"
+#include "monitor.h"
 
 /* debug PIC */
 //#define DEBUG_PIC
@@ -511,7 +511,7 @@ static void pic_init1(int io_addr, int elcr_addr, PicState *s)
     qemu_register_reset(pic_reset, s);
 }
 
-void pic_info(void)
+void pic_info(Monitor *mon)
 {
     int i;
     PicState *s;
@@ -521,26 +521,27 @@ void pic_info(void)
 
     for(i=0;i<2;i++) {
         s = &isa_pic->pics[i];
-        term_printf("pic%d: irr=%02x imr=%02x isr=%02x hprio=%d irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
-                    i, s->irr, s->imr, s->isr, s->priority_add,
-                    s->irq_base, s->read_reg_select, s->elcr,
-                    s->special_fully_nested_mode);
+        monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d "
+                       "irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
+                       i, s->irr, s->imr, s->isr, s->priority_add,
+                       s->irq_base, s->read_reg_select, s->elcr,
+                       s->special_fully_nested_mode);
     }
 }
 
-void irq_info(void)
+void irq_info(Monitor *mon)
 {
 #ifndef DEBUG_IRQ_COUNT
-    term_printf("irq statistic code not compiled.\n");
+    monitor_printf(mon, "irq statistic code not compiled.\n");
 #else
     int i;
     int64_t count;
 
-    term_printf("IRQ statistics:\n");
+    monitor_printf(mon, "IRQ statistics:\n");
     for (i = 0; i < 16; i++) {
         count = irq_count[i];
         if (count > 0)
-            term_printf("%2d: %" PRId64 "\n", i, count);
+            monitor_printf(mon, "%2d: %" PRId64 "\n", i, count);
     }
 #endif
 }
diff --git a/hw/pc.c b/hw/pc.c
index 57ba803..63a53ce 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -31,7 +31,7 @@
 #include "net.h"
 #include "smbus.h"
 #include "boards.h"
-#include "console.h"
+#include "monitor.h"
 #include "fw_cfg.h"
 #include "virtio-blk.h"
 #include "virtio-balloon.h"
@@ -204,6 +204,7 @@ static int boot_device2nibble(char boot_device)
  and used there as well */
 static int pc_boot_set(void *opaque, const char *boot_device)
 {
+    Monitor *mon = cur_mon;
 #define PC_MAX_BOOT_DEVICES 3
     RTCState *s = (RTCState *)opaque;
     int nbds, bds[3] = { 0, };
@@ -211,14 +212,14 @@ static int pc_boot_set(void *opaque, const char *boot_device)
 
     nbds = strlen(boot_device);
     if (nbds > PC_MAX_BOOT_DEVICES) {
-        term_printf("Too many boot devices for PC\n");
+        monitor_printf(mon, "Too many boot devices for PC\n");
         return(1);
     }
     for (i = 0; i < nbds; i++) {
         bds[i] = boot_device2nibble(boot_device[i]);
         if (bds[i] == 0) {
-            term_printf("Invalid boot device for PC: '%c'\n",
-                    boot_device[i]);
+            monitor_printf(mon, "Invalid boot device for PC: '%c'\n",
+                           boot_device[i]);
             return(1);
         }
     }
diff --git a/hw/pc.h b/hw/pc.h
index 7f21144..a97ebd5 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -1,5 +1,8 @@
 #ifndef HW_PC_H
 #define HW_PC_H
+
+#include "qemu-common.h"
+
 /* PC-style peripherals (also used by other machines).  */
 
 /* serial.c */
@@ -34,8 +37,8 @@ void pic_set_alt_irq_func(PicState2 *s, SetIRQFunc *alt_irq_func,
 int pic_read_irq(PicState2 *s);
 void pic_update_irq(PicState2 *s);
 uint32_t pic_intack_read(PicState2 *s);
-void pic_info(void);
-void irq_info(void);
+void pic_info(Monitor *mon);
+void irq_info(Monitor *mon);
 
 /* APIC */
 typedef struct IOAPICState IOAPICState;
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 6286764..a01efe0 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -28,7 +28,7 @@
 #include "net.h"
 #include "sysemu.h"
 #include "pc.h"
-#include "console.h"
+#include "monitor.h"
 #include "block_int.h"
 #include "virtio-blk.h"
 
@@ -43,7 +43,7 @@ static PCIDevice *qemu_pci_hot_add_nic(PCIBus *pci_bus, const char *opts)
     return pci_nic_init (pci_bus, &nd_table[ret], -1, "rtl8139");
 }
 
-void drive_hot_add(const char *pci_addr, const char *opts)
+void drive_hot_add(Monitor *mon, const char *pci_addr, const char *opts)
 {
     int dom, pci_bus;
     unsigned slot;
@@ -52,13 +52,13 @@ void drive_hot_add(const char *pci_addr, const char *opts)
     PCIDevice *dev;
 
     if (pci_read_devaddr(pci_addr, &dom, &pci_bus, &slot)) {
-        term_printf("Invalid pci address\n");
+        monitor_printf(mon, "Invalid pci address\n");
         return;
     }
 
     dev = pci_find_device(pci_bus, slot, 0);
     if (!dev) {
-        term_printf("no pci device with address %s\n", pci_addr);
+        monitor_printf(mon, "no pci device with address %s\n", pci_addr);
         return;
     }
 
@@ -75,16 +75,18 @@ void drive_hot_add(const char *pci_addr, const char *opts)
                          drives_table[drive_idx].unit);
         break;
     default:
-        term_printf("Can't hot-add drive to type %d\n", type);
+        monitor_printf(mon, "Can't hot-add drive to type %d\n", type);
     }
 
     if (success)
-        term_printf("OK bus %d, unit %d\n", drives_table[drive_idx].bus,
-                                            drives_table[drive_idx].unit);
+        monitor_printf(mon, "OK bus %d, unit %d\n",
+                       drives_table[drive_idx].bus,
+                       drives_table[drive_idx].unit);
     return;
 }
 
-static PCIDevice *qemu_pci_hot_add_storage(PCIBus *pci_bus, const char *opts)
+static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, PCIBus *pci_bus,
+                                           const char *opts)
 {
     void *opaque = NULL;
     int type = -1, drive_idx = -1;
@@ -97,7 +99,7 @@ static PCIDevice *qemu_pci_hot_add_storage(PCIBus *pci_bus, const char *opts)
             type = IF_VIRTIO;
         }
     } else {
-        term_printf("no if= specified\n");
+        monitor_printf(mon, "no if= specified\n");
         return NULL;
     }
 
@@ -106,7 +108,7 @@ static PCIDevice *qemu_pci_hot_add_storage(PCIBus *pci_bus, const char *opts)
         if (drive_idx < 0)
             return NULL;
     } else if (type == IF_VIRTIO) {
-        term_printf("virtio requires a backing file/device.\n");
+        monitor_printf(mon, "virtio requires a backing file/device.\n");
         return NULL;
     }
 
@@ -121,13 +123,14 @@ static PCIDevice *qemu_pci_hot_add_storage(PCIBus *pci_bus, const char *opts)
         opaque = virtio_blk_init (pci_bus, drives_table[drive_idx].bdrv);
         break;
     default:
-        term_printf ("type %s not a hotpluggable PCI device.\n", buf);
+        monitor_printf(mon, "type %s not a hotpluggable PCI device.\n", buf);
     }
 
     return opaque;
 }
 
-void pci_device_hot_add(const char *pci_addr, const char *type, const char *opts)
+void pci_device_hot_add(Monitor *mon, const char *pci_addr, const char *type,
+                        const char *opts)
 {
     PCIDevice *dev = NULL;
     PCIBus *pci_bus;
@@ -135,47 +138,47 @@ void pci_device_hot_add(const char *pci_addr, const char *type, const char *opts
     unsigned slot;
 
     if (pci_assign_devaddr(pci_addr, &dom, &bus, &slot)) {
-        term_printf("Invalid pci address\n");
+        monitor_printf(mon, "Invalid pci address\n");
         return;
     }
 
     pci_bus = pci_find_bus(bus);
     if (!pci_bus) {
-        term_printf("Can't find pci_bus %d\n", bus);
+        monitor_printf(mon, "Can't find pci_bus %d\n", bus);
         return;
     }
 
     if (strcmp(type, "nic") == 0)
         dev = qemu_pci_hot_add_nic(pci_bus, opts);
     else if (strcmp(type, "storage") == 0)
-        dev = qemu_pci_hot_add_storage(pci_bus, opts);
+        dev = qemu_pci_hot_add_storage(mon, pci_bus, opts);
     else
-        term_printf("invalid type: %s\n", type);
+        monitor_printf(mon, "invalid type: %s\n", type);
 
     if (dev) {
         qemu_system_device_hot_add(bus, PCI_SLOT(dev->devfn), 1);
-        term_printf("OK domain %d, bus %d, slot %d, function %d\n",
-                    0, pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
-                    PCI_FUNC(dev->devfn));
+        monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
+                       0, pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
+                       PCI_FUNC(dev->devfn));
     } else
-        term_printf("failed to add %s\n", opts);
+        monitor_printf(mon, "failed to add %s\n", opts);
 }
 #endif
 
-void pci_device_hot_remove(const char *pci_addr)
+void pci_device_hot_remove(Monitor *mon, const char *pci_addr)
 {
     PCIDevice *d;
     int dom, bus;
     unsigned slot;
 
     if (pci_read_devaddr(pci_addr, &dom, &bus, &slot)) {
-        term_printf("Invalid pci address\n");
+        monitor_printf(mon, "Invalid pci address\n");
         return;
     }
 
     d = pci_find_device(bus, slot, 0);
     if (!d) {
-        term_printf("slot %d empty\n", slot);
+        monitor_printf(mon, "slot %d empty\n", slot);
         return;
     }
 
@@ -199,7 +202,7 @@ void pci_device_hot_remove_success(int pcibus, int slot)
     int class_code;
 
     if (!d) {
-        term_printf("invalid slot %d\n", slot);
+        monitor_printf(cur_mon, "invalid slot %d\n", slot);
         return;
     }
 
diff --git a/hw/pci.c b/hw/pci.c
index 97918a3..18362d3 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -23,7 +23,7 @@
  */
 #include "hw.h"
 #include "pci.h"
-#include "console.h"
+#include "monitor.h"
 #include "net.h"
 #include "virtio-net.h"
 #include "sysemu.h"
@@ -705,42 +705,44 @@ static const pci_class_desc pci_class_descriptions[] =
 
 static void pci_info_device(PCIDevice *d)
 {
+    Monitor *mon = cur_mon;
     int i, class;
     PCIIORegion *r;
     const pci_class_desc *desc;
 
-    term_printf("  Bus %2d, device %3d, function %d:\n",
-           d->bus->bus_num, d->devfn >> 3, d->devfn & 7);
+    monitor_printf(mon, "  Bus %2d, device %3d, function %d:\n",
+                   d->bus->bus_num, d->devfn >> 3, d->devfn & 7);
     class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
-    term_printf("    ");
+    monitor_printf(mon, "    ");
     desc = pci_class_descriptions;
     while (desc->desc && class != desc->class)
         desc++;
     if (desc->desc) {
-        term_printf("%s", desc->desc);
+        monitor_printf(mon, "%s", desc->desc);
     } else {
-        term_printf("Class %04x", class);
+        monitor_printf(mon, "Class %04x", class);
     }
-    term_printf(": PCI device %04x:%04x\n",
+    monitor_printf(mon, ": PCI device %04x:%04x\n",
            le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
            le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))));
 
     if (d->config[PCI_INTERRUPT_PIN] != 0) {
-        term_printf("      IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]);
+        monitor_printf(mon, "      IRQ %d.\n",
+                       d->config[PCI_INTERRUPT_LINE]);
     }
     if (class == 0x0604) {
-        term_printf("      BUS %d.\n", d->config[0x19]);
+        monitor_printf(mon, "      BUS %d.\n", d->config[0x19]);
     }
     for(i = 0;i < PCI_NUM_REGIONS; i++) {
         r = &d->io_regions[i];
         if (r->size != 0) {
-            term_printf("      BAR%d: ", i);
+            monitor_printf(mon, "      BAR%d: ", i);
             if (r->type & PCI_ADDRESS_SPACE_IO) {
-                term_printf("I/O at 0x%04x [0x%04x].\n",
-                       r->addr, r->addr + r->size - 1);
+                monitor_printf(mon, "I/O at 0x%04x [0x%04x].\n",
+                               r->addr, r->addr + r->size - 1);
             } else {
-                term_printf("32 bit memory at 0x%08x [0x%08x].\n",
-                       r->addr, r->addr + r->size - 1);
+                monitor_printf(mon, "32 bit memory at 0x%08x [0x%08x].\n",
+                               r->addr, r->addr + r->size - 1);
             }
         }
     }
@@ -766,7 +768,7 @@ void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
     }
 }
 
-void pci_info(void)
+void pci_info(Monitor *mon)
 {
     pci_for_each_device(0, pci_info_device);
 }
diff --git a/hw/pci.h b/hw/pci.h
index 8c301d0..987a8d4 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -1,6 +1,8 @@
 #ifndef QEMU_PCI_H
 #define QEMU_PCI_H
 
+#include "qemu-common.h"
+
 /* PCI includes legacy ISA access.  */
 #include "isa.h"
 
@@ -238,7 +240,7 @@ PCIDevice *pci_find_device(int bus_num, int slot, int function);
 int pci_read_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp);
 int pci_assign_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp);
 
-void pci_info(void);
+void pci_info(Monitor *mon);
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
                         pci_map_irq_fn map_irq, const char *name);
 
diff --git a/hw/pcmcia.h b/hw/pcmcia.h
index 8f8366c..290a76f 100644
--- a/hw/pcmcia.h
+++ b/hw/pcmcia.h
@@ -1,5 +1,7 @@
 /* PCMCIA/Cardbus */
 
+#include "qemu-common.h"
+
 struct pcmcia_socket_s {
     qemu_irq irq;
     int attached;
@@ -9,7 +11,7 @@ struct pcmcia_socket_s {
 
 void pcmcia_socket_register(struct pcmcia_socket_s *socket);
 void pcmcia_socket_unregister(struct pcmcia_socket_s *socket);
-void pcmcia_info(void);
+void pcmcia_info(Monitor *mon);
 
 struct pcmcia_card_s {
     void *state;
diff --git a/hw/shix.c b/hw/shix.c
index ee4f03f..694d91c 100644
--- a/hw/shix.c
+++ b/hw/shix.c
@@ -28,6 +28,7 @@
    More information in target-sh4/README.sh4
 */
 #include "hw.h"
+#include "pc.h"
 #include "sh.h"
 #include "sysemu.h"
 #include "boards.h"
@@ -35,12 +36,12 @@
 #define BIOS_FILENAME "shix_bios.bin"
 #define BIOS_ADDRESS 0xA0000000
 
-void irq_info(void)
+void irq_info(Monitor *mon)
 {
     /* XXXXX */
 }
 
-void pic_info(void)
+void pic_info(Monitor *mon)
 {
     /* XXXXX */
 }
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index ff8f0c7..3868692 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -23,7 +23,7 @@
  */
 #include "hw.h"
 #include "sun4m.h"
-#include "console.h"
+#include "monitor.h"
 
 //#define DEBUG_IRQ_COUNT
 //#define DEBUG_IRQ
@@ -219,33 +219,33 @@ static CPUWriteMemoryFunc *slavio_intctlm_mem_write[3] = {
     slavio_intctlm_mem_writel,
 };
 
-void slavio_pic_info(void *opaque)
+void slavio_pic_info(Monitor *mon, void *opaque)
 {
     SLAVIO_INTCTLState *s = opaque;
     int i;
 
     for (i = 0; i < MAX_CPUS; i++) {
-        term_printf("per-cpu %d: pending 0x%08x\n", i,
-                    s->slaves[i]->intreg_pending);
+        monitor_printf(mon, "per-cpu %d: pending 0x%08x\n", i,
+                       s->slaves[i]->intreg_pending);
     }
-    term_printf("master: pending 0x%08x, disabled 0x%08x\n",
-                s->intregm_pending, s->intregm_disabled);
+    monitor_printf(mon, "master: pending 0x%08x, disabled 0x%08x\n",
+                   s->intregm_pending, s->intregm_disabled);
 }
 
-void slavio_irq_info(void *opaque)
+void slavio_irq_info(Monitor *mon, void *opaque)
 {
 #ifndef DEBUG_IRQ_COUNT
-    term_printf("irq statistic code not compiled.\n");
+    monitor_printf(mon, "irq statistic code not compiled.\n");
 #else
     SLAVIO_INTCTLState *s = opaque;
     int i;
     int64_t count;
 
-    term_printf("IRQ statistics:\n");
+    monitor_printf(mon, "IRQ statistics:\n");
     for (i = 0; i < 32; i++) {
         count = s->irq_count[i];
         if (count > 0)
-            term_printf("%2d: %" PRId64 "\n", i, count);
+            monitor_printf(mon, "%2d: %" PRId64 "\n", i, count);
     }
 #endif
 }
diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c
index 1759157..33df653 100644
--- a/hw/sun4c_intctl.c
+++ b/hw/sun4c_intctl.c
@@ -23,7 +23,7 @@
  */
 #include "hw.h"
 #include "sun4m.h"
-#include "console.h"
+#include "monitor.h"
 //#define DEBUG_IRQ_COUNT
 //#define DEBUG_IRQ
 
@@ -90,26 +90,26 @@ static CPUWriteMemoryFunc *sun4c_intctl_mem_write[3] = {
     NULL,
 };
 
-void sun4c_pic_info(void *opaque)
+void sun4c_pic_info(Monitor *mon, void *opaque)
 {
     Sun4c_INTCTLState *s = opaque;
 
-    term_printf("master: pending 0x%2.2x, enabled 0x%2.2x\n", s->pending,
-                s->reg);
+    monitor_printf(mon, "master: pending 0x%2.2x, enabled 0x%2.2x\n",
+                   s->pending, s->reg);
 }
 
-void sun4c_irq_info(void *opaque)
+void sun4c_irq_info(Monitor *mon, void *opaque)
 {
 #ifndef DEBUG_IRQ_COUNT
-    term_printf("irq statistic code not compiled.\n");
+    monitor_printf(mon, "irq statistic code not compiled.\n");
 #else
     Sun4c_INTCTLState *s = opaque;
     int64_t count;
 
-    term_printf("IRQ statistics:\n");
+    monitor_printf(mon, "IRQ statistics:\n");
     count = s->irq_count[i];
     if (count > 0)
-        term_printf("%2d: %" PRId64 "\n", i, count);
+        monitor_printf(mon, "%2d: %" PRId64 "\n", i, count);
 #endif
 }
 
diff --git a/hw/sun4m.c b/hw/sun4m.c
index bae8803..21667c0 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -283,16 +283,16 @@ static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
 
 static void *slavio_intctl;
 
-void pic_info(void)
+void pic_info(Monitor *mon)
 {
     if (slavio_intctl)
-        slavio_pic_info(slavio_intctl);
+        slavio_pic_info(mon, slavio_intctl);
 }
 
-void irq_info(void)
+void irq_info(Monitor *mon)
 {
     if (slavio_intctl)
-        slavio_irq_info(slavio_intctl);
+        slavio_irq_info(mon, slavio_intctl);
 }
 
 void cpu_check_irqs(CPUState *env)
diff --git a/hw/sun4m.h b/hw/sun4m.h
index e1fa837..219aaef 100644
--- a/hw/sun4m.h
+++ b/hw/sun4m.h
@@ -1,6 +1,8 @@
 #ifndef SUN4M_H
 #define SUN4M_H
 
+#include "qemu-common.h"
+
 /* Devices used by sparc32 system.  */
 
 /* iommu.c */
@@ -31,8 +33,8 @@ void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg,
                          const uint32_t *intbit_to_level,
                          qemu_irq **irq, qemu_irq **cpu_irq,
                          qemu_irq **parent_irq, unsigned int cputimer);
-void slavio_pic_info(void *opaque);
-void slavio_irq_info(void *opaque);
+void slavio_pic_info(Monitor *mon, void *opaque);
+void slavio_irq_info(Monitor *mon, void *opaque);
 
 /* sbi.c */
 void *sbi_init(target_phys_addr_t addr, qemu_irq **irq, qemu_irq **cpu_irq,
@@ -41,8 +43,8 @@ void *sbi_init(target_phys_addr_t addr, qemu_irq **irq, qemu_irq **cpu_irq,
 /* sun4c_intctl.c */
 void *sun4c_intctl_init(target_phys_addr_t addr, qemu_irq **irq,
                         qemu_irq *parent_irq);
-void sun4c_pic_info(void *opaque);
-void sun4c_irq_info(void *opaque);
+void sun4c_pic_info(Monitor *mon, void *opaque);
+void sun4c_irq_info(Monitor *mon, void *opaque);
 
 /* slavio_timer.c */
 void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq,
diff --git a/hw/usb.h b/hw/usb.h
index a5e0d44..3ecb7d6 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -244,7 +244,7 @@ USBDevice *usb_hub_init(int nb_ports);
 /* usb-linux.c */
 USBDevice *usb_host_device_open(const char *devname);
 int usb_host_device_close(const char *devname);
-void usb_host_info(void);
+void usb_host_info(Monitor *mon);
 
 /* usb-hid.c */
 USBDevice *usb_mouse_init(void);
diff --git a/migration-exec.c b/migration-exec.c
index 6ed322a..e2e6e89 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -18,7 +18,7 @@
 #include "migration.h"
 #include "qemu-char.h"
 #include "sysemu.h"
-#include "console.h"
+#include "monitor.h"
 #include "buffered_file.h"
 #include "block.h"
 
@@ -94,7 +94,7 @@ MigrationState *exec_start_outgoing_migration(const char *command,
 
     if (s->detach == 1) {
         dprintf("detaching from monitor\n");
-        monitor_suspend();
+        monitor_suspend(cur_mon);
         s->detach = 2;
     }
 
diff --git a/migration-tcp.c b/migration-tcp.c
index 3f5b104..7f67fd9 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -16,7 +16,7 @@
 #include "migration.h"
 #include "qemu-char.h"
 #include "sysemu.h"
-#include "console.h"
+#include "monitor.h"
 #include "buffered_file.h"
 #include "block.h"
 
@@ -110,7 +110,7 @@ MigrationState *tcp_start_outgoing_migration(const char *host_port,
 
     if (s->detach == 1) {
         dprintf("detaching from monitor\n");
-        monitor_suspend();
+        monitor_suspend(cur_mon);
         s->detach = 2;
     }
 
diff --git a/migration.c b/migration.c
index 0ef777a..cf69bbe 100644
--- a/migration.c
+++ b/migration.c
@@ -13,7 +13,7 @@
 
 #include "qemu-common.h"
 #include "migration.h"
-#include "console.h"
+#include "monitor.h"
 #include "buffered_file.h"
 #include "sysemu.h"
 #include "block.h"
@@ -48,7 +48,7 @@ void qemu_start_incoming_migration(const char *uri)
         fprintf(stderr, "unknown migration protocol: %s\n", uri);
 }
 
-void do_migrate(int detach, const char *uri)
+void do_migrate(Monitor *mon, int detach, const char *uri)
 {
     MigrationState *s = NULL;
     const char *p;
@@ -60,10 +60,10 @@ void do_migrate(int detach, const char *uri)
         s = exec_start_outgoing_migration(p, max_throttle, detach);
 #endif
     else
-        term_printf("unknown migration protocol: %s\n", uri);
+        monitor_printf(mon, "unknown migration protocol: %s\n", uri);
 
     if (s == NULL)
-        term_printf("migration failed\n");
+        monitor_printf(mon, "migration failed\n");
     else {
         if (current_migration)
             current_migration->release(current_migration);
@@ -72,7 +72,7 @@ void do_migrate(int detach, const char *uri)
     }
 }
 
-void do_migrate_cancel(void)
+void do_migrate_cancel(Monitor *mon)
 {
     MigrationState *s = current_migration;
 
@@ -80,7 +80,7 @@ void do_migrate_cancel(void)
         s->cancel(s);
 }
 
-void do_migrate_set_speed(const char *value)
+void do_migrate_set_speed(Monitor *mon, const char *value)
 {
     double d;
     char *ptr;
@@ -100,24 +100,24 @@ void do_migrate_set_speed(const char *value)
     max_throttle = (uint32_t)d;
 }
 
-void do_info_migrate(void)
+void do_info_migrate(Monitor *mon)
 {
     MigrationState *s = current_migration;
-    
+
     if (s) {
-        term_printf("Migration status: ");
+        monitor_printf(mon, "Migration status: ");
         switch (s->get_status(s)) {
         case MIG_STATE_ACTIVE:
-            term_printf("active\n");
+            monitor_printf(mon, "active\n");
             break;
         case MIG_STATE_COMPLETED:
-            term_printf("completed\n");
+            monitor_printf(mon, "completed\n");
             break;
         case MIG_STATE_ERROR:
-            term_printf("failed\n");
+            monitor_printf(mon, "failed\n");
             break;
         case MIG_STATE_CANCELLED:
-            term_printf("cancelled\n");
+            monitor_printf(mon, "cancelled\n");
             break;
         }
     }
@@ -146,7 +146,7 @@ void migrate_fd_cleanup(FdMigrationState *s)
 
     /* Don't resume monitor until we've flushed all of the buffers */
     if (s->detach == 2) {
-        monitor_resume();
+        monitor_resume(cur_mon);
         s->detach = 0;
     }
 
diff --git a/migration.h b/migration.h
index d9771ad..32f5a72 100644
--- a/migration.h
+++ b/migration.h
@@ -14,6 +14,8 @@
 #ifndef QEMU_MIGRATION_H
 #define QEMU_MIGRATION_H
 
+#include "qemu-common.h"
+
 #define MIG_STATE_ERROR		-1
 #define MIG_STATE_COMPLETED	0
 #define MIG_STATE_CANCELLED	1
@@ -47,13 +49,13 @@ struct FdMigrationState
 
 void qemu_start_incoming_migration(const char *uri);
 
-void do_migrate(int detach, const char *uri);
+void do_migrate(Monitor *mon, int detach, const char *uri);
 
-void do_migrate_cancel(void);
+void do_migrate_cancel(Monitor *mon);
 
-void do_migrate_set_speed(const char *value);
+void do_migrate_set_speed(Monitor *mon, const char *value);
 
-void do_info_migrate(void);
+void do_info_migrate(Monitor *mon);
 
 int exec_start_incoming_migration(const char *host_port);
 
diff --git a/monitor.c b/monitor.c
index 2dd1c19..2936222 100644
--- a/monitor.c
+++ b/monitor.c
@@ -30,6 +30,8 @@
 #include "net.h"
 #include "qemu-char.h"
 #include "sysemu.h"
+#include "monitor.h"
+#include "readline.h"
 #include "console.h"
 #include "block.h"
 #include "audio/audio.h"
@@ -57,36 +59,39 @@
  *
  */
 
-typedef struct term_cmd_t {
+typedef struct mon_cmd_t {
     const char *name;
     const char *args_type;
     void *handler;
     const char *params;
     const char *help;
-} term_cmd_t;
+} mon_cmd_t;
 
 #define MAX_MON 4
 static CharDriverState *monitor_hd[MAX_MON];
 static int hide_banner;
 
-static const term_cmd_t term_cmds[];
-static const term_cmd_t info_cmds[];
+static const mon_cmd_t mon_cmds[];
+static const mon_cmd_t info_cmds[];
 
 static uint8_t term_outbuf[1024];
 static int term_outbuf_index;
 static BlockDriverCompletionFunc *password_completion_cb;
 static void *password_opaque;
 
+Monitor *cur_mon;
+
 static void monitor_start_input(void);
 
 static CPUState *mon_cpu = NULL;
 
-static void monitor_read_password(ReadLineFunc *readline_func, void *opaque)
+static void monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
+                                  void *opaque)
 {
     readline_start("Password: ", 1, readline_func, opaque);
 }
 
-void term_flush(void)
+void monitor_flush(Monitor *mon)
 {
     int i;
     if (term_outbuf_index > 0) {
@@ -98,7 +103,7 @@ void term_flush(void)
 }
 
 /* flush at every end of line or if the buffer is full */
-void term_puts(const char *str)
+static void monitor_puts(Monitor *mon, const char *str)
 {
     char c;
     for(;;) {
@@ -110,26 +115,26 @@ void term_puts(const char *str)
         term_outbuf[term_outbuf_index++] = c;
         if (term_outbuf_index >= (sizeof(term_outbuf) - 1) ||
             c == '\n')
-            term_flush();
+            monitor_flush(mon);
     }
 }
 
-void term_vprintf(const char *fmt, va_list ap)
+void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
 {
     char buf[4096];
     vsnprintf(buf, sizeof(buf), fmt, ap);
-    term_puts(buf);
+    monitor_puts(mon, buf);
 }
 
-void term_printf(const char *fmt, ...)
+void monitor_printf(Monitor *mon, const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
-    term_vprintf(fmt, ap);
+    monitor_vprintf(mon, fmt, ap);
     va_end(ap);
 }
 
-void term_print_filename(const char *filename)
+void monitor_print_filename(Monitor *mon, const char *filename)
 {
     int i;
 
@@ -138,19 +143,19 @@ void term_print_filename(const char *filename)
 	case ' ':
 	case '"':
 	case '\\':
-	    term_printf("\\%c", filename[i]);
+	    monitor_printf(mon, "\\%c", filename[i]);
 	    break;
 	case '\t':
-	    term_printf("\\t");
+	    monitor_printf(mon, "\\t");
 	    break;
 	case '\r':
-	    term_printf("\\r");
+	    monitor_printf(mon, "\\r");
 	    break;
 	case '\n':
-	    term_printf("\\n");
+	    monitor_printf(mon, "\\n");
 	    break;
 	default:
-	    term_printf("%c", filename[i]);
+	    monitor_printf(mon, "%c", filename[i]);
 	    break;
 	}
     }
@@ -160,7 +165,7 @@ static int monitor_fprintf(FILE *stream, const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
-    term_vprintf(fmt, ap);
+    monitor_vprintf((Monitor *)stream, fmt, ap);
     va_end(ap);
     return 0;
 }
@@ -185,39 +190,36 @@ static int compare_cmd(const char *name, const char *list)
     return 0;
 }
 
-static void help_cmd1(const term_cmd_t *cmds, const char *prefix, const char *name)
+static void help_cmd_dump(Monitor *mon, const mon_cmd_t *cmds,
+                          const char *prefix, const char *name)
 {
-    const term_cmd_t *cmd;
+    const mon_cmd_t *cmd;
 
     for(cmd = cmds; cmd->name != NULL; cmd++) {
         if (!name || !strcmp(name, cmd->name))
-            term_printf("%s%s %s -- %s\n", prefix, cmd->name, cmd->params, cmd->help);
+            monitor_printf(mon, "%s%s %s -- %s\n", prefix, cmd->name,
+                           cmd->params, cmd->help);
     }
 }
 
-static void help_cmd(const char *name)
+static void help_cmd(Monitor *mon, const char *name)
 {
     if (name && !strcmp(name, "info")) {
-        help_cmd1(info_cmds, "info ", NULL);
+        help_cmd_dump(mon, info_cmds, "info ", NULL);
     } else {
-        help_cmd1(term_cmds, "", name);
+        help_cmd_dump(mon, mon_cmds, "", name);
         if (name && !strcmp(name, "log")) {
             const CPULogItem *item;
-            term_printf("Log items (comma separated):\n");
-            term_printf("%-10s %s\n", "none", "remove all logs");
+            monitor_printf(mon, "Log items (comma separated):\n");
+            monitor_printf(mon, "%-10s %s\n", "none", "remove all logs");
             for(item = cpu_log_items; item->mask != 0; item++) {
-                term_printf("%-10s %s\n", item->name, item->help);
+                monitor_printf(mon, "%-10s %s\n", item->name, item->help);
             }
         }
     }
 }
 
-static void do_help(const char *name)
-{
-    help_cmd(name);
-}
-
-static void do_commit(const char *device)
+static void do_commit(Monitor *mon, const char *device)
 {
     int i, all_devices;
 
@@ -229,10 +231,10 @@ static void do_commit(const char *device)
     }
 }
 
-static void do_info(const char *item)
+static void do_info(Monitor *mon, const char *item)
 {
-    const term_cmd_t *cmd;
-    void (*handler)(void);
+    const mon_cmd_t *cmd;
+    void (*handler)(Monitor *);
 
     if (!item)
         goto help;
@@ -241,48 +243,39 @@ static void do_info(const char *item)
             goto found;
     }
  help:
-    help_cmd("info");
+    help_cmd(mon, "info");
     return;
  found:
     handler = cmd->handler;
-    handler();
+    handler(mon);
 }
 
-static void do_info_version(void)
+static void do_info_version(Monitor *mon)
 {
-  term_printf("%s\n", QEMU_VERSION);
+    monitor_printf(mon, "%s\n", QEMU_VERSION);
 }
 
-static void do_info_name(void)
+static void do_info_name(Monitor *mon)
 {
     if (qemu_name)
-        term_printf("%s\n", qemu_name);
+        monitor_printf(mon, "%s\n", qemu_name);
 }
 
 #if defined(TARGET_I386)
-static void do_info_hpet(void)
+static void do_info_hpet(Monitor *mon)
 {
-    term_printf("HPET is %s by QEMU\n", (no_hpet) ? "disabled" : "enabled");
+    monitor_printf(mon, "HPET is %s by QEMU\n",
+                   (no_hpet) ? "disabled" : "enabled");
 }
 #endif
 
-static void do_info_uuid(void)
-{
-    term_printf(UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
-            qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
-            qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
-            qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
-            qemu_uuid[15]);
-}
-
-static void do_info_block(void)
-{
-    bdrv_info();
-}
-
-static void do_info_blockstats(void)
+static void do_info_uuid(Monitor *mon)
 {
-    bdrv_info_stats();
+    monitor_printf(mon, UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1],
+                   qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], qemu_uuid[5],
+                   qemu_uuid[6], qemu_uuid[7], qemu_uuid[8], qemu_uuid[9],
+                   qemu_uuid[10], qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
+                   qemu_uuid[14], qemu_uuid[15]);
 }
 
 /* get the current CPU defined by the user */
@@ -307,22 +300,22 @@ static CPUState *mon_get_cpu(void)
     return mon_cpu;
 }
 
-static void do_info_registers(void)
+static void do_info_registers(Monitor *mon)
 {
     CPUState *env;
     env = mon_get_cpu();
     if (!env)
         return;
 #ifdef TARGET_I386
-    cpu_dump_state(env, NULL, monitor_fprintf,
+    cpu_dump_state(env, (FILE *)mon, monitor_fprintf,
                    X86_DUMP_FPU);
 #else
-    cpu_dump_state(env, NULL, monitor_fprintf,
+    cpu_dump_state(env, (FILE *)mon, monitor_fprintf,
                    0);
 #endif
 }
 
-static void do_info_cpus(void)
+static void do_info_cpus(Monitor *mon)
 {
     CPUState *env;
 
@@ -330,36 +323,38 @@ static void do_info_cpus(void)
     mon_get_cpu();
 
     for(env = first_cpu; env != NULL; env = env->next_cpu) {
-        term_printf("%c CPU #%d:",
-                    (env == mon_cpu) ? '*' : ' ',
-                    env->cpu_index);
+        monitor_printf(mon, "%c CPU #%d:",
+                       (env == mon_cpu) ? '*' : ' ',
+                       env->cpu_index);
 #if defined(TARGET_I386)
-        term_printf(" pc=0x" TARGET_FMT_lx, env->eip + env->segs[R_CS].base);
+        monitor_printf(mon, " pc=0x" TARGET_FMT_lx,
+                       env->eip + env->segs[R_CS].base);
 #elif defined(TARGET_PPC)
-        term_printf(" nip=0x" TARGET_FMT_lx, env->nip);
+        monitor_printf(mon, " nip=0x" TARGET_FMT_lx, env->nip);
 #elif defined(TARGET_SPARC)
-        term_printf(" pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx, env->pc, env->npc);
+        monitor_printf(mon, " pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx,
+                       env->pc, env->npc);
 #elif defined(TARGET_MIPS)
-        term_printf(" PC=0x" TARGET_FMT_lx, env->active_tc.PC);
+        monitor_printf(mon, " PC=0x" TARGET_FMT_lx, env->active_tc.PC);
 #endif
         if (env->halted)
-            term_printf(" (halted)");
-        term_printf("\n");
+            monitor_printf(mon, " (halted)");
+        monitor_printf(mon, "\n");
     }
 }
 
-static void do_cpu_set(int index)
+static void do_cpu_set(Monitor *mon, int index)
 {
     if (mon_set_cpu(index) < 0)
-        term_printf("Invalid CPU index\n");
+        monitor_printf(mon, "Invalid CPU index\n");
 }
 
-static void do_info_jit(void)
+static void do_info_jit(Monitor *mon)
 {
-    dump_exec_info(NULL, monitor_fprintf);
+    dump_exec_info((FILE *)mon, monitor_fprintf);
 }
 
-static void do_info_history (void)
+static void do_info_history(Monitor *mon)
 {
     int i;
     const char *str;
@@ -369,37 +364,37 @@ static void do_info_history (void)
         str = readline_get_history(i);
         if (!str)
             break;
-	term_printf("%d: '%s'\n", i, str);
+        monitor_printf(mon, "%d: '%s'\n", i, str);
         i++;
     }
 }
 
 #if defined(TARGET_PPC)
 /* XXX: not implemented in other targets */
-static void do_info_cpu_stats (void)
+static void do_info_cpu_stats(Monitor *mon)
 {
     CPUState *env;
 
     env = mon_get_cpu();
-    cpu_dump_statistics(env, NULL, &monitor_fprintf, 0);
+    cpu_dump_statistics(env, (FILE *)mon, &monitor_fprintf, 0);
 }
 #endif
 
-static void do_quit(void)
+static void do_quit(Monitor *mon)
 {
     exit(0);
 }
 
-static int eject_device(BlockDriverState *bs, int force)
+static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
 {
     if (bdrv_is_inserted(bs)) {
         if (!force) {
             if (!bdrv_is_removable(bs)) {
-                term_printf("device is not removable\n");
+                monitor_printf(mon, "device is not removable\n");
                 return -1;
             }
             if (bdrv_is_locked(bs)) {
-                term_printf("device is locked\n");
+                monitor_printf(mon, "device is locked\n");
                 return -1;
             }
         }
@@ -408,50 +403,52 @@ static int eject_device(BlockDriverState *bs, int force)
     return 0;
 }
 
-static void do_eject(int force, const char *filename)
+static void do_eject(Monitor *mon, int force, const char *filename)
 {
     BlockDriverState *bs;
 
     bs = bdrv_find(filename);
     if (!bs) {
-        term_printf("device not found\n");
+        monitor_printf(mon, "device not found\n");
         return;
     }
-    eject_device(bs, force);
+    eject_device(mon, bs, force);
 }
 
-static void do_change_block(const char *device, const char *filename, const char *fmt)
+static void do_change_block(Monitor *mon, const char *device,
+                            const char *filename, const char *fmt)
 {
     BlockDriverState *bs;
     BlockDriver *drv = NULL;
 
     bs = bdrv_find(device);
     if (!bs) {
-        term_printf("device not found\n");
+        monitor_printf(mon, "device not found\n");
         return;
     }
     if (fmt) {
         drv = bdrv_find_format(fmt);
         if (!drv) {
-            term_printf("invalid format %s\n", fmt);
+            monitor_printf(mon, "invalid format %s\n", fmt);
             return;
         }
     }
-    if (eject_device(bs, 0) < 0)
+    if (eject_device(mon, bs, 0) < 0)
         return;
     bdrv_open2(bs, filename, 0, drv);
-    monitor_read_bdrv_key_start(bs, NULL, NULL);
+    monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
 }
 
-static void change_vnc_password_cb(void *opaque, const char *password)
+static void change_vnc_password_cb(Monitor *mon, const char *password,
+                                   void *opaque)
 {
     if (vnc_display_password(NULL, password) < 0)
-        term_printf("could not set VNC server password\n");
+        monitor_printf(mon, "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(Monitor *mon, const char *target, const char *arg)
 {
     if (strcmp(target, "passwd") == 0 ||
 	strcmp(target, "password") == 0) {
@@ -459,36 +456,37 @@ static void do_change_vnc(const char *target, const char *arg)
             char password[9];
 	    strncpy(password, arg, sizeof(password));
 	    password[sizeof(password) - 1] = '\0';
-            change_vnc_password_cb(NULL, password);
+            change_vnc_password_cb(mon, password, NULL);
         } else {
-            monitor_read_password(change_vnc_password_cb, NULL);
+            monitor_read_password(mon, change_vnc_password_cb, NULL);
         }
     } else {
 	if (vnc_display_open(NULL, target) < 0)
-	    term_printf("could not start VNC server on %s\n", target);
+            monitor_printf(mon, "could not start VNC server on %s\n", target);
     }
 }
 
-static void do_change(const char *device, const char *target, const char *arg)
+static void do_change(Monitor *mon, const char *device, const char *target,
+                      const char *arg)
 {
     if (strcmp(device, "vnc") == 0) {
-	do_change_vnc(target, arg);
+	do_change_vnc(mon, target, arg);
     } else {
-	do_change_block(device, target, arg);
+	do_change_block(mon, device, target, arg);
     }
 }
 
-static void do_screen_dump(const char *filename)
+static void do_screen_dump(Monitor *mon, const char *filename)
 {
     vga_hw_screen_dump(filename);
 }
 
-static void do_logfile(const char *filename)
+static void do_logfile(Monitor *mon, const char *filename)
 {
     cpu_set_log_filename(filename);
 }
 
-static void do_log(const char *items)
+static void do_log(Monitor *mon, const char *items)
 {
     int mask;
 
@@ -497,88 +495,97 @@ static void do_log(const char *items)
     } else {
         mask = cpu_str_to_log_mask(items);
         if (!mask) {
-            help_cmd("log");
+            help_cmd(mon, "log");
             return;
         }
     }
     cpu_set_log(mask);
 }
 
-static void do_stop(void)
+static void do_stop(Monitor *mon)
 {
     vm_stop(EXCP_INTERRUPT);
 }
 
 static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs);
 
-static void do_cont(void)
+struct bdrv_iterate_context {
+    Monitor *mon;
+    int err;
+};
+
+static void do_cont(Monitor *mon)
 {
-    int err = 0;
+    struct bdrv_iterate_context context = { mon, 0 };
 
-    bdrv_iterate(encrypted_bdrv_it, &err);
+    bdrv_iterate(encrypted_bdrv_it, &context);
     /* only resume the vm if all keys are set and valid */
-    if (!err)
+    if (!context.err)
         vm_start();
 }
 
 static void bdrv_key_cb(void *opaque, int err)
 {
+    Monitor *mon = opaque;
+
     /* another key was set successfully, retry to continue */
     if (!err)
-        do_cont();
+        do_cont(mon);
 }
 
 static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
 {
-    int *err = opaque;
+    struct bdrv_iterate_context *context = opaque;
 
-    if (!*err && bdrv_key_required(bs)) {
-        *err = -EBUSY;
-        monitor_read_bdrv_key_start(bs, bdrv_key_cb, NULL);
+    if (!context->err && bdrv_key_required(bs)) {
+        context->err = -EBUSY;
+        monitor_read_bdrv_key_start(context->mon, bs, bdrv_key_cb,
+                                    context->mon);
     }
 }
 
 #ifdef CONFIG_GDBSTUB
-static void do_gdbserver(const char *port)
+static void do_gdbserver(Monitor *mon, const char *port)
 {
     if (!port)
         port = DEFAULT_GDBSTUB_PORT;
     if (gdbserver_start(port) < 0) {
-        qemu_printf("Could not open gdbserver socket on port '%s'\n", port);
+        monitor_printf(mon, "Could not open gdbserver socket on port '%s'\n",
+                       port);
     } else {
-        qemu_printf("Waiting gdb connection on port '%s'\n", port);
+        monitor_printf(mon, "Waiting gdb connection on port '%s'\n", port);
     }
 }
 #endif
 
-static void term_printc(int c)
+static void monitor_printc(Monitor *mon, int c)
 {
-    term_printf("'");
+    monitor_printf(mon, "'");
     switch(c) {
     case '\'':
-        term_printf("\\'");
+        monitor_printf(mon, "\\'");
         break;
     case '\\':
-        term_printf("\\\\");
+        monitor_printf(mon, "\\\\");
         break;
     case '\n':
-        term_printf("\\n");
+        monitor_printf(mon, "\\n");
         break;
     case '\r':
-        term_printf("\\r");
+        monitor_printf(mon, "\\r");
         break;
     default:
         if (c >= 32 && c <= 126) {
-            term_printf("%c", c);
+            monitor_printf(mon, "%c", c);
         } else {
-            term_printf("\\x%02x", c);
+            monitor_printf(mon, "\\x%02x", c);
         }
         break;
     }
-    term_printf("'");
+    monitor_printf(mon, "'");
 }
 
-static void memory_dump(int count, int format, int wsize,
+static void memory_dump(Monitor *mon, int count, int format, int wsize,
                         target_phys_addr_t addr, int is_physical)
 {
     CPUState *env;
@@ -612,7 +619,7 @@ static void memory_dump(int count, int format, int wsize,
             }
         }
 #endif
-        monitor_disas(env, addr, count, is_physical, flags);
+        monitor_disas(mon, env, addr, count, is_physical, flags);
         return;
     }
 
@@ -643,9 +650,9 @@ static void memory_dump(int count, int format, int wsize,
 
     while (len > 0) {
         if (is_physical)
-            term_printf(TARGET_FMT_plx ":", addr);
+            monitor_printf(mon, TARGET_FMT_plx ":", addr);
         else
-            term_printf(TARGET_FMT_lx ":", (target_ulong)addr);
+            monitor_printf(mon, TARGET_FMT_lx ":", (target_ulong)addr);
         l = len;
         if (l > line_size)
             l = line_size;
@@ -656,7 +663,7 @@ static void memory_dump(int count, int format, int wsize,
             if (!env)
                 break;
             if (cpu_memory_rw_debug(env, addr, buf, l, 0) < 0) {
-                term_printf(" Cannot access memory\n");
+                monitor_printf(mon, " Cannot access memory\n");
                 break;
             }
         }
@@ -677,27 +684,27 @@ static void memory_dump(int count, int format, int wsize,
                 v = ldq_raw(buf + i);
                 break;
             }
-            term_printf(" ");
+            monitor_printf(mon, " ");
             switch(format) {
             case 'o':
-                term_printf("%#*" PRIo64, max_digits, v);
+                monitor_printf(mon, "%#*" PRIo64, max_digits, v);
                 break;
             case 'x':
-                term_printf("0x%0*" PRIx64, max_digits, v);
+                monitor_printf(mon, "0x%0*" PRIx64, max_digits, v);
                 break;
             case 'u':
-                term_printf("%*" PRIu64, max_digits, v);
+                monitor_printf(mon, "%*" PRIu64, max_digits, v);
                 break;
             case 'd':
-                term_printf("%*" PRId64, max_digits, v);
+                monitor_printf(mon, "%*" PRId64, max_digits, v);
                 break;
             case 'c':
-                term_printc(v);
+                monitor_printc(mon, v);
                 break;
             }
             i += wsize;
         }
-        term_printf("\n");
+        monitor_printf(mon, "\n");
         addr += l;
         len -= l;
     }
@@ -709,11 +716,11 @@ static void memory_dump(int count, int format, int wsize,
 #define GET_TLONG(h, l) (l)
 #endif
 
-static void do_memory_dump(int count, int format, int size,
+static void do_memory_dump(Monitor *mon, int count, int format, int size,
                            uint32_t addrh, uint32_t addrl)
 {
     target_long addr = GET_TLONG(addrh, addrl);
-    memory_dump(count, format, size, addr, 0);
+    memory_dump(mon, count, format, size, addr, 0);
 }
 
 #if TARGET_PHYS_ADDR_BITS > 32
@@ -722,60 +729,61 @@ static void do_memory_dump(int count, int format, int size,
 #define GET_TPHYSADDR(h, l) (l)
 #endif
 
-static void do_physical_memory_dump(int count, int format, int size,
-                                    uint32_t addrh, uint32_t addrl)
+static void do_physical_memory_dump(Monitor *mon, int count, int format,
+                                    int size, uint32_t addrh, uint32_t addrl)
 
 {
     target_phys_addr_t addr = GET_TPHYSADDR(addrh, addrl);
-    memory_dump(count, format, size, addr, 1);
+    memory_dump(mon, count, format, size, addr, 1);
 }
 
-static void do_print(int count, int format, int size, unsigned int valh, unsigned int vall)
+static void do_print(Monitor *mon, int count, int format, int size,
+                     unsigned int valh, unsigned int vall)
 {
     target_phys_addr_t val = GET_TPHYSADDR(valh, vall);
 #if TARGET_PHYS_ADDR_BITS == 32
     switch(format) {
     case 'o':
-        term_printf("%#o", val);
+        monitor_printf(mon, "%#o", val);
         break;
     case 'x':
-        term_printf("%#x", val);
+        monitor_printf(mon, "%#x", val);
         break;
     case 'u':
-        term_printf("%u", val);
+        monitor_printf(mon, "%u", val);
         break;
     default:
     case 'd':
-        term_printf("%d", val);
+        monitor_printf(mon, "%d", val);
         break;
     case 'c':
-        term_printc(val);
+        monitor_printc(mon, val);
         break;
     }
 #else
     switch(format) {
     case 'o':
-        term_printf("%#" PRIo64, val);
+        monitor_printf(mon, "%#" PRIo64, val);
         break;
     case 'x':
-        term_printf("%#" PRIx64, val);
+        monitor_printf(mon, "%#" PRIx64, val);
         break;
     case 'u':
-        term_printf("%" PRIu64, val);
+        monitor_printf(mon, "%" PRIu64, val);
         break;
     default:
     case 'd':
-        term_printf("%" PRId64, val);
+        monitor_printf(mon, "%" PRId64, val);
         break;
     case 'c':
-        term_printc(val);
+        monitor_printc(mon, val);
         break;
     }
 #endif
-    term_printf("\n");
+    monitor_printf(mon, "\n");
 }
 
-static void do_memory_save(unsigned int valh, unsigned int vall,
+static void do_memory_save(Monitor *mon, unsigned int valh, unsigned int vall,
                            uint32_t size, const char *filename)
 {
     FILE *f;
@@ -790,7 +798,7 @@ static void do_memory_save(unsigned int valh, unsigned int vall,
 
     f = fopen(filename, "wb");
     if (!f) {
-        term_printf("could not open '%s'\n", filename);
+        monitor_printf(mon, "could not open '%s'\n", filename);
         return;
     }
     while (size != 0) {
@@ -805,8 +813,9 @@ static void do_memory_save(unsigned int valh, unsigned int vall,
     fclose(f);
 }
 
-static void do_physical_memory_save(unsigned int valh, unsigned int vall,
-                                    uint32_t size, const char *filename)
+static void do_physical_memory_save(Monitor *mon, unsigned int valh,
+                                    unsigned int vall, uint32_t size,
+                                    const char *filename)
 {
     FILE *f;
     uint32_t l;
@@ -815,7 +824,7 @@ static void do_physical_memory_save(unsigned int valh, unsigned int vall,
 
     f = fopen(filename, "wb");
     if (!f) {
-        term_printf("could not open '%s'\n", filename);
+        monitor_printf(mon, "could not open '%s'\n", filename);
         return;
     }
     while (size != 0) {
@@ -831,7 +840,7 @@ static void do_physical_memory_save(unsigned int valh, unsigned int vall,
     fclose(f);
 }
 
-static void do_sum(uint32_t start, uint32_t size)
+static void do_sum(Monitor *mon, uint32_t start, uint32_t size)
 {
     uint32_t addr;
     uint8_t buf[1];
@@ -844,7 +853,7 @@ static void do_sum(uint32_t start, uint32_t size)
         sum = (sum >> 1) | (sum << 15);
         sum += buf[0];
     }
-    term_printf("%05d\n", sum);
+    monitor_printf(mon, "%05d\n", sum);
 }
 
 typedef struct {
@@ -1027,7 +1036,8 @@ static void release_keys(void *opaque)
     }
 }
 
-static void do_sendkey(const char *string, int has_hold_time, int hold_time)
+static void do_sendkey(Monitor *mon, const char *string, int has_hold_time,
+                       int hold_time)
 {
     char keyname_buf[16];
     char *separator;
@@ -1046,17 +1056,17 @@ static void do_sendkey(const char *string, int has_hold_time, int hold_time)
         if (keyname_len > 0) {
             pstrcpy(keyname_buf, sizeof(keyname_buf), string);
             if (keyname_len > sizeof(keyname_buf) - 1) {
-                term_printf("invalid key: '%s...'\n", keyname_buf);
+                monitor_printf(mon, "invalid key: '%s...'\n", keyname_buf);
                 return;
             }
             if (i == MAX_KEYCODES) {
-                term_printf("too many keys\n");
+                monitor_printf(mon, "too many keys\n");
                 return;
             }
             keyname_buf[keyname_len] = 0;
             keycode = get_keycode(keyname_buf);
             if (keycode < 0) {
-                term_printf("unknown key: '%s'\n", keyname_buf);
+                monitor_printf(mon, "unknown key: '%s'\n", keyname_buf);
                 return;
             }
             keycodes[i++] = keycode;
@@ -1080,7 +1090,7 @@ static void do_sendkey(const char *string, int has_hold_time, int hold_time)
 
 static int mouse_button_state;
 
-static void do_mouse_move(const char *dx_str, const char *dy_str,
+static void do_mouse_move(Monitor *mon, const char *dx_str, const char *dy_str,
                           const char *dz_str)
 {
     int dx, dy, dz;
@@ -1092,13 +1102,14 @@ static void do_mouse_move(const char *dx_str, const char *dy_str,
     kbd_mouse_event(dx, dy, dz, mouse_button_state);
 }
 
-static void do_mouse_button(int button_state)
+static void do_mouse_button(Monitor *mon, int button_state)
 {
     mouse_button_state = button_state;
     kbd_mouse_event(0, 0, 0, mouse_button_state);
 }
 
-static void do_ioport_read(int count, int format, int size, int addr, int has_index, int index)
+static void do_ioport_read(Monitor *mon, int count, int format, int size,
+                           int addr, int has_index, int index)
 {
     uint32_t val;
     int suffix;
@@ -1124,8 +1135,8 @@ static void do_ioport_read(int count, int format, int size, int addr, int has_in
         suffix = 'l';
         break;
     }
-    term_printf("port%c[0x%04x] = %#0*x\n",
-                suffix, addr, size * 2, val);
+    monitor_printf(mon, "port%c[0x%04x] = %#0*x\n",
+                   suffix, addr, size * 2, val);
 }
 
 /* boot_set handler */
@@ -1138,48 +1149,51 @@ void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
     boot_opaque = opaque;
 }
 
-static void do_boot_set(const char *bootdevice)
+static void do_boot_set(Monitor *mon, const char *bootdevice)
 {
     int res;
 
     if (qemu_boot_set_handler)  {
         res = qemu_boot_set_handler(boot_opaque, bootdevice);
         if (res == 0)
-            term_printf("boot device list now set to %s\n", bootdevice);
+            monitor_printf(mon, "boot device list now set to %s\n",
+                           bootdevice);
         else
-            term_printf("setting boot device list failed with error %i\n", res);
+            monitor_printf(mon, "setting boot device list failed with "
+                           "error %i\n", res);
     } else {
-        term_printf("no function defined to set boot device list for this architecture\n");
+        monitor_printf(mon, "no function defined to set boot device list for "
+                       "this architecture\n");
     }
 }
 
-static void do_system_reset(void)
+static void do_system_reset(Monitor *mon)
 {
     qemu_system_reset_request();
 }
 
-static void do_system_powerdown(void)
+static void do_system_powerdown(Monitor *mon)
 {
     qemu_system_powerdown_request();
 }
 
 #if defined(TARGET_I386)
-static void print_pte(uint32_t addr, uint32_t pte, uint32_t mask)
+static void print_pte(Monitor *mon, uint32_t addr, uint32_t pte, uint32_t mask)
 {
-    term_printf("%08x: %08x %c%c%c%c%c%c%c%c\n",
-                addr,
-                pte & mask,
-                pte & PG_GLOBAL_MASK ? 'G' : '-',
-                pte & PG_PSE_MASK ? 'P' : '-',
-                pte & PG_DIRTY_MASK ? 'D' : '-',
-                pte & PG_ACCESSED_MASK ? 'A' : '-',
-                pte & PG_PCD_MASK ? 'C' : '-',
-                pte & PG_PWT_MASK ? 'T' : '-',
-                pte & PG_USER_MASK ? 'U' : '-',
-                pte & PG_RW_MASK ? 'W' : '-');
+    monitor_printf(mon, "%08x: %08x %c%c%c%c%c%c%c%c\n",
+                   addr,
+                   pte & mask,
+                   pte & PG_GLOBAL_MASK ? 'G' : '-',
+                   pte & PG_PSE_MASK ? 'P' : '-',
+                   pte & PG_DIRTY_MASK ? 'D' : '-',
+                   pte & PG_ACCESSED_MASK ? 'A' : '-',
+                   pte & PG_PCD_MASK ? 'C' : '-',
+                   pte & PG_PWT_MASK ? 'T' : '-',
+                   pte & PG_USER_MASK ? 'U' : '-',
+                   pte & PG_RW_MASK ? 'W' : '-');
 }
 
-static void tlb_info(void)
+static void tlb_info(Monitor *mon)
 {
     CPUState *env;
     int l1, l2;
@@ -1190,7 +1204,7 @@ static void tlb_info(void)
         return;
 
     if (!(env->cr[0] & CR0_PG_MASK)) {
-        term_printf("PG disabled\n");
+        monitor_printf(mon, "PG disabled\n");
         return;
     }
     pgd = env->cr[3] & ~0xfff;
@@ -1199,14 +1213,14 @@ static void tlb_info(void)
         pde = le32_to_cpu(pde);
         if (pde & PG_PRESENT_MASK) {
             if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
-                print_pte((l1 << 22), pde, ~((1 << 20) - 1));
+                print_pte(mon, (l1 << 22), pde, ~((1 << 20) - 1));
             } else {
                 for(l2 = 0; l2 < 1024; l2++) {
                     cpu_physical_memory_read((pde & ~0xfff) + l2 * 4,
                                              (uint8_t *)&pte, 4);
                     pte = le32_to_cpu(pte);
                     if (pte & PG_PRESENT_MASK) {
-                        print_pte((l1 << 22) + (l2 << 12),
+                        print_pte(mon, (l1 << 22) + (l2 << 12),
                                   pte & ~PG_PSE_MASK,
                                   ~0xfff);
                     }
@@ -1216,18 +1230,18 @@ static void tlb_info(void)
     }
 }
 
-static void mem_print(uint32_t *pstart, int *plast_prot,
+static void mem_print(Monitor *mon, uint32_t *pstart, int *plast_prot,
                       uint32_t end, int prot)
 {
     int prot1;
     prot1 = *plast_prot;
     if (prot != prot1) {
         if (*pstart != -1) {
-            term_printf("%08x-%08x %08x %c%c%c\n",
-                        *pstart, end, end - *pstart,
-                        prot1 & PG_USER_MASK ? 'u' : '-',
-                        'r',
-                        prot1 & PG_RW_MASK ? 'w' : '-');
+            monitor_printf(mon, "%08x-%08x %08x %c%c%c\n",
+                           *pstart, end, end - *pstart,
+                           prot1 & PG_USER_MASK ? 'u' : '-',
+                           'r',
+                           prot1 & PG_RW_MASK ? 'w' : '-');
         }
         if (prot != 0)
             *pstart = end;
@@ -1237,7 +1251,7 @@ static void mem_print(uint32_t *pstart, int *plast_prot,
     }
 }
 
-static void mem_info(void)
+static void mem_info(Monitor *mon)
 {
     CPUState *env;
     int l1, l2, prot, last_prot;
@@ -1248,7 +1262,7 @@ static void mem_info(void)
         return;
 
     if (!(env->cr[0] & CR0_PG_MASK)) {
-        term_printf("PG disabled\n");
+        monitor_printf(mon, "PG disabled\n");
         return;
     }
     pgd = env->cr[3] & ~0xfff;
@@ -1261,7 +1275,7 @@ static void mem_info(void)
         if (pde & PG_PRESENT_MASK) {
             if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
                 prot = pde & (PG_USER_MASK | PG_RW_MASK | PG_PRESENT_MASK);
-                mem_print(&start, &last_prot, end, prot);
+                mem_print(mon, &start, &last_prot, end, prot);
             } else {
                 for(l2 = 0; l2 < 1024; l2++) {
                     cpu_physical_memory_read((pde & ~0xfff) + l2 * 4,
@@ -1273,18 +1287,18 @@ static void mem_info(void)
                     } else {
                         prot = 0;
                     }
-                    mem_print(&start, &last_prot, end, prot);
+                    mem_print(mon, &start, &last_prot, end, prot);
                 }
             }
         } else {
             prot = 0;
-            mem_print(&start, &last_prot, end, prot);
+            mem_print(mon, &start, &last_prot, end, prot);
         }
     }
 }
 #endif
 
-static void do_info_kqemu(void)
+static void do_info_kqemu(Monitor *mon)
 {
 #ifdef USE_KQEMU
     CPUState *env;
@@ -1292,38 +1306,38 @@ static void do_info_kqemu(void)
     val = 0;
     env = mon_get_cpu();
     if (!env) {
-        term_printf("No cpu initialized yet");
+        monitor_printf(mon, "No cpu initialized yet");
         return;
     }
     val = env->kqemu_enabled;
-    term_printf("kqemu support: ");
+    monitor_printf(mon, "kqemu support: ");
     switch(val) {
     default:
     case 0:
-        term_printf("disabled\n");
+        monitor_printf(mon, "disabled\n");
         break;
     case 1:
-        term_printf("enabled for user code\n");
+        monitor_printf(mon, "enabled for user code\n");
         break;
     case 2:
-        term_printf("enabled for user and kernel code\n");
+        monitor_printf(mon, "enabled for user and kernel code\n");
         break;
     }
 #else
-    term_printf("kqemu support: not compiled\n");
+    monitor_printf(mon, "kqemu support: not compiled\n");
 #endif
 }
 
-static void do_info_kvm(void)
+static void do_info_kvm(Monitor *mon)
 {
 #ifdef CONFIG_KVM
-    term_printf("kvm support: ");
+    monitor_printf(mon, "kvm support: ");
     if (kvm_enabled())
-	term_printf("enabled\n");
+        monitor_printf(mon, "enabled\n");
     else
-	term_printf("disabled\n");
+        monitor_printf(mon, "disabled\n");
 #else
-    term_printf("kvm support: not compiled\n");
+    monitor_printf(mon, "kvm support: not compiled\n");
 #endif
 }
 
@@ -1337,23 +1351,25 @@ int64_t kqemu_ret_int_count;
 int64_t kqemu_ret_excp_count;
 int64_t kqemu_ret_intr_count;
 
-static void do_info_profile(void)
+static void do_info_profile(Monitor *mon)
 {
     int64_t total;
     total = qemu_time;
     if (total == 0)
         total = 1;
-    term_printf("async time  %" PRId64 " (%0.3f)\n",
-                dev_time, dev_time / (double)ticks_per_sec);
-    term_printf("qemu time   %" PRId64 " (%0.3f)\n",
-                qemu_time, qemu_time / (double)ticks_per_sec);
-    term_printf("kqemu time  %" PRId64 " (%0.3f %0.1f%%) count=%" PRId64 " int=%" PRId64 " excp=%" PRId64 " intr=%" PRId64 "\n",
-                kqemu_time, kqemu_time / (double)ticks_per_sec,
-                kqemu_time / (double)total * 100.0,
-                kqemu_exec_count,
-                kqemu_ret_int_count,
-                kqemu_ret_excp_count,
-                kqemu_ret_intr_count);
+    monitor_printf(mon, "async time  %" PRId64 " (%0.3f)\n",
+                   dev_time, dev_time / (double)ticks_per_sec);
+    monitor_printf(mon, "qemu time   %" PRId64 " (%0.3f)\n",
+                   qemu_time, qemu_time / (double)ticks_per_sec);
+    monitor_printf(mon, "kqemu time  %" PRId64 " (%0.3f %0.1f%%) count=%"
+                        PRId64 " int=%" PRId64 " excp=%" PRId64 " intr=%"
+                        PRId64 "\n",
+                   kqemu_time, kqemu_time / (double)ticks_per_sec,
+                   kqemu_time / (double)total * 100.0,
+                   kqemu_exec_count,
+                   kqemu_ret_int_count,
+                   kqemu_ret_excp_count,
+                   kqemu_ret_intr_count);
     qemu_time = 0;
     kqemu_time = 0;
     kqemu_exec_count = 0;
@@ -1366,27 +1382,27 @@ static void do_info_profile(void)
 #endif
 }
 #else
-static void do_info_profile(void)
+static void do_info_profile(Monitor *mon)
 {
-    term_printf("Internal profiler not compiled\n");
+    monitor_printf(mon, "Internal profiler not compiled\n");
 }
 #endif
 
 /* Capture support */
 static LIST_HEAD (capture_list_head, CaptureState) capture_head;
 
-static void do_info_capture (void)
+static void do_info_capture(Monitor *mon)
 {
     int i;
     CaptureState *s;
 
     for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) {
-        term_printf ("[%d]: ", i);
+        monitor_printf(mon, "[%d]: ", i);
         s->ops.info (s->opaque);
     }
 }
 
-static void do_stop_capture (int n)
+static void do_stop_capture(Monitor *mon, int n)
 {
     int i;
     CaptureState *s;
@@ -1402,10 +1418,10 @@ static void do_stop_capture (int n)
 }
 
 #ifdef HAS_AUDIO
-static void do_wav_capture (const char *path,
-                            int has_freq, int freq,
-                            int has_bits, int bits,
-                            int has_channels, int nchannels)
+static void do_wav_capture(Monitor *mon, const char *path,
+                           int has_freq, int freq,
+                           int has_bits, int bits,
+                           int has_channels, int nchannels)
 {
     CaptureState *s;
 
@@ -1416,7 +1432,7 @@ static void do_wav_capture (const char *path,
     nchannels = has_channels ? nchannels : 2;
 
     if (wav_start_capture (s, path, freq, bits, nchannels)) {
-        term_printf ("Faied to add wave capture\n");
+        monitor_printf(mon, "Faied to add wave capture\n");
         qemu_free (s);
     }
     LIST_INSERT_HEAD (&capture_head, s, entries);
@@ -1424,7 +1440,7 @@ static void do_wav_capture (const char *path,
 #endif
 
 #if defined(TARGET_I386)
-static void do_inject_nmi(int cpu_index)
+static void do_inject_nmi(Monitor *mon, int cpu_index)
 {
     CPUState *env;
 
@@ -1436,37 +1452,38 @@ static void do_inject_nmi(int cpu_index)
 }
 #endif
 
-static void do_info_status(void)
+static void do_info_status(Monitor *mon)
 {
     if (vm_running)
-       term_printf("VM status: running\n");
+       monitor_printf(mon, "VM status: running\n");
     else
-       term_printf("VM status: paused\n");
+       monitor_printf(mon, "VM status: paused\n");
 }
 
 
-static void do_balloon(int value)
+static void do_balloon(Monitor *mon, int value)
 {
     ram_addr_t target = value;
     qemu_balloon(target << 20);
 }
 
-static void do_info_balloon(void)
+static void do_info_balloon(Monitor *mon)
 {
     ram_addr_t actual;
 
     actual = qemu_balloon_status();
     if (kvm_enabled() && !kvm_has_sync_mmu())
-        term_printf("Using KVM without synchronous MMU, ballooning disabled\n");
+        monitor_printf(mon, "Using KVM without synchronous MMU, "
+                       "ballooning disabled\n");
     else if (actual == 0)
-        term_printf("Ballooning not activated in VM\n");
+        monitor_printf(mon, "Ballooning not activated in VM\n");
     else
-        term_printf("balloon: actual=%d\n", (int)(actual >> 20));
+        monitor_printf(mon, "balloon: actual=%d\n", (int)(actual >> 20));
 }
 
 /* Please update qemu-doc.texi when adding or changing commands */
-static const term_cmd_t term_cmds[] = {
-    { "help|?", "s?", do_help,
+static const mon_cmd_t mon_cmds[] = {
+    { "help|?", "s?", help_cmd,
       "[cmd]", "show the help" },
     { "commit", "s", do_commit,
       "device|all", "commit changes to the disk images (if -snapshot is used) or backing files" },
@@ -1572,16 +1589,16 @@ static const term_cmd_t term_cmds[] = {
 };
 
 /* Please update qemu-doc.texi when adding or changing commands */
-static const term_cmd_t info_cmds[] = {
+static const mon_cmd_t info_cmds[] = {
     { "version", "", do_info_version,
       "", "show the version of QEMU" },
     { "network", "", do_info_network,
       "", "show the network state" },
     { "chardev", "", qemu_chr_info,
       "", "show the character devices" },
-    { "block", "", do_info_block,
+    { "block", "", bdrv_info,
       "", "show the block devices" },
-    { "blockstats", "", do_info_blockstats,
+    { "blockstats", "", bdrv_info_stats,
       "", "show block device statistics" },
     { "registers", "", do_info_registers,
       "", "show the cpu registers" },
@@ -1989,9 +2006,9 @@ static const MonitorDef monitor_defs[] = {
     { NULL },
 };
 
-static void expr_error(const char *msg)
+static void expr_error(Monitor *mon, const char *msg)
 {
-    term_printf("%s\n", msg);
+    monitor_printf(mon, "%s\n", msg);
     longjmp(expr_env, 1);
 }
 
@@ -2037,9 +2054,9 @@ static void next(void)
     }
 }
 
-static int64_t expr_sum(void);
+static int64_t expr_sum(Monitor *mon);
 
-static int64_t expr_unary(void)
+static int64_t expr_unary(Monitor *mon)
 {
     int64_t n;
     char *p;
@@ -2048,32 +2065,32 @@ static int64_t expr_unary(void)
     switch(*pch) {
     case '+':
         next();
-        n = expr_unary();
+        n = expr_unary(mon);
         break;
     case '-':
         next();
-        n = -expr_unary();
+        n = -expr_unary(mon);
         break;
     case '~':
         next();
-        n = ~expr_unary();
+        n = ~expr_unary(mon);
         break;
     case '(':
         next();
-        n = expr_sum();
+        n = expr_sum(mon);
         if (*pch != ')') {
-            expr_error("')' expected");
+            expr_error(mon, "')' expected");
         }
         next();
         break;
     case '\'':
         pch++;
         if (*pch == '\0')
-            expr_error("character constant expected");
+            expr_error(mon, "character constant expected");
         n = *pch;
         pch++;
         if (*pch != '\'')
-            expr_error("missing terminating \' character");
+            expr_error(mon, "missing terminating \' character");
         next();
         break;
     case '$':
@@ -2096,14 +2113,14 @@ static int64_t expr_unary(void)
             *q = 0;
             ret = get_monitor_def(&reg, buf);
             if (ret == -1)
-                expr_error("unknown register");
+                expr_error(mon, "unknown register");
             else if (ret == -2)
-                expr_error("no cpu defined");
+                expr_error(mon, "no cpu defined");
             n = reg;
         }
         break;
     case '\0':
-        expr_error("unexpected end of expression");
+        expr_error(mon, "unexpected end of expression");
         n = 0;
         break;
     default:
@@ -2113,7 +2130,7 @@ static int64_t expr_unary(void)
         n = strtoul(pch, &p, 0);
 #endif
         if (pch == p) {
-            expr_error("invalid char in expression");
+            expr_error(mon, "invalid char in expression");
         }
         pch = p;
         while (qemu_isspace(*pch))
@@ -2124,18 +2141,18 @@ static int64_t expr_unary(void)
 }
 
 
-static int64_t expr_prod(void)
+static int64_t expr_prod(Monitor *mon)
 {
     int64_t val, val2;
     int op;
 
-    val = expr_unary();
+    val = expr_unary(mon);
     for(;;) {
         op = *pch;
         if (op != '*' && op != '/' && op != '%')
             break;
         next();
-        val2 = expr_unary();
+        val2 = expr_unary(mon);
         switch(op) {
         default:
         case '*':
@@ -2144,7 +2161,7 @@ static int64_t expr_prod(void)
         case '/':
         case '%':
             if (val2 == 0)
-                expr_error("division by zero");
+                expr_error(mon, "division by zero");
             if (op == '/')
                 val /= val2;
             else
@@ -2155,18 +2172,18 @@ static int64_t expr_prod(void)
     return val;
 }
 
-static int64_t expr_logic(void)
+static int64_t expr_logic(Monitor *mon)
 {
     int64_t val, val2;
     int op;
 
-    val = expr_prod();
+    val = expr_prod(mon);
     for(;;) {
         op = *pch;
         if (op != '&' && op != '|' && op != '^')
             break;
         next();
-        val2 = expr_prod();
+        val2 = expr_prod(mon);
         switch(op) {
         default:
         case '&':
@@ -2183,18 +2200,18 @@ static int64_t expr_logic(void)
     return val;
 }
 
-static int64_t expr_sum(void)
+static int64_t expr_sum(Monitor *mon)
 {
     int64_t val, val2;
     int op;
 
-    val = expr_logic();
+    val = expr_logic(mon);
     for(;;) {
         op = *pch;
         if (op != '+' && op != '-')
             break;
         next();
-        val2 = expr_logic();
+        val2 = expr_logic(mon);
         if (op == '+')
             val += val2;
         else
@@ -2203,7 +2220,7 @@ static int64_t expr_sum(void)
     return val;
 }
 
-static int get_expr(int64_t *pval, const char **pp)
+static int get_expr(Monitor *mon, int64_t *pval, const char **pp)
 {
     pch = *pp;
     if (setjmp(expr_env)) {
@@ -2212,7 +2229,7 @@ static int get_expr(int64_t *pval, const char **pp)
     }
     while (qemu_isspace(*pch))
         pch++;
-    *pval = expr_sum();
+    *pval = expr_sum(mon);
     *pp = pch;
     return 0;
 }
@@ -2287,30 +2304,31 @@ static int default_fmt_size = 4;
 
 #define MAX_ARGS 16
 
-static void monitor_handle_command(const char *cmdline)
+static void monitor_handle_command(Monitor *mon, const char *cmdline)
 {
     const char *p, *pstart, *typestr;
     char *q;
     int c, nb_args, len, i, has_arg;
-    const term_cmd_t *cmd;
+    const mon_cmd_t *cmd;
     char cmdname[256];
     char buf[1024];
     void *str_allocated[MAX_ARGS];
     void *args[MAX_ARGS];
-    void (*handler_0)(void);
-    void (*handler_1)(void *arg0);
-    void (*handler_2)(void *arg0, void *arg1);
-    void (*handler_3)(void *arg0, void *arg1, void *arg2);
-    void (*handler_4)(void *arg0, void *arg1, void *arg2, void *arg3);
-    void (*handler_5)(void *arg0, void *arg1, void *arg2, void *arg3,
-                      void *arg4);
-    void (*handler_6)(void *arg0, void *arg1, void *arg2, void *arg3,
-                      void *arg4, void *arg5);
-    void (*handler_7)(void *arg0, void *arg1, void *arg2, void *arg3,
-                      void *arg4, void *arg5, void *arg6);
+    void (*handler_0)(Monitor *mon);
+    void (*handler_1)(Monitor *mon, void *arg0);
+    void (*handler_2)(Monitor *mon, void *arg0, void *arg1);
+    void (*handler_3)(Monitor *mon, void *arg0, void *arg1, void *arg2);
+    void (*handler_4)(Monitor *mon, void *arg0, void *arg1, void *arg2,
+                      void *arg3);
+    void (*handler_5)(Monitor *mon, void *arg0, void *arg1, void *arg2,
+                      void *arg3, void *arg4);
+    void (*handler_6)(Monitor *mon, void *arg0, void *arg1, void *arg2,
+                      void *arg3, void *arg4, void *arg5);
+    void (*handler_7)(Monitor *mon, void *arg0, void *arg1, void *arg2,
+                      void *arg3, void *arg4, void *arg5, void *arg6);
 
 #ifdef DEBUG
-    term_printf("command='%s'\n", cmdline);
+    monitor_printf(mon, "command='%s'\n", cmdline);
 #endif
 
     /* extract the command name */
@@ -2330,11 +2348,11 @@ static void monitor_handle_command(const char *cmdline)
     cmdname[len] = '\0';
 
     /* find the command */
-    for(cmd = term_cmds; cmd->name != NULL; cmd++) {
+    for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
         if (compare_cmd(cmdname, cmd->name))
             goto found;
     }
-    term_printf("unknown command: '%s'\n", cmdname);
+    monitor_printf(mon, "unknown command: '%s'\n", cmdname);
     return;
  found:
 
@@ -2371,13 +2389,15 @@ static void monitor_handle_command(const char *cmdline)
                 if (ret < 0) {
                     switch(c) {
                     case 'F':
-                        term_printf("%s: filename expected\n", cmdname);
+                        monitor_printf(mon, "%s: filename expected\n",
+                                       cmdname);
                         break;
                     case 'B':
-                        term_printf("%s: block device name expected\n", cmdname);
+                        monitor_printf(mon, "%s: block device name expected\n",
+                                       cmdname);
                         break;
                     default:
-                        term_printf("%s: string expected\n", cmdname);
+                        monitor_printf(mon, "%s: string expected\n", cmdname);
                         break;
                     }
                     goto fail;
@@ -2388,7 +2408,7 @@ static void monitor_handle_command(const char *cmdline)
             add_str:
                 if (nb_args >= MAX_ARGS) {
                 error_args:
-                    term_printf("%s: too many arguments\n", cmdname);
+                    monitor_printf(mon, "%s: too many arguments\n", cmdname);
                     goto fail;
                 }
                 args[nb_args++] = str;
@@ -2446,7 +2466,8 @@ static void monitor_handle_command(const char *cmdline)
                     }
                 next:
                     if (*p != '\0' && !qemu_isspace(*p)) {
-                        term_printf("invalid char in format: '%c'\n", *p);
+                        monitor_printf(mon, "invalid char in format: '%c'\n",
+                                       *p);
                         goto fail;
                     }
                     if (format < 0)
@@ -2508,7 +2529,7 @@ static void monitor_handle_command(const char *cmdline)
                         goto add_num;
                     }
                 }
-                if (get_expr(&val, &p))
+                if (get_expr(mon, &val, &p))
                     goto fail;
             add_num:
                 if (c == 'i') {
@@ -2541,8 +2562,8 @@ static void monitor_handle_command(const char *cmdline)
                 if (*p == '-') {
                     p++;
                     if (*p != c) {
-                        term_printf("%s: unsupported option -%c\n",
-                                    cmdname, *p);
+                        monitor_printf(mon, "%s: unsupported option -%c\n",
+                                       cmdname, *p);
                         goto fail;
                     }
                     p++;
@@ -2555,7 +2576,7 @@ static void monitor_handle_command(const char *cmdline)
             break;
         default:
         bad_type:
-            term_printf("%s: unknown type '%c'\n", cmdname, c);
+            monitor_printf(mon, "%s: unknown type '%c'\n", cmdname, c);
             goto fail;
         }
     }
@@ -2563,46 +2584,47 @@ static void monitor_handle_command(const char *cmdline)
     while (qemu_isspace(*p))
         p++;
     if (*p != '\0') {
-        term_printf("%s: extraneous characters at the end of line\n",
-                    cmdname);
+        monitor_printf(mon, "%s: extraneous characters at the end of line\n",
+                       cmdname);
         goto fail;
     }
 
     switch(nb_args) {
     case 0:
         handler_0 = cmd->handler;
-        handler_0();
+        handler_0(mon);
         break;
     case 1:
         handler_1 = cmd->handler;
-        handler_1(args[0]);
+        handler_1(mon, args[0]);
         break;
     case 2:
         handler_2 = cmd->handler;
-        handler_2(args[0], args[1]);
+        handler_2(mon, args[0], args[1]);
         break;
     case 3:
         handler_3 = cmd->handler;
-        handler_3(args[0], args[1], args[2]);
+        handler_3(mon, args[0], args[1], args[2]);
         break;
     case 4:
         handler_4 = cmd->handler;
-        handler_4(args[0], args[1], args[2], args[3]);
+        handler_4(mon, args[0], args[1], args[2], args[3]);
         break;
     case 5:
         handler_5 = cmd->handler;
-        handler_5(args[0], args[1], args[2], args[3], args[4]);
+        handler_5(mon, args[0], args[1], args[2], args[3], args[4]);
         break;
     case 6:
         handler_6 = cmd->handler;
-        handler_6(args[0], args[1], args[2], args[3], args[4], args[5]);
+        handler_6(mon, args[0], args[1], args[2], args[3], args[4], args[5]);
         break;
     case 7:
         handler_7 = cmd->handler;
-        handler_7(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+        handler_7(mon, args[0], args[1], args[2], args[3], args[4], args[5],
+                  args[6]);
         break;
     default:
-        term_printf("unsupported number of arguments: %d\n", nb_args);
+        monitor_printf(mon, "unsupported number of arguments: %d\n", nb_args);
         goto fail;
     }
  fail:
@@ -2629,7 +2651,7 @@ static void cmd_completion(const char *name, const char *list)
         memcpy(cmd, pstart, len);
         cmd[len] = '\0';
         if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
-            add_completion(cmd);
+            readline_add_completion(cmd);
         }
         if (*p == '\0')
             break;
@@ -2660,7 +2682,8 @@ static void file_completion(const char *input)
         pstrcpy(file_prefix, sizeof(file_prefix), p + 1);
     }
 #ifdef DEBUG_COMPLETION
-    term_printf("input='%s' path='%s' prefix='%s'\n", input, path, file_prefix);
+    monitor_printf(cur_mon, "input='%s' path='%s' prefix='%s'\n",
+                   input, path, file_prefix);
 #endif
     ffs = opendir(path);
     if (!ffs)
@@ -2681,7 +2704,7 @@ static void file_completion(const char *input)
             stat(file, &sb);
             if(S_ISDIR(sb.st_mode))
                 pstrcat(file, sizeof(file), "/");
-            add_completion(file);
+            readline_add_completion(file);
         }
     }
     closedir(ffs);
@@ -2694,7 +2717,7 @@ static void block_completion_it(void *opaque, BlockDriverState *bs)
 
     if (input[0] == '\0' ||
         !strncmp(name, (char *)input, strlen(input))) {
-        add_completion(name);
+        readline_add_completion(name);
     }
 }
 
@@ -2730,13 +2753,13 @@ void readline_find_completion(const char *cmdline)
     char *args[MAX_ARGS];
     int nb_args, i, len;
     const char *ptype, *str;
-    const term_cmd_t *cmd;
+    const mon_cmd_t *cmd;
     const KeyDef *key;
 
     parse_cmdline(cmdline, &nb_args, args);
 #ifdef DEBUG_COMPLETION
     for(i = 0; i < nb_args; i++) {
-        term_printf("arg%d = '%s'\n", i, (char *)args[i]);
+        monitor_printf(cur_mon, "arg%d = '%s'\n", i, (char *)args[i]);
     }
 #endif
 
@@ -2754,13 +2777,13 @@ void readline_find_completion(const char *cmdline)
             cmdname = "";
         else
             cmdname = args[0];
-        completion_index = strlen(cmdname);
-        for(cmd = term_cmds; cmd->name != NULL; cmd++) {
+        readline_set_completion_index(strlen(cmdname));
+        for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
             cmd_completion(cmdname, cmd->name);
         }
     } else {
         /* find the command */
-        for(cmd = term_cmds; cmd->name != NULL; cmd++) {
+        for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
             if (compare_cmd(args[0], cmd->name))
                 goto found;
         }
@@ -2778,23 +2801,23 @@ void readline_find_completion(const char *cmdline)
         switch(*ptype) {
         case 'F':
             /* file completion */
-            completion_index = strlen(str);
+            readline_set_completion_index(strlen(str));
             file_completion(str);
             break;
         case 'B':
             /* block device name completion */
-            completion_index = strlen(str);
+            readline_set_completion_index(strlen(str));
             bdrv_iterate(block_completion_it, (void *)str);
             break;
         case 's':
             /* XXX: more generic ? */
             if (!strcmp(cmd->name, "info")) {
-                completion_index = strlen(str);
+                readline_set_completion_index(strlen(str));
                 for(cmd = info_cmds; cmd->name != NULL; cmd++) {
                     cmd_completion(str, cmd->name);
                 }
             } else if (!strcmp(cmd->name, "sendkey")) {
-                completion_index = strlen(str);
+                readline_set_completion_index(strlen(str));
                 for(key = key_defs; key->name != NULL; key++) {
                     cmd_completion(str, key->name);
                 }
@@ -2816,27 +2839,28 @@ static int term_can_read(void *opaque)
 static void term_read(void *opaque, const uint8_t *buf, int size)
 {
     int i;
-    for(i = 0; i < size; i++)
+
+    for (i = 0; i < size; i++)
         readline_handle_byte(buf[i]);
 }
 
 static int monitor_suspended;
 
-static void monitor_handle_command1(void *opaque, const char *cmdline)
+static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque)
 {
-    monitor_handle_command(cmdline);
+    monitor_handle_command(mon, cmdline);
     if (!monitor_suspended)
         readline_show_prompt();
     else
         monitor_suspended = 2;
 }
 
-void monitor_suspend(void)
+void monitor_suspend(Monitor *mon)
 {
     monitor_suspended = 1;
 }
 
-void monitor_resume(void)
+void monitor_resume(Monitor *mon)
 {
     if (monitor_suspended == 2)
         monitor_start_input();
@@ -2845,24 +2869,26 @@ void monitor_resume(void)
 
 static void monitor_start_input(void)
 {
-    readline_start("(qemu) ", 0, monitor_handle_command1, NULL);
+    readline_start("(qemu) ", 0, monitor_command_cb, NULL);
     readline_show_prompt();
 }
 
 static void term_event(void *opaque, int event)
 {
+    Monitor *mon = opaque;
+
     if (event != CHR_EVENT_RESET)
 	return;
 
     if (!hide_banner)
-	    term_printf("QEMU %s monitor - type 'help' for more information\n",
-			QEMU_VERSION);
+        monitor_printf(mon, "QEMU %s monitor - type 'help' for more "
+                       "information\n", QEMU_VERSION);
     monitor_start_input();
 }
 
 static int is_first_init = 1;
 
-void monitor_init(CharDriverState *hd, int show_banner)
+void monitor_init(CharDriverState *chr, int show_banner)
 {
     int i;
 
@@ -2877,25 +2903,25 @@ void monitor_init(CharDriverState *hd, int show_banner)
     }
     for (i = 0; i < MAX_MON; i++) {
         if (monitor_hd[i] == NULL) {
-            monitor_hd[i] = hd;
+            monitor_hd[i] = chr;
             break;
         }
     }
 
     hide_banner = !show_banner;
 
-    qemu_chr_add_handlers(hd, term_can_read, term_read, term_event, NULL);
+    qemu_chr_add_handlers(chr, term_can_read, term_read, term_event, cur_mon);
 
-    readline_start("", 0, monitor_handle_command1, NULL);
+    readline_start("", 0, monitor_command_cb, NULL);
 }
 
-static void bdrv_password_cb(void *opaque, const char *password)
+static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
 {
     BlockDriverState *bs = opaque;
     int ret = 0;
 
     if (bdrv_set_key(bs, password) != 0) {
-        term_printf("invalid password\n");
+        monitor_printf(mon, "invalid password\n");
         ret = -EPERM;
     }
     if (password_completion_cb)
@@ -2904,7 +2930,7 @@ static void bdrv_password_cb(void *opaque, const char *password)
     monitor_start_input();
 }
 
-void monitor_read_bdrv_key_start(BlockDriverState *bs,
+void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
                                  BlockDriverCompletionFunc *completion_cb,
                                  void *opaque)
 {
@@ -2914,11 +2940,11 @@ void monitor_read_bdrv_key_start(BlockDriverState *bs,
         return;
     }
 
-    term_printf("%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
-                bdrv_get_encrypted_filename(bs));
+    monitor_printf(mon, "%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
+                   bdrv_get_encrypted_filename(bs));
 
     password_completion_cb = completion_cb;
     password_opaque = opaque;
 
-    monitor_read_password(bdrv_password_cb, bs);
+    monitor_read_password(mon, bdrv_password_cb, bs);
 }
diff --git a/monitor.h b/monitor.h
new file mode 100644
index 0000000..d06e2d8
--- /dev/null
+++ b/monitor.h
@@ -0,0 +1,25 @@
+#ifndef MONITOR_H
+#define MONITOR_H
+
+#include "qemu-common.h"
+#include "qemu-char.h"
+#include "block.h"
+
+extern Monitor *cur_mon;
+
+void monitor_init(CharDriverState *chr, int show_banner);
+
+void monitor_suspend(Monitor *mon);
+void monitor_resume(Monitor *mon);
+
+void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
+                                 BlockDriverCompletionFunc *completion_cb,
+                                 void *opaque);
+
+void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap);
+void monitor_printf(Monitor *mon, const char *fmt, ...)
+    __attribute__ ((__format__ (__printf__, 2, 3)));
+void monitor_print_filename(Monitor *mon, const char *filename);
+void monitor_flush(Monitor *mon);
+
+#endif /* !MONITOR_H */
diff --git a/net.c b/net.c
index 29beb28..9da6906 100644
--- a/net.c
+++ b/net.c
@@ -23,7 +23,7 @@
  */
 #include "qemu-common.h"
 #include "net.h"
-#include "console.h"
+#include "monitor.h"
 #include "sysemu.h"
 #include "qemu-timer.h"
 #include "qemu-char.h"
@@ -665,7 +665,7 @@ void net_slirp_smb(const char *exported_dir)
 }
 
 #endif /* !defined(_WIN32) */
-void do_info_slirp(void)
+void do_info_slirp(Monitor *mon)
 {
     slirp_stats();
 }
@@ -1795,28 +1795,28 @@ static int net_host_check_device(const char *device)
     return 0;
 }
 
-void net_host_device_add(const char *device, const char *opts)
+void net_host_device_add(Monitor *mon, const char *device, const char *opts)
 {
     if (!net_host_check_device(device)) {
-        term_printf("invalid host network device %s\n", device);
+        monitor_printf(mon, "invalid host network device %s\n", device);
         return;
     }
     net_client_init(device, opts);
 }
 
-void net_host_device_remove(int vlan_id, const char *device)
+void net_host_device_remove(Monitor *mon, int vlan_id, const char *device)
 {
     VLANState *vlan;
     VLANClientState *vc;
 
     if (!net_host_check_device(device)) {
-        term_printf("invalid host network device %s\n", device);
+        monitor_printf(mon, "invalid host network device %s\n", device);
         return;
     }
 
     vlan = qemu_find_vlan(vlan_id);
     if (!vlan) {
-        term_printf("can't find vlan %d\n", vlan_id);
+        monitor_printf(mon, "can't find vlan %d\n", vlan_id);
         return;
     }
 
@@ -1825,7 +1825,7 @@ void net_host_device_remove(int vlan_id, const char *device)
             break;
 
     if (!vc) {
-        term_printf("can't find device %s\n", device);
+        monitor_printf(mon, "can't find device %s\n", device);
         return;
     }
     qemu_del_vlan_client(vc);
@@ -1851,19 +1851,19 @@ int net_client_parse(const char *str)
     return net_client_init(device, p);
 }
 
-void do_info_network(void)
+void do_info_network(Monitor *mon)
 {
     VLANState *vlan;
     VLANClientState *vc;
 
     for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
-        term_printf("VLAN %d devices:\n", vlan->id);
+        monitor_printf(mon, "VLAN %d devices:\n", vlan->id);
         for(vc = vlan->first_client; vc != NULL; vc = vc->next)
-            term_printf("  %s: %s\n", vc->name, vc->info_str);
+            monitor_printf(mon, "  %s: %s\n", vc->name, vc->info_str);
     }
 }
 
-int do_set_link(const char *name, const char *up_or_down)
+int do_set_link(Monitor *mon, const char *name, const char *up_or_down)
 {
     VLANState *vlan;
     VLANClientState *vc = NULL;
@@ -1875,7 +1875,7 @@ int do_set_link(const char *name, const char *up_or_down)
 done:
 
     if (!vc) {
-        term_printf("could not find network device '%s'", name);
+        monitor_printf(mon, "could not find network device '%s'", name);
         return 0;
     }
 
@@ -1884,8 +1884,8 @@ done:
     else if (strcmp(up_or_down, "down") == 0)
         vc->link_down = 1;
     else
-        term_printf("invalid link status '%s'; only 'up' or 'down' valid\n",
-                    up_or_down);
+        monitor_printf(mon, "invalid link status '%s'; only 'up' or 'down' "
+                       "valid\n", up_or_down);
 
     if (vc->link_status_changed)
         vc->link_status_changed(vc);
diff --git a/net.h b/net.h
index 03c7f18..1a51be7 100644
--- a/net.h
+++ b/net.h
@@ -53,8 +53,8 @@ void qemu_check_nic_model_list(NICInfo *nd, const char * const *models,
                                const char *default_model);
 void qemu_handler_true(void *opaque);
 
-void do_info_network(void);
-int do_set_link(const char *name, const char *up_or_down);
+void do_info_network(Monitor *mon);
+int do_set_link(Monitor *mon, const char *name, const char *up_or_down);
 
 /* NIC info */
 
@@ -102,8 +102,8 @@ void net_slirp_redir(const char *redir_str);
 void net_cleanup(void);
 int slirp_is_inited(void);
 void net_client_check(void);
-void net_host_device_add(const char *device, const char *opts);
-void net_host_device_remove(int vlan_id, const char *device);
+void net_host_device_add(Monitor *mon, const char *device, const char *opts);
+void net_host_device_remove(Monitor *mon, int vlan_id, const char *device);
 
 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
 #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
diff --git a/qemu-char.c b/qemu-char.c
index 1fd3aef..d4ff367 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -23,6 +23,7 @@
  */
 #include "qemu-common.h"
 #include "net.h"
+#include "monitor.h"
 #include "console.h"
 #include "sysemu.h"
 #include "qemu-timer.h"
@@ -2199,11 +2200,11 @@ void qemu_chr_close(CharDriverState *chr)
     qemu_free(chr);
 }
 
-void qemu_chr_info(void)
+void qemu_chr_info(Monitor *mon)
 {
     CharDriverState *chr;
 
     TAILQ_FOREACH(chr, &chardevs, next) {
-        term_printf("%s: filename=%s\n", chr->label, chr->filename);
+        monitor_printf(mon, "%s: filename=%s\n", chr->label, chr->filename);
     }
 }
diff --git a/qemu-char.h b/qemu-char.h
index 9ff6b99..e5ad45c 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -1,7 +1,9 @@
 #ifndef QEMU_CHAR_H
 #define QEMU_CHAR_H
 
+#include "qemu-common.h"
 #include "sys-queue.h"
+
 /* character device */
 
 #define CHR_EVENT_BREAK 0 /* serial break char */
@@ -78,7 +80,7 @@ void qemu_chr_initial_reset(void);
 int qemu_chr_can_read(CharDriverState *s);
 void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len);
 void qemu_chr_accept_input(CharDriverState *s);
-void qemu_chr_info(void);
+void qemu_chr_info(Monitor *mon);
 
 extern int term_escape_char;
 
diff --git a/qemu-common.h b/qemu-common.h
index db33493..f8ac7e6 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -205,6 +205,9 @@ void qemu_iovec_reset(QEMUIOVector *qiov);
 void qemu_iovec_to_buffer(QEMUIOVector *qiov, void *buf);
 void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count);
 
+struct Monitor;
+typedef struct Monitor Monitor;
+
 #endif /* dyngen-exec.h hack */
 
 #endif
diff --git a/qemu-tool.c b/qemu-tool.c
index 4dda5af..c08f061 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -12,7 +12,7 @@
  */
 
 #include "qemu-common.h"
-#include "console.h"
+#include "monitor.h"
 #include "sysemu.h"
 #include "qemu-timer.h"
 
@@ -30,11 +30,13 @@ void qemu_service_io(void)
 {
 }
 
-void term_printf(const char *fmt, ...)
+Monitor *cur_mon;
+
+void monitor_printf(Monitor *mon, const char *fmt, ...)
 {
 }
 
-void term_print_filename(const char *filename)
+void monitor_print_filename(Monitor *mon, const char *filename)
 {
 }
 
diff --git a/readline.c b/readline.c
index 5a089be..ffa5424 100644
--- a/readline.c
+++ b/readline.c
@@ -21,8 +21,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "qemu-common.h"
-#include "console.h"
+#include "readline.h"
+#include "monitor.h"
 
 #define TERM_CMD_BUF_SIZE 4095
 #define TERM_MAX_CMDS 64
@@ -49,7 +49,7 @@ static char *term_history[TERM_MAX_CMDS];
 static int term_hist_entry = -1;
 
 static int nb_completions;
-int completion_index;
+static int completion_index;
 static char *completions[NB_COMPLETIONS_MAX];
 
 static ReadLineFunc *term_readline_func;
@@ -59,8 +59,10 @@ static void *term_readline_opaque;
 
 void readline_show_prompt(void)
 {
-    term_printf("%s", term_prompt);
-    term_flush();
+    Monitor *mon = cur_mon;
+
+    monitor_printf(mon, "%s", term_prompt);
+    monitor_flush(mon);
     term_last_cmd_buf_index = 0;
     term_last_cmd_buf_size = 0;
     term_esc_state = IS_NORM;
@@ -69,22 +71,23 @@ void readline_show_prompt(void)
 /* update the displayed command line */
 static void term_update(void)
 {
+    Monitor *mon = cur_mon;
     int i, delta, len;
 
     if (term_cmd_buf_size != term_last_cmd_buf_size ||
         memcmp(term_cmd_buf, term_last_cmd_buf, term_cmd_buf_size) != 0) {
         for(i = 0; i < term_last_cmd_buf_index; i++) {
-            term_printf("\033[D");
+            monitor_printf(mon, "\033[D");
         }
         term_cmd_buf[term_cmd_buf_size] = '\0';
         if (term_is_password) {
             len = strlen(term_cmd_buf);
             for(i = 0; i < len; i++)
-                term_printf("*");
+                monitor_printf(mon, "*");
         } else {
-            term_printf("%s", term_cmd_buf);
+            monitor_printf(mon, "%s", term_cmd_buf);
         }
-        term_printf("\033[K");
+        monitor_printf(mon, "\033[K");
         memcpy(term_last_cmd_buf, term_cmd_buf, term_cmd_buf_size);
         term_last_cmd_buf_size = term_cmd_buf_size;
         term_last_cmd_buf_index = term_cmd_buf_size;
@@ -93,17 +96,17 @@ static void term_update(void)
         delta = term_cmd_buf_index - term_last_cmd_buf_index;
         if (delta > 0) {
             for(i = 0;i < delta; i++) {
-                term_printf("\033[C");
+                monitor_printf(mon, "\033[C");
             }
         } else {
             delta = -delta;
             for(i = 0;i < delta; i++) {
-                term_printf("\033[D");
+                monitor_printf(mon, "\033[D");
             }
         }
         term_last_cmd_buf_index = term_cmd_buf_index;
     }
-    term_flush();
+    monitor_flush(mon);
 }
 
 static void term_insert_char(int ch)
@@ -285,15 +288,21 @@ static void term_hist_add(const char *cmdline)
 
 /* completion support */
 
-void add_completion(const char *str)
+void readline_add_completion(const char *str)
 {
     if (nb_completions < NB_COMPLETIONS_MAX) {
         completions[nb_completions++] = qemu_strdup(str);
     }
 }
 
+void readline_set_completion_index(int index)
+{
+    completion_index = index;
+}
+
 static void term_completion(void)
 {
+    Monitor *mon = cur_mon;
     int len, i, j, max_width, nb_cols, max_prefix;
     char *cmdline;
 
@@ -317,7 +326,7 @@ static void term_completion(void)
         if (len > 0 && completions[0][len - 1] != '/')
             term_insert_char(' ');
     } else {
-        term_printf("\n");
+        monitor_printf(mon, "\n");
         max_width = 0;
         max_prefix = 0;	
         for(i = 0; i < nb_completions; i++) {
@@ -347,9 +356,9 @@ static void term_completion(void)
         nb_cols = 80 / max_width;
         j = 0;
         for(i = 0; i < nb_completions; i++) {
-            term_printf("%-*s", max_width, completions[i]);
+            monitor_printf(mon, "%-*s", max_width, completions[i]);
             if (++j == nb_cols || i == (nb_completions - 1)) {
-                term_printf("\n");
+                monitor_printf(mon, "\n");
                 j = 0;
             }
         }
@@ -360,6 +369,8 @@ static void term_completion(void)
 /* return true if command handled */
 void readline_handle_byte(int ch)
 {
+    Monitor *mon = cur_mon;
+
     switch(term_esc_state) {
     case IS_NORM:
         switch(ch) {
@@ -380,13 +391,13 @@ void readline_handle_byte(int ch)
             term_cmd_buf[term_cmd_buf_size] = '\0';
             if (!term_is_password)
                 term_hist_add(term_cmd_buf);
-            term_printf("\n");
+            monitor_printf(mon, "\n");
             term_cmd_buf_index = 0;
             term_cmd_buf_size = 0;
             term_last_cmd_buf_index = 0;
             term_last_cmd_buf_size = 0;
             /* NOTE: readline_start can be called here */
-            term_readline_func(term_readline_opaque, term_cmd_buf);
+            term_readline_func(mon, term_cmd_buf, term_readline_opaque);
             break;
         case 23:
             /* ^W */
diff --git a/readline.h b/readline.h
new file mode 100644
index 0000000..c5c10d6
--- /dev/null
+++ b/readline.h
@@ -0,0 +1,20 @@
+#ifndef READLINE_H
+#define READLINE_H
+
+#include "qemu-common.h"
+
+typedef void ReadLineFunc(Monitor *mon, const char *str, void *opaque);
+
+void readline_add_completion(const char *str);
+void readline_set_completion_index(int index);
+void readline_find_completion(const char *cmdline);
+
+const char *readline_get_history(unsigned int index);
+
+void readline_handle_byte(int ch);
+
+void readline_start(const char *prompt, int is_password,
+                    ReadLineFunc *readline_func, void *opaque);
+void readline_show_prompt(void);
+
+#endif /* !READLINE_H */
diff --git a/savevm.c b/savevm.c
index 3eb2000..bea6885 100644
--- a/savevm.c
+++ b/savevm.c
@@ -24,7 +24,7 @@
 #include "qemu-common.h"
 #include "hw/hw.h"
 #include "net.h"
-#include "console.h"
+#include "monitor.h"
 #include "sysemu.h"
 #include "qemu-timer.h"
 #include "qemu-char.h"
@@ -993,7 +993,7 @@ static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
     return ret;
 }
 
-void do_savevm(const char *name)
+void do_savevm(Monitor *mon, const char *name)
 {
     BlockDriverState *bs, *bs1;
     QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
@@ -1010,7 +1010,7 @@ void do_savevm(const char *name)
 
     bs = get_bs_snapshots();
     if (!bs) {
-        term_printf("No block device can accept snapshots\n");
+        monitor_printf(mon, "No block device can accept snapshots\n");
         return;
     }
 
@@ -1049,22 +1049,22 @@ void do_savevm(const char *name)
     sn->vm_clock_nsec = qemu_get_clock(vm_clock);
 
     if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
-        term_printf("Device %s does not support VM state snapshots\n",
-                    bdrv_get_device_name(bs));
+        monitor_printf(mon, "Device %s does not support VM state snapshots\n",
+                       bdrv_get_device_name(bs));
         goto the_end;
     }
 
     /* save the VM state */
     f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 1);
     if (!f) {
-        term_printf("Could not open VM state file\n");
+        monitor_printf(mon, "Could not open VM state file\n");
         goto the_end;
     }
     ret = qemu_savevm_state(f);
     vm_state_size = qemu_ftell(f);
     qemu_fclose(f);
     if (ret < 0) {
-        term_printf("Error %d while writing VM\n", ret);
+        monitor_printf(mon, "Error %d while writing VM\n", ret);
         goto the_end;
     }
 
@@ -1076,16 +1076,17 @@ void do_savevm(const char *name)
             if (must_delete) {
                 ret = bdrv_snapshot_delete(bs1, old_sn->id_str);
                 if (ret < 0) {
-                    term_printf("Error while deleting snapshot on '%s'\n",
-                                bdrv_get_device_name(bs1));
+                    monitor_printf(mon,
+                                   "Error while deleting snapshot on '%s'\n",
+                                   bdrv_get_device_name(bs1));
                 }
             }
             /* Write VM state size only to the image that contains the state */
             sn->vm_state_size = (bs == bs1 ? vm_state_size : 0);
             ret = bdrv_snapshot_create(bs1, sn);
             if (ret < 0) {
-                term_printf("Error while creating snapshot on '%s'\n",
-                            bdrv_get_device_name(bs1));
+                monitor_printf(mon, "Error while creating snapshot on '%s'\n",
+                               bdrv_get_device_name(bs1));
             }
         }
     }
@@ -1095,7 +1096,7 @@ void do_savevm(const char *name)
         vm_start();
 }
 
-void do_loadvm(const char *name)
+void do_loadvm(Monitor *mon, const char *name)
 {
     BlockDriverState *bs, *bs1;
     BlockDriverInfo bdi1, *bdi = &bdi1;
@@ -1106,7 +1107,7 @@ void do_loadvm(const char *name)
 
     bs = get_bs_snapshots();
     if (!bs) {
-        term_printf("No block device supports snapshots\n");
+        monitor_printf(mon, "No block device supports snapshots\n");
         return;
     }
 
@@ -1122,19 +1123,21 @@ void do_loadvm(const char *name)
             ret = bdrv_snapshot_goto(bs1, name);
             if (ret < 0) {
                 if (bs != bs1)
-                    term_printf("Warning: ");
+                    monitor_printf(mon, "Warning: ");
                 switch(ret) {
                 case -ENOTSUP:
-                    term_printf("Snapshots not supported on device '%s'\n",
-                                bdrv_get_device_name(bs1));
+                    monitor_printf(mon,
+                                   "Snapshots not supported on device '%s'\n",
+                                   bdrv_get_device_name(bs1));
                     break;
                 case -ENOENT:
-                    term_printf("Could not find snapshot '%s' on device '%s'\n",
-                                name, bdrv_get_device_name(bs1));
+                    monitor_printf(mon, "Could not find snapshot '%s' on "
+                                   "device '%s'\n",
+                                   name, bdrv_get_device_name(bs1));
                     break;
                 default:
-                    term_printf("Error %d while activating snapshot on '%s'\n",
-                                ret, bdrv_get_device_name(bs1));
+                    monitor_printf(mon, "Error %d while activating snapshot on"
+                                   " '%s'\n", ret, bdrv_get_device_name(bs1));
                     break;
                 }
                 /* fatal on snapshot block device */
@@ -1145,8 +1148,8 @@ void do_loadvm(const char *name)
     }
 
     if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
-        term_printf("Device %s does not support VM state snapshots\n",
-                    bdrv_get_device_name(bs));
+        monitor_printf(mon, "Device %s does not support VM state snapshots\n",
+                       bdrv_get_device_name(bs));
         return;
     }
 
@@ -1158,27 +1161,27 @@ void do_loadvm(const char *name)
     /* restore the VM state */
     f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 0);
     if (!f) {
-        term_printf("Could not open VM state file\n");
+        monitor_printf(mon, "Could not open VM state file\n");
         goto the_end;
     }
     ret = qemu_loadvm_state(f);
     qemu_fclose(f);
     if (ret < 0) {
-        term_printf("Error %d while loading VM state\n", ret);
+        monitor_printf(mon, "Error %d while loading VM state\n", ret);
     }
  the_end:
     if (saved_vm_running)
         vm_start();
 }
 
-void do_delvm(const char *name)
+void do_delvm(Monitor *mon, const char *name)
 {
     BlockDriverState *bs, *bs1;
     int i, ret;
 
     bs = get_bs_snapshots();
     if (!bs) {
-        term_printf("No block device supports snapshots\n");
+        monitor_printf(mon, "No block device supports snapshots\n");
         return;
     }
 
@@ -1188,17 +1191,18 @@ void do_delvm(const char *name)
             ret = bdrv_snapshot_delete(bs1, name);
             if (ret < 0) {
                 if (ret == -ENOTSUP)
-                    term_printf("Snapshots not supported on device '%s'\n",
-                                bdrv_get_device_name(bs1));
+                    monitor_printf(mon,
+                                   "Snapshots not supported on device '%s'\n",
+                                   bdrv_get_device_name(bs1));
                 else
-                    term_printf("Error %d while deleting snapshot on '%s'\n",
-                                ret, bdrv_get_device_name(bs1));
+                    monitor_printf(mon, "Error %d while deleting snapshot on "
+                                   "'%s'\n", ret, bdrv_get_device_name(bs1));
             }
         }
     }
 }
 
-void do_info_snapshots(void)
+void do_info_snapshots(Monitor *mon)
 {
     BlockDriverState *bs, *bs1;
     QEMUSnapshotInfo *sn_tab, *sn;
@@ -1207,29 +1211,30 @@ void do_info_snapshots(void)
 
     bs = get_bs_snapshots();
     if (!bs) {
-        term_printf("No available block device supports snapshots\n");
+        monitor_printf(mon, "No available block device supports snapshots\n");
         return;
     }
-    term_printf("Snapshot devices:");
+    monitor_printf(mon, "Snapshot devices:");
     for(i = 0; i <= nb_drives; i++) {
         bs1 = drives_table[i].bdrv;
         if (bdrv_has_snapshot(bs1)) {
             if (bs == bs1)
-                term_printf(" %s", bdrv_get_device_name(bs1));
+                monitor_printf(mon, " %s", bdrv_get_device_name(bs1));
         }
     }
-    term_printf("\n");
+    monitor_printf(mon, "\n");
 
     nb_sns = bdrv_snapshot_list(bs, &sn_tab);
     if (nb_sns < 0) {
-        term_printf("bdrv_snapshot_list: error %d\n", nb_sns);
+        monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
         return;
     }
-    term_printf("Snapshot list (from %s):\n", bdrv_get_device_name(bs));
-    term_printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
+    monitor_printf(mon, "Snapshot list (from %s):\n",
+                   bdrv_get_device_name(bs));
+    monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
     for(i = 0; i < nb_sns; i++) {
         sn = &sn_tab[i];
-        term_printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
+        monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
     }
     qemu_free(sn_tab);
 }
diff --git a/slirp/misc.c b/slirp/misc.c
index f558b3c..b4c73d1 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -557,14 +557,14 @@ relay(s)
 #endif
 
 #ifdef CONFIG_QEMU
-extern void term_vprintf(const char *fmt, va_list ap);
+#include "monitor.h"
 
 void lprint(const char *format, ...)
 {
     va_list args;
 
     va_start(args, format);
-    term_vprintf(format, args);
+    monitor_vprintf(cur_mon, format, args);
     va_end(args);
 }
 #else
diff --git a/sysemu.h b/sysemu.h
index 57217c1..8775412 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -2,6 +2,8 @@
 #define SYSEMU_H
 /* Misc. things related to the system emulator.  */
 
+#include "qemu-common.h"
+
 /* vl.c */
 extern const char *bios_name;
 extern const char *bios_dir;
@@ -39,10 +41,10 @@ void qemu_system_powerdown(void);
 #endif
 void qemu_system_reset(void);
 
-void do_savevm(const char *name);
-void do_loadvm(const char *name);
-void do_delvm(const char *name);
-void do_info_snapshots(void);
+void do_savevm(Monitor *mon, const char *name);
+void do_loadvm(Monitor *mon, const char *name);
+void do_delvm(Monitor *mon, const char *name);
+void do_info_snapshots(Monitor *mon);
 
 void qemu_announce_self(void);
 
@@ -75,7 +77,7 @@ int tap_win32_init(VLANState *vlan, const char *model,
                    const char *name, const char *ifname);
 
 /* SLIRP */
-void do_info_slirp(void);
+void do_info_slirp(Monitor *mon);
 
 extern int bios_size;
 extern int cirrus_vga_enabled;
@@ -179,9 +181,10 @@ void destroy_nic(dev_match_fn *match_fn, void *arg);
 void destroy_bdrvs(dev_match_fn *match_fn, void *arg);
 
 /* pci-hotplug */
-void pci_device_hot_add(const char *pci_addr, const char *type, const char *opts);
-void drive_hot_add(const char *pci_addr, const char *opts);
-void pci_device_hot_remove(const char *pci_addr);
+void pci_device_hot_add(Monitor *mon, const char *pci_addr, const char *type,
+                        const char *opts);
+void drive_hot_add(Monitor *mon, const char *pci_addr, const char *opts);
+void pci_device_hot_remove(Monitor *mon, const char *pci_addr);
 void pci_device_hot_remove_success(int pcibus, int slot);
 
 /* serial ports */
@@ -237,9 +240,9 @@ struct soundhw {
 extern struct soundhw soundhw[];
 #endif
 
-void do_usb_add(const char *devname);
-void do_usb_del(const char *devname);
-void usb_info(void);
+void do_usb_add(Monitor *mon, const char *devname);
+void do_usb_del(Monitor *mon, const char *devname);
+void usb_info(Monitor *mon);
 
 const char *get_opt_name(char *buf, int buf_size, const char *p);
 const char *get_opt_value(char *buf, int buf_size, const char *p);
diff --git a/usb-linux.c b/usb-linux.c
index f19f0c4..70d7a1c 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -32,7 +32,7 @@
 
 #include "qemu-common.h"
 #include "qemu-timer.h"
-#include "console.h"
+#include "monitor.h"
 
 #include <dirent.h>
 #include <sys/ioctl.h>
@@ -985,6 +985,7 @@ static int usb_host_auto_del(const char *spec);
 
 USBDevice *usb_host_device_open(const char *devname)
 {
+    Monitor *mon = cur_mon;
     int bus_num, addr;
     char product_name[PRODUCT_NAME_SZ];
 
@@ -998,7 +999,8 @@ USBDevice *usb_host_device_open(const char *devname)
         return NULL;
 
     if (hostdev_find(bus_num, addr)) {
-       term_printf("husb: host usb device %d.%d is already open\n", bus_num, addr);
+       monitor_printf(mon, "husb: host usb device %d.%d is already open\n",
+                      bus_num, addr);
        return NULL;
     }
 
@@ -1149,6 +1151,7 @@ static int usb_host_scan_dev(void *opaque, USBScanFunc *func)
  */
 static int usb_host_read_file(char *line, size_t line_size, const char *device_file, const char *device_name)
 {
+    Monitor *mon = cur_mon;
     FILE *f;
     int ret = 0;
     char filename[PATH_MAX];
@@ -1161,7 +1164,7 @@ static int usb_host_read_file(char *line, size_t line_size, const char *device_f
         fclose(f);
         ret = 1;
     } else {
-        term_printf("husb: could not open %s\n", filename);
+        monitor_printf(mon, "husb: could not open %s\n", filename);
     }
 
     return ret;
@@ -1254,6 +1257,7 @@ static int usb_host_scan_sys(void *opaque, USBScanFunc *func)
  */
 static int usb_host_scan(void *opaque, USBScanFunc *func)
 {
+    Monitor *mon = cur_mon;
     FILE *f = 0;
     DIR *dir = 0;
     int ret = 0;
@@ -1292,14 +1296,15 @@ static int usb_host_scan(void *opaque, USBScanFunc *func)
         }
     found_devices:
         if (!usb_fs_type) {
-            term_printf("husb: unable to access USB devices\n");
+            monitor_printf(mon, "husb: unable to access USB devices\n");
             return -ENOENT;
         }
 
         /* the module setting (used later for opening devices) */
         usb_host_device_path = qemu_mallocz(strlen(devpath)+1);
         strcpy(usb_host_device_path, devpath);
-        term_printf("husb: using %s file-system with %s\n", fs_type[usb_fs_type], usb_host_device_path);
+        monitor_printf(mon, "husb: using %s file-system with %s\n",
+                       fs_type[usb_fs_type], usb_host_device_path);
     }
 
     switch (usb_fs_type) {
@@ -1606,6 +1611,7 @@ static void usb_info_device(int bus_num, int addr, int class_id,
                             const char *product_name,
                             int speed)
 {
+    Monitor *mon = cur_mon;
     const char *class_str, *speed_str;
 
     switch(speed) {
@@ -1623,17 +1629,17 @@ static void usb_info_device(int bus_num, int addr, int class_id,
         break;
     }
 
-    term_printf("  Device %d.%d, speed %s Mb/s\n",
+    monitor_printf(mon, "  Device %d.%d, speed %s Mb/s\n",
                 bus_num, addr, speed_str);
     class_str = usb_class_str(class_id);
     if (class_str)
-        term_printf("    %s:", class_str);
+        monitor_printf(mon, "    %s:", class_str);
     else
-        term_printf("    Class %02x:", class_id);
-    term_printf(" USB device %04x:%04x", vendor_id, product_id);
+        monitor_printf(mon, "    Class %02x:", class_id);
+    monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id);
     if (product_name[0] != '\0')
-        term_printf(", %s", product_name);
-    term_printf("\n");
+        monitor_printf(mon, ", %s", product_name);
+    monitor_printf(mon, "\n");
 }
 
 static int usb_host_info_device(void *opaque, int bus_num, int addr,
@@ -1663,20 +1669,21 @@ static void hex2str(int val, char *str, size_t size)
         snprintf(str, size, "%x", val);
 }
 
-void usb_host_info(void)
+void usb_host_info(Monitor *mon)
 {
     struct USBAutoFilter *f;
 
     usb_host_scan(NULL, usb_host_info_device);
 
     if (usb_auto_filter)
-        term_printf("  Auto filters:\n");
+        monitor_printf(mon, "  Auto filters:\n");
     for (f = usb_auto_filter; f; f = f->next) {
         char bus[10], addr[10], vid[10], pid[10];
         dec2str(f->bus_num, bus, sizeof(bus));
         dec2str(f->addr, addr, sizeof(addr));
         hex2str(f->vendor_id, vid, sizeof(vid));
         hex2str(f->product_id, pid, sizeof(pid));
-    	term_printf("    Device %s.%s ID %s:%s\n", bus, addr, vid, pid);
+        monitor_printf(mon, "    Device %s.%s ID %s:%s\n",
+                       bus, addr, vid, pid);
     }
 }
diff --git a/vl.c b/vl.c
index 89883c3..1de2f00 100644
--- a/vl.c
+++ b/vl.c
@@ -31,6 +31,7 @@
 #include "hw/baum.h"
 #include "hw/bt.h"
 #include "net.h"
+#include "monitor.h"
 #include "console.h"
 #include "sysemu.h"
 #include "gdbstub.h"
@@ -652,34 +653,34 @@ int kbd_mouse_is_absolute(void)
     return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute;
 }
 
-void do_info_mice(void)
+void do_info_mice(Monitor *mon)
 {
     QEMUPutMouseEntry *cursor;
     int index = 0;
 
     if (!qemu_put_mouse_event_head) {
-        term_printf("No mouse devices connected\n");
+        monitor_printf(mon, "No mouse devices connected\n");
         return;
     }
 
-    term_printf("Mouse devices available:\n");
+    monitor_printf(mon, "Mouse devices available:\n");
     cursor = qemu_put_mouse_event_head;
     while (cursor != NULL) {
-        term_printf("%c Mouse #%d: %s\n",
-                    (cursor == qemu_put_mouse_event_current ? '*' : ' '),
-                    index, cursor->qemu_put_mouse_event_name);
+        monitor_printf(mon, "%c Mouse #%d: %s\n",
+                       (cursor == qemu_put_mouse_event_current ? '*' : ' '),
+                       index, cursor->qemu_put_mouse_event_name);
         index++;
         cursor = cursor->next;
     }
 }
 
-void do_mouse_set(int index)
+void do_mouse_set(Monitor *mon, int index)
 {
     QEMUPutMouseEntry *cursor;
     int i = 0;
 
     if (!qemu_put_mouse_event_head) {
-        term_printf("No mouse devices connected\n");
+        monitor_printf(mon, "No mouse devices connected\n");
         return;
     }
 
@@ -692,7 +693,7 @@ void do_mouse_set(int index)
     if (cursor != NULL)
         qemu_put_mouse_event_current = cursor;
     else
-        term_printf("Mouse at given index not found\n");
+        monitor_printf(mon, "Mouse at given index not found\n");
 }
 
 /* compute with 96 bit intermediate result: (a*b)/c */
@@ -2696,7 +2697,8 @@ static int usb_device_add(const char *devname, int is_hotplug)
         if (bdrv_key_required(bs)) {
             autostart = 0;
             if (is_hotplug) {
-                monitor_read_bdrv_key_start(bs, usb_msd_password_cb, dev);
+                monitor_read_bdrv_key_start(cur_mon, bs, usb_msd_password_cb,
+                                            dev);
                 return 0;
             }
         }
@@ -2778,24 +2780,24 @@ static int usb_device_del(const char *devname)
     return usb_device_del_addr(bus_num, addr);
 }
 
-void do_usb_add(const char *devname)
+void do_usb_add(Monitor *mon, const char *devname)
 {
     usb_device_add(devname, 1);
 }
 
-void do_usb_del(const char *devname)
+void do_usb_del(Monitor *mon, const char *devname)
 {
     usb_device_del(devname);
 }
 
-void usb_info(void)
+void usb_info(Monitor *mon)
 {
     USBDevice *dev;
     USBPort *port;
     const char *speed_str;
 
     if (!usb_enabled) {
-        term_printf("USB support not enabled\n");
+        monitor_printf(mon, "USB support not enabled\n");
         return;
     }
 
@@ -2817,8 +2819,8 @@ void usb_info(void)
             speed_str = "?";
             break;
         }
-        term_printf("  Device %d.%d, Speed %s Mb/s, Product %s\n",
-                    0, dev->addr, speed_str, dev->devname);
+        monitor_printf(mon, "  Device %d.%d, Speed %s Mb/s, Product %s\n",
+                       0, dev->addr, speed_str, dev->devname);
     }
 }
 
@@ -2852,16 +2854,17 @@ void pcmcia_socket_unregister(struct pcmcia_socket_s *socket)
         }
 }
 
-void pcmcia_info(void)
+void pcmcia_info(Monitor *mon)
 {
     struct pcmcia_socket_entry_s *iter;
+
     if (!pcmcia_sockets)
-        term_printf("No PCMCIA sockets\n");
+        monitor_printf(mon, "No PCMCIA sockets\n");
 
     for (iter = pcmcia_sockets; iter; iter = iter->next)
-        term_printf("%s: %s\n", iter->socket->slot_string,
-                    iter->socket->attached ? iter->socket->card_string :
-                    "Empty");
+        monitor_printf(mon, "%s: %s\n", iter->socket->slot_string,
+                       iter->socket->attached ? iter->socket->card_string :
+                       "Empty");
 }
 
 /***********************************************************/
@@ -5700,7 +5703,7 @@ int main(int argc, char **argv, char **envp)
 #endif
 
     if (loadvm)
-        do_loadvm(loadvm);
+        do_loadvm(cur_mon, loadvm);
 
     if (incoming) {
         autostart = 0; /* fixme how to deal with -daemonize */
diff --git a/vnc.c b/vnc.c
index 81c842a..67cec07 100644
--- a/vnc.c
+++ b/vnc.c
@@ -24,6 +24,7 @@
  */
 
 #include "qemu-common.h"
+#include "monitor.h"
 #include "console.h"
 #include "sysemu.h"
 #include "qemu_socket.h"
@@ -166,19 +167,19 @@ struct VncState
 static VncDisplay *vnc_display; /* needed for info vnc */
 static DisplayChangeListener *dcl;
 
-void do_info_vnc(void)
+void do_info_vnc(Monitor *mon)
 {
     if (vnc_display == NULL || vnc_display->display == NULL)
-	term_printf("VNC server disabled\n");
+        monitor_printf(mon, "VNC server disabled\n");
     else {
-	term_printf("VNC server active on: ");
-	term_print_filename(vnc_display->display);
-	term_printf("\n");
+        monitor_printf(mon, "VNC server active on: ");
+        monitor_print_filename(mon, vnc_display->display);
+        monitor_printf(mon, "\n");
 
 	if (vnc_display->clients == NULL)
-	    term_printf("No client connected\n");
+            monitor_printf(mon, "No client connected\n");
 	else
-	    term_printf("Client connected\n");
+	    monitor_printf(mon, "Client connected\n");
     }
 }
 
@@ -807,10 +808,11 @@ static void audio_capture(void *opaque, void *buf, int size)
 
 static void audio_add(VncState *vs)
 {
+    Monitor *mon = cur_mon;
     struct audio_capture_ops ops;
 
     if (vs->audio_cap) {
-        term_printf ("audio already running\n");
+        monitor_printf(mon, "audio already running\n");
         return;
     }
 
@@ -820,7 +822,7 @@ static void audio_add(VncState *vs)
 
     vs->audio_cap = AUD_add_capture(NULL, &vs->as, &ops, vs);
     if (!vs->audio_cap) {
-        term_printf ("Failed to add audio capture\n");
+        monitor_printf(mon, "Failed to add audio capture\n");
     }
 }
 

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [Qemu-devel] [PATCH v2 17/19] monitor: Improve mux'ed console experience
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (12 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 13/19] monitor: Rework terminal management Jan Kiszka
@ 2009-02-21 18:29 ` Jan Kiszka
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 15/19] monitor: Introduce ReadLineState Jan Kiszka
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-21 18:29 UTC (permalink / raw)
  To: qemu-devel

Up to now, you never really knew if you already switched the console
after pressing CTRL-A C or if you mistyped it again. This patch
clarifies the situation by providing a prompt in a new line and
injecting a linebreak when switching away again. For this purpose, the
two events CHR_EVENT_MUX_IN and CHR_EVENT_MUX_OUT are introduced and
distributed on focus switches.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 monitor.c   |   27 ++++++++++++++++++++++-----
 qemu-char.c |   11 +++++++++--
 qemu-char.h |    8 +++++---
 readline.c  |    5 +++++
 readline.h  |    1 +
 5 files changed, 42 insertions(+), 10 deletions(-)

diff --git a/monitor.c b/monitor.c
index ba0e9a8..7cae863 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2887,12 +2887,27 @@ static void monitor_event(void *opaque, int event)
 {
     Monitor *mon = opaque;
 
-    if (event != CHR_EVENT_RESET)
-	return;
+    switch (event) {
+    case CHR_EVENT_MUX_IN:
+        readline_restart(mon->rs);
+        monitor_resume(mon);
+        monitor_flush(mon);
+        break;
+
+    case CHR_EVENT_MUX_OUT:
+        if (mon->suspend_cnt == 0)
+            monitor_printf(mon, "\n");
+        monitor_flush(mon);
+        monitor_suspend(mon);
+        break;
 
-    monitor_printf(mon, "QEMU %s monitor - type 'help' for more information\n",
-                   QEMU_VERSION);
-    readline_show_prompt(mon->rs);
+    case CHR_EVENT_RESET:
+        monitor_printf(mon, "QEMU %s monitor - type 'help' for more "
+                       "information\n", QEMU_VERSION);
+        if (mon->chr->focus == 0)
+            readline_show_prompt(mon->rs);
+        break;
+    }
 }
 
 void monitor_init(CharDriverState *chr, int flags)
@@ -2909,6 +2924,8 @@ void monitor_init(CharDriverState *chr, int flags)
 
     mon->chr = chr;
     mon->flags = flags;
+    if (mon->chr->focus != 0)
+        mon->suspend_cnt = 1; /* mux'ed monitors start suspended */
     mon->rs = readline_init(mon, monitor_find_completion);
     monitor_read_command(mon, 0);
 
diff --git a/qemu-char.c b/qemu-char.c
index f815646..8c5544c 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -310,6 +310,12 @@ static void mux_print_help(CharDriverState *chr)
     }
 }
 
+static void mux_chr_send_event(MuxDriver *d, int mux_nr, int event)
+{
+    if (d->chr_event[mux_nr])
+        d->chr_event[mux_nr](d->ext_opaque[mux_nr], event);
+}
+
 static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
 {
     if (d->term_got_escape) {
@@ -341,9 +347,11 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
             break;
         case 'c':
             /* Switch to the next registered device */
+            mux_chr_send_event(d, chr->focus, CHR_EVENT_MUX_OUT);
             chr->focus++;
             if (chr->focus >= d->mux_cnt)
                 chr->focus = 0;
+            mux_chr_send_event(d, chr->focus, CHR_EVENT_MUX_IN);
             break;
        case 't':
            term_timestamps = !term_timestamps;
@@ -413,8 +421,7 @@ static void mux_chr_event(void *opaque, int event)
 
     /* Send the event to all registered listeners */
     for (i = 0; i < d->mux_cnt; i++)
-        if (d->chr_event[i])
-            d->chr_event[i](d->ext_opaque[i], event);
+        mux_chr_send_event(d, i, event);
 }
 
 static void mux_chr_update_read_handler(CharDriverState *chr)
diff --git a/qemu-char.h b/qemu-char.h
index e5ad45c..e1aa8db 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -6,9 +6,11 @@
 
 /* character device */
 
-#define CHR_EVENT_BREAK 0 /* serial break char */
-#define CHR_EVENT_FOCUS 1 /* focus to this terminal (modal input needed) */
-#define CHR_EVENT_RESET 2 /* new connection established */
+#define CHR_EVENT_BREAK   0 /* serial break char */
+#define CHR_EVENT_FOCUS   1 /* focus to this terminal (modal input needed) */
+#define CHR_EVENT_RESET   2 /* new connection established */
+#define CHR_EVENT_MUX_IN  3 /* mux-focus was set to this terminal */
+#define CHR_EVENT_MUX_OUT 4 /* mux-focus will move on */
 
 
 #define CHR_IOCTL_SERIAL_SET_PARAMS   1
diff --git a/readline.c b/readline.c
index 1868b10..9c4b68b 100644
--- a/readline.c
+++ b/readline.c
@@ -444,6 +444,11 @@ void readline_start(ReadLineState *rs, const char *prompt, int read_password,
     rs->readline_func = readline_func;
     rs->readline_opaque = opaque;
     rs->read_password = read_password;
+    readline_restart(rs);
+}
+
+void readline_restart(ReadLineState *rs)
+{
     rs->cmd_buf_index = 0;
     rs->cmd_buf_size = 0;
 }
diff --git a/readline.h b/readline.h
index fcf0f33..fc9806e 100644
--- a/readline.h
+++ b/readline.h
@@ -46,6 +46,7 @@ void readline_handle_byte(ReadLineState *rs, int ch);
 
 void readline_start(ReadLineState *rs, const char *prompt, int read_password,
                     ReadLineFunc *readline_func, void *opaque);
+void readline_restart(ReadLineState *rs);
 void readline_show_prompt(ReadLineState *rs);
 
 ReadLineState *readline_init(Monitor *mon,

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [Qemu-devel] [PATCH v2 00/19] monitor rework
  2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
                   ` (18 preceding siblings ...)
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 19/19] monitor: Pass-through for gdbstub Jan Kiszka
@ 2009-02-27 17:43 ` Anthony Liguori
  2009-02-27 17:57   ` [Qemu-devel] " Jan Kiszka
  19 siblings, 1 reply; 25+ messages in thread
From: Anthony Liguori @ 2009-02-27 17:43 UTC (permalink / raw)
  To: qemu-devel

Jan Kiszka wrote:
> Looks like each round of this series makes it longer and longer... :)
>
> Changes in this version:
>  o consequent rework of the monitor API (as Anthony suggested)
>     - introduce mon argument to monitor services
>     - pass mon to monitor command handlers
>  o fix for broken initial CHR_EVENT_RESET
>  o proper monitor default size
>  o more testing, various fixes
>    (e.g. telnet monitors didn't work with v1)
>
> To recall the major contributions of this series:
>  o complete fix for early disk password inquiry
>  o non-VM-blocking password inquiry
>  o unlimited and fully decoupled monitor terminals
>  o monitor pass-through via gdb
>  o improved usability of mux'ed monitor terminals
>
> Ideally, the series would go in before the upcoming release.

It's too much for this release (which is hopefully days away).

I suspect that even after thorough review, there will be a few bugs that 
this series uncovers.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Qemu-devel] Re: [PATCH v2 00/19] monitor rework
  2009-02-27 17:43 ` [Qemu-devel] [PATCH v2 00/19] monitor rework Anthony Liguori
@ 2009-02-27 17:57   ` Jan Kiszka
  2009-02-27 19:53     ` Anthony Liguori
  0 siblings, 1 reply; 25+ messages in thread
From: Jan Kiszka @ 2009-02-27 17:57 UTC (permalink / raw)
  To: qemu-devel

Anthony Liguori wrote:
> Jan Kiszka wrote:
>> Looks like each round of this series makes it longer and longer... :)
>>
>> Changes in this version:
>>  o consequent rework of the monitor API (as Anthony suggested)
>>     - introduce mon argument to monitor services
>>     - pass mon to monitor command handlers
>>  o fix for broken initial CHR_EVENT_RESET
>>  o proper monitor default size
>>  o more testing, various fixes
>>    (e.g. telnet monitors didn't work with v1)
>>
>> To recall the major contributions of this series:
>>  o complete fix for early disk password inquiry
>>  o non-VM-blocking password inquiry
>>  o unlimited and fully decoupled monitor terminals
>>  o monitor pass-through via gdb
>>  o improved usability of mux'ed monitor terminals
>>
>> Ideally, the series would go in before the upcoming release.
> 
> It's too much for this release (which is hopefully days away).
> 
> I suspect that even after thorough review, there will be a few bugs that
> this series uncovers.

Just keep in mind that we then start with a few regressions around
encrypted disks (leaving them mostly unusable). Or do you plan to merge
the bug-fixing part into the stable tree later on?

Jan

-- 
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Qemu-devel] Re: [PATCH v2 00/19] monitor rework
  2009-02-27 17:57   ` [Qemu-devel] " Jan Kiszka
@ 2009-02-27 19:53     ` Anthony Liguori
  2009-02-27 21:06       ` Jan Kiszka
  0 siblings, 1 reply; 25+ messages in thread
From: Anthony Liguori @ 2009-02-27 19:53 UTC (permalink / raw)
  To: qemu-devel

Jan Kiszka wrote:
> Just keep in mind that we then start with a few regressions around
> encrypted disks (leaving them mostly unusable). Or do you plan to merge
> the bug-fixing part into the stable tree later on?
>   

Good question.  Is it possible to separate the bug fixing parts from 
more of the general refactoring?

Regards,

Anthony Liguori

> Jan
>
>   

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Qemu-devel] Re: [PATCH v2 00/19] monitor rework
  2009-02-27 19:53     ` Anthony Liguori
@ 2009-02-27 21:06       ` Jan Kiszka
  0 siblings, 0 replies; 25+ messages in thread
From: Jan Kiszka @ 2009-02-27 21:06 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 489 bytes --]

Anthony Liguori wrote:
> Jan Kiszka wrote:
>> Just keep in mind that we then start with a few regressions around
>> encrypted disks (leaving them mostly unusable). Or do you plan to merge
>> the bug-fixing part into the stable tree later on?
>>   
> 
> Good question.  Is it possible to separate the bug fixing parts from
> more of the general refactoring?

As I said: find bug fixes or small polishing in patches 1..8. They
should be considered for a stable version.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Qemu-devel] [PATCH v2 01/19] char: Fix initial reset
  2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 01/19] char: Fix initial reset Jan Kiszka
@ 2009-03-05 23:01   ` Anthony Liguori
  0 siblings, 0 replies; 25+ messages in thread
From: Anthony Liguori @ 2009-03-05 23:01 UTC (permalink / raw)
  To: qemu-devel

Jan Kiszka wrote:
> Recent changes to the graphical console initialization broke the initial
> CHR_EVENT_RESET distribution. The reset BHs generated on char device
> initialization are now already consumed during machine init (ide init
> ... -> qemu_aio_wait -> qemu_bh_poll). Therefore, this patch moves the
> initial qemu_chr_reset calls into a separate funtion which is called
> after machine init.
>
>   

Applied 1-8 to stable and the whole series to trunk.  Thanks.  The big 
term_printf -> monitor_printf() conversion was missing some calls but I 
fixed those.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2009-03-05 23:01 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-21 18:29 [Qemu-devel] [PATCH v2 00/19] monitor rework Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 01/19] char: Fix initial reset Jan Kiszka
2009-03-05 23:01   ` Anthony Liguori
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 08/19] monitor: Rework early disk password inquiry Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 05/19] block: Introduce bdrv_get_encrypted_filename Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 04/19] block: Improve bdrv_iterate Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 02/19] char-mux: Use separate input buffers Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 07/19] monitor: Report encrypted disks in snapshot mode Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 10/19] monitor: Break out readline_show_prompt Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 06/19] monitor: Use reasonable default virtual console size Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 03/19] block: Polish error handling of brdv_open2 Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 09/19] monitor: Simplify password input mode Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 11/19] monitor: Rework modal password input Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 12/19] monitor: Rework API Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 13/19] monitor: Rework terminal management Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 17/19] monitor: Improve mux'ed console experience Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 15/19] monitor: Introduce ReadLineState Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 14/19] monitor: Drop banner hiding Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 18/19] monitor: Introduce MONITOR_USE_READLINE flag Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 16/19] monitor: Decouple terminals Jan Kiszka
2009-02-21 18:29 ` [Qemu-devel] [PATCH v2 19/19] monitor: Pass-through for gdbstub Jan Kiszka
2009-02-27 17:43 ` [Qemu-devel] [PATCH v2 00/19] monitor rework Anthony Liguori
2009-02-27 17:57   ` [Qemu-devel] " Jan Kiszka
2009-02-27 19:53     ` Anthony Liguori
2009-02-27 21:06       ` Jan Kiszka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).