diff -r 01fafeaa2f64 qemu_socket.h --- a/qemu_socket.h Thu Dec 14 20:48:11 2006 +0000 +++ b/qemu_socket.h Sat Dec 16 11:19:45 2006 -0600 @@ -19,6 +19,7 @@ #include #include #include +#include #define socket_error() errno #define closesocket(s) close(s) diff -r 01fafeaa2f64 vl.c --- a/vl.c Thu Dec 14 20:48:11 2006 +0000 +++ b/vl.c Sat Dec 16 11:42:40 2006 -0600 @@ -2206,6 +2206,7 @@ static void udp_chr_add_read_handler(Cha } int parse_host_port(struct sockaddr_in *saddr, const char *str); +int parse_unix_path(struct sockaddr_un *uaddr, const char *str); int parse_host_src_port(struct sockaddr_in *haddr, struct sockaddr_in *saddr, const char *str); @@ -2270,6 +2271,7 @@ typedef struct { int connected; int max_size; int do_telnetopt; + int is_unix; } TCPCharDriver; static void tcp_chr_accept(void *opaque); @@ -2291,6 +2293,8 @@ static int tcp_chr_read_poll(void *opaqu TCPCharDriver *s = chr->opaque; if (!s->connected) return 0; + if (!s->fd_can_read) + return 0; s->max_size = s->fd_can_read(s->fd_opaque); return s->max_size; } @@ -2416,12 +2420,25 @@ static void tcp_chr_accept(void *opaque) CharDriverState *chr = opaque; TCPCharDriver *s = chr->opaque; struct sockaddr_in saddr; +#ifndef _WIN32 + struct sockaddr_un uaddr; +#endif + struct sockaddr *addr; socklen_t len; int fd; for(;;) { - len = sizeof(saddr); - fd = accept(s->listen_fd, (struct sockaddr *)&saddr, &len); +#ifndef _WIN32 + if (s->is_unix) { + len = sizeof(uaddr); + addr = (struct sockaddr *)&uaddr; + } else +#endif + { + len = sizeof(saddr); + addr = (struct sockaddr *)&saddr; + } + fd = accept(s->listen_fd, addr, &len); if (fd < 0 && errno != EINTR) { return; } else if (fd >= 0) { @@ -2447,7 +2464,8 @@ static void tcp_chr_close(CharDriverStat } static CharDriverState *qemu_chr_open_tcp(const char *host_str, - int is_telnet) + int is_telnet, + int is_unix) { CharDriverState *chr = NULL; TCPCharDriver *s = NULL; @@ -2456,9 +2474,26 @@ static CharDriverState *qemu_chr_open_tc int is_waitconnect = 1; const char *ptr; struct sockaddr_in saddr; - - if (parse_host_port(&saddr, host_str) < 0) - goto fail; +#ifndef _WIN32 + struct sockaddr_un uaddr; +#endif + struct sockaddr *addr; + socklen_t addrlen; + +#ifndef _WIN32 + if (is_unix) { + addr = (struct sockaddr *)&uaddr; + addrlen = sizeof(uaddr); + if (parse_unix_path(&uaddr, host_str) < 0) + goto fail; + } else +#endif + { + addr = (struct sockaddr *)&saddr; + addrlen = sizeof(saddr); + if (parse_host_port(&saddr, host_str) < 0) + goto fail; + } ptr = host_str; while((ptr = strchr(ptr,','))) { @@ -2481,8 +2516,14 @@ static CharDriverState *qemu_chr_open_tc s = qemu_mallocz(sizeof(TCPCharDriver)); if (!s) goto fail; - - fd = socket(PF_INET, SOCK_STREAM, 0); + +#ifndef _WIN32 + if (is_unix) + fd = socket(PF_UNIX, SOCK_STREAM, 0); + else +#endif + fd = socket(PF_INET, SOCK_STREAM, 0); + if (fd < 0) goto fail; @@ -2492,24 +2533,43 @@ static CharDriverState *qemu_chr_open_tc s->connected = 0; s->fd = -1; s->listen_fd = -1; + s->is_unix = is_unix; + + chr->opaque = s; + chr->chr_write = tcp_chr_write; + chr->chr_add_read_handler = tcp_chr_add_read_handler; + chr->chr_close = tcp_chr_close; + if (is_listen) { /* allow fast reuse */ - val = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); +#ifndef _WIN32 + if (is_unix) { + char path[109]; + strncpy(path, uaddr.sun_path, 108); + path[108] = 0; + unlink(path); + } else +#endif + { + val = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); + } - ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); - if (ret < 0) + ret = bind(fd, addr, addrlen); + if (ret < 0) goto fail; + ret = listen(fd, 0); if (ret < 0) goto fail; + s->listen_fd = fd; qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); if (is_telnet) s->do_telnetopt = 1; } else { for(;;) { - ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); + ret = connect(fd, addr, addrlen); if (ret < 0) { err = socket_error(); if (err == EINTR || err == EWOULDBLOCK) { @@ -2530,10 +2590,6 @@ static CharDriverState *qemu_chr_open_tc qemu_set_fd_handler(s->fd, NULL, tcp_chr_connect, chr); } - chr->opaque = s; - chr->chr_write = tcp_chr_write; - chr->chr_add_read_handler = tcp_chr_add_read_handler; - chr->chr_close = tcp_chr_close; if (is_listen && is_waitconnect) { printf("QEMU waiting for connection on: %s\n", host_str); tcp_chr_accept(chr); @@ -2559,16 +2615,18 @@ CharDriverState *qemu_chr_open(const cha return qemu_chr_open_null(); } else if (strstart(filename, "tcp:", &p)) { - return qemu_chr_open_tcp(p, 0); + return qemu_chr_open_tcp(p, 0, 0); } else if (strstart(filename, "telnet:", &p)) { - return qemu_chr_open_tcp(p, 1); + return qemu_chr_open_tcp(p, 1, 0); } else if (strstart(filename, "udp:", &p)) { return qemu_chr_open_udp(p); } else #ifndef _WIN32 - if (strstart(filename, "file:", &p)) { + if (strstart(filename, "unix:", &p)) { + return qemu_chr_open_tcp(p, 0, 1); + } else if (strstart(filename, "file:", &p)) { return qemu_chr_open_file_out(p); } else if (strstart(filename, "pipe:", &p)) { return qemu_chr_open_pipe(p); @@ -2740,6 +2798,24 @@ int parse_host_port(struct sockaddr_in * if (r == p) return -1; saddr->sin_port = htons(port); + return 0; +} + +int parse_unix_path(struct sockaddr_un *uaddr, const char *str) +{ + const char *p; + int len; + + len = MIN(108, strlen(str)); + p = strchr(str, ','); + if (p) + len = MIN(len, p - str); + + memset(uaddr, 0, sizeof(*uaddr)); + + uaddr->sun_family = AF_UNIX; + memcpy(uaddr->sun_path, str, len); + return 0; } @@ -6955,6 +7031,7 @@ int main(int argc, char **argv) vm_start(); } } + main_loop(); quit_timers(); return 0; diff -r 01fafeaa2f64 qemu-doc.texi --- a/qemu-doc.texi Thu Dec 14 20:48:11 2006 +0000 +++ b/qemu-doc.texi Sat Dec 16 11:45:08 2006 -0600 @@ -586,6 +586,11 @@ sequence. Typically in unix telnet you sequence. Typically in unix telnet you do it with Control-] and then type "send break" followed by pressing the enter key. +@item unix:path[,server][,nowait] +A unix domain socket is used instead of a tcp socket. The option works the +same as if you had specified @code{-serial tcp} except the unix domain socket +@var{path} is used for connections. + @end table @item -parallel dev