#include #include #include #include #include #include #include #include #include #include #include "qemu-gtk.h" #include "tcp.h" /* ----------------------------------------------------------------- */ static int monitor_parse(struct qemu_window *win, char *buf, int len) { char *reply, *prompt, *cmd; int off; prompt = strstr(buf, "(qemu) "); if (NULL == prompt) return 0; off = prompt - buf; if (prompt > buf+1 && prompt[-2] == '\r' && prompt[-1] == '\n') prompt -= 2; *prompt = 0; if (!win->mrun) goto out; cmd = win->mrun->cmd; reply = strstr(buf, "\r\n"); if (!reply) goto out; reply += 2; #if 0 fprintf(stderr, "\"%s\" -> [%s]\n--\n", cmd, reply); #endif if (0 == strcmp(cmd, "info version")) { snprintf(win->version, sizeof(win->version), "%s", reply); update_status(win); } else if (0 == strcmp(cmd, "info name")) { snprintf(win->name, sizeof(win->name), "%s", reply); update_status(win); } else if (0 == strcmp(cmd, "info vnc")) { if (1 == sscanf(reply, "VNC server active on: %127[^\r\n]", win->vnc_display) && strstr(reply, "No client connected")) vnc_connect(win); } out: return off + 7; } /* ----------------------------------------------------------------- */ static void monitor_next(struct qemu_window *win) { char buf[256]; int len; if (win->mrun) free(win->mrun); win->mrun = win->mqueue; if (!win->mrun) return; win->mqueue = win->mrun->next; len = snprintf(buf, sizeof(buf), "%s\n", win->mrun->cmd); write(win->monitor.handle, buf, len); } void monitor_append(struct qemu_window *win, char *cmd) { struct qemu_mq *mq; if (win->mqueue) { for (mq = win->mqueue; mq->next; mq = mq->next) ; mq->next = malloc(sizeof(*mq)); mq = mq->next; } else { win->mqueue = malloc(sizeof(*mq)); mq = win->mqueue; } mq->next = NULL; snprintf(mq->cmd, sizeof(mq->cmd), "%s", cmd); if (0 == win->mused) monitor_next(win); } static gboolean monitor_watch(GIOChannel *source, GIOCondition condition, gpointer userdata) { struct qemu_window *win = userdata; int rc; if (win->mused == win->msize) { if (!win->msize) win->msize = 4; win->msize *= 2; win->mbuf = realloc(win->mbuf, win->msize +1); } rc = read(win->monitor.handle, win->mbuf + win->mused, win->msize - win->mused); switch(rc) { case -1: if (EINTR == errno) break; perror("monitor: read"); goto close; case 0: fprintf(stderr, "monitor: EOF\n"); goto close; default: if (win->monitor.vte) vte_terminal_feed(VTE_TERMINAL(win->monitor.vte), win->mbuf + win->mused, rc); win->mused += rc; win->mbuf[win->mused] = 0; rc = monitor_parse(win, win->mbuf, win->mused); if (rc) { if (rc < win->mused) memmove(win->mbuf, win->mbuf + rc, win->mused - rc); win->mused -= rc; } break; } if (0 == win->mused) monitor_next(win); return TRUE; close: if (win->monitor.vte) vte_terminal_feed(VTE_TERMINAL(win->monitor.vte), "\r\n=== CLOSED ===", 16); close(win->monitor.handle); win->monitor.handle = -1; // gtk_widget_destroy(win->toplevel); return FALSE; } /* ----------------------------------------------------------------- */ int monitor_connect(struct qemu_window *win, char *dest) { int fd; fd = conn_init(&win->monitor, "monitor", dest); if (-1 == fd) return -1; win->monitor.ch = g_io_channel_unix_new(fd); win->monitor.id = g_io_add_watch(win->monitor.ch, G_IO_IN, monitor_watch, win); monitor_append(win, "info version"); monitor_append(win, "info name"); monitor_append(win, "info vnc"); return fd; }