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