ia64/xen-unstable

changeset 1662:8f8449890369

bitkeeper revision 1.1041.6.1 (40e5221awCqaZfcsO_ny2z3p_6BiEg)

nsplitd.c, Makefile:
mvdir
Makefile:
Rename: BitKeeper/deleted/.del-Makefile~9f548ce6ff509eac -> tools/nsplitd/Makefile
nsplitd.c:
Rename: BitKeeper/deleted/.del-nsplitd.c~8b67653f8e377176 -> tools/nsplitd/nsplitd.c
author kaf24@scramble.cl.cam.ac.uk
date Fri Jul 02 08:51:38 2004 +0000 (2004-07-02)
parents d9a96380ff94
children 23e371e87d2f
files .rootkeys tools/misc/nsplitd/Makefile tools/misc/nsplitd/nsplitd.c
line diff
     1.1 --- a/.rootkeys	Thu Jul 01 23:32:40 2004 +0000
     1.2 +++ b/.rootkeys	Fri Jul 02 08:51:38 2004 +0000
     1.3 @@ -201,6 +201,8 @@ 3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/mis
     1.4  3f6dc140C8tAeBfroAF24VrmCS4v_w tools/misc/miniterm/README
     1.5  3f6dc142IHaf6XIcAYGmhV9nNSIHFQ tools/misc/miniterm/miniterm.c
     1.6  40c9c469kT0H9COWzA4XzPBjWK0WsA tools/misc/netfix
     1.7 +4022a73cEKvrYe_DVZW2JlAxobg9wg tools/misc/nsplitd/Makefile
     1.8 +4022a73cKms4Oq030x2JBzUB426lAQ tools/misc/nsplitd/nsplitd.c
     1.9  3f870808_8aFBAcZbWiWGdgrGQyIEw tools/misc/p4perf.h
    1.10  3f5ef5a2ir1kVAthS14Dc5QIRCEFWg tools/misc/xen-clone
    1.11  3f5ef5a2dTZP0nnsFoeq2jRf3mWDDg tools/misc/xen-clone.README
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/misc/nsplitd/Makefile	Fri Jul 02 08:51:38 2004 +0000
     2.3 @@ -0,0 +1,22 @@
     2.4 +
     2.5 +CC     = gcc
     2.6 +CFLAGS = -Wall -O3
     2.7 +CFILES = $(wildcard *.c)
     2.8 +
     2.9 +HDRS     = $(wildcard *.h)
    2.10 +OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))
    2.11 +
    2.12 +TARGET   = nsplitd
    2.13 +
    2.14 +all: $(TARGET)
    2.15 +
    2.16 +install: all
    2.17 +
    2.18 +clean:
    2.19 +	$(RM) *.o $(TARGET) *~
    2.20 +
    2.21 +$(TARGET): $(OBJS)
    2.22 +	$(CC) $(CFLAGS) -o $@ $^
    2.23 +
    2.24 +%.o: %.c $(HDRS) Makefile
    2.25 +	$(CC) $(CFLAGS) -c -o $@ $<
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/misc/nsplitd/nsplitd.c	Fri Jul 02 08:51:38 2004 +0000
     3.3 @@ -0,0 +1,686 @@
     3.4 +/*
     3.5 + *	nsplitd.c
     3.6 + *	---------
     3.7 + *
     3.8 + * $Id: nsplitd.c,v 2.6 1998/09/17 14:28:37 sde1000 Exp $
     3.9 + *
    3.10 + * Copyright (c) 1995, University of Cambridge Computer Laboratory,
    3.11 + * Copyright (c) 1995, Richard Black, All Rights Reserved.
    3.12 + *
    3.13 + *
    3.14 + * A complete re-implementation of DME's nsplitd for use from inetd
    3.15 + *
    3.16 + */
    3.17 +
    3.18 +/* The basic stream comes in (via inetd) and we then conenct to
    3.19 + * somewhere else providing a loop-through service, except we offer
    3.20 + * two other ports for connection - one of which gets a second channel
    3.21 + * using the top bit to distinguish, and the other is a master control
    3.22 + * port (normally used for gdb) which gets complete exclusive access
    3.23 + * for its duration.
    3.24 + *
    3.25 + * Originally designed for multiplexing a xwcons/telnet with a gdb
    3.26 + * post-mortem debugging session.
    3.27 + *
    3.28 + * Here is a picture:
    3.29 + *
    3.30 + * 					    port0 (from inetd)
    3.31 + *      8-bit connection     	       	   /
    3.32 + * 	   made by us	   <----> nsplitd <-----gdbport (default port0+2)
    3.33 + * 	to host:port/tcp		  |\
    3.34 + * 					  | port1 (default port0+1)
    3.35 + *                                         \
    3.36 + *                                          control (default port0+3)
    3.37 + *
    3.38 + * If port1 is explicitly disabled (through a command-line option) then
    3.39 + * port0 becomes 8-bit clean.
    3.40 + */
    3.41 +
    3.42 +/*
    3.43 + * N.B.: We do NOT support 8 bit stdin/stdout usage on a
    3.44 + * /dev/... because to do that right involves much messing with ioctl
    3.45 + * and TIOC... etc.  If you want to do that sort of thing then the
    3.46 + * right way to do it is to chain this onto wconsd (which does know
    3.47 + * about and understand all the ioctl and TIOC grief).
    3.48 + */
    3.49 +
    3.50 +#include <sys/types.h>
    3.51 +#include <stdarg.h>
    3.52 +#include <stdio.h>
    3.53 +#include <stdlib.h>
    3.54 +#include <assert.h>
    3.55 +#include <errno.h>
    3.56 +#include <unistd.h>
    3.57 +#include <ctype.h>
    3.58 +#include <netdb.h>
    3.59 +#include <string.h>
    3.60 +
    3.61 +#include <sys/time.h>
    3.62 +#include <sys/signal.h>
    3.63 +#include <sys/socket.h>
    3.64 +#include <netinet/in.h>
    3.65 +#include <netinet/tcp.h>
    3.66 +#include <arpa/inet.h>
    3.67 +#include <sys/ioctl.h>
    3.68 +#include <syslog.h>
    3.69 +
    3.70 +#ifndef FALSE
    3.71 +#define FALSE 0
    3.72 +#endif
    3.73 +#ifndef TRUE
    3.74 +#define TRUE 1
    3.75 +#endif
    3.76 +
    3.77 +#ifndef LOG_DAEMON
    3.78 +#define LOG_DAEMON 0
    3.79 +#endif
    3.80 +
    3.81 +#define DB(x)  /* ((x), fflush(stderr)) */
    3.82 +
    3.83 +extern char *optarg;
    3.84 +
    3.85 +extern int optind, opterr, optopt;
    3.86 +
    3.87 +static char *prog_name;
    3.88 +
    3.89 +static void usage(void)
    3.90 +{
    3.91 +    fprintf(stderr, "This program (%s) should be run via inetd (tcp)\n\n",
    3.92 +	    prog_name);
    3.93 +    fprintf(stderr, "usage: %s [-h<highport>][-g<gdbport>]"
    3.94 +	    "[-c<ctlport>][-8] host:service\n",
    3.95 +	    prog_name);
    3.96 +    exit(1);
    3.97 +}
    3.98 +
    3.99 +static void fault(char *format, ...)
   3.100 +{
   3.101 +    va_list		ap;
   3.102 +    char		logbuf[1024];
   3.103 +
   3.104 +    va_start(ap, format);
   3.105 +    fprintf(stderr, "%s: ", prog_name);
   3.106 +    vfprintf(stderr, format, ap);
   3.107 +    fflush(stderr);
   3.108 +    va_end(ap);
   3.109 +    
   3.110 +    /* XXX This is a bit dubious, but there is no vsyslog */
   3.111 +    va_start(ap, format);
   3.112 +    vsprintf(logbuf, format, ap);
   3.113 +    syslog(LOG_ERR, logbuf);
   3.114 +    va_end(ap);
   3.115 +    exit(1);
   3.116 +}
   3.117 +
   3.118 +static int getservice(char *name, unsigned short *port)
   3.119 +{
   3.120 +    struct servent		*se;
   3.121 +
   3.122 +    if (!name) return -1;
   3.123 +
   3.124 +    if (isdigit(name[0]))
   3.125 +	*port = atoi(name);
   3.126 +    else
   3.127 +    {
   3.128 +	if (!(se = getservbyname(name, "tcp")))
   3.129 +	    return -1;
   3.130 +	*port = ntohs(se->s_port);
   3.131 +    }
   3.132 +    return 0;
   3.133 +}
   3.134 +
   3.135 +/* 
   3.136 + *  connect_host: connect to ("name", "port")
   3.137 + */
   3.138 +static int connect_host (char *name, unsigned int port)
   3.139 +{
   3.140 +    int			fd;
   3.141 +    struct hostent	*hostent;
   3.142 +    struct sockaddr_in	sin;
   3.143 +    int			on;
   3.144 +    
   3.145 +    if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
   3.146 +	fault("socket");
   3.147 +    
   3.148 +    if (!(hostent = gethostbyname(name)))
   3.149 +	fault("gethostbyname: %s: %s\n", name, strerror(errno));
   3.150 +    
   3.151 +    memset(&sin, 0, sizeof(sin));
   3.152 +    sin.sin_family = AF_INET;
   3.153 +    sin.sin_port   = htons (port);
   3.154 +    memcpy(&sin.sin_addr.s_addr, hostent->h_addr, sizeof(struct in_addr));
   3.155 +    
   3.156 +    if (connect(fd, (struct sockaddr *) &sin, sizeof (sin)) < 0)
   3.157 +	fault("connect: %s:%u: %s\n", name, port, strerror(errno));
   3.158 +    
   3.159 +    on = 1;
   3.160 +    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
   3.161 +	syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m");
   3.162 +
   3.163 +    on = 1;
   3.164 +    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)
   3.165 +	syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
   3.166 +
   3.167 +    return fd;
   3.168 +}
   3.169 +
   3.170 +/*
   3.171 + * open a tcp socket and start listening for connections on it
   3.172 + */
   3.173 +static int startlistening(unsigned short port)
   3.174 +{
   3.175 +    int			fd, on;
   3.176 +    struct sockaddr_in	sin;
   3.177 +
   3.178 +    if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
   3.179 +	fault("socket");
   3.180 +    
   3.181 +    on = 1;
   3.182 +    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)
   3.183 +      syslog(LOG_WARNING, "setsockopt (SO_REUSEADDR): %m");
   3.184 +
   3.185 +    memset(&sin, 0, sizeof(sin));
   3.186 +    sin.sin_family      = AF_INET;
   3.187 +    sin.sin_port        = htons (port);
   3.188 +    sin.sin_addr.s_addr = INADDR_ANY;
   3.189 +    if (bind(fd, &sin, sizeof(sin)) < 0)
   3.190 +	fault("bind: %u: %s\n", port, strerror(errno));
   3.191 +    
   3.192 +    if (listen(fd, 1) < 0)
   3.193 +	fault("listen: %s\n", strerror(errno));
   3.194 +    
   3.195 +    return fd;
   3.196 +}
   3.197 +
   3.198 +static void noblock(int fd)
   3.199 +{
   3.200 +    int on=1;
   3.201 +    
   3.202 +    if (ioctl(fd, FIONBIO, &on) < 0)
   3.203 +	fault("ioctl: FIONBIO: %s\n", strerror(errno));
   3.204 +}
   3.205 +
   3.206 +
   3.207 +/* You might not believe this, but fd_sets don't have to be a 32-bit
   3.208 + * integer.  In particular, in glibc2 it is an array of unsigned
   3.209 + * longs.  Hence, this hacked up FD_SET_rjb() that works out if it
   3.210 + * would have been a nop. */
   3.211 +#define FD_SET_rjb(fd, setp) \
   3.212 +do {						\
   3.213 +    if ((fd) != 32)				\
   3.214 +	FD_SET((fd), (setp));			\
   3.215 +} while(0)
   3.216 +
   3.217 +#define FD_ISSET_rjb(fd, setp) (((fd) != 32)? FD_ISSET((fd), (setp)) : 0)
   3.218 +
   3.219 +#define MAXSIZE	256
   3.220 +
   3.221 +/* -----------------------------------------------------------------
   3.222 + * The main bit of the algorithm. Note we use 32 to mean not connected
   3.223 + * because this gives us 1<<32 == 0. We could have done this one
   3.224 + * character at a time, but that would have been very inefficient and
   3.225 + * not the unix way.  */
   3.226 +static int debug;
   3.227 +
   3.228 +static void doit(int actl, int acto, int lish, int lisg, int lisc)
   3.229 +{
   3.230 +    int		acth, actg, actc;
   3.231 +    int		gdbmode = FALSE;
   3.232 +    char	gibuf[MAXSIZE], oibuf[MAXSIZE];
   3.233 +    char	libuf[MAXSIZE], lobuf[MAXSIZE];
   3.234 +    char	hibuf[MAXSIZE], hobuf[MAXSIZE];
   3.235 +    char	ctlbuf[MAXSIZE];
   3.236 +    fd_set	rdfs, wrfs, exfs;
   3.237 +    int		gicc, oicc, licc, locc, hicc, hocc, ctlcc;
   3.238 +    char	*giptr, *oiptr, *liptr, *loptr, *hiptr, *hoptr;
   3.239 +    int		rc, fromlen;
   3.240 +    struct sockaddr_in		from;
   3.241 +    
   3.242 +    gicc = oicc = licc = locc = hicc = hocc = ctlcc = 0;
   3.243 +    acth = actg = actc = 32;			/* XXX yummy */
   3.244 +
   3.245 +    noblock(actl);
   3.246 +    noblock(acto);
   3.247 +
   3.248 +    for(;;)
   3.249 +    {
   3.250 +	FD_ZERO(&rdfs);
   3.251 +	FD_ZERO(&wrfs);
   3.252 +	FD_ZERO(&exfs);
   3.253 +
   3.254 +	/* always take input from the control port (if it's connected) */
   3.255 +	FD_SET_rjb(actc, &rdfs);
   3.256 +
   3.257 +	if (gdbmode)
   3.258 +	{
   3.259 +	    if (oicc)
   3.260 +		FD_SET_rjb(actg, &wrfs);
   3.261 +	    else
   3.262 +		FD_SET_rjb(acto, &rdfs);
   3.263 +	    
   3.264 +	    if (gicc)
   3.265 +		FD_SET_rjb(acto, &wrfs);
   3.266 +	    else
   3.267 +		FD_SET_rjb(actg, &rdfs);
   3.268 +	}
   3.269 +	else
   3.270 +	{
   3.271 +	    /* There is no such thing as oibuf because its been split into
   3.272 +	     * lobuf and hobuf
   3.273 +	     */
   3.274 +	    if (locc || hocc)
   3.275 +	    {
   3.276 +		if (locc)
   3.277 +		    FD_SET_rjb(actl, &wrfs);
   3.278 +		if (hocc)
   3.279 +		    FD_SET_rjb(acth, &wrfs);
   3.280 +	    }
   3.281 +	    else
   3.282 +		FD_SET_rjb(acto, &rdfs);
   3.283 +	    
   3.284 +	    if (licc)
   3.285 +		FD_SET_rjb(acto, &wrfs);
   3.286 +	    else
   3.287 +		FD_SET_rjb(actl, &rdfs);
   3.288 +	    
   3.289 +	    if (hicc)
   3.290 +		FD_SET_rjb(acto, &wrfs);
   3.291 +	    else
   3.292 +		FD_SET_rjb(acth, &rdfs);
   3.293 +	}
   3.294 +	
   3.295 +	if (acth == 32 && lish>=0)	FD_SET_rjb(lish, &rdfs);
   3.296 +	if (actg == 32)			FD_SET_rjb(lisg, &rdfs);
   3.297 +	if (actc == 32)			FD_SET_rjb(lisc, &rdfs);
   3.298 +
   3.299 +	/* now make exfs the union of the read and write fd sets, plus
   3.300 +	 * "actl" */
   3.301 +	{
   3.302 +	    int i;
   3.303 +	    exfs = rdfs;
   3.304 +	    for(i=0; i<32; i++)  /* XXX we only copy fd numbers up to 31 */
   3.305 +		if (FD_ISSET(i, &wrfs))
   3.306 +		    FD_SET_rjb(i, &exfs);
   3.307 +	    FD_SET_rjb(actl, &exfs);
   3.308 +	}
   3.309 +
   3.310 +	/* XXX AND: can't print something of type fd_set as %x - it
   3.311 +         * might be an array */
   3.312 +	DB(fprintf(stderr, "%s: before select: %08x %08x %08x\n",
   3.313 +		   prog_name, rdfs, wrfs, exfs));
   3.314 +	
   3.315 +	if (select(32, &rdfs, &wrfs, &exfs, NULL) < 0)
   3.316 +	    fault("select: %s\n", strerror(errno));
   3.317 +	
   3.318 +	DB(fprintf(stderr, "%s: after  select: %08x %08x %08x\n",
   3.319 +		   prog_name, rdfs, wrfs, exfs));
   3.320 +	
   3.321 +	/* XXX it appears that a non-blocking socket may not show up
   3.322 +	 * correctly in exfs but instead goes readable with no data in
   3.323 +	 * it. Thus we check for zero and goto the appropriate close
   3.324 +	 * method.  */
   3.325 +
   3.326 +	/* Deal with exceptions */
   3.327 +	if (FD_ISSET_rjb(actg, &exfs))
   3.328 +	{
   3.329 +	exfs_actg:
   3.330 +	    close(actg);
   3.331 +	    gdbmode = FALSE;
   3.332 +	    oicc = 0;
   3.333 +	    oiptr = oibuf;
   3.334 +	    actg = 32;
   3.335 +	    continue;		/* because assumptions changed */
   3.336 +	}
   3.337 +	if (FD_ISSET_rjb(acth, &exfs))
   3.338 +	{
   3.339 +	exfs_acth:
   3.340 +	    close(acth);
   3.341 +	    hicc = hocc = 0;
   3.342 +	    hiptr = hibuf;
   3.343 +	    hoptr = hibuf;
   3.344 +	    acth = 32;
   3.345 +	    continue;		/* because assumptions changed */
   3.346 +	}
   3.347 +	if (FD_ISSET_rjb(actl, &exfs) ||
   3.348 +	    FD_ISSET_rjb(acto, &exfs))
   3.349 +	{
   3.350 +	exfs_actl:
   3.351 +	exfs_acto:
   3.352 +	    /* Thats all folks ... */
   3.353 +	    break;
   3.354 +	}
   3.355 +	if (FD_ISSET_rjb(actc, &exfs))
   3.356 +	{
   3.357 +	exfs_ctl:
   3.358 +	    close(actc);
   3.359 +	    actc = 32;
   3.360 +	    ctlcc = 0;
   3.361 +	    continue;
   3.362 +	}
   3.363 +
   3.364 +	/* Deal with reading */
   3.365 +	if (FD_ISSET_rjb(acto, &rdfs))
   3.366 +	{
   3.367 +	    if ((oicc = read(acto, oiptr = oibuf, MAXSIZE)) < 0)
   3.368 +		fault("read acto: %d: %s\n", oicc, strerror(errno));
   3.369 +	    if (!oicc) goto exfs_acto;
   3.370 +	    
   3.371 +	    if (!gdbmode)
   3.372 +	    {
   3.373 +		int t;
   3.374 +
   3.375 +		assert((locc == 0) && (hocc == 0));
   3.376 +		loptr = lobuf;
   3.377 +		hoptr = hobuf;
   3.378 +		
   3.379 +		if (lish>=0) {
   3.380 +		    for(t=0; t<oicc; t++)
   3.381 +			if (oibuf[t] & 0x80)
   3.382 +			    hobuf[hocc++] = oibuf[t] & 0x7f;
   3.383 +			else
   3.384 +			    lobuf[locc++] = oibuf[t];
   3.385 +		} else {
   3.386 +		    for (t=0; t<oicc; t++)
   3.387 +			lobuf[locc++] = oibuf[t];
   3.388 +		}
   3.389 +		/* If no high connection scratch that */
   3.390 +		if (acth == 32)
   3.391 +		    hocc=0;
   3.392 +	    }
   3.393 +	}
   3.394 +	if (FD_ISSET_rjb(actl, &rdfs))
   3.395 +	{
   3.396 +	    if ((licc = read(actl, liptr = libuf, MAXSIZE)) < 0)
   3.397 +		fault("read actl: %d: %s\n", licc, strerror(errno));
   3.398 +	    if (!licc) goto exfs_actl;
   3.399 +	}
   3.400 +	if (FD_ISSET_rjb(acth, &rdfs))
   3.401 +	{
   3.402 +	    int t;
   3.403 +	    
   3.404 +	    if ((hicc = read(acth, hiptr = hibuf, MAXSIZE)) < 0)
   3.405 +		fault("read acth: %d: %s\n", hicc, strerror(errno));
   3.406 +	    if (!hicc) goto exfs_acth;
   3.407 +	    for(t=0; t<hicc; t++)
   3.408 +		hibuf[t] |= 0x80;
   3.409 +	}
   3.410 +	if (FD_ISSET_rjb(actg, &rdfs))
   3.411 +	{
   3.412 +	    if ((gicc = read(actg, giptr = gibuf, MAXSIZE)) < 0)
   3.413 +		fault("read actg: %d: %s\n", gicc, strerror(errno));
   3.414 +	    if (debug) write(1, giptr, gicc);		/* XXX */
   3.415 +	    if (!gicc) goto exfs_actg;
   3.416 +	}
   3.417 +	if (FD_ISSET_rjb(actc, &rdfs))
   3.418 +	{
   3.419 +	    if ((ctlcc = read(actc, ctlbuf, MAXSIZE)) < 0)
   3.420 +		fault("read actc: %d: %s\n", ctlcc, strerror(errno));
   3.421 +	    if (debug) write(1, ctlbuf, gicc);
   3.422 +	    if (!ctlcc) goto exfs_ctl;
   3.423 +	    if (ctlbuf[0] == 'r') /* reset command */
   3.424 +	    {
   3.425 +		syslog(LOG_INFO, "reset command read, exiting");
   3.426 +		if (debug) write(1, "reseting\n", sizeof("reseting\n"));
   3.427 +		break;
   3.428 +	    }
   3.429 +	}
   3.430 +	
   3.431 +	/* Deal with writing */
   3.432 +	if (FD_ISSET_rjb(actg, &wrfs))
   3.433 +	{
   3.434 +	    /* We must be in gdb mode so send oi buffer data */
   3.435 +	    assert(gdbmode);
   3.436 +	    if (debug) write(2, oiptr, oicc);		/* XXX */
   3.437 +	    if ((rc = write(actg, oiptr, oicc)) <= 0)
   3.438 +		fault("write actg: %d: %s\n", rc, strerror(errno));
   3.439 +	    oiptr += rc;
   3.440 +	    oicc  -= rc;
   3.441 +	}
   3.442 +	if (FD_ISSET_rjb(actl, &wrfs))
   3.443 +	{
   3.444 +	    if ((rc = write(actl, loptr, locc)) <= 0)
   3.445 +		fault("write actl: %d: %s\n", rc, strerror(errno));
   3.446 +	    loptr += rc;
   3.447 +	    locc  -= rc;
   3.448 +	}
   3.449 +	if (FD_ISSET_rjb(acth, &wrfs))
   3.450 +	{
   3.451 +	    if ((rc = write(acth, hoptr, hocc)) <= 0)
   3.452 +		fault("write acth: %d: %s\n", rc, strerror(errno));
   3.453 +	    hoptr += rc;
   3.454 +	    hocc  -= rc;
   3.455 +	}
   3.456 +	if (FD_ISSET_rjb(acto, &wrfs))
   3.457 +	{
   3.458 +	    /* If in gdb mode send gdb input, otherwise send low data
   3.459 +	       preferentially */
   3.460 +	    if (gdbmode)
   3.461 +	    {
   3.462 +		assert(gicc);
   3.463 +		if ((rc = write(acto, giptr, gicc)) <= 0)
   3.464 +		    fault("write acto: %d: %s\n", rc, strerror(errno));
   3.465 +		giptr += rc;
   3.466 +		gicc  -= rc;
   3.467 +	    }
   3.468 +	    else
   3.469 +	    {
   3.470 +		if (licc)
   3.471 +		{
   3.472 +		    if ((rc = write(acto, liptr, licc)) <= 0)
   3.473 +			fault("write acto: %d: %s\n", rc, strerror(errno));
   3.474 +		    liptr += rc;
   3.475 +		    licc  -= rc;
   3.476 +		}
   3.477 +		else
   3.478 +		{
   3.479 +		    assert(hicc);
   3.480 +		    if ((rc = write(acto, hiptr, hicc)) <= 0)
   3.481 +			fault("write acto: %d: %s\n", rc, strerror(errno));
   3.482 +		    hiptr += rc;
   3.483 +		    hicc  -= rc;
   3.484 +		}
   3.485 +	    }
   3.486 +	}
   3.487 +	
   3.488 +	/* Deals with new connections */
   3.489 +	if ((acth == 32) && lish>=0 && (FD_ISSET_rjb(lish, &rdfs)))
   3.490 +	{
   3.491 +	    fromlen = sizeof(from);
   3.492 +	    if ((acth = accept(lish, &from, &fromlen)) < 0)
   3.493 +	    {
   3.494 +		syslog(LOG_WARNING, "accept: %m");
   3.495 +		acth = 32;
   3.496 +	    }
   3.497 +	    else
   3.498 +	    {
   3.499 +		noblock(acth);
   3.500 +		hicc = hocc = 0;
   3.501 +		syslog(LOG_INFO, "highbit client peer is %s:%u\n",
   3.502 +		       inet_ntoa(from.sin_addr), ntohs(from.sin_port));
   3.503 +	    }
   3.504 +	}
   3.505 +	
   3.506 +	if ((actg == 32) && (FD_ISSET_rjb(lisg, &rdfs)))
   3.507 +	{
   3.508 +	    fromlen = sizeof(from);
   3.509 +	    if ((actg = accept(lisg, &from, &fromlen)) < 0)
   3.510 +	    {
   3.511 +		syslog(LOG_WARNING, "accept: %m");
   3.512 +		actg = 32;
   3.513 +	    }
   3.514 +	    else
   3.515 +	    {
   3.516 +		noblock(actg);
   3.517 +		gicc = 0;
   3.518 +		gdbmode = TRUE;
   3.519 +		syslog(LOG_INFO, "gdb client peer is %s:%u\n",
   3.520 +		       inet_ntoa(from.sin_addr), ntohs(from.sin_port));
   3.521 +	    }
   3.522 +	}
   3.523 +
   3.524 +	if ((actc == 32) && (FD_ISSET_rjb(lisc, &rdfs)))
   3.525 +	{
   3.526 +	    fromlen = sizeof(from);
   3.527 +	    if ((actc = accept(lisc, &from, &fromlen)) < 0)
   3.528 +	    {
   3.529 +		syslog(LOG_WARNING, "accept (ctl): %m");
   3.530 +		actc = 32;
   3.531 +	    }
   3.532 +	    else
   3.533 +	    {
   3.534 +		noblock(actc);
   3.535 +		syslog(LOG_INFO, "ctl client peer is %s:%u\n",
   3.536 +		       inet_ntoa(from.sin_addr), ntohs(from.sin_port));
   3.537 +	    }
   3.538 +	}
   3.539 +	    
   3.540 +	/* Back to top of loop */
   3.541 +    }
   3.542 +    
   3.543 +    /* We are bailing because one of the primary connections has gone
   3.544 +     * away. We close these all explicitly here because that way the
   3.545 +     * timeout on reusing the port numbers is smnaller. */
   3.546 +    
   3.547 +    close(acth);
   3.548 +    close(actg);
   3.549 +    /* XXX AND: why are we closing all these "character counts" ?? */
   3.550 +    close(gicc);
   3.551 +    close(oicc);
   3.552 +    close(licc);
   3.553 +    close(locc);
   3.554 +    close(hicc);
   3.555 +    close(hocc);
   3.556 +}
   3.557 +
   3.558 +/*
   3.559 + * ------------------------------------------------------------
   3.560 + */
   3.561 +int main(int argc, char **argv)
   3.562 +{
   3.563 +    /* In general, suffix "l" is low channel, "h" is high channel, "g"
   3.564 +     * is gdb channel, "c" is control channel and "o" is output channel.
   3.565 +     */
   3.566 +    struct sockaddr_in		from;
   3.567 +    int				infd = 0, outfd;
   3.568 +    unsigned short		portl, porth, portg, portc, porto;
   3.569 +    int				on = 1, c;
   3.570 +    char			*outname, *outservice;
   3.571 +    int				fromlen;
   3.572 +    int				lish, lisg, lisc;
   3.573 +#if 0
   3.574 +    FILE			*newerr;
   3.575 +#endif /* 0 */
   3.576 +    
   3.577 +    prog_name = argv[0];
   3.578 +
   3.579 +    if (isatty(infd))
   3.580 +	usage();
   3.581 +
   3.582 +    /* Here, then not just a simple idiot. */
   3.583 +
   3.584 +    signal(SIGPIPE, SIG_IGN);
   3.585 +
   3.586 +    openlog(prog_name, LOG_PID, LOG_DAEMON);
   3.587 +
   3.588 +    fromlen = sizeof(from);
   3.589 +    if (getsockname(infd, &from, &fromlen) < 0)
   3.590 +	fault("getsockname: %s", strerror(errno));
   3.591 +    if ((fromlen != sizeof(from)) || (from.sin_family != AF_INET))
   3.592 +	fault("not an inet socket (family=%d)\n", from.sin_family);
   3.593 +    
   3.594 +    portl = ntohs(from.sin_port);
   3.595 +    porth = portl+1;
   3.596 +    portg = porth+1;
   3.597 +    portc = portg+1;
   3.598 +
   3.599 +    fromlen = sizeof(from);
   3.600 +    if (getpeername(infd, &from, &fromlen) < 0)
   3.601 +	fault("getpeername: %s", strerror(errno));
   3.602 +    if ((fromlen != sizeof(from)) || (from.sin_family != AF_INET))
   3.603 +	fault("not an inet socket (family=%d)\n", from.sin_family);
   3.604 +
   3.605 +    syslog(LOG_INFO, "on port %u peer is %s:%u\n", portl,
   3.606 +	   inet_ntoa(from.sin_addr), ntohs(from.sin_port));
   3.607 +    
   3.608 +    if (setsockopt(infd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)
   3.609 +	syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
   3.610 +
   3.611 +    /* from here on, we map stderr to output on the connection so we can
   3.612 +     * report errors to the remote user.
   3.613 +     */
   3.614 +#if 0
   3.615 +    if (!(newerr = fdopen(infd, "w")))
   3.616 +	syslog(LOG_WARNING, "fdopen: %m");
   3.617 +    else
   3.618 +	*stderr = *newerr;
   3.619 +#endif
   3.620 +	
   3.621 +    while((c = getopt(argc, argv, "d8h:g:c:")) != EOF)
   3.622 +    {
   3.623 +	switch(c)
   3.624 +	{
   3.625 +	case 'd':
   3.626 +	    debug++;
   3.627 +	    break;
   3.628 +	    
   3.629 +	case 'h':
   3.630 +	    /* high bit port */
   3.631 +	    if (getservice(optarg, &porth) < 0)
   3.632 +		fault("getservice failed (high port '%s')\n", optarg);
   3.633 +	    break;
   3.634 +	    
   3.635 +	case 'g':
   3.636 +	    /* gdb port */
   3.637 +	    if (getservice(optarg, &portg) < 0)
   3.638 +		fault("getservice failed (gdb port '%s')\n", optarg);
   3.639 +	    break;
   3.640 +
   3.641 +	case 'c':
   3.642 +	    /* control port */
   3.643 +	    if (getservice(optarg, &portc) < 0)
   3.644 +		fault("getservice failed (control port '%s')\n", optarg);
   3.645 +	    break;
   3.646 +
   3.647 +	case '8':
   3.648 +	    /* 8-bit clean; no high port */
   3.649 +	    porth=0;
   3.650 +	    break;
   3.651 +
   3.652 +	default:
   3.653 +	    fault("bad argument list!\n");
   3.654 +	}
   3.655 +    }
   3.656 +    
   3.657 +    if (argc != optind + 1)
   3.658 +	fault("unparsed arguments (%d!=%d)\n", argc, optind+1);
   3.659 +
   3.660 +    outname = argv[optind];
   3.661 +    if (!(outservice = strchr(outname, ':')))
   3.662 +	fault("output arg '%s' doesn't contain ':'\n", outname);
   3.663 +    *outservice++ = 0;
   3.664 +    if (getservice(outservice, &porto) < 0)
   3.665 +	fault("getservice failed (output port '%s')\n", outservice);
   3.666 +    
   3.667 +    /* Time to start the sockets */
   3.668 +
   3.669 +    if (porth) {
   3.670 +	lish  = startlistening(porth);
   3.671 +    } else {
   3.672 +	lish  = -1;
   3.673 +    }
   3.674 +    lisg  = startlistening(portg);
   3.675 +    lisc  = startlistening(portc);
   3.676 +    
   3.677 +    outfd = connect_host(outname, porto);
   3.678 +    
   3.679 +    doit(infd, outfd, lish, lisg, lisc);
   3.680 +
   3.681 +    syslog(LOG_INFO, "terminating normally\n");
   3.682 +
   3.683 +    fclose(stderr);
   3.684 +
   3.685 +    closelog();
   3.686 +    exit(0); 
   3.687 +}
   3.688 +
   3.689 +/* End $Id: nsplitd.c,v 2.6 1998/09/17 14:28:37 sde1000 Exp $ */