direct-io.hg
changeset 6038:deff07c1b686
Really include renamed console files. :-)
Signed-off-by: Keir Fraser <keir@xensource.com>
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 +}