ia64/xen-unstable

changeset 4049:176d6d355157

bitkeeper revision 1.1236.12.25 (422f282953v_J4bTBy1CN1Z9x3rhog)

.del-util.c~fb55f547242f9869:
Delete: tools/x2d2/util.c
.del-minixend.h~9bba8a3fbfa4153:
Delete: tools/x2d2/minixend.h
.del-minixend.c~ef5576bb71152607:
Delete: tools/x2d2/minixend.c
.del-cntrl_con.c~9df6acbfc777c229:
Delete: tools/x2d2/cntrl_con.c
.del-Makefile~7ab0b94e34972cb0:
Delete: tools/x2d2/Makefile
author kaf24@firebug.cl.cam.ac.uk
date Wed Mar 09 16:45:29 2005 +0000 (2005-03-09)
parents cf2f74cc53af
children a38777f9f099 96b57b335681
files .rootkeys tools/x2d2/Makefile tools/x2d2/cntrl_con.c tools/x2d2/minixend.c tools/x2d2/minixend.h tools/x2d2/util.c
line diff
     1.1 --- a/.rootkeys	Wed Mar 09 16:43:57 2005 +0000
     1.2 +++ b/.rootkeys	Wed Mar 09 16:45:29 2005 +0000
     1.3 @@ -850,11 +850,6 @@ 41a2188aIf3Xk6uvk7KzjdpOsflAEw tools/vne
     1.4  41a2188ar6_vOO3_tEJQjmFVU3409A tools/vnet/vnetd/vcache.h
     1.5  41a2188aETrGU60X9WtGhYVfU7z0Pw tools/vnet/vnetd/vnetd.c
     1.6  41a2188ahYjemudGyB7078AWMFR-0w tools/vnet/vnetd/vnetd.h
     1.7 -4194e861IgTabTt8HOuh143QIJFD1Q tools/x2d2/Makefile
     1.8 -4194e861M2gcBz4i94cQYpqzi8n6UA tools/x2d2/cntrl_con.c
     1.9 -4194e8612TrrMvC8ZlA4h2ZYCPWz4g tools/x2d2/minixend.c
    1.10 -4194e861x2eqNCD61RYPCUEBVdMYuw tools/x2d2/minixend.h
    1.11 -4194e861A4V9VbD_FYmgXpYEj5YwVg tools/x2d2/util.c
    1.12  41d58ba63w1WfBmd6Cr_18nhLNv7PA tools/xcs/Makefile
    1.13  41d58ba6NxgkfzD_rmsGjgd_zJ3H_w tools/xcs/bindings.c
    1.14  41d58ba6I2umi60mShq4Pl0RDg7lzQ tools/xcs/connection.c
     2.1 --- a/tools/x2d2/Makefile	Wed Mar 09 16:43:57 2005 +0000
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,22 +0,0 @@
     2.4 -XEN_ROOT=../..
     2.5 -include $(XEN_ROOT)/tools/Rules.mk
     2.6 -
     2.7 -CC       = gcc
     2.8 -CFLAGS  += -Wall -Werror -O3 -fno-strict-aliasing
     2.9 -
    2.10 -CFLAGS  += -I $(XEN_XC)
    2.11 -CFLAGS  += -I $(XEN_LIBXC)
    2.12 -CFLAGS  += -I $(XEN_LIBXUTIL)
    2.13 -
    2.14 -HDRS     = $(wildcard *.h)
    2.15 -OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))
    2.16 -
    2.17 -BIN      = minixend
    2.18 -
    2.19 -all: $(BIN)
    2.20 -
    2.21 -clean:
    2.22 -	$(RM) *.a *.so *.o *.rpm $(BIN)
    2.23 -
    2.24 -$(BIN): $(OBJS)
    2.25 -	$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_LIBXUTIL) -lxc -lxutil -lpthread
     3.1 --- a/tools/x2d2/cntrl_con.c	Wed Mar 09 16:43:57 2005 +0000
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,457 +0,0 @@
     3.4 -#define _GNU_SOURCE
     3.5 -
     3.6 -#include <sys/types.h>
     3.7 -#include <sys/ioctl.h>
     3.8 -#include <sys/socket.h>
     3.9 -#include <assert.h>
    3.10 -#include <ctype.h>
    3.11 -#include <err.h>
    3.12 -#include <errno.h>
    3.13 -#include <pthread.h>
    3.14 -#include <netinet/in.h>
    3.15 -#include <stdarg.h>
    3.16 -#include <stddef.h>
    3.17 -#include <stdio.h>
    3.18 -#include <stdlib.h>
    3.19 -#include <string.h>
    3.20 -#include <unistd.h>
    3.21 -
    3.22 -#include "minixend.h"
    3.23 -
    3.24 -struct command {
    3.25 -	const char *name;
    3.26 -	void (*func)(struct open_connection *oc, const struct command *c,
    3.27 -		     const char *, const char *);
    3.28 -};
    3.29 -
    3.30 -static void
    3.31 -domain_created(const char *name, int mem_kb, int domid)
    3.32 -{
    3.33 -	struct domain *d;
    3.34 -	d = xmalloc(sizeof(*d));
    3.35 -	d->domid = domid;
    3.36 -	d->name = xstrdup(name);
    3.37 -	d->mem_kb = mem_kb;
    3.38 -	d->state = DOM_STATE_CREATED;
    3.39 -	d->control_evtchn = -1; /* Not connected yet. */
    3.40 -
    3.41 -	memcpy(d->netif_mac, "\xaa\x00\x00\x02\x00\x00", 6);
    3.42 -	d->netif_mac[5] = d->domid;
    3.43 -
    3.44 -	pthread_mutex_init(&d->mux, NULL);
    3.45 -	pthread_cond_init(&d->cond, NULL);
    3.46 -	pthread_create(&d->thread, NULL, domain_thread_func, d);
    3.47 -
    3.48 -	list_insert_after(&d->domain_list, &head_domain);
    3.49 -}
    3.50 -
    3.51 -static struct domain *
    3.52 -find_domain(int domain_id)
    3.53 -{
    3.54 -	struct domain *d;
    3.55 -
    3.56 -	foreach_domain(d) {
    3.57 -		if (d->domid == domain_id)
    3.58 -			return d;
    3.59 -	}
    3.60 -	return NULL;
    3.61 -}
    3.62 -
    3.63 -static int
    3.64 -free_event_port(struct domain *d, int port)
    3.65 -{
    3.66 -	if (d == NULL)
    3.67 -		return xc_evtchn_close(xc_handle, DOMID_SELF, port);
    3.68 -	else
    3.69 -		return xc_evtchn_close(xc_handle, d->domid, port);
    3.70 -}
    3.71 -
    3.72 -static char *
    3.73 -readline(struct open_connection *oc)
    3.74 -{
    3.75 -	char *end;
    3.76 -	char *res;
    3.77 -	int line_length;
    3.78 -
    3.79 -	if (oc->state == OC_STATE_ERROR)
    3.80 -		return NULL;
    3.81 -
    3.82 -	end = memchr(oc->buf, '\r', oc->buf_used);
    3.83 -	assert(end != NULL);
    3.84 -	line_length = end - oc->buf;
    3.85 -
    3.86 -	res = xmalloc(line_length + 1);
    3.87 -	memcpy(res, oc->buf, line_length);
    3.88 -	res[line_length] = 0;
    3.89 -	memmove(oc->buf, oc->buf + line_length + 2,
    3.90 -		oc->buf_used - line_length - 2);
    3.91 -
    3.92 -	oc->buf_used -= line_length + 2;
    3.93 -
    3.94 -	if (memchr(oc->buf, '\n', oc->buf_used))
    3.95 -		oc->state = OC_STATE_COMMAND_PENDING;
    3.96 -	else
    3.97 -		oc->state = OC_STATE_CONNECTED;
    3.98 -
    3.99 -	return res;
   3.100 -}
   3.101 -
   3.102 -static unsigned long
   3.103 -find_domain_shared_info_mfn(struct domain *d)
   3.104 -{
   3.105 -	xc_dominfo_t info;
   3.106 -
   3.107 -	xc_domain_getinfo(xc_handle, d->domid, 1, &info);
   3.108 -	return info.shared_info_frame;
   3.109 -}
   3.110 -
   3.111 -static void
   3.112 -send_message(struct open_connection *oc, const char *fmt, ...)
   3.113 -{
   3.114 -	char *buf;
   3.115 -	va_list ap;
   3.116 -	int size;
   3.117 -	int off;
   3.118 -	ssize_t r;
   3.119 -
   3.120 -	if (oc->state == OC_STATE_ERROR)
   3.121 -		return;
   3.122 -
   3.123 -	va_start(ap, fmt);
   3.124 -	size = vasprintf(&buf, fmt, ap);
   3.125 -	va_end(ap);
   3.126 -	if (size < 0)
   3.127 -		err(1, "preparing response to a query");
   3.128 -	assert(buf[0] == 'E' || buf[0] == 'N');
   3.129 -	assert(isdigit(buf[1]));
   3.130 -	assert(isdigit(buf[2]));
   3.131 -	assert(buf[3] == ' ' || buf[3] == '\n');
   3.132 -
   3.133 -	off = 0;
   3.134 -	while (off < size) {
   3.135 -		r = write(oc->fd, buf + off, size - off);
   3.136 -		if (r < 0) {
   3.137 -			warn("sending response to remote");
   3.138 -			oc->state = OC_STATE_ERROR;
   3.139 -			free(buf);
   3.140 -			return;
   3.141 -		}
   3.142 -		off += r;
   3.143 -	}
   3.144 -	free(buf);
   3.145 -}
   3.146 -
   3.147 -static void
   3.148 -default_command_handler(struct open_connection *oc, const struct command *ign,
   3.149 -			const char *buf, const char *args)
   3.150 -{
   3.151 -	warnx("bad command %s", buf);
   3.152 -	send_message(oc, "E00 unknown command %s\n", buf);
   3.153 -}
   3.154 -
   3.155 -static void
   3.156 -create_command_handler(struct open_connection *oc, const struct command *ign,
   3.157 -		       const char *buf, const char *args)
   3.158 -{
   3.159 -	char *name;
   3.160 -	unsigned mem_kb;
   3.161 -	int r;
   3.162 -	u32 domid = -1;
   3.163 -
   3.164 -	r = sscanf(args, "%d %a[^\n]", &mem_kb, &name);
   3.165 -	if (r != 2) {
   3.166 -		send_message(oc, "E01 failed to parse %s\n", args);
   3.167 -		return;
   3.168 -	}
   3.169 -	r = xc_domain_create(xc_handle, mem_kb, -1, 0, &domid);
   3.170 -	if (r < 0) {
   3.171 -		send_message(oc, "E02 creating domain (%s)\n",
   3.172 -			     strerror(errno));
   3.173 -		free(name);
   3.174 -		return;
   3.175 -	}
   3.176 -
   3.177 -	domain_created(name, mem_kb, domid);
   3.178 -
   3.179 -	send_message(oc, "N00 %d\n", domid);
   3.180 -	free(name);
   3.181 -}
   3.182 -
   3.183 -static void
   3.184 -build_command_handler(struct open_connection *oc, const struct command *ign,
   3.185 -		      const char *buf, const char *args)
   3.186 -{
   3.187 -	struct domain *d;
   3.188 -	int domain_id;
   3.189 -	char *image, *cmdline;
   3.190 -	int event_ports[2];
   3.191 -	int r;
   3.192 -
   3.193 -	r = sscanf(args, "%d %a[^\t] %a[^\n]", &domain_id,
   3.194 -		   &image, &cmdline);
   3.195 -	if (r != 3) {
   3.196 -		send_message(oc, "E03 failed to parse %s\n", args);
   3.197 -		return;
   3.198 -	}
   3.199 -	d = find_domain(domain_id);
   3.200 -	if (d == NULL) {
   3.201 -		send_message(oc, "E04 unknown domain %d\n", domain_id);
   3.202 -		goto out;
   3.203 -	}
   3.204 -	if (d->state != DOM_STATE_CREATED) {
   3.205 -		send_message(oc, "E05 domain %d in bad state\n", domain_id);
   3.206 -		goto out;
   3.207 -	}
   3.208 -
   3.209 -	r = allocate_event_channel(d, event_ports);
   3.210 -	if (r < 0) {
   3.211 -		send_message(oc, "E06 allocating control event channel: %s\n",
   3.212 -			     strerror(errno));
   3.213 -		goto out;
   3.214 -	}
   3.215 -
   3.216 -	r = xc_linux_build(xc_handle, domain_id, image, NULL, cmdline,
   3.217 -			   event_ports[1], 0);
   3.218 -	if (r < 0) {
   3.219 -		send_message(oc, "E07 building domain: %s\n",
   3.220 -			     strerror(errno));
   3.221 -		free_event_port(NULL, event_ports[0]);
   3.222 -		free_event_port(d, event_ports[1]);
   3.223 -		goto out;
   3.224 -	}
   3.225 -
   3.226 -	if (ioctl(evtchn_fd, EVTCHN_BIND, event_ports[0]) < 0)
   3.227 -		err(1, "binding to event control event channel");
   3.228 -
   3.229 -	d->shared_info_mfn = find_domain_shared_info_mfn(d);
   3.230 -	d->shared_info = map_domain_mem(d, d->shared_info_mfn);
   3.231 -	if (d->shared_info == NULL)
   3.232 -		err(1, "maping domain shared info page at %lx.\n",
   3.233 -		    d->shared_info_mfn);
   3.234 -	d->ctrl_if = (control_if_t *)((unsigned)d->shared_info + 2048);
   3.235 -
   3.236 -	d->control_evtchn = event_ports[0];
   3.237 -	d->state = DOM_STATE_PAUSED;
   3.238 -
   3.239 -	send_message(oc, "N00\n");
   3.240 -
   3.241 - out:
   3.242 -	free(image);
   3.243 -	free(cmdline);
   3.244 -	return;
   3.245 -}
   3.246 -
   3.247 -static void
   3.248 -unpause_command_handler(struct open_connection *oc,
   3.249 -			const struct command *ign,
   3.250 -			const char *buf,
   3.251 -			const char *args)
   3.252 -{
   3.253 -	int domain_id;
   3.254 -	int r;
   3.255 -	struct domain *d;
   3.256 -
   3.257 -	r = sscanf(args, "%d", &domain_id);
   3.258 -	if (r != 1) {
   3.259 -		send_message(oc, "E08 cannot parse %s\n", args);
   3.260 -		return;
   3.261 -	}
   3.262 -	d = find_domain(domain_id);
   3.263 -	if (d == NULL) {
   3.264 -		send_message(oc, "E09 cannot find domain %d\n", domain_id);
   3.265 -		return;
   3.266 -	}
   3.267 -	if (d->state != DOM_STATE_PAUSED) {
   3.268 -		send_message(oc, "E10 domain not paused\n");
   3.269 -		return;
   3.270 -	}
   3.271 -
   3.272 -	r = xc_domain_unpause(xc_handle, d->domid);
   3.273 -	if (r < 0) {
   3.274 -		send_message(oc, "E11 unpausing domain: %s\n",
   3.275 -			     strerror(errno));
   3.276 -		return;
   3.277 -	}
   3.278 -
   3.279 -	d->state = DOM_STATE_RUNNING;
   3.280 -	send_message(oc, "N00\n");
   3.281 -}
   3.282 -
   3.283 -static void
   3.284 -console_command_handler(struct open_connection *oc,
   3.285 -			const struct command *ign,
   3.286 -			const char *buf,
   3.287 -			const char *args)
   3.288 -{
   3.289 -	int domain_id;
   3.290 -	struct domain *d;
   3.291 -	int r;
   3.292 -	struct sockaddr_in name;
   3.293 -	socklen_t namelen;
   3.294 -
   3.295 -	r = sscanf(args, "%d", &domain_id);
   3.296 -	if (r != 1) {
   3.297 -		send_message(oc, "E12 cannot parse %s\n", args);
   3.298 -		return;
   3.299 -	}
   3.300 -	d = find_domain(domain_id);
   3.301 -	if (d == NULL) {
   3.302 -		send_message(oc, "E13 cannot find domain %d\n", domain_id);
   3.303 -		return;
   3.304 -	}
   3.305 -	if (d->cc != NULL) {
   3.306 -		send_message(oc, "E14 console already exists\n");
   3.307 -		return;
   3.308 -	}
   3.309 -
   3.310 -	d->cc = xmalloc(sizeof(*d->cc));
   3.311 -	d->cc->fd = socket(PF_INET, SOCK_STREAM, 0);
   3.312 -	if (d->cc->fd < 0)
   3.313 -		err(1, "creating console socket");
   3.314 -	d->cc->dom = d;
   3.315 -	d->cc->state = CC_STATE_PENDING;
   3.316 -	d->cc->buf_used = 0;
   3.317 -	d->cc->buf_allocated = 0;
   3.318 -	d->cc->buf = NULL;
   3.319 -
   3.320 -	r = listen(d->cc->fd, 1);
   3.321 -	if (r < 0)
   3.322 -		err(1, "listening on console socket");
   3.323 -	namelen = sizeof(name);
   3.324 -	r = getsockname(d->cc->fd, (struct sockaddr *)&name, &namelen);
   3.325 -	if (r < 0)
   3.326 -		err(1, "getting name of console socket");
   3.327 -	assert(name.sin_family == AF_INET);
   3.328 -	assert(namelen == sizeof(name));
   3.329 -	list_insert_after(&d->cc->list, &head_console);
   3.330 -	send_message(oc, "N00 %d\n", ntohs(name.sin_port));
   3.331 -}
   3.332 -
   3.333 -static void
   3.334 -plug_command_handler(struct open_connection *oc,
   3.335 -		     const struct command *ign,
   3.336 -		     const char *buf,
   3.337 -		     const char *args)
   3.338 -{
   3.339 -	unsigned domid;
   3.340 -	int r;
   3.341 -	struct domain *d;
   3.342 -
   3.343 -	r = sscanf(args, "%d", &domid);
   3.344 -	if (r != 1) {
   3.345 -		send_message(oc, "E15 cannot parse %s\n", args);
   3.346 -		return;
   3.347 -	}
   3.348 -	d = find_domain(domid);
   3.349 -	if (d == NULL) {
   3.350 -		send_message(oc, "E16 cannot find domain %d\n", domid);
   3.351 -		return;
   3.352 -	}
   3.353 -
   3.354 -	d->plugged = 1;
   3.355 -	send_message(oc, "N00\n");
   3.356 -	PRINTF(1, "set domain %d plug state to %d\n", d->domid, d->plugged);
   3.357 -}
   3.358 -
   3.359 -static void
   3.360 -destroy_command_handler(struct open_connection *oc,
   3.361 -			const struct command *ign,
   3.362 -			const char *buf,
   3.363 -			const char *args)
   3.364 -{
   3.365 -	unsigned domid;
   3.366 -	int r;
   3.367 -	struct domain *d;
   3.368 -
   3.369 -	r = sscanf(args, "%d", &domid);
   3.370 -	if (r != 1) {
   3.371 -		send_message(oc, "E17 cannot parse %s\n", args);
   3.372 -		return;
   3.373 -	}
   3.374 -	d = find_domain(domid);
   3.375 -	if (d == NULL) {
   3.376 -		send_message(oc, "E18 cannot find domain %d\n", domid);
   3.377 -		return;
   3.378 -	}
   3.379 -
   3.380 -	r = xc_domain_destroy(xc_handle, domid);
   3.381 -	if (r < 0) {
   3.382 -		send_message( oc, "E19 error destroying domain %d: %s\n",
   3.383 -			      domid, strerror(errno) );
   3.384 -		return;
   3.385 -	}
   3.386 -	d->state = DOM_STATE_DEAD;
   3.387 -
   3.388 -	send_message(oc, "N00\n");
   3.389 -}
   3.390 -
   3.391 -static void
   3.392 -list_command_handler(struct open_connection *oc,
   3.393 -		     const struct command *ign,
   3.394 -		     const char *buf,
   3.395 -		     const char *args)
   3.396 -{
   3.397 -	struct domain *d;
   3.398 -	static const char *const state_strings[] = {
   3.399 -		[DOM_STATE_CREATED] = "created",
   3.400 -		[DOM_STATE_PAUSED] = "paused",
   3.401 -		[DOM_STATE_RUNNING] = "running",
   3.402 -		[DOM_STATE_DEAD] = "dead"
   3.403 -	};
   3.404 -
   3.405 -	foreach_domain(d) {
   3.406 -		send_message(oc, "N01 %d %s %d %s\n",
   3.407 -			     d->domid,
   3.408 -			     d->name,
   3.409 -			     d->mem_kb,
   3.410 -			     state_strings[d->state]);
   3.411 -	}
   3.412 -	send_message(oc, "N00\n");
   3.413 -}
   3.414 -
   3.415 -static struct command
   3.416 -default_command = { NULL, default_command_handler };
   3.417 -
   3.418 -static struct command
   3.419 -commands[] = {
   3.420 -	{ "build", build_command_handler },
   3.421 -	{ "console", console_command_handler },
   3.422 -	{ "create", create_command_handler },
   3.423 -	{ "destroy", destroy_command_handler },
   3.424 -	{ "plug", plug_command_handler },
   3.425 -	{ "list", list_command_handler },
   3.426 -	{ "unpause", unpause_command_handler }
   3.427 -};
   3.428 -
   3.429 -void
   3.430 -process_command(struct open_connection *oc)
   3.431 -{
   3.432 -	char *buf, *b;
   3.433 -	int command_len;
   3.434 -	int x;
   3.435 -	struct command *cmd;
   3.436 -
   3.437 -	buf = readline(oc);
   3.438 -	if (buf == NULL)
   3.439 -		return;
   3.440 -	b = strchr(buf, ' ');
   3.441 -	if (b == NULL)
   3.442 -		command_len = strlen(buf);
   3.443 -	else
   3.444 -		command_len = b - buf;
   3.445 -	b = buf + command_len;
   3.446 -	while (b[0] && b[0] == ' ')
   3.447 -		b++;
   3.448 -
   3.449 -	cmd = &default_command;
   3.450 -	for (x = 0; x < sizeof(commands) / sizeof(commands[0]); x++) {
   3.451 -		if (strlen(commands[x].name) == command_len &&
   3.452 -		    memcmp(commands[x].name, buf, command_len) == 0) {
   3.453 -			cmd = &commands[x];
   3.454 -			break;
   3.455 -		}
   3.456 -	}
   3.457 -	cmd->func(oc, cmd, buf, b);
   3.458 -	free(buf);
   3.459 -	return;
   3.460 -}
     4.1 --- a/tools/x2d2/minixend.c	Wed Mar 09 16:43:57 2005 +0000
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,939 +0,0 @@
     4.4 -#define _GNU_SOURCE
     4.5 -
     4.6 -#include <sys/types.h>
     4.7 -#include <sys/fcntl.h>
     4.8 -#include <sys/ioctl.h>
     4.9 -#include <sys/mman.h>
    4.10 -#include <sys/select.h>
    4.11 -#include <sys/socket.h>
    4.12 -#include <sys/wait.h>
    4.13 -#include <asm/page.h>
    4.14 -#include <assert.h>
    4.15 -#include <ctype.h>
    4.16 -#include <err.h>
    4.17 -#include <errno.h>
    4.18 -#include <netinet/in.h>
    4.19 -#include <printf.h>
    4.20 -#include <pthread.h>
    4.21 -#include <sched.h>
    4.22 -#include <stdarg.h>
    4.23 -#include <stddef.h>
    4.24 -#include <stdio.h>
    4.25 -#include <stdlib.h>
    4.26 -#include <string.h>
    4.27 -#include <unistd.h>
    4.28 -
    4.29 -#include "minixend.h"
    4.30 -
    4.31 -#define NETWORK_SCRIPT "/etc/xen/scripts/network"
    4.32 -#define VIFBRIDGE_SCRIPT "/etc/xen/scripts/vif-bridge"
    4.33 -
    4.34 -#define MINIXEND_PORT 5123
    4.35 -
    4.36 -#define mb() asm volatile ("" ::: "memory")
    4.37 -
    4.38 -static void send_control_message(int type, int subtype, int id,
    4.39 -				 int size, void *payload,
    4.40 -				 struct domain *target);
    4.41 -
    4.42 -struct list_head
    4.43 -head_domain = LIST_HEAD(&head_domain);
    4.44 -
    4.45 -static struct list_head
    4.46 -head_connection = LIST_HEAD(&head_connection);
    4.47 -
    4.48 -struct list_head
    4.49 -head_console = LIST_HEAD(&head_console);
    4.50 -
    4.51 -#define foreach_open_connection(d)                                          \
    4.52 -foreach_item(d, &head_connection, struct open_connection, connection_list)
    4.53 -
    4.54 -/* Not modified after initial start up */
    4.55 -static struct domain *dom0;
    4.56 -unsigned xc_handle;
    4.57 -static int listen_fd;
    4.58 -int evtchn_fd;
    4.59 -
    4.60 -static struct list_head
    4.61 -head_event_receiver = LIST_HEAD(&head_event_receiver);
    4.62 -
    4.63 -struct event_receiver {
    4.64 -	struct list_head list;
    4.65 -	int id;
    4.66 -	pthread_cond_t cond;
    4.67 -};
    4.68 -
    4.69 -/* We're protected by the dom0 mutex in here */
    4.70 -static struct event_receiver *
    4.71 -allocate_event_receiver(struct domain *d)
    4.72 -{
    4.73 -	static int next_message_id;
    4.74 -	struct event_receiver *work;
    4.75 -
    4.76 -	assert(d == dom0);
    4.77 -	work = xmalloc(sizeof(*work));
    4.78 -	work->id = next_message_id++;
    4.79 -	pthread_cond_init(&work->cond, NULL);
    4.80 -
    4.81 -	list_insert_after(&work->list, &head_event_receiver);
    4.82 -
    4.83 -	return work;
    4.84 -}
    4.85 -
    4.86 -static struct event_receiver *
    4.87 -find_event_receiver(int id)
    4.88 -{
    4.89 -	struct event_receiver *work;
    4.90 -	foreach_item(work, &head_event_receiver, struct event_receiver, list)
    4.91 -		if (work->id == id)
    4.92 -			return work;
    4.93 -	return NULL;
    4.94 -}
    4.95 -
    4.96 -static void
    4.97 -release_event_receiver(struct event_receiver *w)
    4.98 -{
    4.99 -	list_remove(&w->list);
   4.100 -	pthread_cond_destroy(&w->cond);
   4.101 -	free(w);
   4.102 -}
   4.103 -
   4.104 -/* Send a message to dom0, and then block awaiting a reply. */
   4.105 -/* Make sure we don't hold any domain mutexs */
   4.106 -static void
   4.107 -send_dom0_message_block(control_msg_t *msg)
   4.108 -{
   4.109 -	CONTROL_RING_IDX c;
   4.110 -	struct event_receiver *er;
   4.111 -	control_msg_t buf;
   4.112 -
   4.113 -	PRINTF(0, "sending message to dom0 and blocking for reply.\n");
   4.114 -	pthread_mutex_lock(&dom0->mux);
   4.115 -	PRINTF(0, "got dom0 lock.\n");
   4.116 -	er = allocate_event_receiver(dom0);
   4.117 -	PRINTF(0, "allocated evetn receiver.\n");
   4.118 -	msg->id = er->id;
   4.119 -	PRINTF(1, "sending message with id %d\n", msg->id);
   4.120 -	send_control_message(msg->type, msg->subtype,
   4.121 -			     msg->id, msg->length, msg->msg, dom0);
   4.122 -	xc_evtchn_send(xc_handle, dom0->control_evtchn);
   4.123 -
   4.124 -	PRINTF(0, "waiting for reply\n");
   4.125 -	pthread_cond_wait(&er->cond, &dom0->mux);
   4.126 -	PRINTF(0, "got reply\n");
   4.127 -
   4.128 -	c = dom0->rx_resp_cons % CONTROL_RING_SIZE;
   4.129 -	memcpy(&buf, &dom0->ctrl_if->rx_ring[c], sizeof(buf));
   4.130 -	assert(msg->id == buf.id);
   4.131 -	assert(msg->type == buf.type);
   4.132 -	assert(msg->subtype == buf.subtype);
   4.133 -	memcpy(msg, &buf, sizeof(*msg));
   4.134 -	dom0->rx_resp_cons++;
   4.135 -
   4.136 -	release_event_receiver(er);
   4.137 -
   4.138 -	pthread_mutex_unlock(&dom0->mux);
   4.139 -
   4.140 -	PRINTF(1, "got reply to message with id %d\n", msg->id);
   4.141 -}
   4.142 -
   4.143 -/* Allocate an interdomain event channel.  event_ports[0] is the
   4.144 -   local event port number, event_ports[1] the remote */
   4.145 -int
   4.146 -allocate_event_channel(struct domain *d, int event_ports[2])
   4.147 -{
   4.148 -	return xc_evtchn_bind_interdomain(xc_handle, DOMID_SELF,
   4.149 -					  d->domid, event_ports,
   4.150 -					  event_ports+1);
   4.151 -}
   4.152 -
   4.153 -static void
   4.154 -accept_new_connection(void)
   4.155 -{
   4.156 -	int fd;
   4.157 -	struct open_connection *oc;
   4.158 -
   4.159 -	fd = accept(listen_fd, NULL, NULL);
   4.160 -	if (fd < 0)
   4.161 -		return;
   4.162 -	oc = xmalloc(sizeof(*oc));
   4.163 -	oc->fd = fd;
   4.164 -	oc->state = OC_STATE_CONNECTED;
   4.165 -	oc->buf_used = 0;
   4.166 -	oc->buf_allocated = 16;
   4.167 -	oc->buf = xmalloc(oc->buf_allocated);
   4.168 -	list_insert_after(&oc->connection_list, &head_connection);
   4.169 -}
   4.170 -
   4.171 -static void
   4.172 -closedown_connection(struct open_connection *oc)
   4.173 -{
   4.174 -	close(oc->fd);
   4.175 -	assert(oc->buf);
   4.176 -	free(oc->buf);
   4.177 -	free(oc);
   4.178 -}
   4.179 -
   4.180 -#if 0
   4.181 -/* Hackl for the benefit of domain replay */
   4.182 -static unsigned
   4.183 -report_work(u32 *ptr, u32 val, unsigned dom, int do_direct)
   4.184 -{
   4.185 -	if (!do_direct) {
   4.186 -		int rc;
   4.187 -		asm("int $0x80" : "=a" (rc)
   4.188 -		    : "0" (264), "b" (ptr), "c" (val), "d" (dom));
   4.189 -		if (rc < 0) {
   4.190 -			errno = -rc;
   4.191 -			rc = -1;
   4.192 -		}
   4.193 -		return rc;
   4.194 -	} else {
   4.195 -		*ptr = val;
   4.196 -		return 0;
   4.197 -	}
   4.198 -}
   4.199 -#else
   4.200 -static unsigned
   4.201 -report_work(u32 *ptr, u32 val, unsigned dom, int do_direct)
   4.202 -{
   4.203 -	*ptr = val;
   4.204 -	return 0;
   4.205 -}
   4.206 -#endif
   4.207 -
   4.208 -static void
   4.209 -send_control_reply(const control_msg_t *msg, struct domain *d)
   4.210 -{
   4.211 -	CONTROL_RING_IDX c;
   4.212 -
   4.213 -	PRINTF(3,"Control reply, type %d:%d, length %d.\n",
   4.214 -	       msg->type, msg->subtype, msg->length);
   4.215 -	c = d->ctrl_if->tx_resp_prod % CONTROL_RING_SIZE;
   4.216 -	memcpy(&d->ctrl_if->tx_ring[c], msg, sizeof(*msg));
   4.217 -	report_work(&d->ctrl_if->tx_resp_prod,
   4.218 -		    d->ctrl_if->tx_resp_prod + 1,
   4.219 -		    d->domid,
   4.220 -		    0);
   4.221 -	PRINTF(4,"tx_resp_prod %ld.\n", d->ctrl_if->tx_resp_prod);
   4.222 -	assert(!d->plugged);
   4.223 -}
   4.224 -
   4.225 -static void
   4.226 -send_trivial_control_reply(const control_msg_t *msg, struct domain *d)
   4.227 -{
   4.228 -	control_msg_t rep;
   4.229 -
   4.230 -	memset(&rep, 0, sizeof(rep));
   4.231 -	rep.type = msg->type;
   4.232 -	rep.subtype = msg->subtype;
   4.233 -	rep.id = msg->id;
   4.234 -	send_control_reply(&rep, d);
   4.235 -}
   4.236 -
   4.237 -static void
   4.238 -process_console_control_message(control_msg_t *m, struct domain *d)
   4.239 -{
   4.240 -	int off;
   4.241 -	int r;
   4.242 -
   4.243 -	if (m->subtype != CMSG_CONSOLE_DATA) {
   4.244 -		warnx("unknown console message subtype %d",
   4.245 -		      m->subtype);
   4.246 -		return;
   4.247 -	}
   4.248 -
   4.249 -	if (m->length > 60) {
   4.250 -		warnx("truncating message from domain %d (was length %d)",
   4.251 -		      d->domid, m->length);
   4.252 -		m->length = 60;
   4.253 -	}
   4.254 -	PRINTF(1, "DOM%d: %.*s\n", d->domid, m->length, m->msg);
   4.255 -	send_trivial_control_reply(m, d);
   4.256 -
   4.257 -	if (d->cc) {
   4.258 -		PRINTF(5, "Have a console connection.\n");
   4.259 -		if (d->cc->state == CC_STATE_CONNECTED) {
   4.260 -			PRINTF(5, "Console is connected, sending directly.\n");
   4.261 -			for (off = 0; off < m->length; off += r) {
   4.262 -				r = write(d->cc->fd, m->msg + off,
   4.263 -					  m->length - off);
   4.264 -				if (r <= 0) {
   4.265 -					d->cc->state = CC_STATE_ERROR;
   4.266 -					break;
   4.267 -				}
   4.268 -			}
   4.269 -		} else {
   4.270 -			PRINTF(5, "Console not connected, buffering.\n");
   4.271 -			if (d->cc->buf_allocated == 0) {
   4.272 -				d->cc->buf_allocated = 60;
   4.273 -				d->cc->buf = xmalloc(d->cc->buf_allocated);
   4.274 -				d->cc->buf_used = 0;
   4.275 -			} else if (d->cc->buf_allocated <
   4.276 -				   d->cc->buf_used + m->length) {
   4.277 -				d->cc->buf_allocated += 60;
   4.278 -				d->cc->buf = xrealloc(d->cc->buf,
   4.279 -						      d->cc->buf_allocated);
   4.280 -			}
   4.281 -			assert(d->cc->buf_allocated >=
   4.282 -			       d->cc->buf_used + m->length);
   4.283 -			memcpy(d->cc->buf + d->cc->buf_used,
   4.284 -			       m->msg,
   4.285 -			       m->length);
   4.286 -			d->cc->buf_used += m->length;
   4.287 -		}
   4.288 -	}
   4.289 -}
   4.290 -
   4.291 -static void
   4.292 -process_blkif_fe_message(control_msg_t *m, struct domain *d)
   4.293 -{
   4.294 -	switch (m->subtype) {
   4.295 -	default:
   4.296 -		warnx("unknown blkif front end message subtype %d",
   4.297 -		      m->subtype);
   4.298 -	}
   4.299 -}
   4.300 -
   4.301 -static void
   4.302 -send_control_message(int type, int subtype, int id,
   4.303 -		     int size, void *payload, struct domain *target)
   4.304 -{
   4.305 -	control_msg_t msg;
   4.306 -	CONTROL_RING_IDX c;
   4.307 -
   4.308 -	msg.type = type;
   4.309 -	msg.subtype = subtype;
   4.310 -	msg.id = id;
   4.311 -	msg.length = size;
   4.312 -	memcpy(msg.msg, payload, size);
   4.313 -
   4.314 -	c = target->ctrl_if->rx_req_prod % CONTROL_RING_SIZE;
   4.315 -	memcpy(&target->ctrl_if->rx_ring[c], &msg, sizeof(msg));
   4.316 -	report_work(&target->ctrl_if->rx_req_prod,
   4.317 -		    target->ctrl_if->rx_req_prod + 1,
   4.318 -		    target->domid,
   4.319 -		    0);
   4.320 -	assert(!target->plugged);
   4.321 -}
   4.322 -
   4.323 -/* Procedure for bringing a new netif front end up:
   4.324 -
   4.325 -   -- Front end sends us NETIF_FE_DRIVER_STATUS_CHANGED
   4.326 -   -- We send back end NETIF_BE_CREATE, wait for a reply
   4.327 -   -- Back end creates a new netif for us, replies
   4.328 -   -- We send front end a NETIF_FE_DRIVER_STATUS_CHANGED message saying
   4.329 -      how many interfaces we've created for it
   4.330 -   -- We send front end a NETIF_FE_INTERFACE_STATUS_CHANGED for each
   4.331 -      netif created
   4.332 -   -- Front end sends us a NETIF_FE_INTERFACE_CONNECT for each netif
   4.333 -*/
   4.334 -static void
   4.335 -handle_netif_fe_driver_status(control_msg_t *m,
   4.336 -			      netif_fe_driver_status_t *sh,
   4.337 -			      struct domain *d)
   4.338 -{
   4.339 -	netif_fe_interface_status_t if_s;
   4.340 -	control_msg_t be_msg;
   4.341 -	netif_be_create_t *be = (void *)be_msg.msg;
   4.342 -	int r;
   4.343 -
   4.344 -	switch (sh->status) {
   4.345 -	case NETIF_DRIVER_STATUS_UP:
   4.346 -		/* Tell the back end about the new interface coming
   4.347 -		 * up. */
   4.348 -		if (d->created_netif_backend) {
   4.349 -			send_control_reply(m, d);
   4.350 -			send_control_message(CMSG_NETIF_FE,
   4.351 -					     CMSG_NETIF_FE_DRIVER_STATUS,
   4.352 -					     1,
   4.353 -					     sizeof(*sh),
   4.354 -					     sh,
   4.355 -					     d);
   4.356 -			return;
   4.357 -		}
   4.358 -		be_msg.type = CMSG_NETIF_BE;
   4.359 -		be_msg.subtype = CMSG_NETIF_BE_CREATE;
   4.360 -		be_msg.id = d->domid;
   4.361 -		be_msg.length = sizeof(*be);
   4.362 -		be->domid = d->domid;
   4.363 -		be->netif_handle = 0;
   4.364 -		memcpy(be->mac, d->netif_mac, 6);
   4.365 -
   4.366 -		PRINTF(2,"Telling back end about new front end.\n");
   4.367 -		pthread_mutex_unlock(&d->mux);
   4.368 -		send_dom0_message_block(&be_msg);
   4.369 -		pthread_mutex_lock(&d->mux);
   4.370 -		PRINTF(3,"Done.\n");
   4.371 -
   4.372 -		if (be->status != NETIF_BE_STATUS_OKAY) {
   4.373 -			/* Uh oh... can't bring back end
   4.374 -			 * up. */
   4.375 -			send_control_reply(m, d);
   4.376 -			send_control_message(CMSG_NETIF_FE,
   4.377 -					     CMSG_NETIF_FE_DRIVER_STATUS,
   4.378 -					     1,
   4.379 -					     sizeof(*sh),
   4.380 -					     sh,
   4.381 -					     d);
   4.382 -			return;
   4.383 -		}
   4.384 -		d->created_netif_backend = 1;
   4.385 -
   4.386 -		r = our_system(VIFBRIDGE_SCRIPT " up domain=%s mac=%.02x:%.02x:%.02x:%.02x:%.02x:%.02x vif=vif%d.0 bridge=xen-br0",
   4.387 -			       d->name,
   4.388 -			       d->netif_mac[0],
   4.389 -			       d->netif_mac[1],
   4.390 -			       d->netif_mac[2],
   4.391 -			       d->netif_mac[3],
   4.392 -			       d->netif_mac[4],
   4.393 -			       d->netif_mac[5],
   4.394 -			       d->domid);
   4.395 -		if (r != 0)
   4.396 -			warn("error %d running " VIFBRIDGE_SCRIPT, r);
   4.397 -
   4.398 -		/* Tell domain how many interfaces it has to deal
   4.399 -		 * with. */
   4.400 -		send_control_reply(m, d);
   4.401 -		send_control_message(CMSG_NETIF_FE,
   4.402 -				     CMSG_NETIF_FE_DRIVER_STATUS,
   4.403 -				     1,
   4.404 -				     sizeof(*sh),
   4.405 -				     sh,
   4.406 -				     d);
   4.407 -
   4.408 -		PRINTF(2,"Telling front end about its interfaces.\n");
   4.409 -		if_s.handle = 0;
   4.410 -		if_s.status = NETIF_INTERFACE_STATUS_DISCONNECTED;
   4.411 -		send_control_message(CMSG_NETIF_FE,
   4.412 -				     CMSG_NETIF_FE_INTERFACE_STATUS,
   4.413 -				     1,
   4.414 -				     sizeof(if_s),
   4.415 -				     &if_s,
   4.416 -				     d);
   4.417 -		PRINTF(3,"Done.\n");
   4.418 -
   4.419 -		break;
   4.420 -	default:
   4.421 -		warnx("unknown netif status %ld", sh->status);
   4.422 -		break;
   4.423 -	}
   4.424 -}
   4.425 -
   4.426 -static void
   4.427 -handle_netif_fe_interface_connect(control_msg_t *m,
   4.428 -				  netif_fe_interface_connect_t *ic,
   4.429 -				  struct domain *d)
   4.430 -{
   4.431 -	control_msg_t be_msg;
   4.432 -	netif_be_connect_t *bmsg = (void *)be_msg.msg;
   4.433 -	netif_fe_interface_status_t fmsg = {0};
   4.434 -	int evtchn_ports[2];
   4.435 -	int r;
   4.436 -
   4.437 -	PRINTF(4, "front end sent us an interface connect message.\n");
   4.438 -	send_trivial_control_reply(m, d);
   4.439 -
   4.440 -	r = xc_evtchn_bind_interdomain(xc_handle,
   4.441 -				       dom0->domid,
   4.442 -				       d->domid,
   4.443 -				       &evtchn_ports[0],
   4.444 -				       &evtchn_ports[1]);
   4.445 -	if (r < 0)
   4.446 -		err(1, "allocating network event channel");
   4.447 -
   4.448 -	be_msg.type = CMSG_NETIF_BE;
   4.449 -	be_msg.subtype = CMSG_NETIF_BE_CONNECT;
   4.450 -	be_msg.id = 0;
   4.451 -	be_msg.length = sizeof(*bmsg);
   4.452 -	bmsg->domid = d->domid;
   4.453 -	bmsg->netif_handle = ic->handle;
   4.454 -	bmsg->tx_shmem_frame = ic->tx_shmem_frame;
   4.455 -	bmsg->rx_shmem_frame = ic->rx_shmem_frame;
   4.456 -	bmsg->evtchn = evtchn_ports[0];
   4.457 -
   4.458 -	pthread_mutex_unlock(&d->mux);
   4.459 -	send_dom0_message_block(&be_msg);
   4.460 -	pthread_mutex_lock(&d->mux);
   4.461 -
   4.462 -	if (bmsg->status != NETIF_BE_STATUS_OKAY) {
   4.463 -		PRINTF(2, "error connected backend netif: %ld\n",
   4.464 -		       bmsg->status);
   4.465 -		abort(); /* Need to handle this */
   4.466 -	} else {
   4.467 -		PRINTF(3, "connect backend netif\n");
   4.468 -
   4.469 -		/* Tell the domain that we've connected it up. */
   4.470 -		fmsg.handle = ic->handle;
   4.471 -		fmsg.status = NETIF_INTERFACE_STATUS_CONNECTED;
   4.472 -		fmsg.evtchn = evtchn_ports[1];
   4.473 -		memcpy(fmsg.mac, d->netif_mac, 6);
   4.474 -
   4.475 -		send_control_message(CMSG_NETIF_FE,
   4.476 -				     CMSG_NETIF_FE_INTERFACE_STATUS,
   4.477 -				     0,
   4.478 -				     sizeof(fmsg),
   4.479 -				     &fmsg,
   4.480 -				     d);
   4.481 -	}
   4.482 -}
   4.483 -
   4.484 -static void
   4.485 -process_netif_fe_message(control_msg_t *m, struct domain *d)
   4.486 -{
   4.487 -	switch (m->subtype) {
   4.488 -	case CMSG_NETIF_FE_DRIVER_STATUS:
   4.489 -	{
   4.490 -		netif_fe_driver_status_t *sh =
   4.491 -			(netif_fe_driver_status_t *)m->msg;
   4.492 -		handle_netif_fe_driver_status(m, sh, d);
   4.493 -		break;
   4.494 -	}
   4.495 -	case CMSG_NETIF_FE_INTERFACE_CONNECT:
   4.496 -	{
   4.497 -		netif_fe_interface_connect_t *ic =
   4.498 -			(netif_fe_interface_connect_t *)m->msg;
   4.499 -		handle_netif_fe_interface_connect(m, ic, d);
   4.500 -		break;
   4.501 -	}
   4.502 -	default:
   4.503 -		warnx("unknown netif front end message subtype %d",
   4.504 -		      m->subtype);
   4.505 -	}
   4.506 -}
   4.507 -
   4.508 -static void
   4.509 -process_control_message(control_msg_t *msg, struct domain *d)
   4.510 -{
   4.511 -	control_msg_t m;
   4.512 -
   4.513 -	/* Don't want a malicous domain messing us about, so copy the
   4.514 -	   control mesasge into a local buffer. */
   4.515 -	memcpy(&m, msg, sizeof(m));
   4.516 -	switch (m.type) {
   4.517 -	case CMSG_CONSOLE:
   4.518 -		process_console_control_message(&m, d);
   4.519 -		break;
   4.520 -	case CMSG_BLKIF_FE:
   4.521 -		process_blkif_fe_message(&m, d);
   4.522 -		break;
   4.523 -	case CMSG_NETIF_FE:
   4.524 -		process_netif_fe_message(&m, d);
   4.525 -		break;
   4.526 -	default:
   4.527 -		warnx("unknown control message type %d", m.type);
   4.528 -	}
   4.529 -}
   4.530 -
   4.531 -static void
   4.532 -domain_did_control_event(struct domain *d)
   4.533 -{
   4.534 -	CONTROL_RING_IDX c;
   4.535 -
   4.536 -	/* Pick up and process control ring messages. */
   4.537 -	while (d->tx_req_cons != d->ctrl_if->tx_req_prod) {
   4.538 -		c = d->tx_req_cons % CONTROL_RING_SIZE;
   4.539 -		process_control_message(&d->ctrl_if->tx_ring[c], d);
   4.540 -		d->tx_req_cons++;
   4.541 -		assert(d->tx_req_cons <= d->ctrl_if->tx_req_prod);
   4.542 -		PRINTF(5, "req_cons %ld, req_prod %ld.\n",
   4.543 -		       d->tx_req_cons, d->ctrl_if->tx_req_prod);
   4.544 -	}
   4.545 -
   4.546 -	/* Take any replies off, and discard them. */
   4.547 -	if (d->rx_resp_cons != d->ctrl_if->rx_resp_prod)
   4.548 -		PRINTF(1, "discard %ld events\n",
   4.549 -		       d->ctrl_if->rx_resp_prod -
   4.550 -		       d->rx_resp_cons);
   4.551 -	d->rx_resp_cons = d->ctrl_if->rx_resp_prod;
   4.552 -}
   4.553 -
   4.554 -/* This is the main function for domain control threads */
   4.555 -void *
   4.556 -domain_thread_func(void *D)
   4.557 -{
   4.558 -	struct domain *d = D;
   4.559 -	int r;
   4.560 -	CONTROL_RING_IDX old_resp_prod, old_req_prod;
   4.561 -
   4.562 -	pthread_mutex_lock(&d->mux);
   4.563 -	for (;;) {
   4.564 -		pthread_cond_wait(&d->cond, &d->mux);
   4.565 -
   4.566 -		old_resp_prod = d->ctrl_if->tx_resp_prod;
   4.567 -		old_req_prod = d->ctrl_if->rx_req_prod;
   4.568 -
   4.569 -		domain_did_control_event(d);
   4.570 -		if (d->cc && d->cc->in_buf_used != 0 && d->plugged == 0) {
   4.571 -			r = d->cc->in_buf_used;
   4.572 -			if (r > 60)
   4.573 -				r = 60;
   4.574 -			PRINTF(1, "Sending to domain: %.*s\n",
   4.575 -			       r, d->cc->in_buf);
   4.576 -			send_control_message(CMSG_CONSOLE,
   4.577 -					     CMSG_CONSOLE_DATA,
   4.578 -					     0,
   4.579 -					     r,
   4.580 -					     d->cc->in_buf,
   4.581 -					     d);
   4.582 -			memmove(d->cc->in_buf, d->cc->in_buf + r,
   4.583 -				d->cc->in_buf_used - r);
   4.584 -			d->cc->in_buf_used -= r;
   4.585 -		}
   4.586 -
   4.587 -		if (d->ctrl_if->tx_resp_prod != old_resp_prod ||
   4.588 -		    d->ctrl_if->rx_req_prod != old_req_prod)
   4.589 -			xc_evtchn_send(xc_handle, d->control_evtchn);
   4.590 -	}
   4.591 -}
   4.592 -
   4.593 -/* This is the only thing you can do with a domain structure if you're
   4.594 -   not in the thread which controls that domain.  Domain 0 is
   4.595 -   special. */
   4.596 -void
   4.597 -signal_domain(struct domain *d)
   4.598 -{
   4.599 -	CONTROL_RING_IDX c;
   4.600 -	int id;
   4.601 -	struct event_receiver *evt;
   4.602 -
   4.603 -	pthread_mutex_lock(&d->mux);
   4.604 -	if (d == dom0) {
   4.605 -		/* Take events off of dom0's control ring, and send
   4.606 -		   them to the event receivers. */
   4.607 -		while (d->tx_req_cons != d->ctrl_if->tx_req_prod) {
   4.608 -			c = d->tx_req_cons % CONTROL_RING_SIZE;
   4.609 -			id = d->ctrl_if->tx_ring[c].id;
   4.610 -			evt = find_event_receiver(id);
   4.611 -			if (evt != NULL) {
   4.612 -				PRINTF(1, "delivering event id %d\n", evt->id);
   4.613 -				pthread_cond_broadcast(&evt->cond);
   4.614 -				pthread_mutex_unlock(&d->mux);
   4.615 -				sched_yield();
   4.616 -				pthread_mutex_lock(&d->mux);
   4.617 -			} else {
   4.618 -				warnx("unexpected message id %d discarded",
   4.619 -				      id);
   4.620 -				d->tx_req_cons++;
   4.621 -			}
   4.622 -		}
   4.623 -		while (d->rx_resp_cons != d->ctrl_if->rx_resp_prod) {
   4.624 -			c = d->rx_resp_cons % CONTROL_RING_SIZE;
   4.625 -			id = d->ctrl_if->rx_ring[c].id;
   4.626 -			evt = find_event_receiver(id);
   4.627 -			if (evt != NULL) {
   4.628 -				PRINTF(1, "delivering event rep id %d\n", evt->id);
   4.629 -				pthread_cond_broadcast(&evt->cond);
   4.630 -				pthread_mutex_unlock(&d->mux);
   4.631 -				sched_yield();
   4.632 -				pthread_mutex_lock(&d->mux);
   4.633 -			} else {
   4.634 -				warnx("unexpected message reply id %d discarded",
   4.635 -				      id);
   4.636 -				d->rx_resp_cons++;
   4.637 -			}
   4.638 -		}
   4.639 -	} else {
   4.640 -		if (d->plugged) {
   4.641 -			d->event_pending = 1;
   4.642 -		} else {
   4.643 -			pthread_cond_broadcast(&d->cond);
   4.644 -		}
   4.645 -	}
   4.646 -	pthread_mutex_unlock(&d->mux);
   4.647 -}
   4.648 -
   4.649 -static void
   4.650 -handle_evtchn_event(void)
   4.651 -{
   4.652 -	short port;
   4.653 -	struct domain *d;
   4.654 -
   4.655 -	read(evtchn_fd, &port, sizeof(short));
   4.656 -	write(evtchn_fd, &port, sizeof(short));
   4.657 -	foreach_domain (d) {
   4.658 -		if (d->control_evtchn == port) {
   4.659 -			signal_domain(d);
   4.660 -			return;
   4.661 -		}
   4.662 -	}
   4.663 -	warnx("got an event on an unknown port %d", port);
   4.664 -}
   4.665 -
   4.666 -void *
   4.667 -map_domain_mem(struct domain *d, unsigned long mfn)
   4.668 -{
   4.669 -	return xc_map_foreign_range(xc_handle, d->domid,
   4.670 -				    PAGE_SIZE, PROT_READ | PROT_WRITE,
   4.671 -				    mfn);
   4.672 -}
   4.673 -
   4.674 -static void
   4.675 -handle_console_event(struct console_connection *cc)
   4.676 -{
   4.677 -	int r;
   4.678 -	int fd;
   4.679 -
   4.680 -	switch (cc->state) {
   4.681 -	case CC_STATE_ERROR:
   4.682 -		/* Errors shouldn't get here. */
   4.683 -		abort();
   4.684 -	case CC_STATE_PENDING:
   4.685 -		fd = accept(cc->fd, NULL, NULL);
   4.686 -		if (fd >= 0) {
   4.687 -			PRINTF(3, "Accepted console connection for domain %d",
   4.688 -			       cc->dom->domid);
   4.689 -			close(cc->fd);
   4.690 -			cc->fd = fd;
   4.691 -			cc->state = CC_STATE_CONNECTED;
   4.692 -			while (cc->buf_used != 0) {
   4.693 -				r = write(cc->fd,
   4.694 -					  cc->buf,
   4.695 -					  cc->buf_used);
   4.696 -				if (r <= 0) {
   4.697 -					cc->state = CC_STATE_ERROR;
   4.698 -					break;
   4.699 -				}
   4.700 -				memmove(cc->buf,
   4.701 -					cc->buf + r,
   4.702 -					cc->buf_used - r);
   4.703 -				cc->buf_used -= r;
   4.704 -			}
   4.705 -			free(cc->buf);
   4.706 -			cc->buf = NULL;
   4.707 -			cc->buf_allocated = 0;
   4.708 -		} else {
   4.709 -			PRINTF(1, "error %s accepting console", strerror(errno));
   4.710 -		}
   4.711 -		pthread_mutex_unlock(&cc->dom->mux);
   4.712 -		break;
   4.713 -	case CC_STATE_CONNECTED:
   4.714 -		if (cc->in_buf_allocated == 0) {
   4.715 -			assert(cc->in_buf_used == 0);
   4.716 -			cc->in_buf_allocated = 128;
   4.717 -			cc->in_buf = xmalloc(cc->in_buf_allocated);
   4.718 -		}
   4.719 -		if (cc->in_buf_used == cc->in_buf_allocated) {
   4.720 -			cc->in_buf_allocated *= 2;
   4.721 -			cc->in_buf = xrealloc(cc->in_buf, cc->in_buf_allocated);
   4.722 -		}
   4.723 -		r = read(cc->fd, cc->in_buf + cc->in_buf_used,
   4.724 -			 cc->in_buf_allocated - cc->in_buf_used);
   4.725 -		if (r <= 0) {
   4.726 -			cc->state = CC_STATE_ERROR;
   4.727 -		} else {
   4.728 -			cc->in_buf_used += r;
   4.729 -		}
   4.730 -		pthread_mutex_unlock(&cc->dom->mux);
   4.731 -		signal_domain(cc->dom);
   4.732 -		break;
   4.733 -	}
   4.734 -}
   4.735 -
   4.736 -static void
   4.737 -handle_connection_event(struct open_connection *oc)
   4.738 -{
   4.739 -	int r;
   4.740 -
   4.741 -	/* We know that some amount of data is ready and waiting for
   4.742 -	   us.  Slurp it in. */
   4.743 -	if (oc->buf_used == oc->buf_allocated) {
   4.744 -		oc->buf_allocated *= 2;
   4.745 -		oc->buf = xrealloc(oc->buf, oc->buf_allocated);
   4.746 -	}
   4.747 -	r = read(oc->fd, oc->buf + oc->buf_used,
   4.748 -		 oc->buf_allocated - oc->buf_used);
   4.749 -	if (r < 0) {
   4.750 -		warn("reading command from remote");
   4.751 -		oc->state = OC_STATE_ERROR;
   4.752 -	} else if (r == 0) {
   4.753 -		warnx("reading command from remote");
   4.754 -		oc->state = OC_STATE_ERROR;
   4.755 -	} else {
   4.756 -		oc->buf_used += r;
   4.757 -		if (strchr(oc->buf, '\n'))
   4.758 -			oc->state = OC_STATE_COMMAND_PENDING;
   4.759 -	}
   4.760 -}
   4.761 -
   4.762 -static void
   4.763 -get_and_process_event(void)
   4.764 -{
   4.765 -	fd_set read_fds, except_fds;
   4.766 -	struct open_connection *oc;
   4.767 -	struct console_connection *cc;
   4.768 -	int max_fd = listen_fd;
   4.769 -	int r;
   4.770 -	struct list_head *li, *temp_li;
   4.771 -
   4.772 -	FD_ZERO(&read_fds);
   4.773 -	FD_ZERO(&except_fds);
   4.774 -	FD_SET(listen_fd, &read_fds);
   4.775 -	FD_SET(evtchn_fd, &read_fds);
   4.776 -	if (evtchn_fd > max_fd)
   4.777 -		max_fd = evtchn_fd;
   4.778 -	foreach_open_connection(oc) {
   4.779 -		FD_SET(oc->fd, &read_fds);
   4.780 -		FD_SET(oc->fd, &except_fds);
   4.781 -		if (oc->fd > max_fd)
   4.782 -			max_fd = oc->fd;
   4.783 -	}
   4.784 -	foreach_console_connection(cc) {
   4.785 -		FD_SET(cc->fd, &read_fds);
   4.786 -		FD_SET(cc->fd, &except_fds);
   4.787 -		if (cc->fd > max_fd)
   4.788 -			max_fd = cc->fd;
   4.789 -	}
   4.790 -
   4.791 -	r = select(max_fd + 1, &read_fds, NULL, &except_fds, NULL);
   4.792 -	if (r < 0)
   4.793 -		err(1, "select");
   4.794 -	if (FD_ISSET(listen_fd, &read_fds)) {
   4.795 -		accept_new_connection();
   4.796 -	} else if (FD_ISSET(evtchn_fd, &read_fds))
   4.797 -		handle_evtchn_event();
   4.798 -
   4.799 -
   4.800 -	foreach_open_connection(oc) {
   4.801 -		if (FD_ISSET(oc->fd, &read_fds))
   4.802 -			handle_connection_event(oc);
   4.803 -		if (FD_ISSET(oc->fd, &except_fds))
   4.804 -			oc->state = OC_STATE_ERROR;
   4.805 -	}
   4.806 -	list_foreach_safe(&head_console, li, temp_li) {
   4.807 -		cc = list_item(li, struct console_connection, list);
   4.808 -		if (FD_ISSET(cc->fd, &read_fds))
   4.809 -			handle_console_event(cc);
   4.810 -		if (FD_ISSET(cc->fd, &except_fds) ||
   4.811 -		    cc->state == CC_STATE_ERROR) {
   4.812 -			PRINTF(1, "Cleaning up console connection");
   4.813 -			cc->dom->cc = NULL;
   4.814 -			list_remove(&cc->list);
   4.815 -			close(cc->fd);
   4.816 -			if (cc->buf_allocated != 0)
   4.817 -				free(cc->buf);
   4.818 -			if (cc->in_buf_allocated != 0)
   4.819 -				free(cc->in_buf);
   4.820 -			free(cc);
   4.821 -		}
   4.822 -	}
   4.823 -
   4.824 -	/* Run pending stuff on the open connections. */
   4.825 -	list_foreach_safe(&head_connection, li, temp_li) {
   4.826 -		oc = list_item(li, struct open_connection, connection_list);
   4.827 -		switch (oc->state) {
   4.828 -		case OC_STATE_ERROR:
   4.829 -			list_remove(&oc->connection_list);
   4.830 -			closedown_connection(oc);
   4.831 -			break;
   4.832 -		case OC_STATE_COMMAND_PENDING:
   4.833 -			process_command(oc);
   4.834 -			break;
   4.835 -		case OC_STATE_CONNECTED:
   4.836 -			/* Don't need to do anything */
   4.837 -			break;
   4.838 -		}
   4.839 -	}
   4.840 -}
   4.841 -
   4.842 -static int
   4.843 -start_listening(void)
   4.844 -{
   4.845 -	int sock;
   4.846 -	struct sockaddr_in inaddr;
   4.847 -
   4.848 -	sock = socket(PF_INET, SOCK_STREAM, 0);
   4.849 -	if (sock < 0)
   4.850 -		err(1, "creating socket");
   4.851 -	memset(&inaddr, 0, sizeof(inaddr));
   4.852 -	inaddr.sin_family = AF_INET;
   4.853 -	inaddr.sin_port = htons(MINIXEND_PORT);
   4.854 -
   4.855 -	if (bind(sock, (struct sockaddr *)&inaddr, sizeof(inaddr)) < 0)
   4.856 -		err(1, "binding to port %d", MINIXEND_PORT);
   4.857 -	if (listen(sock, 5) < 0)
   4.858 -		err(1, "listening for connections");
   4.859 -
   4.860 -	return sock;
   4.861 -}
   4.862 -
   4.863 -static struct domain *
   4.864 -find_dom0(void)
   4.865 -{
   4.866 -	int r;
   4.867 -	xc_dominfo_t info;
   4.868 -	struct domain *work;
   4.869 -
   4.870 -	r = xc_domain_getinfo(xc_handle, 0, 1, &info);
   4.871 -	if (r < 0)
   4.872 -		err(1, "getting domain 0 information");
   4.873 -	work = xmalloc(sizeof(*work));
   4.874 -	work->control_evtchn = 2;
   4.875 -	if (ioctl(evtchn_fd, EVTCHN_BIND, 2) < 0)
   4.876 -		err(1, "binding to domain 0 control event channel");
   4.877 -
   4.878 -	work->domid = 0;
   4.879 -	work->name = strdup("dom0");
   4.880 -	work->mem_kb = info.max_memkb;
   4.881 -	work->state = DOM_STATE_RUNNING;
   4.882 -	work->shared_info_mfn = info.shared_info_frame;
   4.883 -
   4.884 -	work->shared_info = map_domain_mem(work, info.shared_info_frame);
   4.885 -	work->ctrl_if = (control_if_t *)((unsigned)work->shared_info + 2048);
   4.886 -	work->tx_req_cons = work->ctrl_if->tx_req_prod;
   4.887 -	work->rx_resp_cons = work->ctrl_if->rx_resp_prod;
   4.888 -
   4.889 -	pthread_mutex_init(&work->mux, NULL);
   4.890 -	pthread_cond_init(&work->cond, NULL);
   4.891 -
   4.892 -	list_insert_after(&work->domain_list, &head_domain);
   4.893 -
   4.894 -	return work;
   4.895 -}
   4.896 -
   4.897 -int
   4.898 -main(int argc, char *argv[])
   4.899 -{
   4.900 -	int r;
   4.901 -
   4.902 -	r = our_system(NETWORK_SCRIPT " start antispoof=no");
   4.903 -	if (r < 0)
   4.904 -		err(1, "running " NETWORK_SCRIPT);
   4.905 -	if (!WIFEXITED(r)) {
   4.906 -		if (WIFSIGNALED(r)) {
   4.907 -			errx(1, NETWORK_SCRIPT " killed by signal %d",
   4.908 -			     WTERMSIG(r));
   4.909 -		}
   4.910 -		errx(1, NETWORK_SCRIPT " terminated abnormally");
   4.911 -	}
   4.912 -	if (WEXITSTATUS(r) != 0)
   4.913 -		errx(1, NETWORK_SCRIPT " returned error status %d",
   4.914 -		     WEXITSTATUS(r));
   4.915 -
   4.916 -	xc_handle = xc_interface_open();
   4.917 -
   4.918 -	listen_fd = start_listening();
   4.919 -
   4.920 -	evtchn_fd = open("/dev/xen/evtchn", O_RDWR);
   4.921 -	if (evtchn_fd < 0)
   4.922 -		err(1, "openning /dev/xen/evtchn");
   4.923 -
   4.924 -	dom0 = find_dom0();
   4.925 -
   4.926 -	while (1) {
   4.927 -		get_and_process_event();
   4.928 -
   4.929 -		PRINTF(5, "Dom0 ring state:\n");
   4.930 -		PRINTF(5, "RX: req_prod %ld, resp_prod %ld, resp_cons %ld\n",
   4.931 -		       dom0->ctrl_if->rx_req_prod,
   4.932 -		       dom0->ctrl_if->rx_resp_prod,
   4.933 -		       dom0->rx_resp_cons);
   4.934 -		PRINTF(5, "TX: req_prod %ld, resp_prod %ld, req_cons %ld\n",
   4.935 -		       dom0->ctrl_if->tx_req_prod,
   4.936 -		       dom0->ctrl_if->tx_resp_prod,
   4.937 -		       dom0->tx_req_cons);
   4.938 -	}
   4.939 -
   4.940 -	return 0;
   4.941 -}
   4.942 -
     5.1 --- a/tools/x2d2/minixend.h	Wed Mar 09 16:43:57 2005 +0000
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,154 +0,0 @@
     5.4 -#ifndef MINIXEND_H__
     5.5 -#define MINIXEND_H__
     5.6 -
     5.7 -#include <sys/types.h>
     5.8 -#include <xc.h>
     5.9 -
    5.10 -struct list_head {
    5.11 -	struct list_head *next, **pprev;
    5.12 -};
    5.13 -
    5.14 -struct open_connection {
    5.15 -	struct list_head connection_list;
    5.16 -	int fd;
    5.17 -	enum {
    5.18 -		OC_STATE_CONNECTED,
    5.19 -		OC_STATE_ERROR,
    5.20 -		OC_STATE_COMMAND_PENDING
    5.21 -	} state;
    5.22 -
    5.23 -	/* Buffer of stuff coming from the remote until we get a whole
    5.24 -	   command */
    5.25 -	int buf_used;
    5.26 -	int buf_allocated;
    5.27 -	char *buf;
    5.28 -};
    5.29 -
    5.30 -struct console_connection;
    5.31 -
    5.32 -/* Only ever accessed from the domain's controlling thread, unless
    5.33 -   it's dom0, in which case we perform a moderately complex dance to
    5.34 -   avoid needing any sort of locking at all. */
    5.35 -struct domain {
    5.36 -	struct list_head domain_list;
    5.37 -	int control_evtchn; /* the local port for the doain control
    5.38 -			       interface event channel. */
    5.39 -	int domid;
    5.40 -	char *name;
    5.41 -	int mem_kb;
    5.42 -	enum {
    5.43 -		DOM_STATE_CREATED, /* created but not built */
    5.44 -		DOM_STATE_PAUSED,  /* built but not started or paused */
    5.45 -		DOM_STATE_RUNNING, /* running normally */
    5.46 -		DOM_STATE_DEAD     /* dead; either destroyed, crashed,
    5.47 -				      or exitted. */
    5.48 -	} state;
    5.49 -
    5.50 -	unsigned long shared_info_mfn;
    5.51 -	shared_info_t *shared_info;
    5.52 -	control_if_t *ctrl_if;
    5.53 -	CONTROL_RING_IDX tx_req_cons;
    5.54 -	CONTROL_RING_IDX rx_resp_cons;
    5.55 -
    5.56 -	unsigned created_netif_backend:1;
    5.57 -	unsigned plugged:1;
    5.58 -	unsigned event_pending:1; /* True if an event arrived while
    5.59 -				     the domain was plugged. */
    5.60 -
    5.61 -	struct console_connection *cc;
    5.62 -
    5.63 -	char netif_mac[6];
    5.64 -
    5.65 -	/* Used for two purposes: waking up domain threads when
    5.66 -	   necessary, and synchronising access to dom0, which doesn't
    5.67 -	   have a domain thread. */
    5.68 -	pthread_mutex_t mux;
    5.69 -	pthread_cond_t cond;
    5.70 -
    5.71 -	pthread_t thread;
    5.72 -};
    5.73 -
    5.74 -struct console_connection {
    5.75 -	struct list_head list;
    5.76 -	int fd;
    5.77 -	struct domain *dom;
    5.78 -
    5.79 -	enum {
    5.80 -		CC_STATE_PENDING,
    5.81 -		CC_STATE_CONNECTED,
    5.82 -		CC_STATE_ERROR
    5.83 -	} state;
    5.84 -
    5.85 -	unsigned buf_allocated;
    5.86 -	unsigned buf_used;
    5.87 -	char *buf;
    5.88 -
    5.89 -	unsigned in_buf_allocated;
    5.90 -	unsigned in_buf_used;
    5.91 -	char *in_buf;
    5.92 -};
    5.93 -
    5.94 -
    5.95 -void *domain_thread_func(void *d);
    5.96 -void process_command(struct open_connection *oc);
    5.97 -
    5.98 -void *xmalloc(size_t s);
    5.99 -void *xrealloc(void *x, size_t s);
   5.100 -char *xstrdup(const char *s);
   5.101 -
   5.102 -int allocate_event_channel(struct domain *d, int event_ports[2]);
   5.103 -void *map_domain_mem(struct domain *d, unsigned long mfn);
   5.104 -void signal_domain(struct domain *d);
   5.105 -int our_system(const char *fmt, ...);
   5.106 -
   5.107 -extern unsigned xc_handle;
   5.108 -#define EVTCHN_BIND _IO('E', 2)
   5.109 -extern int evtchn_fd;
   5.110 -
   5.111 -#define list_item(head, type, field)                                        \
   5.112 -((type *)((unsigned)(head) - offsetof(type, field)))
   5.113 -
   5.114 -#define foreach_item(iter, head, type, field)                               \
   5.115 -for ((iter) = list_item((head)->next, type, field);                         \
   5.116 -     (iter) != list_item((head), type, field);                              \
   5.117 -     (iter) = list_item((iter)->field.next, type, field))
   5.118 -
   5.119 -#define list_insert_after(what, head)                                       \
   5.120 -do {                                                                        \
   5.121 -	(what)->next = (head)->next;                                        \
   5.122 -	(what)->pprev = &(head)->next;                                      \
   5.123 -	(head)->next->pprev = &(what)->next;                                \
   5.124 -	(head)->next = what;                                                \
   5.125 -} while (0)
   5.126 -
   5.127 -#define list_remove(head)                                                   \
   5.128 -(head)->next->pprev = (head)->pprev;                                        \
   5.129 -*(head)->pprev = (head)->next;
   5.130 -
   5.131 -#define list_foreach_safe(head, li, temp)                                   \
   5.132 -for ((li) = (head)->next, (temp) = (li)->next;                              \
   5.133 -     (li) != (head);                                                        \
   5.134 -     (li) = (temp), (temp) = (li)->next)
   5.135 -
   5.136 -#define LIST_HEAD(x) { (x), &(x)->next }
   5.137 -
   5.138 -
   5.139 -extern struct list_head head_domain;
   5.140 -extern struct list_head head_console;
   5.141 -
   5.142 -#define foreach_domain(d)                                                   \
   5.143 -foreach_item(d, &head_domain, struct domain, domain_list)
   5.144 -#define foreach_console_connection(cc)                                      \
   5.145 -foreach_item(cc, &head_console, struct console_connection, list)
   5.146 -
   5.147 -
   5.148 -#define CURRENT_LOG_LEVEL 0
   5.149 -
   5.150 -#define PRINTF(level, ...)                                         \
   5.151 -do {                                                               \
   5.152 -	if ((level) >= CURRENT_LOG_LEVEL)                          \
   5.153 -		printf(__VA_ARGS__);                               \
   5.154 -} while (0)
   5.155 -
   5.156 -
   5.157 -#endif /* MINIXEND_H__ */
     6.1 --- a/tools/x2d2/util.c	Wed Mar 09 16:43:57 2005 +0000
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,132 +0,0 @@
     6.4 -#define _GNU_SOURCE
     6.5 -
     6.6 -#include <sys/types.h>
     6.7 -#include <sys/wait.h>
     6.8 -#include <assert.h>
     6.9 -#include <err.h>
    6.10 -#include <errno.h>
    6.11 -#include <fcntl.h>
    6.12 -#include <stdarg.h>
    6.13 -#include <stdlib.h>
    6.14 -#include <stdio.h>
    6.15 -#include <string.h>
    6.16 -#include <unistd.h>
    6.17 -
    6.18 -void *
    6.19 -xmalloc(size_t s)
    6.20 -{
    6.21 -	void *x;
    6.22 -
    6.23 -	x = malloc(s);
    6.24 -	if (x == NULL)
    6.25 -		err(1, "allocating memory");
    6.26 -	memset(x, 0, s);
    6.27 -	return x;
    6.28 -}
    6.29 -
    6.30 -void *
    6.31 -xrealloc(void *x, size_t s)
    6.32 -{
    6.33 -	void *y;
    6.34 -	y = realloc(x, s);
    6.35 -	if (y == NULL)
    6.36 -		err(1, "allocating more memory");
    6.37 -	return y;
    6.38 -}
    6.39 -
    6.40 -char *
    6.41 -xstrdup(const char *s)
    6.42 -{
    6.43 -	char *x = strdup(s);
    6.44 -	if (x == NULL)
    6.45 -		err(1, "duplicating %s", s);
    6.46 -	return x;
    6.47 -}
    6.48 -
    6.49 -/* Slightly less stupid implementation of system().  We return
    6.50 -   negative iff there is an error executing the shell; otherwise, we
    6.51 -   return the wait status as reported by waitpid(). Also, we support
    6.52 -   printf-style escapes.  We don't handle setting the SIGCHLD handler
    6.53 -   to SIGIGN, though: in that case, we have a race. */
    6.54 -int
    6.55 -our_system(const char *fmt, ...)
    6.56 -{
    6.57 -	char *cmd = NULL;
    6.58 -	int r;
    6.59 -	va_list ap;
    6.60 -	pid_t child = -1;
    6.61 -	int pip[2] = {-1, -1};
    6.62 -	int e;
    6.63 -	fd_set fds;
    6.64 -	struct timeval to;
    6.65 -	int res;
    6.66 -	pid_t c;
    6.67 -	unsigned status;
    6.68 -
    6.69 -	va_start(ap, fmt);
    6.70 -	r = vasprintf(&cmd, fmt, ap);
    6.71 -	va_end(ap);
    6.72 -	if (r < 0)
    6.73 -		return r;
    6.74 -	r = pipe(pip);
    6.75 -	if (r < 0) {
    6.76 -		res = r;
    6.77 -		goto out;
    6.78 -	}
    6.79 -	child = fork();
    6.80 -	if (child < 0) {
    6.81 -		res = child;
    6.82 -		goto out;
    6.83 -	}
    6.84 -	if (child == 0) {
    6.85 -		close(pip[0]);
    6.86 -		fcntl(pip[1], F_SETFD, 1);
    6.87 -		r = execl("/bin/sh", "/bin/sh", "-c", cmd, NULL);
    6.88 -		/* Uh oh, exec failed */
    6.89 -		write(pip[1], &r, sizeof(r));
    6.90 -		_exit(1);
    6.91 -	}
    6.92 -
    6.93 -	close(pip[1]);
    6.94 -	pip[1] = -1;
    6.95 -
    6.96 -	c = waitpid(child, &status, 0);
    6.97 -	if (c < 0) {
    6.98 -		res = c;
    6.99 -		goto out;
   6.100 -	}
   6.101 -	assert(c == child);
   6.102 -	child = -1;
   6.103 -
   6.104 -	/* Check execl result */
   6.105 -	FD_ZERO(&fds);
   6.106 -	FD_SET(pip[0], &fds);
   6.107 -	memset(&to, 0, sizeof(to));
   6.108 -	r = select(pip[0]+1, &fds, NULL, NULL, &to);
   6.109 -	if (r == 0) {
   6.110 -		res = status;
   6.111 -	} else {
   6.112 -		assert(FD_ISSET(pip[0], &fds));
   6.113 -		r = read(pip[0], &res, sizeof(res));
   6.114 -		if (r != sizeof(res))
   6.115 -			res = status;
   6.116 -	}
   6.117 -	close(pip[0]);
   6.118 -	pip[0] = -1;
   6.119 -
   6.120 - out:
   6.121 -	e = errno;
   6.122 -	if (child >= 0) {
   6.123 -		/* Not obvious what the correct thing to do here is. */
   6.124 -		/* Don't want to kill the child; that will create a
   6.125 -		   zombie. */
   6.126 -//		kill(child, 9);
   6.127 -	}
   6.128 -	if (pip[0] >= 0)
   6.129 -		close(pip[0]);
   6.130 -	if (pip[1] >= 0)
   6.131 -		close(pip[1]);
   6.132 -	free(cmd);
   6.133 -	errno = e;
   6.134 -	return res;
   6.135 -}