[comp.sources.amiga] uupc version 1.1

ain@j.cc.purdue.edu (Patrick White) (03/21/88)

Program Name:	uupc  version 1.1  (part 1 of 3)
Submitted By:	Johan Widen  <jw@sics.se>
Summary:	Implements uucp for the Amiga -- allows your Amiga to become
		a uupc site for mail (and news?).
Poster Boy:  Pat White  (ain@j.cc.purdue.edu)
Uncompiled.

NOTES:
   Haven't tried to compile it.
   Converted the origional zoo to shars so docs, binaries & sources could
be separated.
   I'm pretty sure this would allow one to receive news, but I remember
something in the docs about it not having been tested from when I was
quickly scanning them... so I'm not too sure on this.
   Rob has been playing with it for a while and says it works.


-- Pat White   (co-moderator comp.sources/binaries.amiga)
UUCP: j.cc.purdue.edu!ain  BITNET: PATWHITE@PURCCVM   PHONE: (317) 743-8421
U.S.  Mail:  320 Brown St. apt. 406,    West Lafayette, IN 47906

========================================

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	Makefile
#	dcp.c
#	dcp.h
#	dcpgpkt.c
#	dcpsys.c
#	dcpxfer.c
# This archive created: Sat Mar 19 01:40:46 1988
# By:	Patrick White (PUCC Land, USA)
echo shar: extracting Makefile '(701 characters)'
cat << \SHAR_EOF > Makefile
CFLAGS=-b -r

all: uupc mail pccp

uupc: uuhost.o dcp.o dcpsys.o dcpxfer.o dcpgpkt.o rmail.o lib.o ulib.o ndir.o \
 genv.o sio.o timer.o serial.o sleep.o
	df0:c/blink with link.uupc.cmd

mail:   mailhost.o mail.o lmail.o mlib.o lib.o ndir.o genv.o raw.o sendpacket.o
	df0:c/blink with link.mail.cmd

pccp: pccp.o genv.o
	cc -o pccp pccp.o genv.o

dcp.o: dcp.h host.h genv.h
dcpgpkt.o: dcp.h host.h genv.h
dcpsys.o: dcp.h host.h genv.h ndir.h
dcpxfer.o: dcp.h host.h genv.h
genv.o: genv.h
lib.o: host.h genv.h
lmail.o: host.h genv.h
mail.o: host.h genv.h
mailhost.o: host.h genv.h
mlib.o: host.h genv.h
ndir.o: ndir.h
pccp.o: host.h
rmail.o: host.h genv.h
ulib.o: host.h genv.h
uuhost.o: host.h genv.h
SHAR_EOF
if test 701 -ne "`wc -c Makefile`"
then
echo shar: error transmitting Makefile '(should have been 701 characters)'
fi
echo shar: extracting dcp.c '(9330 characters)'
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
Maintenance Notes:
  25Aug87 - Added a version number - Jal
  25Aug87 - Return 0 if contact made with host, or 5 otherwise.
  04Sep87 - Bug causing premature sysend() fixed. - Randall Jessup.

*/
/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987
 * This program implements a uucico type file transfer and remote
 * execution type protocol.
 */
#define  VERSION "1.8 Camelot"
#include "dcp.h"
#include <signal.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;

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 );
	onBreak();
}

onBreak()
{
	extern char *orgDir;

	sysAbortEnd();
	chdir( orgDir );
	exit(100);
}

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

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


	mkfilename( s_logfile, logdir, LOGFILE );
	mkfilename( s_syslog,  logdir, 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 );

	fp = -1;
	fw = (FILE *)NULL;
	remote = MASTER;
	strcpy( Rmtname, "any" );
	remote = MASTER;


	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;
			}
		}
	}


	signal(SIGINT, onBreak);
	printmsg(0, "UUPC Version %s", VERSION );
	if ( remote == MASTER ) {
		printmsg( 0, "Calling %s    %d", Rmtname, debuglevel );
		if (( fsys = FOPEN( s_systems, "r", 't' )) == (char *)NULL )
			onBreak();
		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();
				Contact = TRUE;
				break;
			case 'Y':
				state = sysend();
				break;
			case 'Z':
				state = sysAbortEnd();
				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 );
	if (Contact )
	   return 0;
	else
	   return 5;
}


/**/
/*
**
**
**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 'R':
			state = mreceive();
			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 'd':	/* send file in slave mode */
			while ((state = sdata()) == 'D');
			break;
		case 'Z':
			state = reof();
			break;
		case 'A':
			return('Y'); /* "Abort" state */
		default:
			return('Y');
		}
	}
}


/**/
/*
 *  s e n d
 *
 *  This is the state table switcher for sending files in master mode.  It 
 *  loops until either it finishes, or an error is encountered.  The routines
 *  called by send() 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 'R':
			return ('R'); /* Receive a file */
		case 'A':
			return ('Y'); /* "Abort" */
		default:
			return ('Y'); /* Unknown, fail */
		}
	}
}


/**/
/*
 *  m r e c e i v e
 *
 *  This is the state table switcher for receiving files in master mode.  It
 *  loops until either it finishes, or an error is encountered.  The routines
 *  called by sendsw are responsible for changing the state.
 *
 */
mreceive()
{
	fp = -1;                /* reset file getter/opener */
	state = 'F';/* Receive initiate is the start state */
	while (TRUE)/* Do this as long as necessary */ {
		printmsg( 4, "send state: %c", state );
		switch (state) {
		case 'F':
			state = mrfile();
			break; /* Recive-File */
		case 'D':
			if((state = rdata()) == 'F')
				return('S');
			break; /* Receive-Data */
		case 'B':
			return ('S'); /* Complete */
		case 'A':
			state = mrabort(); /* "Abort" */
			break;
		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", command );

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


		unlink(cfile);
		if (input[0]) {
 			importpath( hostfile, input );
	 		unlink(hostfile);
		}
		if (output[0]) {
			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 );
			fflush( stdout );
		}
		fputs( msg, logfile );
	}
}
SHAR_EOF
if test 9330 -ne "`wc -c dcp.c`"
then
echo shar: error transmitting dcp.c '(should have been 9330 characters)'
fi
echo shar: extracting dcp.h '(2347 characters)'
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

#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
if test 2347 -ne "`wc -c dcp.h`"
then
echo shar: error transmitting dcp.h '(should have been 2347 characters)'
fi
echo shar: extracting dcpgpkt.c '(15366 characters)'
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

MAINTENANCE NOTES:
  25Aug87 - Allow for up to 7 windows - Jal

*/

#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 MAXBADINAROW 5		/* Max bad reads in a row */
#define TIMEOUT 4		/* could be longer */
#define KPKT    1024/PKTSIZE
#define POK      -1

#define MAXWINDOW 7
#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;
static int	badInARow = 0;
static int	fseq[NBUF], outlen[NBUF], inlen[NBUF], arr[NBUF];
static int	nwindows;
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, 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 = MAXWINDOW - 1;
	nwindows = MAXWINDOW;
	for (i = 0; i < NBUF; i++) {
		ftimer[i] = 0;
		arr[i] = FALSE;
	}
	/* 3-way handshake */
	timeout = 10; /* want some timeout capability here */
	gspack(7, 0, 0, 0, tmp);
rsrt:
	if (badInARow >= MAXBADINAROW || nerr >= MAXERR)
		return(-1);
	switch (grpack(&n1, &n2, &len, tmp)) {
	case 7:
		badInARow = 0;
		gspack(6, 0, 0, 0, tmp);
		nwindows = n1;
		if ( nwindows > MAXWINDOW )
		   nwindows = MAXWINDOW;
		rwu = nwindows - 1;
		goto rsrt;
	case 6:
		badInARow = 0;
		gspack(5, 0, 0, 0, tmp);
		goto rsrt;
	case 5:
		badInARow = 0;
		break;
	default:
		badInARow++;
		nerr++;
		gspack(7, 0, 0, 0, tmp);
		goto rsrt;
	}
	nerr = 0;
	return(0);      /* channel open */
}


gclosepk()
{
	int	i;
	char	tmp[PKTSIZE+1];
	timeout = 10;
	for (i = 0; i < MAXTRY && badInARow < MAXBADINAROW; 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 = 10;
	/* 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];
	movmem(inbuf[i2], cdata, *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 = 10; /* non-blocking reads */
	/* WAIT FOR INPUT i.e. if weve sent nwindows pkts and none have been */
	/* acked, wait for acks */
	while (nbuffers >= nwindows) 
		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) {
		strncpy(outbuf[i1], cdata, PKTSIZE);
		len = PKTSIZE;
		for (i = strlen(cdata); i < len; i++)
			outbuf[i1][i] = '\0';
	} else {
		movmem(cdata, outbuf[i1], 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");
		badInARow = 0;
		goto close;
	case NAK:
		nerr++;
		badInARow = 0;
		acktmr = naktmr = 0; /* stop ack/nak timer */
		printmsg( 5, "**got NAK %d", rack );
		rack = (rack + 1) % MAXSEQ;
		while (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 reply; /* any other stuff ? */

	case EMPTY:
		printmsg( 5, "**got EMPTY" );
		if(badInARow++ >= MAXBADINAROW)
			return(0);
		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++;
				rack = i2;
				while (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;
				}
				return(POK);
			}
		}
		return(POK);
	case ACK:
		printmsg( 5, "**got ACK %d", rack );
		badInARow = 0;
		acktmr = naktmr = 0; /* disable ack/nak's */
		while (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 */
		}
		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 );
		badInARow = 0;
		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;
				movmem(rdata, inbuf[i1], 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 );
		}
		while (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 */
		}
		if (dflg)
			return(POK); /* hack for non-mtask sys's */
	case ERROR:
		if(badInARow++ >= MAXBADINAROW)
			return(0);
		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:
		if(badInARow++ >= MAXBADINAROW)
			return(0);
		printmsg( 5, "**got SCREW UP" );
		goto reply; /* ignore it */
	}
close:
	gspack(CLOSE, 0, 0, 0, rdata);
	return(CLOSE);
}


/**/
/*************** FRAMING *****************************/
/*
 *
 *
 *      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] += nwindows;   
		break;
	case 6:
		pkt[4] += 1;
		break;   /* pktsiz = 64 (1) */
	case 7:
		pkt[4] += MAXWINDOW;   
		break;
	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;

	chkabort();
	c = '\0';
	while ((c & 0x7f) != '\020') {
		if (sread(&c, 1, timeout) <= 0)
			return(EMPTY);
	}
	if (sread(&grpkt[1], HDRSIZE - 1, timeout) < (HDRSIZE - 1))
		return(EMPTY);
	/*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 */
	}
	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';
	} else {       /* data packet */
		if (grpkt[1] != PKTSIZ2)
			return(-5);   /* cant handle other than 64*/
		if (sread(cnt1, PKTSIZE, timeout) < PKTSIZE)
			return(EMPTY);
		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
if test 15366 -ne "`wc -c dcpgpkt.c`"
then
echo shar: error transmitting dcpgpkt.c '(should have been 15366 characters)'
fi
echo shar: extracting dcpsys.c '(13004 characters)'
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"
static int timeOut = 30;/* default timeout when processing callup script */
			/* You can specify the timeout in the systems file */
			/*	DELAY10					*/
			/* sets the timeout to 10.			*/
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()
{
	extern int lineIsOpen;
	char	msg[80];

	if(lineIsOpen) {
		msg[1] = '\0';
		msgtime = 2 * MSGTIME;
		wmsg("OOOOOO", 2);
		rmsg(msg, 2);
	}
	closeline();
	if ( remote == MASTER )
		return('I');
	return('A');
}


/*
**
**sysAbortEnd
** break connection without any message
*/
sysAbortEnd()
{
	msgtime = 2 * MSGTIME;
	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;
{
	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;
	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;
{
	printmsg( 2, "sending %s", str );

#ifdef BREAK
	if (prefix("BREAK", str)) {
		/* send break */
		ssendbrk();
		return;
	}
#endif
	if (prefix("DELAY", str)) {
		str += 5;
		timeOut = atoi(str);
		str += strspn(str, "0123456789");
	}

	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()
{
	char	buf[4];

	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()
{
	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, timeOut );

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

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

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

			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);
		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	len;
	char	cname[40];

	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	len;
	char	cname[40];

	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:dir file = %s cfile = %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
if test 13004 -ne "`wc -c dcpsys.c`"
then
echo shar: error transmitting dcpsys.c '(should have been 13004 characters)'
fi
echo shar: extracting dcpxfer.c '(10190 characters)'
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"

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;

	strcpy(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;
	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 );
	if(!strchr(fromfile,':') && !strchr(fromfile,'/'))
	    unlink(fromfile);
	printmsg( 0, "transfer %s complete", fromfile );

	/*
	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 */
}




/**/
/*
 *  r e o f
 *
 *  Send End-Of-File and receive Ack in slave mode.
 */
reof()
{
	int	len;
	if ((*sendpkt)(spacket, 0, 0))
		return(0);
	if ((*getpkt)(spacket, &len))
		return(0); /* rec CY or CN */
	if (strncmp(spacket, "CY", 2))
		return(0); /* send failed */
	close(fp);
	fp = (-1);
 	importpath( hostfile, fromfile );
	printmsg( 0, "transfer %s complete", fromfile );

	/*
	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	len;
	int	toLength;
	char	*cp;
	int	nextState;

	if (fp == -1) {/* If not already open, */
		printmsg( 3, "looking for next file..." );
		if ((nextState = getfile()) == 'B') {
			fclose( fw );
			unlink( cfile );
			fw = (char *)NULL;
			return(nextState); /* end sending session */
		}
		if(nextState == 'R')
			return(nextState);

		/* check for ~/ path -> /usr/spool/uucppublic */
		if ( strncmp( fromfile, "~/", 2 ) == SAME )
			sprintf( hostfile, "%s%s", pubdir, 
				 fromfile + 1);
		else
			importpath( hostfile, fromfile );

		printmsg( 3, "   Opening %s for sending.", 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", hostfile );
			return('A');
		}
	} else
		return('A'); /* If somethings already open. were in trouble*/
	printmsg( 0, "Sending %s to %s", hostfile, tofile );
	/* S fromfile tofile user - tofile 0666 */
	toLength = strlen(tofile);
	cp = tofile;
	while(toLength >= pktsize) {
		strncpy(spacket, cp, pktsize);
		cp += pktsize;
		if ((*sendpkt)(spacket, 0, 1))
			return(0);
		toLength -= pktsize;
	}
	strcpy(spacket, cp);
	if ((*sendpkt)(spacket, 0, 1))
		return(0);
	if ((*getpkt)(spacket, &len))
		return(0);
	if (spacket[1] != 'Y')
		return('A'); 		/* If otherside says no-quit */
	size = bufill(spacket);
	return('D');
}


/**/
/*
 *  m r f i l e
 *
 *  Receive File Header.
 */
mrfile()
{
	int	len;
	int	fromLength;
	char	*cp;

	if (fp == -1) {/* If not already open, */
		/* check for ~/ path -> /usr/spool/uucppublic */
		if ( strncmp( tofile, "~/", 2 ) == SAME )
			sprintf( hostfile, "%s%s", pubdir, 
				 tofile + 1);
		else
	 		importpath( hostfile, tofile );

		printmsg( 3, "   Opening %s for receiving.", hostfile );
		if ((fp = CREAT( hostfile, 0775, 'b' )) == -1) {
			printmsg( 0, "Cannot create %s", hostfile );
			return('A');
		}
	} else
		return('A'); /* If somethings already open. were in trouble*/
	printmsg( 0, "Receiving %s from %s", hostfile, fromfile );
	/* R fromfile tofile user - tofile 0666 */
	fromLength = strlen(fromfile);
	cp = fromfile;
	while(fromLength >= pktsize) {
		strncpy(spacket, cp, pktsize);
		cp += pktsize;
		if ((*sendpkt)(spacket, 0, 1))
			return(0);
		fromLength -= pktsize;
	}
	strcpy(spacket, cp);
	if ((*sendpkt)(spacket, 0, 1))
		return(0);
	if ((*getpkt)(spacket, &len))
		return(0);
	if (spacket[1] != 'Y')
		return('A'); 			/* If otherside says no-quit*/
	size = bufill(spacket);
	return('D');
}


mrabort()
{
	if(fp != -1)
		close(fp);
	strcpy(rpacket, "CN5");
	if ((*sendpkt)(rpacket, 0, 1))
		return(0);
	printmsg( 0, "transfer failed" );
	return('Y');
}


/**/
/*
 *  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 or received.
 *  If there are no more then 'B' is returned. Otherwise 'S' or 'R' will
 *  be returned.
 *  We handle the following formats:
 *    R from to [other stuff]
 *    S from to [other stuff]
 */
getfile()
{
	char	line[132];
	char    from1[132];
	char    to1[132];
	char	user[64];
	char	mode[64];
	register char * cp;

	if ( !fgets( line, BUFSIZ, fw ) || (line[0] != 'R' && line[0] != 'S') )
		return('B');
	if(line[0] == 'R') {
	    sscanf(&line[2], "%s %s ", from1, tofile);
	    if(tofile[strlen(tofile) - 1] == '/') {
		if((cp = strrchr(from1,'/')) || (cp = strchr(from1,':')))
		    cp++;
		else
		    cp = from1;
		strcat(tofile, cp);
	    }
	    strcpy(fromfile, line);
	} else {
	    sscanf(&line[2], "%s %s %s - %s %s", from1, to1, user, fromfile,
		   mode);
	    if((to1[strlen(to1) - 1] == '/') && (cp = strchr(from1,':'))) {
		*cp = '/';
	    } else {
		cp = from1;
	    }
	    sprintf(tofile,"S %s %s %s - %s %s\n", cp, to1, user, fromfile,
		    mode);
	}
 	printmsg(3, "   getfile: fromfile=%s, tofile=%s.", fromfile, tofile);
	return(line[0]);
}


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


/**/
/*
 *
 *      endp() end protocol
 *
*/
endp()
{
	strcpy(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);
		strcpy(rpacket, "CY");
		if ((*sendpkt)(rpacket, 0, 1))
			return(0);
		printmsg( 0, "transfer complete" );
		return('F');
	}
	if ( write(fp, rpacket, len) != len ) /* Write the data to the file */
	   {
		printmsg( 0, "Error Writing File" );
		return 'A';
	   }
	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;
	char	tmpfilename[256]; /*Holds the converted file name */
	char	*cp, *cp2;

	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))
		    *cp = tolower(*cp); */

	numflds = getargs( buf, flds );

	if(buf[0] == 'R') {
		cp = flds[1];
		cp2 = flds[2];
		printmsg( 3, "rfile: send file \"%s\"", cp );
	} else {
		cp = flds[2];
		cp2 = flds[1];
		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 );
	if(buf[0] == 'R')
		printmsg( 3, "rfile: send file \"%s\"", tmpfilename );
	else
		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", cp2 );
		cp = rindex( cp2, '/' );
		if ( cp == (char *) NULL )
			cp = cp2;
		else
			cp++;

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

		strcat( tmpfilename, cp );
	}
	if(buf[0] == 'R') {
		printmsg( 3, "rfile: send file \"%s\"", tmpfilename );
		/* let host munge filename as appropriate */
		importpath( fromfile, tmpfilename );
		printmsg( 3, "rfile: send file \"%s\"", tofile );
		if ((fp = open( fromfile, 0)) == -1) {
			printmsg( 0, "cannot open %s", fromfile );
			return('A');
		}
		printmsg( 0, "Sending %s to %s", fromfile, flds[2] );
		strcpy(spacket, "RY");
		if ((*sendpkt)(spacket, 0, 1))
			return(0);
		size = bufill(spacket);
		return('d'); /* Switch to data state */
	} else {
		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) {
			printmsg( 0, "cannot create %s", tofile );
			return('A');
		}
		printmsg( 0, "Receiving %s to %s", flds[1], tofile );
		strcpy(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
if test 10190 -ne "`wc -c dcpxfer.c`"
then
echo shar: error transmitting dcpxfer.c '(should have been 10190 characters)'
fi
#	End of shell archive
exit 0

ain@j.cc.purdue.edu (Patrick White) (03/21/88)

Program Name:	uupc  version 1.1  (part 2 of 3)
Submitted By:	Johan Widen  <jw@sics.se>
Summary:	Implements uucp for the Amiga -- allows your Amiga to become
		a uupc site for mail (and news?).
Poster Boy:  Pat White  (ain@j.cc.purdue.edu)
Uncompiled.

NOTES:
   Didn't try compiling it.
   Converted the origional zoo to shars so docs, binaries & sources could
be separated.
   I'm pretty sure this would allow one to receive news, but I remember
something in the docs about it not having been tested from when I was
quickly scanning them... so I'm not too sure on this.
   Rob has been playing with it for a while and says it works.


-- Pat White   (co-moderator comp.sources/binaries.amiga)
UUCP: j.cc.purdue.edu!ain  BITNET: PATWHITE@PURCCVM   PHONE: (317) 743-8421
U.S.  Mail:  320 Brown St. apt. 406,    West Lafayette, IN 47906

========================================

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	genv.c
#	genv.h
#	host.h
#	lib.c
#	lmail.c
#	mail.c
#	mailhost.c
#	mlib.c
#	ndir.c
#	ndir.h
#	pccp.c
# This archive created: Sat Mar 19 01:41:50 1988
# By:	Patrick White (PUCC Land, USA)
echo shar: extracting genv.c '(7740 characters)'
cat << \SHAR_EOF > genv.c
/* 		genv.c
 
 
 
		copyright (C) 1987 Jeff Lydiatt
 
		Copying and use of this program are controlled by the terms of the
		Free Software Foundations GNU Emacs General Public License.
 
 
		version		0.1		10 July 87

*/
 
#include <stdio.h>
#include <ctype.h>

#include "genv.h"

extern int debuglevel;
     /* Environment variables are in file "PROFILE" */
#define PROFILE ":usr/lib/uucp/profile"

#define SAME	0
#define MAXLINE 255

#define DMAILBOX	"mailbox"
#define	DNAME		"noname"
#define	DDOMAIN		"pc.uucp"
#define	DMAILDIR	":usr/spool/mail"
#define DHOME		":usr/noname"
#define	DCONFDIR	":usr/lib/uucp"
#define	DSPOOLDIR	":usr/spool/uucp"
#define DLOGDIR		":usr/spool/uucp"
#define DPUBDIR		":usr/spool/uucppublic"
#define DNEWSDIR	":usr/spool/rnews"
#define DTEMPDIR	"RAM:T"
#define	DMAILSERVICE	"host"
#define	DNODENAME	"noname"
#define	DDEVICE		"CON:"
#define	DSPEED		"1200"
#define DPAGESIZE	"24"
#define DTIMEZONE	"+0100"

#define	TFILENAME	"tmpfile"
#define	FILENAME 	"%s/%s"

char	*name = NULL;
char	*mailbox = NULL;
char	*home = NULL;
char	*domain = NULL;
char	*maildir = NULL;
char	*confdir = NULL;
char 	*spooldir = NULL;
char	*logdir = NULL;
char	*pubdir = NULL;
char	*mailserv = NULL;
char	*nodename = NULL;
char	*device = NULL;
char	*speed = NULL;
char	*tempdir = NULL;
char	*newsdir = NULL;
int	pagesize = 24;
static char *pagesizeString = NULL;
char	*timeZone = NULL;

/*--------------------------------------------------------------*/
/*	getsym: get next symbol from file f.  f already open	*/
/*--------------------------------------------------------------*/

#define ID	1001
#define DELIM	1002
#define STR	1003
#define EOL	1004
#define OTHER	1005
#define UNKNOWN -1000

static int getsym( f, sym )
FILE *f;
char *sym;
{
   /* Simple non reentrant, non reuseable get next symbol from file f */
   /* Valid symbols are:
        Type	Symbol Returned	Comment

	ID	<identifier>	any valid c identifier.
        DELIM	'='		an equal sign.
	STR	a string	anything between "" or ''.
	EOL	'\n'		a newline.
	EOF			the end of file character.
	OTHER   a character	anything else.
	
	Comments begin with # and are delimited by an end of line
   */

   static int lastchar = UNKNOWN;
   int c, delim;

   /* strip leading white space */

   if ( lastchar != UNKNOWN )
      c = lastchar;
   else
      c = fgetc( f );

   while ( c == ' ' || c == '\t' )
      c = fgetc( f );
   lastchar = UNKNOWN;
 
  /* Comments are '#' delimited by EOL character */

   if ( c == '#' )
      while ( c != '\n' && c != EOF )
	 c = fgetc( f );

   if ( c == EOF )		/* End of file? */
      return EOF;

   if ( c == '\n' )		/* End of Line? */
     {
	strcpy( sym, "\n" );
	return EOL;
     }

   if ( c == '=' )		/* Delimiter '='? */
     {
	strcpy( sym, "=" );
	return DELIM;
     } 

   if ( c == '\"' || c == '\'' )/* String ? */
     {
	delim = c;
	while ( (c = fgetc( f )) != delim && c != EOF && c != '\n' )
	   *sym++ = c;
	*sym = '\0';
	c = fgetc( f );
	return STR;
     }

   if ( isalpha( c ) )		/* Identifier ? */
     {
	*sym++ = c;
	while ( ( c = fgetc( f )) == '_' || isalnum(c) )
	  *sym++ = c;
	*sym = '\0';
	lastchar = c;
	return ID;
     }

   *sym++ = c;
   *sym = '\0';
   return OTHER;

}
	
/*--------------------------------------------------------------*/
/*	xmalloc: Just alloc with die on allocation failure	*/
/*--------------------------------------------------------------*/
static char *xmalloc( size )
unsigned int size;
{
	char *malloc();
	register char *p;


	if ( (p = malloc( size )) != NULL )
	   return p;

	fprintf( stderr, "Genv.c: Can't allocated %u bytes\n", size );
	exit( NULL );
}

/*--------------------------------------------------------------*/
/*	setenv: insert an environment variable into my list	*/
/*--------------------------------------------------------------*/

struct environment
   {
	struct environment *next;
	char *name;
	char *value;
   };

typedef struct environment ENV;

static ENV *envList = NULL;

static void setenv( var, value )
char *var;
char *value;
{
	register ENV *envframe;

	envframe = (ENV *) xmalloc( sizeof( ENV ));
	envframe->name  = xmalloc( strlen(var)+1 );
	envframe->value = xmalloc( strlen(value)+1 );
	envframe->next  = envList;
	envList		= envframe;
	
	strcpy( envframe->name, var );
	strcpy( envframe->value, value);
}

/*--------------------------------------------------------------*/
/*	getenv: get pointer to value of environment variable	*/
/*--------------------------------------------------------------*/

static char *getenv( var )
char *var;
{
	register ENV *list;

	for ( list = envList;
	      list != (ENV *)NULL;
	      list = list->next )
	   if ( strcmp( var, list->name ) == SAME )
		return list->value;

	return NULL;
}

/*--------------------------------------------------------------*/
/*	readenv: read environment from a file. 			*/
/*--------------------------------------------------------------*/

static void readenv()
{
   FILE *f;
   int symval;
   char name[MAXLINE+1], value[MAXLINE+1];

   if ( (f = fopen( PROFILE, "r" )) == NULL )
     {
	fprintf( stderr, "Can't open profile file \"%s\"\n",
	PROFILE );
	exit( NULL );
     }

    /* File is layed out as follows:

    <environment variable> '=' <ID> | <STRING> # comment....

     */
 
    while ( (symval = getsym( f, name )) != EOF )
      {
	/* Skip over any comment lines */

	while ( symval == EOL )
	   symval = getsym( f, name );
	if ( symval == EOF )
	   break;

	if ( symval != ID )
	  {
	     fprintf( stderr, "Bad environment variable name %s\n", name );
	     exit( NULL );
	  }

	if ( (symval = getsym( f, value )) != DELIM )
	  {
	     fprintf( stderr, "Missing '=' in environment file\n" );
	     exit( NULL );
	  }

	if ( (symval = getsym( f, value )) != ID && symval != STR )
	  {
	     fprintf( stderr, "missing value in environment file\n");
	     exit( NULL );
	  }

	setenv( name, value );
      }
    fclose( f );

}

/*--------------------------------------------------------------*/
/*	exitenv: free that memory when done!			*/
/*--------------------------------------------------------------*/

void exitenv()
{
	register ENV *p, *q;	

	for ( p = envList; p != NULL; p = q )
	  {
		free( p->name );
		free( p->value);
		q = p->next;
		free( p );
	  }
	envList = NULL;
}

static void genv(thename, envname, dflt)
char **thename;
char *envname;
char *dflt;
{
	if ((*thename = getenv( envname )) == NULL) {
		fprintf( stderr, "genv: %s not found, using %s\n", envname, dflt );
		*thename = dflt;
	}
	/* fprintf( stderr, "genv: %s \"%s\"\n", envname, *thename ); /**/
}

void loadenv()
{

	readenv();	/* read the profile from a file */ 

	/* get environment var's */
	genv( &name, NAME, DNAME );
	genv( &mailbox, MAILBOX, DMAILBOX );
	genv( &home, HOME, DHOME );
	genv( &domain, DOMAIN, DDOMAIN );
	genv( &maildir, MAILDIR, DMAILDIR );
	genv( &confdir, CONFDIR, DCONFDIR );
	genv( &spooldir, SPOOLDIR, DSPOOLDIR );
	genv( &logdir, LOGDIR, DLOGDIR );
	genv( &pubdir, PUBDIR, DPUBDIR );
	genv( &mailserv, MAILSERVICE, DMAILSERVICE );
	genv( &nodename, NODENAME, DNODENAME );
	genv( &device, DEVICE, DDEVICE );
	genv( &speed, SPEED, DSPEED );
	genv( &tempdir, TEMPDIR, DTEMPDIR );
	genv( &newsdir, NEWSDIR2, DNEWSDIR );
	genv( &pagesizeString, PAGESIZE, DPAGESIZE );
	pagesize = atoi(pagesizeString);
	genv( &timeZone, TIMEZONE, DTIMEZONE );
}
 
void mkfilename( filename, dirname, name )
char * filename;
char * dirname;
char * name;
{
	sprintf( filename, FILENAME, dirname, name );	
	if(debuglevel > 4)
		fprintf( stderr, "New filename %s\n", filename );  /**/	
}


#ifdef TEST
main()
{
	register ENV *p;	

	loadenv();

	for ( p = envList; p != NULL; p = p->next )
	  fprintf( stderr, "Name=\"%s\" value=\"%s\"\n", 
		   p->name, p->value );
	
}
#endif



SHAR_EOF
if test 7740 -ne "`wc -c genv.c`"
then
echo shar: error transmitting genv.c '(should have been 7740 characters)'
fi
echo shar: extracting genv.h '(1960 characters)'
cat << \SHAR_EOF > genv.h
/*	genv.c
 
 
 
	copyright (C) 1987 Stuart Lynne
 
	Copying and use of this program are controlled by the terms of the
	Free Software Foundations GNU Emacs General Public License.
 
 
	version		0.1		March 31/1987
 
	
 
environment variables
 
	The following evironment variables are defined:
 
	MAILBOX		current user's mailbox, 	"sl"
	NAME		current user's name, 		"Stuart Lynne"
	DOMAIN		domain of this machine, 	"mac.van-bc.can"
	MAILDIR		where mail is kept,		"/usr/mail"
	CONFDIR		where config data is  kept,	"/usr/lib/uucp"
	SPOOLDIR	where spooled files are 	"/usr/spool/uucp"
	LOGDIR		where log file are placed	"/usr/spool/uucp"
	PUBDIR		public spool directory		"/usr/spool/uucppublic"
	NEWSDIR		news directory			"/usr/spool/news"
	TEMPDIR		where temp files are created	"/tmp"
	HOME		where uses private files are	"/usr/sl"
	MAILSERVICE	who do we send remote mail	"van-bc"
	NODENAME	what is our local nodename	"slmac"
	DEVICE		what is the default device	".a"
	SPEED		what is the default speed	"1200"
	PAGESIZE	lines per page in mail pager	"24"
	TIMEZONE	to be appended to Date: field	"+0100"
 
*/
 

#define	MAILBOX		"MAILBOX"
#define	NAME		"NAME"
#define	DOMAIN		"DOMAIN"
#define	MAILDIR		"MAILDIR"
#define HOME		"HOME"

#define	CONFDIR		"CONFDIR"
#define SPOOLDIR	"SPOOLDIR"
#define LOGDIR		"LOGDIR"
#define	PUBDIR		"PUBDIR"
#define NEWSDIR2	"NEWSDIR"
#define TEMPDIR		"TEMPDIR"
#define	MAILSERVICE	"MAILSERVICE"

#define NODENAME	"NODENAME"
#define	DEVICE		"DEVICE"
#define	SPEED		"SPEED"
 
#define PAGESIZE	"PAGESIZE"

#define TIMEZONE	"TIMEZONE"

extern char	*mailbox;
extern char	*name;
extern char	*domain;
extern char	*maildir;
extern char	*home;

extern char	*confdir;
extern char	*spooldir;
extern char	*logdir;
extern char	*pubdir;
extern char	*tempdir;
extern char	*mailserv;

extern char	*nodename;
extern char	*device;
extern char	*speed;
extern char	*newsdir;

extern int	pagesize;

extern char	*timeZone;

void loadenv();
void mkfilename();
SHAR_EOF
if test 1960 -ne "`wc -c genv.h`"
then
echo shar: error transmitting genv.h '(should have been 1960 characters)'
fi
echo shar: extracting host.h '(829 characters)'
cat << \SHAR_EOF > host.h
 /*		Amiga.h

		Amiga version

*/

#include <time.h>
#include <errno.h>
#include <ctype.h>
#ifndef MANX
#include <string.h>
#include <stdlib.h>
#endif

#ifndef AMIGA
#define AMIGA   1
#endif
#define SAME 	0
#ifndef TRUE
#define TRUE	1
#define FALSE   0
#endif

#define	TFILENAME	"tmpfile.%.7d"
#define	SFILENAME	"SEQF"

#define SEPCHAR		'/'		/* path separator	*/
#define SIGFILE		".signature"	/* file containing signature	*/
#define COPYFILE	"mail.sent"	/* copy of sent mail	*/

#define BREAK		/* BREAK command is defined in "systems" */
#define HOSTINIT	/* name of function used to initialize	*/

#define FILEMODE(f)

#define	CALLFILE	"C.%s"
#define	XQTFILE		"X.%s"

#ifndef MANX
#define index		strchr
#define rindex		strrchr
#endif

#include "genv.h"

extern	char * fgets();
extern	char * index();

extern 	int	debuglevel;




SHAR_EOF
if test 829 -ne "`wc -c host.h`"
then
echo shar: error transmitting host.h '(should have been 829 characters)'
fi
echo shar: extracting lib.c '(2757 characters)'
cat << \SHAR_EOF > lib.c
/* 		lib.c

*/

#include <dos.h>
#include <exec/memory.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <stdio.h>
#include "host.h"

#ifndef NULL
#define NULL 0L
#endif

char *index();
char *rindex();

MKDIR( path )
char * path;
{
	char * cp = path;

	if ( *cp == '\0' )
		return( 0 );

	/* see if we need to make any intermediate directories */
	while ( ( cp = index( cp, '/' ) ) != (char *) NULL ) {
		*cp = '\0';
		mkdir( path );
		*cp = '/';
		cp++;
	}

	/* make last dir */
	return( mkdir( path ) );

}

CHDIR( path )
char * path;
{
	char * cp = path;

	if ( *cp == '\0' )
		return( 0 );

	MKDIR( path );

	/* change to last directory */
	return( chdir( path ) );

}

FILE * FOPEN( name, mode, ftype )
char * name;
char * mode;
char ftype;
{

	char * last;
	FILE * results;

	/* are we opening for write or append */

	FILEMODE( ftype );
	results = fopen( name, mode );

	if ( results != (FILE *) NULL || *mode == 'r' )
		return( results );

	/* are we opening in sub-directory */
	last = rindex( name, '/' );

	/* lets just verify that all sub-dir's exist */
	if ( last != (char *) NULL ) {
		*last = '\0';
		MKDIR( name );
		*last = '/';
	}

	/* now try open again */
	return( fopen( name, mode ));

}

int CREAT( name, mode, ftyp )
char * name;
int mode;
char ftyp;
{

	char * last;
	int results;

	/* are we opening for write or append */
	FILEMODE( ftyp );
	results = creat( name, mode );

	if ( results != -1 )
		return( results );

	/* are we opening in sub-directory */
	last = rindex( name, '/' );

	/* lets just verify that all sub-dir's exist */
	if ( last != (char *) NULL ) {
		*last = '\0';
		MKDIR( name );
		*last = '/';
	}

	/* now try open again */
	return( creat( name, mode ) );

}

extern FILE *logfile;
extern int debuglevel;
extern int remote;

#define MASTER 1


int getargs( line, flds )
char *line;
char **flds;
{
	int i = 0;

	while ( (*line != '\0') && (*line != '\n') )
	{
	   if ( isspace(*line) )
	   {
	      line++;
	      continue;
	   }
	   *flds++ = line;
	   i++;
	   while( (isspace(*line) == 0) && (*line != '\0') ) line++;
	   if (isspace(*line)) *line++ = '\0';
	}
	return(i);
}

/* Behaves almost like the Lattice dfind function, but dfindOne will not
 * keep a lock.
 */

int dfindOne(info, name, attr)
struct FILEINFO *info;
char *name;
int attr;
{
    BPTR lock;
    struct FILEINFO *tmpInfo;
    int retVal;

    if(!(lock = Lock(name, ACCESS_READ)))
	return(-1);
    tmpInfo = (struct FILEINFO *) AllocMem(sizeof(*tmpInfo), MEMF_CLEAR);
    if(retVal = Examine(lock, tmpInfo))
	movmem((char *) tmpInfo, (char *) info, sizeof(*tmpInfo));
    FreeMem((char *) tmpInfo, sizeof(*tmpInfo));
    UnLock(lock);
    if(retVal && (attr || info->fib_DirEntryType < 0))
	return(0);
    else
	return(-1);
}
SHAR_EOF
if test 2757 -ne "`wc -c lib.c`"
then
echo shar: error transmitting lib.c '(should have been 2757 characters)'
fi
echo shar: extracting lmail.c '(10108 characters)'
cat << \SHAR_EOF > lmail.c
/*			lmail.c

		copyright (C) 1987 Stuart Lynne

	Copying and use of this program are controlled by the terms of the
	Free Software Foundations GNU Emacs General Public License.


		version		0.1		March 31/1987


description

	An 822 compatible (hopefully) mail delivery system for pc's.

	Designed for delivering mail on a pc based system. It will put
	local mail (ie, not @ or ! in address) into files in the default
	mail directory.

	If remote it will put into an outgoing mailbag in the default mail
	directory. Performs a simple bundling of mail messages into one
	file with arguments prepended as To: arg header lines. And adds a
	Message-Lines: header which gives the number of lines in the
	content part of the message (after the first blank line).

		pcmail john jack jill@xyz.uucp < afile

		To: john, jack, jill@xyz.uucp

		...
		...
		...

	It also adds the from From and Date lines. Subject: lines may be inserted
	by placing them at the beginning of the message.

	A Unix version should lock the /usr/mail/mailbag file.

environment variables

	The following evironment variables are used:

		MAILBOX		current user's mailbox, "stuart"
		NAME		current user's name, 	"Stuart Lynne"
		DOMAIN		domain of this machine, "slynne.mac.van-bc.can"
		MAILDIR		where is mail kept,	"mpw:mail"

*/

#include <dos.h>
#include <stdio.h>
#include "host.h"

char *_TZ = "GMT0";

FILE *FOPEN();

#define FORWARD		"Forward to"


static FILE   *mailfile;
static FILE   *tempfile;

static char	buf[BUFSIZ];
static char	miscBuf[100];
static char    *inFileName;
static long int sequence = 0;

static long tloc;
static char chartime[40];	/* current time in characters */
static char *thetime;

static char	tfilename[100];
extern char	mfilename[];
static char	mailsent[100];

static char 	remotes[BUFSIZ];

static char *uucp = "uucp";

char *fgets();
int fputs();

extern int debuglevel;

static char	Subject[132] = "";

extern long DOSBase;
static char *mcurdir;
static char s_mcurdir[128];	/* current directory path (save malloc call) */
char * getcwd();
int chdir();


lmail(argc, argv, inname)
int argc;
char **argv;
char *inname;
{
	int argcount;
	char **argvec;
	int i;
	char timeBuf[40];

	if (debuglevel > 5) {
		fprintf(stderr,"pcmail: argc %d ", argc);
		argcount = argc;
		argvec = argv;
		while (argcount--)
			fprintf(stderr," \"%s\"", *argvec++);
		fprintf(stderr,"\n");

		time(&tloc);
		thetime = ctime(&tloc);
		sprintf(timeBuf,"%.3s, %.2s %.3s %.2s %.8s %s\n", thetime,
			thetime + 8, thetime + 4, thetime + 22, thetime + 11,
			timeZone);
		thetime = timeBuf;
		fprintf(stderr,"thetime: %s",thetime);
	}

	mcurdir = getcwd(s_mcurdir, sizeof(s_mcurdir));
	chdir(spooldir);

	/* get sequence number */
	mkfilename(tfilename, confdir, SFILENAME);

 	if (debuglevel > 4)
		fprintf(stderr,"pcmail: opening %s\n", tfilename);

	if(tempfile = FOPEN(tfilename,"r", 't')) {
		fscanf(tempfile,"%ld", &sequence);
		fclose(tempfile);
	}
 	else
 		fprintf(stderr,"pcmail: can't find %s file, creating\n",
 			tfilename);

	/* update sequence number */
	if (debuglevel > 5)
		fprintf(stderr,"pcmail: new sequence # %ld\n", sequence);

	if(tempfile = FOPEN(tfilename,"w", 't')) {
		fprintf(tempfile,"%ld\n", (sequence+1)%10000);
		fclose(tempfile);
	}

	if(!(inFileName = inname)) {
	 	sprintf(miscBuf, TFILENAME, sequence);
 		mkfilename(tfilename, tempdir, miscBuf);
		inFileName = tfilename;
	
	 	if (debuglevel > 5) 
 			fprintf(stderr,"pcmail: opening %s\n", inFileName);

		if (!(tempfile = FOPEN(inFileName,"w", 'b'))) {
			fprintf(stderr,"pcmail: can't open %s\n", inFileName);
			exit(1);
		}
		/* copy stdin to tempfile */
		while (i = fread(buf, 1, sizeof(buf), stdin)) {
			fwrite(buf, i, 1, tempfile);
		}
/* mail compiled with Lattice crashes if we use the following. Why? */
/*		buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0;
		while (fgets(buf, sizeof(buf) - 2, stdin)) {
			if(buf[0])
				fputs(buf, tempfile);	
		} */
	} else {
		if (!(tempfile = FOPEN(inFileName,"a", 'b'))) {
			fprintf(stdout,"pcmail: can't open %s\n",inFileName);
			return(0);
		}
	}
	/* append signature */
	mkfilename(mfilename, home, SIGFILE);

	if (debuglevel > 4)
		fprintf(stderr,"pcmail: opening sigfile %s\n", mfilename);
	if(mailfile = FOPEN(mfilename,"r", 't')) {
		fputs("\n---\n", tempfile);
		buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0;
		while (fgets(buf, sizeof(buf) - 2, mailfile)) {
			if(buf[0])
				fputs(buf, tempfile);
		}
		fclose(mailfile);
 	}

 	fclose(tempfile);

	/* loop on args, copying to appropriate postbox,
	 *  do remote only once
	 *  remote checking is done empirically, could be better
	 */
	remotes[0] = 0;

	if (!strcmp(argv[1],"-s")) {
		argv += 2;
		argc -= 2;
		if (argc <= 0)
			return(-1);
		strcpy(Subject, *argv);
	}
	argcount = argc;
	argvec = argv;

	while (--argcount > 0) {
		argvec++;
		if (debuglevel > 5)
			fprintf(stderr,"pcmail: arg# %d %s\n", argcount,
				 *argvec);
		if (strchr(*argvec, '!') || strchr(*argvec, '@') ||
		    strchr(*argvec, '%')) {
			if (debuglevel > 5)
				fprintf(stderr,"pcmail: send to remote\n");
			/* can we cram one more address on line */
			if((strlen(remotes) + strlen(*argvec) + 3) >
			    sizeof(remotes)) {
				/* dump it then, to bad */
				sendone(argc, argv, remotes, TRUE);
				remotes[0] = 0;
			}
			/* add *arvgvec to list of remotes */
			strcat(remotes," ");
			strcat(remotes, *argvec);
		}
		else {
			if (debuglevel > 5)
				fprintf(stderr,"pcmail: calling sendone %s\n",
					*argvec);
			sendone(argc, argv, *argvec, FALSE);
		}
	}
	/* dump remotes if necessary */
	if (remotes[0])
		sendone(argc, argv, remotes, TRUE);

/*	mkfilename(mailsent, home, COPYFILE);
	if (debuglevel > 4)
	   fprintf(stderr,"pcmail: copfile = %s\n", mailsent);
	sendone(argc, argv, mailsent, FALSE); */

	unlink(tfilename);
	chdir(mcurdir);
	return(0);
}


/* sendone copies file plus headers to appropriate postbox
   NB. we do headers here to allow flexibility later, for example
   in being able to do bcc, per host service processing etc.
*/
sendone(argc, argv, address, remote)
int argc;
char **argv;
char *address;
int remote;
{
	register char 	*cp;
	char	icfilename[32];		/* local C. copy file */
	char	ixfilename[32];		/* local X. xqt file */
	char	idfilename[32];		/* local D. data file */
	char	rxfilename[32];		/* remote X. xqt file */
	char	rdfilename[32];		/* remote D. data file */
 	char	tmfilename[32];		/* temporary storage */
	struct FILEINFO info;

 	if (remote) {
 		/* sprintf all required file names */
		sprintf(tmfilename,"%c.%.7s%04d", 'C', mailserv, sequence);
		importpath(icfilename, tmfilename);
		sprintf(tmfilename,"%c.%.7s%04d", 'D', mailserv, sequence);
		importpath(idfilename, tmfilename);
		sprintf(tmfilename,"%c.%.7s%04d", 'D', nodename, sequence);
		importpath(ixfilename, tmfilename);
		sprintf(rdfilename,"%c.%.7s%04d", 'D', nodename, sequence);
		sprintf(rxfilename,"%c.%.7s%04d", 'X', nodename, sequence);
 	}
 	else {
		/* postbox file name */
 		if (!strchr(address, SEPCHAR))
			mkfilename(idfilename, maildir, address);
		else
			strcpy(idfilename, address);
	}

	if (debuglevel > 5)
 		fprintf(stderr,"pcmail: sendone: %s\n", idfilename);

 	if (remote == FALSE) {
		if (debuglevel > 5)
			fprintf(stderr,"pcmail: sendone: check for remote\n");
		/* check for forwarding */
		if (!dfindOne(&info, idfilename, 0) && info.fib_Size > 10 &&
		    (mailfile = FOPEN(idfilename,"r", 'b'))) {
			cp = fgets(buf, sizeof(buf), mailfile);
			fclose(mailfile);
			if (cp && !strncmp(buf, FORWARD, 10)) {
				strcpy(buf, buf+11);
				return(sendone(argc, argv, buf, FALSE));
			}
		}
	}

	/* open mailfile */
	if (!(mailfile = FOPEN(idfilename,"a", 'b'))) {
		fprintf(stdout,"pcmail: cannot append to %s\n", idfilename);
		return(0);
	}
	if (debuglevel > 5)
		fprintf(stderr,"pcmail: append to mailfile\n");

	time(&tloc);
	thetime = ctime(&tloc);
	sprintf(chartime,"%.3s, %.2s %.3s %.2s %.8s %s", thetime,
		thetime + 8, thetime + 4, thetime + 22, thetime + 11,
		timeZone);
 	thetime = chartime;	/* and work with our own copy */

	fprintf(mailfile,"From %s %s", mailbox, thetime);
	if (remote)
		fprintf(mailfile," remote from %s", nodename);
	fputc('\n', mailfile);
	fprintf(mailfile,"Received: by %s (pcmail) %s\n", domain, thetime);
	fprintf(mailfile,"Date: %s\n", thetime);
	/* add Date:, From: and Message-ID: headers */
	fprintf(mailfile,"From: %s <%s@%s>\n", name, mailbox, domain);
	fprintf(mailfile,"Message-ID: <%ld@%s>\n", sequence, domain);
	/* add To: headers */
	fprintf(mailfile,"To: %s", *++argv);
	argc--;
	while (--argc > 0)
		fprintf(mailfile,", %s", *++argv);
	fputc('\n', mailfile);
	if (strlen(Subject))
		fprintf(mailfile,"Subject: %s\n", Subject);
	fputc('\n', mailfile);

	/* copy spoolfile to postbox file */
	if (debuglevel > 4)
		fprintf(stderr,"pcmail: copy spoolfile %s to %s\n", inFileName,
			idfilename);
	if (!(tempfile = FOPEN(inFileName,"r", 'b'))) {
		fprintf(stdout,"pcmail: can't open %s\n", inFileName);
		return(0);
	}
	buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0;
	while (fgets(buf, sizeof(buf) - 2, tempfile)) {
		if (!strncmp(buf,"From ", 5))
			fputc('>', mailfile);
		if(buf[0])
			fputs(buf, mailfile);
 	}

	/* close files */
	fclose(mailfile);
	fclose(tempfile);

	/* all done unless going to remote via uucp */
	/* must create the job control files */
	if (remote) {
		/* create remote X xqt file */
		if(!(mailfile = FOPEN(ixfilename,"w", 'b'))) {
			fprintf(stdout,"pcmail: cannot open %s\n", ixfilename);
			return(0);
		}
		fprintf(mailfile,"U %s %s\n", uucp, nodename);
		fprintf(mailfile,"F %s\n", rdfilename);
		fprintf(mailfile,"I %s\n", rdfilename);
		fprintf(mailfile,"C rmail %s\n", address);
		fclose(mailfile);

		/* create local C copy file */
		if(!(mailfile = FOPEN(icfilename,"w", 't'))) {
			fprintf(stdout,"pcmail: cannot open %s\n", icfilename);
			return(0);
		}
		fprintf(mailfile,"S %s %s %s - %s 0666 %s\n", idfilename,
			rdfilename, uucp, idfilename, uucp);
		fprintf(mailfile,"S %s %s %s - %s 0666 %s\n", ixfilename,
			rxfilename, uucp, ixfilename, uucp);
		fclose(mailfile);
	}

	return(1);
}
SHAR_EOF
if test 10108 -ne "`wc -c lmail.c`"
then
echo shar: error transmitting lmail.c '(should have been 10108 characters)'
fi
echo shar: extracting mail.c '(12248 characters)'
cat << \SHAR_EOF > mail.c
/*
 *	mail.c
 */

/* The users refers to the letters with a number between 1 and numberOfLetters,
 * message 1 being the most recent.
 *
 * The messages are refered to internally with a number between 0 and
 * numberOfLetters - 1, with message numberOfLetters - 1 being the most recent.
 */

#include <dos.h>
#include <stdio.h>
#include "host.h"

#define  VERSION "1.4 Camelot"

FILE *FOPEN();
FILE *freopen();

/* int	debuglevel = 1; */

#define LSIZE   	256
#define SHORTLSIZE	132

static char	line[LSIZE];
static char	resp[LSIZE];

char	mfilename[SHORTLSIZE];

struct ldesc {
   int   	delete;		/* status of this message */
   long		adr;		/* address of From line */
   long		date;		/* address of Date: line */
   long		subject;	/* address of Subject: line */
   long		from;		/* address of From: line */
   long		size;		/* number of lines */
   struct ldesc *suc;		/* link to previous letter */
   struct ldesc *prev;		/* link to next letter */
};

static struct ldesc *newLetter(struct ldesc *);
static struct ldesc *letterN(int);

static struct	ldesc letterHead;
static struct	ldesc *curLetter = NULL;
static int	numberOfLetters = 0;

static char   	thefilename[128];

static char   	tmailbox[64];
static char 	tmailbag[64];


static FILE   	*fmailbox;
static FILE 	*rmailbox;
static FILE	*fmailbag;

static int	error = 0;

static int	printonly;

static int	PageCount = 0;

mailmain(argc, argv)
char **argv;
{

	/* HOSTINIT;
	loadenv(); */

	letterHead.prev = letterHead.suc = &letterHead;
	letterHead.adr = 0;
	mkfilename( tmailbox, tempdir, "mailbox");
	mkfilename( tmailbag, tempdir, "mailbag");

	unlink( tmailbox );

	if ( mailbox == (char *)NULL )
		mailbox = "???";

	if (argc > 1 && !strncmp(argv[1],"-d", 2)) {
		debuglevel = atoi(argv[1] + 2);
		argc--;
		argv++;
	}
	if ( argc == 1 ||
		( argv[1][0] == '-' ) && ( argv[1][1] != 's' ))
		showmail(argc, argv );
	else
		lmail(argc, argv, NULL );

	finis();
}

finis()
{
	if ( fmailbag != (FILE *)NULL) fclose( fmailbag );
	unlink( tmailbox );
	unlink( tmailbag );
	return( error );
}

/*	sendmail
	send message n to "line"
	Todo: we should supply a Subject line with the -s switch.
*/
sendmail( n, line )
{
	char 	*argv[50];
	int 	argc;

	/* open a temporary file */
	fmailbag = FOPEN( tmailbag, "w", 'b' );
	copymsg(n, fmailbag, FALSE);
	fclose( fmailbag );

	argc = getargs( line, argv );
	lmail( argc, argv, tmailbag );

	/* get rid of mailbag */
	unlink( tmailbag );
}

static userToInternal( i )
{
	return( numberOfLetters - i );
}

static internalToUser( i )
{
	return( numberOfLetters - i );
}

showmail(argc, argv)
char **argv;
{
	int i, j;
	char *p;
	long nextadr;
	struct ldesc *letter;
	struct FILEINFO info;

	/* get mailbox file name */
	mkfilename( mfilename, maildir, mailbox );

	/* parse arg's */
	for (; argc > 1 && argv[1][0] == '-'; argv++, argc--) {
		switch(argv[1][1]) {
		case 'f':
			if ( argc >= 3) {
				if ( argv[2][0] == '=' )
					mkfilename( mfilename, maildir,
						    &argv[2][1] );
				else
					strcpy( mfilename, argv[2] );
				argv++;
				argc--;
			} else {
				fprintf(stderr,"Usage: mail -f filename\n");
				finis();
			}
			break;
		case 'p':
			printonly++;
			break;
		default:
			fprintf(stderr, "mail: unknown option %c\n",
				argv[1][1]);
			finis();
		}
	}

	/* open real mailbox file */
	if (dfindOne(&info, mfilename, 0) || !info.fib_Size) {
		fprintf( stdout, "No mail in %s.\n", mfilename );
		return;
	}
	if (!(rmailbox = FOPEN( mfilename, "r", 'b' ))) {
		fprintf(stdout,"Unable to open %s.\n", mfilename);
		return;
	}

	/* open up tmp mailbox file */
  	if (( fmailbox = FOPEN( tmailbox, "w", 'b' )) == (FILE *)NULL ) {
		fprintf( stderr, "mail: cannot open %s for writing\n", tmailbox );
		finis();
	}

	/* copy real mailbox file to tmp mailbox file */
	numberOfLetters = 0 ;
	nextadr = 0;
	line[sizeof(line) - 2] = '\n'; line[sizeof(line) - 1] = 0;
	while ( fgets(line, sizeof(line) - 2, rmailbox ) != (char *)NULL) {
		if(line[0])
			fputs( line, fmailbox );

		if ( strncmp( line, "From ", 5 ) == SAME ) {
			letter = newLetter(NULL);
			letter->from =
			letter->subject =
			letter->date = -1L;
			letter->adr = nextadr;
			letter->delete = FALSE;
			letter->size = 0L;
		}else if ( strncmp( line, "Date: ", 6 ) == SAME )
			letter->date = nextadr;
		else if ( strncmp( line, "From: ", 6 ) == SAME )
			letter->from = nextadr;
		else if ( strncmp( line, "Subject: ", 9 ) == SAME )
			letter->subject = nextadr;

		letter->size += 1L;
		nextadr += strlen( line );
	}

	letter->suc->adr = nextadr;

	/* close mailbox files */
	fclose( rmailbox );
	fclose( fmailbox );

	fmailbox = FOPEN( tmailbox, "r", 'b' );

	if ( printonly ) {
		j = numberOfLetters;
		while ( j > 0 )
			pager( --j );
		return;
	}

	printsub( -1 );

	resp[sizeof(resp) - 2] = '\n'; resp[sizeof(resp) - 1] = 0;
	j = 1;
	while ( TRUE ) {
		j = min(numberOfLetters, max(1, j));

		fprintf( stdout, "%d ? ", j );

		if ( fgets( resp, sizeof(resp) - 2, stdin) == (char *)NULL )
			break;

		switch ( resp[0] ) {
		default:
			fprintf(stderr, "mail %s: usage\n", VERSION);
		case '?':
			fprintf( stderr, "q\tquit\n" );
			fprintf( stderr, "x\texit\tmailbox restored\n" );
			fprintf( stderr, "p\tprint message\n" );
			fprintf( stderr, "s [file] save message to a file (default =mbox)\n" );
			fprintf( stderr, "w [file] save message to a file (default =mbox) without header\n" );
			fprintf( stderr, "-^\tprint previous message\n" );
			fprintf( stderr, "d\tdelete current message\n" );
			fprintf( stderr, "u\tundelete current message\n" );
			fprintf( stderr, "+n\tprint next message\n" );
			fprintf( stderr, "h\tprint headers\n" );
			fprintf( stderr, "H\tprint current header\n" );
			fprintf( stderr, "f user\tforward current message to user\n" );
			fprintf( stderr, "m user\tmail a message to user\n" );
			fprintf( stderr, "[g] num\tset current message\n" );
			break;
		case '+':
		case 'n':
			if(++j <= numberOfLetters)
				pager( userToInternal(j) );
			break;
		case 'g':
			j = atoi( resp+2 );
			break;
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			j = atoi( resp );
			break;
		case 'x':
			if(j > 0) {
				for(i = 0; i < numberOfLetters; i++)
					letterN(i)->delete = FALSE;
			}
		case 'q':
			goto donep;
		case '\n':
		case 'p':
			if(j > 0)
				pager( userToInternal(j) );
			break;
		case '^':
		case '-':
			if(--j > 0)
				pager( userToInternal(j) );
			break;
		case 'y':
		case 'w':
		case 's':
			if(j < 1)
				break;
			if (strlen(resp) <= 2) {
				strcpy(resp + 1," =mbox");
			}
			if (resp[1] != ' ' ||
			    !(p = strtok(resp + 1," \t\n"))) {
				fprintf(stderr, "bad filename\n");
				continue;
			}
			if ( *p == '=' && strlen(p) > 1)
	                	mkfilename( thefilename, maildir, p + 1 );
			else
				strcpy( thefilename, p );
			fprintf(stderr,"Appending to %s\n", thefilename );
			if (!(fmailbag = FOPEN(thefilename, "a", 't'))) {
			      fprintf( stderr, "mail: cannot append to %s\n",
			               thefilename );
				continue;
			}
			copymsg( userToInternal(j), fmailbag, resp[0]=='w' );
			fclose( fmailbag );
			letterN(userToInternal(j))->delete = TRUE;
			j++;
			break;
		case 'm':
			fprintf( stderr,"mail command not implemented yet.\n" );
			break;
		case 'f':
			if(j < 1)
				break;
			if (resp[1] != ' ') {
				printf( "invalid command\n" );
				continue;
			}
			sendmail( userToInternal(j), resp );
			break;

		case 'd':
			if(j < 1)
				break;
			letterN(userToInternal(j))->delete = TRUE;
			j++;
			if (resp[1] == 'q')
				goto donep;
			break;

		case 'u':
			if(j < 1)
				break;
			letterN(userToInternal(j))->delete = FALSE;
			j++;
			if (resp[1] == 'q')
				goto donep;
			break;

		case 'h':
			printsub( -1 );
			break;

		case 'H':
			if(j > 0)
				printsub( userToInternal(j) );
			break;

		}

	}
	donep:
	for(i = 0; i < numberOfLetters; i++)
		if(letterN(i)->delete) {
			copyback();
			break;
		}
}

readaline( adr, line )
long adr;
char *line;
{
	char 	buf[LSIZE];
	char	*cp;

	buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0;
	*line = '\0';
	if ( adr != -1L && !fseek( fmailbox, adr, 0 ) &&
	     fgets( buf, sizeof(buf) - 2, fmailbox ))
		strcpy( line, buf );

	if ((cp = index( line, '\n' )))
		*cp = '\0';
}


/*
returnaddress()
{
	readaline( lp->from, line );
	if (
		( i = index( line, '<' )) != 0 &&
		( k = index( line, '>')) != 0 &&
		( k > i )
		)
	{
		k -= i;
		strncpy( from, line[i], k );
		from[k] = '\0';
	}
	else {


	}
}
*/

printsub( internalIndex )
int internalIndex;
{
	struct ldesc	*ld;
	int		j;
	char	from[LSIZE], subject[LSIZE], date[SHORTLSIZE], line[LSIZE];
	int k, mink, maxk;

	pagereset();

	if ( internalIndex == -1 ) {
		maxk = numberOfLetters -1;
		mink = 0;
	}
	else
		maxk = mink = internalIndex;

	for ( k = maxk ; k >= mink ; k-- ) {

		j = internalToUser( k );
		ld = letterN(k);

 		(void)strcpy(from, "unknown");	/* default to "unknown" */
		readaline( ld->from, line );
		if ( strlen( line ) > 5 ) {
			/* Assume From: mailbox@site.domain */
			/* get first usable stuff after From: */
			strcpy(from, line + 5);
		}

		/* Date: Wed May 13 23:59:53 1987 */
 		*date = '\0';	/* default date to null */
		readaline( ld->date, date );
		if ( strlen( date ) > 5 ) {
			sscanf( date + 5, "%*s %s %s", line, subject );
			sprintf( date, "%s %s", line, subject );
		}

		strcpy( subject, "--- no subject ---" );
		readaline( ld->subject, line );
		if ( strlen( line ) > 8 ) {
			strcpy( subject, line + 8);
		}

		date[6] = '\0';

		sprintf( line, "%c%3d  %6s (%6d)  %s\n    %s\n",
			 ld->delete ? 'D' : ' ', j, date, ld->size, from,
			 subject );
		if ( pageline( line ) == TRUE )
			break;
	}
}

copyback()
{
	register i;

	if (!(fmailbag = FOPEN( mfilename, "w", 'b' ))) {
		fprintf (stderr, "mail: can't rewrite %s\n", thefilename );
		finis();
	}
	for ( i = 0; i < numberOfLetters; i++ )
		if ( letterN(i)->delete == FALSE ) {
			copymsg( i, fmailbag, FALSE );
		}
	fclose (fmailbag );
}


/* copy a message
   if noheaders true, don't copy header lines
*/
copymsg( n, f, noheaders )
FILE *f;
{
	long 	bytes;
	char	buf[BUFSIZ];
	struct ldesc *ld;

	ld = letterN(n);
	fseek( fmailbox, ld->adr, 0 );
	bytes = ld->suc->adr - ld->adr;

	buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0;
	while ( noheaders && bytes > 0 &&
		fgets( buf, sizeof(buf) - 2, fmailbox )) {
		bytes -= strlen( buf );

		if ( strcmp( buf, "\n") == SAME ) {
			noheaders = FALSE;
			fputs( buf, f );
		}
	}
	bytes = ld->suc->adr - ftell(fmailbox);
	while(bytes > 0 &&
	      fread(buf, min(bytes, sizeof(buf)), 1, fmailbox) == 1) {
		if(fwrite(buf, min(bytes, sizeof(buf)), 1, f) != 1) {
			fprintf(stderr,"write failed\n");
			return;
		}
		bytes -= min(bytes, sizeof(buf));
	}
}

pager(n)
{
	long 	bytes;
	char	buf[LSIZE];
	struct ldesc *ld;

	ld = letterN(n);
	fseek( fmailbox, ld->adr, 0 );
	bytes = ld->suc->adr - ld->adr;

	pagereset();
	buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0;
	while ( bytes > 0 && fgets( buf, sizeof(buf) - 2, fmailbox )) {
		bytes -= strlen( buf );
		if ( buf[0] && pageline( buf ) == TRUE )
			break;
	}

	pageline( "\n" );
}

pagereset()
{
	PageCount = 0;
}

pageline( s )
char * s;
{
	char c;

	fputs( s, stdout );
	if ( ++PageCount > pagesize ) {
		PageCount = 0;
		fflush(stdout);
		c = get_one();
		switch( c ) {
		case 'q':
		case 'Q':
		case '\003':
		case 'x':
		case 'X':
			return( TRUE );
		}
	}
	return( FALSE );
}

/* Allocate and insert a new ldesc after previous */

static struct ldesc *newLetter(previous)
register struct ldesc *previous;
{
    register struct ldesc *tmpldesc;

    if(!(tmpldesc = (struct ldesc *) calloc(1, sizeof(*tmpldesc)))) {
	fprintf(stderr,"Out of memory\n");
	exit(1);
    }
    if(!previous) {
	previous = letterHead.prev;
    }
    tmpldesc->prev = previous;
    tmpldesc->suc = previous->suc;
    previous->suc->prev = tmpldesc;
    previous->suc = tmpldesc;
    numberOfLetters++;
    return(tmpldesc);
}

/* return reference to letter n */

static struct ldesc *letterN(n)
int n;
{
    register struct ldesc *lp = letterHead.suc;

    if(n < 0 || n >= numberOfLetters) {
	fprintf(stderr,"letterN: letter %n does not exist\n");
    }
    while(n--)
	lp = lp->suc;
    return(lp);
}
SHAR_EOF
if test 12248 -ne "`wc -c mail.c`"
then
echo shar: error transmitting mail.c '(should have been 12248 characters)'
fi
echo shar: extracting mailhost.c '(1160 characters)'
cat << \SHAR_EOF > mailhost.c
/*		mailhost.c

*/

#include <stdio.h>
#include <setjmp.h>
#include "host.h"

static char *curdir;
char * getcwd();
int chdir();
int	debuglevel = 0;		/* debuginglevel */

jmp_buf	dcpexit;

main( argc, argv )
int	argc;
char *argv[];
{
	int returnCode = 0;
	char curdirBuf[100];

	/* Amiga specific prolog */

	loadenv();
	curdir = getcwd( curdirBuf, sizeof(curdirBuf) );

	/* setup longjmp for error exit's */
	if ( setjmp( dcpexit ) == 0 ) {
		mailmain( argc, argv );
	}

	/* Amiga specific epilog */

	exitenv();
	chdir( curdir );
	exit( returnCode );
}

/* canonical name conversion routines

	importpath	canonical -> host
	exportpath	host -> canonical

	host		your local pathname format
	canonical	unix style
*/

importpath( host, canon )
char * host;
char * canon;
{
	extern char *pubdir;

	*host = '\0';

	if ( *canon == '~' )
	  {
		if ( canon[1] == '/' )
		   strcpy( host, pubdir );
		else
		   {
			strcpy( host, home );
			strcat( host, "/" );
		   }
	  }

	strcat( host, canon );

        if ( *host == '/' )
	  *host = ':';
}

exportpath( canon, host )
char * host;
char * canon;
{
	strcpy( canon, host );
	if ( *canon == ':' )
	   *canon = '/';
}
SHAR_EOF
if test 1160 -ne "`wc -c mailhost.c`"
then
echo shar: error transmitting mailhost.c '(should have been 1160 characters)'
fi
echo shar: extracting mlib.c '(591 characters)'
cat << \SHAR_EOF > mlib.c
/*		lib.c


		Amiga library
		

	Things to do in uu host

		serial I/O
		
		directory stuff
			opendir, readdir, closedir

		prolog and epilog

		system call

*/

#include <stdio.h>
#include "host.h"
#ifdef MANX
#include <sgtty.h>

int get_one()
{
	char c;
	
	struct sgttyb stty, sttyo;
	ioctl( 0, TIOCGETP, &stty );
	sttyo = stty;
	stty.sg_flags |= RAW;
/*	stty.sg_flags &= ~ ECHO; */
	ioctl( 0, TIOCSETP, &stty );

	c = fgetc( stdin );
	ioctl( 0, TIOCSETP, &sttyo );

	return( c );
}
#else
int get_one()
{
	int c;

	raw(stdin);
	c = fgetc(stdin);
	cooked(stdin);
	return( c );
}
#endif



SHAR_EOF
if test 591 -ne "`wc -c mlib.c`"
then
echo shar: error transmitting mlib.c '(should have been 591 characters)'
fi
echo shar: extracting ndir.c '(2157 characters)'
cat << \SHAR_EOF > ndir.c
#include "ndir.h"
#include <exec/memory.h>
#ifdef MANX
#include <functions.h>
#endif

#ifdef TEST
#include <stdio.h>
#endif

/*
 * support for Berkeley directory reading routine on a V7 file system
 */

extern char *malloc();

/*
 * open a directory.
 */

DIR *
opendir(name)
char *name;
{
	register DIR *dirp;
	struct Lock  *lock;

#ifdef TEST
	fprintf( stderr, "opendir: Opening \"%s\"\n", name );
#endif
	if ( ( lock = Lock( name, ACCESS_READ )) == NULL )
	  {
#ifdef TEST
		fprintf( stderr, "opendir: Can't open.\n" );
#endif
		return NULL;
	  }

	if ( (dirp = (DIR *)malloc(sizeof(DIR))) == NULL )
	  {
#ifdef TEST
		fprintf( stderr, "opendir: couldn't malloc %d\n",sizeof(DIR));
#endif
		UnLock( lock );
		return NULL;
	  }
	if ( !Examine( lock, &dirp->fib) )
	  {
#ifdef TEST
	     fprintf( stderr, "opendir: Couldn't Examine directory\n" );
#endif
	     free( dirp );
	     UnLock( lock );
	  }

	dirp->lock = lock;
#ifdef TEST
	fprintf( stderr, "opendir: Sucessful\n" );
#endif

	return dirp;
}


/*
 * get next entry in a directory.
 */
struct direct *
readdir(dirp)
register DIR *dirp;
{
	static struct direct dir;

	while ( ExNext( dirp->lock, &dirp->fib ) )
	   {
		if ( dirp->fib.fib_DirEntryType <= 0 )
		  {
			dir.d_ino = 0;
			strcpy( dir.d_name, dirp->fib.fib_FileName );
#ifdef TEST
			fprintf( stderr, "readdir: OK \"%s\"\n",  dir.d_name);
#endif
			dir.d_namlen = strlen(dir.d_name);
			dir.d_reclen = DIRSIZ(&dir);
			return (&dir);
		  }
	    }

#ifdef TEST
	fprintf( stderr, "readdir: No More Entries.\n" );
#endif
	strcpy( dir.d_name, "" );
	return NULL;

}

/*
 * close a directory.
 */
void
closedir(dirp)
register DIR *dirp;
{

	UnLock( dirp->lock );
	free((char *)dirp);
}


#ifdef TEST
#ifdef MANX
#include <errno.h>
#endif

main()
{
	char command[100];

	struct DIR *dirp;
	struct direct *dp;
	
	while(gets(command) != NULL) {

		fprintf( stderr, "test: %s\n", command );

		if ((dirp = opendir( command )) == NULL ) {
			fprintf( stderr, "couldn't open dir %s\n", command );
		}
		else
		   {
			while ((dp = readdir(dirp)) != NULL) 
				fprintf( stderr, "%s", dp->d_name );
		
			closedir( dirp );
		   }    
	}
}
#endif


SHAR_EOF
if test 2157 -ne "`wc -c ndir.c`"
then
echo shar: error transmitting ndir.c '(should have been 2157 characters)'
fi
echo shar: extracting ndir.h '(1242 characters)'
cat << \SHAR_EOF > ndir.h
/* @(#)ndir.h	1.4	4/16/85 */
#include <libraries/dos.h>
#ifndef MANX
#include <proto/dos.h>
#endif
#ifndef DEV_BSIZE
#define	DEV_BSIZE	512
#endif
#define DIRBLKSIZ	DEV_BSIZE
#define	MAXNAMLEN	255

struct	direct {
	long	d_ino;			/* inode number of entry */
	short	d_reclen;		/* length of this record */ 
	short	d_namlen;		/* length of string in d_name */
	char	d_name[MAXNAMLEN + 1];	/* name must be no longer than this */
};

/*
 * The DIRSIZ macro gives the minimum record length which will hold
 * the directory entry.  This requires the amount of space in struct direct
 * without the d_name field, plus enough space for the name with a terminating
 * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
 */

#ifdef DIRSIZ
#undef DIRSIZ
#endif /* DIRSIZ */
#define DIRSIZ(dp) \
    ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))

/*
 * Definitions for library routines operating on directories.
 */
/*
typedef struct _dirdesc {
	int	dd_fd;
	long	dd_loc;
	long	dd_size;
	char	dd_buf[DIRBLKSIZ];
} DIR;
*/
typedef struct _dirdesc {
	struct Lock	*lock;
	struct FileInfoBlock fib;
} DIR;
#ifndef NULL
#define NULL 0L
#endif
extern	DIR *opendir();
extern	struct direct *readdir();
extern	void closedir();


SHAR_EOF
if test 1242 -ne "`wc -c ndir.h`"
then
echo shar: error transmitting ndir.h '(should have been 1242 characters)'
fi
echo shar: extracting pccp.c '(13168 characters)'
cat << \SHAR_EOF > pccp.c
/* pccp - copy files between systems
 *
 * SYNOPSIS
 *	pccp [-C] [-r] [-v] [-xd] fromfile... tofile
 *
 * DESCRIPTION
 *	pccp is a partial implementation of the UNIX uucp command. The business
 *	of pccp is to translate user level copy commands into command files
 *	understood by uupc. pccp may also start uupc on these files.
 *
 *	A file name may be a local pathname or of the form
 *		system!pathname
 *	where system is one of the sites listed in the uupc systems file.
 *	If the remote pathname contains wild cards (? * and so on) these
 *	will be expanded on the remote system. This program does no wildcard
 *	expansion. The caller, the local uupc or the remote uupc have to decide
 *	about wildcards.
 *
 *	A pathname is one of the following:
 *		a complete pathname
 *
 *		a pathname preceded by ~user/. ~user will be expanded to
 *		the home directory of the user on the appropriate system.
 *		The name ~/ will be expanded to the public uucp directory.
 *
 *		anything else will be prependded with the path of the current
 *		directory. 
 *
 * OPTIONS
 *	-C	Copy the outgoing files to the spool directory. This lets
 *	 	you remove the source file without affecting the file transfer.
 *		The default action is to transfer directly from the source
 *		file.
 *
 *	-r	Do not start the transfer. Just queue the job.
 *
 *	-v	Verbose. Will at least display the version.
 *
 *	-xd	This option will be passed on to uupc. It specifies the
 *		the debug level. d is a digit between zero and nine.
 */
/*	The code for finding an executable is taken from the cc program written
 *	by Fred Fish. There are restrictions on the use of that code. See
 *	the cc program on Fish disk 28 for more info.
 *
 *	As regards all other code in this program: use it any way you want,
 *	I put no restrictions on it.
 *
 * 				6-FEB-88 Johan Widen
 *				USENET:	 jw@sics.se
 */

#include <dos.h>
#include <stdio.h>
#include "host.h"

#define VERSION "1.0 6-FEB-88"
#define PROGRAM "pccp"

/*
 *	Set list of places to search for various executables, libraries, etc.
 *	Searched in order, first match wins, null string is current directory.
 *	Note that these names are used as prefixes exactly as given, so
 *	device names must end in ':' and directory names must end in '/'.
 *
 */

static char *Devices[] = {
    "",
    "vd0:",
    "ram:",
    "df0:",
    NULL
};

static char *BinDirs[] = {
    "",
    "c:",
    "df0:c/",
    NULL
};

static void   usage();
static void   pathArgUsage();
static int    checkLocalRemote(int, char**);
static int    sequenceNumber(int);
static char **copyToSpool(int, char**, int);
static void   createCommandFile(int, char **, char**, int, int, int, char *);
static void   removeSpoolFiles(int, char**);
static int    expandFileName(char *, char *);
static char  *checkAlloc(int);
static char  *locate(char *, char **);
static int    readable(char *);
static int    runCommand(char *);

int debuglevel = 0;

main(argc, argv)
int    argc;
char **argv;
{
    int copyFlag = 0;
    int queueOnlyFlag = 0;
    int verboseFlag = 0;
    int localToRemote;
    char **pathArgs;
    int sequence;
    char remoteHost[80];
    char executeBuf[80];

    for(argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
	switch(argv[0][1]) {
	case 'C':
	    copyFlag = 1;
	    break;
	case 'r':
	    queueOnlyFlag = 1;
	    break;
	case 'v':
	    verboseFlag = 1;
	    break;
	case 'x':
	    if(isdigit(argv[0][2]))
		debuglevel = argv[0][2] - '0';
	    else
		usage();
	    break;
	default:
	    usage();
	}
    }
    if(argc < 2) 
	usage();

    loadenv();
    
    if(verboseFlag)
	fprintf(stderr,"%s\n", VERSION);

    if((localToRemote = checkLocalRemote(argc, argv)) < 0)
	exit(1);
    pathArgs = argv;
    if(localToRemote && copyFlag) {
	sequence = sequenceNumber(argc - 1);
	pathArgs = copyToSpool(argc, pathArgs, sequence);
    } else {
	sequence = sequenceNumber(1);
    }
    createCommandFile(argc, argv, pathArgs, sequence, localToRemote, copyFlag,
		      remoteHost);
    if(queueOnlyFlag)
	exit(0);
    
    sprintf(executeBuf,"%s -r1 -s%s -x%d", locate("uupc", BinDirs), remoteHost,
	    debuglevel);
    
    exit(runCommand(executeBuf));
}

static void
usage()
{
    fprintf(stderr,"%s version %s\n", PROGRAM, VERSION);
    fprintf(stderr,"Usage: %s [-C] [-r] [-v] [-xd] fromfiles... tofile\n",
	    PROGRAM);
    fprintf(stderr,"-C means copy to spool before sending.\n");
    fprintf(stderr,"-r means queue only, do not start uupc.\n");
    fprintf(stderr,"-v means verbose.\n");
    fprintf(stderr,"-xd '0'<= d <= '9' set debug level for uupc.\n");
    fprintf(stderr,"file may be a local pathname or system!pathname\n");
    fprintf(stderr,
"pathname may be a full path or begin with ~user (\"~/\" means public uucp\n");
    fprintf(stderr,
"directory).  Other pathnames get prepended with current directory\n");
    exit(1);
}

/* checkLocalRemote(argc, argv)
 * int argc;		Number of pathnames.
 * char **argv;		Pathnames.
 *
 * Description: we currently require that one of the following holds
 *	1. The last argument is a remote pathname. All other arguments are
 *	   local pathnames.
 *
 *	2. There are only two arguments. The first argument is a remote path-
 *	   name and the last argument is a local pathname.
 *
 * Return 1 if case 1 holds. Return 0 if case 2 holds. Otherwise return -1.
 */

static int
checkLocalRemote(argc, argv)
register int argc;
register char **argv;
{
    register int i;

    if(argc == 2 && strchr(argv[0],'!')) {
	if(strchr(argv[1],'!')) {
	    pathArgUsage();
	    return(-1);
	}
	return(0);
    }
    /* first argument is a local pathname */
    if(!strchr(argv[argc - 1],'!')) {
	pathArgUsage();
	return(-1);
    }
    for(i = 1; i < argc - 1; i++)
	if(strchr(argv[i],'!')) {
	    pathArgUsage();
	    return(-1);
	}
    return(1);
}

static void
pathArgUsage()
{
    fprintf(stderr,"%s: pathname arguments must be either:\n", PROGRAM);
    fprintf(stderr,"\tremote!path localpath\n  or\n");
    fprintf(stderr,"\tlocalpath... remote!path\n");
}

/* int sequenceNumber(inc)
 * int inc;		Reserve this many numbers;
 *
 * Description: The filenames in the spool area are made unique by including
 * a sequence number in them. Get the next sequence number. Update the sequence
 * number.
 */
static int
sequenceNumber(inc)
int inc;
{
    char sequencePath[256];
    FILE *sequenceFile;
    int sequence;

    mkfilename(sequencePath, confdir, SFILENAME);
    if(sequenceFile = fopen(sequencePath,"r")) {
	fscanf(sequenceFile,"%ld", &sequence);
	fclose(sequenceFile);
    } else
	sequence = 0;
    if(!(sequenceFile = fopen(sequencePath,"w"))) {
 	fprintf(stderr,"%s: unable to create %s\n", PROGRAM, sequencePath);
        exit(3);
    }
    fprintf(sequenceFile,"%04d\n", (sequence + inc)%10000);
    fclose(sequenceFile);
    return(sequence);
}

/* char **copyToSpool(argc, oldPathArgs, sequence)
 * int argc;		Number of pathnames.
 * char **oldPathArgs;  Files to copy to spool area.
 * int sequence;	File name sequence number.
 *
 * Description: copy the first argc - 1 files to the spool area. The spool
 * files are given unique names. The new names are returned together with
 * the original last argument.
 */
static char **
copyToSpool(argc, oldPathArgs, sequence)
int  argc;
register char **oldPathArgs;
int  sequence;
{
    register char **newPathArgs;
    char spoolName[256];
    char dFileName[80];
    char buf[BUFSIZ];
    register int i;
    int bytesRead;
    FILE *inFile, *outFile;

    newPathArgs = (char **) checkAlloc(argc*sizeof(char **));
    newPathArgs[argc - 1] = oldPathArgs[argc - 1];
    for(i = 0; i < argc - 1; i++) {
	sprintf(dFileName,"D.%.7s%04d", nodename, sequence++);
	mkfilename(spoolName, spooldir, dFileName);
	newPathArgs[i] = checkAlloc(strlen(spoolName) + 1);
	strcpy(newPathArgs[i], spoolName);
    }
    for(i = 0; i < argc - 1; i++) {
	if(!expandFileName(oldPathArgs[i], spoolName)) {
	    removeSpoolFiles(i, newPathArgs);
	    exit(4);
	}
	if(!(inFile = fopen(spoolName,"r"))) {
	    fprintf(stderr,"%s: unable to open %s\n", PROGRAM, spoolName);
	    removeSpoolFiles(i, newPathArgs);
	    exit(5);
	}
	if(!(outFile = fopen(newPathArgs[i],"w"))) {
	    fprintf(stderr,"%s: unable to open %s\n", PROGRAM, newPathArgs[i]);
	    removeSpoolFiles(i, newPathArgs);
	    exit(6);
	}
	while (bytesRead = fread(buf, 1, sizeof(buf), inFile)) {
	    if(fwrite(buf, bytesRead, 1, outFile) != 1) {
		fclose(outFile);
		fprintf(stderr,"%s: write error when copying %s to %s\n",
			PROGRAM, spoolName, newPathArgs[i]);
		removeSpoolFiles(i + 1, newPathArgs);
		exit(7);
	    }
	}
	fclose(inFile);
	fclose(outFile);
    }
    return(newPathArgs);
}

static void
createCommandFile(argc, oldPathArgs, pathArgs, sequence, localToRemote,
		  copyFlag, remoteHost)
int argc;
char **oldPathArgs;
char **pathArgs;
int sequence;
int localToRemote;
int copyFlag;
char *remoteHost;
{
    char buf[BUFSIZ];
    char expandedPath[256];
    char cFilePath[256];
    char cFileName[80];
    FILE *cFile;
    char *cp, *remoteFile;
    register int i;
    int spoolDirLen;
    int length;

    if(localToRemote)
	cp = pathArgs[argc - 1];
    else
	cp = pathArgs[0];
    remoteFile = strchr(cp,'!') + 1;
    strncpy(remoteHost, cp, remoteFile - cp - 1);
    remoteHost[remoteFile - cp - 1] = 0;
    sprintf(cFileName,"C.%.7s%04d", remoteHost, sequence);
    mkfilename(cFilePath, spooldir, cFileName);
    if(!(cFile = fopen(cFilePath,"w"))) {
	fprintf(stderr,"%s: unable to open %s\n", PROGRAM, cFilePath);
	if(localToRemote && copyFlag)
	   removeSpoolFiles(argc - 1, pathArgs);
	exit(8);
    }
    spoolDirLen = strlen(spooldir);
    if(localToRemote) {
	for(i = 0; i < argc - 1; i++) {
	    if(!expandFileName(oldPathArgs[i], expandedPath)) {
		fclose(cFile);
		unlink(cFilePath);
		exit(8);
	    }
	    if(copyFlag) {
		sprintf(buf,"S %s %s uucp - %s 0666\n", expandedPath,
			remoteFile, pathArgs[i] + spoolDirLen + 1);
	    } else {
		sprintf(buf,"S %s %s uucp - %s 0666\n", expandedPath,
			remoteFile, expandedPath);
	    }
	    /* The first arg should really be the original file but uupc */
	    /* does not handle this yet. */
	    length = strlen(buf);
	    if(1 != fwrite(buf, length, 1, cFile)) {
		fprintf(stderr,"%s: write error on %s\n", PROGRAM, cFilePath);
		if(copyFlag)
		    removeSpoolFiles(argc - 1, pathArgs);
		fclose(cFile);
		unlink(cFilePath);
		exit(9);
	    }
	}
    } else {
	if(!expandFileName(pathArgs[1], expandedPath)) {
	    fclose(cFile);
	    unlink(cFilePath);
	    exit(10);
	}
	sprintf(buf,"R %s %s uucp\n", remoteFile, expandedPath);
	length = strlen(buf);
	if(1 != fwrite(buf, length, 1, cFile)) {
	    fprintf(stderr,"%s: write error on %s\n", PROGRAM, cFilePath);
	    fclose(cFile);
	    unlink(cFilePath);
	    exit(11);
	}
    }
    fclose(cFile);
}

static void
removeSpoolFiles(count, newPathArgs)
int count;
register char **newPathArgs;
{
    register int i;

    for(i = 0; i < count; i++) {
	unlink(newPathArgs[i]);
    }
}

static int
expandFileName(from, to)
register char *from;
register char *to;
{
    char *cp;
    char user[50];

    if(from[0] == '/' || from[0] == ':') {
	strcpy(to, from);
	to[0] = ':';
    } else if(from[0] == '~') {
	if(!(cp = strchr(from,'/'))) {
	    strcat(from, "/");
	    cp = strchr(from,'/');
	}
	if((cp - from) > 1) {
	    strncpy(user, from + 1, cp - from - 1);
	    user[cp - from - 1] = 0;
	    if(strcmp(user, mailbox)) {
		fprintf(stderr,"%s: unknown user %s\n", PROGRAM, user);
		return(0);
	    }
	    mkfilename(to, home, cp + 1);
	} else {
	    mkfilename(to, pubdir, cp + 1);
	}
    } else {
	getcwd(to, 256);
	cp = to + strlen(to) - 1;
	if(*cp != '/' && *cp != ':') {
	    strcpy(cp + 1, "/");
	}
	strcat(cp, from);
    }
    return(1);
}

static char *
checkAlloc(size)
int size;
{
    char *cp;

    if(!(cp = malloc(size))) {
	fprintf(stderr,"%s: out of memory\n", PROGRAM);
	exit(2);
    }
    return(cp);
}

/*
 *	Look through the list of paths pointed to by "vec" until we find
 *	a file with name given pointed to by "namep".  If none is found,
 *	the name pointed to by namep is returned.
 */
 
static char *locate(namep, vec)
char *namep;
char **vec;
{
    static char namebuf[64];
    
    while (*vec != NULL) {
	sprintf(namebuf, "%s%s", *vec, namep);
	if (readable(namebuf)) {
	    namep = namebuf;
	    break;
	}
	vec++;
    }
    return(namep);
}

/*
 *	Check to see if the file exists and is readable.
 */

static int readable(name)
char *name;
{
    register int status = 0;
    register int fildes;
    
    fildes = Lock(name, ACCESS_READ);
    if (fildes != 0) {
    	UnLock (fildes);
	status = 1;
    }
    return(status);
}

static int runCommand(command)
char *command;
{
    int status;
    register char *cp;
    char *prog, *args;
    struct ProcID child;
    
    /* This code assumes that there is at least one argument */
    prog = cp = command;
    while(*cp && *cp != ' ')
	cp++;
    *cp++ = 0;
    while(*cp == ' ')
	cp++;
    args = cp;
    if(forkl(prog, prog, args, NULL, NULL, &child) == -1) {
	fprintf(stderr,"%s: unable to execute %s\n", PROGRAM, prog);
	status = 1;
    } else {
	status = wait(&child);
    }
    return(status);
}
SHAR_EOF
if test 13168 -ne "`wc -c pccp.c`"
then
echo shar: error transmitting pccp.c '(should have been 13168 characters)'
fi
#	End of shell archive
exit 0

ain@j.cc.purdue.edu (Patrick White) (03/22/88)

Program Name:	uupc  version 1.1  (part 3 of 3)
Submitted By:	Johan Widen  <jw@sics.se>
Summary:	Implements uucp for the Amiga -- allows your Amiga to become
		a uupc site for mail (and news?).
Poster Boy:  Pat White  (ain@j.cc.purdue.edu)
Uncompiled.

NOTES:
   Converted the origional zoo to shars so docs, binaries & sources could
be separated.
   I'm pretty sure this would allow one to receive news, but I remember
something in the docs about it not having been tested from when I was
quickly scanning them... so I'm not too sure on this.
   Rob has been playing with it for a while and says it works.


-- Pat White   (co-moderator comp.sources/binaries.amiga)
UUCP: j.cc.purdue.edu!ain  BITNET: PATWHITE@PURCCVM   PHONE: (317) 743-8421
U.S.  Mail:  320 Brown St. apt. 406,    West Lafayette, IN 47906

========================================

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	raw.c
#	rmail.c
#	sendpacket.c
#	serial.c
#	sio.c
#	sleep.c
#	timer.c
#	ulib.c
#	uuhost.c
# This archive created: Sat Mar 19 01:42:21 1988
# By:	Patrick White (PUCC Land, USA)
echo shar: extracting raw.c '(2393 characters)'
cat << \SHAR_EOF > raw.c
/* 
 *	raw.c
 *
 *    This is a routine for setting a given stream to raw or cooked mode.
 * This is useful when you are using Lattice C to produce programs that
 * want to read single characters with the "getch()" or "fgetc" call.
 *
 * Written : 18-Jun-87 By Chuck McManis. 
 * 	     If you use it I would appreciate credit for it somewhere.
 */
#include <exec/types.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ios1.h>
#include <error.h>
#include <proto/exec.h>
#include <proto/dos.h>

/* New Packet in 1.2 */
/* #define ACTION_SCREEN_MODE	994L */

extern	int	errno;		/* The error variable */

/*
 * Function raw() - Convert the specified file pointer to 'raw' mode. This
 * only works on TTY's and essentially keeps DOS from translating keys for
 * you, also (BIG WIN) it means getch() will return immediately rather than
 * wait for a return. You lose editing features though.
 */
long
raw(fp)

FILE *fp;

{
  struct MsgPort 	*mp; /* The File Handle message port */
  struct FileHandle 	*afh;
  struct UFB 		*ufb;
  long			Arg[1],res;

  ufb = (struct UFB *) chkufb(fileno(fp));  /* Step one, get the file handle */
  afh = (struct FileHandle *)(ufb->ufbfh); 

  if (!IsInteractive(afh)) {	/* Step two, check to see if it's a console */
    errno = ENOTTY;
    return(-1);
  }
                              /* Step three, get it's message port. */
  mp  = ((struct FileHandle *)(BADDR(afh)))->fh_Type;
  Arg[0] = -1L;
  res = SendPacket(mp,ACTION_SCREEN_MODE,Arg,1); /* Put it in RAW: mode */
  if (res == 0) {
    errno = ENXIO;
    return(-1);
  }
  return(0);
}

/*
 * Function - cooked() this function returns the designate file pointer to
 * it's normal, wait for a <CR> mode. This is exactly like raw() except that
 * it sends a 0 to the console to make it back into a CON: from a RAW:
 */

long
cooked(fp)

FILE *fp;

{
  struct MsgPort 	*mp; /* The File Handle message port */
  struct FileHandle 	*afh;
  struct UFB 		*ufb;
  long			Arg[1],res;

  ufb = (struct UFB *) chkufb(fileno(fp));
  afh = (struct FileHandle *)(ufb->ufbfh);
  if ( ! IsInteractive(afh)) {
    errno = ENOTTY;
    return(-1);
  }
  mp  = ((struct FileHandle *)(BADDR(afh)))->fh_Type;
  Arg[0] = 0;
  res = SendPacket(mp,ACTION_SCREEN_MODE,Arg,1);
  if (res == 0) {
    errno = ENXIO;
    return(-1);
  }
  return(0);
}
SHAR_EOF
if test 2393 -ne "`wc -c raw.c`"
then
echo shar: error transmitting raw.c '(should have been 2393 characters)'
fi
echo shar: extracting rmail.c '(8785 characters)'
cat << \SHAR_EOF > rmail.c
/*			rmail.c

	copyright (C) 1987 Stuart Lynne

	Copying and use of this program are controlled by the terms of the
	Free Software Foundations GNU Emacs General Public License.


	version		0.1		March 31/1987


pcmail

	pcmail address1 address2 ... < the.message

description

	An 822 compatible (hopefully) mail delivery system for pc's.

	Designed for delivering mail on a pc based system. It will put
	local mail (ie, not @ or ! in address) into files in the default
	mail directory.

	If remote it will put into an outgoing mailbag in the default mail
	directory. Performs a simple bundling of mail messages into one
	file with arguments prepended as To: arg header lines.

		pcmail john jack jill@xyz.uucp < afile

		To: john, jack, jill@xyz.uucp

		...
		...
		...

	It also adds the from From and Date lines. Subject: lines may be inserted
	by placing them at the beginning of the message.

	A Unix version should lock the /usr/mail/mailbag file.

environment variables

	The following evironment variables are used:

		MAILBOX		current user's mailbox, 	"stuart"
		NAME		current user's name, 		"Stuart Lynne"
		DOMAIN		domain of this machine, 	"slynne.mac.van-bc.can"
		MAILDIR		where is mail kept,			"mpw:mail"
*/

#include <dos.h>
#include <stdio.h>
#include "host.h"

char *_TZ = "GMT0";

FILE *FOPEN();

#define FORWARD		"Forward to"


static FILE   *mailfile;
static FILE   *tempfile;

static char	buf[BUFSIZ];
static char	miscbuff[100];
static char    *inFileName;
static long int sequence = 0;

static long tloc;
static char chartime[40];	/* current time in characters */
static char *thetime;

static char	tfilename[100];
extern char	mfilename[];
static char	mailsent[100];

static char 	remotes[BUFSIZ];


static char *uucp = "uucp";

char *fgets();
int fputs();

extern int debuglevel;

extern long DOSBase;
static char *mcurdir;
static char s_mcurdir[128];	/* current directory path (save malloc call) */
char * getcwd();
int chdir();


rmail(argc, argv, inname)
int argc;
char *inname;
char **argv;
{
	register int argcount;
	register char **argvec;
	char timeBuf[40];

	if (debuglevel > 5) {
		fprintf(stderr,"pcmail: argc %d ", argc);
		argcount = argc;
		argvec = argv;
		while (argcount--)
			fprintf(stderr," \"%s\"", *argvec++);
		fprintf(stderr,"\n");

		time(&tloc);
		thetime = ctime(&tloc);
		sprintf(timeBuf,"%.3s, %.2s %.3s %.2s %.8s %s\n", thetime,
			thetime + 8, thetime + 4, thetime + 22, thetime + 11,
			timeZone);
		thetime = timeBuf;
		fprintf(stderr,"thetime: %s",thetime);
	}

	mcurdir = getcwd(s_mcurdir, sizeof(s_mcurdir));
	chdir(spooldir);

	/* get sequence number */
	mkfilename(tfilename, confdir, SFILENAME);

 	if (debuglevel > 4)
 	   fprintf(stderr,"pcmail: opening %s\n", tfilename); /* */

	if(tempfile = FOPEN(tfilename,"r", 't')) {
		fscanf(tempfile,"%ld", &sequence);
		fclose(tempfile);
	}
 	else
 		fprintf(stderr,"pcmail: can't find %s file, creating\n",
 			tfilename);

	/* update sequence number */
	if (debuglevel > 5)
		fprintf(stderr,"pcmail: new sequence # %ld\n", sequence);

	if(tempfile = FOPEN(tfilename,"w", 't')) {
		fprintf(tempfile,"%ld\n", (sequence+1)%10000);
		fclose(tempfile);
	}

	inFileName = inname;

	/* loop on args, copying to appropriate postbox,
	   do remote only once
	   remote checking is done empirically, could be better
	*/
	remotes[0] = '\0';

	argcount = argc;
	argvec = argv;

	while (--argcount > 0) {
		argvec++;
		if (debuglevel > 5)
			fprintf(stderr,"pcmail: arg# %d %s\n", argcount,
				 *argvec);
		if (strchr(*argvec, '!') || strchr(*argvec, '@') ||
		    strchr(*argvec, '%')) {
			if (debuglevel > 5)
				fprintf(stderr,"pcmail: send to remote\n");
			/* can we cram one more address on line */
			if((strlen(remotes) + strlen(*argvec) + 3) >
			    sizeof(remotes)) {
				/* dump it then, to bad */
				sendone(argc, argv, remotes, TRUE);
				remotes[0] = '\0';
			}
			/* add *arvgvec to list of remotes */
			strcat(remotes," ");
			strcat(remotes, *argvec);
		}
		else {
			if (debuglevel > 5)
				fprintf(stderr,"pcmail: calling sendone %s\n",
					*argvec);
			sendone(argc, argv, *argvec, FALSE);
		}
	}
	/* dump remotes if necessary */
	if (remotes[0])
		sendone(argc, argv, remotes, TRUE);
	chdir(mcurdir);
	return(0);
}


/* sendone copies file plus headers to appropriate postbox
   NB. we do headers here to allow flexibility later, for example
   in being able to do bcc, per host service processing etc.
*/
sendone(argc, argv, address, remote)
int argc;
char **argv;
char *address;
int remote;
{
	register char 	*cp;
	char	icfilename[32];		/* local C. copy file */
	char	ixfilename[32];		/* local X. xqt file */
	char	idfilename[32];		/* local D. data file */
	char	rxfilename[32];		/* remote X. xqt file */
	char	rdfilename[32];		/* remote D. data file */
 	char	tmfilename[32];		/* temporary storage */
	struct FILEINFO info;

 	if (remote) {
 		/* sprintf all required file names */
		sprintf(tmfilename,"%c.%.7s%04d", 'C', mailserv, sequence);
		importpath(icfilename, tmfilename);
		sprintf(tmfilename,"%c.%.7s%04d", 'D', mailserv, sequence);
		importpath(idfilename, tmfilename);
		sprintf(tmfilename,"%c.%.7s%04d", 'D', nodename, sequence);
		importpath(ixfilename, tmfilename);
		sprintf(rdfilename,"%c.%.7s%04d", 'D', nodename, sequence);
		sprintf(rxfilename,"%c.%.7s%04d", 'X', nodename, sequence);
 	}
 	else {
		/* postbox file name */
 		if (!strchr(address, SEPCHAR))
			mkfilename(idfilename, maildir, address);
		else
			strcpy(idfilename, address);
	}

	if (debuglevel > 5)
 		fprintf(stderr,"pcmail: sendone: %s\n", idfilename);

 	if (remote == FALSE) {
		if (debuglevel > 5)
			fprintf(stderr,"pcmail: sendone: check for remote\n");
		/* check for forwarding */
		if (!dfindOne(&info, idfilename, 0) && info.fib_Size > 10 &&
		    (mailfile = FOPEN(idfilename,"r", 'b'))) {
			cp = fgets(buf, sizeof(buf), mailfile);
			fclose(mailfile);
			if (cp && !strncmp(buf, FORWARD, 10)) {
				strcpy(buf, buf+11);
				return(sendone(argc, argv, buf, FALSE));
			}
		}
	}

	/* open mailfile */
	if (!(mailfile = FOPEN(idfilename,"a", 'b'))) {
		fprintf(stdout,"pcmail: cannot append to %s\n", idfilename);
		return(0);
	}
	
	if (debuglevel > 5)
		fprintf(stderr,"pcmail: append to mailfile\n");

	time(&tloc);
	thetime = ctime(&tloc);
	sprintf(chartime,"%.3s, %.2s %.3s %.2s %.8s %s", thetime,
		thetime + 8, thetime + 4, thetime + 22, thetime + 11,
		timeZone);
 	thetime = chartime;	/* and work with our own copy */

	fprintf(mailfile,"From uucp %s\n", thetime);
	fprintf(mailfile,"Received: by %s (pcmail) %s\n", domain, thetime);

	/* copy spoolfile to postbox file */
	if (debuglevel > 4)
		fprintf(stderr,"pcmail: copy spoolfile %s to %s\n", inFileName,
			idfilename);
	if (!(tempfile = FOPEN(inFileName,"r", 'b'))) {
		fprintf(stdout,"pcmail: can't open %s\n", inFileName);
		return(0);
	}
	buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0;
	while (fgets(buf, sizeof(buf) - 2, tempfile)) {
		if (strncmp(buf,"From ", 5) == 0)
			fputc('>', mailfile);
		if(buf[0])
			fputs(buf, mailfile);
 	}

	/* close files */
	fclose(mailfile);
	fclose(tempfile);

	/* all done unless going to remote via uucp */
	/* must create the job control files */
	if (remote) {
		/* create remote X xqt file */
		if(!(mailfile = FOPEN(ixfilename,"w", 'b'))) {
			fprintf(stdout,"pcmail: cannot open %s\n", ixfilename);
			return(0);
		}
		fprintf(mailfile,"U %s %s\n", uucp, nodename);
		fprintf(mailfile,"F %s\n", rdfilename);
		fprintf(mailfile,"I %s\n", rdfilename);
		fprintf(mailfile,"C rmail %s\n", address);
		fclose(mailfile);

		/* create local C copy file */
		if(!(mailfile = FOPEN(icfilename,"w", 't'))) {
			fprintf(stdout,"pcmail: cannot open %s\n", icfilename);
			return(0);
		}

		fprintf(mailfile,"S %s %s %s - %s 0666 %s\n", idfilename,
			rdfilename, uucp, idfilename, uucp);
		fprintf(mailfile,"S %s %s %s - %s 0666 %s\n", ixfilename,
			rxfilename, uucp, ixfilename, uucp);
		fclose(mailfile);
	}

	return(1);
}

#ifndef AMIGA
#ifdef RMAIL
rnews(argc, argv)
int argc;
char *argv[];
{
	struct tm	*thetm;
	char	filename[132];
	char	format[128];
	FILE 	*f;
	char	buf[BUFSIZ];

	static int count = 0;

	tloc = time((long *)NULL);
	thetime = ctime(&tloc);
	tloc = time((long *)NULL);

	thetm = localtime(&tloc);

	/* mkfilename(format, spooldir, NEWSDIR);	*/
	sprintf(filename, NEWSDIR,
		thetm->tm_year % 100, thetm->tm_mon,
		thetm->tm_mday, thetm->tm_hour,
		thetm->tm_min,  thetm->tm_sec,  count
		);

	count++;

	if (debuglevel > 5)
		fprintf(stderr,"rnews: %s\n", filename);

	if ((f = FOPEN(filename,"w", 't')) == (FILE *)NULL) {
		fprintf(stderr,"rnews: can't open %s %d\n", filename, errno);
		return(-1);
	}

	while (fgets(buf, BUFSIZ, stdin) != (char *)NULL)
		fputs(buf, f);

	fclose(f);
}

#endif /* RMAIL */
#endif /* AMIGA */




SHAR_EOF
if test 8785 -ne "`wc -c rmail.c`"
then
echo shar: error transmitting rmail.c '(should have been 8785 characters)'
fi
echo shar: extracting sendpacket.c '(2082 characters)'
cat << \SHAR_EOF > sendpacket.c
/*
 *	Sendpacket.c 
 *
 *  An invaluable addition to your Amiga.lib file. This code sends a packet
 * the given message port. This makes working around DOS lots easier.
 * 
 * Note, I didn't write this, those wonderful folks at CBM did. I do suggest
 * however that you may wish to add it to Amiga.Lib, to do so, compile it
 * and say 'oml lib:amiga.lib -r sendpacket.o' 
 */

#include <exec/types.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <proto/exec.h>
#include <proto/dos.h>

/*
 * Function - SendPacket written by Phil Lindsay, Carolyn Scheppner, and
 * Andy Finkel. This function will send a packet of the given type to the
 * Message Port supplied.
 */

long
SendPacket(pid,action,args,nargs)

struct MsgPort *pid;  /* process indentifier ... (handlers message port ) */
long action,          /* packet type ... (what you want handler to do )   */
     args[],          /* a pointer to a argument list */
     nargs;           /* number of arguments in list  */
{
  struct MsgPort        *replyport;
  struct StandardPacket *packet;
 
  long  count, *pargs, res1;

  replyport = (struct MsgPort *) CreatePort(NULL,0);
  if(!replyport) return(0);

  /* Allocate space for a packet, make it public and clear it */
  packet = (struct StandardPacket *) 
    AllocMem((long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);
  if(!packet) {
    DeletePort(replyport);
    return(0);
  }

  packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt);
  packet->sp_Pkt.dp_Link         = &(packet->sp_Msg);
  packet->sp_Pkt.dp_Port         = replyport;
  packet->sp_Pkt.dp_Type         = action;

  /* copy the args into the packet */
  pargs = &(packet->sp_Pkt.dp_Arg1);       /* address of first argument */
  for(count=0;count < nargs;count++) 
    pargs[count]=args[count];
 
  PutMsg(pid,packet); /* send packet */

  WaitPort(replyport);
  GetMsg(replyport); 

  res1 = packet->sp_Pkt.dp_Res1;

  FreeMem(packet,(long)sizeof(struct StandardPacket));
  DeletePort(replyport); 

  return(res1);
}
SHAR_EOF
if test 2082 -ne "`wc -c sendpacket.c`"
then
echo shar: error transmitting sendpacket.c '(should have been 2082 characters)'
fi
echo shar: extracting serial.c '(7910 characters)'
cat << \SHAR_EOF > serial.c
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <exec/libraries.h>
#include <exec/devices.h>
#include <exec/io.h>
#include <devices/serial.h>
#ifndef MANX
#include <proto/exec.h>
#endif
#include <stdio.h>

struct IOExtSer *IORreadser = NULL, *IORwriteser = NULL;
struct MsgPort *serialreadport = NULL, *serialwriteport = NULL;
extern struct MsgPort *CreatePort();
extern struct IORequest *CreateExtIO();

static int close_flag = 0;

#define SERDATR ((USHORT *) 0xdff018)
#define TBE	(1 << 13)
#define SERDAT	((USHORT *) 0xdff030)

static UBYTE parity = 2, stopbits = 0;
static UBYTE speed = 2, xonxoff = 0;
static ULONG speedtab[] = {9600,4800,2400,1200,1200,300};
static UBYTE paritytab[] = {2,1,0};
static UBYTE stopbitstab[] = {1, 2};

initserial()
{
	int     error;

	/* SET UP the message port in the I/O request */
	serialreadport = CreatePort ("Serial Read",0);
	serialwriteport = CreatePort ("Serial Write",0);
	if (serialreadport == NULL || serialwriteport == NULL) {
		sercleanup();
		printf("\nProblems during CreatePort");
		exit(100);
	}

	/* Create the request blocks for passing info to and from the serial 
	   device. */
	IORreadser = (struct IOExtSer *)
		CreateExtIO(serialreadport,sizeof(struct IOExtSer));
	IORwriteser = (struct IOExtSer *)
		CreateExtIO(serialwriteport,sizeof(struct IOExtSer));
	if (IORreadser == NULL || IORwriteser == NULL) { 
		sercleanup();
		printf("\nProblems during CreateExtIO"); 
		exit(101);
	}

	/* OPEN the serial.device */
	if ((error = OpenDevice (SERIALNAME, 0, IORreadser, 0)) != 0) {
		sercleanup();
		printf ("Serial device did not open 1, error = %ld\n",error);
		exit(102);
	}
	close_flag = TRUE;

	dosetparams();

	*IORwriteser = *IORreadser;
	IORwriteser->IOSer.io_Message.mn_ReplyPort = serialwriteport;
}

sercleanup()
{
	if(close_flag) {
		CloseDevice (IORreadser);
		close_flag = 0;
	}
	if(serialreadport) {
		DeletePort (serialreadport);
		serialreadport = NULL;
	}
	if(serialwriteport) {
		DeletePort (serialwriteport);
		serialwriteport = NULL;
	}
	if(IORreadser) {
		DeleteExtIO(IORreadser,sizeof(struct IOExtSer));
		IORreadser = NULL;
	}
	if(IORwriteser) {
		DeleteExtIO(IORwriteser,sizeof(struct IOExtSer));
		IORwriteser = NULL;
	}
}

setspeed(menusel)
int menusel;
{
	speed = menusel;
}

dosetparams()
{
	ULONG rbl;
	ULONG brk;
	ULONG baud;
	UBYTE rwl;
	UBYTE wwl;
	UBYTE sf;
	ULONG t0;
	ULONG t1;

	/*    SET PARAMS for the serial.device */
	rbl = 4096;
	if(paritytab[parity]) {
		rwl = 0x07;
		wwl = 0x07;
	} else {
		rwl = 0x08;
		wwl = 0x08;
	}
	brk = 750000;
	baud = speedtab[speed];
	sf = 0;
	if(!xonxoff) {
		sf  = SERF_XDISABLED;
	}
	if(paritytab[parity] == 1) {
		sf |= SERF_PARTY_ON | SERF_PARTY_ODD;
	} else if(paritytab[parity] == 2) {
		sf |= SERF_PARTY_ON;
	}
	t0  = 0x51040303;
	t1  = 0x03030303;

	SetParams(IORreadser,rbl,rwl,wwl,stopbitstab[stopbits],
		  brk,baud,sf,t0,t1);
}

/* SERIAL I/O functions */

SetParams(io,rbuf_len,rlen,wlen,stopbits,brk,baud,sf,ta0,ta1)

struct IOExtSer *io;
ULONG rbuf_len;
UBYTE rlen;
UBYTE wlen;
UBYTE stopbits;
ULONG brk;
ULONG baud;
UBYTE sf;
ULONG ta0;
ULONG ta1;
{
	int error;

	io->io_ReadLen       = rlen;
	io->io_BrkTime       = brk;
	io->io_Baud          = baud;
	io->io_WriteLen      = wlen;
	io->io_StopBits      = stopbits;
	io->io_RBufLen       = rbuf_len;
	io->io_SerFlags      = sf;
	io->IOSer.io_Command = SDCMD_SETPARAMS;
	io->io_TermArray.TermArray0 = ta0;
	io->io_TermArray.TermArray1 = ta1;

	if ((error = DoIO (io)) != 0) {
		printf ("serial.device setparams error %ld \n", error);
	}
	return (error);
}

ReadSer(data,length)
UBYTE *data;
int length;
{
	IORreadser->IOSer.io_Data = (APTR)data;
	IORreadser->IOSer.io_Length = (ULONG)length;
	IORreadser->IOSer.io_Command = CMD_READ;

	SendIO(IORreadser);
}

kill_ReadSer()
{
	AbortIO(IORreadser);
	while(GetMsg(serialreadport));
}

readserresult(errno,length)
int *errno, *length;
{
	*errno = IORreadser->IOSer.io_Error;
	*length = IORreadser->IOSer.io_Actual;
}

WriteSer(data,length)
UBYTE *data;
int length;
{
	IORwriteser->IOSer.io_Data = (APTR)data;
	IORwriteser->IOSer.io_Length = length;
	IORwriteser->IOSer.io_Command = CMD_WRITE;

	SendIO(IORwriteser);
}

writeserresult(errno)
int *errno;
{
	*errno = IORwriteser->IOSer.io_Error;
}

SendWaitWrite(data,length)
UBYTE *data;
int length;
{
	int error;

	IORwriteser->IOSer.io_Data = (APTR)data;
	IORwriteser->IOSer.io_Length = length;
	IORwriteser->IOSer.io_Command = CMD_WRITE;

	if((error = DoIO(IORwriteser)) != 0) {
		fprintf (stderr,"serial.device write error %ld \n", error);
	}
	return ((int)IORwriteser->IOSer.io_Actual);
}

/* send a break to the host */
void breakSer(readActive)
int readActive;
{
	if(readActive)
		AbortIO(IORreadser);
	IORreadser->IOSer.io_Command = SDCMD_BREAK;
	DoIO(IORreadser);
	if(readActive) {
		IORreadser->IOSer.io_Command = CMD_READ;
		SendIO(IORreadser);
	}
}

#ifdef notdef
/***********************************************************************
*
*	Exec Support Function -- Extended IO Request
*
***********************************************************************/

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <exec/ports.h>
#include <exec/libraries.h>
#include <exec/io.h>
#include <exec/tasks.h>
#include <exec/execbase.h>

extern APTR AllocMem();

/****** exec_support/CreateExtIO **************************************
*
*   NAME	
*	CreateExtIO() -- create an Extended IO request
*
*   SYNOPSIS
*	ioReq = CreateExtIO(ioReplyPort,size);   
*
*   FUNCTION
*	Allocates memory for and initializes a new IO request block
*	of a user-specified number of bytes.
*
*   INPUTS
*	ioReplyPort - a pointer to an already initialized
*		message port to be used for this IO request's reply port.
*
*   RESULT
*	Returns a pointer to the new block.  Pointer is of the type
*	struct IORequest.
*
*	0 indicates inability to allocate enough memory for the request block
*	or not enough signals available.
*
*   EXAMPLE
*	struct IORequest *myBlock;
*	if( (myBlock = CreateExtIO(myPort,sizeof(struct IOExtTD)) == NULL)
*		exit(NO_MEM_OR_SIGNALS);
*
*	example used to allocate space for IOExtTD (trackdisk driver
*	IO Request block for extended IO operations).
*
*   SEE ALSO
*	DeleteExtIO
*
***********************************************************************/

struct IORequest *CreateExtIO(ioReplyPort,size)
    struct MsgPort *ioReplyPort;
    LONG size;
{
    struct IORequest *ioReq;

    if (ioReplyPort == 0)
	return ((struct IORequest   *) 0);

    ioReq = (struct IORequest *)AllocMem (size, MEMF_CLEAR | MEMF_PUBLIC);

    if (ioReq == 0)
	return ((struct IORequest   *) 0);

    ioReq -> io_Message.mn_Node.ln_Type = NT_MESSAGE;
    ioReq -> io_Message.mn_Node.ln_Pri = 0;

    ioReq -> io_Message.mn_ReplyPort = ioReplyPort;

    return (ioReq);
}

/****** exec_support/DeleteExtIO **************************************
*
*   NAME
*	DeleteExtIO() - return memory allocated for extended IO request
*
*   SYNOPSIS
*	DeleteExtIO(ioReq,size);
*
*   FUNCTION
*	See summary line at NAME.  Also frees the signal bit which
*	had been allocated by the call to CreateExtIO.
*
*   INPUTS
*	A pointer to the IORequest block whose resources are to be freed.
*
*   RESULT
*	Frees the memory.  Returns (no error conditions shown)
*
*   EXAMPLE
*	struct IORequest *myBlock;
*	DeleteExtIO(myBlock,(sizeof(struct IOExtTD)));
*		
*	example shows that CreateExtIO had been used to create a trackdisk
*	(extended) IO Request block.
*
*   SEE ALSO
*	CreateExtIO
*
**************************************************************************/

DeleteExtIO(ioExt,size)
    struct IORequest *ioExt;
    LONG size;
{
    ioExt -> io_Message.mn_Node.ln_Type = 0xff;
    ioExt -> io_Device = (struct Device *) -1;
    ioExt -> io_Unit = (struct Unit *) -1;

    FreeMem (ioExt, size);
}
#endif
SHAR_EOF
if test 7910 -ne "`wc -c serial.c`"
then
echo shar: error transmitting serial.c '(should have been 7910 characters)'
fi
echo shar: extracting sio.c '(4904 characters)'
cat << \SHAR_EOF > sio.c
/*------------------------------------------------------------------*/
/*	Sio.c:  Serial I/O for Amiga Version of PCMail		    */
/*	Created: 27Jun87 by J.A. Lydiatt			    */
/*								    */
/* Exports the following routines required by PCMail:		    */
/*  SIOInit():		Initialize Serial Port			    */
/*  SIOClose():		Close and free Serial Port resources	    */
/*  SIOSpeed():		Set bps					    */
/*  SIORead():		read characters from serial port	    */
/*  SIOWrite():		write characters to serial port		    */
/*  SIOInBuffer():	Set Buffer size for read & writes.	    */
/*  SIOOutBuffer():	(Has no effect in Amiga Version)	    */
/*------------------------------------------------------------------*/

#include <exec/types.h>
#include <exec/io.h>
#include <stdio.h>
#ifndef TRUE
#define TRUE -1
#define FALSE 0
#endif

/*--- SerialIO Function Declarations --- */

extern void initserial();
extern void sercleanup();		/* Return SerialIO resources	  */
extern void setspeed();			/* Set baud rate		  */
extern void dosetparams();		/* Set serial parameters	  */

/*--------------------------------------------------------------*/
/*	 getspeed/getbaud: check for valid baud parameters	*/
/*--------------------------------------------------------------*/

static struct {
	unsigned baudr;
	int speedcode;

} speeds[] = {
	300,	5,
	1200,	3,
	2400,	2,
	4800,	1,
	9600,	0,
	0,
};

static unsigned getspeed(code)
{
	register n;

	for (n=0; speeds[n].baudr; ++n)
		if (speeds[n].speedcode == code)
			return speeds[n].baudr;
	return 0;
}


static int getbaud(code)
char *code;
{
	register n;
	register int Baudrate;
	
	Baudrate = atoi(code);
	
	for (n=0; speeds[n].baudr; ++n)
		if (speeds[n].baudr == Baudrate)
			return speeds[n].speedcode;
	return -1;
}

/*--------------------------------------------------------------*/
/*	SIOInit: initialize serial I/O				*/
/*--------------------------------------------------------------*/


SIOInit ( whichport, speed )
char * whichport;
char * speed;
{
	int baud;

	/*  fprintf( stderr, "sioinit %s %s\n", whichport, speed ); /* */

	initserial();
	if ( (baud = getbaud( speed )) >= 0 )
		setspeed( baud );

	if ( !OpenTimer() ) {
	   fprintf( stderr, "Can't open the Timer Device\n" );
	   sercleanup();
	   return( -1 );
	}

	dosetparams();
	return( 0 );
}

/*--------------------------------------------------------------*/
/*	SIOSpeed:  set the serial Baud rate 			*/
/*--------------------------------------------------------------*/

SIOSpeed( speed )
char *speed;
{
    int baud;

    if ( (baud = getbaud( speed )) >= 0 ) {
	setspeed( baud );
	dosetparams();
    }
}

/*--------------------------------------------------------------*/
/*	SIOInBuffer/ SIOOutBuffer:	Set Buffer Size.	*/
/*--------------------------------------------------------------*/

SIOInBuffer ( buf, size )
char * buf;
int size;
{
}

SIOOutBuffer ( buf, size )
char * buf;
int size;
{
}

/*--------------------------------------------------------------*/
/*	SIOClose:	Close Serial port.			*/
/*--------------------------------------------------------------*/

SIOClose ( dtr )
{
   sercleanup();
   CloseTimer();
}

/*--------------------------------------------------------------*/
/*	SIOWrite: send count characters to serial port		*/
/*--------------------------------------------------------------*/

SIOWrite ( buf, count )
register char * buf;
int count;
{
	SendWaitWrite(buf, count);
	return count;
}

/*--------------------------------------------------------------*/
/*	SIORead: read mincount <= #characters <= maxcount	*/
/*	return  # of characters read, or -1 if timed out after	*/
/*	after tenths / 10 seconds.				*/
/*--------------------------------------------------------------*/
static int readOutstanding = 0;

int SIORead ( buf, mincount, maxcount, tenths )
char   *buf;
int	mincount;
int	maxcount;
int	tenths; /* timeout is in tenth's of seconds */
{
	ULONG signals;
	extern struct MsgPort *serialreadport, *timerPort;
	static char inBuf[512];
	static int inBufPos = 0;
	int count, errorNumber;
 
	if(tenths < 10)
		tenths = 10;
	StartTimer(tenths/10L, 0);

	while(1) {
		if((inBufPos >= mincount) && !readOutstanding) {
			movmem(inBuf,buf,mincount);
			inBufPos -= mincount;
			if(inBufPos)
				movmem(inBuf + mincount, inBuf, inBufPos);
			return(mincount);
		}
		if(!readOutstanding) {
			ReadSer(inBuf + inBufPos, mincount - inBufPos);
			readOutstanding = 1;
		}
		signals = Wait((1 << timerPort->mp_SigBit)
			     | (1 << serialreadport->mp_SigBit));

		if(signals & (1 << timerPort->mp_SigBit)) {
			if(TimerExpired()) {
				return(-1);
			} else {
				getTimerMsg();
			}
		}
		if(signals & (1 << serialreadport->mp_SigBit)) {
			readserresult(&errorNumber, &count);
			GetMsg(serialreadport);
			readOutstanding = 0;
			if(errorNumber) {
				inBufPos = 0;
				return(-1);
			}
			inBufPos += count;
		}
	}
}

void ssendbrk() {
	breakSer(readOutstanding);
}
SHAR_EOF
if test 4904 -ne "`wc -c sio.c`"
then
echo shar: error transmitting sio.c '(should have been 4904 characters)'
fi
echo shar: extracting sleep.c '(287 characters)'
cat << \SHAR_EOF > sleep.c
/*--------------------------------------------------------------*/
/* sleep.c:	Implement sleep( seconds ) on the Amiga.	*/
/*--------------------------------------------------------------*/

void sleep( seconds )
unsigned int seconds;
{
     if ( seconds > 0 )
	Delay( seconds*50L );
}

SHAR_EOF
if test 287 -ne "`wc -c sleep.c`"
then
echo shar: error transmitting sleep.c '(should have been 287 characters)'
fi
echo shar: extracting timer.c '(3078 characters)'
cat << \SHAR_EOF > timer.c
/*  
 *  Timer.c: Functions to invoke the Amiga timer:
 *  
 *  External Functions:
 *
 *  OpenTimer, CloseTimer, StartTimer, TimerExpired, GetTimerSigBit
 * 
 *  Maintenance Notes:
 *   05Jul86  - Created by Jeff Lydiatt, Vancouver, Canada.
 */

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <exec/tasks.h>
#include <exec/io.h>
#include <devices/timer.h>
#ifdef MANX
#include <functions.h>
#else
#include <proto/exec.h>
#include <proto/timer.h>
#endif

static struct timerequest TimerIO;
struct MsgPort    *timerPort = NULL;
static BOOL timerON;
static BOOL timerExpired;

/*-------------------------------------------------------------*/
/*	OpenTimer: return TRUE if timer opened OK	       */
/*-------------------------------------------------------------*/

BOOL OpenTimer()
{
   register struct timerequest *t = &TimerIO;
   register struct MsgPort *port;

   timerON = FALSE;
   timerExpired = TRUE;
   if ( timerPort != NULL )
      return TRUE;

   if ( (port = CreatePort("Timer Port", 0L)) == NULL )
      return FALSE;
   else
      timerPort = port;

   setmem(&TimerIO, sizeof(TimerIO), 0);
   if (OpenDevice(TIMERNAME, UNIT_VBLANK, t, 0L) != 0)
     {
	DeletePort( port );
	timerPort = NULL;
	return FALSE;
     }

   return TRUE;
}

/*-------------------------------------------------------------*/
/*	CloseTimer: All Done with the timer.		       */
/*-------------------------------------------------------------*/

void CloseTimer()
{
   register struct timerequest *t = &TimerIO;

   if (!timerPort)
      return;
   if ( timerON )
      AbortIO( t );

   CloseDevice( t );
   DeletePort( timerPort );
   timerPort = NULL;
}

/*-------------------------------------------------------------*/
/*	GetTimerSigBit: return Timer signal bit		       */
/*-------------------------------------------------------------*/

int GetTimerSigBit()
{
   return timerPort->mp_SigBit;
}

/*-------------------------------------------------------------*/
/*	StartTimer: launch the timer.			       */
/*-------------------------------------------------------------*/

void StartTimer(seconds, micros)
ULONG seconds, micros;
{
   register struct timerequest *t = &TimerIO;

   if ( timerON )
     {
	AbortIO( t );
	while(GetMsg( timerPort ));
	timerON = FALSE;
        timerExpired = TRUE;
     }

   t->tr_time.tv_secs = seconds;
   t->tr_time.tv_micro = micros;
   t->tr_node.io_Command = TR_ADDREQUEST;
/*   t->tr_node.io_Flags = IOF_QUICK;
   t->tr_node.io_Error = 0; */
   t->tr_node.io_Message.mn_ReplyPort = timerPort;
   SendIO( t );
   timerExpired = FALSE;
   timerON = TRUE;
}

/*-------------------------------------------------------------*/
/*	TimerExpired: returns TRUE if timer expired.	       */
/*-------------------------------------------------------------*/

BOOL TimerExpired()
{
   if ( timerON && ( CheckIO( &TimerIO ) == NULL) )
      return FALSE;

   while(GetMsg( timerPort ));
   timerExpired = TRUE;
   timerON = FALSE;

   return timerExpired;
}

getTimerMsg()
{
    GetMsg( timerPort );
}
SHAR_EOF
if test 3078 -ne "`wc -c timer.c`"
then
echo shar: error transmitting timer.c '(should have been 3078 characters)'
fi
echo shar: extracting ulib.c '(5372 characters)'
cat << \SHAR_EOF > ulib.c
/*		ulib.c


		Amiga library
		

	Things to do in uu host

		serial I/O
		
		directory stuff
			opendir, readdir, closedir

		prolog and epilog

		system call

*/

#include <stdio.h>
#include "host.h"
#ifdef MANX
#include <sgtty.h>
#endif

int lineIsOpen = 0;

/**/
/*
 *
 *      login (for slave in PC mode)
 * Real dumb login handshake
*/
login()
{
	char	logmsg[132];
#ifdef PC
lretry:
	msgtime = 9999;
	rmsg(logmsg, 0); /* wait for a <CR> or <NL> */
	msgtime = 2 * MSGTIME;
	wmsg("Username:", 0);
	rmsg(logmsg, 0);
	printmsg( 0, "Username = %s", logmsg );
	wmsg("Password:", 0);
	rmsg(logmsg, 0);
	printmsg( 14, "Password = %s", logmsg );
	if (strcmp(logmsg, "uucp") != 0) 
		goto lretry;
#endif
	return('I');
}


char inbuf[BUFSIZ];
char outbuf[BUFSIZ];

swrite(data, num)
int	num;
char	*data;
{

	int test;
	unsigned char * cp;

	if (debuglevel > 14)
		fputc( '{', stderr );
	if (debuglevel > 14) {
		test = num;
		cp = data;
		while (test--)
			fprintf( stderr, isprint(*cp)? "{%c}":"{%02x}", *cp++ );
	}
	test = SIOWrite( data, num );
	if (debuglevel > 14)
		fputc( '}', stderr );
	return( test );

}

/* non-blocking read essential to "g" protocol */
/* see "dcpgpkt.c" for description */
/* This all changes in a mtask systems. Requests for */
/* I/O should get qued and an event flag given. Then the */
/* requesting process (e.g.gmachine()) waits for the event */
/* flag to fire processing either a read or a write. */
/* Could be implemented on VAX/VMS or DG but not MS-DOS */
sread(buf, num, timeout)
char	*buf;
int	num, timeout;
{
/*
	return( SIORead( buf, num, num, timeout*10 ) );
*/
	int count;
	int test;
	unsigned char * cp;

	if (debuglevel > 13)
		fputc( '[', stderr );
	printmsg( 15, "sread: num: %d  timeout: %d", num, timeout );
		
	count = SIORead( buf, num, num, timeout*10 );
	printmsg( 15, "sread: read: %d ", count );

	if (debuglevel > 13 && count > 0) {
		test = count;
		cp = buf;
		while (test--)
			fprintf( stderr, isprint(*cp)? "[%c]":"[%02x]", *cp++ );
	}
		
	if (debuglevel > 13)
		fputc( ']', stderr );
	return( count );	
	
}



openline(name, baud)
char	*name, *baud;
{

	printmsg( 3, "openline: name: \"%s\"  baud: \"%s\"", name, baud );
	lineIsOpen = 1;
	if ( SIOInit( name, baud ) )
	   return -1;
	SIOInBuffer( inbuf, BUFSIZ );
	SIOOutBuffer( outbuf, BUFSIZ );
	return( 0 );
}


closeline()
{
	if(lineIsOpen) {
		SIOClose( 1 );
		lineIsOpen = 0;
	}
}


nodot(string)
{
}



notimp( argc, argv )
char *argv[];
{
	/*debuglevelMsg("\Pcheck argc (08) and argv (0a) ");*/
	fprintf( stderr, "shell: %s not implemented\n", *argv );
}

/*------------------------------------------------------------------*/
/*	RNews:	my private rnews!				    */
/*------------------------------------------------------------------*/
static void RNews( inname )
char *inname;
{
	extern	char *newsdir;
	register struct tm	*thetm;
	long	tloc;
	char	filename[132];
	FILE 	*f, *fin;
	FILE	*FOPEN();
	char	buf[BUFSIZ];
	int	bytesRead;
	
	static int count = 0;
	int	len;
	
	/* inname is of form "D.jlamiBCnnnn".  Pick off the nnnn. */
	len = strlen( inname ) - 1;
	while ( len >= 0 )
	  {
		if ( '0' <= inname[len] && inname[len] <= '9' )
		   --len;
		else
		   break;
	   }

	sprintf( filename, "%s/%s", newsdir, &inname[len+1] );
	if ( (f = FOPEN( filename, "r", 't' )) != NULL )
	   {
		/* Already exists, so make a timestamped one. */
		fclose( f );	
		tloc = time( (long *)NULL );
		thetm = localtime( &tloc );

		sprintf( filename, "%s/%02d%02d%02d%02d%02d%02d.%03d",
			newsdir,
			thetm->tm_year % 100, thetm->tm_mon,
			thetm->tm_mday, thetm->tm_hour,
			thetm->tm_min,  thetm->tm_sec,  count
			);
		++count;
	   }
	
	if ( (f = FOPEN( filename, "w", 't' )) == (FILE *)NULL ) {
		fprintf( stderr, "rnews: can't open %s\n", filename );
		onBreak();
	}

	if ( (fin = FOPEN( inname, "r", 't' )) == NULL )
	  {
		fprintf( stderr, "rnews: Couldn't open %s\n", inname );
		fclose( f );
		onBreak();
	  }
	
	while(bytesRead = fread(buf, 1, BUFSIZ, fin)) {
		if(fwrite(buf, bytesRead, 1, f) != 1) {
			fprintf(stderr,"rnews: write error on %s\n", filename);
			fclose(f);
			onBreak();
		}
	}

	fclose( f );
	fclose( fin );
}

/* if name is of the form user@domain or domain!user and domain is either */
/* DOMAIN or NODENAME then return user. Otherwise return name.		  */
/* Note: this function modifies it's argument.				  */

static char * getLocalName(name)
char *name;
{
	char *cp;

	if(cp = strchr(name, '@')) {
		if(!strcmp(cp + 1, domain) || !strcmp(cp + 1, nodename))
			*cp = 0;
	} else if(cp = strchr(name, '!')) {
		*cp = 0;
		if(!strcmp(name, domain) || !strcmp(name, nodename))
			return(cp + 1);
		*cp = '!';
	}
	return(name);
}

/* 		shell

*/

char * getcwd();

shell( command, inname, outname, errname )
char * command;
char * inname;
char * outname;
{

	char	* argvec[50];

	int rmail();
	int rnews();
	
	int 	argcp;

	char **argvp;
	char args;

	argcp = 0;

	argcp = getargs( command, argvec );

	argvp = argvec;
	args = argcp;

	if ( debuglevel > 5 ) {
		while ( args ) 
			fprintf( stderr, "arg: %d  %s\n", args--, *argvp++ );
		argvp = argvec;
		args = argcp;
	}
	/* */
	
	if ( strcmp( *argvp, "rmail" ) == SAME ) {
		argvec[1] = getLocalName(argvec[1]);
		rmail( argcp, argvp, inname );
	} else if ( strcmp( *argvp, "rnews" ) == SAME ) {
		/* proto = rnews; */
		RNews( inname );
		return; 
	} else
		notimp( argcp, argvp );
}






SHAR_EOF
if test 5372 -ne "`wc -c ulib.c`"
then
echo shar: error transmitting ulib.c '(should have been 5372 characters)'
fi
echo shar: extracting uuhost.c '(1187 characters)'
cat << \SHAR_EOF > uuhost.c
/*		uuhost.c
*/
#include <stdio.h>
#include <setjmp.h>
#include "host.h"

char   *orgDir;
char   *getcwd();
int	chdir();
int	debuglevel = 0;		/* debuginglevel */

jmp_buf	dcpexit;

main( argc, argv )
int	argc;
char *argv[];
{
	int returnCode = 0;
	char orgDirBuf[100];

	/* Amiga specific prolog */

	loadenv();
	orgDir = getcwd( orgDirBuf, sizeof(orgDirBuf) );

	chdir( spooldir );

	/* setup longjmp for error exit's */
	if ( setjmp( dcpexit ) == 0 ) {
		returnCode = dcpmain( argc, argv );
	}

	/* Amiga specific epilog */

	exitenv();
	chdir( orgDir );
	exit( returnCode );

}


/* canonical name conversion routines

	importpath	canonical -> host
	exportpath	host -> canonical

	host		your local pathname format
	canonical	unix style
*/

importpath( host, canon )
char * host;
char * canon;
{
	extern char *pubdir;

	*host = '\0';

	if ( *canon == '~' )
	  {
		if ( canon[1] == '/' )
		   strcpy( host, pubdir );
		else
		   {
			strcpy( host, home );
			strcat( host, "/" );
		   }
	  }

	strcat( host, canon );

        if ( *host == '/' )
	  *host = ':';
}

exportpath( canon, host )
char * host;
char * canon;
{
	strcpy( canon, host );
	if ( *canon == ':' )
	   *canon = '/';
}
SHAR_EOF
if test 1187 -ne "`wc -c uuhost.c`"
then
echo shar: error transmitting uuhost.c '(should have been 1187 characters)'
fi
#	End of shell archive
exit 0