SL/IP for ISC

Michael Lodman jml at tw-rnd.SanDiego.NCR.COM
Tue Dec 12 03:41:04 AEST 1989


After numerous mail requests, I decided the easiest thing to do would
be to just post this source for SL/IP.

Disclaimer: I am nothing but a user of this code.

cut here------------------------cut here------------------------cut here
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by John Ioannidis <ji at close> on Wed Oct 18 11:18:41 1989
#
# This archive contains:
#	README		Driver.c	Master		space.c		
#	netd.cf		node.d-slip	sdevice.d-slip	slattach.c	
#
# Modification/access file times will be preserved.
# Error checking via wc(1) will be performed.
# Error checking via sum(1) will be performed.

LANG=""; export LANG
PATH=/bin:/usr/bin:$PATH; export PATH

if sum -r </dev/null >/dev/null 2>&1
then
	sumopt='-r'
else
	sumopt=''
fi

echo x - README
cat >README <<'@EOF'
It is assumed that you more or less know how to install a driver in a
System V machine and rebuild the kernel. The instructions here are for
Interactive's 386/ix -- your milage may vary.

* create /etc/conf/pack.d/slip/. Copy Driver.c and space.c there. 
  Compile Driver.c (cc -c Driver.c) and leave space.c intact.

* Put the following line in a /etc/conf/sdevice.d/slip
----------------------cut-here-------------------------
slip	Y	1	0	0	0	0	0	0	0
----------------------cut-here-------------------------

* Put the following two lines in /etc/conf/node.d/slip
----------------------cut-here-------------------------
slip	slip		c	0
slip	sliplisten	c	1
----------------------cut-here-------------------------

* Put the folloing line in a file called Master in /tmp (or in
/etc/conf/pack.d/slip) and run /etc/conf/bin/idinstall -a -m -k slip
on it.
----------------------cut-here-------------------------
slip	-	iSco		slip	0	0	0	32	-1
----------------------cut-here-------------------------
This will install it in /etc/conf/cf.d/mdevice.

Now run kconfig; this is by far the easiest way of reconfiguring a
kernel. Just select '2' (configure a new kernel), followed by a few
yes'es. If all goes well, it should build a new kernel, and when you
reboot, create /dev/slip and /dev/sliplisten in /dev. 

Now you have to change /etc/netd.cf. Edit the one provided here.
What we are doing is we are linking /dev/slip right under /dev/ip, the
same way /dev/lo and /dev/arp are linked.

Finally, compile slattach.c, connect your machine to another machine
that groks slip, and fire up netd and slattach.

Network services, pinging and gatewaying should all work. If you want
to turn on debugging, run slattach with the environment variable
DEBUGSLIP set to 1 (for debugging the STREAMS module), 2 (for
debugging slattach) or 3 (for debugging both). Setting it to zero will
disable both. 

Things I haven't done:

* Change the MTU from 576 to something more reasonable (like 1500)
* Set the POINTOPOINT flag in the if structure (I have yet to figure
out how to do that in a clean way)
* Implement the DLGSTAT ioctl so that netstat -i will work properly.
* Clean up the code; it contains too many debugging hooks right now.
* ...

This is not the cleanest code I have ever written, but until last
month I had never even used a System-V machine, let alone written a
STREAMS device driver for it. The driver itself took me less than a
week to write, in case it matters. I could have banged on the driver
for another week and then released a cleaner version, but I think that
a lot of people want SLIP for their machines and releasing it now will
enable me to have it tested on a variety of platforms and have it
debugged faster. 

In case you need to reach me, you can send me e-mail at
ji at cs.columbia.edu (but you already know that). This is by far the
easiest way to get in touch with me. If you feel like calling me, my
phone number is (212) 854-5510, and I'm there from noon to the wee
hours in the morning (but not continuously!)

Finally, if you are, or know of, a good Un*x kernel hacker who wants
to work for 12-18 months on a REALLY exciting project, drop me a line.

/ji

@EOF
set `sum $sumopt <README`; if test $1 -ne 2293
then
	echo ERROR: README checksum is $1 should be 2293
fi
set `wc -lwc <README`
if test $1$2$3 != 735223172
then
	echo ERROR: wc results of README are $* should be 73 522 3172
fi

touch -m 1018002989 README
touch -a 1018111389 README
chmod 666 README

echo x - Driver.c
cat >Driver.c <<'@EOF'
/*
 * SLIP driver for 386/ix 
 * 
 * Copyright (C) 1989 by John Ioannidis, ji at cs.columbia.edu
 *
 * Permission is granted to use, modify and copy this code
 * provided you don't make a profit out of it and that you
 * keep the copyright notice intact.
 */

#include "sys/types.h"
#include "sys/param.h"
#include "sys/sysmacros.h"

#include "sys/stream.h"
#include "sys/stropts.h"
#include "sys/dir.h"
#include "sys/signal.h"
#include "sys/user.h"
#include "sys/errno.h"

#include "sys/lihdr.h"
#include "sys/socket.h"
#include "netinet/in_systm.h"
#include "netinet/in.h"
#include "netinet/ip.h"
#include "net/if.h"

static struct module_info minfo = 
{
	0, "slip", 0, INFPSZ, 512, 128
};

static int slipopen(), slipclose(), slipwput(), slipwsrv(), sliprsrv();

static struct qinit rinit = 
{
	NULL, sliprsrv, slipopen, slipclose, NULL, &minfo, NULL
};

static struct qinit winit = 
{
	slipwput, slipwsrv, NULL, NULL, NULL, &minfo, NULL
};

struct streamtab slipinfo = { &rinit, &winit, NULL, NULL };

struct slip
{
	short boundp;
	short slipd;
	queue_t *oqptr;
};

extern struct slip slip_slip[];
extern int slip_cnt;

#define SETDEBUG (('J'<<8) | 1)
static int slipdebug=0;

static int slipopen(q, dev, flag, sflag)
queue_t *q;
{
	struct slip *slip;

	/*
	 * If CLONEOPEN, return an error. We are only supposed
	 * to be called from the networking code as minor 0
	 * and from the user-level loopback as minor 1.
	 */

#ifdef DEBUGSLIP
	if (slipdebug)
	  printf("slipopen(0x%x, %d, 0%o, 0%o)\n", q, dev, flag, sflag);
#endif
	if (sflag == CLONEOPEN)
	  return OPENFAIL;
	if (q->q_ptr)
	{
#ifdef DEBUGSLIP
		if (slipdebug)
		  printf("slipopen: attempted reopen slip/%d\n", dev);
#endif
		return OPENFAIL;
	}

	switch (minor(dev))
	{
	      case 1:			/* user side */
		slip = &slip_slip[1];
		q->q_ptr = (caddr_t) slip;
		WR(q)->q_ptr = (caddr_t) slip;
		slip_slip[0].oqptr = q;
		slip->slipd = 1;
		slip->boundp = 0;
		
		return 1;
		break;
		
	      case 0:
		slip = &slip_slip[0];
		q->q_ptr = (caddr_t) slip;
		WR(q)->q_ptr = (caddr_t) slip;
		slip_slip[1].oqptr = q;
		slip->slipd = 0;
		slip->boundp = 0;
		return 0;
		break;
		
	      default:
#ifdef DEBUGSLIP
		if (slipdebug)
		  printf("slipopen: bad minor device slip/%d\n", dev);
#endif
		return OPENFAIL;
	}
	/*NOTREACHED*/
}

/*
 * the write-side put proc. This is where we handle all the
 * requests from the /dev/ip driver. Look up the document for
 * DLI for explanations.
 */

static int 
slipwput(q, mp)
queue_t *q;
mblk_t *mp;
{
	struct ifnet *myif;
	mblk_t *mpc;
	extern struct ifnet *ifnet;
	int i;
	
	
	register struct slip *slip;

	slip = (struct slip*)q->q_ptr;	/* recover our private d/s */

	switch (mp->b_datap->db_type)
	{
	      case M_PROTO:
	      case M_PCPROTO:
	      {
		      
		      register union DL_primitives *lir;
		      
		      lir = (union DL_primitives *)mp->b_rptr;
		      
		      switch (lir->prim_type)
		      {
			    case DL_BIND_REQ:
#ifdef DEBUGSLIP
			      if (slipdebug)
				printf("slipwput%d: DL_BIND_REQ: sap=%x\n",
				       slip->slipd, lir->bind_req.LLC_sap);
#endif
			      mp->b_datap->db_type = M_PCPROTO;
			      lir->bind_ack.PRIM_type = DL_BIND_ACK;
			      /* lir->bind_ack.LLC_sap = 0; */
			      lir->bind_ack.ADDR_length = 0;
			      lir->bind_ack.ADDR_offset = 0;
			      lir->bind_ack.GROWTH_field[0] = 0x1234;
			      lir->bind_ack.GROWTH_field[1] = 0x5678;
			      
			      mp->b_wptr = mp->b_rptr + DL_BIND_ACK_SIZE;
			      
			      qreply(q, mp);
			      break;

			    case DL_UNBIND_REQ:
#ifdef DEBUGSLIP
			      if (slipdebug)
				printf("slipwput%d: DL_UNBIND_REQ\n", slip->slipd);
#endif
			      mp->b_datap->db_type = M_PCPROTO;
			      lir->ok_ack.PRIM_type = DL_OK_ACK;
			      lir->ok_ack.CORRECT_prim = DL_UNBIND_REQ;
			      mp->b_wptr = mp->b_rptr + DL_OK_ACK_SIZE;
			      
			      qreply(q, mp);
			      break;
			      
			    case DL_INFO_REQ:
#ifdef DEBUGSLIP
			      if (slipdebug)
				printf("slipwput%d: DL_INFO_REQ\n", slip->slipd);
#endif
			      mp->b_datap->db_type = M_PCPROTO;
			      lir->info_ack.PRIM_type = DL_INFO_ACK;
			      lir->info_ack.SDU_max = 1024;
			      lir->info_ack.SDU_min = sizeof(struct ip);
			      lir->info_ack.ADDR_length = 0;
			      lir->info_ack.SUBNET_type = 0;
			      lir->info_ack.SERV_class = 0;
			      lir->info_ack.CURRENT_state = DL_IDLE;
			      
			      mp->b_wptr = mp->b_rptr + DL_INFO_ACK_SIZE;
			      
			      qreply(q, mp);
			      break;
			      
			    case DL_UNITDATA_REQ:
#ifdef DEBUGSLIP
			      if (slipdebug)
			      {
				      printf("slipwput%d: DL_UNITDATA_REQ: len=%d off=%d sclass=%d filler=%d :", slip->slipd, lir->data_req.RA_length, lir->data_req.RA_offset, lir->data_req.SERV_class, lir->data_req.FILLER_field);
				      for (i=lir->data_req.RA_offset; i<lir->data_req.RA_offset + lir->data_req.RA_length; i++)
					printf("%d:", ((char *)&(lir->data_req))[i]);
				      printf("\n");
			      }
#endif
			      if (mp->b_cont)
			      {
#ifdef DEBUGSLIP
				      if (slipdebug)
					printf("slipwput%d: putting cont msg to the Q\n", slip->slipd);
#endif
				      putq(q, mp->b_cont);
			      }
			      else
			      {
				      printf("slipwput: DL_UNITDATA_REQ: error! no continuation message!\n");
				      freemsg(mp);
			      }
			      break;
			      
			    default:
			      printf("slipwput%d: prim_type=0%o, putting in Q\n", slip->slipd, lir->prim_type);
			      
			      putq(q, mp);
			      
		      }
	      }
	      break;

	    case M_IOCTL:
	    {
		      struct iocblk *iocp;
		      int error;
		      
		      iocp = (struct iocblk *)mp->b_rptr;
		      switch (iocp->ioc_cmd)
		      {
#ifdef DEBUGSLIP
			    case SETDEBUG:
			      if (iocp->ioc_count != sizeof(int))
				goto iocnak;
			      slipdebug = *(int *)mp->b_cont->b_rptr;
			      mp->b_datap->db_type = M_IOCACK;
			      iocp->ioc_count = 0;
			      qreply(q, mp);
			      break;
#endif
			      
			    default:
			    iocnak:
			      
			      error = EINVAL;
#ifdef DEBUGSLIP
			      if (slipdebug)
				printf("slipwput%d: M_IOCTL: bad ioctl %x\n",
				     slip->slipd, iocp->ioc_cmd);
#endif
			      mp->b_datap->db_type = M_IOCNAK;
			      iocp->ioc_error = error;
			      qreply(q, mp);
		      }
		      break;
	      }

	    case M_FLUSH:
#ifdef DEBUGSLIP
	      if (slipdebug)
		printf("slipwput%d: M_FLUSH: flushing\n", slip->slipd);
#endif
	      if (*mp->b_rptr & FLUSHW)
		flushq(q, 0);
	      if (*mp->b_rptr & FLUSHR)
	      {
		      flushq(RD(q), 0);
		      *mp->b_rptr &= ~FLUSHW;
		      qreply(q, mp);
	      }
	      else
		freemsg(mp);
	      break;

	    case M_DATA:
	    {
		    
		    register union DL_primitives *lir;

#ifdef DEBUGSLIP
		    if (slipdebug)
		      printf("slipwput%d: M_DATA message\n", slip->slipd);
#endif
		    /*
		     * the only way we can get here is by having the
		     * user process pump us a datagram. Create a 
		     * contol part and send up a DL_UNITDATA_IND 
		     * message.
		     */
		    
		    mpc = allocb(DL_UNITDATA_IND_SIZE + 12, BPRI_MED);
		    if (mpc == NULL)
		    {
			    printf("slipwput%d: M_DATA: can't allocb control msgs\n",
				   slip->slipd);
			    return;
		    }
		    mpc->b_datap->db_type = M_PCPROTO;
		    lir = (union DL_primitives *)mpc->b_wptr;
		    lir->data_ind.PRIM_type = DL_UNITDATA_IND;
		    lir->data_ind.RA_length = lir->data_ind.LA_length = 6;
		    lir->data_ind.RA_offset = DL_UNITDATA_IND_SIZE;
		    lir->data_ind.LA_offset = DL_UNITDATA_IND_SIZE + 6;
		    lir->data_ind.SERV_class = 0;
		    mpc->b_wptr[DL_UNITDATA_IND_SIZE+0] = 0x7e;
		    mpc->b_wptr[DL_UNITDATA_IND_SIZE+1] = 0x00;
		    mpc->b_wptr[DL_UNITDATA_IND_SIZE+2] = 0x00;
		    mpc->b_wptr[DL_UNITDATA_IND_SIZE+3] = 0x02;
		    mpc->b_wptr[DL_UNITDATA_IND_SIZE+4] = 0x02;
		    mpc->b_wptr[DL_UNITDATA_IND_SIZE+5] = 0x00;
		    mpc->b_wptr[DL_UNITDATA_IND_SIZE+6] = 0x7e;
		    mpc->b_wptr[DL_UNITDATA_IND_SIZE+7] = 0x00;
		    mpc->b_wptr[DL_UNITDATA_IND_SIZE+8] = 0x00;
		    mpc->b_wptr[DL_UNITDATA_IND_SIZE+9] = 0x01;
		    mpc->b_wptr[DL_UNITDATA_IND_SIZE+10] = 0x02;
		    mpc->b_wptr[DL_UNITDATA_IND_SIZE+11] = 0x00;
		    mpc->b_wptr += DL_UNITDATA_IND_SIZE + 12;
		    mpc->b_cont = mp;
		    /* putq(q, mpc); */
		    putnext(slip->oqptr, mpc);
		    break;
	    }
	      
	    default:
	      /*
	       * if this stream isn't connected, send an M_ERROR upstream
	       */
	      if (slip->oqptr == NULL)
	      {
		      putctl1(RD(q)->q_next, M_ERROR, ENXIO);
		      freemsg(mp);
		      break;
	      }
#ifdef DEBUGSLIP
	      if (slipdebug)
		printf("slipwput%d: DEFAULT (data?) message\n", slip->slipd);
#endif
	      putq(q, mp);
      }
}


					    
static int slipwsrv(q)
register queue_t *q;
{
	mblk_t *mp;
	
	register struct slip *slip;
	
	slip = (struct slip *)q->q_ptr;

#ifdef DEBUGSLIP
	if (slipdebug)
	  printf("slipwsrv%d: called!\n", slip->slipd);
#endif
	
	while ((mp = getq(q)) != NULL)
	{
		/*
		 * Check is we can put the message up the other
		 * stream's read queue
		 */

		if (mp->b_datap->db_type <= QPCTL &&
		    !canput(slip->oqptr->q_next))
		{
#ifdef DEBUGSLIP
			if (slipdebug)
			  printf("slipwsrv%d: blocked, putting back\n",slip->slipd);
#endif
			putbq(q, mp);
			break;
		}
#ifdef DEBUGSLIP
		if (slipdebug)
		  printf("slipwsrv%d: pulled sth from the Q, sending...\n",
		       slip->slipd);
#endif
		putnext(slip->oqptr, mp);
	}
}

static int sliprsrv(q)
queue_t *q;
{
	/*
	 * enter only when "back enabled" by flow control
	 */

	struct slip *slip;
	
#ifdef DEBUGSLIP
	if (slipdebug)
	  printf("sliprsrv%d: called!\n", slip->slipd);
#endif

	slip = (struct slip *)q->q_ptr;
	if (slip->oqptr == NULL)
	  return;
	
	/* manually enable write service procedure */
	qenable(WR(slip->oqptr));
}

static int slipclose(q)
queue_t *q;
{
	register struct slip *slip;
	
	slip = (struct slip *)q->q_ptr;
	slip->boundp = NULL;
	
#ifdef DEBUGSLIP
	if (slipdebug)
	  printf("slipclose%d: called!\n", slip->slipd);
#endif
}

#ifdef notdef	   
	   
			      for (myif=ifnet; myif; myif = myif->if_next)
			      {
#ifdef DEBUGSLIP
				      printf("slipwput: found %s\n", myif->if_name);
#endif
				      if (myif->if_name && !(strcmp(myif->if_name, "slip0")))
				      {
					      myif->if_flags |= IFF_POINTOPOINT;
					      break;
				      }
			      }
			      
			      
#endif




@EOF
set `sum $sumopt <Driver.c`; if test $1 -ne 47282
then
	echo ERROR: Driver.c checksum is $1 should be 47282
fi
set `wc -lwc <Driver.c`
if test $1$2$3 != 454106010378
then
	echo ERROR: wc results of Driver.c are $* should be 454 1060 10378
fi

touch -m 1018002989 Driver.c
touch -a 1018111389 Driver.c
chmod 666 Driver.c

echo x - Master
cat >Master <<'@EOF'
slip	-	iSco		slip	0	0	0	32	-1
@EOF
set `sum $sumopt <Master`; if test $1 -ne 53130
then
	echo ERROR: Master checksum is $1 should be 53130
fi
set `wc -lwc <Master`
if test $1$2$3 != 1930
then
	echo ERROR: wc results of Master are $* should be 1 9 30
fi

touch -m 1018002989 Master
touch -a 1018111389 Master
chmod 666 Master

echo x - space.c
cat >space.c <<'@EOF'
/*
 * SLIP driver for 386/ix 
 * 
 * Copyright (C) 1989 by John Ioannidis, ji at cs.columbia.edu
 *
 * Permission is granted to use, modify and copy this code
 * provided you don't make a profit out of it and that you
 * keep the copyright notice intact.
 */

#include "sys/types.h"
#include "sys/param.h"
#include "sys/sysmacros.h"

#include "sys/stream.h"
#include "sys/stropts.h"
#include "sys/dir.h"
#include "sys/signal.h"
#include "sys/user.h"
#include "sys/errno.h"

#include "config.h"

struct slip
{
	short openp;
	short slipd;
	queue_t *oqptr;
};

struct slip slip_slip[SLIP_MAXSUB];
int slip_cnt = SLIP_MAXSUB;



@EOF
set `sum $sumopt <space.c`; if test $1 -ne 25856
then
	echo ERROR: space.c checksum is $1 should be 25856
fi
set `wc -lwc <space.c`
if test $1$2$3 != 3584622
then
	echo ERROR: wc results of space.c are $* should be 35 84 622
fi

touch -m 1018002989 space.c
touch -a 1018111489 space.c
chmod 666 space.c

echo x - netd.cf
cat >netd.cf <<'@EOF'
#	@(#)netd.cf	1.4 - 88/11/15
#
# This is a configuration file for host-based
# TCP/IP using the wd ethernet interface
#

# open control streams for transport protocols
tcp = "/dev/tcp"
udp = "/dev/udp"

# open an IP stream for each transport protocol
ip_tcp = "/dev/ip" nsap 6       # bind stream to TCP protocol id
ip_udp = "/dev/ip" nsap 17       # bind stream to UDP protocol id

# open ARP for ethernet use
arp    = "/dev/arp" lsap 0x800

# open link level devices
wd_arp = "/dev/wd" lsap 0x806   # stream for ARP messages
wd_ip  = "/dev/wd" lsap 0x800   # stream for IP messages
loop   = "/dev/lo" lsap 0x800	# stream for loopback driver
loslip   = "/dev/slip" lsap 0x800	# ji's sample driver

# put it together
link ip_tcp under tcp
link ip_udp under udp

# names must not assume a unit number so use as part of name
link loop under ip_tcp name "lo0"
link arp under ip_tcp name "wd0"
link loslip under ip_tcp name "slip0"
link wd_arp under arp type 0x101
link wd_ip under arp type 0x1


# initial configuration of interfaces
ifconfig "wd0" toshiba1 up
ifconfig "lo0" localhost up
ifconfig "slip0" 126.0.0.1 126.0.0.2 up
@EOF
set `sum $sumopt <netd.cf`; if test $1 -ne 27466
then
	echo ERROR: netd.cf checksum is $1 should be 27466
fi
set `wc -lwc <netd.cf`
if test $1$2$3 != 391971126
then
	echo ERROR: wc results of netd.cf are $* should be 39 197 1126
fi

touch -m 1018002989 netd.cf
touch -a 1018111489 netd.cf
chmod 666 netd.cf

echo x - node.d-slip
cat >node.d-slip <<'@EOF'
slip	slip		c	0
slip	sliplisten	c	1
@EOF
set `sum $sumopt <node.d-slip`; if test $1 -ne 26127
then
	echo ERROR: node.d-slip checksum is $1 should be 26127
fi
set `wc -lwc <node.d-slip`
if test $1$2$3 != 2835
then
	echo ERROR: wc results of node.d-slip are $* should be 2 8 35
fi

touch -m 1018002989 node.d-slip
touch -a 1018111489 node.d-slip
chmod 666 node.d-slip

echo x - sdevice.d-slip
cat >sdevice.d-slip <<'@EOF'
slip	Y	1	0	0	0	0	0	0	0
@EOF
set `sum $sumopt <sdevice.d-slip`; if test $1 -ne 31828
then
	echo ERROR: sdevice.d-slip checksum is $1 should be 31828
fi
set `wc -lwc <sdevice.d-slip`
if test $1$2$3 != 11023
then
	echo ERROR: wc results of sdevice.d-slip are $* should be 1 10 23
fi

touch -m 1018002989 sdevice.d-slip
touch -a 1018111489 sdevice.d-slip
chmod 666 sdevice.d-slip

echo x - slattach.c
cat >slattach.c <<'@EOF'
#include <sys/types.h>
#include <sys/stropts.h>
#include <sys/lihdr.h>
#include <stdio.h>
#include <ctype.h>
#include <termio.h>

#define isdot(_x)  (((_x)&0x80)|!(isprint(_x)))

#define SLIPEND (0300)
#define SLIPESC (0333)
#define SLIPESC_END (0334)
#define SLIPESC_ESC (0335)

#define SETDEBUG (('J'<<8) | 1)
	
main(argc, argv)
int argc;
char **argv;
{
	int fd, tfd, nr, debugfl;
	int flags, retval, i, inescape, debugon;
	unsigned char ibuf[2048], obuf[2048];
	unsigned char *ib, *ob;
	char *ev;

	struct termio tio;
	struct strbuf ctlptr, dataptr;
	struct strioctl sctl;
	struct DL_unitdata_ind rply;
	
	tfd = open("/dev/tty00", 2);
	if (tfd < 0)
	  perror("/dev/tty00"), exit();
	
	tio.c_iflag = 0;
	tio.c_oflag = 0;
	tio.c_cflag = B9600 | CS8 | CREAD;
	tio.c_lflag = 0;
	tio.c_cc[VMIN] = 1;
	tio.c_cc[VTIME] = 0;
	
	if (ioctl(tfd, TCSETA, &tio) < 0)
	  perror("ioctl"), exit();

	fd = open("/dev/sliplisten", 2);
	if (fd < 0)
	  perror("/dev/sliplisten:"), exit();
	
	if (ev = (char *)getenv("DEBUGSLIP"))
	{
		debugfl = atoi(ev);
		debugon = debugfl & 2;
		debugfl &= 1;
		sctl.ic_cmd = SETDEBUG;
		sctl.ic_timout = 0;
		sctl.ic_dp = (char *)&debugfl;
		sctl.ic_len = 4;
		if (ioctl(fd, I_STR, &sctl) < 0)
		  perror("SETDEBUG");
		
	}
	
	if (fork())
	{
		printf("sliplisten: reader: starting up\n");

		ob = obuf;

		for(;;)
		{
			nr = read(tfd, ibuf,2048);
			write(1, ".", 1);
			inescape = 0;
			
			if (nr <= 0)
			  perror("reading from tty"), exit();
			ib = ibuf;

			for (i=0; i<nr; i++)
			{
				*ob = *ib++;
				
				if (!inescape)
				{
					
					if (*ob == SLIPESC)
					{
						if (debugon)
						  printf("reader: ESC\n");
						inescape = 1;
						continue;
					}
					else if (*ob == SLIPEND)
					{
						if (debugon)
						  printf("reader: END\n");
						dataptr.buf = (char *)obuf;
						dataptr.len = ob - obuf;
						ob = obuf;
						
						if (dataptr.len > 0)
						{
							if (debugon)
							  xdump(dataptr.buf, dataptr.len, "sending to IP");
							if (putmsg(fd, NULL, &dataptr, 0) 
							    < 0)
							  perror("reader: putmsg");
						}
						
						continue;
					}
					else
					{
						ob++;
						inescape = 0;
					}
				}
				else
				{
					if (*ob == SLIPESC_END)
					  *ob++ = SLIPEND;
					else if (*ob == SLIPESC_ESC)
					  *ob++ = SLIPESC;
					else
					  ob++;
				}
				
			}
		}
	}
	else				/* CHILD */
	{
		printf("sliplisten: writer: starting up\n");
		for(;;)
		{
			dataptr.maxlen = 2048;
			dataptr.len = 0;
			dataptr.buf = (char *)ibuf;
			flags = 0;
			
			if ((retval = getmsg(fd, NULL, &dataptr, &flags))
			    < 0)
			{
				perror("getmsg");
				continue;
			}
			write(1, "+", 1);
			
			if (dataptr.len > 0)
			{
				ib = ibuf;
				ob = obuf;
				*ob++ = SLIPEND;
				
				for (i=0; i<dataptr.len; i++)
				{
					if (*ib == SLIPEND)
					{
						*ob++ = SLIPESC;
						*ob++ = SLIPESC_END;
						ib++;
					}
					else if (*ib == SLIPESC)
					{
						*ob++ = SLIPESC;
						*ob++ = SLIPESC_ESC;
						ib++;
					}
					else
					  *ob++ = *ib++;
				}
				*ob++ = SLIPEND;
				if (debugon)
				  xdump(obuf, ob-obuf, "sending to SLIP");

				
				write(tfd, obuf, ob-obuf);
				
			}
		}
	}
}
		
/*
 * NAME
 *	xdump -- make a hex dump of a region in memory
 *
 * SYNOPSIS
 *	xdump(base, length, title)
 *	caddr_t base;
 *	int length;
 *	char *title;
 */
	
static char line[80];
static char hd[17]="0123456789ABCDEF";

#define HI(_x)  (hd[((_x)>>4)&0xF])
#define LO(_x)  (hd[(_x)&0xF])

xdump(base, length, title)
caddr_t base;
int length;
char *title;
{
	register char *bp, *hp, *cp;
	register int cnt;

	printf("%s\n", title);
	
	bp = base;

	hp = line;
	cp = line+50;
	
	for (cnt=80; cnt; line[--cnt]=' ')
	  ;

	line[49] = line[66] = '*';
	line[67] = '\0';

	while(length-- > 0)
	{
		*hp++ = HI(*bp);
		*hp++ = LO(*bp);
		hp++;
		*cp++ = isdot(*bp)?'.':(*bp);
		bp++;

		if (++cnt == 16)
		{
			cnt = 0;
			hp = line;
			cp = line+50;
			puts(line);
		}
	}

	if (cnt)
	{
		while (cnt++ < 16)
		{
			*hp++=' ';
			*hp++=' ';
			*hp++=' ';
			*cp++=' ';
		}
		puts(line);
	}

	return 0;
}
@EOF
set `sum $sumopt <slattach.c`; if test $1 -ne 6126
then
	echo ERROR: slattach.c checksum is $1 should be 6126
fi
set `wc -lwc <slattach.c`
if test $1$2$3 != 2535454072
then
	echo ERROR: wc results of slattach.c are $* should be 253 545 4072
fi

touch -m 1018111689 slattach.c
touch -a 1018111589 slattach.c
chmod 666 slattach.c

exit 0

-- 
+-----------------------------------------------------------+
| Michael Lodman               Mike.Lodman at SanDiego.NCR.COM |
| NCR Corporation  -  Distributed Systems Lab  -  San Diego |
| 9900 Old Grove Rd.  San Diego, CA.  92131  (619) 693-5353 |
+-----------------------------------------------------------+



More information about the Comp.unix.i386 mailing list