diff -r 6b23d9afec55 console.c --- a/console.c Sat Mar 03 21:35:55 2007 -0600 +++ b/console.c Sat Mar 03 21:42:27 2007 -0600 @@ -1155,16 +1155,12 @@ int is_graphic_console(void) return !active_console->text_console; } -CharDriverState *text_console_init(DisplayState *ds) -{ - CharDriverState *chr; +CharDriverState *text_console_init(CharDriverState *chr, DisplayState *ds) +{ TextConsole *s; int i,j; static int color_inited; - chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - return NULL; s = new_console(ds, 1); if (!s) { free(chr); diff -r 6b23d9afec55 monitor.c --- a/monitor.c Sat Mar 03 21:35:55 2007 -0600 +++ b/monitor.c Sat Mar 03 21:58:55 2007 -0600 @@ -372,7 +372,7 @@ static void do_eject(int force, const ch eject_device(bs, force); } -static void do_change(const char *device, const char *filename) +static void do_change_block(const char *device, const char *filename) { BlockDriverState *bs; int i; @@ -395,6 +395,33 @@ static void do_change(const char *device term_printf("invalid password\n"); } } +} + +static void do_change(const char *device, const char *target) +{ + const char *p; + + if (strcmp(device, "vnc") == 0) { + if (vnc_display_open(NULL, target) == -1) + term_printf("could not start VNC server on %s\n", target); + } else if (strstart(device, "serial", &p)) { + int index = atoi(p); + if (index < 0 || index >= MAX_SERIAL_PORTS) { + term_printf("Invalid serial device %d\n", index); + return; + } + if (qemu_chr_open2(serial_hds[index], target) == NULL) + term_printf("Could not reopen serial device\n"); + } else if (strstart(device, "parallel", &p)) { + int index = atoi(p); + if (index < 0 || index >= MAX_PARALLEL_PORTS) { + term_printf("Invalid parallel device %d\n", index); + return; + } + if (qemu_chr_open2(parallel_hds[index], target) == NULL) + term_printf("Could not reopen serial device\n"); + } else + do_change_block(device, target); } static void do_screen_dump(const char *filename) @@ -1205,8 +1232,8 @@ static term_cmd_t term_cmds[] = { "", "quit the emulator" }, { "eject", "-fB", do_eject, "[-f] device", "eject a removable media (use -f to force it)" }, - { "change", "BF", do_change, - "device filename", "change a removable media" }, + { "change", "DF", do_change, + "device filename", "change a device target" }, { "screendump", "F", do_screen_dump, "filename", "save screen into PPM image 'filename'" }, { "log", "s", do_log, @@ -1988,6 +2015,7 @@ static void monitor_handle_command(const switch(c) { case 'F': case 'B': + case 'D': case 's': { int ret; @@ -2012,6 +2040,9 @@ static void monitor_handle_command(const case 'B': term_printf("%s: block device name expected\n", cmdname); break; + case 'D': + term_printf("%s: device name expected\n", cmdname); + break; default: term_printf("%s: string expected\n", cmdname); break; @@ -2312,7 +2343,7 @@ static void file_completion(const char * closedir(ffs); } -static void block_completion_it(void *opaque, const char *name) +static void device_completion_it(void *opaque, const char *name) { const char *input = opaque; @@ -2320,6 +2351,26 @@ static void block_completion_it(void *op !strncmp(name, (char *)input, strlen(input))) { add_completion(name); } +} + +static void device_iterate(void (*it)(void *opaque, const char *name), void *opaque) +{ + char buf[128]; + int i; + + bdrv_iterate(it, opaque); + + for (i = 0; i < MAX_SERIAL_PORTS; i++) { + snprintf(buf, sizeof(buf), "serial%d", i); + it(opaque, buf); + } + + for (i = 0; i < MAX_SERIAL_PORTS; i++) { + snprintf(buf, sizeof(buf), "parallel%d", i); + it(opaque, buf); + } + + it(opaque, "vnc"); } /* NOTE: this parser is an approximate form of the real command parser */ @@ -2408,8 +2459,13 @@ void readline_find_completion(const char case 'B': /* block device name completion */ completion_index = strlen(str); - bdrv_iterate(block_completion_it, (void *)str); - break; + bdrv_iterate(device_completion_it, (void *)str); + break; + case 'D': + /* device name completion */ + completion_index = strlen(str); + device_iterate(device_completion_it, (void *)str); + break; case 's': /* XXX: more generic ? */ if (!strcmp(cmd->name, "info")) { diff -r 6b23d9afec55 vl.c --- a/vl.c Sat Mar 03 21:35:55 2007 -0600 +++ b/vl.c Sat Mar 03 22:01:35 2007 -0600 @@ -1219,13 +1219,8 @@ static int null_chr_write(CharDriverStat return len; } -static CharDriverState *qemu_chr_open_null(void) -{ - CharDriverState *chr; - - chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - return NULL; +static CharDriverState *qemu_chr_open_null(CharDriverState *chr) +{ chr->chr_write = null_chr_write; return chr; } @@ -1587,15 +1582,16 @@ static void fd_chr_update_read_handler(C } } +static void fd_chr_close(CharDriverState *chr) +{ + free(chr->opaque); +} + /* open a character device to a unix fd */ -static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out) -{ - CharDriverState *chr; +static CharDriverState *qemu_chr_open_fd(CharDriverState *chr, int fd_in, int fd_out) +{ FDCharDriver *s; - chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - return NULL; s = qemu_mallocz(sizeof(FDCharDriver)); if (!s) { free(chr); @@ -1606,23 +1602,24 @@ static CharDriverState *qemu_chr_open_fd chr->opaque = s; chr->chr_write = fd_chr_write; chr->chr_update_read_handler = fd_chr_update_read_handler; + chr->chr_close = fd_chr_close; qemu_chr_reset(chr); return chr; } -static CharDriverState *qemu_chr_open_file_out(const char *file_out) +static CharDriverState *qemu_chr_open_file_out(CharDriverState *chr, const char *file_out) { int fd_out; fd_out = open(file_out, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666); if (fd_out < 0) return NULL; - return qemu_chr_open_fd(-1, fd_out); -} - -static CharDriverState *qemu_chr_open_pipe(const char *filename) + return qemu_chr_open_fd(chr, -1, fd_out); +} + +static CharDriverState *qemu_chr_open_pipe(CharDriverState *chr, const char *filename) { int fd_in, fd_out; char filename_in[256], filename_out[256]; @@ -1640,7 +1637,7 @@ static CharDriverState *qemu_chr_open_pi if (fd_in < 0) return NULL; } - return qemu_chr_open_fd(fd_in, fd_out); + return qemu_chr_open_fd(chr, fd_in, fd_out); } @@ -1726,13 +1723,11 @@ static void term_init(void) fcntl(0, F_SETFL, O_NONBLOCK); } -static CharDriverState *qemu_chr_open_stdio(void) -{ - CharDriverState *chr; - +static CharDriverState *qemu_chr_open_stdio(CharDriverState *chr) +{ if (stdio_nb_clients >= STDIO_MAX_CLIENTS) return NULL; - chr = qemu_chr_open_fd(0, 1); + chr = qemu_chr_open_fd(chr, 0, 1); qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr); stdio_nb_clients++; term_init(); @@ -1741,7 +1736,7 @@ static CharDriverState *qemu_chr_open_st } #if defined(__linux__) -static CharDriverState *qemu_chr_open_pty(void) +static CharDriverState *qemu_chr_open_pty(CharDriverState *chr) { struct termios tty; char slave_name[1024]; @@ -1760,7 +1755,7 @@ static CharDriverState *qemu_chr_open_pt tcsetattr (master_fd, TCSAFLUSH, &tty); fprintf(stderr, "char device redirected to %s\n", slave_name); - return qemu_chr_open_fd(master_fd, master_fd); + return qemu_chr_open_fd(chr, master_fd, master_fd); } static void tty_serial_init(int fd, int speed, @@ -1880,9 +1875,8 @@ static int tty_serial_ioctl(CharDriverSt return 0; } -static CharDriverState *qemu_chr_open_tty(const char *filename) -{ - CharDriverState *chr; +static CharDriverState *qemu_chr_open_tty(CharDriverState *chr, const char *filename) +{ int fd; fd = open(filename, O_RDWR | O_NONBLOCK); @@ -1890,7 +1884,7 @@ static CharDriverState *qemu_chr_open_tt return NULL; fcntl(fd, F_SETFL, O_NONBLOCK); tty_serial_init(fd, 115200, 'N', 8, 1); - chr = qemu_chr_open_fd(fd, fd); + chr = qemu_chr_open_fd(chr, fd, fd); if (!chr) return NULL; chr->chr_ioctl = tty_serial_ioctl; @@ -2002,9 +1996,8 @@ static void pp_close(CharDriverState *ch qemu_free(drv); } -static CharDriverState *qemu_chr_open_pp(const char *filename) -{ - CharDriverState *chr; +static CharDriverState *qemu_chr_open_pp(CharDriverState *chr, const char *filename) +{ ParallelCharDriver *drv; int fd; @@ -2025,12 +2018,6 @@ static CharDriverState *qemu_chr_open_pp drv->fd = fd; drv->mode = IEEE1284_MODE_COMPAT; - chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) { - qemu_free(drv); - close(fd); - return NULL; - } chr->chr_write = null_chr_write; chr->chr_ioctl = pp_ioctl; chr->chr_close = pp_close; @@ -2249,14 +2236,10 @@ static int win_chr_poll(void *opaque) return 0; } -static CharDriverState *qemu_chr_open_win(const char *filename) -{ - CharDriverState *chr; +static CharDriverState *qemu_chr_open_win(CharDriverState *chr, const char *filename) +{ WinCharState *s; - chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - return NULL; s = qemu_mallocz(sizeof(WinCharState)); if (!s) { free(chr); @@ -2354,14 +2337,10 @@ static int win_chr_pipe_init(CharDriverS } -static CharDriverState *qemu_chr_open_win_pipe(const char *filename) -{ - CharDriverState *chr; +static CharDriverState *qemu_chr_open_win_pipe(CharDriverState *chr, const char *filename) +{ WinCharState *s; - chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - return NULL; s = qemu_mallocz(sizeof(WinCharState)); if (!s) { free(chr); @@ -2380,14 +2359,10 @@ static CharDriverState *qemu_chr_open_wi return chr; } -static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out) -{ - CharDriverState *chr; +static CharDriverState *qemu_chr_open_win_file(CharDriverState *chr, HANDLE fd_out) +{ WinCharState *s; - chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - return NULL; s = qemu_mallocz(sizeof(WinCharState)); if (!s) { free(chr); @@ -2400,7 +2375,7 @@ static CharDriverState *qemu_chr_open_wi return chr; } -static CharDriverState *qemu_chr_open_win_file_out(const char *file_out) +static CharDriverState *qemu_chr_open_win_file_out(CharDriverState *chr, const char *file_out) { HANDLE fd_out; @@ -2409,7 +2384,7 @@ static CharDriverState *qemu_chr_open_wi if (fd_out == INVALID_HANDLE_VALUE) return NULL; - return qemu_chr_open_win_file(fd_out); + return qemu_chr_open_win_file(chr, fd_out); } #endif @@ -2489,16 +2464,12 @@ int parse_host_src_port(struct sockaddr_ struct sockaddr_in *saddr, const char *str); -static CharDriverState *qemu_chr_open_udp(const char *def) -{ - CharDriverState *chr = NULL; +static CharDriverState *qemu_chr_open_udp(CharDriverState *chr, const char *def) +{ NetCharDriver *s = NULL; int fd = -1; struct sockaddr_in saddr; - chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - goto return_err; s = qemu_mallocz(sizeof(NetCharDriver)); if (!s) goto return_err; @@ -2735,11 +2706,11 @@ static void tcp_chr_close(CharDriverStat qemu_free(s); } -static CharDriverState *qemu_chr_open_tcp(const char *host_str, +static CharDriverState *qemu_chr_open_tcp(CharDriverState *chr, + const char *host_str, int is_telnet, int is_unix) { - CharDriverState *chr = NULL; TCPCharDriver *s = NULL; int fd = -1, ret, err, val; int is_listen = 0; @@ -2785,9 +2756,6 @@ static CharDriverState *qemu_chr_open_tc if (!is_listen) is_waitconnect = 0; - chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - goto fail; s = qemu_mallocz(sizeof(TCPCharDriver)); if (!s) goto fail; @@ -2881,31 +2849,36 @@ static CharDriverState *qemu_chr_open_tc return NULL; } -CharDriverState *qemu_chr_open(const char *filename) +CharDriverState *qemu_chr_open2(CharDriverState *chr, const char *filename) { const char *p; - CharDriverState *chr; + CharDriverState *saved_chr; + + saved_chr = chr; + + if (chr->filename) + free(chr->filename); + chr->filename = strdup(filename); if (!strcmp(filename, "vc")) { - chr = text_console_init(&display_state); + chr = text_console_init(chr, &display_state); } else if (!strcmp(filename, "null")) { - chr = qemu_chr_open_null(); + chr = qemu_chr_open_null(chr); } else if (strstart(filename, "tcp:", &p)) { - chr = qemu_chr_open_tcp(p, 0, 0); + chr = qemu_chr_open_tcp(chr, p, 0, 0); } else if (strstart(filename, "telnet:", &p)) { - chr = qemu_chr_open_tcp(p, 1, 0); + chr = qemu_chr_open_tcp(chr, p, 1, 0); } else if (strstart(filename, "udp:", &p)) { - chr = qemu_chr_open_udp(p); + chr = qemu_chr_open_udp(chr, p); } else if (strstart(filename, "mon:", &p)) { - CharDriverState *drv = qemu_chr_open(p); - if (drv) { - drv = qemu_chr_open_mux(drv); - monitor_init(drv, !nographic); - chr = drv; + chr = qemu_chr_open(p); + if (chr) { + chr = qemu_chr_open_mux(chr); + monitor_init(chr, !nographic); } else { printf("Unable to open driver: %s\n", p); return 0; @@ -2913,44 +2886,61 @@ CharDriverState *qemu_chr_open(const cha } else #ifndef _WIN32 if (strstart(filename, "unix:", &p)) { - chr = qemu_chr_open_tcp(p, 0, 1); + chr = qemu_chr_open_tcp(chr, p, 0, 1); } else if (strstart(filename, "file:", &p)) { - chr = qemu_chr_open_file_out(p); + chr = qemu_chr_open_file_out(chr, p); } else if (strstart(filename, "pipe:", &p)) { - chr = qemu_chr_open_pipe(p); + chr = qemu_chr_open_pipe(chr, p); } else if (!strcmp(filename, "pty")) { - chr = qemu_chr_open_pty(); + chr = qemu_chr_open_pty(chr); } else if (!strcmp(filename, "stdio")) { - chr = qemu_chr_open_stdio(); + chr = qemu_chr_open_stdio(chr); } else #endif #if defined(__linux__) if (strstart(filename, "/dev/parport", NULL)) { - chr = qemu_chr_open_pp(filename); + chr = qemu_chr_open_pp(chr, filename); } else if (strstart(filename, "/dev/", NULL)) { - chr = qemu_chr_open_tty(filename); + chr = qemu_chr_open_tty(chr, filename); } else #endif #ifdef _WIN32 if (strstart(filename, "COM", NULL)) { - chr = qemu_chr_open_win(filename); + chr = qemu_chr_open_win(chr, filename); } else if (strstart(filename, "pipe:", &p)) { - chr = qemu_chr_open_win_pipe(p); + chr = qemu_chr_open_win_pipe(chr, p); } else if (strstart(filename, "file:", &p)) { - chr = qemu_chr_open_win_file_out(p); + chr = qemu_chr_open_win_file_out(chr, p); } else #endif { - return NULL; - } - - if (chr) - chr->filename = strdup(filename); + chr = NULL; + } + + if (chr == NULL) { + free(saved_chr->filename); + saved_chr->filename = NULL; + } return chr; +} + +CharDriverState *qemu_chr_open(const char *filename) +{ + CharDriverState *chr, *drv; + + chr = qemu_mallocz(sizeof(CharDriverState)); + if (!chr) + return NULL; + + drv = qemu_chr_open2(chr, filename); + if (!drv) + qemu_free(chr); + + return drv; } void qemu_chr_close(CharDriverState *chr) @@ -7562,7 +7552,7 @@ int main(int argc, char **argv) for(i = 0; i < MAX_PARALLEL_PORTS; i++) { const char *devname = parallel_devices[i]; - if (devname[0] != '\0' && strcmp(devname, "none")) { + if (devname[0] != '\0' && strcmp(devname, "none")) { parallel_hds[i] = qemu_chr_open(devname); if (!parallel_hds[i]) { fprintf(stderr, "qemu: could not open parallel device '%s'\n", @@ -7571,7 +7561,7 @@ int main(int argc, char **argv) } if (!strcmp(devname, "vc")) qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i); - } + } } machine->init(ram_size, vga_ram_size, boot_device, diff -r 6b23d9afec55 vl.h --- a/vl.h Sat Mar 03 21:35:55 2007 -0600 +++ b/vl.h Sat Mar 03 21:55:54 2007 -0600 @@ -311,6 +311,7 @@ typedef struct CharDriverState { } CharDriverState; CharDriverState *qemu_chr_open(const char *filename); +CharDriverState *qemu_chr_open2(CharDriverState *chr, const char *filename); void qemu_chr_printf(CharDriverState *s, const char *fmt, ...); int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len); void qemu_chr_send_event(CharDriverState *s, int event); @@ -342,7 +343,7 @@ void vga_hw_screen_dump(const char *file void vga_hw_screen_dump(const char *filename); int is_graphic_console(void); -CharDriverState *text_console_init(DisplayState *ds); +CharDriverState *text_console_init(CharDriverState *chr, DisplayState *ds); void console_select(unsigned int index); /* serial ports */ @@ -921,6 +922,7 @@ void cocoa_display_init(DisplayState *ds /* vnc.c */ void vnc_display_init(DisplayState *ds, const char *display); +int vnc_display_open(DisplayState *ds, const char *display); void do_info_vnc(void); /* x_keymap.c */ diff -r 6b23d9afec55 vnc.c --- a/vnc.c Sat Mar 03 21:35:55 2007 -0600 +++ b/vnc.c Sat Mar 03 21:55:54 2007 -0600 @@ -73,7 +73,7 @@ struct VncState int last_x; int last_y; - const char *display; + char *display; Buffer output; Buffer input; @@ -1160,7 +1160,7 @@ static void vnc_listen_read(void *opaque extern int parse_host_port(struct sockaddr_in *saddr, const char *str); -void vnc_display_init(DisplayState *ds, const char *arg) +int vnc_display_open(DisplayState *ds, const char *arg) { struct sockaddr *addr; struct sockaddr_in iaddr; @@ -1172,38 +1172,31 @@ void vnc_display_init(DisplayState *ds, const char *p; VncState *vs; - vs = qemu_mallocz(sizeof(VncState)); - if (!vs) - exit(1); - - ds->opaque = vs; - vnc_state = vs; - vs->display = arg; - - vs->lsock = -1; - vs->csock = -1; - vs->depth = 4; - vs->last_x = -1; - vs->last_y = -1; - - vs->ds = ds; - - if (!keyboard_layout) - keyboard_layout = "en-us"; - - vs->kbd_layout = init_keyboard_layout(keyboard_layout); - if (!vs->kbd_layout) - exit(1); - - vs->ds->data = NULL; - vs->ds->dpy_update = vnc_dpy_update; - vs->ds->dpy_resize = vnc_dpy_resize; - vs->ds->dpy_refresh = vnc_dpy_refresh; - - memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row)); - - vnc_dpy_resize(vs->ds, 640, 400); - + if (ds == NULL) + ds = vnc_state->ds; + + vs = ds->opaque; + + free(vs->display); + vs->display = strdup(arg); + if (vs->csock != -1) { + qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL); + closesocket(vs->csock); + vs->csock = -1; + buffer_reset(&vs->input); + buffer_reset(&vs->output); + vs->need_update = 0; + } + + if (vs->lsock != -1) { + qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL); + close(vs->lsock); + vs->lsock = -1; + } + + if (strcmp(arg, "null") == 0) + return 0; + else #ifndef _WIN32 if (strstart(arg, "unix:", &p)) { addr = (struct sockaddr *)&uaddr; @@ -1212,7 +1205,7 @@ void vnc_display_init(DisplayState *ds, vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0); if (vs->lsock == -1) { fprintf(stderr, "Could not create socket\n"); - exit(1); + return -1; } uaddr.sun_family = AF_UNIX; @@ -1229,12 +1222,12 @@ void vnc_display_init(DisplayState *ds, vs->lsock = socket(PF_INET, SOCK_STREAM, 0); if (vs->lsock == -1) { fprintf(stderr, "Could not create socket\n"); - exit(1); + return -1; } if (parse_host_port(&iaddr, arg) < 0) { fprintf(stderr, "Could not parse VNC address\n"); - exit(1); + return -1; } iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900); @@ -1244,22 +1237,63 @@ void vnc_display_init(DisplayState *ds, (const char *)&reuse_addr, sizeof(reuse_addr)); if (ret == -1) { fprintf(stderr, "setsockopt() failed\n"); - exit(1); + return -1; } } if (bind(vs->lsock, addr, addrlen) == -1) { fprintf(stderr, "bind() failed\n"); - exit(1); + return -1; } if (listen(vs->lsock, 1) == -1) { fprintf(stderr, "listen() failed\n"); + return -1; + } + + ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs); + if (ret == -1) + return -1; + + return 0; +} + +void vnc_display_init(DisplayState *ds, const char *arg) +{ + VncState *vs; + + vs = qemu_mallocz(sizeof(VncState)); + if (!vs) exit(1); - } - - ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs); - if (ret == -1) { + + ds->opaque = vs; + vnc_state = vs; + + vs->lsock = -1; + vs->csock = -1; + vs->depth = 4; + vs->last_x = -1; + vs->last_y = -1; + + vs->ds = ds; + vs->display = NULL; + + if (!keyboard_layout) + keyboard_layout = "en-us"; + + vs->kbd_layout = init_keyboard_layout(keyboard_layout); + if (!vs->kbd_layout) exit(1); - } -} + + vs->ds->data = NULL; + vs->ds->dpy_update = vnc_dpy_update; + vs->ds->dpy_resize = vnc_dpy_resize; + vs->ds->dpy_refresh = vnc_dpy_refresh; + + memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row)); + + vnc_dpy_resize(vs->ds, 640, 400); + + if (vnc_display_open(vs->ds, arg) == -1) + exit(1); +} diff -r 6b23d9afec55 qemu-doc.texi --- a/qemu-doc.texi Sat Mar 03 21:35:55 2007 -0600 +++ b/qemu-doc.texi Sat Mar 03 22:09:34 2007 -0600 @@ -267,7 +267,8 @@ will only be allowed from @var{interface will only be allowed from @var{interface} on display @var{d}. Optionally, @var{interface} can be omitted. @var{display} can also be in the form @var{unix:path} where @var{path} is the location of a unix socket to listen for -connections on. +connections on. @var{display} can also be @var{null} which create a VNC server +that does not listen on any interfaces. @item -k language