[comp.sources.misc] uupc.dcp.8.3

Stuart.Lynne@van-bc.UUCP (Stuart Lynne) (08/17/87)

>From uucp Wed Aug 12 02:36 PDT 1987
>From slynne  Wed Aug 12 02:35:56 1987 remote from slmac
Received: by van-bc.uucp (smail2.3)
	id AA17550; 12 Aug 87 02:35:56 PDT (Wed)
Received: by slmac.vnet.van-bc.uucp (pcmail) Wed Aug 12 02:36:17 1987
Date: Wed Aug 12 02:36:17 1987
From: Stuart Lynne - test a mac <slynne@slmac.vnet.van-bc.uucp>
Message-ID: <147@slmac.vnet.van-bc.uucp>
To: sl@van-bc
Subject: shar/uupc.dcp.8.3

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	dcp.c
#	dcp.h
#	dcpgpkt.c
#	dcpsys.c
#	dcpxfer.c
# This archive created: Wed Aug 12 02:01:59 1987
# By:	Stuart Lynne - test a mac ()
export PATH; PATH=/bin:$PATH
if test -f 'dcp.c'
then
       echo shar: will not over-write existing file "'dcp.c'"
else
cat << \SHAR_EOF > 'dcp.c'
/*			dcp.c

			Revised edition of dcp

			Stuart Lynne May/87

			Copyright (c) Richard H. Lamb 1985, 1986, 1987
			Changes Copyright (c) Stuart Lynne 1987

*/
/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
/* This program implements a uucico type file transfer and remote
execution type protocol.
*/
#include "dcp.h"
/**/
int	pktsize;                	/* packet size for pro */
FILE	*logfile;            	/* system log file */
FILE	*syslog;            	/* system log file */
FILE	*fw;                 	/* cfile pointer */
char	state;					/* system state*/
char	cfile[80];              /* work file pointer */
int		remote;                 /* -1 means we're remote ..7*/
int		msgtime;                /* timout setting */
char	fromfile[132];
char	hostfile[132];		/* host version of fromfile */
char	tofile[132];
int		fp;                     /* current disk file ptr */
int		size;                   /* nbytes in buff */
FILE	*fsys;
char	Rmtname[20];
char	rmtname[20];
char	* cctime;
char	proto[5];
/* char	loginseq[256]; */
char 	sysline[BUFSIZ];
char	s_systems[64];
char	s_logfile[64];
char	s_syslog[64];
char 	*flds[60];
int 	kflds;
int		debuglevel;		/* debugging flag */

unsigned int	checksum();


/**/
/* new usage

	dcp	[-xn] -r0		slave mode
	dcp	[-xn] -shost 		call host
	dcp	[-xn] -sall		call all hosts

	dcp	[-xn] 		call any hosts as required by C. files

*/

complain( s )
char *s;
{
	fprintf( stderr, "Please set your %s environment variable.", s );
}

static void cant( file )
char *file;
{
	fprintf( stderr, "Can't open: \"%s\"\n", file );
	exit( NULL );
}

dcpmain( argc, argv )
int	argc;
char*argv[];
{
	FILE	*ftmp;
	char	line[132];

	if ( name == NULL || *name == '\0' ) {
		complain( NAME );
		exit( -1 );
	}
	if ( nodename == NULL || *nodename == '\0' ) {
		complain( NODENAME );
		exit( -1 );
	}


	mkfilename( s_logfile, spooldir, LOGFILE );
	mkfilename( s_syslog,  spooldir, SYSLOG  );
	mkfilename( s_systems, confdir,  SYSTEMS );

	if ( (logfile = FOPEN( s_logfile, "a", 't' )) == NULL )
	   cant( s_logfile );
	if ( (syslog  = FOPEN( s_syslog,  "a", 't' )) == NULL )
	   cant( s_syslog );

	remote = MASTER;
	debuglevel = 1;
	fp = -1;
	fw = (char *)NULL;


	remote = MASTER;
	strcpy( Rmtname, "any" );

	while ( --argc ) {
		if ( **++argv == '-') {
			switch(argv[0][1]) {
			case 'x':
				debuglevel = atoi( &argv[0][2] );
				break;
			case 's':
				sprintf( Rmtname, "%.7s", &argv[0][2] );
				break;
			case 'r':
				remote = atoi( &argv[0][2] );
				break;

			default:
				break;
			}
		}
	}


	if ( remote == MASTER ) {
 		printmsg( 0, "Calling %s, debuglevel=%d", Rmtname, debuglevel );
		if (( fsys = FOPEN( s_systems, "r", 't' )) == (char *)NULL )
			exit( FAILED );
		state = 'I';


		while (TRUE) {
			printmsg( 4, "Mstate = %c", state );
			switch (state) {
			case 'I':
				state = getsystem();
				break;
			case 'S':
				state = callup();
				break;
			case 'P':
				state = startup();
				break;
			case 'D':
				state = master();
				break;
			case 'Y':
				state = sysend();
				break;
			case 'G':
				if ( strcmp( Rmtname, "any" ) != SAME )
					state = 'Y';
				else
					state = 'I';
				break;
			}
			if (state == 'A')
				break;
		}
		fclose( fsys );
	} else
	 {
		if (openline( device, speed ) == -1)
			return(FALSE);
		state = 'L';
		while (TRUE) {
			printmsg( 4, "Sstate = %c", state );
			switch (state) {
			case 'L':
				state = login();
				break;
			case 'I':
				state = startup();
				break;
			case 'R':
				state = slave();
				break;
			case 'Y':
				state = sysend();
				break;
			}
			if (state == 'A')
				break;
		}
		closeline();
	}

	/* fprintf( stderr, "calling dcxqt\n" ); */
	if (dcxqt())
		printmsg( 0, "ERROR in DCXQT" );

	/* scan and process any recieved files */

	fclose( syslog );
	fclose( logfile );
	return 0;
}


/**/
/*
**
**
**master
**
**
*/
master()
{
	state = 'I';
	while (TRUE) {
		printmsg( 4, "Top level state (master mode) %c", state );
		switch (state) {
		case 'I':
			state = sinit();
			break;
		case 'B':
			state = scandir();
			break;
		case 'S':
			state = send();
			break;
		case 'Q':
			state = sbreak();
			break;
		case 'G':
			state = receive();
			break;
		case 'C':
			state = 'Y';
			break;
		case 'Y':
			state = endp();
			break;
		case 'P':
			return('Y');
		case 'A':
			return('A');
		default:
			return('A');
		}
	}
}


/**/
/*
**
**
**slave
**
**
*/
slave()
{
	state = 'I';
	while (TRUE) {
		printmsg( 4, "Top level state (slave mode) %c", state );
		switch (state) {
		case 'I':
			state = rinit();
			break;
		case 'F':
			state = receive();
			break;
		case 'C':
			state = schkdir();
			break;
		case 'T':
			state = 'B';
			break;
		case 'B':
			state = scandir();
			break;
		case 'S':
			state = send();
			break;
		case 'Q':
			state = sbreak();
			break;
		case 'G':
			return('Y');
		case 'Y':
			state = endp();
			break;
		case 'P':
			return('Y');
		case 'A':
			return('A');
		default:
			return('A');
		}
	}
}


/**/
/*
 *  r e c e i v e
 *
 *  This is the state table switcher for receiving files.
 */

receive()
{

	state = 'F';/* Receive-Init is the start state */

	while (TRUE) {
		printmsg( 4, " receive state: %c", state );
		switch (state)/* Do until done */ {
		case 'F':
			state = rfile();
			break; /* Receive-File */
		case 'D':
			state = rdata();
			break; /* Receive-Data */
		case 'C':
			return('C');/* Complete state */
		case 'A':
			return('Y');/* "Abort" state */
		default:
			return('Y');
		}
	}
}


/**/
/*
 *  s e n d
 *
 *  Sendsw is the state table switcher for sending files.  It loops until
 *  either it finishes, or an error is encountered.  The routines called
 *  by sendsw are responsible for changing the state.
 *
 */
send()
{
	fp = -1;                /* reset file getter/opener */
	state = 'F';/* Send initiate is the start state */
	while (TRUE)/* Do this as long as necessary */ {
		printmsg( 4, "send state: %c", state );
		switch (state) {
		case 'F':
			state = sfile();
			break; /* Send-File */
		case 'D':
			state = sdata();
			break; /* Send-Data */
		case 'Z':
			state = seof();
			break; /* Send-End-of-File */
		case 'B':
			return ('B'); /* Complete */
		case 'A':
			return ('Y'); /* "Abort" */
		default:
			return ('Y'); /* Unknown, fail */
		}
	}
}


/**/
/* A command formatter for DCP. RH Lamb */
/* sets up stdin and stdout on various machines */
/* There is NO command checking so watch what you send and who you */
/* let accsess your machine. "C rm /usr/*.*" could be executed. */
dcxqt()
{
	int	i;
	char	command[60], input[60], output[60], line[BUFSIZ];
	char	*cp;

	while (dscandir()) {
		strcpy( line, cfile );
		fw = FOPEN( line, "r", 'b' );/* imported X file */
		strcpy(cfile, line);
		printmsg( 2, "dcxqt:%s %ld", cfile, fw );
		input[0]   = '\0';
		output[0]  = '\0';
		command[0] = '\0';
		while ( fgets( line, BUFSIZ, fw ) != (char *)NULL ) {

			cp = index( line, '\n' );
			if ( cp != (char *)NULL )
				*cp = '\0';

			printmsg( 8, "dcxqt: %s", line );
			switch (line[0]) {
			case 'U':
				break;
			case 'I':
				strcpy( input,   &line[2] );
				break;
			case 'O':
				strcpy( output,  &line[2] );
				break;
			case 'C':
				strcpy( command, &line[2] );
				break;
			case 'R':
				break;
			default :
				break;
			}
		}
		fclose( fw );

		printmsg( 0, "xqt: %s\n", command );

		shell( command, input, output, (char *)NULL );


		unlink(cfile);
 		importpath( hostfile, input );
 		unlink(hostfile);
		importpath( hostfile, output );
 		unlink(hostfile);
	}
	return(0);
}

/**/
/*
 *  p r i n t m s g
 *
 *  Print error message on standard output if not remote.
 */
/*VARARGS1*/
printmsg(level, fmt, a1, a2, a3, a4, a5)
int 	level;
char	*fmt;
char	*a1, *a2, *a3, *a4, *a5;
{
	char	msg[256];

	if ( debuglevel > level ) {
		sprintf( msg, fmt, a1, a2, a3, a4, a5 );
		strcat( msg, "\n" );
		if ( remote == MASTER )
			fputs( msg, stdout );
		fputs( msg, logfile );
	}
}




SHAR_EOF
chmod +x 'dcp.c'
fi # end of overwriting check
if test -f 'dcp.h'
then
       echo shar: will not over-write existing file "'dcp.h'"
else
cat << \SHAR_EOF > 'dcp.h'
/* DCP a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
#include <stdio.h>		/* Standard UNIX  definitions */
#include "host.h"		/* Host specific definitions */

FILE * FOPEN();
int CREAT();

#define SYSTEMS		"systems"
#define LOGFILE		"LOGFILE"
#define SYSLOG		"SYSLOG"

#define MSGTIME         20
#define MAXPACK         256

#define ACK     4       /*      general definitions     */
#define NAK     2
#define DATA    0
#define CLOSE   1
#define ERROR   10
#define EMPTY   11



#define	SLAVE	0
#define	MASTER	1

#ifndef TRUE
#define TRUE   (-1)
#define FALSE   0
#endif

#define SAME	0
#define FAILED	-1
#define OK		0


/* L.sys field defines */

#define	FLD_REMOTE	0
#define	FLD_CCTIME	1
#define	FLD_DEVICE	2
#define	FLD_TYPE	3
#define	FLD_SPEED	4
#define	FLD_PROTO	5
#define	FLD_EXPECT	6
#define FLD_SEND	7

/**/
typedef int	(*procref)();

typedef struct {
	char	type;
	procref a;
	procref b;
	procref c;
	procref d;
} Proto;

/* the various protocols available. Add here for others */
extern procref          getpkt, sendpkt, openpk, closepk;

extern int	ggetpkt(), gsendpkt(), gopenpk(), gclosepk();
/*
extern int	kgetpkt(), ksendpkt(), kopenpk(), kclosepk();
extern int	rgetpkt(), rsendpkt(), ropenpk(), rclosepk();
extern int	tgetpkt(), tsendpkt(), topenpk(), tclosepk();
*/

/**/
extern int	pktsize;                /* packet size for this pro*/
extern FILE	*logfile;            	/* system log file */
extern FILE	*syslog;            	/* system log file */
extern FILE	*fw;           		/* cfile pointer */
extern char	cfile[80];              /* work file pointer */
extern int	remote;                 /* -1 means we're remote*/
extern int	findwork;
extern int	msgtime;                /* timout setting */
extern char	fromfile[132];
extern char	hostfile[132];		/* host version of fromfile */
extern char	tofile[132];
extern char	state;                  /* present state */
extern int	fp;                     /* current disk file ptr */
extern int	size;                   /* nbytes in buff */
extern FILE	*fsys;
extern char	Rmtname[20];
extern char	rmtname[20];
extern char	*cctime;
extern char	proto[5];

extern char sysline[BUFSIZ];
extern char s_systems[64];
extern char s_logfile[64];
extern char s_syslog[64];
extern char *flds[60];
extern int  kflds;

extern int	debuglevel;		/* debugging flag */
extern unsigned int	checksum();
extern char *index();
extern char *rindex();

extern	char *curdir;



SHAR_EOF
chmod +x 'dcp.h'
fi # end of overwriting check
if test -f 'dcpgpkt.c'
then
       echo shar: will not over-write existing file "'dcpgpkt.c'"
else
cat << \SHAR_EOF > 'dcpgpkt.c'
/*			dcpgpkt.c

			Revised edition of dcp

			Stuart Lynne May/87

			Copyright (c) Richard H. Lamb 1985, 1986, 1987
			Changes Copyright (c) Stuart Lynne 1987

*/
/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
/* 3-window "g" ptotocol */
/* Thanks got to John Gilmore for sending me a copy of Greg Chesson's
UUCP protocol description-- Obviously invaluable
Thanks also go to Andrew Tannenbaum for the section on Siding window
protocols with a program example in his "Computer Networks" book
*/
#include "dcp.h"
#define PKTSIZE         64
#define PKTSIZ2         2
#define HDRSIZE         6
#define MAXTRY          4

#define MAXERR  200		/* Dont want to quit in a middle of a long file*/
#define TIMEOUT 4		/* could be longer */
#define KPKT    1024/PKTSIZE
#define POK      -1

#define SWINDOW 3	/* fixed now, U make it variable */
#define RWINDOW 3
#define NBUF    8   /* always SAME as MAXSEQ ? */
#define MAXSEQ  8

#define between(a,b,c) ((a<=b && b<c) || (c<a && a<=b) || (b<c && c<a))

/* packet defin */
static int	rwl, swl, swu, rwu, nerr, nbuffers, npkt, irec, timeout, GOT_SYNC, GOT_HDR;
static int	fseq[NBUF], outlen[NBUF], inlen[NBUF], arr[NBUF];
static char	outbuf[NBUF][PKTSIZE+1], inbuf[NBUF][PKTSIZE+1];
static unsigned char	grpkt[HDRSIZE+1];
static long	ftimer[NBUF], acktmr, naktmr;
/**/
/******************SUB SUB SUB PACKET HANDLER************/
gopenpk()
{
	int	i, j, n1, n2, len;
	char	tmp[PKTSIZE+1];
	pktsize = PKTSIZE; /* change it later after the init */
	msgtime = MSGTIME; /* not sure I need this for "g" proto */
	/* initialize proto parameters */
	swl = nerr = nbuffers = npkt = 0;
	swl = swu = 1;
	rwl = 0;
	rwu = RWINDOW - 1;
	for (i = 0; i < NBUF; i++) {
		ftimer[i] = 0;
		arr[i] = FALSE;
	}
	GOT_SYNC = GOT_HDR = FALSE;
	/* 3-way handshake */
	timeout = 1; /* want some timeout capability here */
	gspack(7, 0, 0, 0, tmp);
rsrt:
	if (nerr >= MAXERR)
		return(-1);
	/* INIT sequence. Easy fix for variable pktsize and windows. */
	/* I didnt since all the machines I talk to use W=3 PKTSZ=64 */
	/* If you do this make sure to reflect the changes in "grpack" */
	/* and "gspack" */
	switch (grpack(&n1, &n2, &len, tmp)) {
	case 7:
		gspack(6, 0, 0, 0, tmp);
		goto rsrt;
	case 6:
		gspack(5, 0, 0, 0, tmp);
		goto rsrt;
	case 5:
		break;
	default:
		nerr++;
		gspack(7, 0, 0, 0, tmp);
		goto rsrt;
	}
	nerr = 0;
	return(0);      /* channel open */
}


gclosepk()
{
	int	i;
	char	tmp[PKTSIZE+1];
	timeout = 1;
	for (i = 0; i < MAXTRY; i++) {
		gspack(CLOSE, 0, 0, 0, tmp);
		if (gmachine() == CLOSE)
			break;
	}
	printmsg( 0, "number of errors %d and pkts xfered %d", nerr, npkt );
	return(0);
}


/*
 *
 * ggetpkt
 ***** description: Gets no more than a packet's worth of data from
****               the "packet i/o state machine". May have to
****               periodically run the pkt machine to get some
****               packets.
* on input: dont care   getpkt(data,&len)  char *data int len
* on return: data+\0 and length in len. ret(0) if alls well
* ret(-1) if problems.(fail)
 */
ggetpkt(cdata, len)
int	*len;
char	cdata[];
{
	int	i2;
	irec = 1;
	timeout = 0;
	/* WAIT FOR THE DESIRED PACKET */
	while ((arr[rwl]) == FALSE)
		if (gmachine() != POK)
			return(-1);
	/* GOT A PKT ! */
	i2 = rwl; /*<-- mod(,rwindow) for larger than 8 seq no.s */
	*len = inlen[i2];
	strncpy(cdata, inbuf[i2], *len);
	arr[i2] = FALSE;
	rwu = (1 + rwu) % MAXSEQ; /* bump rec window */
	npkt++;
	return(0);
}


/*
 *
 *  sendpkt
 *
*****   description:    Put at most a packet's worth of data  in the pkt state
 ****                   machine for xmission.
*****                   May have to run the pkt machine a few times to get
*****                   an available output slot.
 *
 * on input: char *data int len,flg; len=length of data in data.
 *           flg=2 just send the packet with no wait for ack.
 *           flg>0 zero out the unused part of the buffer. (for UUCP "msg"
 *                                                                   pkts)
 *           flg=0 normal data
 * return:   ret(0) if alls well ret(-1) if problems (fail)
 *
*/
gsendpkt(cdata, len, flg)
int	len, flg;
char	*cdata;
{
	int	i, i1;
	long	ttmp;
	irec = 0;
	timeout = 0; /* non-blocking reads */
	/* WAIT FOR INPUT i.e. if weve sent SWINDOW pkts and none have been */
	/* acked, wait for acks */
	while (nbuffers >= SWINDOW)
		if (gmachine() != POK)
			return(-1);
	i1 = swu;  /* <--If we ever have more than 8 seq no.s, must mod() here*/
	/* PLACE PACKET IN TABLE AND MARK UNACKED */
	/* fill with zeros or not */
	if (flg) {
		strcpy(outbuf[i1], cdata);
		len = PKTSIZE;
		for (i = strlen(cdata); i < len; i++)
			outbuf[i1][i] = '\0';
	} else {
		strncpy(outbuf[i1], cdata, len);
		outbuf[i1][len] = '\0';
	}
	/* mark packet  */
	outlen[i1] = len;
	ftimer[i1] = time(&ttmp);
	fseq[i1] = swu;
	swu = (1 + swu) % MAXSEQ;	/* bump send window */
	nbuffers++;
	npkt++;
	/* send it */
	gspack(DATA, rwl, fseq[i1], outlen[i1], outbuf[i1]);
	/* send it once then let the pkt machine take it. wouldnt need this for */
	/* mtasking systems */
	/* sl gmachine(); */
	return(0);
}


/************     packet machine   ****** RH Lamb 3/87 */
/* Idealy we would like to fork this process off in an infinite loop */
/* and send and rec pkts thru "inbuf" and "outbuf". Cant do this in MS-DOS*/
/* so we setup "getpkt" and "sendpkt" to call this routine often and return */
/* only when the input buffer is empty thus "blocking" the pkt-machine task. */
gmachine()
{
	int	rack, rseq, rlen, i1, i2, dflg;
	char	rdata[PKTSIZE+1];
	long	ttmp, itmp;
reply:
	printmsg( 6, "*send %d<W<%d, rec %d<W<%d, err %d", swl, swu, rwl, rwu, nerr );
	/* waiting for ACKs for swl to swu-1. Next pkt to send=swu */
	/* rwl=expected pkt */
	printmsg( 7, "Kbytes transfered %d errors %d\r", npkt / KPKT, nerr );
	if (nerr >= MAXERR)
		goto close;
	dflg = 0;
	switch (grpack(&rack, &rseq, &rlen, rdata)) {
	case CLOSE:
		printmsg( 5, "**got CLOSE");
		goto close;
	case NAK:
		nerr++;
		acktmr = naktmr = 0; /* stop ack/nak timer */
		printmsg( 5, "**got NAK %d", rack );
nloop:
		if (between(swl, rack, swu)) { /* resend rack->(swu-1) */
			i1 = rack;
			gspack(DATA, rwl, rack, outlen[i1], outbuf[i1]);
			printmsg( 5, "***resent %d", rack );
			ftimer[i1] = time(&ttmp);
			rack = (1 + rack) % MAXSEQ;
			goto nloop;
		}
		if (dflg)
			return(POK);
		goto reply; /* any other stuff ? */

	case EMPTY:
		printmsg( 5, "**got EMPTY" );
		itmp = time(&ttmp);
		if (acktmr)
			if ((itmp - acktmr) >= TIMEOUT) { /* ack timed out*/
				gspack(ACK, rwl, 0, 0, rdata);
				acktmr = itmp;
			}
		if (naktmr)
			if ((itmp - naktmr) >= TIMEOUT) { /*nak timed out*/
				gspack(NAK, rwl, 0, 0, rdata);
				naktmr = itmp;
			}
		/* resend any timed out un-acked pkts */
		for (i2 = swl; between(swl, i2, swu); i2 = (1 + i2) % MAXSEQ)  {
			acktmr = naktmr = 0; /* reset ack/nak */
			i1 = i2;
			printmsg( 5, "--->seq,elapst %d %ld", i2, (itmp - ftimer[i1]) );
			if ((itmp - ftimer[i1]) >= TIMEOUT) {
				printmsg( 5, "***timeout %d", i2 );
				/* since "g" is "go-back-N", when we time out we */
				/* must send the last N pkts in order. The generalized*/
				/* sliding window scheme relaxes this reqirment */
				nerr++;
				dflg = 1;  /* same hack */
				rack = i2;
				goto nloop;
			}
		}
		return(POK);
	case ACK:
		printmsg( 5, "**got ACK %d", rack );
		acktmr = naktmr = 0; /* disable ack/nak's */
aloop:
		if (between(swl, rack, swu)) {   /* S<-- -->(S+W-1)%8 */
			printmsg( 5, "***ACK %d", swl );
			ftimer[swl] = 0;
			nbuffers--;
			swl = (1 + swl) % MAXSEQ;
			dflg = 1;  /* same hack */			/* sl */
			goto aloop;
		}
		if (dflg)
			return(POK); /* hack for non-mtask sys's */
		/* to empty "inbuf[]" */
		goto reply;
	case DATA:
		printmsg( 5, "**got DATA %d %d", rack, rseq );
		i1 = (1 + rwl) % MAXSEQ; /* (R+1)%8 <-- -->(R+W)%8 */
		i2 = (1 + rwu) % MAXSEQ;
		if (between(i1, rseq, i2)) {
			if (i1 == rseq) {
				i1 = rseq;
				arr[i1] = TRUE;
				inlen[i1] = rlen;
				strncpy(inbuf[i1], rdata, rlen);
				rwl = (rwl + 1) % MAXSEQ;
				printmsg( 5, "***ACK d %d", rwl );
				gspack(ACK, rwl, 0, 0, rdata);
				acktmr = time(&ttmp); /* enable ack/nak tmout*/
				dflg = 1; /*return to call when finished*/
				/* in a mtask system, unneccesary */
			} else {
				nerr++;
				printmsg( 5, "***unexpect %d ne %d", rseq, rwl );
			}
		} else {
			nerr++;
			printmsg( 5, "***wrong seq %d", rseq );
		}
		goto aloop;
	case ERROR:
		nerr++;
		printmsg( 5, "**got BAD CHK" );
		gspack(NAK, rwl, 0, 0, rdata);
		naktmr = time(&ttmp); /* set nak timer */
		printmsg( 5, "***NAK d %d", rwl );
		goto reply;
	default:
		printmsg( 5, "**got SCREW UP" );
		goto reply; /* ignore it */
	}
close:
	gspack(CLOSE, 0, 0, 0, rdata);
	return(CLOSE);
}


/**/
/*************** FRAMMING *****************************/
/*
 *
 *
 *      send a packet
 * nt2=type nt3=pkrec nt4=pksent len=length<=PKTSIZE cnt1= data * ret(0) always
 */
gspack(nt2, nt3, nt4, len, cnt1)
int	nt2, nt3, nt4, len;
char	cnt1[];
{
	unsigned int	check, i;
	unsigned char	c2, pkt[HDRSIZE+1], dpkerr[10];
	if (len > 64)
		len = 64;
	if (len == 0)
		cnt1[0] = '\0';
/**Link testing mods- create artificial errors ***/ /*
printf("**n:normal,e:error,l:lost,p:partial,h:bad header,s:new seq--> ");
gets(dpkerr);
	if(dpkerr[0] == 's') { sscanf(&dpkerr[1],"%d",&nt4); } /**/
	/** End Link testing mods ***/
	printmsg( 5, "send packet type %d, num=%d, n=%d, len=%d", nt2, nt3, nt4, len );
	printmsg( 5, "data =\n|%s|", cnt1 );
	c2 = '\0';
	pkt[0] = '\020';
	pkt[4] = nt2 << 3;
	nt2 &= 7;
	switch (nt2) {
	case 1:
		break;                  /* stop protocol */
	case 2:
		pkt[4] += nt3;
		break;   /* reject        */
	case 3:
		break;
	case 4:
		pkt[4] += nt3;
		break;   /* ack          */
	case 5:
		pkt[4] += SWINDOW;
		break;   /* 3 windows */
	case 6:
		pkt[4] += 1;
		break;   /* pktsiz = 64 (1) */
	case 7:
		pkt[4] += SWINDOW;
		break;   /* 3 windows */
	case 0:
		pkt[4] += 0x80 + nt3 + (nt4 << 3);
		c2 = (PKTSIZE - len) & 0xff;
		/* havnt set it up for VERY LONG pkts with a few */
		/* bytes yet (-128) */
		if (c2) { /* short packet handling */
			pkt[4] += 0x40;   /* if len < PKTSIZE */
			for (i = PKTSIZE - 1; i > 0; i--)
				cnt1[i] = cnt1[i-1];
			cnt1[0] = c2;
		}
		break;
	}
	pkt[4] &= 0xff;
	if (nt2) {
		pkt[1] = 9;             /* control packet size = 0 (9) */
		check = (0xaaaa - pkt[4]) & 0xffff;
	} else {
		pkt[1] = PKTSIZ2;             /* data packet size = 64 (2) */
		check = checksum(cnt1, PKTSIZE);
		i = pkt[4];/* got to do this on PC for ex-or high bits */
		i &= 0xff;
		check = (check ^ i) & 0xffff;
		check = (0xaaaa - check) & 0xffff;
	}
	pkt[2] = check & 0xff;
	pkt[3] = (check >> 8) & 0xff;
	pkt[5] = (pkt[1] ^ pkt[2] ^ pkt[3] ^ pkt[4]) & 0xff;
/***More Link testing MODS ******/ /*
switch(dpkerr[0]) {
case 'e':   cnt1[10] = -cnt1[10];
			break;
case 'h':	pkt[5] = -pkt[5];
			break;
case 'l':	return;
case 'p':	swrite(pkt,HDRSIZE);
			if(pkt[1] != 9) swrite(cnt1,PKTSIZE-3);
			return;
default:	break;
	}  /**/
	/******End Link Testing Mods **********/
	swrite(pkt, HDRSIZE);       /* header is 6-bytes long */
	/*      write(flog,pkt,HDRSIZE);   */
	if (pkt[1] != 9) {
		swrite(cnt1, PKTSIZE);     /* data is always 64
		bytes long */
		/*    write(flog,cnt1,PKTSIZE);   */
	}
}


/**/
/*
 *
 *      read packet
 * on return: nt3=pkrec nt4=pksent len=length <=PKTSIZE  cnt1=data *
 * ret(type) ok; ret(EMPTY) input buf empty; ret(ERROR) bad header;
 *          ret(EMPTY) lost pkt timeout; ret(ERROR) checksum error;ret(-5) ?
****NOTE :
***sread(buf,n,timeout)
	while(TRUE) {
		if(# of chars available >= n) (without dec internal counter)
			read n chars into buf (decrenent internal char counter)
			break
		else
			if(time>timeout) break
	}
	return(# of chars available)
****END NOTE
 */
grpack(nt3, nt4, len, cnt1)
int	*nt3, *nt4, *len;
char	cnt1[];
{
	unsigned int	nt1, check, checkchk, i;
	unsigned char	c, c2;
	int	ii;
	if (GOT_SYNC)
		goto get_hdr;
	if (GOT_HDR)
		goto get_data;
	c = '\0';
	while ((c & 0x7f) != '\020')
		if (sread(&c, 1, timeout) == 0)
			return(EMPTY);
	GOT_SYNC = TRUE;
get_hdr:
	if (sread(&grpkt[1], HDRSIZE - 1, timeout) < (HDRSIZE - 1))
		return(EMPTY);
	GOT_SYNC = FALSE;
	/*i = grpkt[1] ^ grpkt[2] ^ grpkt[3] ^ grpkt[4] ^ grpkt[5];*/
 	i = (unsigned)grpkt[1] ^ (unsigned)grpkt[2] ^
 	    (unsigned)grpkt[3] ^ (unsigned)grpkt[4] ^
 	    (unsigned)grpkt[5];

	i &= 0xff;
	printmsg( 10, "prpkt %02x %02x %02x %02x %02x .. %02x ",
				grpkt[1], grpkt[2], grpkt[3], grpkt[4], grpkt[5],
				i
			);

	if (i) {               /*  bad header */
		printmsg( 0, "****bad header****" );
		return(ERROR); /* Im not sure whether "g" considers it an empty or error */
	}
	GOT_HDR = TRUE;
	if ((grpkt[1] &= 0x7f) == 9) {       /* control packet */
		*len = 0;
		c = grpkt[4] & 0xff;
		nt1  = c >> 3;
		*nt3 = c & 7;
		*nt4 = 0;
		check = 0;
		checkchk = 0;
		cnt1[*len] = '\0';
		GOT_HDR = FALSE;
	} else {       /* data packet */
		if (grpkt[1] != PKTSIZ2)
			return(-5);   /* cant handle other than 64*/
get_data:
		if (sread(cnt1, PKTSIZE, timeout) < PKTSIZE)
			return(EMPTY);
		GOT_HDR = FALSE;
		nt1  = 0;
		c2 = grpkt[4] & 0xff;
		c = c2 & 0x3f;
		*nt4 = c >> 3;
		*nt3 = c & 7;
		i = grpkt[3];
		i = (i << 8) & 0xff00;
		check = grpkt[2];
		check = i | (check & 0xff);
		checkchk = checksum(cnt1, PKTSIZE);
		i = grpkt[4] | 0x80;
		i &= 0xff;
		checkchk = 0xaaaa - (checkchk ^ i);
		checkchk &= 0xffff;
		if (checkchk != check) {
			printmsg( 4, "***checksum error***" );
			return(ERROR);
		}
		*len = PKTSIZE;
		/* havnt set it up for very long pkts yet (>128) RH Lamb */
		if (c2 & 0x40) {
			ii = (cnt1[0] & 0xff);
			*len = (*len - ii) & 0xff;
			for (ii = 0; ii < *len; ii++)
				cnt1[ii] = cnt1[ii+1];
		}
		cnt1[*len] = '\0';
	}
	printmsg( 5, "rec  packet type %d, num=%d, n=%d, len=%d", nt1, *nt3, *nt4, *len );
	printmsg( 6, "  checksum rec = %x comp = %x, data=\n|%s|", check, checkchk, cnt1 );
	ii = nt1;
	return(ii);
}


unsigned	checksum(data, len)
int	len;
char	data[];
{
	unsigned int	i, j, tmp, chk1, chk2;
	chk1 = 0xffff;
	chk2 = 0;
	j = len;
	for (i = 0; i < len; i++) {
		if (chk1 & 0x8000) {
			chk1 <<= 1;
			chk1++;
		} else {
			chk1 <<= 1;
		}
		tmp = chk1;
		chk1 += (data[i] & 0xff);
		chk2 += chk1 ^ j;
		if ((chk1 & 0xffff) <= (tmp & 0xffff))
			chk1 ^= chk2;
		j--;
	}
	return(chk1 & 0xffff);
}


/* */
/*
gwrmsg
	send a null terminated string out
*/
gwrmsg( typ, buf )
char typ;
char *buf; /* null terminated */
{
}

/*
grdmsg
	read a null terminated string
*/
grdmsg( buf )
char * buf;
{

}

/*
gwrdata
	read a file and send it out
*/
gwrdata( f )
{
}

/*
grrdata
	read in data and send to file
*/
grrdata( f )
{
}


/*
grdblk
	read a block of data in
*/
grdblk( blk, len )
{
}

/*
gwrblk
	write out a block of data
*/
gwrblk( blk, len )
{
}

SHAR_EOF
chmod +x 'dcpgpkt.c'
fi # end of overwriting check
if test -f 'dcpsys.c'
then
       echo shar: will not over-write existing file "'dcpsys.c'"
else
cat << \SHAR_EOF > 'dcpsys.c'

/*			dcpsys.c

			Revised edition of dcp

			Stuart Lynne May/87

			Copyright (c) Richard H. Lamb 1985, 1986, 1987
			Changes Copyright (c) Stuart Lynne 1987

*/
/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
/* Get the next system, and other support routines  */
#include "dcp.h"
/*#define PROTOS  "trkg"*/
#define PROTOS  "g"
#define MAXLOGTRY       3

Proto Protolst[] = {
		'g', ggetpkt, gsendpkt, gopenpk, gclosepk,
/*
	    'k', kgetpkt, ksendpkt, kopenpk, kclosepk,
	    'r', rgetpkt, rsendpkt, ropenpk, rclosepk,
	    't', tgetpkt, tsendpkt, topenpk, tclosepk,
*/
		 '0'};

#define EOTMSG "\004\r\004\r"

procref         getpkt, sendpkt, openpk, closepk;

/**/

/***************************************************************/
/***            Sub Systems             */
/*
**
**getsystem
** Process an "systems" file entry (like L.sys)
*/
getsystem()
{
	int	i;

	if ( fgets( sysline, BUFSIZ, fsys ) == (char *)NULL )
		return( 'A' );
	printmsg( 2, "%s", sysline );

	kflds = getargs( sysline, flds );
	strcpy( rmtname, flds[FLD_REMOTE] );
	cctime = flds[FLD_CCTIME];
	strcpy( device, flds[FLD_DEVICE] );

	/* strcpy( type, flds[FLD_TYPE] ); */
	strcpy( speed, flds[FLD_SPEED] );
	strcpy( proto, flds[FLD_PROTO] );


	if (debuglevel > 3)
		for (i = FLD_EXPECT; i < kflds; i += 2)
			fprintf( stderr, "expect[%02d]:\t%s\nsend  [%02d]:\t%s\n",
				i, flds[i], i+1, flds[i+1] );

	printmsg( 2, "rmt= %s ctm= %s", rmtname, flds[FLD_CCTIME] );
	printmsg( 2, "dev= %s ", device );
	printmsg( 2, "spd= %s pro= %s", speed, proto );
	fw = (FILE *)NULL;
	if (
		/* (checktime( cctime )) || */
		( strcmp( Rmtname, "all" ) == SAME ) ||
		( strcmp( Rmtname, rmtname ) == SAME ) ||
	 	( (strcmp( Rmtname, "any" ) == SAME) && scandir() == 'S' )
	 	)
	{
		if ( fw != (FILE *)NULL )
		  fclose( fw );	/* in case we matched with scandir */
		return( 'S' );  /* startup this system */
	}
	else
		return('G');
}


/**/
/*
**
**checkname
** Do we know the guy ?
*/
checkname(name)
char	name[];
{
	FILE *ff;
	char line[BUFSIZ], tmp[20]; /* can change to 8 if %8s works */

	if ( ( ff = FOPEN( s_systems, "r", 't' )) == (char *)NULL )
		return( FAILED );

	while ( fgets( line, BUFSIZ, ff ) != (char *)NULL ){
		sscanf( line, "%8s ", tmp );
		printmsg( 3, "rmt= %s sys= %s", name, tmp );
		if ( strncmp( tmp, line, 7 ) == 0 ) {
			fclose( ff );
			return ( OK ); /*OK I like you */
		}
	}
	fclose( ff );
	return( FAILED ); /* Who are you ? */

}


/**/
/*
**
**checktime
** check if we may make a call at this time
**------------>to be implemented. Again. Didnt think it crucial
*/
checktime(xtime)
char	xtime[];
{
	return(0); /* OK go to it */
}



/**/
/*
**
**sysend
** end UUCP session negotiation
*/
sysend()
{
	char	msg[80];

	msg[1] = '\0';
	msgtime = 2 * MSGTIME;
	/* while (msg[1] != 'O') { */
		wmsg("OOOOOO", 2);
		if (rmsg(msg, 2) == -1)
			goto hang;
	/*}*/
hang:
	wmsg("OOOOOO", 2);
	closeline();
	if ( remote == MASTER )
		return('I');
	return('A');
}


/**/
/*
**
**      delay
**
*/
/*ddelay(dtime)
int	dtime;
{
	int	i, j;
	for (i = 0; i < dtime; i++) {
	}
}
*/

/**/
/*
**
**wmsg
** write a ^P type msg to the remote uucp
*/
wmsg(msg, syn)
int	syn;
char	msg[];
{
	int	len;
	len = strlen(msg);
	if (syn == 2)
		swrite("\0\020", 2);
	swrite(msg, len);
	if (syn == 2)
		swrite("\0", 1);
}


/*
**
**rmsg
** read a ^P msg from UUCP
*/
rmsg(msg, syn)
int	syn;
char	msg[];
{
	int	ii;
	char	c, cc[5];
	/* *msg0;*/
	/*msg0 = msg;*/
	c = 'a';
	if (syn == 2) {
		while ((c & 0x7f) != '\020') {
			if (sread(cc, 1, msgtime) < 1)
				return(-1);
			c = cc[0]; /* Dont ask. MSC needs more than a byte to breathe */
			/*		printf("Hello im in rmsg c=%x\n",c); */
		}
	}
	for (ii = 0; ii < 132 && c ; ii++) {
		if (sread(cc, 1, msgtime) < 1)
			return(-1);
		c = cc[0] & 0x7f;
		if (c == '\r' || c == '\n')
			c = '\0';
		msg[ii] = c;
		/*if(c == '\020') msg = msg0; */
	}
	return(strlen(msg));
}



/**/
/*
**
**
**startup
**
**
*/
startup()
{
	char	msg[80], tmp1[20], tmp2[20];
	if ( remote == MASTER ) {
		msgtime = 2 * MSGTIME;
		if (rmsg(msg, 2) == -1)
			return('Y');
		printmsg( 2, "1st msg = %s", msg );
		if (msg[5] == '=' && strncmp(&msg[6], rmtname, 7))
			return('Y');


		/*sprintf(msg, "S%.7s -Q0 -x%d", nodename, debuglevel);*/  /* -Q0 -x16 remote debuglevel set */
		sprintf(msg, "S%.7s", nodename);

		wmsg(msg, 2);
		if (rmsg(msg, 2) == -1)
			return('Y');
		printmsg( 2, "2nd msg = %s", msg );
		if (strncmp(&msg[1], "OK", 2))
			return('Y');
		if (rmsg(msg, 2) == -1)
			return('Y');
		printmsg( 2, "3rd msg = %s", msg );
		if (msg[0] != 'P' || index(&msg[1], proto[0]) == (char *)NULL) {
			wmsg("UN", 2);
			return('Y');
		}
		sprintf(msg, "U%c", proto[0]);
		wmsg(msg, 2);
		setproto(proto[0]);
		return('D');
	} else {
		msgtime = 2 * MSGTIME;
		sprintf(msg, "Shere=%s", nodename);
		wmsg(msg, 2);
		if (rmsg(msg, 2) == -1)
			return('Y');
		sscanf(&msg[1], "%s %s %s", rmtname, tmp1, tmp2);
		sscanf(tmp2, "-x%d", &debuglevel);
		printmsg( 1, "debuglevel level = %d", debuglevel );
		printmsg( 2, "1st msg from remote = %s", msg );
		if (checkname(rmtname))
			return('Y');
		wmsg("ROK", 2);
		sprintf(msg, "P%s", PROTOS);
		wmsg(msg, 2);
		if (rmsg(msg, 2) == -1)
			return('Y');
		if (msg[0] != 'U' || index(PROTOS, msg[1]) == (char *)NULL )
			return('Y');
		proto[0] = msg[1];
		setproto(proto[0]);
		return('R');
	}
}


/******* set the protocol **********/
setproto(pr)
char	pr;
{
	int	i;
	Proto * tproto;
	for (tproto = Protolst; tproto->type != '\0' && pr != tproto->type; tproto++) {
		printmsg( 3, "setproto: %c %c", pr, tproto->type );
	}
	if (tproto->type == '\0') {
		printmsg( 0, "setproto:You said I had it but I cant find it" );
		exit(1);
	}
	getpkt = tproto->a;
	sendpkt = tproto->b;
	openpk = tproto->c;
	closepk = tproto->d;
}



/**/
int prefix(sh,lg)
char *sh,*lg;
{
	return( strncmp(sh,lg,strlen(sh)) == SAME);
}

int notin(sh,lg)
char *sh,*lg;
{
	while (*lg) {
		if (prefix(sh,lg++))
			return( FALSE );
	}
	return( TRUE );
}

#define MAXR 300
int expectstr( str, timeout )
char *str;
{
	static char rdvec[MAXR];
	char *rp = rdvec;
	int kr;
	char nextch;

	printmsg( 0, "wanted %s", str );

	if ( strcmp(str, "\"\"") == SAME ) {
		return( TRUE );
	}
	*rp = 0;
	while ( notin( str,rdvec ) ) {
		/* fprintf(stderr, "---------->%s<------\n", rdvec);/**/
		kr = sread( &nextch, 1, timeout /* 40 */ );
		/* nextch &= 0177;
		fprintf(stderr, "kr - %2d '%c'\n", kr, nextch); */
		if (kr <= 0) {
			return( FALSE );
		}
		if ((*rp = nextch & 0177) != '\0') {
			rp++;
		}
		*rp = '\0';
		if (rp >= rdvec + MAXR) {
			return( FALSE );
		}
	}
	return( TRUE );
}

int writestr(s)
	register char *s;
{
	register char last;
	register char * m;
	int nocr;
	last = '\0';
	nocr = FALSE;
	while (*s) {
		if (last == '\\') {
			switch (*s) {
			case 'd':
			case 'D': /* delay */
               sleep(2);
               break;
            case 'c':
            case 'C': /* end string don't output CR */
               nocr = TRUE;
               break;
            case 'r':
            case 'R': /* carriage return */
            case 'm':
            case 'M':
      			swrite( "\r", 1 );
               	break;
            case 'n':
            case 'N':
      			swrite( "\n", 1 );
               	break;
            case 'b':
            case 'B':
      			swrite( "\b", 1 );
               	break;
            case 't':
            case 'T':
      			swrite( "\t", 1 );
               	break;
            case 's':
            case 'S':
      			swrite( " ", 1 );
               	break;
            case 'z':
            case 'Z':
            	SIOSpeed( ++s );
            	while ( *s != '\0' && *s != '\\' )
            		s++;
            	if ( *s == '\\' )
            		s++;
            	break;
            default:
      			swrite( s, 1 );
			}
			last = '\0';
		}
		else if (*s != '\\') {
      		swrite( s, 1 );
			/* fputc(*s,stderr); */
		}
		else {
			last = *s;
		}
		s++;
	}
	return( nocr );
}

/***
 *   void sendthem(str)   send line of login sequence
 *         char *str;
 *
 *   return codes:  none
 */

void sendstr(str)
char *str;
{
	int nw, ns;
	int nulls;

	printmsg( 2, "sending %s", str );

#ifdef BREAK
	if (prefix("BREAK", str)) {
		sscanf(&str[5], "%1d", &nulls);
		if (nulls <= 0 || nulls > 10)
			nulls = 3;
		/* send break */
		ssendbrk(nulls);
		return;
	}
#endif

	if ( strcmp(str, "EOT") == SAME ) {
		swrite(EOTMSG, strlen(EOTMSG));
		return;
	}

	if ( strcmp(str,"\"\"") == SAME )
		*str = '\0';
		/*fprintf(stderr,"'%s'\n",str);*/

	if ( strcmp(str,"") != SAME ) {
		if (!writestr(str)) {
			swrite ("\r", 1);
		}
	}
	else {
		swrite("\r", 1);
	}
	return;
}

int sendexpect( s, e, timeout )
char * s;
char * e;
{
	sendstr( s );
	return( expectstr( e, timeout ) );
}

dial()
{
	int	flg, kk, jj, ll, firstflg;
	char	buf[4], *prsend;

	char *exp;
	char *alternate;
	int	ok;
	int i;

	if ( strcmp( flds[FLD_TYPE], "HAYES" ) != SAME ) {
		printmsg( 0, "dial: unsupported dialer %s", flds[FLD_TYPE] );
		return( FALSE );
	}

	printmsg( 3, "calling host %s", rmtname );
	if (openline(device, "2400" ))
		return( FALSE );

	printmsg( 0, "hayes: trying 2400" );
	if ( sendexpect( "ATZ", "OK", 2 ) != TRUE ) {
		sendexpect( "\\d+++\\d", "OK", 2 );
		if ( sendexpect( "ATZ", "OK", 2 ) != TRUE ) {
			printmsg( 0, "hayes: trying 1200" );
			SIOSpeed( "1200" );
			if ( sendexpect( "ATZ", "OK", 2 ) != TRUE ) {
				sendexpect( "\\d+++\\d", "OK", 2 );
				if ( sendexpect( "ATZ", "OK", 2 ) != TRUE )
					return( FALSE);
				}
		}
	}
	printmsg( 0, "hayes: got modem response" );

	/*(sendstr( "\\d\\dATS7=30" );
	expectstr( "OK", 40 );*/

	sendstr( "\\d\\dATX4\\c" );

	if ( sendexpect( speed, "CONNECT ", 40 ) == TRUE ) {
		printmsg( 3, "hayes: got CONNECT" );

		if ( sread( buf, 4, 4 ) == 4 ) {
			printmsg( 3, "hayes: speed select %s", buf );
			/* set speed appropriately */
			SIOSpeed( buf );
		}
		return( TRUE );
	}
	else
		return( FALSE );

}


/*
**
**callup
** script processor - nothing fancy!
*/
callup()
{
	int	flg, kk, jj, ll, firstflg;
	char	*prsend;

	char *exp;
	char *alternate;
	int	ok;
	int i;

	printmsg( 0, "calling host %s", rmtname );

	if ( strcmp( flds[FLD_TYPE], "DIR" ) != SAME ) {
		if ( dial() == FALSE )
			return( 'G' );
	}
	else if (openline(device, speed))
		return( 'G' );

	for (i = 6; i < kflds; i+=2) {

		exp = flds[i];
		printmsg( 2, "callup: expect %d of %d  \"%s\"", i, kflds, exp );

		ok = FALSE;
		while (ok != TRUE) {

			alternate = index( exp, '-' );
			if (alternate != (char *)NULL)
				*alternate++ = '\0';

			ok = expectstr( exp, 30 );

			printmsg( 1, "got %s", ok != TRUE ? "?" : "that" );

			if ( ok == TRUE ) {
				printmsg( 0, "got that" );
				break;
			}

			if ( alternate == (char *)NULL ) {
				printmsg( 0, "LOGIN FAILED" );
				return( 'Y' );
			}

			exp = index( alternate, '-' );
			if ( exp != (char *)NULL )
				*exp++ = '\0';

			printmsg( 0, "send alternate" );

			sendstr( alternate );
		}

	printmsg( 2, "callup: send %d of %d  \"%s\"", i+1, kflds, flds[i+1] );
	sleep(1); /* (1)*/
	sendstr(flds[i+1]);
	}
	return('P');

}

/**/
/*
**
**      slowrite
** comunication slow write. needed for auto-baud modems
*/
/*slowrite(st)
register char	*st;
{
	int	len, j;
	char	c;
	len = strlen(st);
	printmsg( 2, "sent %s", st );
	for (j = 0; j < len; j++) {
		swrite(&st[j], 1);
		ddelay(80000);
	}
}
*/

/**/
/*
**
**scandir
**
*/

#include "ndir.h"


/*	scandir

	scan work dir for C. files matching current remote host (rmtname)

	return

		A	- abort
		Y	- can't open file
		S	- ok
		Q	- no files

*/
scandir()
{
	int	fn, len, i;
	char	cname[40], tmp[132];

	DIR *dirp;
	struct direct *dp;

	if ((dirp = opendir( spooldir )) == (DIR *)NULL ) {
		fprintf( stderr, "couldn't open dir %s\n", spooldir );
		return( 'A' );
	}
	sprintf(cname, CALLFILE, rmtname);
	len = strlen(cname);
	while ((dp = readdir(dirp)) != (struct direct *)NULL) {
		printmsg( 4, "scandir: %s", dp->d_name );
		if ( strncmp( cname, dp->d_name, len ) == SAME ) {
			printmsg( 4, "scandir: match!!" );
			strcpy(cfile, dp->d_name);
			closedir( dirp );
			if ((fw = FOPEN( cfile, "r", 't' )) == (char *)NULL )
				return('Y');
			return('S');
		}
	}
	closedir( dirp );
	return('Q');

}


/**/
/*
**
**dscandir
** scan the directory
*/

dscandir()
{
	int	fn, len, i;
	char	cname[40], tmp[132];

	DIR *dirp;
	struct direct *dp;


	if ((dirp = opendir( spooldir )) == (DIR *)NULL ) {
		fprintf( stderr, "couldn't open dir %s\n", spooldir );
		return(0);
	}
	sprintf(cname, XQTFILE, rmtname); /* sprintf(cname,"c%.4s",rmtname); */
	len = strlen(cname);
	while ((dp = readdir(dirp)) != (struct direct *)NULL) {
		printmsg( 4, "dscandir: file = %s cname = %s", dp->d_name, cname );
		if ( strncmp( cname, dp->d_name, len ) == SAME ) {
			printmsg( 4, "dscandir: match!!" );
			strcpy(cfile, dp->d_name);
			closedir( dirp );
			return( -1 );
		}
	}
	closedir( dirp );
	return( 0 );

}




SHAR_EOF
chmod +x 'dcpsys.c'
fi # end of overwriting check
if test -f 'dcpxfer.c'
then
       echo shar: will not over-write existing file "'dcpxfer.c'"
else
cat << \SHAR_EOF > 'dcpxfer.c'
/*			dcpxfer.c

			Revised edition of dcp

			Stuart Lynne May/87

			Copyright (c) Richard H. Lamb 1985, 1986, 1987
			Changes Copyright (c) Stuart Lynne 1987

*/
/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
/* file send routines */
#include "dcp.h"
#include <ctype.h>

static unsigned char	rpacket[MAXPACK];
static unsigned char	spacket[MAXPACK];
/**/
/***************SEND PROTOCOL***************************/
/*
 *  s d a t a
 *
 *  Send File Data
 */
sdata()
{

	while( TRUE ) {

		if (( *sendpkt) ( spacket, size, 0 ))
			return (0 );     /* send data */
		if (( size = bufill( spacket )) == 0 )  /* Get data from file */
			return( 'Z' ); 						/* If EOF set state to that */
	}

	return('D');/* Got data, stay in state D */

}


/*
 *  b u f i l l
 *
 *  Get a bufferful of data from the file that's being sent.
 *  Only control-quoting is done; 8-bit & repeat count prefixes are
 *  not handled.
 */
bufill(buffer)
char	*buffer;/* Buffer */
{
	return( read(fp, buffer, pktsize) );/* Handle partial buffer */
}


/*
 *  s b r e a k
 *
 *  Send Break (EOT)
 */
sbreak()
{
	int	len, i;
	sprintf(spacket, "H");
	if ((*sendpkt)(spacket, 0, 1))
		return(0);
	if ((*getpkt)(spacket, &len))
		return(0);
	printmsg( 2, "Switch modes" );
	if (spacket[1] == 'N')
		return('G');
	return('Y');
}


/**/
/*
 *  s e o f
 *
 *  Send End-Of-File.
 */
seof()
{
	int	len, i;
	if ((*sendpkt)(spacket, 0, 0))
		return(0);
	if ((*getpkt)(spacket, &len))
		return(0); /* rec CY or CN */
	if (strncmp(spacket, "CY", 2))
		return(0); /* cant send file */
	close(fp);
	fp = (-1);
 	importpath( hostfile, fromfile );
	unlink(hostfile);
	printmsg( 0, "Transfer of %s (%s) completed.  fp=%d", fromfile, hostfile, fp );

	/*
	fprintf( syslog, "%s!%s (%d/%d-%d:%d:%d) -> %ld / %ld secs", host, id, size, secs );
	*/

	return('F');                    /* go get the next file to send */
}


/**/
/*
 *  s f i l e
 *
 *  Send File Header.
 */
sfile()
{
	int	i, len;
	char * cp;
	if (fp == -1) {/* If not already open, */
		printmsg( 3, "looking for next file..." );
		if (getfile()) { /* get next file from current work*/
			fclose( fw );
			unlink( cfile );/* close and delete completed workfile */
			fw = (char *)NULL;
			return('B'); /* end sending session */
		}

 		importpath( hostfile, fromfile );

		printmsg( 3, "Opening %s (%s) for sending.", fromfile, hostfile );
		fp = open(hostfile, 0);/* open the file to be sent */
		if (fp == -1) {/* If bad file pointer, give up */
			printmsg( 0, "Cannot open file %s (%s).", fromfile, hostfile );
			return('A');
		}
	} else
		return('A'); /* If somethings already open. were in trouble*/
	printmsg( 0, "Sending %s (%s) as %s", fromfile, hostfile, tofile );
	strcpy(spacket, tofile);
	if ((*sendpkt)(spacket, 0, 1))
		return(0);       /* send S fromfile tofile */
	if ((*getpkt)(spacket, &len))
		return(0);       /* user - tofile 0666. */
	if (spacket[1] != 'Y')
		return('A'); 			/* If otherside says no-quit*/
	size = bufill(spacket);
	return('D');
}


/**/
/*
 *  s i n i t
 *
 *  Send Initiate: send this host's parameters and get other side's back.
 */
sinit()
{
	if ((*openpk)())
		return('A');
	return('B');
}


/**/
/*
 *
 *
 *  getfile
 *
 *  getfile reads the next line from the presently open workfile
 *  (cfile) and determines from this the next file to be sent
 *  (file). If there are no more TRUE is returned.
 *  --A fix for "R from to 0666" should be done here to recieve files
 *  --in addition to sending them. The appropriate "state letter"
 *  --i.e. "R" should be returned to the send "master" or "slave"
 *  --state switching table in "dcp.c"
 *  --I did not implement this since the majority of uucp transactions
 *  --appear to be "S from to 0666" type. RHLamb 1/87
 *
 */
getfile()
{
	int	i;
	char	line[132];
	register char * cp;

	if ( fgets( line, BUFSIZ, fw ) == (char *)NULL )
		return(TRUE);

	sscanf(&line[2], "%s ", fromfile);
	for ( i = 0, cp = line; *cp!='\0'; i++, cp++ ) {
		if ( strncmp( cp, "0666", 4 ) == 0)
			break;
	}
	cp+=4;
	*cp = '\0';
	strcpy(tofile, line);
 	printmsg(3, "   getfile: fromfile=%s, tofile=%s.", fromfile, tofile);
	return(FALSE);
}


/**/
/*********************** MISC SUB SUB PROTOCOL *************************/
/*
**
**schkdir
** scan the dir
*/
schkdir()
{
	char	c;
	c = scandir();
	if (c == 'Q') {
		return('Y');
	}
	if (c == 'S') {
		sprintf(rpacket, "HN");
		if ((*sendpkt)(rpacket, 0, 1))
			return(0);
	}
	return('B');
}


/**/
/*
 *
 *      endp() end protocol
 *
*/
endp()
{
	sprintf(rpacket, "HY");
	(*sendpkt)(rpacket, 0, 2); /* dont wait for ACK */
	(*closepk)();
	return('P');
}


/**/
/***********************RECIEVE PROTOCOL**********************/
/*
 *  r d a t a
 *
 *  Receive Data
 */
rdata()
{
	int	len;
	if ((*getpkt)(rpacket, &len))
		return(0);
	if (len == 0) {
		close(fp);
		sprintf(rpacket, "CY");
		if ((*sendpkt)(rpacket, 0, 1))
			return(0);
		printmsg( 0, "transfer complete" );
		return('F');
	}
	write(fp, rpacket, len);/* Write the data to the file */
	return('D');/* Remain in data state */
}


/**/
/*
 *  r f i l e
 *
 *  Receive File Header
 */
rfile()
{

	char 	buf[256];
	char *	flds[10];
	int		numflds;

	int		len, i;
	char	tmpfilename[256]; /*Holds the converted file name */
	char	*cp;

	printmsg( 3, "rfile entered" );

	cp = buf;

	while ( TRUE ) {
		if ((*getpkt)( rpacket, &len ))
			return( 0 );
		strncpy( cp, rpacket, len );
		cp += len;
		if ( *(cp - 1) == '\0' ) break;
	}
	if (( buf[0] & 0x7f ) == 'H' )
		return( 'C' );

	printmsg( 3, "rfile: buf %d \"%s\"", len, buf );

	/* Convert upper case to lower */
	for (cp = buf; *cp != '\0';cp++)
		if (isupper(*cp)) tolower(*cp);

	numflds = getargs( buf, flds );

	cp = flds[2];
	printmsg( 3, "rfile: receive file \"%s\"", cp );

	/* check for ~/ destination -> /usr/spool/uucppublic */
	if ( strncmp( cp, "~/", 2 ) == SAME )
		sprintf( tmpfilename, "%s%s", pubdir, cp+1);
	else
		strcpy( tmpfilename, cp );
	printmsg( 3, "rfile: receive file \"%s\"", tmpfilename );

	/* check for dirname only */
	cp = tmpfilename + strlen( tmpfilename ) - 1;
	if ( *cp == '\n' )
		*cp-- = '\0';

	if ( *cp == '/' ) {

		fprintf( stderr, "rfile: fromfile %s\n", flds[1] );
		cp = rindex( flds[1], '/' );
		if ( cp == (char *) NULL )
			cp = flds[1];
		else
			cp++;

		fprintf( stderr, "rfile: dironly add   %s\n", cp );

		strcat( tmpfilename, cp );
	}
	printmsg( 3, "rfile: receive file \"%s\"", tmpfilename );


	/* let host munge filename as appropriate */
	importpath( tofile, tmpfilename );
	printmsg( 3, "rfile: receive file \"%s\"", tofile );

	if ((fp = CREAT( tofile, 0775, 'b' )) == -1) { /* Try to open a new file */
		printmsg( 0, "cannot create %s", tofile ); /* Give up if can't */
		return('A');
	}

	printmsg( 0, "Receiving %s as %s", flds[1], tofile );
	sprintf(rpacket, "SY");
	if ((*sendpkt)(rpacket, 0, 1))
		return(0);
	return('D'); /* Switch to data state */
}


/**/
/*
 *  r i n i t
 *
 *  Receive Initialization
 */
rinit()
{
	if ((*openpk)())
		return(0);
	return('F');
}




SHAR_EOF
chmod +x 'dcpxfer.c'
fi # end of overwriting check
#	End of shell archive
exit 0

--
{ubc-vision,uunet}!van-bc!sl				Stuart.Lynne@van-bc.uucp