[comp.sources.misc] uniflex dcp Part 2 of 2

sampson@killer.UUCP (Steve Sampson) (08/27/87)

#!/bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by sampson on Mon Aug 24 03:11:01 CDT 1987
# Contents:  dcp.c dcpgpkt.c dcpio.c dcprec.c dcpscan.c dcpsend.c
#	dcpstart.c dcpsys.c rmail.c uuxqt.c
 
echo x - dcp.c
sed 's/^XX//' > "dcp.c" <<'@//E*O*F dcp.c//'
XX/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
XX
XX/*
XX *	This program implements a uucico type file transfer and remote
XX *	execution type protocol. 
XX */
XX
XX#include "dcp.h"
XX
XXint	pktsize;                /* packet size for pro */
XXint	flog;                   /* system log file */
XXint	fw;                     /* cfile pointer */
XXint	fpr,fpw;                /* comm dev pointer */
XXchar	state;			/* system state */
XXchar	cfile[80];              /* work file pointer */
XXint	remote;                 /* -1 means we're remote*/
XXint	debug;                  /* debugging level */
XXint	msgtime;                /* timout setting */
XXchar	fromfile[132];
XXchar	tofile[132];
XXint	fp;                     /* current disk file ptr */
XXint	size;                   /* nbytes in buff */
XXint	fsys;
XXchar	tty[16];
XXchar	myname[8];
XXchar	username[128];
XXchar	spooldir[64];
XXchar	rmtname[8];
XXchar	cctime[16];
XXchar	device[16];
XXchar	type[8];
XXchar	speed[8];
XXchar	proto[8];
XXchar	loginseq[132];
XX
XX/*
XX *	Usage:
XX *	  dcp (master/slave(D)) (debug level 0 = none(D))
XX *	      (system name(MYNAME)) (console device)
XX *
XX *	defaults come from USERFILE
XX */
XX
XXmain(argc,argv)
XXint	argc;
XXchar	*argv[];
XX{
XX	int	ftmp;
XX	char	line[132];
XX
XX	flog = creat(SYSLOG, PERMS);
XX	close(flog);
XX
XX	flog = open(SYSLOG, 2);
XX
XX	remote = TRUE;
XX	debug = 0;
XX	fp = fw = -1;
XX
XX	chdir(SPOOLDIR);
XX
XX	if (argc > 1 && strcmp(argv[1], "master") == 0)
XX		remote = FALSE;
XX
XX	if (argc > 2)
XX		sscanf(argv[2], "%d", &debug);
XX
XX	if (argc > 3)
XX		strcpy(myname, argv[3]);
XX	else
XX		strcpy(myname, MYNAME);
XX
XX	if (argc > 4)
XX		strcpy(tty, argv[4]);
XX	else
XX		strcpy(tty, TTY);
XX
XX	if (!remote)  {
XX		if ((fsys = open(SYSTEMS, 0)) == -1)
XX			return(FALSE);
XX
XX		state = 'I';
XX
XX		while (TRUE)  {
XX			if (debug > 0)
XX				printmsg("Mstate = %c",state);
XX
XX			switch(state)  {
XX			case 'I':
XX				state = getsystem();
XX				break;
XX			case 'S':
XX				state = callup();
XX				break;
XX			case 'P':
XX				state = startup();
XX				break;
XX			case 'D':
XX				state = master();
XX				break;
XX			case 'Y':
XX				state = sysend();
XX				break;
XX			case 'G':
XX				state = 'I';
XX				break;
XX			}
XX
XX			if (state == 'A')
XX				break;
XX		}
XX
XX		close(fsys);
XX		closeline();
XX	} else  {
XX		if (openline(tty, speed) == -1)
XX			return(FALSE);
XX
XX		state = 'I';
XX
XX		while (TRUE)  {
XX			if (debug > 0)
XX				printmsg("Sstate = %c",state);
XX
XX			switch (state)  {
XX			case 'I':
XX				state = startup();
XX				break;
XX			case 'R':
XX				state = slave();
XX				break;
XX			case 'Y':
XX				state = sysend();
XX				break;
XX			}
XX			
XX			if (state == 'A')
XX				break;
XX		}
XX
XX		closeline();
XX	}
XX
XX	close(flog);
XX
XX	execl("/etc/uuxqt", "uuxqt", 0);
XX	if (debug)
XX		printmsg("Error can't exec /etc/uuxqt");
XX}
XX
XX
XX/*
XX**
XX**
XX**master
XX**
XX**
XX*/
XX
XX
XXmaster()
XX{
XX	state = 'I';
XX
XX	while (TRUE)  {
XX		if (debug > 1)
XX			printmsg("Top level state (master mode) %c", state);
XX
XX		switch (state)  {
XX		case 'I':
XX			state = sinit();
XX			break;
XX		case 'B':
XX			state = scandir();
XX			break;
XX		case 'S':
XX			state = send();
XX			break;
XX		case 'Q':
XX			state = sbreak();
XX			break;
XX		case 'G':
XX			state = receive();
XX			break;
XX		case 'C':
XX			state = 'Y';
XX			break;
XX		case 'Y':
XX			state = endp();
XX			break;
XX		case 'P':
XX			return('Y');
XX		case 'A':
XX		default:
XX			return('A');
XX		}
XX	}
XX}
XX
XX
XX/*
XX**
XX**
XX**slave
XX**
XX**
XX*/
XX
XX
XXslave()
XX{
XX	state = 'I';
XX
XX	while (TRUE)  {
XX		if (debug > 1)
XX			printmsg("Top level state (slave mode) %c", state);
XX
XX		switch (state)  {
XX		case 'I':
XX			state = rinit();
XX			break;
XX		case 'F':
XX			state = receive();
XX			break;
XX		case 'C':
XX			state = schkdir();
XX			break;
XX		case 'T':
XX			state = 'B';
XX			break;
XX		case 'B':
XX			state = scandir();
XX			break;
XX		case 'S':
XX			state = send();
XX			break;
XX		case 'Q':
XX			state = sbreak();
XX			break;
XX		case 'G':
XX		case 'P':
XX			return('Y');
XX		case 'Y':
XX			state = endp();
XX			break;
XX		case 'A':
XX		default:
XX			return('A');
XX		}
XX	}
XX}
XX
XX
XX/*
XX *  r e c e i v e
XX *
XX *  This is the state table switcher for receiving files.
XX */
XX
XXreceive()
XX{
XX
XX	state = 'F';		/* Receive-Init is the start state */
XX
XX	while (TRUE)  {
XX		if (debug > 2)
XX			printmsg(" receive state: %c", state);
XX
XX		switch (state)  {		/* Do until done */
XX		case 'F':
XX			state = rfile();
XX			break;			/* Receive-File */
XX		case 'D':
XX			state = rdata();
XX			break;			/* Receive-Data */
XX		case 'C':
XX			return('C');		/* Complete state */
XX		case 'A':
XX		default:
XX			return('Y');		/* "Abort" state */
XX
XX		}
XX	}
XX}
XX
XX
XX/*
XX *  s e n d 
XX *
XX *  Sendsw is the state table switcher for sending files.  It loops until
XX *  either it finishes, or an error is encountered.  The routines called
XX *  by sendsw are responsible for changing the state.
XX *
XX */
XX
XXsend()
XX{
XX	fp = -1;                /* reset file getter/opener */
XX	state = 'F';		/* Send initiate is the start state */
XX	while (TRUE)  {		/* Do this as long as necessary */
XX		if (debug > 2)
XX			printmsg("send state: %c",state);
XX
XX		switch (state)  {
XX		case 'F':
XX			state = sfile();
XX			break;			/* Send-File */
XX		case 'D':
XX			state = sdata();
XX			break;			/* Send-Data */
XX		case 'Z':
XX			state = seof();
XX			break;			/* Send-End-of-File */
XX		case 'B':
XX			return ('B');		/* Complete */
XX		case 'A':
XX		default:
XX			return ('Y');		/* "Abort" */
XX		}
XX	}
XX}
@//E*O*F dcp.c//
chmod u=rw,g=r,o=r dcp.c
 
echo x - dcpgpkt.c
sed 's/^XX//' > "dcpgpkt.c" <<'@//E*O*F dcpgpkt.c//'
XX/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
XX/* second 1-window "g" protocol */
XX
XX#include "dcp.h"
XX
XX#define PKTSIZE	64
XX#define PKTSIZ2	2
XX#define HDRSIZE 6
XX#define MAXTRY	5	/* ought to be greater than RWINDOW */
XX#define SWINDOW	3
XX#define MAXERR	5
XX
XXstatic	int	pkrec, pksent, pknerr;
XX
XX
XXgclosepk()
XX{
XX	unsigned char	tmp[PKTSIZE];
XX
XX	gspack(1, 0, 0, 0, tmp);
XX	gspack(1, 0, 0, 0, tmp);
XX
XX	return(0);
XX}
XX
XX
XXgopenpk()
XX{
XX	int		i, j, n1, n2, len;
XX	unsigned char	tmp[PKTSIZE];
XX
XX	pkrec = 0;
XX	pksent = 1;
XX	pktsize = PKTSIZE;
XX	msgtime = MSGTIME + 20;
XX	pknerr = 0;
XX	j = 7;
XXgsta:
XX	if (j == 4)
XX		return(0);	/* if ok */
XX
XX	for (i = 0; i < MAXTRY; i++)  {
XX		gspack(j, 0, 0, 0, tmp);
XX		if (grpack(&n1, &n2, &len, tmp) == j)  {
XX			j--;
XX			goto gsta;
XX		}
XX	}
XX
XX	return(-1); /* fail */
XX}
XX
XX
XX/*
XX *
XX * ggetpkt
XX ***** description: Gets no more than a packet's worth of data from
XX *****               the "packet i/o state machine". May have to
XX *****               periodically run the pkt machine to get some
XX *****               packets.
XX * on input: dont care   getpkt(data,&len)  char *data int len
XX * on return: data+\0 and length in len. ret(0) if alls well
XX * ret(-1) if problems.(fail)
XX */
XX
XXggetpkt(data, len)
XXunsigned char	*data;
XXint	*len;
XX{
XX	int		npkrec, npksent, i, u, nlen, nakflg;
XX	unsigned char	tmp[PKTSIZE];
XX
XX	msgtime = 2 * (MSGTIME + 20);
XX	nakflg = 0;
XX
XX	for (i = 0; i < MAXTRY; i++)  {
XX		switch(grpack(&npkrec, &npksent, &nlen, data))  {
XX		case DATA:
XX			if (npksent != ((pkrec + 1) % 8))  {
XX                		if (debug > 0)
XX					printmsg("unexpected pkt %d ", pkrec);
XX                		break;
XX		        }  
XX
XX		        pkrec = (pkrec + 1) % 8;
XX		        *len = nlen;
XX
XX#ifdef UNIFLEX		/* change all LF to CR */
XX
XX			for (u = 0; u < nlen; u++)  {
XX				if (data[u] == 0x0A)
XX					data[u] = 0x0D;
XX			}
XX#endif
XX
XX		        if (nakflg)
XX		        	gspack(NAK, pkrec, 0, 0, tmp);
XX		        else
XX		      		gspack(ACK, pkrec, 0, 0, tmp);
XX
XX		        return(0);
XX		case ERROR:
XX			nakflg = 1;
XX
XX		        if (debug > 0)
XX				printmsg("checksum error pkt %d ", pkrec);
XX
XX		        break;  
XX		case CLOSE:
XX			return(-1);
XX		default:
XX			break; /* anything else:BADHDR,LOST,PARTIAL,UNKNOWN*/
XX		}
XX	}
XX
XX	pknerr++;
XX	if (pknerr >= MAXERR)
XX		return(-1);
XX
XX	return(0);
XX}
XX
XX
XX/*
XX *
XX *  sendpkt
XX *
XX *****   description:    Put at most a packet's worth of data  in the pkt state
XX *****                   machine for xmission.
XX *****                   May have to run the pkt machine a few times to get
XX *****                   an available output slot.
XX *
XX * on input: char *data int len,flg; len=length of data in data.
XX *           flg=2 just send the packet with no wait for ack.
XX *           flg>0 zero out the unused part of the buffer. (for UUCP "msg"
XX *                                                                   pkts)
XX *           flg=0 normal data
XX * return:   ret(0) if alls well ret(-1) if problems (fail)
XX *
XX */
XX
XXgsendpkt(data, len, msg)
XXunsigned char	*data;
XXint	len, msg;
XX{
XX	int		nlen, npkrec, npksent, i;
XX	unsigned char	tmp[PKTSIZE];
XX
XX	msgtime = MSGTIME + 20;
XX
XX#ifdef UNIFLEX	/* change all CR to LF */
XX
XX	for (i = 0; i < strlen(data); i++)  {
XX		if (data[i] == 0x0D)
XX			data[i] = 0x0A;
XX	}
XX#endif
XX
XX	if (msg)  {
XX		len = PKTSIZE;
XX		for (i = strlen(data); i < len; i++)
XX			data[i] = '\0';
XX	}
XX
XX	for (i = 0; i < MAXTRY; i++)  {
XX		gspack(DATA, pkrec, pksent, len, data);
XX		if (msg == 2)
XX			return(0);
XX
XX		switch(grpack(&npkrec, &npksent, &nlen, tmp))  {
XX		case ACK: /* Ignore wrong ACK's */
XX			if (npkrec != pksent)  {
XX		        	if (debug > 0)
XX					printmsg("wrong RR %d (%d) ",
XX					  pksent, npkrec);
XX				break;
XX	        	} 
XX
XX	        	pksent = (1 + pksent) % 8;
XX	        	return(0);
XX		case NAK:
XX			if (debug > 0)
XX				printmsg("REJ %d ", npkrec);
XX
XX		        if (npkrec != pksent)  {
XX	        		if (debug > 0)
XX					printmsg("wrong NAK RJ %d (%d)",
XX					  pksent, npkrec);
XX				break;
XX			}
XX
XX			pksent = (1 + pksent) % 8;
XX			return(0);
XX		case CLOSE:
XX			return(-1);
XX		default:
XX			break;
XX		}
XX	}
XX
XX	pknerr++;
XX	if (pknerr >= MAXERR)
XX		return(-1);
XX
XX	return(0);
XX}
XX
XX
XX/*
XX *
XX *
XX *      send a packet
XX * nt2=type nt3=pkrec nt4=pksent len=length<=PKTSIZE cnt1= data * ret(0) always
XX */
XX
XXgspack(nt2,nt3,nt4,len,cnt1)
XXint	nt2, nt3, nt4, len;
XXunsigned char	*cnt1;
XX{
XX	unsigned int	check, i;
XX	unsigned char	c2, pkt[HDRSIZE];
XX
XX	if (len > 64)
XX		len = 64;
XX
XX	if (len == 0)
XX		cnt1[0] = '\0';
XX
XX	if (debug > 0)  {
XX		printmsg("send packet type %d", nt2);
XX		printmsg("  num = %d n = %d", nt3, nt4);
XX		printmsg("  len = %d data =\n|%s|", len, cnt1);
XX	}
XX
XX	c2 = '\0';
XX	pkt[0] = '\020';
XX	pkt[4] = nt2 << 3;
XX	nt2 &= 7;
XX
XX	switch (nt2)  {
XX	case 1:
XX	      break;                  /* stop protocol */
XX	case 2:
XX	      pkt[4] += nt3;
XX	      break;   /* reject        */
XX	case 3:
XX	      break;
XX	case 4:
XX	      pkt[4] += nt3;
XX	      break;   /* ack          */
XX	case 5:
XX	      pkt[4] += SWINDOW;
XX	      break;   /* 3 windows */
XX	case 6:
XX	      pkt[4] += 1;
XX	      break;   /* pktsiz = 64 (1) */
XX	case 7:
XX	      pkt[4] += SWINDOW;
XX	      break;   /* 3 windows */
XX	case 0:
XX	      pkt[4] += 0x80 + nt3 + (nt4 << 3);
XX
XX              c2 = (PKTSIZE - len) & 0xff;
XX              if (c2)  {
XX                        pkt[4] += 0x40;   /* if len < PKTSIZE */
XX                        for (i = PKTSIZE - 1; i > 0; i--)
XX				cnt1[i] = cnt1[i - 1];
XX
XX                        cnt1[0] = c2;
XX		}
XX                break;
XX	}
XX
XX	pkt[4] &= 0xff;
XX
XX	if (nt2 != DATA)  {
XX	        pkt[1] = 9;             /* control packet size = 0 (9) */
XX		check = pkt[4];
XX	} else {
XX	        pkt[1] = PKTSIZ2;             /* data packet size = 64 (2) */
XX	        check = checksum(cnt1, PKTSIZE);
XX		i = pkt[4];	/* got to do this on PC for ex-or high bits */
XX		i &= 0xff;
XX		check = (check ^ i) & 0xffff;
XX	}
XX
XX	check = (0xaaaa - check) & 0xffff;
XX	pkt[2] = check & 0xff;
XX	pkt[3] = (check >> 8) & 0xff;
XX	pkt[5] = (pkt[1] ^ pkt[2] ^ pkt[3] ^ pkt[4]) & 0xff;
XX
XX	swrite(pkt, HDRSIZE);       /* header is 6-bytes long */
XX
XX	if (pkt[1] != 9)
XX		swrite(cnt1, PKTSIZE);	/* data is always 64 bytes long */ 
XX}
XX
XX
XX/*
XX *
XX *      read packet
XX * on return: nt3=pkrec nt4=pksent len=length <=PKTSIZE  cnt1=data *
XX * ret(type) ok; ret(-1) input buf empty; ret(-2) bad header;
XX *              ret(-3) lost pkt timeout; ret(-4) checksum error;ret(-5) ?
XX */
XX
XXgrpack(nt3,nt4,len,cnt1)
XXint	*nt3, *nt4, *len;
XXunsigned char	*cnt1;
XX{
XX	unsigned int	nt1, check, checkchk, i;
XX	unsigned char	c, c2, pkt[HDRSIZE];
XX	int		ii;
XX
XX	c = '\0';
XX	while ((c & 0x7f) != '\020')
XX		if (sread(&c, 1, msgtime) < 1)
XX			return(-1);
XX
XX	if (sread(&pkt[1], HDRSIZE - 1, msgtime) < (HDRSIZE - 1))
XX		return(-1);
XX
XX	/* header is 6-bytes long */
XX
XX	i = pkt[1] ^ pkt[2] ^ pkt[3] ^ pkt[4] ^ pkt[5];
XX	i &= 0xff;
XX
XX	if (i)  {                        /*  bad header */
XX	        if (debug)
XX			printmsg("****bad header****");
XX
XX	        return(-2);
XX	}
XX
XX	if ((pkt[1] &= 0x7f) == 9)  {       /* control packet */
XX	        *len = 0;
XX	        c = pkt[4] & 0xff;
XX	        nt1  = (unsigned)c >> 3;
XX	        *nt3 = c & 7;
XX	        *nt4 = 0;
XX	        check = 0;
XX	        checkchk = 0;
XX	        cnt1[*len] = '\0';
XX	}
XX	else {       /* data packet */
XX	        if (pkt[1] != PKTSIZ2)
XX			return(-5);   /* cant handle other than 64*/
XX
XX	        nt1  = 0;
XX	        c2 = pkt[4] & 0xff;
XX	        c = c2 & 0x3f;
XX	        *nt4 = (unsigned)c >> 3;
XX	        *nt3 = c & 7;
XX
XX	        if (sread(cnt1, PKTSIZE, msgtime) < PKTSIZE)
XX			return(-3);
XX
XX	        /* 64 byte packets even if partial */
XX
XX		i = pkt[3];
XX		i = (i << 8) & 0xff00;
XX		check = pkt[2];
XX		check = i | (check & 0xff);
XX	        checkchk = checksum(cnt1, PKTSIZE);
XX		i = pkt[4] | 0x80;
XX		i &= 0xff;
XX	        checkchk = 0xaaaa - (checkchk ^ i);
XX       		checkchk &= 0xffff;
XX
XX	        if(checkchk != check) {
XX	                if (debug)
XX				printmsg("***checksum error***");
XX
XX	                return(ERROR);
XX	        }
XX
XX	        *len = PKTSIZE;
XX
XX	        if (c2 & 0x40)  {
XX	                ii = (cnt1[0] & 0xff);
XX	                *len = (*len - ii) & 0xff;
XX	                for (ii = 0; ii < *len; ii++)
XX				cnt1[ii] = cnt1[ii+1];
XX	        }
XX
XX	        cnt1[*len] = '\0';
XX	}
XX
XX	if (debug > 0) {
XX	        printmsg("receive packet type %d ", nt1);
XX	        printmsg("  num = %d n = %d", *nt3, *nt4);
XX	        printmsg("  checksum rec = %x comp = %x", check, checkchk);
XX	        printmsg("  len = %d data =\n|%s|", *len, cnt1);
XX	}
XX
XX	ii = nt1;
XX
XX	return(ii);
XX}
XX
XX
XXunsigned checksum(data, len)
XXchar	*data;
XXint	len;
XX{
XX	unsigned int i,j,tmp,chk1,chk2;
XX
XX	chk1 = 0xffff;
XX	chk2 = 0;
XX	j = len;
XX
XX	for (i = 0; i < len; i++)  {
XX	        if (chk1 & 0x8000)  {
XX			chk1 <<= 1;
XX			chk1++;
XX		}
XX	        else  {
XX			chk1 <<= 1;
XX		}
XX
XX	        tmp = chk1;
XX	        chk1 += (data[i] & 0xff);
XX	        chk2 += chk1 ^ j;
XX	        if ((chk1 & 0xffff) <= (tmp & 0xffff))
XX			chk1 ^= chk2;
XX
XX	        j--;
XX	}
XX
XX	return(chk1 & 0xffff);
XX}
@//E*O*F dcpgpkt.c//
chmod u=rw,g=r,o=r dcpgpkt.c
 
echo x - dcpio.c
sed 's/^XX//' > "dcpio.c" <<'@//E*O*F dcpio.c//'
XX/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
XX/* IO routines */
XX
XX#include <sys/sgtty.h>
XX#include <setjmp.h>
XX#include <signal.h>
XX#include "dcp.h"
XX
XXjmp_buf env;
XXvoid    clkint();
XXstruct	sgttyb ttybufa, ttybufb;
XX
XX
XXvoid clkint()
XX{
XX	longjmp(env, 1);
XX}
XX
XX
XXsetline(tty, baud)
XXint	tty, baud;
XX{
XX	gtty(tty, &ttybufa);
XX	memcpy((char *)&ttybufb, (char *)&ttybufa, sizeof(struct sgttyb));
XX	ttybufa.sg_speed = D8S1NONE;
XX	ttybufa.sg_flag = RAW & ~ECHO;
XX	ttybufa.sg_prot = baud;
XX	stty(tty, &ttybufa);
XX}
XX
XX
XXswrite(data,num)
XXint	num;
XXunsigned char	*data;
XX{
XX	write(fpw, data, num);
XX
XX	return(num);
XX}
XX
XX
XX/* non-blocking read essential to "g" protocol */
XX/* see "dcpgpkt.c" for description */
XX/* Requests for I/O should get qued and an event flag given. Then the */
XX/* requesting process (e.g.gmachine()) waits for the event */
XX/* flag to fire processing either a read or a write. */
XX
XX
XXsread(buf,num,timeout)
XXint	num, timeout;
XXunsigned char	*buf;
XX{
XX	int	i;
XX
XX	if (setjmp(env))  {
XX		if (debug)
XX			printmsg("ret i = %d\n",i);
XX
XX		return(i);
XX	}
XX
XX	signal(SIGALRM, clkint);
XX	alarm(timeout + 1);
XX
XX	for (i = 0; i < num; i++)
XX		read(fpr, &buf[i], 1);
XX
XX	alarm(0);
XX
XX	return(i);
XX}
XX
XX
XXstruct	{
XX	int	baudrate;
XX	char	*code;
XX} rates[] = {
XX    {0x06, "300"},
XX    {0x08, "1200"},
XX    {0x0A, "2400"},
XX    {0x0E, "9600"},
XX    {0x00, ""}
XX    };
XX
XXopenline(name, baud)
XXchar	*name, *baud;
XX{
XX	register int i, speed;
XX
XX	i = speed = 0;
XX	do  {
XX		if (strcmp(baud, rates[i].code) == 0)  {
XX			speed = rates[i].baudrate;
XX			break;
XX		}
XX	} while (rates[++i].baudrate != 0);
XX
XX	if (speed == 0)
XX		speed = 0x08;
XX
XX	fpr = open(name, 0);
XX	fpw = open(name, 1);
XX	setline(fpw, speed);
XX	setline(fpr, speed);
XX
XX	if (fpr < 0)
XX		return(-1);
XX
XX	if (fpw < 0)
XX		return(-1);
XX
XX	return(0);
XX}
XX
XX
XXcloseline()
XX{
XX	stty(fpr, &ttybufb);
XX	stty(fpw, &ttybufb);
XX	close(fpr);
XX	close(fpw);
XX}
@//E*O*F dcpio.c//
chmod u=rw,g=r,o=r dcpio.c
 
echo x - dcprec.c
sed 's/^XX//' > "dcprec.c" <<'@//E*O*F dcprec.c//'
XX/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
XX/* file recieve routines */
XX
XX#include "dcp.h"
XX
XXstatic unsigned char rpacket[MAXPACK];
XX
XX
XX/*
XX**
XX**schkdir
XX** scan the dir
XX*/
XX
XXschkdir()
XX{
XX	char c;
XX
XX	c = scandir();
XX	if (c == 'Q')
XX		return('Y');
XX
XX	if (c == 'S')  {
XX		strcpy(rpacket,"HN");
XX		if ((*sendpkt)(rpacket, 0, 1))
XX			return(0);
XX	}
XX
XX	return('B');
XX}
XX
XX
XX/*
XX *
XX *      endp() end protocol
XX *
XX */
XX
XXendp()
XX{
XX	strcpy(rpacket,"HY");
XX	(*sendpkt)(rpacket, 0, 2); /* dont wait for ACK */
XX	(*closepk)();
XX
XX	return('P');
XX}
XX
XX
XX/*
XX *  r d a t a
XX *
XX *  Receive Data
XX */
XX
XXrdata()
XX{
XX	int len;
XX
XX	if ((*getpkt)(rpacket, &len))
XX		return(0);
XX
XX	if (len == 0)  {
XX	        close(fp);
XX	        strcpy(rpacket,"CY");
XX		if ((*sendpkt)(rpacket, 0, 1))
XX			return(0);
XX
XX		if (debug)
XX			printmsg("transfer complete");
XX
XX		return('F');
XX	}
XX
XX	write(fp, rpacket, len);	/* Write the data to the file */
XX
XX	return('D');			/* Remain in data state */
XX}
XX
XX
XX/*
XX *  r f i l e
XX *
XX *  Receive File Header
XX */
XX
XXrfile()
XX{
XX	int	len, i;
XX	char	filenam1[132];	/*Holds the converted file name */
XX
XX	if ((*getpkt)(rpacket, &len))
XX		return(0);
XX
XX	if ((rpacket[0] & 0x7f) == 'H')
XX		return('C');
XX
XX	sscanf(&rpacket[2], "%s %s ", fromfile, tofile);
XX
XX	if ((fp = creat(tofile, PERMS)) == -1)  {	/* Try to open a new file */
XX		if (debug)
XX			printmsg("cannot create %s",tofile); /* Give up if can't */
XX
XX		return('A');
XX	}
XX
XX	if (debug)
XX		printmsg("Receiving %s as %s", fromfile, tofile);
XX
XX	strcpy(rpacket, "SY");
XX
XX	if ((*sendpkt)(rpacket, 0, 1))
XX		return(0);
XX
XX	return('D');		/* Switch to data state */
XX}
XX
XX
XX/*
XX *  r i n i t
XX *
XX *  Receive Initialization
XX */
XX
XXrinit()
XX{
XX	if ((*openpk)())
XX		return(0);
XX
XX	return('F');
XX}
@//E*O*F dcprec.c//
chmod u=rw,g=r,o=r dcprec.c
 
echo x - dcpscan.c
sed 's/^XX//' > "dcpscan.c" <<'@//E*O*F dcpscan.c//'
XX/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
XX/* Directory scanner */
XX
XX#include <sys/dir.h>
XX#include <string.h>
XX#include "dcp.h"
XX
XX/*
XX**
XX**scandir
XX**
XX*/
XX
XXscandir()
XX{
XX	int	fn;
XX	DIR	*dir;
XX	char	cname[3];
XX	struct	direct  *pdir;
XX
XX	strcpy(cname, "C.");
XX
XX	if ((dir = opendir(SPOOLDIR)) == (DIR *)NULL)
XX		return('A');
XX
XX	while ((pdir = readdir(dir)) != (struct direct *)NULL)  {
XX		if (debug > 4)
XX			printmsg("dir file = %s cfile = %s",pdir->d_name, cname);
XX
XX		if (strncmp(pdir->d_name, cname, 2) == 0)  {
XX			strncpy(cfile, pdir->d_name, pdir->d_namlen);
XX	                closedir(dir);
XX
XX			if (fw == -1)
XX				if ((fw = open(cfile, 0)) == -1)
XX					return('Y');
XX
XX			return('S');
XX		}
XX	}
XX
XX	closedir(dir);
XX
XX	return('Q');
XX}
@//E*O*F dcpscan.c//
chmod u=rw,g=r,o=r dcpscan.c
 
echo x - dcpsend.c
sed 's/^XX//' > "dcpsend.c" <<'@//E*O*F dcpsend.c//'
XX/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
XX/* file send routines */
XX
XX#include "dcp.h"
XX
XXstatic unsigned char spacket[MAXPACK];
XX
XX
XX/*
XX *  s d a t a
XX *
XX *  Send File Data
XX */
XX
XXsdata()
XX{
XX	if ((*sendpkt)(spacket, size, 0))
XX		return(0);			/* send data */
XX
XX	if ((size = bufill(spacket)) == -1)	/* Get data from file */
XX		return('Z');			/* If EOF set state to that */
XX
XX	return('D');				/* Got data, stay in state D */
XX}
XX
XX
XX/*
XX *  b u f i l l
XX *
XX *  Get a bufferful of data from the file that's being sent.
XX *  Only control-quoting is done; 8-bit & repeat count prefixes are
XX *  not handled.
XX */
XX
XXint bufill(buffer)
XXunsigned char	buffer[];
XX{
XX	int	i = 0;
XX	char	t;
XX
XX        while (read(fp, &t, 1) == 1)  {
XX		buffer[i++] = t;	/* Deposit the character itself */
XX
XX		if (i >= pktsize)
XX			return(i);
XX	}
XX
XX	if (i == 0)
XX		return(-1);
XX
XX	return(i);			/* Handle partial buffer */
XX}
XX
XX
XX/*
XX *  s b r e a k
XX *
XX *  Send Break (EOT)
XX */
XX
XXint sbreak()
XX{
XX	int	len;
XX
XX	strcpy(spacket,"H");
XX
XX	if ((*sendpkt)(spacket, 0, 1))
XX		return(0);
XX
XX	if ((*getpkt)(spacket, &len))
XX		return(0);
XX
XX	if (debug)
XX		printmsg("Switch modes");
XX
XX	if (spacket[1] == 'N')
XX		return('G');
XX
XX        return('Y');
XX}
XX
XX
XX/*
XX *  s e o f
XX *
XX *  Send End-Of-File.
XX */
XX
XXint seof()
XX{
XX	int	len;
XX
XX	if ((*sendpkt)(spacket, 0, 0))
XX		return(0);
XX
XX	if ((*getpkt)(spacket, &len))
XX		return(0);		/* rec CY or CN */
XX
XX	if (strncmp(spacket, "CY", 2))
XX		return(0);		/* cant send file */
XX
XX	close(fp);
XX	fp = (-1);
XX	unlink(fromfile);
XX
XX	if (debug)
XX		printmsg("transfer %s complete,%d",fromfile,fp);
XX
XX	return('F');			/* go get the next file to send */
XX}
XX
XX
XX/*
XX *  s f i l e
XX *
XX *  Send File Header.
XX */
XX
XXint sfile()
XX{
XX	int	len;
XX
XX	if (fp == -1)  {		/* If not already open, */
XX		if (debug > 1)
XX			printmsg("looking for next file...");
XX
XX		if (getfile())  {	/* get next file from current work*/
XX			close(fw);
XX			unlink(cfile);	/* close and delete completed workfile */
XX			fw = -1;
XX			return('B');	/* end sending session */
XX		}
XX
XX		if (debug > 1)
XX			printmsg("  New file is %s", fromfile);
XX
XX		if (debug)
XX			printmsg("   Opening %s for sending.", fromfile);
XX
XX		fp = open(fromfile, 0);	/* open the file to be sent */
XX		if (fp == -1)  {	/* If bad file pointer, give up */
XX			if (debug)
XX				printmsg("Cannot open file %s", fromfile);
XX			return('A');
XX		}
XX	} else
XX		return('A'); /* If somethings already open. were in trouble*/
XX
XX	if (debug > 1)
XX		printmsg("Sending %s as %s",fromfile,tofile);
XX
XX	strcpy(spacket,tofile);
XX
XX	if ((*sendpkt)(spacket,0,1))
XX		return(0);		/* send S fromfile tofile */
XX
XX	if ((*getpkt)(spacket,&len))
XX		return(0);		/* user - tofile 0666. */
XX
XX	if (spacket[1] != 'Y')
XX		return('A');		/* If otherside says no-quit*/
XX
XX	size = bufill(spacket);
XX
XX	return('D');
XX}
XX
XX
XX/*
XX *  s i n i t
XX *
XX *  Send Initiate: send this host's parameters and get other side's back.
XX */
XX
XXint sinit()
XX{
XX	if ((*openpk)())
XX		return('A');
XX
XX	return('B');
XX}
XX
XX
XX/*
XX *  getfile
XX *
XX *  getfile reads the next line from the presently open workfile
XX *  (cfile) and determines from this the next file to be sent
XX *  (file). If there are no more TRUE is returned.
XX *  --A fix for "R from to 0666" should be done here to recieve files
XX *  --in addition to sending them. The appropriate "state letter"
XX *  --i.e. "R" should be returned to the send "master" or "slave"
XX *  --state switching table in "dcp.c"
XX *  --I did not implement this since the majority of uucp transactions
XX *  --appear to be "S from to 0666" type. RHLamb 1/87
XX *
XX */
XX
XXint getfile()
XX{
XX	int	i;
XX	char	line[132];
XX
XX	if (getline(fw, line))
XX		return(TRUE);
XX
XX	sscanf(&line[2], "%s ", fromfile);
XX
XX	for (i = 0; line[i]; i++)
XX		if (strncmp(&line[i], "0666", 4) == 0)
XX			break;
XX
XX	line[i+4] = '\0';
XX	strcpy(tofile,line);
XX
XX	return(FALSE);
XX}
@//E*O*F dcpsend.c//
chmod u=rw,g=r,o=r dcpsend.c
 
echo x - dcpstart.c
sed 's/^XX//' > "dcpstart.c" <<'@//E*O*F dcpstart.c//'
XX/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
XX/* Dialer,Proto negotiator,identify routines */
XX
XX#include <string.h>
XX#include "dcp.h"
XX
XX#define	PROTOS		"g"
XX#define	MAXLOGTRY	3
XX
XXProto Protolst[] = {  'g',ggetpkt,gsendpkt,gopenpk,gclosepk,'\0'};
XX
XXprocref         getpkt,sendpkt,openpk,closepk;
XX
XX/*
XX**
XX**
XX**startup
XX**
XX**
XX*/
XX
XXstartup()
XX{
XX	char msg[80],tmp1[20],tmp2[20];
XX
XX	if (!remote)  {
XX		msgtime = 2*MSGTIME;
XX
XX		if (rmsg(msg,2)== -1)
XX			return('Y');
XX
XX		if (debug > 1)
XX			printmsg("1st msg = %s",msg);
XX
XX		/* if (strncmp(&msg[6],rmtname,6))
XX			return('Y'); */
XX
XX		sprintf(msg, "S%.6s", myname);
XX
XX		wmsg(msg,2);
XX
XX		if (rmsg(msg,2)== -1)
XX			return('Y');
XX
XX		if (debug > 1)
XX			printmsg("2nd msg = %s",msg);
XX
XX		if (strncmp(&msg[1],"OK",2))
XX			return('Y');
XX
XX		if (rmsg(msg,2)== -1)
XX			return('Y');
XX
XX		if (debug > 1)
XX			printmsg("3rd msg = %s",msg);
XX
XX		if (msg[0] != 'P' || strchr(&msg[1],proto[0]) == 0)  {
XX			wmsg("UN",2);
XX			return('Y');
XX		}
XX
XX		sprintf(msg,"U%c",proto[0]);
XX		wmsg(msg,2);
XX
XX		setproto(proto[0]);
XX		return('D');
XX	}
XX	else  {
XX		msgtime = 2*MSGTIME;
XX		sprintf(msg,"Shere=%s",myname);
XX		wmsg(msg,2);
XX
XX		if (rmsg(msg,2)== -1)
XX			return('Y');
XX
XX		sscanf(&msg[1],"%s %s %s",rmtname,tmp1,tmp2);
XX		sscanf(tmp2,"-x%d",&debug);
XX
XX		if (debug > 0)
XX			printmsg("debug level = %d",debug);
XX
XX		if (debug > 1)
XX			printmsg("1st msg from remote = %s",msg);
XX
XX		/* if (checkname(rmtname))
XX			return('Y'); */
XX
XX		wmsg("ROK",2);
XX		sprintf(msg,"P%s",PROTOS);
XX		wmsg(msg,2);
XX
XX		if (rmsg(msg,2)== -1)
XX			return('Y');
XX
XX		if (msg[0] != 'U' || strchr(PROTOS,msg[1]) == 0)
XX			return('Y');
XX
XX		proto[0] = msg[1];
XX		setproto(proto[0]);
XX		return('R');
XX	}
XX}
XX
XX
XXsetproto(pr)
XXchar pr;
XX{
XX	Proto *tproto;
XX
XX	for (tproto=Protolst;tproto->type != '\0' && pr != tproto->type; tproto++)  {
XX		if (debug>2)
XX			printmsg("setproto: %c %c",pr,tproto->type);
XX	}
XX
XX	if (tproto->type =='\0')  {
XX		printmsg("setproto: You said I had it but I cant find it");
XX               exit(1);
XX	}
XX
XX	getpkt = tproto->a; sendpkt = tproto->b;
XX	openpk =tproto->c;  closepk =tproto->d;
XX}
XX
XX
XX
XX/*
XX**
XX**callup
XX** script processor - nothing fancy! 
XX*/
XX
XXcallup()
XX{
XX	int flg,kk,jj,ll,firstflg;
XX	char buf2[132],*prsend;
XX
XX	if (openline(device, speed))
XX		return('G');
XX
XX	jj = kk = 0;
XX
XX	while(loginseq[jj] != '\0')  {
XX	        if (loginseq[jj] == '\\' && loginseq[jj+1] == 'n')  {
XX	                buf2[kk++] = '\n';
XX	                jj += 2;
XX	                continue;
XX	        }
XX
XX	        buf2[kk++] = loginseq[jj++];
XX	}
XX	buf2[kk] = '\0';
XX
XX	flg = -1;       /* start by sending */
XX	firstflg = -1;
XX	jj=0;
XX	msgtime = 2*MSGTIME;
XX
XX	while (buf2[jj])  {
XX	        kk=jj;
XX	        while (buf2[kk] != '-' && buf2[kk] != '\0')
XX	                kk++;
XX
XX	        if (buf2[kk]=='\0')
XX			buf2[kk+1]='\0';
XX
XX	        buf2[kk] = '\0';
XX	        if (flg)  {
XX	                prsend = &buf2[jj];
XX	                if (firstflg)
XX		                slowrite(&buf2[jj]);
XX	                else
XX		                wmsg(&buf2[jj],0);
XX
XX	                flg = 0;
XX	                firstflg = 0; /* change this to 0 for normal use */
XX	        } else  {
XX	                ll = 1;
XX	                while (getstring(&buf2[jj]))  {
XX				if (ll++ >= MAXLOGTRY )
XX				      return('Y');
XX
XX				wmsg(prsend,0);
XX	
XX				/* try resending before giving up */
XX	                }
XX
XX	                flg = -1;
XX	        }
XX
XX	        jj = kk + 1;
XX	}
XX
XX	return('P');
XX}
XX
XX
XX/*
XX**
XX**      slowrite
XX** comunication slow write. needed for auto-baud modems
XX*/
XX
XXslowrite(st)
XXregister char *st;
XX{
XX	int	j, len;
XX	char	c;
XX
XX	len = strlen(st);
XX	if (debug > 2)
XX		printmsg("sent %s", st);
XX
XX	for (j = 0; j < len; j++)  {
XX	        swrite(&st[j],1);
XX/* [SRS]	ddelay(80000); */
XX        }
XX}
@//E*O*F dcpstart.c//
chmod u=rw,g=r,o=r dcpstart.c
 
echo x - dcpsys.c
sed 's/^XX//' > "dcpsys.c" <<'@//E*O*F dcpsys.c//'
XX/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
XX/* Get the next system, and other support routines  */
XX
XX#include "dcp.h"
XX
XX/*
XX *	getsystem
XX *	Process the SYSTEMS file entry
XX */
XX
XXgetsystem()
XX{
XX	char line[132];
XX
XX	if (getline(fsys, line))
XX		return('A');
XX
XX	sscanf(line,"%s %s %s %s %s %s %s",rmtname,cctime,device,type,speed,proto,loginseq);
XX
XX	if (debug > 2)  {
XX		printmsg("rmt= %s ctm= %s dev= %s",rmtname,cctime,device);
XX		printmsg("typ= %s spd= %s pro= %s",type,speed,proto);
XX		printmsg("logseq= %s",loginseq);
XX	}
XX
XX	if (strcmp(cctime, "Slave") == 0)
XX		return('G');        /*skip this system*/
XX
XX	if (checktime(cctime))
XX		return('G');/* wrong time */
XX
XX	return('S');    /*startup this system*/
XX}
XX
XX
XX/*
XX**
XX**checkname
XX** Do we know the guy ?
XX*/
XX
XXcheckname(name)
XXchar name[];
XX{
XX	int ffd;
XX	char line[132],tmp[16];
XX
XX	if ((ffd = open(SYSTEMS, 0)) == -1)
XX		return(-1);
XX
XX	while (getline(ffd, line) == FALSE)  {
XX	        sscanf(line,"%s ",tmp);
XX	        if (debug > 3)
XX			printmsg("rmt= %s sys= %s",name,tmp);
XX
XX	        if (strncmp(name,tmp,6) == 0)  {
XX	                close(ffd);
XX	                return(0); /*OK I like you */
XX		}
XX	}
XX
XX	close(ffd);
XX	return(-1); /* Who are you ? */
XX}
XX
XX
XX/*
XX**
XX**checktime
XX** check if we may make a call at this time 
XX*/
XX
XXchecktime(xtime)
XXchar *xtime;
XX{
XX	return(0); /* OK go to it */
XX}
XX
XX
XX/*
XX *
XX *	sysend
XX *
XX *	end UUCP session negotiation
XX */
XX
XXsysend()
XX{
XX	char msg[80];
XX
XX	msg[1] = '\0';
XX	msgtime = 2*MSGTIME;
XX
XX	while (msg[1] != 'O')  {
XX		wmsg("OOOOOO",2);
XX
XX		if (rmsg(msg, 2) == -1)
XX			break;
XX	}
XX
XX        wmsg("OOOOOO",2);
XX
XX	if (!remote)
XX		return('I');
XX
XX	return('A');
XX}
XX
XX
XX/*
XX**
XX**      delay
XX**
XX*/
XX
XXddelay(dtime)
XXint dtime;
XX{
XX	int i;
XX
XX	for (i = 0; i < dtime; i++);
XX}
XX
XX
XX/*
XX**
XX**      getstring
XX** Look for a string - useful for send-expect operation
XX*/
XX
XXgetstring(st)
XXchar *st;
XX{
XX	int len,j;
XX	char c[40];
XX
XX	len = strlen(st);
XX	c[len--] = '\0';
XX
XX	if (debug > 2)
XX		printmsg("wanted %s", st);
XX
XX	while (strcmp(st, c) != 0)  {
XX	        for (j = 0; j < len; j++)
XX			c[j] = c[j+1];
XX
XX		if (sread(&c[len], 1, msgtime) == 0)
XX			return(-1);
XX
XX	        c[len] &= 0x7f;
XX        }
XX
XX	if (debug >2)
XX		printmsg("got that ","");
XX
XX	return 0;
XX}
XX
XX
XX/*
XX**
XX**wmsg
XX** write a ^P type msg to the remote uucp
XX*/
XX
XXwmsg(msg,syn)
XXint syn;
XXunsigned char msg[];
XX{
XX	if (syn == 2)
XX		swrite("\020",1);
XX
XX	swrite(msg,strlen(msg));
XX
XX	if (syn == 2)
XX		swrite("\0", 1);
XX}
XX
XX
XX/*
XX**
XX**rmsg
XX** read a ^P msg from UUCP
XX*/
XX
XXrmsg(msg,syn)
XXint syn;
XXunsigned char msg[];
XX{
XX	int ii;
XX	char c,cc[5];
XX
XX	c = 'a';
XX	if (syn == 2)  {
XX		while ((c & 0x7f) != '\020')  {
XX			if (sread(cc, 1, msgtime) == 0)
XX				return(-1); 
XX			c = cc[0];	/* Dont ask. MSC needs more than a byte to breathe */
XX
XX		}
XX	}
XX
XX	for (ii = 0; ii < 132 && c ; ii++)  {
XX		if (sread(cc, 1, msgtime) == 0)
XX			return(-1);
XX
XX		c = cc[0] & 0x7f;
XX		if (c == '\n')
XX			c = '\0';
XX
XX		msg[ii] = c;
XX	}
XX
XX	return(strlen(msg));
XX}
XX
XX
XX/*
XX**
XX**      getline
XX** get a \n terminated string from whatever
XX*/
XX
XXgetline(lfp, line)
XXint	lfp;
XXchar	*line;
XX{
XX	char c;
XX
XX	while (read(lfp, &c, 1) > 0)  {
XX		if (c == '\n')  {
XX			*line++ = '\0';
XX			return(FALSE);
XX		}
XX		else
XX			*line++ = c;
XX
XX	}
XX
XX	return(TRUE);
XX}
XX
XX
XX/*
XX *  p r i n t m s g
XX *
XX *  Print error message on standard output if not remote.
XX */
XX
XX/*VARARGS1*/
XX
XXprintmsg(fmt, a1, a2, a3, a4, a5)
XXchar * fmt;
XX{
XX        int len;
XX	char msg[256];
XX
XX        sprintf(msg,fmt, a1, a2, a3, a4, a5);
XX
XX	msg[256] = '\0';
XX	len = strlen(msg);
XX
XX	msg[len++] = '\n';
XX	msg[len]   = '\0';
XX
XX	if (!remote)
XX		printf("%s", msg);
XX
XX	write(flog, msg, len);
XX}
@//E*O*F dcpsys.c//
chmod u=rw,g=r,o=r dcpsys.c
 
echo x - rmail.c
sed 's/^XX//' > "rmail.c" <<'@//E*O*F rmail.c//'
XX/*
XX *      rmail.c
XX *
XX *      Mini Remote Mail Handler
XX *
XX *	This program is executed by either 'mail' or 'uuxqt'.
XX *
XX *	The standard UniFLEX mail doesn't handle remote addresses
XX *	so I made a new program called mail and renamed the old
XX *	mail to lmail.  Now if the new mail finds a remote address
XX *	it calls rmail, else lmail.
XX *
XX *	Based on a program by Richard H. Lamb.
XX *
XX *	Usage:
XX *        rmail remotesystem!remoteuser user myname
XX *        rmail remotesystem!remoteuser --- takes default "user, myname"
XX *	  rmail localuser
XX *
XX *      UniFLEX Build:
XX *        cc +O rmail.c                   Compile and Optimize
XX *	  strip rmail			  Strip off symbol table
XX *        mv rmail /usr/bin               Move to directory
XX *        perms o-rwx /usr/bin/rmail      Run by uuxqt and mail only
XX *        owner uucp /usr/bin/rmail       Set ownership to uucp
XX */
XX
XX#info 68020 UniFLEX (R) RMAIL, Version 2.0, August 1987
XX#info Public Domain (P) S. R. Sampson, No rights reserved
XX#tstmp
XX
XX#include "uucp.h"
XX
XX#include <sys/modes.h>
XX#include <sys/fcntl.h>
XX#include <sys/dir.h>
XX#include <stdio.h>
XX#include <time.h>
XX#include <string.h>
XX#include <pwd.h>
XX
XX#define PERMS           (S_IREAD | S_IWRITE | S_IEXEC)	/* rwx------	     */
XX
XXextern	char		*tzname[2];	/* contains two strings CDT or CST   */
XXextern	int		daylight;	/* array reference for above	     */
XX
XXstruct	passwd	*names;
XXlong		temptime;
XXint		fbfile, fcfile, fdfile, remote;
XXchar		bfile[32], cfile[32], dfile[32], xfile[32];
XXchar		rmtname[16], rmtuser[128], myname[16], user[16];
XXchar		datetime[32], ofrom[256], from[256], tmp[256], sys[32];
XXchar		*p, *ptr;
XX
XXstatic void	SendMail();
XXstatic int	GetLine(), CheckLegalName();
XX
XX
XXvoid main(argc, argv)
XXint     argc;
XXchar    *argv[];
XX{
XX	if (argc == 1)  {
XX		printf("Usage: rmail user, rmail remote!user\n");
XX		exit(0);
XX	}
XX
XX	if (argc > 2)			/* useful for debuging		     */
XX                strcpy(user, argv[2]);
XX	else
XX		strcpy(user, USERNAME);
XX
XX        if (argc > 3)
XX                strcpy(myname, argv[3]);
XX	else
XX		strcpy(myname, MYNAME);
XX
XX	/*
XX	 *	If address has a '!' character flag address as remote
XX	 *	else local.
XX	 */
XX
XX        if ((ptr = strchr(argv[1], '!')) == 0)
XX                remote = FALSE;
XX        else  {
XX                *ptr = '\0';
XX                remote = TRUE;
XX        }
XX
XX	/*
XX	 *	Change to user uucp if called by mail.  Else we were
XX	 *	called by uuxqt which is allready uucp.
XX	 */
XX
XX	names = getpwnam(USERNAME);
XX	
XX	if (geteuid() != names->pw_uid)
XX		setuid(names->pw_uid);
XX
XX	endpwent();
XX
XX	/*
XX	 *	Change to working directory
XX	 *
XX	 */
XX
XX        chdir(SPOOLDIR);
XX
XX	/*
XX	 *	Calculate the time
XX	 *
XX	 */
XX
XX        time(&temptime);
XX        strcpy(datetime, ctime(&temptime));
XX        datetime[strlen(datetime) - 1] = '\0';
XX	strcat(datetime, " ");
XX	strcat(datetime, tzname[daylight]);	/* add in CDT or CST	     */
XX
XX	/*
XX	 *	See if this mail was generated locally
XX	 *	or came from somewhere else.  Local mail
XX	 *	has a "From x y" header, remote has a 
XX	 *	"From x y remote from z" header.
XX	 */
XX
XX	strcpy(from, "");
XX	strcpy(ofrom, "");
XX
XX	GetLine(0, tmp);		/* get a line from stdin	     */
XX
XX	/*
XX	 *  First line should be a From line
XX	 *  Our goal is to change from this:
XX	 *
XX	 *  From a!b (date) remote from c
XX	 *
XX	 *  To this:
XX	 *
XX	 *	From c!a!b (date) remote from d
XX	 *
XX	 *  Alternatively we may get a line from mail:
XX	 *
XX	 *	From a (date)
XX	 *
XX	 *  Now we must add on the machine name:
XX	 *
XX	 *	From a (date) remote from b
XX	 */
XX
XX	/*
XX	 *	No from line causes a big error
XX	 */
XX
XX	if (strncmp(tmp, "From ", 5) != 0 &&
XX	    strncmp(tmp, ">From ", 6) != 0)  {
XX
XX		strcpy(dfile, "/tmp/rmXXXXXX");
XX                mktemp(dfile);
XX		fdfile = creat(dfile, PERMS);
XX
XX		write(fdfile, tmp, strlen(tmp));	/* old line */
XX
XX		for (;;)  {
XX	                if (GetLine(0, tmp) == FALSE)	/* stdin     */
XX	                        break;                  /* EOF	     */
XX
XX			write(fdfile, tmp, strlen(tmp));
XX	        }
XX
XX		close(fdfile);
XX
XX		/*
XX		 *	Send a letter to manager about this
XX		 */
XX
XX		SendMail("No From Line\n\n", TRUE);
XX		exit(0);
XX	}
XX
XX	/*
XX	 *  Get the garbage "From" into sys
XX	 *  and the remote address into ofrom
XX	 */
XX
XX	sscanf(tmp, "%s %s ", sys, ofrom);
XX
XX	p = tmp;	/* were gonna mess with a pointer    */
XX
XX	/*
XX	 *  Parse line to seek out "remote from"
XX	 */
XX
XX	for (;;)  {
XX		p = strchr(p + 1, 'r');
XX		if (p == NULL)  {
XX
XX			/*
XX			 * You get here after parsing to
XX			 * the end of the string and didn't
XX			 * find "remote from" text.
XX			 *
XX			 * The only other option is the
XX			 * basic "From" from mail.
XX			 */
XX
XX			break;
XX		}
XX
XX		if (strncmp(p, "remote from ", 12) == 0)
XX			break;
XX	}
XX
XX	if (p == NULL)
XX		strcat(from, ofrom);
XX	else  {
XX		sscanf(p, "remote from %s", from);
XX		strcat(from, "!");
XX		strcat(from, ofrom);
XX	}
XX
XX        if (remote)  {
XX
XX		/* spool a remote file */
XX
XX                strcpy(rmtname, argv[1]);
XX                strcpy(rmtuser, ptr + 1);
XX
XX                sprintf(dfile, "D.%.6sXXXXXX", myname);
XX                mktemp(dfile);
XX                fdfile = creat(dfile, PERMS);
XX
XX		sprintf(tmp, "From %s %s remote from %s\n",
XX		  from, datetime, myname);
XX
XX		write(fdfile, tmp, strlen(tmp));	/* put out new from  */
XX
XX	        sprintf(tmp, "Received: by %s on %s\n", myname, datetime);
XX		write(fdfile, tmp, strlen(tmp));
XX
XX        } else  { /* !remote */
XX        
XX                /* set up a local file */
XX
XX                strcpy(dfile, "/tmp/rmXXXXXX");
XX                mktemp(dfile);
XX		fdfile = creat(dfile, PERMS);
XX
XX		write(fdfile, ">", 1);
XX		write(fdfile, tmp, strlen(tmp));
XX	}
XX
XX	/*
XX	 *	uuxqt and mail will call with:
XX	 *	"rmail [remote!]user <D.xxx >/dev/null"
XX	 *
XX	 *	Copy the stdin to the spool or /tmp file
XX	 */
XX
XX	for (;;)  {
XX                if (GetLine(0, tmp) == FALSE)		/* stdin	     */
XX                        break;                          /* EOF		     */
XX
XX		write(fdfile, tmp, strlen(tmp));
XX        }
XX
XX	close(fdfile);
XX
XX        /*
XX	 *	Now forward the mail, if user does not exist
XX	 *	or the remote machine is not known
XX	 *	then send mail to system manager and sender
XX	 *
XX	 *	The senders name is now in the global from[] string
XX	 */
XX
XX	if (remote)  {
XX		if (CheckLegalName(rmtname) == FALSE)  {
XX			SendMail("Unknown Machine\n\n", FALSE);
XX			exit(0);
XX		}
XX
XX                /* make the spool files for uucico */
XX
XX                sprintf(bfile, "B.%.6sXXXXXX", rmtname);
XX                mktemp(bfile);
XX                fbfile = creat(bfile, PERMS);
XX
XX                sprintf(tmp, "U %s %s\nF %s\nI %s\nC rmail %s\n",
XX                  user, myname, dfile, dfile, rmtuser);
XX                write(fbfile, tmp, strlen(tmp));
XX
XX                close(fbfile);
XX
XX                sprintf(xfile, "X.%.6sXXXXXX", rmtname);
XX                mktemp(xfile);
XX
XX                sprintf(cfile, "C.%.6sXXXXXX", myname);
XX                mktemp(cfile);
XX                fcfile = creat(cfile, PERMS);
XX
XX                sprintf(tmp, "S %s %s %s - %s 0666\nS %s %s %s - %s 0666\n",
XX                  dfile, dfile, user, dfile, bfile, xfile, user, bfile);
XX                write(fcfile, tmp, strlen(tmp));
XX
XX                close(fcfile);
XX
XX	} else  {
XX
XX		names = getpwnam(argv[1]);
XX		endpwent();
XX
XX		if (names == (struct passwd *)NULL)  {
XX			SendMail("Unknown User\n\n", FALSE);
XX			exit(0);
XX		}
XX		else  {
XX		        sprintf(tmp,"mail %s <%s", argv[1], dfile);
XX			if (system(tmp) == 0)
XX				unlink(dfile);
XX			else
XX				perror("rmail to local user failed");
XX		}
XX        }
XX}
XX
XX
XX/*
XX *	Send mail to system manager upon errors
XX */
XX
XXstatic void SendMail(str, mgronly)
XXchar	*str;
XXint	mgronly;
XX{
XX	strcpy(cfile,"/tmp/rmtXXXXXX");
XX	mktemp(cfile);
XX
XX	fcfile = creat(cfile, PERMS);
XX	fdfile = open(dfile, O_RDONLY);
XX
XX	strcpy(tmp, "Subject: ");
XX	strcat(tmp, str);
XX
XX	write(fcfile, tmp, strlen(tmp));
XX
XX	while (GetLine(fdfile, tmp) != FALSE)  {
XX		write(fcfile, "> ", 2);
XX		write(fcfile, tmp, strlen(tmp));
XX	}
XX
XX	close(fcfile);
XX	close(fdfile);
XX
XX	unlink(dfile);
XX
XX	/*
XX	 *	Return mail to system manager
XX	 *	and sender if mgronly == FALSE
XX	 */
XX
XX	if (!mgronly)  {
XX		sprintf(tmp, "mail %s <%s", from, cfile);
XX		system(tmp);
XX	}
XX
XX	sprintf(tmp, "mail %s <%s", ERRORNAME, cfile);
XX	if (system(tmp) == 0)
XX		unlink(cfile);
XX}
XX
XX
XX/*
XX *	Check the machine name by reading the SYSTEMS file
XX *
XX *	returns FALSE if not found, else TRUE
XX *
XX */
XX
XXstatic int CheckLegalName(name)
XXregister char	*name;
XX{
XX	register FILE	*fd;
XX	char		line[256], tmp[16];
XX
XX	if ((fd = fopen(SYSTEMS, "r")) == NULL)
XX		return(FALSE);
XX
XX	while (fgets(line, sizeof line, fd) != NULL)  {
XX	        sscanf(line, "%s ", tmp);
XX
XX	        if (strncmp(name, tmp, 6) == 0)  {
XX			fclose(fd);
XX			return(TRUE);
XX		}
XX	}
XX
XX	fclose(fd);
XX
XX	return(FALSE);
XX}
XX
XX
XX/*
XX *      get a '\n' terminated line from "fd" to "line"
XX *      keep the newline '\n'
XX *
XX */
XX
XXstatic int GetLine(fd, line)
XXint	fd;
XXchar    *line;
XX{
XX        char    c;
XX
XX	for (;;)  {
XX                if (read(fd, &c, 1) < 1)
XX                        return(FALSE);          /* End Of File or Error */
XX
XX                *line++ = c;
XX
XX                if (c == '\n')  {
XX                        *line = c = '\0';
XX		        return(TRUE);		/* there is a line */
XX		}
XX        }
XX}
XX
XX/* EOF */
@//E*O*F rmail.c//
chmod u=rw,g=r,o=r rmail.c
 
echo x - uuxqt.c
sed 's/^XX//' > "uuxqt.c" <<'@//E*O*F uuxqt.c//'
XX/*
XX *	uuxqt.c
XX *
XX *	Unix to Unix Execute
XX *
XX *	This program searches for work files in the spool
XX *	directory and executes them.  Work files have a X. prefix.
XX *
XX *	It is executed by 'uucico', 'cron', or 'at'
XX *
XX *	Based on a program by Richard H. Lamb.
XX *
XX *	UniFLEX Build:
XX *	  cc +O uuxqt.c
XX *	  strip uuxqt
XX *	  mv uuxqt /etc
XX *	  perms o-rwx /etc/uuxqt
XX *	  owner uucp /etc/uuxqt
XX */
XX
XX#info 68020 UniFLEX (R) UUXQT, Version 2.0, August 1987
XX#info Public Domain (P) S. R. Sampson, No rights reserved
XX#tstmp
XX
XX/* Includes */
XX
XX#include "uucp.h"
XX
XX#include <sys/modes.h>
XX#include <sys/fcntl.h>
XX#include <sys/dir.h>		/* defines MAXNAMLEN and directory stuff */
XX#include <string.h>
XX#include <stdio.h>
XX#include <time.h>
XX#include <pwd.h>
XX
XX/* Defines */
XX
XX#define	MAXLINE		256
XX#define	ERROR		-1
XX
XX/* Globals */
XX
XXchar	command[MAXLINE], input[MAXLINE], output[MAXLINE], line[MAXLINE];
XXchar	Cfilename[MAXNAMLEN+1], filename[MAXNAMLEN+1], ltime[32];
XXchar	systemname[16], username[16];
XX
XX/* Forward Declarations */
XX
XXchar	*mfgets();
XX
XX
XXvoid main(argc, argv)
XXint	argc;
XXchar	**argv;
XX{
XX	register struct	direct  *dir;
XX	register char		*p;
XX	struct	passwd		*pw;
XX	FILE			*fdC, *log;
XX	DIR			*dd;
XX	int			inull, onull;
XX	long			tstamp;
XX
XX	/*
XX	 *	Become user uucp if called
XX	 *	by 'cron' or 'at' (user root).
XX	 *
XX	 */
XX
XX	pw = getpwnam(USERNAME);
XX
XX	if (geteuid() != pw->pw_uid)
XX		setuid(pw->pw_uid);
XX
XX	endpwent();
XX
XX	/*
XX	 *	Change to spool directory
XX	 */
XX
XX	chdir(SPOOLDIR);
XX
XX	if ((dd = opendir(SPOOLDIR)) == (DIR *)NULL)
XX		exit(1);
XX
XX	while ((dir = readdir(dd)) != (struct direct *)NULL)  {
XX	        if (strncmp(dir->d_name, "X.", 2) != 0)
XX			continue;
XX
XX		strncpy(Cfilename, dir->d_name, dir->d_namlen);
XX
XX		if ((fdC = fopen(Cfilename, "r")) == ERROR)
XX			continue;
XX
XX		input[0] = output[0] = '\0';
XX		inull = onull = FALSE;
XX
XX		while (mfgets(line, MAXLINE, fdC) != NULL)  {
XX			switch (line[0])  {
XX		        case 'C':
XX				strcpy(command, &line[2]);
XX				break;
XX			/*
XX			 *	See if all required files are present
XX			 */
XX
XX			case 'F':
XX				strcpy(filename, &line[2]);
XX				p = filename;
XX				while ((*p != ' ') && *p)
XX					p++;
XX
XX				*p = '\0';
XX				if (access(filename, 1) == ERROR)  {
XX					fclose(fdC);
XX
XX					/*
XX					 * All files not present, go check
XX					 * other work files and give up
XX					 * on this one till next time
XX					 *
XX					 */
XX
XX					goto not_ready;
XX				}
XX				break;
XX		        case 'I':
XX				strcpy(input, &line[2]);
XX				break;
XX		        case 'O':
XX				strcpy(output, &line[2]);
XX				break;
XX		        case 'U':
XX				strcpy(username, &line[2]);
XX				p = username;
XX				while (*p != ' ')
XX					p++;
XX
XX				*p++ = '\0';
XX				strcpy(systemname, p);
XX				break;
XX		        default:
XX				break;
XX			}
XX		}
XX
XX		fclose(fdC);
XX
XX		if (strlen(input) == 0)  {
XX			inull = TRUE;
XX			strcpy(input, "/dev/null");
XX		}
XX
XX		if (strlen(output) == 0)  {
XX			onull = TRUE;
XX			strcpy(output, "/dev/null");
XX		}
XX
XX		sprintf(line,"%s <%s >%s", command, input, output);
XX
XX		if ((log = fopen(XQTLOG, "a")) != ERROR)  {
XX			time(&tstamp);
XX			strcpy(ltime, ctime(&tstamp));
XX			ltime[strlen(ltime) - 1] = '\0';
XX
XX			fprintf(log, "%s %s %s %s\n",
XX				ltime, systemname, username, line);
XX
XX			fclose(log);
XX		}
XX
XX		if (system(line) != ERROR)  {
XX/*
XX		STILL DEBUGGING DCP  (Keep all files)
XX
XX			unlink(Cfilename);
XX
XX			if (!inull)
XX				unlink(input);
XX
XX			if (!onull)
XX				unlink(output);
XX*/
XX		}
XXnot_ready:;
XX
XX	}
XX
XX	closedir(dd);
XX}
XX
XX
XX/*
XX *	mfgets (modified fgets)
XX *
XX *	Same as fgets() only this version deletes '\n'
XX */
XX
XXstatic char *mfgets(s, n, iop)
XXregister char	*s;
XXregister int	n;
XXregister FILE	*iop;
XX{
XX	register int	c;
XX	register char	*cs;
XX
XX	cs = s;
XX	while (--n > 0 && (c = getc(iop)) != EOF)  {
XX		if (c == '\n')  {
XX			*cs = '\0';
XX			break;
XX		} else
XX			*cs++ = c;
XX	}
XX
XX	return((c == EOF && cs == s) ? (char *)NULL : s);
XX}
XX
XX/* EOF */
@//E*O*F uuxqt.c//
chmod u=rw,g=r,o=r uuxqt.c
 
echo Inspecting for damage in transit...
temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
    321    747   5339 dcp.c
    431   1369   9174 dcpgpkt.c
    122    261   1939 dcpio.c
    130    250   1794 dcprec.c
     45     97    774 dcpscan.c
    217    600   3912 dcpsend.c
    217    424   3866 dcpstart.c
    270    556   3765 dcpsys.c
    429   1222   9429 rmail.c
    220    531   3956 uuxqt.c
   2402   6057  43948 total
!!!
wc  dcp.c dcpgpkt.c dcpio.c dcprec.c dcpscan.c dcpsend.c dcpstart.c dcpsys.c rmail.c uuxqt.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if test -s $dtemp
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
fi
exit 0