diff mbox

[2/2] Add a 'screen' backend to qemu-char.c

Message ID 1271367673-18975-2-git-send-email-thomas@archlinux.org
State New
Headers show

Commit Message

Thomas Bächler April 15, 2010, 9:41 p.m. UTC
This backend uses the 'pty' backend, but attaches the pseudo tty to a screen.
A user can use 'screen:name' as a char device in a qemu options and run
'screen -R name' to attach to it.

This is very useful for running headless qemu/qemu-kvm machines, where you
can create screen sessions for the qemu monitor and serial console.
---
 qemu-char.c   |   33 +++++++++++++++++++++++++++++++--
 qemu-config.c |    3 +++
 2 files changed, 34 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/qemu-char.c b/qemu-char.c
index d845572..d82e4c6 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -973,7 +973,9 @@  static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
     CharDriverState *chr;
     PtyCharDriver *s;
     struct termios tty;
-    int slave_fd, len;
+    int slave_fd, len, r;
+    const char *screensession;
+    char *cmd;
 #if defined(__OpenBSD__) || defined(__DragonFly__)
     char pty_name[PATH_MAX];
 #define q_ptsname(x) pty_name
@@ -1001,7 +1003,29 @@  static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
     chr->filename = qemu_malloc(len);
     snprintf(chr->filename, len, "pty:%s", q_ptsname(s->fd));
     qemu_opt_set(opts, "path", q_ptsname(s->fd));
-    fprintf(stderr, "char device redirected to %s\n", q_ptsname(s->fd));
+
+    if((screensession = qemu_opt_get(opts, "screen")) != NULL) {
+        if(strlen(screensession) == 0) {
+            qemu_free(chr);
+            qemu_free(s);
+            return NULL;
+        }
+        len = strlen(screensession) + strlen(q_ptsname(s->fd)) + 20;
+        cmd = qemu_malloc(len);
+        snprintf(cmd, len, "screen -S '%s' -dm '%s'", screensession, q_ptsname(s->fd));
+        r = system(cmd);
+        qemu_free(cmd);
+        if(r == -1 || WEXITSTATUS(r) != 0) {
+            fprintf(stderr, "failed to launch screen\n");
+            qemu_free(chr);
+            qemu_free(s);
+            return NULL;
+        } else {
+            fprintf(stderr, "char device attached to screen session %s\n", screensession);
+        }
+    } else {
+        fprintf(stderr, "char device redirected to %s\n", q_ptsname(s->fd));
+    }
 
     chr->opaque = s;
     chr->chr_write = pty_chr_write;
@@ -2343,6 +2367,11 @@  QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
         qemu_opt_set(opts, "path", p);
         return opts;
     }
+    if (strstart(filename, "screen:", &p)) {
+        qemu_opt_set(opts, "backend", "pty");
+        qemu_opt_set(opts, "screen", p);
+        return opts;
+    }
     if (strstart(filename, "tcp:", &p) ||
         strstart(filename, "telnet:", &p)) {
         if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) {
diff --git a/qemu-config.c b/qemu-config.c
index 150157c..8ebf219 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -146,6 +146,9 @@  QemuOptsList qemu_chardev_opts = {
         },{
             .name = "signal",
             .type = QEMU_OPT_BOOL,
+        },{
+            .name = "screen",
+            .type = QEMU_OPT_STRING,
         },
         { /* end if list */ }
     },