From: Ian Jackson Date: Wed, 9 Jul 2008 11:32:09 +0000 (+0100) Subject: Store pty name in xenstore for the benefit of the tools. X-Git-Tag: xen-3.3.0-rc1~49 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=ec067fdd67d4f873343c751861e37aa5184ad97d;p=qemu-xen-3.3-testing.git Store pty name in xenstore for the benefit of the tools. This is a rather intrusive patch, because we need a mechanism to get the ptsname out of the guts of the qemu startup code. This is a first cut of such a thing which might eventually go upstream. The main new interface is chr_getname, a new CharDriverState method. If implemented it returns " " where currently "" is "pty" for ptys. If not implemented the function pointer may be null. We import store_dev_info from xen-unstable (17987:9b35ae586cb8) and eviscerate it appropriately. --- diff --git a/qemu-char.h b/qemu-char.h index 41936bc9..ef98ed52 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -44,6 +44,7 @@ struct CharDriverState { void (*chr_send_event)(struct CharDriverState *chr, int event); void (*chr_close)(struct CharDriverState *chr); void (*chr_accept_input)(struct CharDriverState *chr); + int (*chr_getname)(struct CharDriverState *s, char *buf, size_t buflen); void *opaque; int focus; QEMUBH *bh; diff --git a/vl.c b/vl.c index 0add8b60..442faf8f 100644 --- a/vl.c +++ b/vl.c @@ -2338,10 +2338,20 @@ void cfmakeraw (struct termios *termios_p) #endif #if defined(__linux__) || defined(__sun__) || defined(__NetBSD__) || defined(__OpenBSD__) +static int pty_getname(struct CharDriverState *chr, char *buf, size_t len) { + char *name; + FDCharDriver *s = chr->opaque; + + name = ptsname(s->fd_in); + if (!name) return -1; + return snprintf(buf,len, "pty %s", name); +} + static CharDriverState *qemu_chr_open_pty(void) { struct termios tty; int master_fd, slave_fd; + CharDriverState *chr; if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) < 0) { return NULL; @@ -2352,7 +2362,9 @@ static CharDriverState *qemu_chr_open_pty(void) tcsetattr(slave_fd, TCSAFLUSH, &tty); fprintf(stderr, "char device redirected to %s\n", ptsname(master_fd)); - return qemu_chr_open_fd(master_fd, master_fd); + chr = qemu_chr_open_fd(master_fd, master_fd); + chr->chr_getname = pty_getname; + return chr; } static void tty_serial_init(int fd, int speed, @@ -8767,6 +8779,7 @@ int main(int argc, char **argv) } if (strstart(devname, "vc", 0)) qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i); + xenstore_store_serial_port_info(i, serial_hds[i], devname); } } diff --git a/xen-config-host.h b/xen-config-host.h index 22377566..6e84a981 100644 --- a/xen-config-host.h +++ b/xen-config-host.h @@ -32,3 +32,6 @@ extern int vcpus; void xenstore_parse_domain_config(int domid); void xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen); +struct CharDriverState; +void xenstore_store_serial_port_info(int i, struct CharDriverState *chr, + const char *devname); diff --git a/xenstore.c b/xenstore.c index 78f39d03..059e519d 100644 --- a/xenstore.c +++ b/xenstore.c @@ -9,6 +9,7 @@ */ #include "qemu-common.h" +#include "qemu-char.h" #include "block_int.h" #include @@ -974,3 +975,89 @@ int xenstore_vm_write(int domid, char *key, char *value) free(buf); return rc; } + + +/* + * Create a store entry for a device (e.g., monitor, serial/parallel lines). + * The entry is /tty and the value is the name + * of the pty associated with the device. + */ +static int store_dev_info(const char *devName, int domid, + CharDriverState *cState, const char *storeString) +{ +#ifdef CONFIG_STUBDOM + fprintf(logfile, "can't store dev %s name for domid %d in %s from a stub domain\n", devName, domid, storeString); + return ENOSYS; +#else + int xc_handle; + struct xs_handle *xs; + char *path; + char *newpath; + char *pts; + char namebuf[128]; + int ret; + + /* + * Only continue if we're talking to a pty + */ + if (!cState->chr_getname) return 0; + ret = cState->chr_getname(cState, namebuf, sizeof(namebuf)); + if (ret < 0) { + fprintf(logfile, "ptsname failed (for '%s'): %s\n", + storeString, strerror(errno)); + return 0; + } + if (memcmp(namebuf, "pty ", 4)) return 0; + pts = namebuf + 4; + + /* We now have everything we need to set the xenstore entry. */ + xs = xs_daemon_open(); + if (xs == NULL) { + fprintf(logfile, "Could not contact XenStore\n"); + return -1; + } + + xc_handle = xc_interface_open(); + if (xc_handle == -1) { + fprintf(logfile, "xc_interface_open() error\n"); + return -1; + } + + path = xs_get_domain_path(xs, domid); + if (path == NULL) { + fprintf(logfile, "xs_get_domain_path() error\n"); + return -1; + } + newpath = realloc(path, (strlen(path) + strlen(storeString) + + strlen("/tty") + 1)); + if (newpath == NULL) { + free(path); /* realloc errors leave old block */ + fprintf(logfile, "realloc error\n"); + return -1; + } + path = newpath; + + strcat(path, storeString); + strcat(path, "/tty"); + if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) { + fprintf(logfile, "xs_write for '%s' fail", storeString); + return -1; + } + + free(path); + xs_daemon_close(xs); + close(xc_handle); + + return 0; +#endif +} + +void xenstore_store_serial_port_info(int i, CharDriverState *chr, + const char *devname) { + char buf[16]; + + snprintf(buf, sizeof(buf), "/serial/%d", i); + store_dev_info(devname, domid, chr, buf); + if (i == 0) /* serial 0 is also called the console */ + store_dev_info(devname, domid, chr, "/console"); +}