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