ia64/xen-unstable

changeset 1665:52c04d5d2a8e

bitkeeper revision 1.1041.5.2 (40e52b96BQ9bUqp56S9aQ11AJvgoZg)

Merge http://xen.bkbits.net:8080/xeno-unstable.bk
into gandalf.hpl.hp.com:/var/bk/xeno-unstable.bk
author xenbk@gandalf.hpl.hp.com
date Fri Jul 02 09:32:06 2004 +0000 (2004-07-02)
parents 11fc1027833b 23e371e87d2f
children 172f2a1c8a79
files .rootkeys docs/HOWTOs/XenDebugger-HOWTO tools/misc/nsplitd/Makefile tools/misc/nsplitd/nsplitd.c
line diff
     1.1 --- a/.rootkeys	Fri Jul 02 08:30:28 2004 +0000
     1.2 +++ b/.rootkeys	Fri Jul 02 09:32:06 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 --- a/docs/HOWTOs/XenDebugger-HOWTO	Fri Jul 02 08:30:28 2004 +0000
     2.2 +++ b/docs/HOWTOs/XenDebugger-HOWTO	Fri Jul 02 09:32:06 2004 +0000
     2.3 @@ -77,7 +77,7 @@ Serial Port Configuration
     2.4    one stream (without the high bit) is the console and 
     2.5    one stream (with the high bit stripped) is the pdb communication.
     2.6  
     2.7 -  See:  xeno.bk/tools/nsplitd
     2.8 +  See:  xeno.bk/tools/misc/nsplitd
     2.9  
    2.10    nsplitd configuration
    2.11    ---------------------
    2.12 @@ -107,7 +107,7 @@ Serial Port Configuration
    2.13    characters received.
    2.14  
    2.15    You can connect to the nsplitd using
    2.16 -  'tools/xenctl/lib/console_client.py <host> <port>'
    2.17 +  'tools/misc/xencons <host> <port>'
    2.18  
    2.19  GDB 6.0
    2.20    pdb has been tested with gdb 6.0.  It should also work with
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/misc/nsplitd/Makefile	Fri Jul 02 09:32:06 2004 +0000
     3.3 @@ -0,0 +1,22 @@
     3.4 +
     3.5 +CC     = gcc
     3.6 +CFLAGS = -Wall -O3
     3.7 +CFILES = $(wildcard *.c)
     3.8 +
     3.9 +HDRS     = $(wildcard *.h)
    3.10 +OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))
    3.11 +
    3.12 +TARGET   = nsplitd
    3.13 +
    3.14 +all: $(TARGET)
    3.15 +
    3.16 +install: all
    3.17 +
    3.18 +clean:
    3.19 +	$(RM) *.o $(TARGET) *~
    3.20 +
    3.21 +$(TARGET): $(OBJS)
    3.22 +	$(CC) $(CFLAGS) -o $@ $^
    3.23 +
    3.24 +%.o: %.c $(HDRS) Makefile
    3.25 +	$(CC) $(CFLAGS) -c -o $@ $<
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/misc/nsplitd/nsplitd.c	Fri Jul 02 09:32:06 2004 +0000
     4.3 @@ -0,0 +1,686 @@
     4.4 +/*
     4.5 + *	nsplitd.c
     4.6 + *	---------
     4.7 + *
     4.8 + * $Id: nsplitd.c,v 2.6 1998/09/17 14:28:37 sde1000 Exp $
     4.9 + *
    4.10 + * Copyright (c) 1995, University of Cambridge Computer Laboratory,
    4.11 + * Copyright (c) 1995, Richard Black, All Rights Reserved.
    4.12 + *
    4.13 + *
    4.14 + * A complete re-implementation of DME's nsplitd for use from inetd
    4.15 + *
    4.16 + */
    4.17 +
    4.18 +/* The basic stream comes in (via inetd) and we then conenct to
    4.19 + * somewhere else providing a loop-through service, except we offer
    4.20 + * two other ports for connection - one of which gets a second channel
    4.21 + * using the top bit to distinguish, and the other is a master control
    4.22 + * port (normally used for gdb) which gets complete exclusive access
    4.23 + * for its duration.
    4.24 + *
    4.25 + * Originally designed for multiplexing a xwcons/telnet with a gdb
    4.26 + * post-mortem debugging session.
    4.27 + *
    4.28 + * Here is a picture:
    4.29 + *
    4.30 + * 					    port0 (from inetd)
    4.31 + *      8-bit connection     	       	   /
    4.32 + * 	   made by us	   <----> nsplitd <-----gdbport (default port0+2)
    4.33 + * 	to host:port/tcp		  |\
    4.34 + * 					  | port1 (default port0+1)
    4.35 + *                                         \
    4.36 + *                                          control (default port0+3)
    4.37 + *
    4.38 + * If port1 is explicitly disabled (through a command-line option) then
    4.39 + * port0 becomes 8-bit clean.
    4.40 + */
    4.41 +
    4.42 +/*
    4.43 + * N.B.: We do NOT support 8 bit stdin/stdout usage on a
    4.44 + * /dev/... because to do that right involves much messing with ioctl
    4.45 + * and TIOC... etc.  If you want to do that sort of thing then the
    4.46 + * right way to do it is to chain this onto wconsd (which does know
    4.47 + * about and understand all the ioctl and TIOC grief).
    4.48 + */
    4.49 +
    4.50 +#include <sys/types.h>
    4.51 +#include <stdarg.h>
    4.52 +#include <stdio.h>
    4.53 +#include <stdlib.h>
    4.54 +#include <assert.h>
    4.55 +#include <errno.h>
    4.56 +#include <unistd.h>
    4.57 +#include <ctype.h>
    4.58 +#include <netdb.h>
    4.59 +#include <string.h>
    4.60 +
    4.61 +#include <sys/time.h>
    4.62 +#include <sys/signal.h>
    4.63 +#include <sys/socket.h>
    4.64 +#include <netinet/in.h>
    4.65 +#include <netinet/tcp.h>
    4.66 +#include <arpa/inet.h>
    4.67 +#include <sys/ioctl.h>
    4.68 +#include <syslog.h>
    4.69 +
    4.70 +#ifndef FALSE
    4.71 +#define FALSE 0
    4.72 +#endif
    4.73 +#ifndef TRUE
    4.74 +#define TRUE 1
    4.75 +#endif
    4.76 +
    4.77 +#ifndef LOG_DAEMON
    4.78 +#define LOG_DAEMON 0
    4.79 +#endif
    4.80 +
    4.81 +#define DB(x)  /* ((x), fflush(stderr)) */
    4.82 +
    4.83 +extern char *optarg;
    4.84 +
    4.85 +extern int optind, opterr, optopt;
    4.86 +
    4.87 +static char *prog_name;
    4.88 +
    4.89 +static void usage(void)
    4.90 +{
    4.91 +    fprintf(stderr, "This program (%s) should be run via inetd (tcp)\n\n",
    4.92 +	    prog_name);
    4.93 +    fprintf(stderr, "usage: %s [-h<highport>][-g<gdbport>]"
    4.94 +	    "[-c<ctlport>][-8] host:service\n",
    4.95 +	    prog_name);
    4.96 +    exit(1);
    4.97 +}
    4.98 +
    4.99 +static void fault(char *format, ...)
   4.100 +{
   4.101 +    va_list		ap;
   4.102 +    char		logbuf[1024];
   4.103 +
   4.104 +    va_start(ap, format);
   4.105 +    fprintf(stderr, "%s: ", prog_name);
   4.106 +    vfprintf(stderr, format, ap);
   4.107 +    fflush(stderr);
   4.108 +    va_end(ap);
   4.109 +    
   4.110 +    /* XXX This is a bit dubious, but there is no vsyslog */
   4.111 +    va_start(ap, format);
   4.112 +    vsprintf(logbuf, format, ap);
   4.113 +    syslog(LOG_ERR, logbuf);
   4.114 +    va_end(ap);
   4.115 +    exit(1);
   4.116 +}
   4.117 +
   4.118 +static int getservice(char *name, unsigned short *port)
   4.119 +{
   4.120 +    struct servent		*se;
   4.121 +
   4.122 +    if (!name) return -1;
   4.123 +
   4.124 +    if (isdigit(name[0]))
   4.125 +	*port = atoi(name);
   4.126 +    else
   4.127 +    {
   4.128 +	if (!(se = getservbyname(name, "tcp")))
   4.129 +	    return -1;
   4.130 +	*port = ntohs(se->s_port);
   4.131 +    }
   4.132 +    return 0;
   4.133 +}
   4.134 +
   4.135 +/* 
   4.136 + *  connect_host: connect to ("name", "port")
   4.137 + */
   4.138 +static int connect_host (char *name, unsigned int port)
   4.139 +{
   4.140 +    int			fd;
   4.141 +    struct hostent	*hostent;
   4.142 +    struct sockaddr_in	sin;
   4.143 +    int			on;
   4.144 +    
   4.145 +    if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
   4.146 +	fault("socket");
   4.147 +    
   4.148 +    if (!(hostent = gethostbyname(name)))
   4.149 +	fault("gethostbyname: %s: %s\n", name, strerror(errno));
   4.150 +    
   4.151 +    memset(&sin, 0, sizeof(sin));
   4.152 +    sin.sin_family = AF_INET;
   4.153 +    sin.sin_port   = htons (port);
   4.154 +    memcpy(&sin.sin_addr.s_addr, hostent->h_addr, sizeof(struct in_addr));
   4.155 +    
   4.156 +    if (connect(fd, (struct sockaddr *) &sin, sizeof (sin)) < 0)
   4.157 +	fault("connect: %s:%u: %s\n", name, port, strerror(errno));
   4.158 +    
   4.159 +    on = 1;
   4.160 +    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
   4.161 +	syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m");
   4.162 +
   4.163 +    on = 1;
   4.164 +    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)
   4.165 +	syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
   4.166 +
   4.167 +    return fd;
   4.168 +}
   4.169 +
   4.170 +/*
   4.171 + * open a tcp socket and start listening for connections on it
   4.172 + */
   4.173 +static int startlistening(unsigned short port)
   4.174 +{
   4.175 +    int			fd, on;
   4.176 +    struct sockaddr_in	sin;
   4.177 +
   4.178 +    if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
   4.179 +	fault("socket");
   4.180 +    
   4.181 +    on = 1;
   4.182 +    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)
   4.183 +      syslog(LOG_WARNING, "setsockopt (SO_REUSEADDR): %m");
   4.184 +
   4.185 +    memset(&sin, 0, sizeof(sin));
   4.186 +    sin.sin_family      = AF_INET;
   4.187 +    sin.sin_port        = htons (port);
   4.188 +    sin.sin_addr.s_addr = INADDR_ANY;
   4.189 +    if (bind(fd, &sin, sizeof(sin)) < 0)
   4.190 +	fault("bind: %u: %s\n", port, strerror(errno));
   4.191 +    
   4.192 +    if (listen(fd, 1) < 0)
   4.193 +	fault("listen: %s\n", strerror(errno));
   4.194 +    
   4.195 +    return fd;
   4.196 +}
   4.197 +
   4.198 +static void noblock(int fd)
   4.199 +{
   4.200 +    int on=1;
   4.201 +    
   4.202 +    if (ioctl(fd, FIONBIO, &on) < 0)
   4.203 +	fault("ioctl: FIONBIO: %s\n", strerror(errno));
   4.204 +}
   4.205 +
   4.206 +
   4.207 +/* You might not believe this, but fd_sets don't have to be a 32-bit
   4.208 + * integer.  In particular, in glibc2 it is an array of unsigned
   4.209 + * longs.  Hence, this hacked up FD_SET_rjb() that works out if it
   4.210 + * would have been a nop. */
   4.211 +#define FD_SET_rjb(fd, setp) \
   4.212 +do {						\
   4.213 +    if ((fd) != 32)				\
   4.214 +	FD_SET((fd), (setp));			\
   4.215 +} while(0)
   4.216 +
   4.217 +#define FD_ISSET_rjb(fd, setp) (((fd) != 32)? FD_ISSET((fd), (setp)) : 0)
   4.218 +
   4.219 +#define MAXSIZE	256
   4.220 +
   4.221 +/* -----------------------------------------------------------------
   4.222 + * The main bit of the algorithm. Note we use 32 to mean not connected
   4.223 + * because this gives us 1<<32 == 0. We could have done this one
   4.224 + * character at a time, but that would have been very inefficient and
   4.225 + * not the unix way.  */
   4.226 +static int debug;
   4.227 +
   4.228 +static void doit(int actl, int acto, int lish, int lisg, int lisc)
   4.229 +{
   4.230 +    int		acth, actg, actc;
   4.231 +    int		gdbmode = FALSE;
   4.232 +    char	gibuf[MAXSIZE], oibuf[MAXSIZE];
   4.233 +    char	libuf[MAXSIZE], lobuf[MAXSIZE];
   4.234 +    char	hibuf[MAXSIZE], hobuf[MAXSIZE];
   4.235 +    char	ctlbuf[MAXSIZE];
   4.236 +    fd_set	rdfs, wrfs, exfs;
   4.237 +    int		gicc, oicc, licc, locc, hicc, hocc, ctlcc;
   4.238 +    char	*giptr, *oiptr, *liptr, *loptr, *hiptr, *hoptr;
   4.239 +    int		rc, fromlen;
   4.240 +    struct sockaddr_in		from;
   4.241 +    
   4.242 +    gicc = oicc = licc = locc = hicc = hocc = ctlcc = 0;
   4.243 +    acth = actg = actc = 32;			/* XXX yummy */
   4.244 +
   4.245 +    noblock(actl);
   4.246 +    noblock(acto);
   4.247 +
   4.248 +    for(;;)
   4.249 +    {
   4.250 +	FD_ZERO(&rdfs);
   4.251 +	FD_ZERO(&wrfs);
   4.252 +	FD_ZERO(&exfs);
   4.253 +
   4.254 +	/* always take input from the control port (if it's connected) */
   4.255 +	FD_SET_rjb(actc, &rdfs);
   4.256 +
   4.257 +	if (gdbmode)
   4.258 +	{
   4.259 +	    if (oicc)
   4.260 +		FD_SET_rjb(actg, &wrfs);
   4.261 +	    else
   4.262 +		FD_SET_rjb(acto, &rdfs);
   4.263 +	    
   4.264 +	    if (gicc)
   4.265 +		FD_SET_rjb(acto, &wrfs);
   4.266 +	    else
   4.267 +		FD_SET_rjb(actg, &rdfs);
   4.268 +	}
   4.269 +	else
   4.270 +	{
   4.271 +	    /* There is no such thing as oibuf because its been split into
   4.272 +	     * lobuf and hobuf
   4.273 +	     */
   4.274 +	    if (locc || hocc)
   4.275 +	    {
   4.276 +		if (locc)
   4.277 +		    FD_SET_rjb(actl, &wrfs);
   4.278 +		if (hocc)
   4.279 +		    FD_SET_rjb(acth, &wrfs);
   4.280 +	    }
   4.281 +	    else
   4.282 +		FD_SET_rjb(acto, &rdfs);
   4.283 +	    
   4.284 +	    if (licc)
   4.285 +		FD_SET_rjb(acto, &wrfs);
   4.286 +	    else
   4.287 +		FD_SET_rjb(actl, &rdfs);
   4.288 +	    
   4.289 +	    if (hicc)
   4.290 +		FD_SET_rjb(acto, &wrfs);
   4.291 +	    else
   4.292 +		FD_SET_rjb(acth, &rdfs);
   4.293 +	}
   4.294 +	
   4.295 +	if (acth == 32 && lish>=0)	FD_SET_rjb(lish, &rdfs);
   4.296 +	if (actg == 32)			FD_SET_rjb(lisg, &rdfs);
   4.297 +	if (actc == 32)			FD_SET_rjb(lisc, &rdfs);
   4.298 +
   4.299 +	/* now make exfs the union of the read and write fd sets, plus
   4.300 +	 * "actl" */
   4.301 +	{
   4.302 +	    int i;
   4.303 +	    exfs = rdfs;
   4.304 +	    for(i=0; i<32; i++)  /* XXX we only copy fd numbers up to 31 */
   4.305 +		if (FD_ISSET(i, &wrfs))
   4.306 +		    FD_SET_rjb(i, &exfs);
   4.307 +	    FD_SET_rjb(actl, &exfs);
   4.308 +	}
   4.309 +
   4.310 +	/* XXX AND: can't print something of type fd_set as %x - it
   4.311 +         * might be an array */
   4.312 +	DB(fprintf(stderr, "%s: before select: %08x %08x %08x\n",
   4.313 +		   prog_name, rdfs, wrfs, exfs));
   4.314 +	
   4.315 +	if (select(32, &rdfs, &wrfs, &exfs, NULL) < 0)
   4.316 +	    fault("select: %s\n", strerror(errno));
   4.317 +	
   4.318 +	DB(fprintf(stderr, "%s: after  select: %08x %08x %08x\n",
   4.319 +		   prog_name, rdfs, wrfs, exfs));
   4.320 +	
   4.321 +	/* XXX it appears that a non-blocking socket may not show up
   4.322 +	 * correctly in exfs but instead goes readable with no data in
   4.323 +	 * it. Thus we check for zero and goto the appropriate close
   4.324 +	 * method.  */
   4.325 +
   4.326 +	/* Deal with exceptions */
   4.327 +	if (FD_ISSET_rjb(actg, &exfs))
   4.328 +	{
   4.329 +	exfs_actg:
   4.330 +	    close(actg);
   4.331 +	    gdbmode = FALSE;
   4.332 +	    oicc = 0;
   4.333 +	    oiptr = oibuf;
   4.334 +	    actg = 32;
   4.335 +	    continue;		/* because assumptions changed */
   4.336 +	}
   4.337 +	if (FD_ISSET_rjb(acth, &exfs))
   4.338 +	{
   4.339 +	exfs_acth:
   4.340 +	    close(acth);
   4.341 +	    hicc = hocc = 0;
   4.342 +	    hiptr = hibuf;
   4.343 +	    hoptr = hibuf;
   4.344 +	    acth = 32;
   4.345 +	    continue;		/* because assumptions changed */
   4.346 +	}
   4.347 +	if (FD_ISSET_rjb(actl, &exfs) ||
   4.348 +	    FD_ISSET_rjb(acto, &exfs))
   4.349 +	{
   4.350 +	exfs_actl:
   4.351 +	exfs_acto:
   4.352 +	    /* Thats all folks ... */
   4.353 +	    break;
   4.354 +	}
   4.355 +	if (FD_ISSET_rjb(actc, &exfs))
   4.356 +	{
   4.357 +	exfs_ctl:
   4.358 +	    close(actc);
   4.359 +	    actc = 32;
   4.360 +	    ctlcc = 0;
   4.361 +	    continue;
   4.362 +	}
   4.363 +
   4.364 +	/* Deal with reading */
   4.365 +	if (FD_ISSET_rjb(acto, &rdfs))
   4.366 +	{
   4.367 +	    if ((oicc = read(acto, oiptr = oibuf, MAXSIZE)) < 0)
   4.368 +		fault("read acto: %d: %s\n", oicc, strerror(errno));
   4.369 +	    if (!oicc) goto exfs_acto;
   4.370 +	    
   4.371 +	    if (!gdbmode)
   4.372 +	    {
   4.373 +		int t;
   4.374 +
   4.375 +		assert((locc == 0) && (hocc == 0));
   4.376 +		loptr = lobuf;
   4.377 +		hoptr = hobuf;
   4.378 +		
   4.379 +		if (lish>=0) {
   4.380 +		    for(t=0; t<oicc; t++)
   4.381 +			if (oibuf[t] & 0x80)
   4.382 +			    hobuf[hocc++] = oibuf[t] & 0x7f;
   4.383 +			else
   4.384 +			    lobuf[locc++] = oibuf[t];
   4.385 +		} else {
   4.386 +		    for (t=0; t<oicc; t++)
   4.387 +			lobuf[locc++] = oibuf[t];
   4.388 +		}
   4.389 +		/* If no high connection scratch that */
   4.390 +		if (acth == 32)
   4.391 +		    hocc=0;
   4.392 +	    }
   4.393 +	}
   4.394 +	if (FD_ISSET_rjb(actl, &rdfs))
   4.395 +	{
   4.396 +	    if ((licc = read(actl, liptr = libuf, MAXSIZE)) < 0)
   4.397 +		fault("read actl: %d: %s\n", licc, strerror(errno));
   4.398 +	    if (!licc) goto exfs_actl;
   4.399 +	}
   4.400 +	if (FD_ISSET_rjb(acth, &rdfs))
   4.401 +	{
   4.402 +	    int t;
   4.403 +	    
   4.404 +	    if ((hicc = read(acth, hiptr = hibuf, MAXSIZE)) < 0)
   4.405 +		fault("read acth: %d: %s\n", hicc, strerror(errno));
   4.406 +	    if (!hicc) goto exfs_acth;
   4.407 +	    for(t=0; t<hicc; t++)
   4.408 +		hibuf[t] |= 0x80;
   4.409 +	}
   4.410 +	if (FD_ISSET_rjb(actg, &rdfs))
   4.411 +	{
   4.412 +	    if ((gicc = read(actg, giptr = gibuf, MAXSIZE)) < 0)
   4.413 +		fault("read actg: %d: %s\n", gicc, strerror(errno));
   4.414 +	    if (debug) write(1, giptr, gicc);		/* XXX */
   4.415 +	    if (!gicc) goto exfs_actg;
   4.416 +	}
   4.417 +	if (FD_ISSET_rjb(actc, &rdfs))
   4.418 +	{
   4.419 +	    if ((ctlcc = read(actc, ctlbuf, MAXSIZE)) < 0)
   4.420 +		fault("read actc: %d: %s\n", ctlcc, strerror(errno));
   4.421 +	    if (debug) write(1, ctlbuf, gicc);
   4.422 +	    if (!ctlcc) goto exfs_ctl;
   4.423 +	    if (ctlbuf[0] == 'r') /* reset command */
   4.424 +	    {
   4.425 +		syslog(LOG_INFO, "reset command read, exiting");
   4.426 +		if (debug) write(1, "reseting\n", sizeof("reseting\n"));
   4.427 +		break;
   4.428 +	    }
   4.429 +	}
   4.430 +	
   4.431 +	/* Deal with writing */
   4.432 +	if (FD_ISSET_rjb(actg, &wrfs))
   4.433 +	{
   4.434 +	    /* We must be in gdb mode so send oi buffer data */
   4.435 +	    assert(gdbmode);
   4.436 +	    if (debug) write(2, oiptr, oicc);		/* XXX */
   4.437 +	    if ((rc = write(actg, oiptr, oicc)) <= 0)
   4.438 +		fault("write actg: %d: %s\n", rc, strerror(errno));
   4.439 +	    oiptr += rc;
   4.440 +	    oicc  -= rc;
   4.441 +	}
   4.442 +	if (FD_ISSET_rjb(actl, &wrfs))
   4.443 +	{
   4.444 +	    if ((rc = write(actl, loptr, locc)) <= 0)
   4.445 +		fault("write actl: %d: %s\n", rc, strerror(errno));
   4.446 +	    loptr += rc;
   4.447 +	    locc  -= rc;
   4.448 +	}
   4.449 +	if (FD_ISSET_rjb(acth, &wrfs))
   4.450 +	{
   4.451 +	    if ((rc = write(acth, hoptr, hocc)) <= 0)
   4.452 +		fault("write acth: %d: %s\n", rc, strerror(errno));
   4.453 +	    hoptr += rc;
   4.454 +	    hocc  -= rc;
   4.455 +	}
   4.456 +	if (FD_ISSET_rjb(acto, &wrfs))
   4.457 +	{
   4.458 +	    /* If in gdb mode send gdb input, otherwise send low data
   4.459 +	       preferentially */
   4.460 +	    if (gdbmode)
   4.461 +	    {
   4.462 +		assert(gicc);
   4.463 +		if ((rc = write(acto, giptr, gicc)) <= 0)
   4.464 +		    fault("write acto: %d: %s\n", rc, strerror(errno));
   4.465 +		giptr += rc;
   4.466 +		gicc  -= rc;
   4.467 +	    }
   4.468 +	    else
   4.469 +	    {
   4.470 +		if (licc)
   4.471 +		{
   4.472 +		    if ((rc = write(acto, liptr, licc)) <= 0)
   4.473 +			fault("write acto: %d: %s\n", rc, strerror(errno));
   4.474 +		    liptr += rc;
   4.475 +		    licc  -= rc;
   4.476 +		}
   4.477 +		else
   4.478 +		{
   4.479 +		    assert(hicc);
   4.480 +		    if ((rc = write(acto, hiptr, hicc)) <= 0)
   4.481 +			fault("write acto: %d: %s\n", rc, strerror(errno));
   4.482 +		    hiptr += rc;
   4.483 +		    hicc  -= rc;
   4.484 +		}
   4.485 +	    }
   4.486 +	}
   4.487 +	
   4.488 +	/* Deals with new connections */
   4.489 +	if ((acth == 32) && lish>=0 && (FD_ISSET_rjb(lish, &rdfs)))
   4.490 +	{
   4.491 +	    fromlen = sizeof(from);
   4.492 +	    if ((acth = accept(lish, &from, &fromlen)) < 0)
   4.493 +	    {
   4.494 +		syslog(LOG_WARNING, "accept: %m");
   4.495 +		acth = 32;
   4.496 +	    }
   4.497 +	    else
   4.498 +	    {
   4.499 +		noblock(acth);
   4.500 +		hicc = hocc = 0;
   4.501 +		syslog(LOG_INFO, "highbit client peer is %s:%u\n",
   4.502 +		       inet_ntoa(from.sin_addr), ntohs(from.sin_port));
   4.503 +	    }
   4.504 +	}
   4.505 +	
   4.506 +	if ((actg == 32) && (FD_ISSET_rjb(lisg, &rdfs)))
   4.507 +	{
   4.508 +	    fromlen = sizeof(from);
   4.509 +	    if ((actg = accept(lisg, &from, &fromlen)) < 0)
   4.510 +	    {
   4.511 +		syslog(LOG_WARNING, "accept: %m");
   4.512 +		actg = 32;
   4.513 +	    }
   4.514 +	    else
   4.515 +	    {
   4.516 +		noblock(actg);
   4.517 +		gicc = 0;
   4.518 +		gdbmode = TRUE;
   4.519 +		syslog(LOG_INFO, "gdb client peer is %s:%u\n",
   4.520 +		       inet_ntoa(from.sin_addr), ntohs(from.sin_port));
   4.521 +	    }
   4.522 +	}
   4.523 +
   4.524 +	if ((actc == 32) && (FD_ISSET_rjb(lisc, &rdfs)))
   4.525 +	{
   4.526 +	    fromlen = sizeof(from);
   4.527 +	    if ((actc = accept(lisc, &from, &fromlen)) < 0)
   4.528 +	    {
   4.529 +		syslog(LOG_WARNING, "accept (ctl): %m");
   4.530 +		actc = 32;
   4.531 +	    }
   4.532 +	    else
   4.533 +	    {
   4.534 +		noblock(actc);
   4.535 +		syslog(LOG_INFO, "ctl client peer is %s:%u\n",
   4.536 +		       inet_ntoa(from.sin_addr), ntohs(from.sin_port));
   4.537 +	    }
   4.538 +	}
   4.539 +	    
   4.540 +	/* Back to top of loop */
   4.541 +    }
   4.542 +    
   4.543 +    /* We are bailing because one of the primary connections has gone
   4.544 +     * away. We close these all explicitly here because that way the
   4.545 +     * timeout on reusing the port numbers is smnaller. */
   4.546 +    
   4.547 +    close(acth);
   4.548 +    close(actg);
   4.549 +    /* XXX AND: why are we closing all these "character counts" ?? */
   4.550 +    close(gicc);
   4.551 +    close(oicc);
   4.552 +    close(licc);
   4.553 +    close(locc);
   4.554 +    close(hicc);
   4.555 +    close(hocc);
   4.556 +}
   4.557 +
   4.558 +/*
   4.559 + * ------------------------------------------------------------
   4.560 + */
   4.561 +int main(int argc, char **argv)
   4.562 +{
   4.563 +    /* In general, suffix "l" is low channel, "h" is high channel, "g"
   4.564 +     * is gdb channel, "c" is control channel and "o" is output channel.
   4.565 +     */
   4.566 +    struct sockaddr_in		from;
   4.567 +    int				infd = 0, outfd;
   4.568 +    unsigned short		portl, porth, portg, portc, porto;
   4.569 +    int				on = 1, c;
   4.570 +    char			*outname, *outservice;
   4.571 +    int				fromlen;
   4.572 +    int				lish, lisg, lisc;
   4.573 +#if 0
   4.574 +    FILE			*newerr;
   4.575 +#endif /* 0 */
   4.576 +    
   4.577 +    prog_name = argv[0];
   4.578 +
   4.579 +    if (isatty(infd))
   4.580 +	usage();
   4.581 +
   4.582 +    /* Here, then not just a simple idiot. */
   4.583 +
   4.584 +    signal(SIGPIPE, SIG_IGN);
   4.585 +
   4.586 +    openlog(prog_name, LOG_PID, LOG_DAEMON);
   4.587 +
   4.588 +    fromlen = sizeof(from);
   4.589 +    if (getsockname(infd, &from, &fromlen) < 0)
   4.590 +	fault("getsockname: %s", strerror(errno));
   4.591 +    if ((fromlen != sizeof(from)) || (from.sin_family != AF_INET))
   4.592 +	fault("not an inet socket (family=%d)\n", from.sin_family);
   4.593 +    
   4.594 +    portl = ntohs(from.sin_port);
   4.595 +    porth = portl+1;
   4.596 +    portg = porth+1;
   4.597 +    portc = portg+1;
   4.598 +
   4.599 +    fromlen = sizeof(from);
   4.600 +    if (getpeername(infd, &from, &fromlen) < 0)
   4.601 +	fault("getpeername: %s", strerror(errno));
   4.602 +    if ((fromlen != sizeof(from)) || (from.sin_family != AF_INET))
   4.603 +	fault("not an inet socket (family=%d)\n", from.sin_family);
   4.604 +
   4.605 +    syslog(LOG_INFO, "on port %u peer is %s:%u\n", portl,
   4.606 +	   inet_ntoa(from.sin_addr), ntohs(from.sin_port));
   4.607 +    
   4.608 +    if (setsockopt(infd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)
   4.609 +	syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
   4.610 +
   4.611 +    /* from here on, we map stderr to output on the connection so we can
   4.612 +     * report errors to the remote user.
   4.613 +     */
   4.614 +#if 0
   4.615 +    if (!(newerr = fdopen(infd, "w")))
   4.616 +	syslog(LOG_WARNING, "fdopen: %m");
   4.617 +    else
   4.618 +	*stderr = *newerr;
   4.619 +#endif
   4.620 +	
   4.621 +    while((c = getopt(argc, argv, "d8h:g:c:")) != EOF)
   4.622 +    {
   4.623 +	switch(c)
   4.624 +	{
   4.625 +	case 'd':
   4.626 +	    debug++;
   4.627 +	    break;
   4.628 +	    
   4.629 +	case 'h':
   4.630 +	    /* high bit port */
   4.631 +	    if (getservice(optarg, &porth) < 0)
   4.632 +		fault("getservice failed (high port '%s')\n", optarg);
   4.633 +	    break;
   4.634 +	    
   4.635 +	case 'g':
   4.636 +	    /* gdb port */
   4.637 +	    if (getservice(optarg, &portg) < 0)
   4.638 +		fault("getservice failed (gdb port '%s')\n", optarg);
   4.639 +	    break;
   4.640 +
   4.641 +	case 'c':
   4.642 +	    /* control port */
   4.643 +	    if (getservice(optarg, &portc) < 0)
   4.644 +		fault("getservice failed (control port '%s')\n", optarg);
   4.645 +	    break;
   4.646 +
   4.647 +	case '8':
   4.648 +	    /* 8-bit clean; no high port */
   4.649 +	    porth=0;
   4.650 +	    break;
   4.651 +
   4.652 +	default:
   4.653 +	    fault("bad argument list!\n");
   4.654 +	}
   4.655 +    }
   4.656 +    
   4.657 +    if (argc != optind + 1)
   4.658 +	fault("unparsed arguments (%d!=%d)\n", argc, optind+1);
   4.659 +
   4.660 +    outname = argv[optind];
   4.661 +    if (!(outservice = strchr(outname, ':')))
   4.662 +	fault("output arg '%s' doesn't contain ':'\n", outname);
   4.663 +    *outservice++ = 0;
   4.664 +    if (getservice(outservice, &porto) < 0)
   4.665 +	fault("getservice failed (output port '%s')\n", outservice);
   4.666 +    
   4.667 +    /* Time to start the sockets */
   4.668 +
   4.669 +    if (porth) {
   4.670 +	lish  = startlistening(porth);
   4.671 +    } else {
   4.672 +	lish  = -1;
   4.673 +    }
   4.674 +    lisg  = startlistening(portg);
   4.675 +    lisc  = startlistening(portc);
   4.676 +    
   4.677 +    outfd = connect_host(outname, porto);
   4.678 +    
   4.679 +    doit(infd, outfd, lish, lisg, lisc);
   4.680 +
   4.681 +    syslog(LOG_INFO, "terminating normally\n");
   4.682 +
   4.683 +    fclose(stderr);
   4.684 +
   4.685 +    closelog();
   4.686 +    exit(0); 
   4.687 +}
   4.688 +
   4.689 +/* End $Id: nsplitd.c,v 2.6 1998/09/17 14:28:37 sde1000 Exp $ */