#include <dirent.h>
#include <netdb.h>
#include <sys/select.h>
-#ifdef HOST_BSD
+#ifdef CONFIG_BSD
#include <sys/stat.h>
#ifdef __FreeBSD__
#include <libutil.h>
s->chr_read(s->handler_opaque, buf, len);
}
+int qemu_chr_get_msgfd(CharDriverState *s)
+{
+ return s->get_msgfd ? s->get_msgfd(s) : -1;
+}
+
void qemu_chr_accept_input(CharDriverState *s)
{
if (s->chr_accept_input)
}
/* MUX driver for serial I/O splitting */
-static int term_timestamps;
-static int64_t term_timestamps_start;
#define MAX_MUX 4
#define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */
#define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1)
unsigned char buffer[MAX_MUX][MUX_BUFFER_SIZE];
int prod[MAX_MUX];
int cons[MAX_MUX];
+ int timestamps;
+ int linestart;
+ int64_t timestamps_start;
} MuxDriver;
{
MuxDriver *d = chr->opaque;
int ret;
- if (!term_timestamps) {
+ if (!d->timestamps) {
ret = d->drv->chr_write(d->drv, buf, len);
} else {
int i;
ret = 0;
- for(i = 0; i < len; i++) {
- ret += d->drv->chr_write(d->drv, buf+i, 1);
- if (buf[i] == '\n') {
+ for (i = 0; i < len; i++) {
+ if (d->linestart) {
char buf1[64];
int64_t ti;
int secs;
ti = qemu_get_clock(rt_clock);
- if (term_timestamps_start == -1)
- term_timestamps_start = ti;
- ti -= term_timestamps_start;
+ if (d->timestamps_start == -1)
+ d->timestamps_start = ti;
+ ti -= d->timestamps_start;
secs = ti / 1000;
snprintf(buf1, sizeof(buf1),
"[%02d:%02d:%02d.%03d] ",
secs % 60,
(int)(ti % 1000));
d->drv->chr_write(d->drv, (uint8_t *)buf1, strlen(buf1));
+ d->linestart = 0;
+ }
+ ret += d->drv->chr_write(d->drv, buf+i, 1);
+ if (buf[i] == '\n') {
+ d->linestart = 1;
}
}
}
}
case 's':
{
- int i;
- for (i = 0; i < nb_drives; i++) {
- bdrv_commit(drives_table[i].bdrv);
+ DriveInfo *dinfo;
+ TAILQ_FOREACH(dinfo, &drives, next) {
+ bdrv_commit(dinfo->bdrv);
}
}
break;
chr->focus = 0;
mux_chr_send_event(d, chr->focus, CHR_EVENT_MUX_IN);
break;
- case 't':
- term_timestamps = !term_timestamps;
- term_timestamps_start = -1;
- break;
+ case 't':
+ d->timestamps = !d->timestamps;
+ d->timestamps_start = -1;
+ d->linestart = 0;
+ break;
}
} else if (ch == term_escape_char) {
d->term_got_escape = 1;
FDCharDriver *s = chr->opaque;
if (s->fd_in >= 0) {
- if (nographic && s->fd_in == 0) {
+ if (display_type == DT_NOGRAPHIC && s->fd_in == 0) {
} else {
qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll,
fd_chr_read, NULL, chr);
FDCharDriver *s = chr->opaque;
if (s->fd_in >= 0) {
- if (nographic && s->fd_in == 0) {
+ if (display_type == DT_NOGRAPHIC && s->fd_in == 0) {
} else {
qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
}
tty.c_oflag |= OPOST;
tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
/* if graphical mode, we allow Ctrl-C handling */
- if (nographic)
+ if (display_type == DT_NOGRAPHIC)
tty.c_lflag &= ~ISIG;
tty.c_cflag &= ~(CSIZE|PARENB);
tty.c_cflag |= CS8;
#ifdef __sun__
/* Once Solaris has openpty(), this is going to be removed. */
-int openpty(int *amaster, int *aslave, char *name,
- struct termios *termp, struct winsize *winp)
+static int openpty(int *amaster, int *aslave, char *name,
+ struct termios *termp, struct winsize *winp)
{
const char *slave;
int mfd = -1, sfd = -1;
return -1;
}
-void cfmakeraw (struct termios *termios_p)
+static void cfmakeraw (struct termios *termios_p)
{
termios_p->c_iflag &=
~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
close(s->fd);
+ qemu_del_timer(s->timer);
+ qemu_free_timer(s->timer);
qemu_free(s);
}
{
NetCharDriver *s = chr->opaque;
- return sendto(s->fd, buf, len, 0,
+ return sendto(s->fd, (const void *)buf, len, 0,
(struct sockaddr *)&s->daddr, sizeof(struct sockaddr_in));
}
if (s->max_size == 0)
return;
- s->bufcnt = recv(s->fd, s->buf, sizeof(s->buf), 0);
+ s->bufcnt = recv(s->fd, (void *)s->buf, sizeof(s->buf), 0);
s->bufptr = s->bufcnt;
if (s->bufcnt <= 0)
return;
}
}
+static void udp_chr_close(CharDriverState *chr)
+{
+ NetCharDriver *s = chr->opaque;
+ if (s->fd >= 0) {
+ qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+ closesocket(s->fd);
+ }
+ qemu_free(s);
+}
+
static CharDriverState *qemu_chr_open_udp(const char *def)
{
CharDriverState *chr = NULL;
chr->opaque = s;
chr->chr_write = udp_chr_write;
chr->chr_update_read_handler = udp_chr_update_read_handler;
+ chr->chr_close = udp_chr_close;
return chr;
return_err:
int do_telnetopt;
int do_nodelay;
int is_unix;
+ int msgfd;
} TCPCharDriver;
static void tcp_chr_accept(void *opaque);
*size = j;
}
+static int tcp_get_msgfd(CharDriverState *chr)
+{
+ TCPCharDriver *s = chr->opaque;
+
+ return s->msgfd;
+}
+
+#ifndef _WIN32
+static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg)
+{
+ TCPCharDriver *s = chr->opaque;
+ struct cmsghdr *cmsg;
+
+ for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+ int fd;
+
+ if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
+ cmsg->cmsg_level != SOL_SOCKET ||
+ cmsg->cmsg_type != SCM_RIGHTS)
+ continue;
+
+ fd = *((int *)CMSG_DATA(cmsg));
+ if (fd < 0)
+ continue;
+
+ if (s->msgfd != -1)
+ close(s->msgfd);
+ s->msgfd = fd;
+ }
+}
+
+static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
+{
+ TCPCharDriver *s = chr->opaque;
+ struct msghdr msg = { NULL, };
+ struct iovec iov[1];
+ union {
+ struct cmsghdr cmsg;
+ char control[CMSG_SPACE(sizeof(int))];
+ } msg_control;
+ ssize_t ret;
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = len;
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = &msg_control;
+ msg.msg_controllen = sizeof(msg_control);
+
+ ret = recvmsg(s->fd, &msg, 0);
+ if (ret > 0 && s->is_unix)
+ unix_process_msgfd(chr, &msg);
+
+ return ret;
+}
+#else
+static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
+{
+ TCPCharDriver *s = chr->opaque;
+ return recv(s->fd, buf, len, 0);
+}
+#endif
+
static void tcp_chr_read(void *opaque)
{
CharDriverState *chr = opaque;
len = sizeof(buf);
if (len > s->max_size)
len = s->max_size;
- size = recv(s->fd, buf, len, 0);
+ size = tcp_chr_recv(chr, (void *)buf, len);
if (size == 0) {
/* connection closed */
s->connected = 0;
tcp_chr_process_IAC_bytes(chr, s, buf, &size);
if (size > 0)
qemu_chr_read(chr, buf, size);
+ if (s->msgfd != -1) {
+ close(s->msgfd);
+ s->msgfd = -1;
+ }
}
}
static void tcp_chr_close(CharDriverState *chr)
{
TCPCharDriver *s = chr->opaque;
- if (s->fd >= 0)
+ if (s->fd >= 0) {
+ qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
closesocket(s->fd);
- if (s->listen_fd >= 0)
+ }
+ if (s->listen_fd >= 0) {
+ qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
closesocket(s->listen_fd);
+ }
qemu_free(s);
}
s->connected = 0;
s->fd = -1;
s->listen_fd = -1;
+ s->msgfd = -1;
s->is_unix = is_unix;
s->do_nodelay = do_nodelay && !is_unix;
chr->opaque = s;
chr->chr_write = tcp_chr_write;
chr->chr_close = tcp_chr_close;
+ chr->get_msgfd = tcp_get_msgfd;
if (is_listen) {
s->listen_fd = fd;
CharDriverState *chr;
if (!strcmp(filename, "vc")) {
- chr = text_console_init(0);
+ chr = text_console_init(NULL);
} else
if (strstart(filename, "vc:", &p)) {
chr = text_console_init(p);