ia64/xen-unstable

changeset 6053:deff07c1b686

Really include renamed console files. :-)
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Sun Aug 07 09:13:39 2005 +0000 (2005-08-07)
parents ec1878b6956e
children 69bf77e1b102
files tools/console/Makefile tools/console/client/main.c tools/console/daemon/io.c tools/console/daemon/io.h tools/console/daemon/main.c tools/console/daemon/utils.c tools/console/daemon/utils.h tools/console/testsuite/Makefile tools/console/testsuite/README tools/console/testsuite/console-dom0.c tools/console/testsuite/console-domU.c tools/console/testsuite/procpipe.c
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/console/Makefile	Sun Aug 07 09:13:39 2005 +0000
     1.3 @@ -0,0 +1,39 @@
     1.4 +
     1.5 +XEN_ROOT=../..
     1.6 +include $(XEN_ROOT)/tools/Rules.mk
     1.7 +
     1.8 +DAEMON_INSTALL_DIR = /usr/sbin
     1.9 +CLIENT_INSTALL_DIR = /usr/libexec/xen
    1.10 +
    1.11 +INSTALL         = install
    1.12 +INSTALL_PROG    = $(INSTALL) -m0755
    1.13 +INSTALL_DIR     = $(INSTALL) -d -m0755
    1.14 +
    1.15 +CC       = gcc
    1.16 +CFLAGS   = -Wall -Werror -g3
    1.17 +
    1.18 +CFLAGS  += -I $(XEN_XCS)
    1.19 +CFLAGS  += -I $(XEN_LIBXC)
    1.20 +CFLAGS  += -I $(XEN_XENSTORE)
    1.21 +
    1.22 +BIN      = xenconsoled xenconsole
    1.23 +
    1.24 +all: $(BIN)
    1.25 +
    1.26 +clean:
    1.27 +	$(RM) *.a *.so *.o *.rpm $(BIN)
    1.28 +	$(RM) client/*.o daemon/*.o
    1.29 +
    1.30 +xenconsoled: $(patsubst %.c,%.o,$(wildcard daemon/*.c))
    1.31 +	$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_XENSTORE) \
    1.32 +              -lxc -lxenstore
    1.33 +
    1.34 +xenconsole: $(patsubst %.c,%.o,$(wildcard client/*.c))
    1.35 +	$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_XENSTORE) \
    1.36 +	      -lxc -lxenstore
    1.37 +
    1.38 +install: $(BIN)
    1.39 +	$(INSTALL_DIR) -p $(DESTDIR)/$(DAEMON_INSTALL_DIR)
    1.40 +	$(INSTALL_PROG) xenconsoled $(DESTDIR)/$(DAEMON_INSTALL_DIR)
    1.41 +	$(INSTALL_DIR) -p $(DESTDIR)/$(CLIENT_INSTALL_DIR)
    1.42 +	$(INSTALL_PROG) xenconsole $(DESTDIR)/$(CLIENT_INSTALL_DIR)
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/console/client/main.c	Sun Aug 07 09:13:39 2005 +0000
     2.3 @@ -0,0 +1,228 @@
     2.4 +/*\
     2.5 + *  Copyright (C) International Business Machines  Corp., 2005
     2.6 + *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
     2.7 + *
     2.8 + *  Xen Console Daemon
     2.9 + *
    2.10 + *  This program is free software; you can redistribute it and/or modify
    2.11 + *  it under the terms of the GNU General Public License as published by
    2.12 + *  the Free Software Foundation; under version 2 of the License.
    2.13 + * 
    2.14 + *  This program is distributed in the hope that it will be useful,
    2.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.17 + *  GNU General Public License for more details.
    2.18 + * 
    2.19 + *  You should have received a copy of the GNU General Public License
    2.20 + *  along with this program; if not, write to the Free Software
    2.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2.22 +\*/
    2.23 +
    2.24 +#include <sys/types.h>
    2.25 +#include <sys/socket.h>
    2.26 +#include <sys/un.h>
    2.27 +#include <stdio.h>
    2.28 +#include <unistd.h>
    2.29 +#include <errno.h>
    2.30 +#include <stdlib.h>
    2.31 +#include <time.h>
    2.32 +#include <fcntl.h>
    2.33 +#include <sys/wait.h>
    2.34 +#include <termios.h>
    2.35 +#include <signal.h>
    2.36 +#include <getopt.h>
    2.37 +#include <sys/select.h>
    2.38 +#include <err.h>
    2.39 +#include <errno.h>
    2.40 +#include <pty.h>
    2.41 +
    2.42 +#include "xc.h"
    2.43 +#include "xs.h"
    2.44 +
    2.45 +#define ESCAPE_CHARACTER 0x1d
    2.46 +
    2.47 +static volatile sig_atomic_t received_signal = 0;
    2.48 +
    2.49 +static void sighandler(int signum)
    2.50 +{
    2.51 +	received_signal = 1;
    2.52 +}
    2.53 +
    2.54 +static bool write_sync(int fd, const void *data, size_t size)
    2.55 +{
    2.56 +	size_t offset = 0;
    2.57 +	ssize_t len;
    2.58 +
    2.59 +	while (offset < size) {
    2.60 +		len = write(fd, data + offset, size - offset);
    2.61 +		if (len < 1) {
    2.62 +			return false;
    2.63 +		}
    2.64 +		offset += len;
    2.65 +	}
    2.66 +
    2.67 +	return true;
    2.68 +}
    2.69 +
    2.70 +static void usage(const char *program) {
    2.71 +	printf("Usage: %s [OPTION] DOMID\n"
    2.72 +	       "Attaches to a virtual domain console\n"
    2.73 +	       "\n"
    2.74 +	       "  -h, --help       display this help and exit\n"
    2.75 +	       , program);
    2.76 +}
    2.77 +
    2.78 +/* don't worry too much if setting terminal attributes fail */
    2.79 +static void init_term(int fd, struct termios *old)
    2.80 +{
    2.81 +	struct termios new_term;
    2.82 +
    2.83 +	if (tcgetattr(fd, old) == -1) {
    2.84 +		return;
    2.85 +	}
    2.86 +
    2.87 +	new_term = *old;
    2.88 +	cfmakeraw(&new_term);
    2.89 +
    2.90 +	tcsetattr(fd, TCSAFLUSH, &new_term);
    2.91 +}
    2.92 +
    2.93 +static void restore_term(int fd, struct termios *old)
    2.94 +{
    2.95 +	tcsetattr(fd, TCSAFLUSH, old);
    2.96 +}
    2.97 +
    2.98 +static int console_loop(int xc_handle, domid_t domid, int fd)
    2.99 +{
   2.100 +	int ret;
   2.101 +
   2.102 +	do {
   2.103 +		fd_set fds;
   2.104 +
   2.105 +		FD_ZERO(&fds);
   2.106 +		FD_SET(STDIN_FILENO, &fds);
   2.107 +		FD_SET(fd, &fds);
   2.108 +
   2.109 +		ret = select(fd + 1, &fds, NULL, NULL, NULL);
   2.110 +		if (ret == -1) {
   2.111 +			if (errno == EINTR || errno == EAGAIN) {
   2.112 +				continue;
   2.113 +			}
   2.114 +			return -1;
   2.115 +		}
   2.116 +
   2.117 +		if (FD_ISSET(STDIN_FILENO, &fds)) {
   2.118 +			ssize_t len;
   2.119 +			char msg[60];
   2.120 +
   2.121 +			len = read(STDIN_FILENO, msg, sizeof(msg));
   2.122 +			if (len == 1 && msg[0] == ESCAPE_CHARACTER) {
   2.123 +				return 0;
   2.124 +			} 
   2.125 +
   2.126 +			if (len == 0 || len == -1) {
   2.127 +				if (len == -1 &&
   2.128 +				    (errno == EINTR || errno == EAGAIN)) {
   2.129 +					continue;
   2.130 +				}
   2.131 +				return -1;
   2.132 +			}
   2.133 +
   2.134 +			if (!write_sync(fd, msg, len)) {
   2.135 +				perror("write() failed");
   2.136 +				return -1;
   2.137 +			}
   2.138 +		}
   2.139 +
   2.140 +		if (FD_ISSET(fd, &fds)) {
   2.141 +			ssize_t len;
   2.142 +			char msg[512];
   2.143 +
   2.144 +			len = read(fd, msg, sizeof(msg));
   2.145 +			if (len == 0 || len == -1) {
   2.146 +				if (len == -1 &&
   2.147 +				    (errno == EINTR || errno == EAGAIN)) {
   2.148 +					continue;
   2.149 +				}
   2.150 +				return -1;
   2.151 +			}
   2.152 +
   2.153 +			if (!write_sync(STDOUT_FILENO, msg, len)) {
   2.154 +				perror("write() failed");
   2.155 +				return -1;
   2.156 +			}
   2.157 +		}
   2.158 +	} while (received_signal == 0);
   2.159 +
   2.160 +	return 0;
   2.161 +}
   2.162 +
   2.163 +int main(int argc, char **argv)
   2.164 +{
   2.165 +	struct termios attr;
   2.166 +	int domid;
   2.167 +	int xc_handle;
   2.168 +	char *sopt = "hf:pc";
   2.169 +	int ch;
   2.170 +	int opt_ind=0;
   2.171 +	struct option lopt[] = {
   2.172 +		{ "help",    0, 0, 'h' },
   2.173 +		{ "file",    1, 0, 'f' },
   2.174 +		{ "pty",     0, 0, 'p' },
   2.175 +		{ "ctty",    0, 0, 'c' },
   2.176 +		{ 0 },
   2.177 +
   2.178 +	};
   2.179 +	char *str_pty;
   2.180 +	char path[1024];
   2.181 +	int spty;
   2.182 +	unsigned int len = 0;
   2.183 +	struct xs_handle *xs;
   2.184 +
   2.185 +	while((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
   2.186 +		switch(ch) {
   2.187 +		case 'h':
   2.188 +			usage(argv[0]);
   2.189 +			exit(0);
   2.190 +			break;
   2.191 +		}
   2.192 +	}
   2.193 +	
   2.194 +	if ((argc - optind) != 1) {
   2.195 +		fprintf(stderr, "Invalid number of arguments\n");
   2.196 +		fprintf(stderr, "Try `%s --help' for more information.\n", 
   2.197 +			argv[0]);
   2.198 +		exit(EINVAL);
   2.199 +	}
   2.200 +	
   2.201 +	domid = atoi(argv[optind]);
   2.202 +
   2.203 +	xs = xs_daemon_open();
   2.204 +	if (xs == NULL) {
   2.205 +		err(errno, "Could not contact XenStore");
   2.206 +	}
   2.207 +
   2.208 +	xc_handle = xc_interface_open();
   2.209 +	if (xc_handle == -1) {
   2.210 +		err(errno, "xc_interface_open()");
   2.211 +	}
   2.212 +	
   2.213 +	signal(SIGTERM, sighandler);
   2.214 +
   2.215 +	snprintf(path, sizeof(path), "/console/%d/tty", domid);
   2.216 +	str_pty = xs_read(xs, path, &len);
   2.217 +	if (str_pty == NULL) {
   2.218 +		err(errno, "Could not read tty from store");
   2.219 +	}
   2.220 +	spty = open(str_pty, O_RDWR | O_NOCTTY);
   2.221 +	if (spty == -1) {
   2.222 +		err(errno, "Could not open tty `%s'", str_pty);
   2.223 +	}
   2.224 +	free(str_pty);
   2.225 +
   2.226 +	init_term(STDIN_FILENO, &attr);
   2.227 +	console_loop(xc_handle, domid, spty);
   2.228 +	restore_term(STDIN_FILENO, &attr);
   2.229 +
   2.230 +	return 0;
   2.231 + }
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/console/daemon/io.c	Sun Aug 07 09:13:39 2005 +0000
     3.3 @@ -0,0 +1,343 @@
     3.4 +/*\
     3.5 + *  Copyright (C) International Business Machines  Corp., 2005
     3.6 + *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
     3.7 + *
     3.8 + *  Xen Console Daemon
     3.9 + *
    3.10 + *  This program is free software; you can redistribute it and/or modify
    3.11 + *  it under the terms of the GNU General Public License as published by
    3.12 + *  the Free Software Foundation; under version 2 of the License.
    3.13 + * 
    3.14 + *  This program is distributed in the hope that it will be useful,
    3.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.17 + *  GNU General Public License for more details.
    3.18 + * 
    3.19 + *  You should have received a copy of the GNU General Public License
    3.20 + *  along with this program; if not, write to the Free Software
    3.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    3.22 +\*/
    3.23 +
    3.24 +#define _GNU_SOURCE
    3.25 +
    3.26 +#include "utils.h"
    3.27 +#include "io.h"
    3.28 +
    3.29 +#include "xc.h"
    3.30 +#include "xs.h"
    3.31 +#include "xen/io/domain_controller.h"
    3.32 +#include "xcs_proto.h"
    3.33 +
    3.34 +#include <malloc.h>
    3.35 +#include <stdlib.h>
    3.36 +#include <errno.h>
    3.37 +#include <string.h>
    3.38 +#include <sys/select.h>
    3.39 +#include <fcntl.h>
    3.40 +#include <unistd.h>
    3.41 +#include <termios.h>
    3.42 +
    3.43 +#define MAX(a, b) (((a) > (b)) ? (a) : (b))
    3.44 +#define MIN(a, b) (((a) < (b)) ? (a) : (b))
    3.45 +
    3.46 +struct buffer
    3.47 +{
    3.48 +	char *data;
    3.49 +	size_t size;
    3.50 +	size_t capacity;
    3.51 +	size_t max_capacity;
    3.52 +};
    3.53 +
    3.54 +static void buffer_append(struct buffer *buffer, const void *data, size_t size)
    3.55 +{
    3.56 +	if ((buffer->capacity - buffer->size) < size) {
    3.57 +		buffer->capacity += (size + 1024);
    3.58 +		buffer->data = realloc(buffer->data, buffer->capacity);
    3.59 +		if (buffer->data == NULL) {
    3.60 +			dolog(LOG_ERR, "Memory allocation failed");
    3.61 +			exit(ENOMEM);
    3.62 +		}
    3.63 +	}
    3.64 +
    3.65 +	memcpy(buffer->data + buffer->size, data, size);
    3.66 +	buffer->size += size;
    3.67 +
    3.68 +	if (buffer->max_capacity &&
    3.69 +	    buffer->size > buffer->max_capacity) {
    3.70 +		memmove(buffer->data + (buffer->size - buffer->max_capacity),
    3.71 +			buffer->data, buffer->max_capacity);
    3.72 +		buffer->data = realloc(buffer->data, buffer->max_capacity);
    3.73 +		buffer->capacity = buffer->max_capacity;
    3.74 +	}
    3.75 +}
    3.76 +
    3.77 +static bool buffer_empty(struct buffer *buffer)
    3.78 +{
    3.79 +	return buffer->size == 0;
    3.80 +}
    3.81 +
    3.82 +static void buffer_advance(struct buffer *buffer, size_t size)
    3.83 +{
    3.84 +	size = MIN(size, buffer->size);
    3.85 +	memmove(buffer->data, buffer + size, buffer->size - size);
    3.86 +	buffer->size -= size;
    3.87 +}
    3.88 +
    3.89 +struct domain
    3.90 +{
    3.91 +	int domid;
    3.92 +	int tty_fd;
    3.93 +	struct buffer buffer;
    3.94 +	struct domain *next;
    3.95 +};
    3.96 +
    3.97 +static struct domain *dom_head;
    3.98 +
    3.99 +static bool domain_is_valid(int domid)
   3.100 +{
   3.101 +	bool ret;
   3.102 +	xc_dominfo_t info;
   3.103 +
   3.104 +	ret = (xc_domain_getinfo(xc, domid, 1, &info) == 1 &&
   3.105 +	       info.domid == domid);
   3.106 +		
   3.107 +	return ret;
   3.108 +}
   3.109 +
   3.110 +static int domain_create_tty(struct domain *dom)
   3.111 +{
   3.112 +	char path[1024];
   3.113 +	int master;
   3.114 +
   3.115 +	if ((master = getpt()) == -1 ||
   3.116 +	    grantpt(master) == -1 || unlockpt(master) == -1) {
   3.117 +		dolog(LOG_ERR, "Failed to create tty for domain-%d",
   3.118 +		      dom->domid);
   3.119 +		master = -1;
   3.120 +	} else {
   3.121 +		const char *slave = ptsname(master);
   3.122 +		struct termios term;
   3.123 +		char *data;
   3.124 +		unsigned int len;
   3.125 +
   3.126 +		if (tcgetattr(master, &term) != -1) {
   3.127 +			cfmakeraw(&term);
   3.128 +			tcsetattr(master, TCSAFLUSH, &term);
   3.129 +		}
   3.130 +
   3.131 +		xs_mkdir(xs, "/console");
   3.132 +		snprintf(path, sizeof(path), "/console/%d", dom->domid);
   3.133 +		xs_mkdir(xs, path);
   3.134 +		strcat(path, "/tty");
   3.135 +
   3.136 +		xs_write(xs, path, slave, strlen(slave), O_CREAT);
   3.137 +
   3.138 +		snprintf(path, sizeof(path), "/console/%d/limit", dom->domid);
   3.139 +		data = xs_read(xs, path, &len);
   3.140 +		if (data) {
   3.141 +			dom->buffer.max_capacity = strtoul(data, 0, 0);
   3.142 +			free(data);
   3.143 +		}
   3.144 +	}
   3.145 +
   3.146 +	return master;
   3.147 +}
   3.148 +
   3.149 +static struct domain *create_domain(int domid)
   3.150 +{
   3.151 +	struct domain *dom;
   3.152 +
   3.153 +	dom = (struct domain *)malloc(sizeof(struct domain));
   3.154 +	if (dom == NULL) {
   3.155 +		dolog(LOG_ERR, "Out of memory %s:%s():L%d",
   3.156 +		      __FILE__, __FUNCTION__, __LINE__);
   3.157 +		exit(ENOMEM);
   3.158 +	}
   3.159 +
   3.160 +	dom->domid = domid;
   3.161 +	dom->tty_fd = domain_create_tty(dom);
   3.162 +	dom->buffer.data = 0;
   3.163 +	dom->buffer.size = 0;
   3.164 +	dom->buffer.capacity = 0;
   3.165 +	dom->buffer.max_capacity = 0;
   3.166 +
   3.167 +	dolog(LOG_DEBUG, "New domain %d", domid);
   3.168 +
   3.169 +	return dom;
   3.170 +}
   3.171 +
   3.172 +static struct domain *lookup_domain(int domid)
   3.173 +{
   3.174 +	struct domain **pp;
   3.175 +
   3.176 +	for (pp = &dom_head; *pp; pp = &(*pp)->next) {
   3.177 +		struct domain *dom = *pp;
   3.178 +
   3.179 +		if (dom->domid == domid) {
   3.180 +			return dom;
   3.181 +		} else if (dom->domid > domid) {
   3.182 +			*pp = create_domain(domid);
   3.183 +			(*pp)->next = dom;
   3.184 +			return *pp;
   3.185 +		}
   3.186 +	}
   3.187 +
   3.188 +	*pp = create_domain(domid);
   3.189 +	return *pp;
   3.190 +}
   3.191 +
   3.192 +static void remove_domain(struct domain *dom)
   3.193 +{
   3.194 +	struct domain **pp;
   3.195 +
   3.196 +	dolog(LOG_DEBUG, "Removing domain-%d", dom->domid);
   3.197 +
   3.198 +	for (pp = &dom_head; *pp; pp = &(*pp)->next) {
   3.199 +		struct domain *d = *pp;
   3.200 +
   3.201 +		if (dom->domid == d->domid) {
   3.202 +			*pp = d->next;
   3.203 +			if (d->buffer.data) {
   3.204 +				free(d->buffer.data);
   3.205 +			}
   3.206 +			free(d);
   3.207 +			break;
   3.208 +		}
   3.209 +	}
   3.210 +}
   3.211 +
   3.212 +static void handle_tty_read(struct domain *dom)
   3.213 +{
   3.214 +	ssize_t len;
   3.215 +	xcs_msg_t msg;
   3.216 +
   3.217 +	msg.type = XCS_REQUEST;
   3.218 +	msg.u.control.remote_dom = dom->domid;
   3.219 +	msg.u.control.msg.type = CMSG_CONSOLE;
   3.220 +	msg.u.control.msg.subtype = CMSG_CONSOLE_DATA;
   3.221 +	msg.u.control.msg.id = 1;
   3.222 +
   3.223 +	len = read(dom->tty_fd, msg.u.control.msg.msg, 60);
   3.224 +	if (len < 1) {
   3.225 +		close(dom->tty_fd);
   3.226 +
   3.227 +		if (domain_is_valid(dom->domid)) {
   3.228 +			dom->tty_fd = domain_create_tty(dom);
   3.229 +		} else {
   3.230 +			remove_domain(dom);
   3.231 +		}
   3.232 +	} else if (domain_is_valid(dom->domid)) {
   3.233 +		msg.u.control.msg.length = len;
   3.234 +
   3.235 +		if (!write_sync(xcs_data_fd, &msg, sizeof(msg))) {
   3.236 +			dolog(LOG_ERR, "Write to xcs failed: %m");
   3.237 +		}
   3.238 +	} else {
   3.239 +		close(dom->tty_fd);
   3.240 +		remove_domain(dom);
   3.241 +	}
   3.242 +}
   3.243 +
   3.244 +static void handle_tty_write(struct domain *dom)
   3.245 +{
   3.246 +	ssize_t len;
   3.247 +
   3.248 +	len = write(dom->tty_fd, dom->buffer.data, dom->buffer.size);
   3.249 +	if (len < 1) {
   3.250 +		close(dom->tty_fd);
   3.251 +
   3.252 +		if (domain_is_valid(dom->domid)) {
   3.253 +			dom->tty_fd = domain_create_tty(dom);
   3.254 +		} else {
   3.255 +			remove_domain(dom);
   3.256 +		}
   3.257 +	} else {
   3.258 +		buffer_advance(&dom->buffer, len);
   3.259 +	}
   3.260 +}
   3.261 +
   3.262 +static void handle_xcs_msg(int fd)
   3.263 +{
   3.264 +	xcs_msg_t msg;
   3.265 +
   3.266 +	if (!read_sync(fd, &msg, sizeof(msg))) {
   3.267 +		dolog(LOG_ERR, "read from xcs failed! %m");
   3.268 +	} else if (msg.type == XCS_REQUEST) {
   3.269 +		struct domain *dom;
   3.270 +
   3.271 +		dom = lookup_domain(msg.u.control.remote_dom);
   3.272 +		buffer_append(&dom->buffer,
   3.273 +			      msg.u.control.msg.msg,
   3.274 +			      msg.u.control.msg.length);
   3.275 +	}
   3.276 +}
   3.277 +
   3.278 +static void enum_domains(void)
   3.279 +{
   3.280 +	int domid = 0;
   3.281 +	xc_dominfo_t dominfo;
   3.282 +
   3.283 +	while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
   3.284 +		lookup_domain(dominfo.domid);
   3.285 +		domid = dominfo.domid + 1;
   3.286 +	}
   3.287 +}
   3.288 +
   3.289 +void handle_io(void)
   3.290 +{
   3.291 +	fd_set readfds, writefds;
   3.292 +	int ret;
   3.293 +	int max_fd = -1;
   3.294 +	int num_of_writes = 0;
   3.295 +
   3.296 +	do {
   3.297 +		struct domain *d;
   3.298 +		struct timeval tv = { 1, 0 };
   3.299 +
   3.300 +		FD_ZERO(&readfds);
   3.301 +		FD_ZERO(&writefds);
   3.302 +
   3.303 +		FD_SET(xcs_data_fd, &readfds);
   3.304 +		max_fd = MAX(xcs_data_fd, max_fd);
   3.305 +
   3.306 +		for (d = dom_head; d; d = d->next) {
   3.307 +			if (d->tty_fd != -1) {
   3.308 +				FD_SET(d->tty_fd, &readfds);
   3.309 +			}
   3.310 +
   3.311 +			if (d->tty_fd != -1 && !buffer_empty(&d->buffer)) {
   3.312 +				FD_SET(d->tty_fd, &writefds);
   3.313 +			}
   3.314 +
   3.315 +			max_fd = MAX(d->tty_fd, max_fd);
   3.316 +		}
   3.317 +
   3.318 +		ret = select(max_fd + 1, &readfds, &writefds, 0, &tv);
   3.319 +		if (tv.tv_sec == 1 && (++num_of_writes % 100) == 0) {
   3.320 +			/* FIXME */
   3.321 +			/* This is a nasty hack.  xcs does not handle the
   3.322 +			   control channels filling up well at all.  We'll
   3.323 +			   throttle ourselves here since we do proper
   3.324 +			   queueing to give the domains a shot at pulling out
   3.325 +			   the data.  Fixing xcs is not worth it as it's
   3.326 +			   going away */
   3.327 +			tv.tv_usec = 1000;
   3.328 +			select(0, 0, 0, 0, &tv);
   3.329 +		}
   3.330 +		enum_domains();
   3.331 +
   3.332 +		if (FD_ISSET(xcs_data_fd, &readfds)) {
   3.333 +			handle_xcs_msg(xcs_data_fd);
   3.334 +		}
   3.335 +
   3.336 +		for (d = dom_head; d; d = d->next) {
   3.337 +			if (FD_ISSET(d->tty_fd, &readfds)) {
   3.338 +				handle_tty_read(d);
   3.339 +			}
   3.340 +
   3.341 +			if (FD_ISSET(d->tty_fd, &writefds)) {
   3.342 +				handle_tty_write(d);
   3.343 +			}
   3.344 +		}
   3.345 +	} while (ret > -1);
   3.346 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/console/daemon/io.h	Sun Aug 07 09:13:39 2005 +0000
     4.3 @@ -0,0 +1,26 @@
     4.4 +/*\
     4.5 + *  Copyright (C) International Business Machines  Corp., 2005
     4.6 + *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
     4.7 + *
     4.8 + *  Xen Console Daemon
     4.9 + *
    4.10 + *  This program is free software; you can redistribute it and/or modify
    4.11 + *  it under the terms of the GNU General Public License as published by
    4.12 + *  the Free Software Foundation; under version 2 of the License.
    4.13 + * 
    4.14 + *  This program is distributed in the hope that it will be useful,
    4.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.17 + *  GNU General Public License for more details.
    4.18 + * 
    4.19 + *  You should have received a copy of the GNU General Public License
    4.20 + *  along with this program; if not, write to the Free Software
    4.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    4.22 +\*/
    4.23 +
    4.24 +#ifndef CONSOLED_IO_H
    4.25 +#define CONSOLED_IO_H
    4.26 +
    4.27 +void handle_io(void);
    4.28 +
    4.29 +#endif
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/console/daemon/main.c	Sun Aug 07 09:13:39 2005 +0000
     5.3 @@ -0,0 +1,93 @@
     5.4 +/*\
     5.5 + *  Copyright (C) International Business Machines  Corp., 2005
     5.6 + *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
     5.7 + *
     5.8 + *  Xen Console Daemon
     5.9 + *
    5.10 + *  This program is free software; you can redistribute it and/or modify
    5.11 + *  it under the terms of the GNU General Public License as published by
    5.12 + *  the Free Software Foundation; under version 2 of the License.
    5.13 + * 
    5.14 + *  This program is distributed in the hope that it will be useful,
    5.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.17 + *  GNU General Public License for more details.
    5.18 + * 
    5.19 + *  You should have received a copy of the GNU General Public License
    5.20 + *  along with this program; if not, write to the Free Software
    5.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    5.22 +\*/
    5.23 +
    5.24 +#include <getopt.h>
    5.25 +#include <stdlib.h>
    5.26 +#include <stdio.h>
    5.27 +#include <errno.h>
    5.28 +#include <unistd.h>
    5.29 +#include <sys/types.h>
    5.30 +
    5.31 +#include "xc.h"
    5.32 +#include "xen/io/domain_controller.h"
    5.33 +#include "xcs_proto.h"
    5.34 +
    5.35 +#include "utils.h"
    5.36 +#include "io.h"
    5.37 +
    5.38 +int main(int argc, char **argv)
    5.39 +{
    5.40 +	const char *sopts = "hVvi";
    5.41 +	struct option lopts[] = {
    5.42 +		{ "help", 0, 0, 'h' },
    5.43 +		{ "version", 0, 0, 'V' },
    5.44 +		{ "verbose", 0, 0, 'v' },
    5.45 +		{ "interactive", 0, 0, 'i' },
    5.46 +		{ 0 },
    5.47 +	};
    5.48 +	bool is_interactive = false;
    5.49 +	int ch;
    5.50 +	int syslog_option = LOG_CONS;
    5.51 +	int syslog_mask = LOG_WARNING;
    5.52 +	int opt_ind = 0;
    5.53 +
    5.54 +	while ((ch = getopt_long(argc, argv, sopts, lopts, &opt_ind)) != -1) {
    5.55 +		switch (ch) {
    5.56 +		case 'h':
    5.57 +			//usage(argv[0]);
    5.58 +			exit(0);
    5.59 +		case 'V':
    5.60 +			//version(argv[0]);
    5.61 +			exit(0);
    5.62 +		case 'v':
    5.63 +			syslog_option |= LOG_PERROR;
    5.64 +			syslog_mask = LOG_DEBUG;
    5.65 +			break;
    5.66 +		case 'i':
    5.67 +			is_interactive = true;
    5.68 +			break;
    5.69 +		case '?':
    5.70 +			fprintf(stderr,
    5.71 +				"Try `%s --help' for more information\n",
    5.72 +				argv[0]);
    5.73 +			exit(EINVAL);
    5.74 +		}
    5.75 +	}
    5.76 +
    5.77 +	if (geteuid() != 0) {
    5.78 +		fprintf(stderr, "%s requires root to run.\n", argv[0]);
    5.79 +		exit(EPERM);
    5.80 +	}
    5.81 +
    5.82 +	openlog("xenconsoled", syslog_option, LOG_DAEMON);
    5.83 +	setlogmask(syslog_mask);
    5.84 +
    5.85 +	if (!is_interactive) {
    5.86 +		daemonize("/var/run/xenconsoled.pid");
    5.87 +	}
    5.88 +
    5.89 +	xen_setup();
    5.90 +
    5.91 +	handle_io();
    5.92 +
    5.93 +	closelog();
    5.94 +
    5.95 +	return 0;
    5.96 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/console/daemon/utils.c	Sun Aug 07 09:13:39 2005 +0000
     6.3 @@ -0,0 +1,251 @@
     6.4 +/*\
     6.5 + *  Copyright (C) International Business Machines  Corp., 2005
     6.6 + *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
     6.7 + *
     6.8 + *  Xen Console Daemon
     6.9 + *
    6.10 + *  This program is free software; you can redistribute it and/or modify
    6.11 + *  it under the terms of the GNU General Public License as published by
    6.12 + *  the Free Software Foundation; under version 2 of the License.
    6.13 + * 
    6.14 + *  This program is distributed in the hope that it will be useful,
    6.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.17 + *  GNU General Public License for more details.
    6.18 + * 
    6.19 + *  You should have received a copy of the GNU General Public License
    6.20 + *  along with this program; if not, write to the Free Software
    6.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    6.22 +\*/
    6.23 +
    6.24 +#include <sys/types.h>
    6.25 +#include <sys/stat.h>
    6.26 +#include <sys/wait.h>
    6.27 +#include <unistd.h>
    6.28 +#include <stdlib.h>
    6.29 +#include <fcntl.h>
    6.30 +#include <err.h>
    6.31 +#include <errno.h>
    6.32 +#include <stdio.h>
    6.33 +#include <getopt.h>
    6.34 +#include <stdbool.h>
    6.35 +#include <sys/socket.h>
    6.36 +#include <sys/un.h>
    6.37 +#include <string.h>
    6.38 +
    6.39 +#include "xc.h"
    6.40 +#include "xen/io/domain_controller.h"
    6.41 +#include "xcs_proto.h"
    6.42 +
    6.43 +#include "utils.h"
    6.44 +
    6.45 +struct xs_handle *xs;
    6.46 +int xc;
    6.47 +
    6.48 +int xcs_ctrl_fd = -1;
    6.49 +int xcs_data_fd = -1;
    6.50 +
    6.51 +bool _read_write_sync(int fd, void *data, size_t size, bool do_read)
    6.52 +{
    6.53 +	size_t offset = 0;
    6.54 +	ssize_t len;
    6.55 +
    6.56 +	while (offset < size) {
    6.57 +		if (do_read) {
    6.58 +			len = read(fd, data + offset, size - offset);
    6.59 +		} else {
    6.60 +			len = write(fd, data + offset, size - offset);
    6.61 +		}
    6.62 +
    6.63 +		if (len < 1) {
    6.64 +			if (len == -1 && (errno == EAGAIN || errno == EINTR)) {
    6.65 +				return false;
    6.66 +			}
    6.67 +		} else {
    6.68 +			offset += len;
    6.69 +		}
    6.70 +	}
    6.71 +
    6.72 +	return true;
    6.73 +}
    6.74 +
    6.75 +static int open_domain_socket(const char *path)
    6.76 +{
    6.77 +	struct sockaddr_un addr;
    6.78 +	int sock;
    6.79 +	size_t addr_len;
    6.80 +
    6.81 +	if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
    6.82 +		goto out;
    6.83 +	}
    6.84 +
    6.85 +	addr.sun_family = AF_UNIX;
    6.86 +	strcpy(addr.sun_path, path);
    6.87 +	addr_len = sizeof(addr.sun_family) + strlen(XCS_SUN_PATH) + 1;
    6.88 +
    6.89 +	if (connect(sock, (struct sockaddr *)&addr, addr_len) == -1) {
    6.90 +		goto out_close_sock;
    6.91 +	}
    6.92 +
    6.93 +	return sock;
    6.94 +
    6.95 + out_close_sock:
    6.96 +	close(sock);
    6.97 + out:
    6.98 +	return -1;
    6.99 +}
   6.100 +
   6.101 +static void child_exit(int sig)
   6.102 +{
   6.103 +	while (waitpid(-1, NULL, WNOHANG) > 0);
   6.104 +}
   6.105 +
   6.106 +void daemonize(const char *pidfile)
   6.107 +{
   6.108 +	pid_t pid;
   6.109 +	int fd;
   6.110 +	int len;
   6.111 +	int i;
   6.112 +	char buf[100];
   6.113 +
   6.114 +	if (getppid() == 1) {
   6.115 +		return;
   6.116 +	}
   6.117 +
   6.118 +	if ((pid = fork()) > 0) {
   6.119 +		exit(0);
   6.120 +	} else if (pid == -1) {
   6.121 +		err(errno, "fork() failed");
   6.122 +	}
   6.123 +
   6.124 +	setsid();
   6.125 +
   6.126 +	/* redirect fd 0,1,2 to /dev/null */
   6.127 +	if ((fd = open("/dev/null",O_RDWR)) == -1) {
   6.128 +		exit(1);
   6.129 +	}
   6.130 +
   6.131 +	for (i = 0; i <= 2; i++) {
   6.132 +		close(i);
   6.133 +		dup2(fd, i);
   6.134 +	}
   6.135 +
   6.136 +	close(fd);
   6.137 +
   6.138 +	umask(027);
   6.139 +	chdir("/");
   6.140 +
   6.141 +	fd = open(pidfile, O_RDWR | O_CREAT);
   6.142 +	if (fd == -1) {
   6.143 +		exit(1);
   6.144 +	}
   6.145 +
   6.146 +	if (lockf(fd, F_TLOCK, 0) == -1) {
   6.147 +		exit(1);
   6.148 +	}
   6.149 +
   6.150 +	len = sprintf(buf, "%d\n", getpid());
   6.151 +	write(fd, buf, len);
   6.152 +
   6.153 +	signal(SIGCHLD, child_exit);
   6.154 +	signal(SIGTSTP, SIG_IGN);
   6.155 +	signal(SIGTTOU, SIG_IGN);
   6.156 +	signal(SIGTTIN, SIG_IGN);
   6.157 +}
   6.158 +
   6.159 +/* synchronized send/recv strictly for setting up xcs */
   6.160 +/* always use asychronize callbacks any other time */
   6.161 +static bool xcs_send_recv(int fd, xcs_msg_t *msg)
   6.162 +{
   6.163 +	bool ret = false;
   6.164 +
   6.165 +	if (!write_sync(fd, msg, sizeof(*msg))) {
   6.166 +		dolog(LOG_ERR, "Write failed at %s:%s():L%d?  Possible bug.",
   6.167 +		       __FILE__, __FUNCTION__, __LINE__);
   6.168 +		goto out;
   6.169 +	}
   6.170 +
   6.171 +	if (!read_sync(fd, msg, sizeof(*msg))) {
   6.172 +		dolog(LOG_ERR, "Read failed at %s:%s():L%d?  Possible bug.",
   6.173 +		       __FILE__, __FUNCTION__, __LINE__);
   6.174 +		goto out;
   6.175 +	}
   6.176 +
   6.177 +	ret = true;
   6.178 +
   6.179 + out:
   6.180 +	return ret;
   6.181 +}
   6.182 +
   6.183 +bool xen_setup(void)
   6.184 +{
   6.185 +	int sock;
   6.186 +	xcs_msg_t msg;
   6.187 +	
   6.188 +	xs = xs_daemon_open();
   6.189 +	if (xs == NULL) {
   6.190 +		dolog(LOG_ERR,
   6.191 +		      "Failed to contact xenstore (%m).  Is it running?");
   6.192 +		goto out;
   6.193 +	}
   6.194 +
   6.195 +	xc = xc_interface_open();
   6.196 +	if (xc == -1) {
   6.197 +		dolog(LOG_ERR, "Failed to contact hypervisor (%m)");
   6.198 +		goto out;
   6.199 +	}
   6.200 +
   6.201 +	sock = open_domain_socket(XCS_SUN_PATH);
   6.202 +	if (sock == -1) {
   6.203 +		dolog(LOG_ERR, "Failed to contact xcs (%m).  Is it running?");
   6.204 +		goto out_close_store;
   6.205 +	}
   6.206 +
   6.207 +	xcs_ctrl_fd = sock;
   6.208 +
   6.209 +	sock = open_domain_socket(XCS_SUN_PATH);
   6.210 +	if (sock == -1) {
   6.211 +		dolog(LOG_ERR, "Failed to contact xcs (%m).  Is it running?");
   6.212 +		goto out_close_ctrl;
   6.213 +	}
   6.214 +	
   6.215 +	xcs_data_fd = sock;
   6.216 +
   6.217 +	memset(&msg, 0, sizeof(msg));
   6.218 +	msg.type = XCS_CONNECT_CTRL;
   6.219 +	if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
   6.220 +		dolog(LOG_ERR, "xcs control connect failed.  Possible bug.");
   6.221 +		goto out_close_data;
   6.222 +	}
   6.223 +
   6.224 +	msg.type = XCS_CONNECT_DATA;
   6.225 +	if (!xcs_send_recv(xcs_data_fd, &msg) || msg.result != XCS_RSLT_OK) {
   6.226 +		dolog(LOG_ERR, "xcs data connect failed.  Possible bug.");
   6.227 +		goto out_close_data;
   6.228 +	}
   6.229 +
   6.230 +	/* Since the vast majority of control messages are console messages
   6.231 +	   it's just easier to ignore other messages that try to bind to 
   6.232 +	   a specific type. */
   6.233 +	msg.type = XCS_MSG_BIND;
   6.234 +	msg.u.bind.port = PORT_WILDCARD;
   6.235 +	msg.u.bind.type = TYPE_WILDCARD;
   6.236 +	if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
   6.237 +		dolog(LOG_ERR, "xcs vind failed.  Possible bug.");
   6.238 +		goto out_close_data;
   6.239 +	}
   6.240 +	
   6.241 +	return true;
   6.242 +
   6.243 + out_close_data:
   6.244 +	close(xcs_ctrl_fd);
   6.245 +	xcs_data_fd = -1;
   6.246 + out_close_ctrl:
   6.247 +	close(xcs_ctrl_fd);
   6.248 +	xcs_ctrl_fd = -1;
   6.249 + out_close_store:
   6.250 +	xs_daemon_close(xs);
   6.251 + out:
   6.252 +	return false;
   6.253 +}
   6.254 +
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/console/daemon/utils.h	Sun Aug 07 09:13:39 2005 +0000
     7.3 @@ -0,0 +1,47 @@
     7.4 +/*\
     7.5 + *  Copyright (C) International Business Machines  Corp., 2005
     7.6 + *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
     7.7 + *
     7.8 + *  Xen Console Daemon
     7.9 + *
    7.10 + *  This program is free software; you can redistribute it and/or modify
    7.11 + *  it under the terms of the GNU General Public License as published by
    7.12 + *  the Free Software Foundation; under version 2 of the License.
    7.13 + * 
    7.14 + *  This program is distributed in the hope that it will be useful,
    7.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.17 + *  GNU General Public License for more details.
    7.18 + * 
    7.19 + *  You should have received a copy of the GNU General Public License
    7.20 + *  along with this program; if not, write to the Free Software
    7.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    7.22 +\*/
    7.23 +
    7.24 +#ifndef CONSOLED_UTILS_H
    7.25 +#define CONSOLED_UTILS_H
    7.26 +
    7.27 +#include <stdbool.h>
    7.28 +#include <syslog.h>
    7.29 +#include <stdio.h>
    7.30 +
    7.31 +#include "xs.h"
    7.32 +
    7.33 +void daemonize(const char *pidfile);
    7.34 +bool xen_setup(void);
    7.35 +#define read_sync(fd, buffer, size) _read_write_sync(fd, buffer, size, true)
    7.36 +#define write_sync(fd, buffer, size) _read_write_sync(fd, buffer, size, false)
    7.37 +bool _read_write_sync(int fd, void *data, size_t size, bool do_read);
    7.38 +
    7.39 +extern int xcs_ctrl_fd;
    7.40 +extern int xcs_data_fd;
    7.41 +extern struct xs_handle *xs;
    7.42 +extern int xc;
    7.43 +
    7.44 +#if 1
    7.45 +#define dolog(val, fmt, ...) syslog(val, fmt, ## __VA_ARGS__)
    7.46 +#else
    7.47 +#define dolog(val, fmt, ...) fprintf(stderr, fmt "\n", ## __VA_ARGS__)
    7.48 +#endif
    7.49 +
    7.50 +#endif
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/console/testsuite/Makefile	Sun Aug 07 09:13:39 2005 +0000
     8.3 @@ -0,0 +1,11 @@
     8.4 +CFLAGS=-g -Wall
     8.5 +CC=gcc
     8.6 +LDFLAGS=-static
     8.7 +
     8.8 +all: console-dom0 console-domU procpipe
     8.9 +
    8.10 +console-dom0: console-dom0.o
    8.11 +console-domU: console-domU.o
    8.12 +procpipe: procpipe.o
    8.13 +
    8.14 +clean:; $(RM) *.o console-domU console-dom0 procpipe
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/console/testsuite/README	Sun Aug 07 09:13:39 2005 +0000
     9.3 @@ -0,0 +1,29 @@
     9.4 +ABOUT
     9.5 +
     9.6 +This tool uses two programs, one that lives in dom0 and one that lives in domU
     9.7 +to verify that no data is lost.  dom0 and domU share a handshake with each
     9.8 +other that they use to exchange a random seed.
     9.9 +
    9.10 +Both programs then generate a series of random numbers and then writes and
    9.11 +reads the numbers via the console.  Because each side starts with the same seed
    9.12 +they know what data the other side is generating and therefore what should be
    9.13 +expected.
    9.14 +
    9.15 +RUNNNING
    9.16 +
    9.17 +console-domU should be installed within the guest image.  It must be launched
    9.18 +from the client automatically.  I use a custom initrd image and put it in the
    9.19 +/linuxrc.
    9.20 +
    9.21 +console-dom0 and console-domU will communicate with each other and stress the
    9.22 +console code.  You can verify it at various levels by invoking it in different
    9.23 +ways.  procpipe is used to connect the two.  I use the following command for
    9.24 +testing:
    9.25 +
    9.26 +./procpipe ./console-dom0 'xm create -c /etc/xen/xmexample1'
    9.27 +
    9.28 +xmexample1 has no devices and no root set (this is what triggers /linuxrc).
    9.29 +
    9.30 +If it freezes, it probably means that console-domU is expecting more data from
    9.31 +console-dom0 (which means that some data got dropped).  I'd like to add
    9.32 +timeouts in the future to handle this more gracefully.
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/console/testsuite/console-dom0.c	Sun Aug 07 09:13:39 2005 +0000
    10.3 @@ -0,0 +1,117 @@
    10.4 +/* Written by Anthony Liguori <aliguori@us.ibm.com> */
    10.5 +
    10.6 +#include <stdio.h>
    10.7 +#include <stdlib.h>
    10.8 +#include <time.h>
    10.9 +#include <string.h>
   10.10 +#include <unistd.h>
   10.11 +#include <termios.h>
   10.12 +
   10.13 +#define MIN(a, b) (((a) < (b)) ? (a) : (b))
   10.14 +
   10.15 +static void generate_random_buffer(char *buffer, size_t size)
   10.16 +{
   10.17 +	int i;
   10.18 +
   10.19 +	for (i = 0; i < size; i++) {
   10.20 +		buffer[i] = random() & 0xFF;
   10.21 +	}
   10.22 +}
   10.23 +
   10.24 +static void canonicalize(char *buffer)
   10.25 +{
   10.26 +	char *reader, *writer;
   10.27 +
   10.28 +	reader = writer = buffer;
   10.29 +
   10.30 +	while (*reader) {
   10.31 +		*writer = *reader;
   10.32 +		if (*reader != '\r') writer++;
   10.33 +		reader++;
   10.34 +	}
   10.35 +	*writer = *reader;
   10.36 +}
   10.37 +
   10.38 +int main(int argc, char **argv)
   10.39 +{
   10.40 +	char buffer[4096];
   10.41 +	char *line;
   10.42 +	unsigned int seed;
   10.43 +	size_t size;
   10.44 +	int runs;
   10.45 +	unsigned long long total_bytes = 0;
   10.46 +	struct termios term;
   10.47 +
   10.48 +	tcgetattr(STDIN_FILENO, &term);
   10.49 +	cfmakeraw(&term);
   10.50 +	tcsetattr(STDIN_FILENO, TCSAFLUSH, &term);
   10.51 +
   10.52 +	tcgetattr(STDOUT_FILENO, &term);
   10.53 +	cfmakeraw(&term);
   10.54 +	tcsetattr(STDOUT_FILENO, TCSAFLUSH, &term);
   10.55 +
   10.56 +	while ((line = fgets(buffer, sizeof(buffer), stdin))) {
   10.57 +		canonicalize(line);
   10.58 +
   10.59 +		if (strcmp(line, "!!!XEN Test Begin!!!\n") == 0) {
   10.60 +			break;
   10.61 +		} else {
   10.62 +			fprintf(stderr, "%s", line);
   10.63 +		}
   10.64 +	}
   10.65 +
   10.66 +	if (line == NULL) {
   10.67 +		fprintf(stderr, "Client never sent start string.\n");
   10.68 +		return 1;
   10.69 +	}
   10.70 +
   10.71 +	seed = time(0);
   10.72 +
   10.73 +	printf("%u\n", seed); fflush(stdout);
   10.74 +
   10.75 +	fprintf(stderr, "Waiting for seed acknowledgement\n");
   10.76 +	line = fgets(buffer, sizeof(buffer), stdin);
   10.77 +	if (line == NULL) {
   10.78 +		fprintf(stderr, "Client never acknowledge seed.\n");
   10.79 +		return 1;
   10.80 +	}
   10.81 +
   10.82 +	canonicalize(line);
   10.83 +	if (strcmp(line, "Seed Okay.\n") != 0) {
   10.84 +		fprintf(stderr, "Incorrect seed acknowledgement.\n");
   10.85 +		fprintf(stderr, "[%s]", line);
   10.86 +		return 1;
   10.87 +	} else {
   10.88 +		fprintf(stderr, "Processed seed.\n");
   10.89 +	}
   10.90 +
   10.91 +	srandom(seed);
   10.92 +
   10.93 +	for (runs = (random() % 100000) + 4096; runs > 0; runs--) {
   10.94 +
   10.95 +		size = random() % 4096;
   10.96 +
   10.97 +		fprintf(stderr, "Writing %d bytes.\n", size);
   10.98 +
   10.99 +		generate_random_buffer(buffer, size);
  10.100 +		fwrite(buffer, size, 1, stdout);
  10.101 +		fflush(stdout);
  10.102 +
  10.103 +		do {
  10.104 +			line = fgets(buffer, sizeof(buffer), stdin);
  10.105 +			if (line == NULL) {
  10.106 +				fprintf(stderr, "Premature EOF from client.\n");
  10.107 +				return 1;
  10.108 +			}
  10.109 +
  10.110 +			canonicalize(line);
  10.111 +			fprintf(stderr, "%s", line);
  10.112 +		} while (strcmp(line, "Okay.\n") != 0);
  10.113 +
  10.114 +		total_bytes += size;
  10.115 +	}
  10.116 +
  10.117 +	fprintf(stderr, "PASS: processed %llu byte(s).\n", total_bytes);
  10.118 +
  10.119 +	return 0;
  10.120 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/tools/console/testsuite/console-domU.c	Sun Aug 07 09:13:39 2005 +0000
    11.3 @@ -0,0 +1,76 @@
    11.4 +/* Written by Anthony Liguori <aliguori@us.ibm.com> */
    11.5 +
    11.6 +#include <stdio.h>
    11.7 +#include <stdlib.h>
    11.8 +#include <time.h>
    11.9 +#include <termios.h>
   11.10 +#include <unistd.h>
   11.11 +
   11.12 +static void canonicalize(char *buffer)
   11.13 +{
   11.14 +	char *reader, *writer;
   11.15 +
   11.16 +	reader = writer = buffer;
   11.17 +
   11.18 +	while (*reader) {
   11.19 +		*writer = *reader;
   11.20 +		if (*reader != '\r') writer++;
   11.21 +		reader++;
   11.22 +	}
   11.23 +	*writer = *reader;
   11.24 +}
   11.25 +
   11.26 +int main(int argc, char **argv)
   11.27 +{
   11.28 +	char buffer[4096];
   11.29 +	char *line;
   11.30 +	unsigned int seed;
   11.31 +	size_t size;
   11.32 +	int i;
   11.33 +	int runs;
   11.34 +	struct termios term;
   11.35 +
   11.36 +	tcgetattr(STDIN_FILENO, &term);
   11.37 +	cfmakeraw(&term);
   11.38 +	tcsetattr(STDIN_FILENO, TCSAFLUSH, &term);
   11.39 +
   11.40 +	tcgetattr(STDOUT_FILENO, &term);
   11.41 +	cfmakeraw(&term);
   11.42 +	tcsetattr(STDOUT_FILENO, TCSAFLUSH, &term);
   11.43 +
   11.44 +	printf("!!!XEN Test Begin!!!\n"); fflush(stdout);
   11.45 +	line = fgets(buffer, sizeof(buffer), stdin);
   11.46 +	if (line == NULL) {
   11.47 +		printf("Failure\n"); fflush(stdout);
   11.48 +		return 1;
   11.49 +	}
   11.50 +
   11.51 +	canonicalize(line);
   11.52 +	seed = strtoul(line, 0, 0);
   11.53 +
   11.54 +	printf("Seed Okay.\n"); fflush(stdout);
   11.55 +
   11.56 +	srandom(seed);
   11.57 +
   11.58 +	for (runs = (random() % 100000) + 4096; runs > 0; runs--) {
   11.59 +		size = random() % 4096;
   11.60 +
   11.61 +		for (i = 0; i < size; i++) {
   11.62 +			int ch;
   11.63 +			int exp;
   11.64 +
   11.65 +			ch = fgetc(stdin);
   11.66 +			exp = random() & 0xFF;
   11.67 +			if (ch != exp) {
   11.68 +				printf("Expected %d got %d\n",
   11.69 +				       exp, ch);
   11.70 +				fflush(stdout);
   11.71 +			}
   11.72 +			printf("Got %d/%d good bytes\n", i, size);
   11.73 +		}
   11.74 +		
   11.75 +		printf("Okay.\n"); fflush(stdout);
   11.76 +	}
   11.77 +
   11.78 +	return 0;
   11.79 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tools/console/testsuite/procpipe.c	Sun Aug 07 09:13:39 2005 +0000
    12.3 @@ -0,0 +1,133 @@
    12.4 +/* Written by Anthony Liguori <aliguori@us.ibm.com> */
    12.5 +
    12.6 +#include <stdio.h>
    12.7 +#include <getopt.h>
    12.8 +#include <errno.h>
    12.9 +#include <stdlib.h>
   12.10 +#include <err.h>
   12.11 +
   12.12 +#include <sys/types.h>
   12.13 +#include <sys/wait.h>
   12.14 +#include <unistd.h>
   12.15 +
   12.16 +#define PACKAGE_NAME "procpipe"
   12.17 +#define PACKAGE_VERSION "0.0.1"
   12.18 +
   12.19 +#define GPL_SHORT \
   12.20 +"This is free software; see the source for copying conditions.  There is NO\n"\
   12.21 +"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
   12.22 +
   12.23 +#define PACKAGE_BUGS "aliguori@us.ibm.com"
   12.24 +#define PACKAGE_AUTHOR "Anthony Liguori"
   12.25 +#define PACKAGE_OWNER "IBM, Corp."
   12.26 +#define PACKAGE_LICENSE GPL_SHORT
   12.27 +
   12.28 +static void usage(const char *name)
   12.29 +{
   12.30 +	printf("Usage: %s [OPTIONS]\n"
   12.31 +	       "\n"
   12.32 +	       "  -h, --help      display this help and exit\n"
   12.33 +	       "  -V, --version   output version information and exit\n"
   12.34 +	       "\n"
   12.35 +	       "Report bugs to <%s>.\n"
   12.36 +	       , name, PACKAGE_BUGS);
   12.37 +}
   12.38 +
   12.39 +static void version(const char *name)
   12.40 +{
   12.41 +	printf("%s (%s) %s\n"
   12.42 +	       "Written by %s.\n"
   12.43 +	       "\n"
   12.44 +	       "Copyright (C) 2005 %s.\n"
   12.45 +	       "%s\n"
   12.46 +	       , name, PACKAGE_NAME, PACKAGE_VERSION,
   12.47 +	       PACKAGE_AUTHOR, PACKAGE_OWNER, PACKAGE_LICENSE);
   12.48 +}
   12.49 +
   12.50 +static pid_t exec(int stdout, int stdin, const char *cmd)
   12.51 +{
   12.52 +	pid_t pid;
   12.53 +
   12.54 +	pid = fork();
   12.55 +	if (pid == 0) {
   12.56 +		close(STDOUT_FILENO);
   12.57 +		dup2(stdout, STDOUT_FILENO);
   12.58 +		close(STDIN_FILENO);
   12.59 +		dup2(stdin, STDIN_FILENO);
   12.60 +
   12.61 +		execlp("/bin/sh", "sh", "-c", cmd, NULL);
   12.62 +	}
   12.63 +
   12.64 +	return pid;
   12.65 +}
   12.66 +
   12.67 +int main(int argc, char **argv)
   12.68 +{
   12.69 +	int ch, opt_ind = 0;
   12.70 +	const char *sopt = "hV";
   12.71 +	struct option lopt[] = {
   12.72 +		{ "help", 0, 0, 'h' },
   12.73 +		{ "version", 0, 0, 'V' },
   12.74 +		{ 0 }
   12.75 +	};
   12.76 +	int host_stdout[2];
   12.77 +	int host_stdin[2];
   12.78 +	int res;
   12.79 +	pid_t pid1, pid2;
   12.80 +	int status;
   12.81 +
   12.82 +	while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
   12.83 +		switch (ch) {
   12.84 +		case 'h':
   12.85 +			usage(argv[0]);
   12.86 +			exit(0);
   12.87 +		case 'V':
   12.88 +			version(argv[0]);
   12.89 +			exit(0);
   12.90 +		case '?':
   12.91 +			errx(EINVAL, "Try `%s --help' for more information.",
   12.92 +			     argv[0]);
   12.93 +		}
   12.94 +	}
   12.95 +
   12.96 +	if ((argc - optind) != 2) {
   12.97 +		errx(EINVAL, "Two commands are required.\n"
   12.98 +		     "Try `%s --help' for more information.", argv[0]);
   12.99 +	}
  12.100 +
  12.101 +	res = pipe(host_stdout);
  12.102 +	if (res == -1) {
  12.103 +		err(errno, "pipe() failed");
  12.104 +	}
  12.105 +
  12.106 +	res = pipe(host_stdin);
  12.107 +	if (res == -1) {
  12.108 +		err(errno, "pipe() failed");
  12.109 +	}
  12.110 +
  12.111 +	pid1 = exec(host_stdout[1], host_stdin[0], argv[optind]);
  12.112 +	if (pid1 == -1) {
  12.113 +		err(errno, "exec(%s)", argv[optind]);
  12.114 +	}
  12.115 +
  12.116 +	pid2 = exec(host_stdin[1], host_stdout[0], argv[optind + 1]);
  12.117 +	if (pid2 == -1) {
  12.118 +		err(errno, "exec(%s)", argv[optind + 1]);
  12.119 +	}
  12.120 +
  12.121 +	waitpid(pid1, &status, 0);
  12.122 +	if (WIFEXITED(status)) status = WEXITSTATUS(status);
  12.123 +
  12.124 +	if (status != 0) {
  12.125 +		printf("Child exited with status %d\n", status);
  12.126 +	}
  12.127 +
  12.128 +	waitpid(pid2, &status, 0);
  12.129 +	if (WIFEXITED(status)) status = WEXITSTATUS(status);
  12.130 +
  12.131 +	if (status != 0) {
  12.132 +		printf("Child2 exited with status %d\n", status);
  12.133 +	}
  12.134 +
  12.135 +	return 0;
  12.136 +}