SLIP driver source for ix/386
Michael Haberler
mah at nestroy.wu-wien.ac.at
Sun Mar 3 20:47:22 AEST 1991
This has come up a couple of times although there's a SLIP implementation in
ix/386 2.2. I've used it, and it works. Nevertheless I was interested in
source because it would make it easier to start a PPP or Compressed SLIP
implementation.
This is what I've got. It's interesting insofar as IP packets are fed to a
userland process which does the SLIP encoding (actually 2 processes, one for
the read and one for the write side). Thus, it shouldnt be too hard to take
an existing PPP code and retrofit it into this code. I've looked into
this, but I dont have the time right now, so maybe somebody else wants to
jump into this :-)
This works on 2.2; netstat -i is broken with it, though.
- michael
Minor question: What's the proper name and place to order Sys5.3 Streams
Device Driver manuals? Do the cost a fortune?
# 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 |
+-----------------------------------------------------------+
--
Conor P. Cahill (703)430-9247 Virtual Technologies, Inc.,
uunet!virtech!cpcahil 46030 Manekin Plaza, Suite 160
Sterling, VA 22170
--
Michael Haberler mah at nestroy.wu-wien.ac.at, mah at awiwuw11.bitnet
University of Economics and Business Administration
Augasse 2-6, A-1090 Vienna, Austria
Tel: +43 (222) 313-36 x4796 (9-18 CET) Fax 347-555
More information about the Comp.unix.sysv386
mailing list