ain@j.cc.purdue.edu (Patrick White) (03/21/88)
Program Name: uupc version 1.1 (part 1 of 3) Submitted By: Johan Widen <jw@sics.se> Summary: Implements uucp for the Amiga -- allows your Amiga to become a uupc site for mail (and news?). Poster Boy: Pat White (ain@j.cc.purdue.edu) Uncompiled. NOTES: Haven't tried to compile it. Converted the origional zoo to shars so docs, binaries & sources could be separated. I'm pretty sure this would allow one to receive news, but I remember something in the docs about it not having been tested from when I was quickly scanning them... so I'm not too sure on this. Rob has been playing with it for a while and says it works. -- Pat White (co-moderator comp.sources/binaries.amiga) UUCP: j.cc.purdue.edu!ain BITNET: PATWHITE@PURCCVM PHONE: (317) 743-8421 U.S. Mail: 320 Brown St. apt. 406, West Lafayette, IN 47906 ======================================== # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # Makefile # dcp.c # dcp.h # dcpgpkt.c # dcpsys.c # dcpxfer.c # This archive created: Sat Mar 19 01:40:46 1988 # By: Patrick White (PUCC Land, USA) echo shar: extracting Makefile '(701 characters)' cat << \SHAR_EOF > Makefile CFLAGS=-b -r all: uupc mail pccp uupc: uuhost.o dcp.o dcpsys.o dcpxfer.o dcpgpkt.o rmail.o lib.o ulib.o ndir.o \ genv.o sio.o timer.o serial.o sleep.o df0:c/blink with link.uupc.cmd mail: mailhost.o mail.o lmail.o mlib.o lib.o ndir.o genv.o raw.o sendpacket.o df0:c/blink with link.mail.cmd pccp: pccp.o genv.o cc -o pccp pccp.o genv.o dcp.o: dcp.h host.h genv.h dcpgpkt.o: dcp.h host.h genv.h dcpsys.o: dcp.h host.h genv.h ndir.h dcpxfer.o: dcp.h host.h genv.h genv.o: genv.h lib.o: host.h genv.h lmail.o: host.h genv.h mail.o: host.h genv.h mailhost.o: host.h genv.h mlib.o: host.h genv.h ndir.o: ndir.h pccp.o: host.h rmail.o: host.h genv.h ulib.o: host.h genv.h uuhost.o: host.h genv.h SHAR_EOF if test 701 -ne "`wc -c Makefile`" then echo shar: error transmitting Makefile '(should have been 701 characters)' fi echo shar: extracting dcp.c '(9330 characters)' cat << \SHAR_EOF > dcp.c /* dcp.c Revised edition of dcp Stuart Lynne May/87 Copyright (c) Richard H. Lamb 1985, 1986, 1987 Changes Copyright (c) Stuart Lynne 1987 Maintenance Notes: 25Aug87 - Added a version number - Jal 25Aug87 - Return 0 if contact made with host, or 5 otherwise. 04Sep87 - Bug causing premature sysend() fixed. - Randall Jessup. */ /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 * This program implements a uucico type file transfer and remote * execution type protocol. */ #define VERSION "1.8 Camelot" #include "dcp.h" #include <signal.h> /**/ int pktsize; /* packet size for pro */ FILE *logfile; /* system log file */ FILE *syslog; /* system log file */ FILE *fw; /* cfile pointer */ char state; /* system state*/ char cfile[80]; /* work file pointer */ int remote; /* -1 means we're remote ..7*/ int msgtime; /* timout setting */ char fromfile[132]; char hostfile[132]; /* host version of fromfile */ char tofile[132]; int fp; /* current disk file ptr */ int size; /* nbytes in buff */ FILE *fsys; char Rmtname[20]; char rmtname[20]; char * cctime; char proto[5]; /* char loginseq[256]; */ char sysline[BUFSIZ]; char s_systems[64]; char s_logfile[64]; char s_syslog[64]; char *flds[60]; int kflds; unsigned int checksum(); /**/ /* new usage dcp [-xn] -r0 slave mode dcp [-xn] -shost call host dcp [-xn] -sall call all hosts dcp [-xn] call any hosts as required by C. files */ complain( s ) char *s; { fprintf( stderr, "Please set your %s environment variable.", s ); } static void cant( file ) char *file; { fprintf( stderr, "Can't open: \"%s\"\n", file ); onBreak(); } onBreak() { extern char *orgDir; sysAbortEnd(); chdir( orgDir ); exit(100); } dcpmain( argc, argv ) int argc; char*argv[]; { FILE *ftmp; char line[132]; int Contact = FALSE; if ( name == NULL || *name == '\0' ) { complain( NAME ); onBreak(); } if ( nodename == NULL || *nodename == '\0' ) { complain( NODENAME ); onBreak(); } mkfilename( s_logfile, logdir, LOGFILE ); mkfilename( s_syslog, logdir, SYSLOG ); mkfilename( s_systems, confdir, SYSTEMS ); if ( (logfile = FOPEN( s_logfile, "a", 't' )) == NULL ) cant( s_logfile ); if ( (syslog = FOPEN( s_syslog, "a", 't' )) == NULL ) cant( s_syslog ); fp = -1; fw = (FILE *)NULL; remote = MASTER; strcpy( Rmtname, "any" ); remote = MASTER; while ( --argc ) { if ( **(++argv) == '-') { switch(argv[0][1]) { case 'x': debuglevel = atoi( &argv[0][2] ); break; case 's': sprintf( Rmtname, "%.7s", &argv[0][2] ); break; case 'r': remote = atoi( &argv[0][2] ); break; default: break; } } } signal(SIGINT, onBreak); printmsg(0, "UUPC Version %s", VERSION ); if ( remote == MASTER ) { printmsg( 0, "Calling %s %d", Rmtname, debuglevel ); if (( fsys = FOPEN( s_systems, "r", 't' )) == (char *)NULL ) onBreak(); state = 'I'; while (TRUE) { printmsg( 4, "Mstate = %c", state ); switch (state) { case 'I': state = getsystem(); break; case 'S': state = callup(); break; case 'P': state = startup(); break; case 'D': state = master(); Contact = TRUE; break; case 'Y': state = sysend(); break; case 'Z': state = sysAbortEnd(); break; case 'G': if ( strcmp( Rmtname, "any" ) == SAME ) state = 'Y'; else state = 'I'; break; } if (state == 'A') break; } fclose( fsys ); } else { if (openline( device, speed ) == -1) return(FALSE); state = 'L'; while (TRUE) { printmsg( 4, "Sstate = %c", state ); switch (state) { case 'L': state = login(); break; case 'I': state = startup(); break; case 'R': state = slave(); break; case 'Y': state = sysend(); break; } if (state == 'A') break; } closeline(); } /* fprintf( stderr, "calling dcxqt\n" ); */ if (dcxqt()) printmsg( 0, "ERROR in DCXQT" ); /* scan and process any recieved files */ fclose( syslog ); fclose( logfile ); if (Contact ) return 0; else return 5; } /**/ /* ** ** **master ** ** */ master() { state = 'I'; while (TRUE) { printmsg( 4, "Top level state (master mode) %c", state ); switch (state) { case 'I': state = sinit(); break; case 'B': state = scandir(); break; case 'R': state = mreceive(); break; case 'S': state = send(); break; case 'Q': state = sbreak(); break; case 'G': state = receive(); break; case 'C': state = 'Y'; break; case 'Y': state = endp(); break; case 'P': return('Y'); case 'A': return('A'); default: return('A'); } } } /**/ /* ** ** **slave ** ** */ slave() { state = 'I'; while (TRUE) { printmsg( 4, "Top level state (slave mode) %c", state ); switch (state) { case 'I': state = rinit(); break; case 'F': state = receive(); break; case 'C': state = schkdir(); break; case 'T': state = 'B'; break; case 'B': state = scandir(); break; case 'S': state = send(); break; case 'Q': state = sbreak(); break; case 'G': return('Y'); case 'Y': state = endp(); break; case 'P': return('Y'); case 'A': return('A'); default: return('A'); } } } /**/ /* * r e c e i v e * * This is the state table switcher for receiving files. */ receive() { state = 'F';/* Receive-Init is the start state */ while (TRUE) { printmsg( 4, " receive state: %c", state ); switch (state)/* Do until done */ { case 'F': state = rfile(); break; /* Receive-File */ case 'D': state = rdata(); break; /* Receive-Data */ case 'C': return('C');/* Complete state */ case 'd': /* send file in slave mode */ while ((state = sdata()) == 'D'); break; case 'Z': state = reof(); break; case 'A': return('Y'); /* "Abort" state */ default: return('Y'); } } } /**/ /* * s e n d * * This is the state table switcher for sending files in master mode. It * loops until either it finishes, or an error is encountered. The routines * called by send() are responsible for changing the state. * */ send() { fp = -1; /* reset file getter/opener */ state = 'F';/* Send initiate is the start state */ while (TRUE)/* Do this as long as necessary */ { printmsg( 4, "send state: %c", state ); switch (state) { case 'F': state = sfile(); break; /* Send-File */ case 'D': state = sdata(); break; /* Send-Data */ case 'Z': state = seof(); break; /* Send-End-of-File */ case 'B': return ('B'); /* Complete */ case 'R': return ('R'); /* Receive a file */ case 'A': return ('Y'); /* "Abort" */ default: return ('Y'); /* Unknown, fail */ } } } /**/ /* * m r e c e i v e * * This is the state table switcher for receiving files in master mode. It * loops until either it finishes, or an error is encountered. The routines * called by sendsw are responsible for changing the state. * */ mreceive() { fp = -1; /* reset file getter/opener */ state = 'F';/* Receive initiate is the start state */ while (TRUE)/* Do this as long as necessary */ { printmsg( 4, "send state: %c", state ); switch (state) { case 'F': state = mrfile(); break; /* Recive-File */ case 'D': if((state = rdata()) == 'F') return('S'); break; /* Receive-Data */ case 'B': return ('S'); /* Complete */ case 'A': state = mrabort(); /* "Abort" */ break; default: return ('Y'); /* Unknown, fail */ } } } /**/ /* A command formatter for DCP. RH Lamb */ /* sets up stdin and stdout on various machines */ /* There is NO command checking so watch what you send and who you */ /* let accsess your machine. "C rm /usr/*.*" could be executed. */ dcxqt() { int i; char command[60], input[60], output[60], line[BUFSIZ]; char *cp; while (dscandir()) { strcpy( line, cfile ); fw = FOPEN( line, "r", 'b' );/* imported X file */ strcpy(cfile, line); printmsg( 2, "dcxqt:%s %ld", cfile, fw ); input[0] = '\0'; output[0] = '\0'; command[0] = '\0'; while ( fgets( line, BUFSIZ, fw ) != (char *)NULL ) { cp = index( line, '\n' ); if ( cp != (char *)NULL ) *cp = '\0'; printmsg( 8, "dcxqt: %s", line ); switch (line[0]) { case 'U': break; case 'I': strcpy( input, &line[2] ); break; case 'O': strcpy( output, &line[2] ); break; case 'C': strcpy( command, &line[2] ); break; case 'R': break; default : break; } } fclose( fw ); printmsg( 0, "xqt: %s", command ); shell( command, input, output, (char *)NULL ); unlink(cfile); if (input[0]) { importpath( hostfile, input ); unlink(hostfile); } if (output[0]) { importpath( hostfile, output ); unlink(hostfile); } } return(0); } /**/ /* * p r i n t m s g * * Print error message on standard output if not remote. */ /*VARARGS1*/ printmsg(level, fmt, a1, a2, a3, a4, a5) int level; char *fmt; char *a1, *a2, *a3, *a4, *a5; { char msg[256]; if ( debuglevel > level ) { sprintf( msg, fmt, a1, a2, a3, a4, a5 ); strcat( msg, "\n" ); if ( remote == MASTER ) { fputs( msg, stdout ); fflush( stdout ); } fputs( msg, logfile ); } } SHAR_EOF if test 9330 -ne "`wc -c dcp.c`" then echo shar: error transmitting dcp.c '(should have been 9330 characters)' fi echo shar: extracting dcp.h '(2347 characters)' cat << \SHAR_EOF > dcp.h /* DCP a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */ #include <stdio.h> /* Standard UNIX definitions */ #include "host.h" /* Host specific definitions */ FILE * FOPEN(); int CREAT(); #define SYSTEMS "systems" #define LOGFILE "LOGFILE" #define SYSLOG "SYSLOG" #define MSGTIME 20 #define MAXPACK 256 #define ACK 4 /* general definitions */ #define NAK 2 #define DATA 0 #define CLOSE 1 #define ERROR 10 #define EMPTY 11 #define SLAVE 0 #define MASTER 1 #define FAILED -1 #define OK 0 /* L.sys field defines */ #define FLD_REMOTE 0 #define FLD_CCTIME 1 #define FLD_DEVICE 2 #define FLD_TYPE 3 #define FLD_SPEED 4 #define FLD_PROTO 5 #define FLD_EXPECT 6 #define FLD_SEND 7 /**/ typedef int (*procref)(); typedef struct { char type; procref a; procref b; procref c; procref d; } Proto; /* the various protocols available. Add here for others */ extern procref getpkt, sendpkt, openpk, closepk; extern int ggetpkt(), gsendpkt(), gopenpk(), gclosepk(); /* extern int kgetpkt(), ksendpkt(), kopenpk(), kclosepk(); extern int rgetpkt(), rsendpkt(), ropenpk(), rclosepk(); extern int tgetpkt(), tsendpkt(), topenpk(), tclosepk(); */ /**/ extern int pktsize; /* packet size for this pro*/ extern FILE *logfile; /* system log file */ extern FILE *syslog; /* system log file */ extern FILE *fw; /* cfile pointer */ extern char cfile[80]; /* work file pointer */ extern int remote; /* -1 means we're remote*/ extern int findwork; extern int msgtime; /* timout setting */ extern char fromfile[132]; extern char hostfile[132]; /* host version of fromfile */ extern char tofile[132]; extern char state; /* present state */ extern int fp; /* current disk file ptr */ extern int size; /* nbytes in buff */ extern FILE *fsys; extern char Rmtname[20]; extern char rmtname[20]; extern char *cctime; extern char proto[5]; extern char sysline[BUFSIZ]; extern char s_systems[64]; extern char s_logfile[64]; extern char s_syslog[64]; extern char *flds[60]; extern int kflds; extern int debuglevel; /* debugging flag */ extern unsigned int checksum(); extern char *index(); extern char *rindex(); extern char *curdir; SHAR_EOF if test 2347 -ne "`wc -c dcp.h`" then echo shar: error transmitting dcp.h '(should have been 2347 characters)' fi echo shar: extracting dcpgpkt.c '(15366 characters)' cat << \SHAR_EOF > dcpgpkt.c /* dcpgpkt.c Revised edition of dcp Stuart Lynne May/87 Copyright (c) Richard H. Lamb 1985, 1986, 1987 Changes Copyright (c) Stuart Lynne 1987 */ /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */ /* 3-window "g" ptotocol */ /* Thanks got to John Gilmore for sending me a copy of Greg Chesson's UUCP protocol description-- Obviously invaluable Thanks also go to Andrew Tannenbaum for the section on Siding window protocols with a program example in his "Computer Networks" book MAINTENANCE NOTES: 25Aug87 - Allow for up to 7 windows - Jal */ #include "dcp.h" #define PKTSIZE 64 #define PKTSIZ2 2 #define HDRSIZE 6 #define MAXTRY 4 #define MAXERR 200 /* Dont want to quit in a middle of a long file*/ #define MAXBADINAROW 5 /* Max bad reads in a row */ #define TIMEOUT 4 /* could be longer */ #define KPKT 1024/PKTSIZE #define POK -1 #define MAXWINDOW 7 #define NBUF 8 /* always SAME as MAXSEQ ? */ #define MAXSEQ 8 #define between(a,b,c) ((a<=b && b<c) || (c<a && a<=b) || (b<c && c<a)) /* packet defin */ static int rwl, swl, swu, rwu, nerr, nbuffers, npkt, irec, timeout; static int badInARow = 0; static int fseq[NBUF], outlen[NBUF], inlen[NBUF], arr[NBUF]; static int nwindows; static char outbuf[NBUF][PKTSIZE+1], inbuf[NBUF][PKTSIZE+1]; static unsigned char grpkt[HDRSIZE+1]; static long ftimer[NBUF], acktmr, naktmr; /**/ /******************SUB SUB SUB PACKET HANDLER************/ gopenpk() { int i, n1, n2, len; char tmp[PKTSIZE+1]; pktsize = PKTSIZE; /* change it later after the init */ msgtime = MSGTIME; /* not sure I need this for "g" proto */ /* initialize proto parameters */ swl = nerr = nbuffers = npkt = 0; swl = swu = 1; rwl = 0; rwu = MAXWINDOW - 1; nwindows = MAXWINDOW; for (i = 0; i < NBUF; i++) { ftimer[i] = 0; arr[i] = FALSE; } /* 3-way handshake */ timeout = 10; /* want some timeout capability here */ gspack(7, 0, 0, 0, tmp); rsrt: if (badInARow >= MAXBADINAROW || nerr >= MAXERR) return(-1); switch (grpack(&n1, &n2, &len, tmp)) { case 7: badInARow = 0; gspack(6, 0, 0, 0, tmp); nwindows = n1; if ( nwindows > MAXWINDOW ) nwindows = MAXWINDOW; rwu = nwindows - 1; goto rsrt; case 6: badInARow = 0; gspack(5, 0, 0, 0, tmp); goto rsrt; case 5: badInARow = 0; break; default: badInARow++; nerr++; gspack(7, 0, 0, 0, tmp); goto rsrt; } nerr = 0; return(0); /* channel open */ } gclosepk() { int i; char tmp[PKTSIZE+1]; timeout = 10; for (i = 0; i < MAXTRY && badInARow < MAXBADINAROW; i++) { gspack(CLOSE, 0, 0, 0, tmp); if (gmachine() == CLOSE) break; } printmsg( 0, "number of errors %d and pkts xfered %d", nerr, npkt ); return(0); } /* * * ggetpkt ***** description: Gets no more than a packet's worth of data from **** the "packet i/o state machine". May have to **** periodically run the pkt machine to get some **** packets. * on input: dont care getpkt(data,&len) char *data int len * on return: data+\0 and length in len. ret(0) if alls well * ret(-1) if problems.(fail) */ ggetpkt(cdata, len) int *len; char cdata[]; { int i2; irec = 1; timeout = 10; /* WAIT FOR THE DESIRED PACKET */ while ((arr[rwl]) == FALSE) if (gmachine() != POK) return(-1); /* GOT A PKT ! */ i2 = rwl; /*<-- mod(,rwindow) for larger than 8 seq no.s */ *len = inlen[i2]; movmem(inbuf[i2], cdata, *len); arr[i2] = FALSE; rwu = (1 + rwu) % MAXSEQ; /* bump rec window */ npkt++; return(0); } /* * * sendpkt * ***** description: Put at most a packet's worth of data in the pkt state **** machine for xmission. ***** May have to run the pkt machine a few times to get ***** an available output slot. * * on input: char *data int len,flg; len=length of data in data. * flg=2 just send the packet with no wait for ack. * flg>0 zero out the unused part of the buffer. (for UUCP "msg" * pkts) * flg=0 normal data * return: ret(0) if alls well ret(-1) if problems (fail) * */ gsendpkt(cdata, len, flg) int len, flg; char *cdata; { int i, i1; long ttmp; irec = 0; timeout = 10; /* non-blocking reads */ /* WAIT FOR INPUT i.e. if weve sent nwindows pkts and none have been */ /* acked, wait for acks */ while (nbuffers >= nwindows) if (gmachine() != POK) return(-1); i1 = swu; /* <--If we ever have more than 8 seq no.s, must mod() here*/ /* PLACE PACKET IN TABLE AND MARK UNACKED */ /* fill with zeros or not */ if (flg) { strncpy(outbuf[i1], cdata, PKTSIZE); len = PKTSIZE; for (i = strlen(cdata); i < len; i++) outbuf[i1][i] = '\0'; } else { movmem(cdata, outbuf[i1], len); outbuf[i1][len] = '\0'; } /* mark packet */ outlen[i1] = len; ftimer[i1] = time(&ttmp); fseq[i1] = swu; swu = (1 + swu) % MAXSEQ; /* bump send window */ nbuffers++; npkt++; /* send it */ gspack(DATA, rwl, fseq[i1], outlen[i1], outbuf[i1]); /* send it once then let the pkt machine take it. wouldnt need this for */ /* mtasking systems */ /* sl gmachine(); */ return(0); } /************ packet machine ****** RH Lamb 3/87 */ /* Idealy we would like to fork this process off in an infinite loop */ /* and send and rec pkts thru "inbuf" and "outbuf". Cant do this in MS-DOS*/ /* so we setup "getpkt" and "sendpkt" to call this routine often and return */ /* only when the input buffer is empty thus "blocking" the pkt-machine task. */ gmachine() { int rack, rseq, rlen, i1, i2, dflg; char rdata[PKTSIZE+1]; long ttmp, itmp; reply: printmsg( 6, "*send %d<W<%d, rec %d<W<%d, err %d", swl, swu, rwl, rwu, nerr ); /* waiting for ACKs for swl to swu-1. Next pkt to send=swu */ /* rwl=expected pkt */ printmsg( 7, "Kbytes transfered %d errors %d\r", npkt / KPKT, nerr ); if (nerr >= MAXERR) goto close; dflg = 0; switch (grpack(&rack, &rseq, &rlen, rdata)) { case CLOSE: printmsg( 5, "**got CLOSE"); badInARow = 0; goto close; case NAK: nerr++; badInARow = 0; acktmr = naktmr = 0; /* stop ack/nak timer */ printmsg( 5, "**got NAK %d", rack ); rack = (rack + 1) % MAXSEQ; while (between(swl, rack, swu)) { /* resend rack->(swu-1) */ i1 = rack; gspack(DATA, rwl, rack, outlen[i1], outbuf[i1]); printmsg( 5, "***resent %d", rack ); ftimer[i1] = time(&ttmp); rack = (1 + rack) % MAXSEQ; } goto reply; /* any other stuff ? */ case EMPTY: printmsg( 5, "**got EMPTY" ); if(badInARow++ >= MAXBADINAROW) return(0); itmp = time(&ttmp); if (acktmr) if ((itmp - acktmr) >= TIMEOUT) { /* ack timed out*/ gspack(ACK, rwl, 0, 0, rdata); acktmr = itmp; } if (naktmr) if ((itmp - naktmr) >= TIMEOUT) { /*nak timed out*/ gspack(NAK, rwl, 0, 0, rdata); naktmr = itmp; } /* resend any timed out un-acked pkts */ for (i2 = swl; between(swl, i2, swu); i2 = (1 + i2) % MAXSEQ) { acktmr = naktmr = 0; /* reset ack/nak */ i1 = i2; printmsg( 5, "--->seq,elapst %d %ld", i2, (itmp - ftimer[i1]) ); if ((itmp - ftimer[i1]) >= TIMEOUT) { printmsg( 5, "***timeout %d", i2 ); /* since "g" is "go-back-N", when we time out we */ /* must send the last N pkts in order. The generalized*/ /* sliding window scheme relaxes this reqirment */ nerr++; rack = i2; while (between(swl, rack, swu)) { /* resend rack->(swu-1) */ i1 = rack; gspack(DATA, rwl, rack, outlen[i1], outbuf[i1]); printmsg( 5, "***resent %d", rack ); ftimer[i1] = time(&ttmp); rack = (1 + rack) % MAXSEQ; } return(POK); } } return(POK); case ACK: printmsg( 5, "**got ACK %d", rack ); badInARow = 0; acktmr = naktmr = 0; /* disable ack/nak's */ while (between(swl, rack, swu)) { /* S<-- -->(S+W-1)%8 */ printmsg( 5, "***ACK %d", swl ); ftimer[swl] = 0; nbuffers--; swl = (1 + swl) % MAXSEQ; dflg = 1; /* same hack */ /* sl */ } if (dflg) return(POK); /* hack for non-mtask sys's */ /* to empty "inbuf[]" */ goto reply; case DATA: printmsg( 5, "**got DATA %d %d", rack, rseq ); badInARow = 0; i1 = (1 + rwl) % MAXSEQ; /* (R+1)%8 <-- -->(R+W)%8 */ i2 = (1 + rwu) % MAXSEQ; if (between(i1, rseq, i2)) { if (i1 == rseq) { i1 = rseq; arr[i1] = TRUE; inlen[i1] = rlen; movmem(rdata, inbuf[i1], rlen); rwl = (rwl + 1) % MAXSEQ; printmsg( 5, "***ACK d %d", rwl ); gspack(ACK, rwl, 0, 0, rdata); acktmr = time(&ttmp); /* enable ack/nak tmout*/ dflg = 1; /*return to call when finished*/ /* in a mtask system, unneccesary */ } else { nerr++; printmsg( 5, "***unexpect %d ne %d", rseq, rwl ); } } else { nerr++; printmsg( 5, "***wrong seq %d", rseq ); } while (between(swl, rack, swu)) { /* S<-- -->(S+W-1)%8 */ printmsg( 5, "***ACK %d", swl ); ftimer[swl] = 0; nbuffers--; swl = (1 + swl) % MAXSEQ; dflg = 1; /* same hack */ /* sl */ } if (dflg) return(POK); /* hack for non-mtask sys's */ case ERROR: if(badInARow++ >= MAXBADINAROW) return(0); nerr++; printmsg( 5, "**got BAD CHK" ); gspack(NAK, rwl, 0, 0, rdata); naktmr = time(&ttmp); /* set nak timer */ printmsg( 5, "***NAK d %d", rwl ); goto reply; default: if(badInARow++ >= MAXBADINAROW) return(0); printmsg( 5, "**got SCREW UP" ); goto reply; /* ignore it */ } close: gspack(CLOSE, 0, 0, 0, rdata); return(CLOSE); } /**/ /*************** FRAMING *****************************/ /* * * * send a packet * nt2=type nt3=pkrec nt4=pksent len=length<=PKTSIZE cnt1= data * ret(0) always */ gspack(nt2, nt3, nt4, len, cnt1) int nt2, nt3, nt4, len; char cnt1[]; { unsigned int check, i; unsigned char c2, pkt[HDRSIZE+1], dpkerr[10]; if (len > 64) len = 64; if (len == 0) cnt1[0] = '\0'; /**Link testing mods- create artificial errors ***/ /* printf("**n:normal,e:error,l:lost,p:partial,h:bad header,s:new seq--> "); gets(dpkerr); if(dpkerr[0] == 's') { sscanf(&dpkerr[1],"%d",&nt4); } /**/ /** End Link testing mods ***/ printmsg( 5, "send packet type %d, num=%d, n=%d, len=%d", nt2, nt3, nt4, len ); printmsg( 5, "data =\n|%s|", cnt1 ); c2 = '\0'; pkt[0] = '\020'; pkt[4] = nt2 << 3; nt2 &= 7; switch (nt2) { case 1: break; /* stop protocol */ case 2: pkt[4] += nt3; break; /* reject */ case 3: break; case 4: pkt[4] += nt3; break; /* ack */ case 5: pkt[4] += nwindows; break; case 6: pkt[4] += 1; break; /* pktsiz = 64 (1) */ case 7: pkt[4] += MAXWINDOW; break; case 0: pkt[4] += 0x80 + nt3 + (nt4 << 3); c2 = (PKTSIZE - len) & 0xff; /* havnt set it up for VERY LONG pkts with a few */ /* bytes yet (-128) */ if (c2) { /* short packet handling */ pkt[4] += 0x40; /* if len < PKTSIZE */ for (i = PKTSIZE - 1; i > 0; i--) cnt1[i] = cnt1[i-1]; cnt1[0] = c2; } break; } pkt[4] &= 0xff; if (nt2) { pkt[1] = 9; /* control packet size = 0 (9) */ check = (0xaaaa - pkt[4]) & 0xffff; } else { pkt[1] = PKTSIZ2; /* data packet size = 64 (2) */ check = checksum(cnt1, PKTSIZE); i = pkt[4];/* got to do this on PC for ex-or high bits */ i &= 0xff; check = (check ^ i) & 0xffff; check = (0xaaaa - check) & 0xffff; } pkt[2] = check & 0xff; pkt[3] = (check >> 8) & 0xff; pkt[5] = (pkt[1] ^ pkt[2] ^ pkt[3] ^ pkt[4]) & 0xff; /***More Link testing MODS ******/ /* switch(dpkerr[0]) { case 'e': cnt1[10] = -cnt1[10]; break; case 'h': pkt[5] = -pkt[5]; break; case 'l': return; case 'p': swrite(pkt,HDRSIZE); if(pkt[1] != 9) swrite(cnt1,PKTSIZE-3); return; default: break; } /**/ /******End Link Testing Mods **********/ swrite(pkt, HDRSIZE); /* header is 6-bytes long */ /* write(flog,pkt,HDRSIZE); */ if (pkt[1] != 9) { swrite(cnt1, PKTSIZE); /* data is always 64 bytes long */ /* write(flog,cnt1,PKTSIZE); */ } } /**/ /* * * read packet * on return: nt3=pkrec nt4=pksent len=length <=PKTSIZE cnt1=data * * ret(type) ok; ret(EMPTY) input buf empty; ret(ERROR) bad header; * ret(EMPTY) lost pkt timeout; ret(ERROR) checksum error;ret(-5) ? ****NOTE : ***sread(buf,n,timeout) while(TRUE) { if(# of chars available >= n) (without dec internal counter) read n chars into buf (decrenent internal char counter) break else if(time>timeout) break } return(# of chars available) ****END NOTE */ grpack(nt3, nt4, len, cnt1) int *nt3, *nt4, *len; char cnt1[]; { unsigned int nt1, check, checkchk, i; unsigned char c, c2; int ii; chkabort(); c = '\0'; while ((c & 0x7f) != '\020') { if (sread(&c, 1, timeout) <= 0) return(EMPTY); } if (sread(&grpkt[1], HDRSIZE - 1, timeout) < (HDRSIZE - 1)) return(EMPTY); /*i = grpkt[1] ^ grpkt[2] ^ grpkt[3] ^ grpkt[4] ^ grpkt[5];*/ i = (unsigned)grpkt[1] ^ (unsigned)grpkt[2] ^ (unsigned)grpkt[3] ^ (unsigned)grpkt[4] ^ (unsigned)grpkt[5]; i &= 0xff; printmsg( 10, "prpkt %02x %02x %02x %02x %02x .. %02x ", grpkt[1], grpkt[2], grpkt[3], grpkt[4], grpkt[5], i ); if (i) { /* bad header */ printmsg( 0, "****bad header****" ); return(ERROR); /* Im not sure whether "g" considers it an empty or error */ } if ((grpkt[1] &= 0x7f) == 9) { /* control packet */ *len = 0; c = grpkt[4] & 0xff; nt1 = c >> 3; *nt3 = c & 7; *nt4 = 0; check = 0; checkchk = 0; cnt1[*len] = '\0'; } else { /* data packet */ if (grpkt[1] != PKTSIZ2) return(-5); /* cant handle other than 64*/ if (sread(cnt1, PKTSIZE, timeout) < PKTSIZE) return(EMPTY); nt1 = 0; c2 = grpkt[4] & 0xff; c = c2 & 0x3f; *nt4 = c >> 3; *nt3 = c & 7; i = grpkt[3]; i = (i << 8) & 0xff00; check = grpkt[2]; check = i | (check & 0xff); checkchk = checksum(cnt1, PKTSIZE); i = grpkt[4] | 0x80; i &= 0xff; checkchk = 0xaaaa - (checkchk ^ i); checkchk &= 0xffff; if (checkchk != check) { printmsg( 4, "***checksum error***" ); return(ERROR); } *len = PKTSIZE; /* havnt set it up for very long pkts yet (>128) RH Lamb */ if (c2 & 0x40) { ii = (cnt1[0] & 0xff); *len = (*len - ii) & 0xff; for (ii = 0; ii < *len; ii++) cnt1[ii] = cnt1[ii+1]; } cnt1[*len] = '\0'; } printmsg( 5, "rec packet type %d, num=%d, n=%d, len=%d", nt1, *nt3, *nt4, *len ); printmsg( 6, " checksum rec = %x comp = %x, data=\n|%s|", check, checkchk, cnt1 ); ii = nt1; return(ii); } unsigned checksum(data, len) int len; char data[]; { unsigned int i, j, tmp, chk1, chk2; chk1 = 0xffff; chk2 = 0; j = len; for (i = 0; i < len; i++) { if (chk1 & 0x8000) { chk1 <<= 1; chk1++; } else { chk1 <<= 1; } tmp = chk1; chk1 += (data[i] & 0xff); chk2 += chk1 ^ j; if ((chk1 & 0xffff) <= (tmp & 0xffff)) chk1 ^= chk2; j--; } return(chk1 & 0xffff); } /* */ /* gwrmsg send a null terminated string out */ gwrmsg( typ, buf ) char typ; char *buf; /* null terminated */ { } /* grdmsg read a null terminated string */ grdmsg( buf ) char * buf; { } /* gwrdata read a file and send it out */ gwrdata( f ) { } /* grrdata read in data and send to file */ grrdata( f ) { } /* grdblk read a block of data in */ grdblk( blk, len ) { } /* gwrblk write out a block of data */ gwrblk( blk, len ) { } SHAR_EOF if test 15366 -ne "`wc -c dcpgpkt.c`" then echo shar: error transmitting dcpgpkt.c '(should have been 15366 characters)' fi echo shar: extracting dcpsys.c '(13004 characters)' cat << \SHAR_EOF > dcpsys.c /* dcpsys.c Revised edition of dcp Stuart Lynne May/87 Copyright (c) Richard H. Lamb 1985, 1986, 1987 Changes Copyright (c) Stuart Lynne 1987 */ /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */ /* Get the next system, and other support routines */ #include "dcp.h" /*#define PROTOS "trkg"*/ #define PROTOS "g" #define MAXLOGTRY 3 Proto Protolst[] = { 'g', ggetpkt, gsendpkt, gopenpk, gclosepk, /* 'k', kgetpkt, ksendpkt, kopenpk, kclosepk, 'r', rgetpkt, rsendpkt, ropenpk, rclosepk, 't', tgetpkt, tsendpkt, topenpk, tclosepk, */ '0'}; #define EOTMSG "\004\r\004\r" static int timeOut = 30;/* default timeout when processing callup script */ /* You can specify the timeout in the systems file */ /* DELAY10 */ /* sets the timeout to 10. */ procref getpkt, sendpkt, openpk, closepk; /**/ /***************************************************************/ /*** Sub Systems */ /* ** **getsystem ** Process an "systems" file entry (like L.sys) */ getsystem() { int i; if ( fgets( sysline, BUFSIZ, fsys ) == (char *)NULL ) return( 'A' ); printmsg( 2, "%s", sysline ); kflds = getargs( sysline, flds ); strcpy( rmtname, flds[FLD_REMOTE] ); cctime = flds[FLD_CCTIME]; strcpy( device, flds[FLD_DEVICE] ); /* strcpy( type, flds[FLD_TYPE] ); */ strcpy( speed, flds[FLD_SPEED] ); strcpy( proto, flds[FLD_PROTO] ); if (debuglevel > 3) for (i = FLD_EXPECT; i < kflds; i += 2) fprintf( stderr, "expect[%02d]:\t%s\nsend [%02d]:\t%s\n", i, flds[i], i+1, flds[i+1] ); printmsg( 2, "rmt= %s ctm= %s", rmtname, flds[FLD_CCTIME] ); printmsg( 2, "dev= %s ", device ); printmsg( 2, "spd= %s pro= %s", speed, proto ); fw = (FILE *)NULL; if ( /* (checktime( cctime )) || */ ( strcmp( Rmtname, "all" ) == SAME ) || ( strcmp( Rmtname, rmtname ) == SAME ) || ( (strcmp( Rmtname, "any" ) == SAME) && scandir() == 'S' ) ) { if ( fw != (FILE *)NULL ) fclose( fw ); /* in case we matched with scandir */ return( 'S' ); /* startup this system */ } else return('G'); } /**/ /* ** **checkname ** Do we know the guy ? */ checkname(name) char name[]; { FILE *ff; char line[BUFSIZ], tmp[20]; /* can change to 8 if %8s works */ if ( ( ff = FOPEN( s_systems, "r", 't' )) == (char *)NULL ) return( FAILED ); while ( fgets( line, BUFSIZ, ff ) != (char *)NULL ){ sscanf( line, "%8s ", tmp ); printmsg( 3, "rmt= %s sys= %s", name, tmp ); if ( strncmp( tmp, line, 7 ) == 0 ) { fclose( ff ); return ( OK ); /*OK I like you */ } } fclose( ff ); return( FAILED ); /* Who are you ? */ } /**/ /* ** **checktime ** check if we may make a call at this time **------------>to be implemented. Again. Didnt think it crucial */ checktime(xtime) char xtime[]; { return(0); /* OK go to it */ } /**/ /* ** **sysend ** end UUCP session negotiation */ sysend() { extern int lineIsOpen; char msg[80]; if(lineIsOpen) { msg[1] = '\0'; msgtime = 2 * MSGTIME; wmsg("OOOOOO", 2); rmsg(msg, 2); } closeline(); if ( remote == MASTER ) return('I'); return('A'); } /* ** **sysAbortEnd ** break connection without any message */ sysAbortEnd() { msgtime = 2 * MSGTIME; closeline(); if ( remote == MASTER ) return('I'); return('A'); } /**/ /* ** ** delay ** */ /*ddelay(dtime) int dtime; { int i, j; for (i = 0; i < dtime; i++) { } } */ /**/ /* ** **wmsg ** write a ^P type msg to the remote uucp */ wmsg(msg, syn) int syn; char msg[]; { int len; len = strlen(msg); if (syn == 2) swrite("\0\020", 2); swrite(msg, len); if (syn == 2) swrite("\0", 1); } /* ** **rmsg ** read a ^P msg from UUCP */ rmsg(msg, syn) int syn; char msg[]; { int ii; char c, cc[5]; /* *msg0;*/ /*msg0 = msg;*/ c = 'a'; if (syn == 2) { while ((c & 0x7f) != '\020') { if (sread(cc, 1, msgtime) < 1) return(-1); c = cc[0]; /* Dont ask. MSC needs more than a byte to breathe */ /* printf("Hello im in rmsg c=%x\n",c); */ } } for (ii = 0; ii < 132 && c ; ii++) { if (sread(cc, 1, msgtime) < 1) return(-1); c = cc[0] & 0x7f; if (c == '\r' || c == '\n') c = '\0'; msg[ii] = c; /*if(c == '\020') msg = msg0; */ } return(strlen(msg)); } /**/ /* ** ** **startup ** ** */ startup() { char msg[80], tmp1[20], tmp2[20]; if ( remote == MASTER ) { msgtime = 2 * MSGTIME; if (rmsg(msg, 2) == -1) return('Y'); printmsg( 2, "1st msg = %s", msg ); if (msg[5] == '=' && strncmp(&msg[6], rmtname, 7)) return('Y'); /*sprintf(msg, "S%.7s -Q0 -x%d", nodename, debuglevel);*/ /* -Q0 -x16 remote debuglevel set */ sprintf(msg, "S%.7s", nodename); wmsg(msg, 2); if (rmsg(msg, 2) == -1) return('Y'); printmsg( 2, "2nd msg = %s", msg ); if (strncmp(&msg[1], "OK", 2)) return('Y'); if (rmsg(msg, 2) == -1) return('Y'); printmsg( 2, "3rd msg = %s", msg ); if (msg[0] != 'P' || index(&msg[1], proto[0]) == (char *)NULL) { wmsg("UN", 2); return('Y'); } sprintf(msg, "U%c", proto[0]); wmsg(msg, 2); setproto(proto[0]); return('D'); } else { msgtime = 2 * MSGTIME; sprintf(msg, "Shere=%s", nodename); wmsg(msg, 2); if (rmsg(msg, 2) == -1) return('Y'); sscanf(&msg[1], "%s %s %s", rmtname, tmp1, tmp2); sscanf(tmp2, "-x%d", &debuglevel); printmsg( 1, "debuglevel level = %d", debuglevel ); printmsg( 2, "1st msg from remote = %s", msg ); if (checkname(rmtname)) return('Y'); wmsg("ROK", 2); sprintf(msg, "P%s", PROTOS); wmsg(msg, 2); if (rmsg(msg, 2) == -1) return('Y'); if (msg[0] != 'U' || index(PROTOS, msg[1]) == (char *)NULL ) return('Y'); proto[0] = msg[1]; setproto(proto[0]); return('R'); } } /******* set the protocol **********/ setproto(pr) char pr; { Proto * tproto; for (tproto = Protolst; tproto->type != '\0' && pr != tproto->type; tproto++) { printmsg( 3, "setproto: %c %c", pr, tproto->type ); } if (tproto->type == '\0') { printmsg( 0, "setproto:You said I had it but I cant find it" ); exit(1); } getpkt = tproto->a; sendpkt = tproto->b; openpk = tproto->c; closepk = tproto->d; } /**/ int prefix(sh,lg) char *sh,*lg; { return( strncmp(sh,lg,strlen(sh)) == SAME); } int notin(sh,lg) char *sh,*lg; { while (*lg) { if (prefix(sh,lg++)) return( FALSE ); } return( TRUE ); } #define MAXR 300 int expectstr( str, timeout ) char *str; { static char rdvec[MAXR]; char *rp = rdvec; int kr; char nextch; printmsg( 0, "wanted %s", str ); if ( strcmp(str, "\"\"") == SAME ) { return( TRUE ); } *rp = 0; while ( notin( str,rdvec ) ) { /* fprintf(stderr, "---------->%s<------\n", rdvec);/**/ kr = sread( &nextch, 1, timeout /* 40 */ ); /* nextch &= 0177; fprintf(stderr, "kr - %2d '%c'\n", kr, nextch); */ if (kr <= 0) { return( FALSE ); } if ((*rp = nextch & 0177) != '\0') { rp++; } *rp = '\0'; if (rp >= rdvec + MAXR) { return( FALSE ); } } return( TRUE ); } int writestr(s) register char *s; { register char last; int nocr; last = '\0'; nocr = FALSE; while (*s) { if (last == '\\') { switch (*s) { case 'd': case 'D': /* delay */ sleep(2); break; case 'c': case 'C': /* end string don't output CR */ nocr = TRUE; break; case 'r': case 'R': /* carriage return */ case 'm': case 'M': swrite( "\r", 1 ); break; case 'n': case 'N': swrite( "\n", 1 ); break; case 'b': case 'B': swrite( "\b", 1 ); break; case 't': case 'T': swrite( "\t", 1 ); break; case 's': case 'S': swrite( " ", 1 ); break; case 'z': case 'Z': SIOSpeed( ++s ); while ( *s != '\0' && *s != '\\' ) s++; if ( *s == '\\' ) s++; break; default: swrite( s, 1 ); } last = '\0'; } else if (*s != '\\') { swrite( s, 1 ); /* fputc(*s,stderr); */ } else { last = *s; } s++; } return( nocr ); } /*** * void sendthem(str) send line of login sequence * char *str; * * return codes: none */ void sendstr(str) char *str; { printmsg( 2, "sending %s", str ); #ifdef BREAK if (prefix("BREAK", str)) { /* send break */ ssendbrk(); return; } #endif if (prefix("DELAY", str)) { str += 5; timeOut = atoi(str); str += strspn(str, "0123456789"); } if ( strcmp(str, "EOT") == SAME ) { swrite(EOTMSG, strlen(EOTMSG)); return; } if ( strcmp(str,"\"\"") == SAME ) *str = '\0'; /*fprintf(stderr,"'%s'\n",str);*/ if ( strcmp(str,"") != SAME ) { if (!writestr(str)) { swrite ("\r", 1); } } else { swrite("\r", 1); } return; } int sendexpect( s, e, timeout ) char * s; char * e; { sendstr( s ); return( expectstr( e, timeout ) ); } dial() { char buf[4]; if ( strcmp( flds[FLD_TYPE], "HAYES" ) != SAME ) { printmsg( 0, "dial: unsupported dialer %s", flds[FLD_TYPE] ); return( FALSE ); } printmsg( 3, "calling host %s", rmtname ); if (openline(device, "2400" )) return( FALSE ); printmsg( 0, "hayes: trying 2400" ); if ( sendexpect( "ATZ", "OK", 2 ) != TRUE ) { sendexpect( "\\d+++\\d", "OK", 2 ); if ( sendexpect( "ATZ", "OK", 2 ) != TRUE ) { printmsg( 0, "hayes: trying 1200" ); SIOSpeed( "1200" ); if ( sendexpect( "ATZ", "OK", 2 ) != TRUE ) { sendexpect( "\\d+++\\d", "OK", 2 ); if ( sendexpect( "ATZ", "OK", 2 ) != TRUE ) return( FALSE); } } } printmsg( 0, "hayes: got modem response" ); /*(sendstr( "\\d\\dATS7=30" ); expectstr( "OK", 40 );*/ sendstr( "\\d\\dATX4\\c" ); if ( sendexpect( speed, "CONNECT ", 40 ) == TRUE ) { printmsg( 3, "hayes: got CONNECT" ); if ( sread( buf, 4, 4 ) == 4 ) { printmsg( 3, "hayes: speed select %s", buf ); /* set speed appropriately */ SIOSpeed( buf ); } return( TRUE ); } else return( FALSE ); } /* ** **callup ** script processor - nothing fancy! */ callup() { char *exp; char *alternate; int ok; int i; printmsg( 0, "calling host %s", rmtname ); if ( strcmp( flds[FLD_TYPE], "DIR" ) != SAME ) { if ( dial() == FALSE ) return( 'G' ); } else if (openline(device, speed)) return( 'G' ); for (i = 6; i < kflds; i+=2) { exp = flds[i]; printmsg( 2, "callup: expect %d of %d \"%s\"", i, kflds, exp ); ok = FALSE; while (ok != TRUE) { alternate = index( exp, '-' ); if (alternate != (char *)NULL) *alternate++ = '\0'; ok = expectstr( exp, timeOut ); printmsg( 1, "got %s", ok != TRUE ? "?" : "that" ); if ( ok == TRUE ) { printmsg( 0, "got that" ); break; } if ( alternate == (char *)NULL ) { printmsg( 0, "LOGIN FAILED" ); return( 'Z' ); } exp = index( alternate, '-' ); if ( exp != (char *)NULL ) *exp++ = '\0'; printmsg( 0, "send alternate" ); sendstr( alternate ); } printmsg(2, "callup: send %d of %d \"%s\"", i+1, kflds, flds[i+1] ); sleep(1); sendstr(flds[i+1]); } return('P'); } /**/ /* ** ** slowrite ** comunication slow write. needed for auto-baud modems */ /*slowrite(st) register char *st; { int len, j; char c; len = strlen(st); printmsg( 2, "sent %s", st ); for (j = 0; j < len; j++) { swrite(&st[j], 1); ddelay(80000); } } */ /**/ /* ** **scandir ** */ #include "ndir.h" /* scandir scan work dir for C. files matching current remote host (rmtname) return A - abort Y - can't open file S - ok Q - no files */ scandir() { int len; char cname[40]; DIR *dirp; struct direct *dp; if ((dirp = opendir( spooldir )) == (DIR *)NULL ) { fprintf( stderr, "couldn't open dir %s\n", spooldir ); return( 'A' ); } sprintf(cname, CALLFILE, rmtname); len = strlen(cname); while ((dp = readdir(dirp)) != (struct direct *)NULL) { printmsg( 4, "scandir: %s", dp->d_name ); if ( strncmp( cname, dp->d_name, len ) == SAME ) { printmsg( 4, "scandir: match!!" ); strcpy(cfile, dp->d_name); closedir( dirp ); if ((fw = FOPEN( cfile, "r", 't' )) == (char *)NULL ) return('Y'); return('S'); } } closedir( dirp ); return('Q'); } /**/ /* ** **dscandir ** scan the directory */ dscandir() { int len; char cname[40]; DIR *dirp; struct direct *dp; if ((dirp = opendir( spooldir )) == (DIR *)NULL ) { fprintf( stderr, "couldn't open dir %s\n", spooldir ); return(0); } sprintf(cname, XQTFILE, rmtname); /* sprintf(cname,"c%.4s",rmtname); */ len = strlen(cname); while ((dp = readdir(dirp)) != (struct direct *)NULL) { printmsg( 4, "dscandir:dir file = %s cfile = %s", dp->d_name, cname ); if ( strncmp( cname, dp->d_name, len ) == SAME ) { printmsg( 4, "dscandir: match!!" ); strcpy(cfile, dp->d_name); closedir( dirp ); return( -1 ); } } closedir( dirp ); return( 0 ); } SHAR_EOF if test 13004 -ne "`wc -c dcpsys.c`" then echo shar: error transmitting dcpsys.c '(should have been 13004 characters)' fi echo shar: extracting dcpxfer.c '(10190 characters)' cat << \SHAR_EOF > dcpxfer.c /* dcpxfer.c Revised edition of dcp Stuart Lynne May/87 Copyright (c) Richard H. Lamb 1985, 1986, 1987 Changes Copyright (c) Stuart Lynne 1987 */ /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */ /* file send routines */ #include "dcp.h" static unsigned char rpacket[MAXPACK]; static unsigned char spacket[MAXPACK]; /**/ /***************SEND PROTOCOL***************************/ /* * s d a t a * * Send File Data */ sdata() { while( TRUE ) { if (( *sendpkt) ( spacket, size, 0 )) return (0 ); /* send data */ if (( size = bufill( spacket )) == 0 ) /* Get data from file */ return( 'Z' ); /* If EOF set state to that */ } return('D');/* Got data, stay in state D */ } /* * b u f i l l * * Get a bufferful of data from the file that's being sent. * Only control-quoting is done; 8-bit & repeat count prefixes are * not handled. */ bufill(buffer) char *buffer;/* Buffer */ { return( read(fp, buffer, pktsize) );/* Handle partial buffer */ } /* * s b r e a k * * Send Break (EOT) */ sbreak() { int len; strcpy(spacket, "H"); if ((*sendpkt)(spacket, 0, 1)) return(0); if ((*getpkt)(spacket, &len)) return(0); printmsg( 2, "Switch modes" ); if (spacket[1] == 'N') return('G'); return('Y'); } /**/ /* * s e o f * * Send End-Of-File. */ seof() { int len; if ((*sendpkt)(spacket, 0, 0)) return(0); if ((*getpkt)(spacket, &len)) return(0); /* rec CY or CN */ if (strncmp(spacket, "CY", 2)) return(0); /* cant send file */ close(fp); fp = (-1); importpath( hostfile, fromfile ); if(!strchr(fromfile,':') && !strchr(fromfile,'/')) unlink(fromfile); printmsg( 0, "transfer %s complete", fromfile ); /* fprintf( syslog, "%s!%s (%d/%d-%d:%d:%d) -> %ld / %ld secs", host, id, size, secs ); */ return('F'); /* go get the next file to send */ } /**/ /* * r e o f * * Send End-Of-File and receive Ack in slave mode. */ reof() { int len; if ((*sendpkt)(spacket, 0, 0)) return(0); if ((*getpkt)(spacket, &len)) return(0); /* rec CY or CN */ if (strncmp(spacket, "CY", 2)) return(0); /* send failed */ close(fp); fp = (-1); importpath( hostfile, fromfile ); printmsg( 0, "transfer %s complete", fromfile ); /* fprintf( syslog, "%s!%s (%d/%d-%d:%d:%d) -> %ld / %ld secs", host, id, size, secs ); */ return('F'); /* go get the next file to send */ } /**/ /* * s f i l e * * Send File Header. */ sfile() { int len; int toLength; char *cp; int nextState; if (fp == -1) {/* If not already open, */ printmsg( 3, "looking for next file..." ); if ((nextState = getfile()) == 'B') { fclose( fw ); unlink( cfile ); fw = (char *)NULL; return(nextState); /* end sending session */ } if(nextState == 'R') return(nextState); /* check for ~/ path -> /usr/spool/uucppublic */ if ( strncmp( fromfile, "~/", 2 ) == SAME ) sprintf( hostfile, "%s%s", pubdir, fromfile + 1); else importpath( hostfile, fromfile ); printmsg( 3, " Opening %s for sending.", hostfile ); fp = open(hostfile, 0);/* open the file to be sent */ if (fp == -1) {/* If bad file pointer, give up */ printmsg( 0, "Cannot open file %s", hostfile ); return('A'); } } else return('A'); /* If somethings already open. were in trouble*/ printmsg( 0, "Sending %s to %s", hostfile, tofile ); /* S fromfile tofile user - tofile 0666 */ toLength = strlen(tofile); cp = tofile; while(toLength >= pktsize) { strncpy(spacket, cp, pktsize); cp += pktsize; if ((*sendpkt)(spacket, 0, 1)) return(0); toLength -= pktsize; } strcpy(spacket, cp); if ((*sendpkt)(spacket, 0, 1)) return(0); if ((*getpkt)(spacket, &len)) return(0); if (spacket[1] != 'Y') return('A'); /* If otherside says no-quit */ size = bufill(spacket); return('D'); } /**/ /* * m r f i l e * * Receive File Header. */ mrfile() { int len; int fromLength; char *cp; if (fp == -1) {/* If not already open, */ /* check for ~/ path -> /usr/spool/uucppublic */ if ( strncmp( tofile, "~/", 2 ) == SAME ) sprintf( hostfile, "%s%s", pubdir, tofile + 1); else importpath( hostfile, tofile ); printmsg( 3, " Opening %s for receiving.", hostfile ); if ((fp = CREAT( hostfile, 0775, 'b' )) == -1) { printmsg( 0, "Cannot create %s", hostfile ); return('A'); } } else return('A'); /* If somethings already open. were in trouble*/ printmsg( 0, "Receiving %s from %s", hostfile, fromfile ); /* R fromfile tofile user - tofile 0666 */ fromLength = strlen(fromfile); cp = fromfile; while(fromLength >= pktsize) { strncpy(spacket, cp, pktsize); cp += pktsize; if ((*sendpkt)(spacket, 0, 1)) return(0); fromLength -= pktsize; } strcpy(spacket, cp); if ((*sendpkt)(spacket, 0, 1)) return(0); if ((*getpkt)(spacket, &len)) return(0); if (spacket[1] != 'Y') return('A'); /* If otherside says no-quit*/ size = bufill(spacket); return('D'); } mrabort() { if(fp != -1) close(fp); strcpy(rpacket, "CN5"); if ((*sendpkt)(rpacket, 0, 1)) return(0); printmsg( 0, "transfer failed" ); return('Y'); } /**/ /* * s i n i t * * Send Initiate: send this host's parameters and get other side's back. */ sinit() { if ((*openpk)()) return('A'); return('B'); } /**/ /* * * * getfile * * getfile reads the next line from the presently open workfile * (cfile) and determines from this the next file to be sent or received. * If there are no more then 'B' is returned. Otherwise 'S' or 'R' will * be returned. * We handle the following formats: * R from to [other stuff] * S from to [other stuff] */ getfile() { char line[132]; char from1[132]; char to1[132]; char user[64]; char mode[64]; register char * cp; if ( !fgets( line, BUFSIZ, fw ) || (line[0] != 'R' && line[0] != 'S') ) return('B'); if(line[0] == 'R') { sscanf(&line[2], "%s %s ", from1, tofile); if(tofile[strlen(tofile) - 1] == '/') { if((cp = strrchr(from1,'/')) || (cp = strchr(from1,':'))) cp++; else cp = from1; strcat(tofile, cp); } strcpy(fromfile, line); } else { sscanf(&line[2], "%s %s %s - %s %s", from1, to1, user, fromfile, mode); if((to1[strlen(to1) - 1] == '/') && (cp = strchr(from1,':'))) { *cp = '/'; } else { cp = from1; } sprintf(tofile,"S %s %s %s - %s %s\n", cp, to1, user, fromfile, mode); } printmsg(3, " getfile: fromfile=%s, tofile=%s.", fromfile, tofile); return(line[0]); } /**/ /*********************** MISC SUB SUB PROTOCOL *************************/ /* ** **schkdir ** scan the dir */ schkdir() { char c; c = scandir(); if (c == 'Q') { return('Y'); } if (c == 'S') { strcpy(rpacket, "HN"); if ((*sendpkt)(rpacket, 0, 1)) return(0); } return('B'); } /**/ /* * * endp() end protocol * */ endp() { strcpy(rpacket, "HY"); (*sendpkt)(rpacket, 0, 2); /* dont wait for ACK */ (*closepk)(); return('P'); } /**/ /***********************RECIEVE PROTOCOL**********************/ /* * r d a t a * * Receive Data */ rdata() { int len; if ((*getpkt)(rpacket, &len)) return(0); if (len == 0) { close(fp); strcpy(rpacket, "CY"); if ((*sendpkt)(rpacket, 0, 1)) return(0); printmsg( 0, "transfer complete" ); return('F'); } if ( write(fp, rpacket, len) != len ) /* Write the data to the file */ { printmsg( 0, "Error Writing File" ); return 'A'; } return('D');/* Remain in data state */ } /**/ /* * r f i l e * * Receive File Header */ rfile() { char buf[256]; char * flds[10]; int numflds; int len; char tmpfilename[256]; /*Holds the converted file name */ char *cp, *cp2; printmsg( 3, "rfile entered" ); cp = buf; while ( TRUE ) { if ((*getpkt)( rpacket, &len )) return( 0 ); strncpy( cp, rpacket, len ); cp += len; if ( *(cp - 1) == '\0' ) break; } if (( buf[0] & 0x7f ) == 'H' ) return( 'C' ); printmsg( 3, "rfile: buf %d \"%s\"", len, buf ); /* Convert upper case to lower */ /* for (cp = buf; *cp != '\0';cp++) if (isupper(*cp)) *cp = tolower(*cp); */ numflds = getargs( buf, flds ); if(buf[0] == 'R') { cp = flds[1]; cp2 = flds[2]; printmsg( 3, "rfile: send file \"%s\"", cp ); } else { cp = flds[2]; cp2 = flds[1]; printmsg( 3, "rfile: receive file \"%s\"", cp ); } /* check for ~/ destination -> /usr/spool/uucppublic */ if ( strncmp( cp, "~/", 2 ) == SAME ) sprintf( tmpfilename, "%s%s", pubdir, cp+1); else strcpy( tmpfilename, cp ); if(buf[0] == 'R') printmsg( 3, "rfile: send file \"%s\"", tmpfilename ); else printmsg( 3, "rfile: receive file \"%s\"", tmpfilename ); /* check for dirname only */ cp = tmpfilename + strlen( tmpfilename ) - 1; if ( *cp == '\n' ) *cp-- = '\0'; if ( *cp == '/' ) { fprintf( stderr, "rfile: fromfile %s\n", cp2 ); cp = rindex( cp2, '/' ); if ( cp == (char *) NULL ) cp = cp2; else cp++; fprintf( stderr, "rfile: dironly add %s\n", cp ); strcat( tmpfilename, cp ); } if(buf[0] == 'R') { printmsg( 3, "rfile: send file \"%s\"", tmpfilename ); /* let host munge filename as appropriate */ importpath( fromfile, tmpfilename ); printmsg( 3, "rfile: send file \"%s\"", tofile ); if ((fp = open( fromfile, 0)) == -1) { printmsg( 0, "cannot open %s", fromfile ); return('A'); } printmsg( 0, "Sending %s to %s", fromfile, flds[2] ); strcpy(spacket, "RY"); if ((*sendpkt)(spacket, 0, 1)) return(0); size = bufill(spacket); return('d'); /* Switch to data state */ } else { printmsg( 3, "rfile: receive file \"%s\"", tmpfilename ); /* let host munge filename as appropriate */ importpath( tofile, tmpfilename ); printmsg( 3, "rfile: receive file \"%s\"", tofile ); if ((fp = CREAT( tofile, 0775, 'b' )) == -1) { printmsg( 0, "cannot create %s", tofile ); return('A'); } printmsg( 0, "Receiving %s to %s", flds[1], tofile ); strcpy(rpacket, "SY"); if ((*sendpkt)(rpacket, 0, 1)) return(0); return('D'); /* Switch to data state */ } } /**/ /* * r i n i t * * Receive Initialization */ rinit() { if ((*openpk)()) return(0); return('F'); } SHAR_EOF if test 10190 -ne "`wc -c dcpxfer.c`" then echo shar: error transmitting dcpxfer.c '(should have been 10190 characters)' fi # End of shell archive exit 0
ain@j.cc.purdue.edu (Patrick White) (03/21/88)
Program Name: uupc version 1.1 (part 2 of 3) Submitted By: Johan Widen <jw@sics.se> Summary: Implements uucp for the Amiga -- allows your Amiga to become a uupc site for mail (and news?). Poster Boy: Pat White (ain@j.cc.purdue.edu) Uncompiled. NOTES: Didn't try compiling it. Converted the origional zoo to shars so docs, binaries & sources could be separated. I'm pretty sure this would allow one to receive news, but I remember something in the docs about it not having been tested from when I was quickly scanning them... so I'm not too sure on this. Rob has been playing with it for a while and says it works. -- Pat White (co-moderator comp.sources/binaries.amiga) UUCP: j.cc.purdue.edu!ain BITNET: PATWHITE@PURCCVM PHONE: (317) 743-8421 U.S. Mail: 320 Brown St. apt. 406, West Lafayette, IN 47906 ======================================== # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # genv.c # genv.h # host.h # lib.c # lmail.c # mail.c # mailhost.c # mlib.c # ndir.c # ndir.h # pccp.c # This archive created: Sat Mar 19 01:41:50 1988 # By: Patrick White (PUCC Land, USA) echo shar: extracting genv.c '(7740 characters)' cat << \SHAR_EOF > genv.c /* genv.c copyright (C) 1987 Jeff Lydiatt Copying and use of this program are controlled by the terms of the Free Software Foundations GNU Emacs General Public License. version 0.1 10 July 87 */ #include <stdio.h> #include <ctype.h> #include "genv.h" extern int debuglevel; /* Environment variables are in file "PROFILE" */ #define PROFILE ":usr/lib/uucp/profile" #define SAME 0 #define MAXLINE 255 #define DMAILBOX "mailbox" #define DNAME "noname" #define DDOMAIN "pc.uucp" #define DMAILDIR ":usr/spool/mail" #define DHOME ":usr/noname" #define DCONFDIR ":usr/lib/uucp" #define DSPOOLDIR ":usr/spool/uucp" #define DLOGDIR ":usr/spool/uucp" #define DPUBDIR ":usr/spool/uucppublic" #define DNEWSDIR ":usr/spool/rnews" #define DTEMPDIR "RAM:T" #define DMAILSERVICE "host" #define DNODENAME "noname" #define DDEVICE "CON:" #define DSPEED "1200" #define DPAGESIZE "24" #define DTIMEZONE "+0100" #define TFILENAME "tmpfile" #define FILENAME "%s/%s" char *name = NULL; char *mailbox = NULL; char *home = NULL; char *domain = NULL; char *maildir = NULL; char *confdir = NULL; char *spooldir = NULL; char *logdir = NULL; char *pubdir = NULL; char *mailserv = NULL; char *nodename = NULL; char *device = NULL; char *speed = NULL; char *tempdir = NULL; char *newsdir = NULL; int pagesize = 24; static char *pagesizeString = NULL; char *timeZone = NULL; /*--------------------------------------------------------------*/ /* getsym: get next symbol from file f. f already open */ /*--------------------------------------------------------------*/ #define ID 1001 #define DELIM 1002 #define STR 1003 #define EOL 1004 #define OTHER 1005 #define UNKNOWN -1000 static int getsym( f, sym ) FILE *f; char *sym; { /* Simple non reentrant, non reuseable get next symbol from file f */ /* Valid symbols are: Type Symbol Returned Comment ID <identifier> any valid c identifier. DELIM '=' an equal sign. STR a string anything between "" or ''. EOL '\n' a newline. EOF the end of file character. OTHER a character anything else. Comments begin with # and are delimited by an end of line */ static int lastchar = UNKNOWN; int c, delim; /* strip leading white space */ if ( lastchar != UNKNOWN ) c = lastchar; else c = fgetc( f ); while ( c == ' ' || c == '\t' ) c = fgetc( f ); lastchar = UNKNOWN; /* Comments are '#' delimited by EOL character */ if ( c == '#' ) while ( c != '\n' && c != EOF ) c = fgetc( f ); if ( c == EOF ) /* End of file? */ return EOF; if ( c == '\n' ) /* End of Line? */ { strcpy( sym, "\n" ); return EOL; } if ( c == '=' ) /* Delimiter '='? */ { strcpy( sym, "=" ); return DELIM; } if ( c == '\"' || c == '\'' )/* String ? */ { delim = c; while ( (c = fgetc( f )) != delim && c != EOF && c != '\n' ) *sym++ = c; *sym = '\0'; c = fgetc( f ); return STR; } if ( isalpha( c ) ) /* Identifier ? */ { *sym++ = c; while ( ( c = fgetc( f )) == '_' || isalnum(c) ) *sym++ = c; *sym = '\0'; lastchar = c; return ID; } *sym++ = c; *sym = '\0'; return OTHER; } /*--------------------------------------------------------------*/ /* xmalloc: Just alloc with die on allocation failure */ /*--------------------------------------------------------------*/ static char *xmalloc( size ) unsigned int size; { char *malloc(); register char *p; if ( (p = malloc( size )) != NULL ) return p; fprintf( stderr, "Genv.c: Can't allocated %u bytes\n", size ); exit( NULL ); } /*--------------------------------------------------------------*/ /* setenv: insert an environment variable into my list */ /*--------------------------------------------------------------*/ struct environment { struct environment *next; char *name; char *value; }; typedef struct environment ENV; static ENV *envList = NULL; static void setenv( var, value ) char *var; char *value; { register ENV *envframe; envframe = (ENV *) xmalloc( sizeof( ENV )); envframe->name = xmalloc( strlen(var)+1 ); envframe->value = xmalloc( strlen(value)+1 ); envframe->next = envList; envList = envframe; strcpy( envframe->name, var ); strcpy( envframe->value, value); } /*--------------------------------------------------------------*/ /* getenv: get pointer to value of environment variable */ /*--------------------------------------------------------------*/ static char *getenv( var ) char *var; { register ENV *list; for ( list = envList; list != (ENV *)NULL; list = list->next ) if ( strcmp( var, list->name ) == SAME ) return list->value; return NULL; } /*--------------------------------------------------------------*/ /* readenv: read environment from a file. */ /*--------------------------------------------------------------*/ static void readenv() { FILE *f; int symval; char name[MAXLINE+1], value[MAXLINE+1]; if ( (f = fopen( PROFILE, "r" )) == NULL ) { fprintf( stderr, "Can't open profile file \"%s\"\n", PROFILE ); exit( NULL ); } /* File is layed out as follows: <environment variable> '=' <ID> | <STRING> # comment.... */ while ( (symval = getsym( f, name )) != EOF ) { /* Skip over any comment lines */ while ( symval == EOL ) symval = getsym( f, name ); if ( symval == EOF ) break; if ( symval != ID ) { fprintf( stderr, "Bad environment variable name %s\n", name ); exit( NULL ); } if ( (symval = getsym( f, value )) != DELIM ) { fprintf( stderr, "Missing '=' in environment file\n" ); exit( NULL ); } if ( (symval = getsym( f, value )) != ID && symval != STR ) { fprintf( stderr, "missing value in environment file\n"); exit( NULL ); } setenv( name, value ); } fclose( f ); } /*--------------------------------------------------------------*/ /* exitenv: free that memory when done! */ /*--------------------------------------------------------------*/ void exitenv() { register ENV *p, *q; for ( p = envList; p != NULL; p = q ) { free( p->name ); free( p->value); q = p->next; free( p ); } envList = NULL; } static void genv(thename, envname, dflt) char **thename; char *envname; char *dflt; { if ((*thename = getenv( envname )) == NULL) { fprintf( stderr, "genv: %s not found, using %s\n", envname, dflt ); *thename = dflt; } /* fprintf( stderr, "genv: %s \"%s\"\n", envname, *thename ); /**/ } void loadenv() { readenv(); /* read the profile from a file */ /* get environment var's */ genv( &name, NAME, DNAME ); genv( &mailbox, MAILBOX, DMAILBOX ); genv( &home, HOME, DHOME ); genv( &domain, DOMAIN, DDOMAIN ); genv( &maildir, MAILDIR, DMAILDIR ); genv( &confdir, CONFDIR, DCONFDIR ); genv( &spooldir, SPOOLDIR, DSPOOLDIR ); genv( &logdir, LOGDIR, DLOGDIR ); genv( &pubdir, PUBDIR, DPUBDIR ); genv( &mailserv, MAILSERVICE, DMAILSERVICE ); genv( &nodename, NODENAME, DNODENAME ); genv( &device, DEVICE, DDEVICE ); genv( &speed, SPEED, DSPEED ); genv( &tempdir, TEMPDIR, DTEMPDIR ); genv( &newsdir, NEWSDIR2, DNEWSDIR ); genv( &pagesizeString, PAGESIZE, DPAGESIZE ); pagesize = atoi(pagesizeString); genv( &timeZone, TIMEZONE, DTIMEZONE ); } void mkfilename( filename, dirname, name ) char * filename; char * dirname; char * name; { sprintf( filename, FILENAME, dirname, name ); if(debuglevel > 4) fprintf( stderr, "New filename %s\n", filename ); /**/ } #ifdef TEST main() { register ENV *p; loadenv(); for ( p = envList; p != NULL; p = p->next ) fprintf( stderr, "Name=\"%s\" value=\"%s\"\n", p->name, p->value ); } #endif SHAR_EOF if test 7740 -ne "`wc -c genv.c`" then echo shar: error transmitting genv.c '(should have been 7740 characters)' fi echo shar: extracting genv.h '(1960 characters)' cat << \SHAR_EOF > genv.h /* genv.c copyright (C) 1987 Stuart Lynne Copying and use of this program are controlled by the terms of the Free Software Foundations GNU Emacs General Public License. version 0.1 March 31/1987 environment variables The following evironment variables are defined: MAILBOX current user's mailbox, "sl" NAME current user's name, "Stuart Lynne" DOMAIN domain of this machine, "mac.van-bc.can" MAILDIR where mail is kept, "/usr/mail" CONFDIR where config data is kept, "/usr/lib/uucp" SPOOLDIR where spooled files are "/usr/spool/uucp" LOGDIR where log file are placed "/usr/spool/uucp" PUBDIR public spool directory "/usr/spool/uucppublic" NEWSDIR news directory "/usr/spool/news" TEMPDIR where temp files are created "/tmp" HOME where uses private files are "/usr/sl" MAILSERVICE who do we send remote mail "van-bc" NODENAME what is our local nodename "slmac" DEVICE what is the default device ".a" SPEED what is the default speed "1200" PAGESIZE lines per page in mail pager "24" TIMEZONE to be appended to Date: field "+0100" */ #define MAILBOX "MAILBOX" #define NAME "NAME" #define DOMAIN "DOMAIN" #define MAILDIR "MAILDIR" #define HOME "HOME" #define CONFDIR "CONFDIR" #define SPOOLDIR "SPOOLDIR" #define LOGDIR "LOGDIR" #define PUBDIR "PUBDIR" #define NEWSDIR2 "NEWSDIR" #define TEMPDIR "TEMPDIR" #define MAILSERVICE "MAILSERVICE" #define NODENAME "NODENAME" #define DEVICE "DEVICE" #define SPEED "SPEED" #define PAGESIZE "PAGESIZE" #define TIMEZONE "TIMEZONE" extern char *mailbox; extern char *name; extern char *domain; extern char *maildir; extern char *home; extern char *confdir; extern char *spooldir; extern char *logdir; extern char *pubdir; extern char *tempdir; extern char *mailserv; extern char *nodename; extern char *device; extern char *speed; extern char *newsdir; extern int pagesize; extern char *timeZone; void loadenv(); void mkfilename(); SHAR_EOF if test 1960 -ne "`wc -c genv.h`" then echo shar: error transmitting genv.h '(should have been 1960 characters)' fi echo shar: extracting host.h '(829 characters)' cat << \SHAR_EOF > host.h /* Amiga.h Amiga version */ #include <time.h> #include <errno.h> #include <ctype.h> #ifndef MANX #include <string.h> #include <stdlib.h> #endif #ifndef AMIGA #define AMIGA 1 #endif #define SAME 0 #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #define TFILENAME "tmpfile.%.7d" #define SFILENAME "SEQF" #define SEPCHAR '/' /* path separator */ #define SIGFILE ".signature" /* file containing signature */ #define COPYFILE "mail.sent" /* copy of sent mail */ #define BREAK /* BREAK command is defined in "systems" */ #define HOSTINIT /* name of function used to initialize */ #define FILEMODE(f) #define CALLFILE "C.%s" #define XQTFILE "X.%s" #ifndef MANX #define index strchr #define rindex strrchr #endif #include "genv.h" extern char * fgets(); extern char * index(); extern int debuglevel; SHAR_EOF if test 829 -ne "`wc -c host.h`" then echo shar: error transmitting host.h '(should have been 829 characters)' fi echo shar: extracting lib.c '(2757 characters)' cat << \SHAR_EOF > lib.c /* lib.c */ #include <dos.h> #include <exec/memory.h> #include <proto/exec.h> #include <proto/dos.h> #include <stdio.h> #include "host.h" #ifndef NULL #define NULL 0L #endif char *index(); char *rindex(); MKDIR( path ) char * path; { char * cp = path; if ( *cp == '\0' ) return( 0 ); /* see if we need to make any intermediate directories */ while ( ( cp = index( cp, '/' ) ) != (char *) NULL ) { *cp = '\0'; mkdir( path ); *cp = '/'; cp++; } /* make last dir */ return( mkdir( path ) ); } CHDIR( path ) char * path; { char * cp = path; if ( *cp == '\0' ) return( 0 ); MKDIR( path ); /* change to last directory */ return( chdir( path ) ); } FILE * FOPEN( name, mode, ftype ) char * name; char * mode; char ftype; { char * last; FILE * results; /* are we opening for write or append */ FILEMODE( ftype ); results = fopen( name, mode ); if ( results != (FILE *) NULL || *mode == 'r' ) return( results ); /* are we opening in sub-directory */ last = rindex( name, '/' ); /* lets just verify that all sub-dir's exist */ if ( last != (char *) NULL ) { *last = '\0'; MKDIR( name ); *last = '/'; } /* now try open again */ return( fopen( name, mode )); } int CREAT( name, mode, ftyp ) char * name; int mode; char ftyp; { char * last; int results; /* are we opening for write or append */ FILEMODE( ftyp ); results = creat( name, mode ); if ( results != -1 ) return( results ); /* are we opening in sub-directory */ last = rindex( name, '/' ); /* lets just verify that all sub-dir's exist */ if ( last != (char *) NULL ) { *last = '\0'; MKDIR( name ); *last = '/'; } /* now try open again */ return( creat( name, mode ) ); } extern FILE *logfile; extern int debuglevel; extern int remote; #define MASTER 1 int getargs( line, flds ) char *line; char **flds; { int i = 0; while ( (*line != '\0') && (*line != '\n') ) { if ( isspace(*line) ) { line++; continue; } *flds++ = line; i++; while( (isspace(*line) == 0) && (*line != '\0') ) line++; if (isspace(*line)) *line++ = '\0'; } return(i); } /* Behaves almost like the Lattice dfind function, but dfindOne will not * keep a lock. */ int dfindOne(info, name, attr) struct FILEINFO *info; char *name; int attr; { BPTR lock; struct FILEINFO *tmpInfo; int retVal; if(!(lock = Lock(name, ACCESS_READ))) return(-1); tmpInfo = (struct FILEINFO *) AllocMem(sizeof(*tmpInfo), MEMF_CLEAR); if(retVal = Examine(lock, tmpInfo)) movmem((char *) tmpInfo, (char *) info, sizeof(*tmpInfo)); FreeMem((char *) tmpInfo, sizeof(*tmpInfo)); UnLock(lock); if(retVal && (attr || info->fib_DirEntryType < 0)) return(0); else return(-1); } SHAR_EOF if test 2757 -ne "`wc -c lib.c`" then echo shar: error transmitting lib.c '(should have been 2757 characters)' fi echo shar: extracting lmail.c '(10108 characters)' cat << \SHAR_EOF > lmail.c /* lmail.c copyright (C) 1987 Stuart Lynne Copying and use of this program are controlled by the terms of the Free Software Foundations GNU Emacs General Public License. version 0.1 March 31/1987 description An 822 compatible (hopefully) mail delivery system for pc's. Designed for delivering mail on a pc based system. It will put local mail (ie, not @ or ! in address) into files in the default mail directory. If remote it will put into an outgoing mailbag in the default mail directory. Performs a simple bundling of mail messages into one file with arguments prepended as To: arg header lines. And adds a Message-Lines: header which gives the number of lines in the content part of the message (after the first blank line). pcmail john jack jill@xyz.uucp < afile To: john, jack, jill@xyz.uucp ... ... ... It also adds the from From and Date lines. Subject: lines may be inserted by placing them at the beginning of the message. A Unix version should lock the /usr/mail/mailbag file. environment variables The following evironment variables are used: MAILBOX current user's mailbox, "stuart" NAME current user's name, "Stuart Lynne" DOMAIN domain of this machine, "slynne.mac.van-bc.can" MAILDIR where is mail kept, "mpw:mail" */ #include <dos.h> #include <stdio.h> #include "host.h" char *_TZ = "GMT0"; FILE *FOPEN(); #define FORWARD "Forward to" static FILE *mailfile; static FILE *tempfile; static char buf[BUFSIZ]; static char miscBuf[100]; static char *inFileName; static long int sequence = 0; static long tloc; static char chartime[40]; /* current time in characters */ static char *thetime; static char tfilename[100]; extern char mfilename[]; static char mailsent[100]; static char remotes[BUFSIZ]; static char *uucp = "uucp"; char *fgets(); int fputs(); extern int debuglevel; static char Subject[132] = ""; extern long DOSBase; static char *mcurdir; static char s_mcurdir[128]; /* current directory path (save malloc call) */ char * getcwd(); int chdir(); lmail(argc, argv, inname) int argc; char **argv; char *inname; { int argcount; char **argvec; int i; char timeBuf[40]; if (debuglevel > 5) { fprintf(stderr,"pcmail: argc %d ", argc); argcount = argc; argvec = argv; while (argcount--) fprintf(stderr," \"%s\"", *argvec++); fprintf(stderr,"\n"); time(&tloc); thetime = ctime(&tloc); sprintf(timeBuf,"%.3s, %.2s %.3s %.2s %.8s %s\n", thetime, thetime + 8, thetime + 4, thetime + 22, thetime + 11, timeZone); thetime = timeBuf; fprintf(stderr,"thetime: %s",thetime); } mcurdir = getcwd(s_mcurdir, sizeof(s_mcurdir)); chdir(spooldir); /* get sequence number */ mkfilename(tfilename, confdir, SFILENAME); if (debuglevel > 4) fprintf(stderr,"pcmail: opening %s\n", tfilename); if(tempfile = FOPEN(tfilename,"r", 't')) { fscanf(tempfile,"%ld", &sequence); fclose(tempfile); } else fprintf(stderr,"pcmail: can't find %s file, creating\n", tfilename); /* update sequence number */ if (debuglevel > 5) fprintf(stderr,"pcmail: new sequence # %ld\n", sequence); if(tempfile = FOPEN(tfilename,"w", 't')) { fprintf(tempfile,"%ld\n", (sequence+1)%10000); fclose(tempfile); } if(!(inFileName = inname)) { sprintf(miscBuf, TFILENAME, sequence); mkfilename(tfilename, tempdir, miscBuf); inFileName = tfilename; if (debuglevel > 5) fprintf(stderr,"pcmail: opening %s\n", inFileName); if (!(tempfile = FOPEN(inFileName,"w", 'b'))) { fprintf(stderr,"pcmail: can't open %s\n", inFileName); exit(1); } /* copy stdin to tempfile */ while (i = fread(buf, 1, sizeof(buf), stdin)) { fwrite(buf, i, 1, tempfile); } /* mail compiled with Lattice crashes if we use the following. Why? */ /* buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0; while (fgets(buf, sizeof(buf) - 2, stdin)) { if(buf[0]) fputs(buf, tempfile); } */ } else { if (!(tempfile = FOPEN(inFileName,"a", 'b'))) { fprintf(stdout,"pcmail: can't open %s\n",inFileName); return(0); } } /* append signature */ mkfilename(mfilename, home, SIGFILE); if (debuglevel > 4) fprintf(stderr,"pcmail: opening sigfile %s\n", mfilename); if(mailfile = FOPEN(mfilename,"r", 't')) { fputs("\n---\n", tempfile); buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0; while (fgets(buf, sizeof(buf) - 2, mailfile)) { if(buf[0]) fputs(buf, tempfile); } fclose(mailfile); } fclose(tempfile); /* loop on args, copying to appropriate postbox, * do remote only once * remote checking is done empirically, could be better */ remotes[0] = 0; if (!strcmp(argv[1],"-s")) { argv += 2; argc -= 2; if (argc <= 0) return(-1); strcpy(Subject, *argv); } argcount = argc; argvec = argv; while (--argcount > 0) { argvec++; if (debuglevel > 5) fprintf(stderr,"pcmail: arg# %d %s\n", argcount, *argvec); if (strchr(*argvec, '!') || strchr(*argvec, '@') || strchr(*argvec, '%')) { if (debuglevel > 5) fprintf(stderr,"pcmail: send to remote\n"); /* can we cram one more address on line */ if((strlen(remotes) + strlen(*argvec) + 3) > sizeof(remotes)) { /* dump it then, to bad */ sendone(argc, argv, remotes, TRUE); remotes[0] = 0; } /* add *arvgvec to list of remotes */ strcat(remotes," "); strcat(remotes, *argvec); } else { if (debuglevel > 5) fprintf(stderr,"pcmail: calling sendone %s\n", *argvec); sendone(argc, argv, *argvec, FALSE); } } /* dump remotes if necessary */ if (remotes[0]) sendone(argc, argv, remotes, TRUE); /* mkfilename(mailsent, home, COPYFILE); if (debuglevel > 4) fprintf(stderr,"pcmail: copfile = %s\n", mailsent); sendone(argc, argv, mailsent, FALSE); */ unlink(tfilename); chdir(mcurdir); return(0); } /* sendone copies file plus headers to appropriate postbox NB. we do headers here to allow flexibility later, for example in being able to do bcc, per host service processing etc. */ sendone(argc, argv, address, remote) int argc; char **argv; char *address; int remote; { register char *cp; char icfilename[32]; /* local C. copy file */ char ixfilename[32]; /* local X. xqt file */ char idfilename[32]; /* local D. data file */ char rxfilename[32]; /* remote X. xqt file */ char rdfilename[32]; /* remote D. data file */ char tmfilename[32]; /* temporary storage */ struct FILEINFO info; if (remote) { /* sprintf all required file names */ sprintf(tmfilename,"%c.%.7s%04d", 'C', mailserv, sequence); importpath(icfilename, tmfilename); sprintf(tmfilename,"%c.%.7s%04d", 'D', mailserv, sequence); importpath(idfilename, tmfilename); sprintf(tmfilename,"%c.%.7s%04d", 'D', nodename, sequence); importpath(ixfilename, tmfilename); sprintf(rdfilename,"%c.%.7s%04d", 'D', nodename, sequence); sprintf(rxfilename,"%c.%.7s%04d", 'X', nodename, sequence); } else { /* postbox file name */ if (!strchr(address, SEPCHAR)) mkfilename(idfilename, maildir, address); else strcpy(idfilename, address); } if (debuglevel > 5) fprintf(stderr,"pcmail: sendone: %s\n", idfilename); if (remote == FALSE) { if (debuglevel > 5) fprintf(stderr,"pcmail: sendone: check for remote\n"); /* check for forwarding */ if (!dfindOne(&info, idfilename, 0) && info.fib_Size > 10 && (mailfile = FOPEN(idfilename,"r", 'b'))) { cp = fgets(buf, sizeof(buf), mailfile); fclose(mailfile); if (cp && !strncmp(buf, FORWARD, 10)) { strcpy(buf, buf+11); return(sendone(argc, argv, buf, FALSE)); } } } /* open mailfile */ if (!(mailfile = FOPEN(idfilename,"a", 'b'))) { fprintf(stdout,"pcmail: cannot append to %s\n", idfilename); return(0); } if (debuglevel > 5) fprintf(stderr,"pcmail: append to mailfile\n"); time(&tloc); thetime = ctime(&tloc); sprintf(chartime,"%.3s, %.2s %.3s %.2s %.8s %s", thetime, thetime + 8, thetime + 4, thetime + 22, thetime + 11, timeZone); thetime = chartime; /* and work with our own copy */ fprintf(mailfile,"From %s %s", mailbox, thetime); if (remote) fprintf(mailfile," remote from %s", nodename); fputc('\n', mailfile); fprintf(mailfile,"Received: by %s (pcmail) %s\n", domain, thetime); fprintf(mailfile,"Date: %s\n", thetime); /* add Date:, From: and Message-ID: headers */ fprintf(mailfile,"From: %s <%s@%s>\n", name, mailbox, domain); fprintf(mailfile,"Message-ID: <%ld@%s>\n", sequence, domain); /* add To: headers */ fprintf(mailfile,"To: %s", *++argv); argc--; while (--argc > 0) fprintf(mailfile,", %s", *++argv); fputc('\n', mailfile); if (strlen(Subject)) fprintf(mailfile,"Subject: %s\n", Subject); fputc('\n', mailfile); /* copy spoolfile to postbox file */ if (debuglevel > 4) fprintf(stderr,"pcmail: copy spoolfile %s to %s\n", inFileName, idfilename); if (!(tempfile = FOPEN(inFileName,"r", 'b'))) { fprintf(stdout,"pcmail: can't open %s\n", inFileName); return(0); } buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0; while (fgets(buf, sizeof(buf) - 2, tempfile)) { if (!strncmp(buf,"From ", 5)) fputc('>', mailfile); if(buf[0]) fputs(buf, mailfile); } /* close files */ fclose(mailfile); fclose(tempfile); /* all done unless going to remote via uucp */ /* must create the job control files */ if (remote) { /* create remote X xqt file */ if(!(mailfile = FOPEN(ixfilename,"w", 'b'))) { fprintf(stdout,"pcmail: cannot open %s\n", ixfilename); return(0); } fprintf(mailfile,"U %s %s\n", uucp, nodename); fprintf(mailfile,"F %s\n", rdfilename); fprintf(mailfile,"I %s\n", rdfilename); fprintf(mailfile,"C rmail %s\n", address); fclose(mailfile); /* create local C copy file */ if(!(mailfile = FOPEN(icfilename,"w", 't'))) { fprintf(stdout,"pcmail: cannot open %s\n", icfilename); return(0); } fprintf(mailfile,"S %s %s %s - %s 0666 %s\n", idfilename, rdfilename, uucp, idfilename, uucp); fprintf(mailfile,"S %s %s %s - %s 0666 %s\n", ixfilename, rxfilename, uucp, ixfilename, uucp); fclose(mailfile); } return(1); } SHAR_EOF if test 10108 -ne "`wc -c lmail.c`" then echo shar: error transmitting lmail.c '(should have been 10108 characters)' fi echo shar: extracting mail.c '(12248 characters)' cat << \SHAR_EOF > mail.c /* * mail.c */ /* The users refers to the letters with a number between 1 and numberOfLetters, * message 1 being the most recent. * * The messages are refered to internally with a number between 0 and * numberOfLetters - 1, with message numberOfLetters - 1 being the most recent. */ #include <dos.h> #include <stdio.h> #include "host.h" #define VERSION "1.4 Camelot" FILE *FOPEN(); FILE *freopen(); /* int debuglevel = 1; */ #define LSIZE 256 #define SHORTLSIZE 132 static char line[LSIZE]; static char resp[LSIZE]; char mfilename[SHORTLSIZE]; struct ldesc { int delete; /* status of this message */ long adr; /* address of From line */ long date; /* address of Date: line */ long subject; /* address of Subject: line */ long from; /* address of From: line */ long size; /* number of lines */ struct ldesc *suc; /* link to previous letter */ struct ldesc *prev; /* link to next letter */ }; static struct ldesc *newLetter(struct ldesc *); static struct ldesc *letterN(int); static struct ldesc letterHead; static struct ldesc *curLetter = NULL; static int numberOfLetters = 0; static char thefilename[128]; static char tmailbox[64]; static char tmailbag[64]; static FILE *fmailbox; static FILE *rmailbox; static FILE *fmailbag; static int error = 0; static int printonly; static int PageCount = 0; mailmain(argc, argv) char **argv; { /* HOSTINIT; loadenv(); */ letterHead.prev = letterHead.suc = &letterHead; letterHead.adr = 0; mkfilename( tmailbox, tempdir, "mailbox"); mkfilename( tmailbag, tempdir, "mailbag"); unlink( tmailbox ); if ( mailbox == (char *)NULL ) mailbox = "???"; if (argc > 1 && !strncmp(argv[1],"-d", 2)) { debuglevel = atoi(argv[1] + 2); argc--; argv++; } if ( argc == 1 || ( argv[1][0] == '-' ) && ( argv[1][1] != 's' )) showmail(argc, argv ); else lmail(argc, argv, NULL ); finis(); } finis() { if ( fmailbag != (FILE *)NULL) fclose( fmailbag ); unlink( tmailbox ); unlink( tmailbag ); return( error ); } /* sendmail send message n to "line" Todo: we should supply a Subject line with the -s switch. */ sendmail( n, line ) { char *argv[50]; int argc; /* open a temporary file */ fmailbag = FOPEN( tmailbag, "w", 'b' ); copymsg(n, fmailbag, FALSE); fclose( fmailbag ); argc = getargs( line, argv ); lmail( argc, argv, tmailbag ); /* get rid of mailbag */ unlink( tmailbag ); } static userToInternal( i ) { return( numberOfLetters - i ); } static internalToUser( i ) { return( numberOfLetters - i ); } showmail(argc, argv) char **argv; { int i, j; char *p; long nextadr; struct ldesc *letter; struct FILEINFO info; /* get mailbox file name */ mkfilename( mfilename, maildir, mailbox ); /* parse arg's */ for (; argc > 1 && argv[1][0] == '-'; argv++, argc--) { switch(argv[1][1]) { case 'f': if ( argc >= 3) { if ( argv[2][0] == '=' ) mkfilename( mfilename, maildir, &argv[2][1] ); else strcpy( mfilename, argv[2] ); argv++; argc--; } else { fprintf(stderr,"Usage: mail -f filename\n"); finis(); } break; case 'p': printonly++; break; default: fprintf(stderr, "mail: unknown option %c\n", argv[1][1]); finis(); } } /* open real mailbox file */ if (dfindOne(&info, mfilename, 0) || !info.fib_Size) { fprintf( stdout, "No mail in %s.\n", mfilename ); return; } if (!(rmailbox = FOPEN( mfilename, "r", 'b' ))) { fprintf(stdout,"Unable to open %s.\n", mfilename); return; } /* open up tmp mailbox file */ if (( fmailbox = FOPEN( tmailbox, "w", 'b' )) == (FILE *)NULL ) { fprintf( stderr, "mail: cannot open %s for writing\n", tmailbox ); finis(); } /* copy real mailbox file to tmp mailbox file */ numberOfLetters = 0 ; nextadr = 0; line[sizeof(line) - 2] = '\n'; line[sizeof(line) - 1] = 0; while ( fgets(line, sizeof(line) - 2, rmailbox ) != (char *)NULL) { if(line[0]) fputs( line, fmailbox ); if ( strncmp( line, "From ", 5 ) == SAME ) { letter = newLetter(NULL); letter->from = letter->subject = letter->date = -1L; letter->adr = nextadr; letter->delete = FALSE; letter->size = 0L; }else if ( strncmp( line, "Date: ", 6 ) == SAME ) letter->date = nextadr; else if ( strncmp( line, "From: ", 6 ) == SAME ) letter->from = nextadr; else if ( strncmp( line, "Subject: ", 9 ) == SAME ) letter->subject = nextadr; letter->size += 1L; nextadr += strlen( line ); } letter->suc->adr = nextadr; /* close mailbox files */ fclose( rmailbox ); fclose( fmailbox ); fmailbox = FOPEN( tmailbox, "r", 'b' ); if ( printonly ) { j = numberOfLetters; while ( j > 0 ) pager( --j ); return; } printsub( -1 ); resp[sizeof(resp) - 2] = '\n'; resp[sizeof(resp) - 1] = 0; j = 1; while ( TRUE ) { j = min(numberOfLetters, max(1, j)); fprintf( stdout, "%d ? ", j ); if ( fgets( resp, sizeof(resp) - 2, stdin) == (char *)NULL ) break; switch ( resp[0] ) { default: fprintf(stderr, "mail %s: usage\n", VERSION); case '?': fprintf( stderr, "q\tquit\n" ); fprintf( stderr, "x\texit\tmailbox restored\n" ); fprintf( stderr, "p\tprint message\n" ); fprintf( stderr, "s [file] save message to a file (default =mbox)\n" ); fprintf( stderr, "w [file] save message to a file (default =mbox) without header\n" ); fprintf( stderr, "-^\tprint previous message\n" ); fprintf( stderr, "d\tdelete current message\n" ); fprintf( stderr, "u\tundelete current message\n" ); fprintf( stderr, "+n\tprint next message\n" ); fprintf( stderr, "h\tprint headers\n" ); fprintf( stderr, "H\tprint current header\n" ); fprintf( stderr, "f user\tforward current message to user\n" ); fprintf( stderr, "m user\tmail a message to user\n" ); fprintf( stderr, "[g] num\tset current message\n" ); break; case '+': case 'n': if(++j <= numberOfLetters) pager( userToInternal(j) ); break; case 'g': j = atoi( resp+2 ); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': j = atoi( resp ); break; case 'x': if(j > 0) { for(i = 0; i < numberOfLetters; i++) letterN(i)->delete = FALSE; } case 'q': goto donep; case '\n': case 'p': if(j > 0) pager( userToInternal(j) ); break; case '^': case '-': if(--j > 0) pager( userToInternal(j) ); break; case 'y': case 'w': case 's': if(j < 1) break; if (strlen(resp) <= 2) { strcpy(resp + 1," =mbox"); } if (resp[1] != ' ' || !(p = strtok(resp + 1," \t\n"))) { fprintf(stderr, "bad filename\n"); continue; } if ( *p == '=' && strlen(p) > 1) mkfilename( thefilename, maildir, p + 1 ); else strcpy( thefilename, p ); fprintf(stderr,"Appending to %s\n", thefilename ); if (!(fmailbag = FOPEN(thefilename, "a", 't'))) { fprintf( stderr, "mail: cannot append to %s\n", thefilename ); continue; } copymsg( userToInternal(j), fmailbag, resp[0]=='w' ); fclose( fmailbag ); letterN(userToInternal(j))->delete = TRUE; j++; break; case 'm': fprintf( stderr,"mail command not implemented yet.\n" ); break; case 'f': if(j < 1) break; if (resp[1] != ' ') { printf( "invalid command\n" ); continue; } sendmail( userToInternal(j), resp ); break; case 'd': if(j < 1) break; letterN(userToInternal(j))->delete = TRUE; j++; if (resp[1] == 'q') goto donep; break; case 'u': if(j < 1) break; letterN(userToInternal(j))->delete = FALSE; j++; if (resp[1] == 'q') goto donep; break; case 'h': printsub( -1 ); break; case 'H': if(j > 0) printsub( userToInternal(j) ); break; } } donep: for(i = 0; i < numberOfLetters; i++) if(letterN(i)->delete) { copyback(); break; } } readaline( adr, line ) long adr; char *line; { char buf[LSIZE]; char *cp; buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0; *line = '\0'; if ( adr != -1L && !fseek( fmailbox, adr, 0 ) && fgets( buf, sizeof(buf) - 2, fmailbox )) strcpy( line, buf ); if ((cp = index( line, '\n' ))) *cp = '\0'; } /* returnaddress() { readaline( lp->from, line ); if ( ( i = index( line, '<' )) != 0 && ( k = index( line, '>')) != 0 && ( k > i ) ) { k -= i; strncpy( from, line[i], k ); from[k] = '\0'; } else { } } */ printsub( internalIndex ) int internalIndex; { struct ldesc *ld; int j; char from[LSIZE], subject[LSIZE], date[SHORTLSIZE], line[LSIZE]; int k, mink, maxk; pagereset(); if ( internalIndex == -1 ) { maxk = numberOfLetters -1; mink = 0; } else maxk = mink = internalIndex; for ( k = maxk ; k >= mink ; k-- ) { j = internalToUser( k ); ld = letterN(k); (void)strcpy(from, "unknown"); /* default to "unknown" */ readaline( ld->from, line ); if ( strlen( line ) > 5 ) { /* Assume From: mailbox@site.domain */ /* get first usable stuff after From: */ strcpy(from, line + 5); } /* Date: Wed May 13 23:59:53 1987 */ *date = '\0'; /* default date to null */ readaline( ld->date, date ); if ( strlen( date ) > 5 ) { sscanf( date + 5, "%*s %s %s", line, subject ); sprintf( date, "%s %s", line, subject ); } strcpy( subject, "--- no subject ---" ); readaline( ld->subject, line ); if ( strlen( line ) > 8 ) { strcpy( subject, line + 8); } date[6] = '\0'; sprintf( line, "%c%3d %6s (%6d) %s\n %s\n", ld->delete ? 'D' : ' ', j, date, ld->size, from, subject ); if ( pageline( line ) == TRUE ) break; } } copyback() { register i; if (!(fmailbag = FOPEN( mfilename, "w", 'b' ))) { fprintf (stderr, "mail: can't rewrite %s\n", thefilename ); finis(); } for ( i = 0; i < numberOfLetters; i++ ) if ( letterN(i)->delete == FALSE ) { copymsg( i, fmailbag, FALSE ); } fclose (fmailbag ); } /* copy a message if noheaders true, don't copy header lines */ copymsg( n, f, noheaders ) FILE *f; { long bytes; char buf[BUFSIZ]; struct ldesc *ld; ld = letterN(n); fseek( fmailbox, ld->adr, 0 ); bytes = ld->suc->adr - ld->adr; buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0; while ( noheaders && bytes > 0 && fgets( buf, sizeof(buf) - 2, fmailbox )) { bytes -= strlen( buf ); if ( strcmp( buf, "\n") == SAME ) { noheaders = FALSE; fputs( buf, f ); } } bytes = ld->suc->adr - ftell(fmailbox); while(bytes > 0 && fread(buf, min(bytes, sizeof(buf)), 1, fmailbox) == 1) { if(fwrite(buf, min(bytes, sizeof(buf)), 1, f) != 1) { fprintf(stderr,"write failed\n"); return; } bytes -= min(bytes, sizeof(buf)); } } pager(n) { long bytes; char buf[LSIZE]; struct ldesc *ld; ld = letterN(n); fseek( fmailbox, ld->adr, 0 ); bytes = ld->suc->adr - ld->adr; pagereset(); buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0; while ( bytes > 0 && fgets( buf, sizeof(buf) - 2, fmailbox )) { bytes -= strlen( buf ); if ( buf[0] && pageline( buf ) == TRUE ) break; } pageline( "\n" ); } pagereset() { PageCount = 0; } pageline( s ) char * s; { char c; fputs( s, stdout ); if ( ++PageCount > pagesize ) { PageCount = 0; fflush(stdout); c = get_one(); switch( c ) { case 'q': case 'Q': case '\003': case 'x': case 'X': return( TRUE ); } } return( FALSE ); } /* Allocate and insert a new ldesc after previous */ static struct ldesc *newLetter(previous) register struct ldesc *previous; { register struct ldesc *tmpldesc; if(!(tmpldesc = (struct ldesc *) calloc(1, sizeof(*tmpldesc)))) { fprintf(stderr,"Out of memory\n"); exit(1); } if(!previous) { previous = letterHead.prev; } tmpldesc->prev = previous; tmpldesc->suc = previous->suc; previous->suc->prev = tmpldesc; previous->suc = tmpldesc; numberOfLetters++; return(tmpldesc); } /* return reference to letter n */ static struct ldesc *letterN(n) int n; { register struct ldesc *lp = letterHead.suc; if(n < 0 || n >= numberOfLetters) { fprintf(stderr,"letterN: letter %n does not exist\n"); } while(n--) lp = lp->suc; return(lp); } SHAR_EOF if test 12248 -ne "`wc -c mail.c`" then echo shar: error transmitting mail.c '(should have been 12248 characters)' fi echo shar: extracting mailhost.c '(1160 characters)' cat << \SHAR_EOF > mailhost.c /* mailhost.c */ #include <stdio.h> #include <setjmp.h> #include "host.h" static char *curdir; char * getcwd(); int chdir(); int debuglevel = 0; /* debuginglevel */ jmp_buf dcpexit; main( argc, argv ) int argc; char *argv[]; { int returnCode = 0; char curdirBuf[100]; /* Amiga specific prolog */ loadenv(); curdir = getcwd( curdirBuf, sizeof(curdirBuf) ); /* setup longjmp for error exit's */ if ( setjmp( dcpexit ) == 0 ) { mailmain( argc, argv ); } /* Amiga specific epilog */ exitenv(); chdir( curdir ); exit( returnCode ); } /* canonical name conversion routines importpath canonical -> host exportpath host -> canonical host your local pathname format canonical unix style */ importpath( host, canon ) char * host; char * canon; { extern char *pubdir; *host = '\0'; if ( *canon == '~' ) { if ( canon[1] == '/' ) strcpy( host, pubdir ); else { strcpy( host, home ); strcat( host, "/" ); } } strcat( host, canon ); if ( *host == '/' ) *host = ':'; } exportpath( canon, host ) char * host; char * canon; { strcpy( canon, host ); if ( *canon == ':' ) *canon = '/'; } SHAR_EOF if test 1160 -ne "`wc -c mailhost.c`" then echo shar: error transmitting mailhost.c '(should have been 1160 characters)' fi echo shar: extracting mlib.c '(591 characters)' cat << \SHAR_EOF > mlib.c /* lib.c Amiga library Things to do in uu host serial I/O directory stuff opendir, readdir, closedir prolog and epilog system call */ #include <stdio.h> #include "host.h" #ifdef MANX #include <sgtty.h> int get_one() { char c; struct sgttyb stty, sttyo; ioctl( 0, TIOCGETP, &stty ); sttyo = stty; stty.sg_flags |= RAW; /* stty.sg_flags &= ~ ECHO; */ ioctl( 0, TIOCSETP, &stty ); c = fgetc( stdin ); ioctl( 0, TIOCSETP, &sttyo ); return( c ); } #else int get_one() { int c; raw(stdin); c = fgetc(stdin); cooked(stdin); return( c ); } #endif SHAR_EOF if test 591 -ne "`wc -c mlib.c`" then echo shar: error transmitting mlib.c '(should have been 591 characters)' fi echo shar: extracting ndir.c '(2157 characters)' cat << \SHAR_EOF > ndir.c #include "ndir.h" #include <exec/memory.h> #ifdef MANX #include <functions.h> #endif #ifdef TEST #include <stdio.h> #endif /* * support for Berkeley directory reading routine on a V7 file system */ extern char *malloc(); /* * open a directory. */ DIR * opendir(name) char *name; { register DIR *dirp; struct Lock *lock; #ifdef TEST fprintf( stderr, "opendir: Opening \"%s\"\n", name ); #endif if ( ( lock = Lock( name, ACCESS_READ )) == NULL ) { #ifdef TEST fprintf( stderr, "opendir: Can't open.\n" ); #endif return NULL; } if ( (dirp = (DIR *)malloc(sizeof(DIR))) == NULL ) { #ifdef TEST fprintf( stderr, "opendir: couldn't malloc %d\n",sizeof(DIR)); #endif UnLock( lock ); return NULL; } if ( !Examine( lock, &dirp->fib) ) { #ifdef TEST fprintf( stderr, "opendir: Couldn't Examine directory\n" ); #endif free( dirp ); UnLock( lock ); } dirp->lock = lock; #ifdef TEST fprintf( stderr, "opendir: Sucessful\n" ); #endif return dirp; } /* * get next entry in a directory. */ struct direct * readdir(dirp) register DIR *dirp; { static struct direct dir; while ( ExNext( dirp->lock, &dirp->fib ) ) { if ( dirp->fib.fib_DirEntryType <= 0 ) { dir.d_ino = 0; strcpy( dir.d_name, dirp->fib.fib_FileName ); #ifdef TEST fprintf( stderr, "readdir: OK \"%s\"\n", dir.d_name); #endif dir.d_namlen = strlen(dir.d_name); dir.d_reclen = DIRSIZ(&dir); return (&dir); } } #ifdef TEST fprintf( stderr, "readdir: No More Entries.\n" ); #endif strcpy( dir.d_name, "" ); return NULL; } /* * close a directory. */ void closedir(dirp) register DIR *dirp; { UnLock( dirp->lock ); free((char *)dirp); } #ifdef TEST #ifdef MANX #include <errno.h> #endif main() { char command[100]; struct DIR *dirp; struct direct *dp; while(gets(command) != NULL) { fprintf( stderr, "test: %s\n", command ); if ((dirp = opendir( command )) == NULL ) { fprintf( stderr, "couldn't open dir %s\n", command ); } else { while ((dp = readdir(dirp)) != NULL) fprintf( stderr, "%s", dp->d_name ); closedir( dirp ); } } } #endif SHAR_EOF if test 2157 -ne "`wc -c ndir.c`" then echo shar: error transmitting ndir.c '(should have been 2157 characters)' fi echo shar: extracting ndir.h '(1242 characters)' cat << \SHAR_EOF > ndir.h /* @(#)ndir.h 1.4 4/16/85 */ #include <libraries/dos.h> #ifndef MANX #include <proto/dos.h> #endif #ifndef DEV_BSIZE #define DEV_BSIZE 512 #endif #define DIRBLKSIZ DEV_BSIZE #define MAXNAMLEN 255 struct direct { long d_ino; /* inode number of entry */ short d_reclen; /* length of this record */ short d_namlen; /* length of string in d_name */ char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ }; /* * The DIRSIZ macro gives the minimum record length which will hold * the directory entry. This requires the amount of space in struct direct * without the d_name field, plus enough space for the name with a terminating * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. */ #ifdef DIRSIZ #undef DIRSIZ #endif /* DIRSIZ */ #define DIRSIZ(dp) \ ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) /* * Definitions for library routines operating on directories. */ /* typedef struct _dirdesc { int dd_fd; long dd_loc; long dd_size; char dd_buf[DIRBLKSIZ]; } DIR; */ typedef struct _dirdesc { struct Lock *lock; struct FileInfoBlock fib; } DIR; #ifndef NULL #define NULL 0L #endif extern DIR *opendir(); extern struct direct *readdir(); extern void closedir(); SHAR_EOF if test 1242 -ne "`wc -c ndir.h`" then echo shar: error transmitting ndir.h '(should have been 1242 characters)' fi echo shar: extracting pccp.c '(13168 characters)' cat << \SHAR_EOF > pccp.c /* pccp - copy files between systems * * SYNOPSIS * pccp [-C] [-r] [-v] [-xd] fromfile... tofile * * DESCRIPTION * pccp is a partial implementation of the UNIX uucp command. The business * of pccp is to translate user level copy commands into command files * understood by uupc. pccp may also start uupc on these files. * * A file name may be a local pathname or of the form * system!pathname * where system is one of the sites listed in the uupc systems file. * If the remote pathname contains wild cards (? * and so on) these * will be expanded on the remote system. This program does no wildcard * expansion. The caller, the local uupc or the remote uupc have to decide * about wildcards. * * A pathname is one of the following: * a complete pathname * * a pathname preceded by ~user/. ~user will be expanded to * the home directory of the user on the appropriate system. * The name ~/ will be expanded to the public uucp directory. * * anything else will be prependded with the path of the current * directory. * * OPTIONS * -C Copy the outgoing files to the spool directory. This lets * you remove the source file without affecting the file transfer. * The default action is to transfer directly from the source * file. * * -r Do not start the transfer. Just queue the job. * * -v Verbose. Will at least display the version. * * -xd This option will be passed on to uupc. It specifies the * the debug level. d is a digit between zero and nine. */ /* The code for finding an executable is taken from the cc program written * by Fred Fish. There are restrictions on the use of that code. See * the cc program on Fish disk 28 for more info. * * As regards all other code in this program: use it any way you want, * I put no restrictions on it. * * 6-FEB-88 Johan Widen * USENET: jw@sics.se */ #include <dos.h> #include <stdio.h> #include "host.h" #define VERSION "1.0 6-FEB-88" #define PROGRAM "pccp" /* * Set list of places to search for various executables, libraries, etc. * Searched in order, first match wins, null string is current directory. * Note that these names are used as prefixes exactly as given, so * device names must end in ':' and directory names must end in '/'. * */ static char *Devices[] = { "", "vd0:", "ram:", "df0:", NULL }; static char *BinDirs[] = { "", "c:", "df0:c/", NULL }; static void usage(); static void pathArgUsage(); static int checkLocalRemote(int, char**); static int sequenceNumber(int); static char **copyToSpool(int, char**, int); static void createCommandFile(int, char **, char**, int, int, int, char *); static void removeSpoolFiles(int, char**); static int expandFileName(char *, char *); static char *checkAlloc(int); static char *locate(char *, char **); static int readable(char *); static int runCommand(char *); int debuglevel = 0; main(argc, argv) int argc; char **argv; { int copyFlag = 0; int queueOnlyFlag = 0; int verboseFlag = 0; int localToRemote; char **pathArgs; int sequence; char remoteHost[80]; char executeBuf[80]; for(argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) { switch(argv[0][1]) { case 'C': copyFlag = 1; break; case 'r': queueOnlyFlag = 1; break; case 'v': verboseFlag = 1; break; case 'x': if(isdigit(argv[0][2])) debuglevel = argv[0][2] - '0'; else usage(); break; default: usage(); } } if(argc < 2) usage(); loadenv(); if(verboseFlag) fprintf(stderr,"%s\n", VERSION); if((localToRemote = checkLocalRemote(argc, argv)) < 0) exit(1); pathArgs = argv; if(localToRemote && copyFlag) { sequence = sequenceNumber(argc - 1); pathArgs = copyToSpool(argc, pathArgs, sequence); } else { sequence = sequenceNumber(1); } createCommandFile(argc, argv, pathArgs, sequence, localToRemote, copyFlag, remoteHost); if(queueOnlyFlag) exit(0); sprintf(executeBuf,"%s -r1 -s%s -x%d", locate("uupc", BinDirs), remoteHost, debuglevel); exit(runCommand(executeBuf)); } static void usage() { fprintf(stderr,"%s version %s\n", PROGRAM, VERSION); fprintf(stderr,"Usage: %s [-C] [-r] [-v] [-xd] fromfiles... tofile\n", PROGRAM); fprintf(stderr,"-C means copy to spool before sending.\n"); fprintf(stderr,"-r means queue only, do not start uupc.\n"); fprintf(stderr,"-v means verbose.\n"); fprintf(stderr,"-xd '0'<= d <= '9' set debug level for uupc.\n"); fprintf(stderr,"file may be a local pathname or system!pathname\n"); fprintf(stderr, "pathname may be a full path or begin with ~user (\"~/\" means public uucp\n"); fprintf(stderr, "directory). Other pathnames get prepended with current directory\n"); exit(1); } /* checkLocalRemote(argc, argv) * int argc; Number of pathnames. * char **argv; Pathnames. * * Description: we currently require that one of the following holds * 1. The last argument is a remote pathname. All other arguments are * local pathnames. * * 2. There are only two arguments. The first argument is a remote path- * name and the last argument is a local pathname. * * Return 1 if case 1 holds. Return 0 if case 2 holds. Otherwise return -1. */ static int checkLocalRemote(argc, argv) register int argc; register char **argv; { register int i; if(argc == 2 && strchr(argv[0],'!')) { if(strchr(argv[1],'!')) { pathArgUsage(); return(-1); } return(0); } /* first argument is a local pathname */ if(!strchr(argv[argc - 1],'!')) { pathArgUsage(); return(-1); } for(i = 1; i < argc - 1; i++) if(strchr(argv[i],'!')) { pathArgUsage(); return(-1); } return(1); } static void pathArgUsage() { fprintf(stderr,"%s: pathname arguments must be either:\n", PROGRAM); fprintf(stderr,"\tremote!path localpath\n or\n"); fprintf(stderr,"\tlocalpath... remote!path\n"); } /* int sequenceNumber(inc) * int inc; Reserve this many numbers; * * Description: The filenames in the spool area are made unique by including * a sequence number in them. Get the next sequence number. Update the sequence * number. */ static int sequenceNumber(inc) int inc; { char sequencePath[256]; FILE *sequenceFile; int sequence; mkfilename(sequencePath, confdir, SFILENAME); if(sequenceFile = fopen(sequencePath,"r")) { fscanf(sequenceFile,"%ld", &sequence); fclose(sequenceFile); } else sequence = 0; if(!(sequenceFile = fopen(sequencePath,"w"))) { fprintf(stderr,"%s: unable to create %s\n", PROGRAM, sequencePath); exit(3); } fprintf(sequenceFile,"%04d\n", (sequence + inc)%10000); fclose(sequenceFile); return(sequence); } /* char **copyToSpool(argc, oldPathArgs, sequence) * int argc; Number of pathnames. * char **oldPathArgs; Files to copy to spool area. * int sequence; File name sequence number. * * Description: copy the first argc - 1 files to the spool area. The spool * files are given unique names. The new names are returned together with * the original last argument. */ static char ** copyToSpool(argc, oldPathArgs, sequence) int argc; register char **oldPathArgs; int sequence; { register char **newPathArgs; char spoolName[256]; char dFileName[80]; char buf[BUFSIZ]; register int i; int bytesRead; FILE *inFile, *outFile; newPathArgs = (char **) checkAlloc(argc*sizeof(char **)); newPathArgs[argc - 1] = oldPathArgs[argc - 1]; for(i = 0; i < argc - 1; i++) { sprintf(dFileName,"D.%.7s%04d", nodename, sequence++); mkfilename(spoolName, spooldir, dFileName); newPathArgs[i] = checkAlloc(strlen(spoolName) + 1); strcpy(newPathArgs[i], spoolName); } for(i = 0; i < argc - 1; i++) { if(!expandFileName(oldPathArgs[i], spoolName)) { removeSpoolFiles(i, newPathArgs); exit(4); } if(!(inFile = fopen(spoolName,"r"))) { fprintf(stderr,"%s: unable to open %s\n", PROGRAM, spoolName); removeSpoolFiles(i, newPathArgs); exit(5); } if(!(outFile = fopen(newPathArgs[i],"w"))) { fprintf(stderr,"%s: unable to open %s\n", PROGRAM, newPathArgs[i]); removeSpoolFiles(i, newPathArgs); exit(6); } while (bytesRead = fread(buf, 1, sizeof(buf), inFile)) { if(fwrite(buf, bytesRead, 1, outFile) != 1) { fclose(outFile); fprintf(stderr,"%s: write error when copying %s to %s\n", PROGRAM, spoolName, newPathArgs[i]); removeSpoolFiles(i + 1, newPathArgs); exit(7); } } fclose(inFile); fclose(outFile); } return(newPathArgs); } static void createCommandFile(argc, oldPathArgs, pathArgs, sequence, localToRemote, copyFlag, remoteHost) int argc; char **oldPathArgs; char **pathArgs; int sequence; int localToRemote; int copyFlag; char *remoteHost; { char buf[BUFSIZ]; char expandedPath[256]; char cFilePath[256]; char cFileName[80]; FILE *cFile; char *cp, *remoteFile; register int i; int spoolDirLen; int length; if(localToRemote) cp = pathArgs[argc - 1]; else cp = pathArgs[0]; remoteFile = strchr(cp,'!') + 1; strncpy(remoteHost, cp, remoteFile - cp - 1); remoteHost[remoteFile - cp - 1] = 0; sprintf(cFileName,"C.%.7s%04d", remoteHost, sequence); mkfilename(cFilePath, spooldir, cFileName); if(!(cFile = fopen(cFilePath,"w"))) { fprintf(stderr,"%s: unable to open %s\n", PROGRAM, cFilePath); if(localToRemote && copyFlag) removeSpoolFiles(argc - 1, pathArgs); exit(8); } spoolDirLen = strlen(spooldir); if(localToRemote) { for(i = 0; i < argc - 1; i++) { if(!expandFileName(oldPathArgs[i], expandedPath)) { fclose(cFile); unlink(cFilePath); exit(8); } if(copyFlag) { sprintf(buf,"S %s %s uucp - %s 0666\n", expandedPath, remoteFile, pathArgs[i] + spoolDirLen + 1); } else { sprintf(buf,"S %s %s uucp - %s 0666\n", expandedPath, remoteFile, expandedPath); } /* The first arg should really be the original file but uupc */ /* does not handle this yet. */ length = strlen(buf); if(1 != fwrite(buf, length, 1, cFile)) { fprintf(stderr,"%s: write error on %s\n", PROGRAM, cFilePath); if(copyFlag) removeSpoolFiles(argc - 1, pathArgs); fclose(cFile); unlink(cFilePath); exit(9); } } } else { if(!expandFileName(pathArgs[1], expandedPath)) { fclose(cFile); unlink(cFilePath); exit(10); } sprintf(buf,"R %s %s uucp\n", remoteFile, expandedPath); length = strlen(buf); if(1 != fwrite(buf, length, 1, cFile)) { fprintf(stderr,"%s: write error on %s\n", PROGRAM, cFilePath); fclose(cFile); unlink(cFilePath); exit(11); } } fclose(cFile); } static void removeSpoolFiles(count, newPathArgs) int count; register char **newPathArgs; { register int i; for(i = 0; i < count; i++) { unlink(newPathArgs[i]); } } static int expandFileName(from, to) register char *from; register char *to; { char *cp; char user[50]; if(from[0] == '/' || from[0] == ':') { strcpy(to, from); to[0] = ':'; } else if(from[0] == '~') { if(!(cp = strchr(from,'/'))) { strcat(from, "/"); cp = strchr(from,'/'); } if((cp - from) > 1) { strncpy(user, from + 1, cp - from - 1); user[cp - from - 1] = 0; if(strcmp(user, mailbox)) { fprintf(stderr,"%s: unknown user %s\n", PROGRAM, user); return(0); } mkfilename(to, home, cp + 1); } else { mkfilename(to, pubdir, cp + 1); } } else { getcwd(to, 256); cp = to + strlen(to) - 1; if(*cp != '/' && *cp != ':') { strcpy(cp + 1, "/"); } strcat(cp, from); } return(1); } static char * checkAlloc(size) int size; { char *cp; if(!(cp = malloc(size))) { fprintf(stderr,"%s: out of memory\n", PROGRAM); exit(2); } return(cp); } /* * Look through the list of paths pointed to by "vec" until we find * a file with name given pointed to by "namep". If none is found, * the name pointed to by namep is returned. */ static char *locate(namep, vec) char *namep; char **vec; { static char namebuf[64]; while (*vec != NULL) { sprintf(namebuf, "%s%s", *vec, namep); if (readable(namebuf)) { namep = namebuf; break; } vec++; } return(namep); } /* * Check to see if the file exists and is readable. */ static int readable(name) char *name; { register int status = 0; register int fildes; fildes = Lock(name, ACCESS_READ); if (fildes != 0) { UnLock (fildes); status = 1; } return(status); } static int runCommand(command) char *command; { int status; register char *cp; char *prog, *args; struct ProcID child; /* This code assumes that there is at least one argument */ prog = cp = command; while(*cp && *cp != ' ') cp++; *cp++ = 0; while(*cp == ' ') cp++; args = cp; if(forkl(prog, prog, args, NULL, NULL, &child) == -1) { fprintf(stderr,"%s: unable to execute %s\n", PROGRAM, prog); status = 1; } else { status = wait(&child); } return(status); } SHAR_EOF if test 13168 -ne "`wc -c pccp.c`" then echo shar: error transmitting pccp.c '(should have been 13168 characters)' fi # End of shell archive exit 0
ain@j.cc.purdue.edu (Patrick White) (03/22/88)
Program Name: uupc version 1.1 (part 3 of 3) Submitted By: Johan Widen <jw@sics.se> Summary: Implements uucp for the Amiga -- allows your Amiga to become a uupc site for mail (and news?). Poster Boy: Pat White (ain@j.cc.purdue.edu) Uncompiled. NOTES: Converted the origional zoo to shars so docs, binaries & sources could be separated. I'm pretty sure this would allow one to receive news, but I remember something in the docs about it not having been tested from when I was quickly scanning them... so I'm not too sure on this. Rob has been playing with it for a while and says it works. -- Pat White (co-moderator comp.sources/binaries.amiga) UUCP: j.cc.purdue.edu!ain BITNET: PATWHITE@PURCCVM PHONE: (317) 743-8421 U.S. Mail: 320 Brown St. apt. 406, West Lafayette, IN 47906 ======================================== # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # raw.c # rmail.c # sendpacket.c # serial.c # sio.c # sleep.c # timer.c # ulib.c # uuhost.c # This archive created: Sat Mar 19 01:42:21 1988 # By: Patrick White (PUCC Land, USA) echo shar: extracting raw.c '(2393 characters)' cat << \SHAR_EOF > raw.c /* * raw.c * * This is a routine for setting a given stream to raw or cooked mode. * This is useful when you are using Lattice C to produce programs that * want to read single characters with the "getch()" or "fgetc" call. * * Written : 18-Jun-87 By Chuck McManis. * If you use it I would appreciate credit for it somewhere. */ #include <exec/types.h> #include <libraries/dos.h> #include <libraries/dosextens.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <ios1.h> #include <error.h> #include <proto/exec.h> #include <proto/dos.h> /* New Packet in 1.2 */ /* #define ACTION_SCREEN_MODE 994L */ extern int errno; /* The error variable */ /* * Function raw() - Convert the specified file pointer to 'raw' mode. This * only works on TTY's and essentially keeps DOS from translating keys for * you, also (BIG WIN) it means getch() will return immediately rather than * wait for a return. You lose editing features though. */ long raw(fp) FILE *fp; { struct MsgPort *mp; /* The File Handle message port */ struct FileHandle *afh; struct UFB *ufb; long Arg[1],res; ufb = (struct UFB *) chkufb(fileno(fp)); /* Step one, get the file handle */ afh = (struct FileHandle *)(ufb->ufbfh); if (!IsInteractive(afh)) { /* Step two, check to see if it's a console */ errno = ENOTTY; return(-1); } /* Step three, get it's message port. */ mp = ((struct FileHandle *)(BADDR(afh)))->fh_Type; Arg[0] = -1L; res = SendPacket(mp,ACTION_SCREEN_MODE,Arg,1); /* Put it in RAW: mode */ if (res == 0) { errno = ENXIO; return(-1); } return(0); } /* * Function - cooked() this function returns the designate file pointer to * it's normal, wait for a <CR> mode. This is exactly like raw() except that * it sends a 0 to the console to make it back into a CON: from a RAW: */ long cooked(fp) FILE *fp; { struct MsgPort *mp; /* The File Handle message port */ struct FileHandle *afh; struct UFB *ufb; long Arg[1],res; ufb = (struct UFB *) chkufb(fileno(fp)); afh = (struct FileHandle *)(ufb->ufbfh); if ( ! IsInteractive(afh)) { errno = ENOTTY; return(-1); } mp = ((struct FileHandle *)(BADDR(afh)))->fh_Type; Arg[0] = 0; res = SendPacket(mp,ACTION_SCREEN_MODE,Arg,1); if (res == 0) { errno = ENXIO; return(-1); } return(0); } SHAR_EOF if test 2393 -ne "`wc -c raw.c`" then echo shar: error transmitting raw.c '(should have been 2393 characters)' fi echo shar: extracting rmail.c '(8785 characters)' cat << \SHAR_EOF > rmail.c /* rmail.c copyright (C) 1987 Stuart Lynne Copying and use of this program are controlled by the terms of the Free Software Foundations GNU Emacs General Public License. version 0.1 March 31/1987 pcmail pcmail address1 address2 ... < the.message description An 822 compatible (hopefully) mail delivery system for pc's. Designed for delivering mail on a pc based system. It will put local mail (ie, not @ or ! in address) into files in the default mail directory. If remote it will put into an outgoing mailbag in the default mail directory. Performs a simple bundling of mail messages into one file with arguments prepended as To: arg header lines. pcmail john jack jill@xyz.uucp < afile To: john, jack, jill@xyz.uucp ... ... ... It also adds the from From and Date lines. Subject: lines may be inserted by placing them at the beginning of the message. A Unix version should lock the /usr/mail/mailbag file. environment variables The following evironment variables are used: MAILBOX current user's mailbox, "stuart" NAME current user's name, "Stuart Lynne" DOMAIN domain of this machine, "slynne.mac.van-bc.can" MAILDIR where is mail kept, "mpw:mail" */ #include <dos.h> #include <stdio.h> #include "host.h" char *_TZ = "GMT0"; FILE *FOPEN(); #define FORWARD "Forward to" static FILE *mailfile; static FILE *tempfile; static char buf[BUFSIZ]; static char miscbuff[100]; static char *inFileName; static long int sequence = 0; static long tloc; static char chartime[40]; /* current time in characters */ static char *thetime; static char tfilename[100]; extern char mfilename[]; static char mailsent[100]; static char remotes[BUFSIZ]; static char *uucp = "uucp"; char *fgets(); int fputs(); extern int debuglevel; extern long DOSBase; static char *mcurdir; static char s_mcurdir[128]; /* current directory path (save malloc call) */ char * getcwd(); int chdir(); rmail(argc, argv, inname) int argc; char *inname; char **argv; { register int argcount; register char **argvec; char timeBuf[40]; if (debuglevel > 5) { fprintf(stderr,"pcmail: argc %d ", argc); argcount = argc; argvec = argv; while (argcount--) fprintf(stderr," \"%s\"", *argvec++); fprintf(stderr,"\n"); time(&tloc); thetime = ctime(&tloc); sprintf(timeBuf,"%.3s, %.2s %.3s %.2s %.8s %s\n", thetime, thetime + 8, thetime + 4, thetime + 22, thetime + 11, timeZone); thetime = timeBuf; fprintf(stderr,"thetime: %s",thetime); } mcurdir = getcwd(s_mcurdir, sizeof(s_mcurdir)); chdir(spooldir); /* get sequence number */ mkfilename(tfilename, confdir, SFILENAME); if (debuglevel > 4) fprintf(stderr,"pcmail: opening %s\n", tfilename); /* */ if(tempfile = FOPEN(tfilename,"r", 't')) { fscanf(tempfile,"%ld", &sequence); fclose(tempfile); } else fprintf(stderr,"pcmail: can't find %s file, creating\n", tfilename); /* update sequence number */ if (debuglevel > 5) fprintf(stderr,"pcmail: new sequence # %ld\n", sequence); if(tempfile = FOPEN(tfilename,"w", 't')) { fprintf(tempfile,"%ld\n", (sequence+1)%10000); fclose(tempfile); } inFileName = inname; /* loop on args, copying to appropriate postbox, do remote only once remote checking is done empirically, could be better */ remotes[0] = '\0'; argcount = argc; argvec = argv; while (--argcount > 0) { argvec++; if (debuglevel > 5) fprintf(stderr,"pcmail: arg# %d %s\n", argcount, *argvec); if (strchr(*argvec, '!') || strchr(*argvec, '@') || strchr(*argvec, '%')) { if (debuglevel > 5) fprintf(stderr,"pcmail: send to remote\n"); /* can we cram one more address on line */ if((strlen(remotes) + strlen(*argvec) + 3) > sizeof(remotes)) { /* dump it then, to bad */ sendone(argc, argv, remotes, TRUE); remotes[0] = '\0'; } /* add *arvgvec to list of remotes */ strcat(remotes," "); strcat(remotes, *argvec); } else { if (debuglevel > 5) fprintf(stderr,"pcmail: calling sendone %s\n", *argvec); sendone(argc, argv, *argvec, FALSE); } } /* dump remotes if necessary */ if (remotes[0]) sendone(argc, argv, remotes, TRUE); chdir(mcurdir); return(0); } /* sendone copies file plus headers to appropriate postbox NB. we do headers here to allow flexibility later, for example in being able to do bcc, per host service processing etc. */ sendone(argc, argv, address, remote) int argc; char **argv; char *address; int remote; { register char *cp; char icfilename[32]; /* local C. copy file */ char ixfilename[32]; /* local X. xqt file */ char idfilename[32]; /* local D. data file */ char rxfilename[32]; /* remote X. xqt file */ char rdfilename[32]; /* remote D. data file */ char tmfilename[32]; /* temporary storage */ struct FILEINFO info; if (remote) { /* sprintf all required file names */ sprintf(tmfilename,"%c.%.7s%04d", 'C', mailserv, sequence); importpath(icfilename, tmfilename); sprintf(tmfilename,"%c.%.7s%04d", 'D', mailserv, sequence); importpath(idfilename, tmfilename); sprintf(tmfilename,"%c.%.7s%04d", 'D', nodename, sequence); importpath(ixfilename, tmfilename); sprintf(rdfilename,"%c.%.7s%04d", 'D', nodename, sequence); sprintf(rxfilename,"%c.%.7s%04d", 'X', nodename, sequence); } else { /* postbox file name */ if (!strchr(address, SEPCHAR)) mkfilename(idfilename, maildir, address); else strcpy(idfilename, address); } if (debuglevel > 5) fprintf(stderr,"pcmail: sendone: %s\n", idfilename); if (remote == FALSE) { if (debuglevel > 5) fprintf(stderr,"pcmail: sendone: check for remote\n"); /* check for forwarding */ if (!dfindOne(&info, idfilename, 0) && info.fib_Size > 10 && (mailfile = FOPEN(idfilename,"r", 'b'))) { cp = fgets(buf, sizeof(buf), mailfile); fclose(mailfile); if (cp && !strncmp(buf, FORWARD, 10)) { strcpy(buf, buf+11); return(sendone(argc, argv, buf, FALSE)); } } } /* open mailfile */ if (!(mailfile = FOPEN(idfilename,"a", 'b'))) { fprintf(stdout,"pcmail: cannot append to %s\n", idfilename); return(0); } if (debuglevel > 5) fprintf(stderr,"pcmail: append to mailfile\n"); time(&tloc); thetime = ctime(&tloc); sprintf(chartime,"%.3s, %.2s %.3s %.2s %.8s %s", thetime, thetime + 8, thetime + 4, thetime + 22, thetime + 11, timeZone); thetime = chartime; /* and work with our own copy */ fprintf(mailfile,"From uucp %s\n", thetime); fprintf(mailfile,"Received: by %s (pcmail) %s\n", domain, thetime); /* copy spoolfile to postbox file */ if (debuglevel > 4) fprintf(stderr,"pcmail: copy spoolfile %s to %s\n", inFileName, idfilename); if (!(tempfile = FOPEN(inFileName,"r", 'b'))) { fprintf(stdout,"pcmail: can't open %s\n", inFileName); return(0); } buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = 0; while (fgets(buf, sizeof(buf) - 2, tempfile)) { if (strncmp(buf,"From ", 5) == 0) fputc('>', mailfile); if(buf[0]) fputs(buf, mailfile); } /* close files */ fclose(mailfile); fclose(tempfile); /* all done unless going to remote via uucp */ /* must create the job control files */ if (remote) { /* create remote X xqt file */ if(!(mailfile = FOPEN(ixfilename,"w", 'b'))) { fprintf(stdout,"pcmail: cannot open %s\n", ixfilename); return(0); } fprintf(mailfile,"U %s %s\n", uucp, nodename); fprintf(mailfile,"F %s\n", rdfilename); fprintf(mailfile,"I %s\n", rdfilename); fprintf(mailfile,"C rmail %s\n", address); fclose(mailfile); /* create local C copy file */ if(!(mailfile = FOPEN(icfilename,"w", 't'))) { fprintf(stdout,"pcmail: cannot open %s\n", icfilename); return(0); } fprintf(mailfile,"S %s %s %s - %s 0666 %s\n", idfilename, rdfilename, uucp, idfilename, uucp); fprintf(mailfile,"S %s %s %s - %s 0666 %s\n", ixfilename, rxfilename, uucp, ixfilename, uucp); fclose(mailfile); } return(1); } #ifndef AMIGA #ifdef RMAIL rnews(argc, argv) int argc; char *argv[]; { struct tm *thetm; char filename[132]; char format[128]; FILE *f; char buf[BUFSIZ]; static int count = 0; tloc = time((long *)NULL); thetime = ctime(&tloc); tloc = time((long *)NULL); thetm = localtime(&tloc); /* mkfilename(format, spooldir, NEWSDIR); */ sprintf(filename, NEWSDIR, thetm->tm_year % 100, thetm->tm_mon, thetm->tm_mday, thetm->tm_hour, thetm->tm_min, thetm->tm_sec, count ); count++; if (debuglevel > 5) fprintf(stderr,"rnews: %s\n", filename); if ((f = FOPEN(filename,"w", 't')) == (FILE *)NULL) { fprintf(stderr,"rnews: can't open %s %d\n", filename, errno); return(-1); } while (fgets(buf, BUFSIZ, stdin) != (char *)NULL) fputs(buf, f); fclose(f); } #endif /* RMAIL */ #endif /* AMIGA */ SHAR_EOF if test 8785 -ne "`wc -c rmail.c`" then echo shar: error transmitting rmail.c '(should have been 8785 characters)' fi echo shar: extracting sendpacket.c '(2082 characters)' cat << \SHAR_EOF > sendpacket.c /* * Sendpacket.c * * An invaluable addition to your Amiga.lib file. This code sends a packet * the given message port. This makes working around DOS lots easier. * * Note, I didn't write this, those wonderful folks at CBM did. I do suggest * however that you may wish to add it to Amiga.Lib, to do so, compile it * and say 'oml lib:amiga.lib -r sendpacket.o' */ #include <exec/types.h> #include <exec/ports.h> #include <exec/memory.h> #include <libraries/dos.h> #include <libraries/dosextens.h> #include <proto/exec.h> #include <proto/dos.h> /* * Function - SendPacket written by Phil Lindsay, Carolyn Scheppner, and * Andy Finkel. This function will send a packet of the given type to the * Message Port supplied. */ long SendPacket(pid,action,args,nargs) struct MsgPort *pid; /* process indentifier ... (handlers message port ) */ long action, /* packet type ... (what you want handler to do ) */ args[], /* a pointer to a argument list */ nargs; /* number of arguments in list */ { struct MsgPort *replyport; struct StandardPacket *packet; long count, *pargs, res1; replyport = (struct MsgPort *) CreatePort(NULL,0); if(!replyport) return(0); /* Allocate space for a packet, make it public and clear it */ packet = (struct StandardPacket *) AllocMem((long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR); if(!packet) { DeletePort(replyport); return(0); } packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt); packet->sp_Pkt.dp_Link = &(packet->sp_Msg); packet->sp_Pkt.dp_Port = replyport; packet->sp_Pkt.dp_Type = action; /* copy the args into the packet */ pargs = &(packet->sp_Pkt.dp_Arg1); /* address of first argument */ for(count=0;count < nargs;count++) pargs[count]=args[count]; PutMsg(pid,packet); /* send packet */ WaitPort(replyport); GetMsg(replyport); res1 = packet->sp_Pkt.dp_Res1; FreeMem(packet,(long)sizeof(struct StandardPacket)); DeletePort(replyport); return(res1); } SHAR_EOF if test 2082 -ne "`wc -c sendpacket.c`" then echo shar: error transmitting sendpacket.c '(should have been 2082 characters)' fi echo shar: extracting serial.c '(7910 characters)' cat << \SHAR_EOF > serial.c #include <exec/types.h> #include <exec/nodes.h> #include <exec/lists.h> #include <exec/ports.h> #include <exec/libraries.h> #include <exec/devices.h> #include <exec/io.h> #include <devices/serial.h> #ifndef MANX #include <proto/exec.h> #endif #include <stdio.h> struct IOExtSer *IORreadser = NULL, *IORwriteser = NULL; struct MsgPort *serialreadport = NULL, *serialwriteport = NULL; extern struct MsgPort *CreatePort(); extern struct IORequest *CreateExtIO(); static int close_flag = 0; #define SERDATR ((USHORT *) 0xdff018) #define TBE (1 << 13) #define SERDAT ((USHORT *) 0xdff030) static UBYTE parity = 2, stopbits = 0; static UBYTE speed = 2, xonxoff = 0; static ULONG speedtab[] = {9600,4800,2400,1200,1200,300}; static UBYTE paritytab[] = {2,1,0}; static UBYTE stopbitstab[] = {1, 2}; initserial() { int error; /* SET UP the message port in the I/O request */ serialreadport = CreatePort ("Serial Read",0); serialwriteport = CreatePort ("Serial Write",0); if (serialreadport == NULL || serialwriteport == NULL) { sercleanup(); printf("\nProblems during CreatePort"); exit(100); } /* Create the request blocks for passing info to and from the serial device. */ IORreadser = (struct IOExtSer *) CreateExtIO(serialreadport,sizeof(struct IOExtSer)); IORwriteser = (struct IOExtSer *) CreateExtIO(serialwriteport,sizeof(struct IOExtSer)); if (IORreadser == NULL || IORwriteser == NULL) { sercleanup(); printf("\nProblems during CreateExtIO"); exit(101); } /* OPEN the serial.device */ if ((error = OpenDevice (SERIALNAME, 0, IORreadser, 0)) != 0) { sercleanup(); printf ("Serial device did not open 1, error = %ld\n",error); exit(102); } close_flag = TRUE; dosetparams(); *IORwriteser = *IORreadser; IORwriteser->IOSer.io_Message.mn_ReplyPort = serialwriteport; } sercleanup() { if(close_flag) { CloseDevice (IORreadser); close_flag = 0; } if(serialreadport) { DeletePort (serialreadport); serialreadport = NULL; } if(serialwriteport) { DeletePort (serialwriteport); serialwriteport = NULL; } if(IORreadser) { DeleteExtIO(IORreadser,sizeof(struct IOExtSer)); IORreadser = NULL; } if(IORwriteser) { DeleteExtIO(IORwriteser,sizeof(struct IOExtSer)); IORwriteser = NULL; } } setspeed(menusel) int menusel; { speed = menusel; } dosetparams() { ULONG rbl; ULONG brk; ULONG baud; UBYTE rwl; UBYTE wwl; UBYTE sf; ULONG t0; ULONG t1; /* SET PARAMS for the serial.device */ rbl = 4096; if(paritytab[parity]) { rwl = 0x07; wwl = 0x07; } else { rwl = 0x08; wwl = 0x08; } brk = 750000; baud = speedtab[speed]; sf = 0; if(!xonxoff) { sf = SERF_XDISABLED; } if(paritytab[parity] == 1) { sf |= SERF_PARTY_ON | SERF_PARTY_ODD; } else if(paritytab[parity] == 2) { sf |= SERF_PARTY_ON; } t0 = 0x51040303; t1 = 0x03030303; SetParams(IORreadser,rbl,rwl,wwl,stopbitstab[stopbits], brk,baud,sf,t0,t1); } /* SERIAL I/O functions */ SetParams(io,rbuf_len,rlen,wlen,stopbits,brk,baud,sf,ta0,ta1) struct IOExtSer *io; ULONG rbuf_len; UBYTE rlen; UBYTE wlen; UBYTE stopbits; ULONG brk; ULONG baud; UBYTE sf; ULONG ta0; ULONG ta1; { int error; io->io_ReadLen = rlen; io->io_BrkTime = brk; io->io_Baud = baud; io->io_WriteLen = wlen; io->io_StopBits = stopbits; io->io_RBufLen = rbuf_len; io->io_SerFlags = sf; io->IOSer.io_Command = SDCMD_SETPARAMS; io->io_TermArray.TermArray0 = ta0; io->io_TermArray.TermArray1 = ta1; if ((error = DoIO (io)) != 0) { printf ("serial.device setparams error %ld \n", error); } return (error); } ReadSer(data,length) UBYTE *data; int length; { IORreadser->IOSer.io_Data = (APTR)data; IORreadser->IOSer.io_Length = (ULONG)length; IORreadser->IOSer.io_Command = CMD_READ; SendIO(IORreadser); } kill_ReadSer() { AbortIO(IORreadser); while(GetMsg(serialreadport)); } readserresult(errno,length) int *errno, *length; { *errno = IORreadser->IOSer.io_Error; *length = IORreadser->IOSer.io_Actual; } WriteSer(data,length) UBYTE *data; int length; { IORwriteser->IOSer.io_Data = (APTR)data; IORwriteser->IOSer.io_Length = length; IORwriteser->IOSer.io_Command = CMD_WRITE; SendIO(IORwriteser); } writeserresult(errno) int *errno; { *errno = IORwriteser->IOSer.io_Error; } SendWaitWrite(data,length) UBYTE *data; int length; { int error; IORwriteser->IOSer.io_Data = (APTR)data; IORwriteser->IOSer.io_Length = length; IORwriteser->IOSer.io_Command = CMD_WRITE; if((error = DoIO(IORwriteser)) != 0) { fprintf (stderr,"serial.device write error %ld \n", error); } return ((int)IORwriteser->IOSer.io_Actual); } /* send a break to the host */ void breakSer(readActive) int readActive; { if(readActive) AbortIO(IORreadser); IORreadser->IOSer.io_Command = SDCMD_BREAK; DoIO(IORreadser); if(readActive) { IORreadser->IOSer.io_Command = CMD_READ; SendIO(IORreadser); } } #ifdef notdef /*********************************************************************** * * Exec Support Function -- Extended IO Request * ***********************************************************************/ #include <exec/types.h> #include <exec/nodes.h> #include <exec/lists.h> #include <exec/memory.h> #include <exec/interrupts.h> #include <exec/ports.h> #include <exec/libraries.h> #include <exec/io.h> #include <exec/tasks.h> #include <exec/execbase.h> extern APTR AllocMem(); /****** exec_support/CreateExtIO ************************************** * * NAME * CreateExtIO() -- create an Extended IO request * * SYNOPSIS * ioReq = CreateExtIO(ioReplyPort,size); * * FUNCTION * Allocates memory for and initializes a new IO request block * of a user-specified number of bytes. * * INPUTS * ioReplyPort - a pointer to an already initialized * message port to be used for this IO request's reply port. * * RESULT * Returns a pointer to the new block. Pointer is of the type * struct IORequest. * * 0 indicates inability to allocate enough memory for the request block * or not enough signals available. * * EXAMPLE * struct IORequest *myBlock; * if( (myBlock = CreateExtIO(myPort,sizeof(struct IOExtTD)) == NULL) * exit(NO_MEM_OR_SIGNALS); * * example used to allocate space for IOExtTD (trackdisk driver * IO Request block for extended IO operations). * * SEE ALSO * DeleteExtIO * ***********************************************************************/ struct IORequest *CreateExtIO(ioReplyPort,size) struct MsgPort *ioReplyPort; LONG size; { struct IORequest *ioReq; if (ioReplyPort == 0) return ((struct IORequest *) 0); ioReq = (struct IORequest *)AllocMem (size, MEMF_CLEAR | MEMF_PUBLIC); if (ioReq == 0) return ((struct IORequest *) 0); ioReq -> io_Message.mn_Node.ln_Type = NT_MESSAGE; ioReq -> io_Message.mn_Node.ln_Pri = 0; ioReq -> io_Message.mn_ReplyPort = ioReplyPort; return (ioReq); } /****** exec_support/DeleteExtIO ************************************** * * NAME * DeleteExtIO() - return memory allocated for extended IO request * * SYNOPSIS * DeleteExtIO(ioReq,size); * * FUNCTION * See summary line at NAME. Also frees the signal bit which * had been allocated by the call to CreateExtIO. * * INPUTS * A pointer to the IORequest block whose resources are to be freed. * * RESULT * Frees the memory. Returns (no error conditions shown) * * EXAMPLE * struct IORequest *myBlock; * DeleteExtIO(myBlock,(sizeof(struct IOExtTD))); * * example shows that CreateExtIO had been used to create a trackdisk * (extended) IO Request block. * * SEE ALSO * CreateExtIO * **************************************************************************/ DeleteExtIO(ioExt,size) struct IORequest *ioExt; LONG size; { ioExt -> io_Message.mn_Node.ln_Type = 0xff; ioExt -> io_Device = (struct Device *) -1; ioExt -> io_Unit = (struct Unit *) -1; FreeMem (ioExt, size); } #endif SHAR_EOF if test 7910 -ne "`wc -c serial.c`" then echo shar: error transmitting serial.c '(should have been 7910 characters)' fi echo shar: extracting sio.c '(4904 characters)' cat << \SHAR_EOF > sio.c /*------------------------------------------------------------------*/ /* Sio.c: Serial I/O for Amiga Version of PCMail */ /* Created: 27Jun87 by J.A. Lydiatt */ /* */ /* Exports the following routines required by PCMail: */ /* SIOInit(): Initialize Serial Port */ /* SIOClose(): Close and free Serial Port resources */ /* SIOSpeed(): Set bps */ /* SIORead(): read characters from serial port */ /* SIOWrite(): write characters to serial port */ /* SIOInBuffer(): Set Buffer size for read & writes. */ /* SIOOutBuffer(): (Has no effect in Amiga Version) */ /*------------------------------------------------------------------*/ #include <exec/types.h> #include <exec/io.h> #include <stdio.h> #ifndef TRUE #define TRUE -1 #define FALSE 0 #endif /*--- SerialIO Function Declarations --- */ extern void initserial(); extern void sercleanup(); /* Return SerialIO resources */ extern void setspeed(); /* Set baud rate */ extern void dosetparams(); /* Set serial parameters */ /*--------------------------------------------------------------*/ /* getspeed/getbaud: check for valid baud parameters */ /*--------------------------------------------------------------*/ static struct { unsigned baudr; int speedcode; } speeds[] = { 300, 5, 1200, 3, 2400, 2, 4800, 1, 9600, 0, 0, }; static unsigned getspeed(code) { register n; for (n=0; speeds[n].baudr; ++n) if (speeds[n].speedcode == code) return speeds[n].baudr; return 0; } static int getbaud(code) char *code; { register n; register int Baudrate; Baudrate = atoi(code); for (n=0; speeds[n].baudr; ++n) if (speeds[n].baudr == Baudrate) return speeds[n].speedcode; return -1; } /*--------------------------------------------------------------*/ /* SIOInit: initialize serial I/O */ /*--------------------------------------------------------------*/ SIOInit ( whichport, speed ) char * whichport; char * speed; { int baud; /* fprintf( stderr, "sioinit %s %s\n", whichport, speed ); /* */ initserial(); if ( (baud = getbaud( speed )) >= 0 ) setspeed( baud ); if ( !OpenTimer() ) { fprintf( stderr, "Can't open the Timer Device\n" ); sercleanup(); return( -1 ); } dosetparams(); return( 0 ); } /*--------------------------------------------------------------*/ /* SIOSpeed: set the serial Baud rate */ /*--------------------------------------------------------------*/ SIOSpeed( speed ) char *speed; { int baud; if ( (baud = getbaud( speed )) >= 0 ) { setspeed( baud ); dosetparams(); } } /*--------------------------------------------------------------*/ /* SIOInBuffer/ SIOOutBuffer: Set Buffer Size. */ /*--------------------------------------------------------------*/ SIOInBuffer ( buf, size ) char * buf; int size; { } SIOOutBuffer ( buf, size ) char * buf; int size; { } /*--------------------------------------------------------------*/ /* SIOClose: Close Serial port. */ /*--------------------------------------------------------------*/ SIOClose ( dtr ) { sercleanup(); CloseTimer(); } /*--------------------------------------------------------------*/ /* SIOWrite: send count characters to serial port */ /*--------------------------------------------------------------*/ SIOWrite ( buf, count ) register char * buf; int count; { SendWaitWrite(buf, count); return count; } /*--------------------------------------------------------------*/ /* SIORead: read mincount <= #characters <= maxcount */ /* return # of characters read, or -1 if timed out after */ /* after tenths / 10 seconds. */ /*--------------------------------------------------------------*/ static int readOutstanding = 0; int SIORead ( buf, mincount, maxcount, tenths ) char *buf; int mincount; int maxcount; int tenths; /* timeout is in tenth's of seconds */ { ULONG signals; extern struct MsgPort *serialreadport, *timerPort; static char inBuf[512]; static int inBufPos = 0; int count, errorNumber; if(tenths < 10) tenths = 10; StartTimer(tenths/10L, 0); while(1) { if((inBufPos >= mincount) && !readOutstanding) { movmem(inBuf,buf,mincount); inBufPos -= mincount; if(inBufPos) movmem(inBuf + mincount, inBuf, inBufPos); return(mincount); } if(!readOutstanding) { ReadSer(inBuf + inBufPos, mincount - inBufPos); readOutstanding = 1; } signals = Wait((1 << timerPort->mp_SigBit) | (1 << serialreadport->mp_SigBit)); if(signals & (1 << timerPort->mp_SigBit)) { if(TimerExpired()) { return(-1); } else { getTimerMsg(); } } if(signals & (1 << serialreadport->mp_SigBit)) { readserresult(&errorNumber, &count); GetMsg(serialreadport); readOutstanding = 0; if(errorNumber) { inBufPos = 0; return(-1); } inBufPos += count; } } } void ssendbrk() { breakSer(readOutstanding); } SHAR_EOF if test 4904 -ne "`wc -c sio.c`" then echo shar: error transmitting sio.c '(should have been 4904 characters)' fi echo shar: extracting sleep.c '(287 characters)' cat << \SHAR_EOF > sleep.c /*--------------------------------------------------------------*/ /* sleep.c: Implement sleep( seconds ) on the Amiga. */ /*--------------------------------------------------------------*/ void sleep( seconds ) unsigned int seconds; { if ( seconds > 0 ) Delay( seconds*50L ); } SHAR_EOF if test 287 -ne "`wc -c sleep.c`" then echo shar: error transmitting sleep.c '(should have been 287 characters)' fi echo shar: extracting timer.c '(3078 characters)' cat << \SHAR_EOF > timer.c /* * Timer.c: Functions to invoke the Amiga timer: * * External Functions: * * OpenTimer, CloseTimer, StartTimer, TimerExpired, GetTimerSigBit * * Maintenance Notes: * 05Jul86 - Created by Jeff Lydiatt, Vancouver, Canada. */ #include <exec/types.h> #include <exec/nodes.h> #include <exec/lists.h> #include <exec/ports.h> #include <exec/tasks.h> #include <exec/io.h> #include <devices/timer.h> #ifdef MANX #include <functions.h> #else #include <proto/exec.h> #include <proto/timer.h> #endif static struct timerequest TimerIO; struct MsgPort *timerPort = NULL; static BOOL timerON; static BOOL timerExpired; /*-------------------------------------------------------------*/ /* OpenTimer: return TRUE if timer opened OK */ /*-------------------------------------------------------------*/ BOOL OpenTimer() { register struct timerequest *t = &TimerIO; register struct MsgPort *port; timerON = FALSE; timerExpired = TRUE; if ( timerPort != NULL ) return TRUE; if ( (port = CreatePort("Timer Port", 0L)) == NULL ) return FALSE; else timerPort = port; setmem(&TimerIO, sizeof(TimerIO), 0); if (OpenDevice(TIMERNAME, UNIT_VBLANK, t, 0L) != 0) { DeletePort( port ); timerPort = NULL; return FALSE; } return TRUE; } /*-------------------------------------------------------------*/ /* CloseTimer: All Done with the timer. */ /*-------------------------------------------------------------*/ void CloseTimer() { register struct timerequest *t = &TimerIO; if (!timerPort) return; if ( timerON ) AbortIO( t ); CloseDevice( t ); DeletePort( timerPort ); timerPort = NULL; } /*-------------------------------------------------------------*/ /* GetTimerSigBit: return Timer signal bit */ /*-------------------------------------------------------------*/ int GetTimerSigBit() { return timerPort->mp_SigBit; } /*-------------------------------------------------------------*/ /* StartTimer: launch the timer. */ /*-------------------------------------------------------------*/ void StartTimer(seconds, micros) ULONG seconds, micros; { register struct timerequest *t = &TimerIO; if ( timerON ) { AbortIO( t ); while(GetMsg( timerPort )); timerON = FALSE; timerExpired = TRUE; } t->tr_time.tv_secs = seconds; t->tr_time.tv_micro = micros; t->tr_node.io_Command = TR_ADDREQUEST; /* t->tr_node.io_Flags = IOF_QUICK; t->tr_node.io_Error = 0; */ t->tr_node.io_Message.mn_ReplyPort = timerPort; SendIO( t ); timerExpired = FALSE; timerON = TRUE; } /*-------------------------------------------------------------*/ /* TimerExpired: returns TRUE if timer expired. */ /*-------------------------------------------------------------*/ BOOL TimerExpired() { if ( timerON && ( CheckIO( &TimerIO ) == NULL) ) return FALSE; while(GetMsg( timerPort )); timerExpired = TRUE; timerON = FALSE; return timerExpired; } getTimerMsg() { GetMsg( timerPort ); } SHAR_EOF if test 3078 -ne "`wc -c timer.c`" then echo shar: error transmitting timer.c '(should have been 3078 characters)' fi echo shar: extracting ulib.c '(5372 characters)' cat << \SHAR_EOF > ulib.c /* ulib.c Amiga library Things to do in uu host serial I/O directory stuff opendir, readdir, closedir prolog and epilog system call */ #include <stdio.h> #include "host.h" #ifdef MANX #include <sgtty.h> #endif int lineIsOpen = 0; /**/ /* * * login (for slave in PC mode) * Real dumb login handshake */ login() { char logmsg[132]; #ifdef PC lretry: msgtime = 9999; rmsg(logmsg, 0); /* wait for a <CR> or <NL> */ msgtime = 2 * MSGTIME; wmsg("Username:", 0); rmsg(logmsg, 0); printmsg( 0, "Username = %s", logmsg ); wmsg("Password:", 0); rmsg(logmsg, 0); printmsg( 14, "Password = %s", logmsg ); if (strcmp(logmsg, "uucp") != 0) goto lretry; #endif return('I'); } char inbuf[BUFSIZ]; char outbuf[BUFSIZ]; swrite(data, num) int num; char *data; { int test; unsigned char * cp; if (debuglevel > 14) fputc( '{', stderr ); if (debuglevel > 14) { test = num; cp = data; while (test--) fprintf( stderr, isprint(*cp)? "{%c}":"{%02x}", *cp++ ); } test = SIOWrite( data, num ); if (debuglevel > 14) fputc( '}', stderr ); return( test ); } /* non-blocking read essential to "g" protocol */ /* see "dcpgpkt.c" for description */ /* This all changes in a mtask systems. Requests for */ /* I/O should get qued and an event flag given. Then the */ /* requesting process (e.g.gmachine()) waits for the event */ /* flag to fire processing either a read or a write. */ /* Could be implemented on VAX/VMS or DG but not MS-DOS */ sread(buf, num, timeout) char *buf; int num, timeout; { /* return( SIORead( buf, num, num, timeout*10 ) ); */ int count; int test; unsigned char * cp; if (debuglevel > 13) fputc( '[', stderr ); printmsg( 15, "sread: num: %d timeout: %d", num, timeout ); count = SIORead( buf, num, num, timeout*10 ); printmsg( 15, "sread: read: %d ", count ); if (debuglevel > 13 && count > 0) { test = count; cp = buf; while (test--) fprintf( stderr, isprint(*cp)? "[%c]":"[%02x]", *cp++ ); } if (debuglevel > 13) fputc( ']', stderr ); return( count ); } openline(name, baud) char *name, *baud; { printmsg( 3, "openline: name: \"%s\" baud: \"%s\"", name, baud ); lineIsOpen = 1; if ( SIOInit( name, baud ) ) return -1; SIOInBuffer( inbuf, BUFSIZ ); SIOOutBuffer( outbuf, BUFSIZ ); return( 0 ); } closeline() { if(lineIsOpen) { SIOClose( 1 ); lineIsOpen = 0; } } nodot(string) { } notimp( argc, argv ) char *argv[]; { /*debuglevelMsg("\Pcheck argc (08) and argv (0a) ");*/ fprintf( stderr, "shell: %s not implemented\n", *argv ); } /*------------------------------------------------------------------*/ /* RNews: my private rnews! */ /*------------------------------------------------------------------*/ static void RNews( inname ) char *inname; { extern char *newsdir; register struct tm *thetm; long tloc; char filename[132]; FILE *f, *fin; FILE *FOPEN(); char buf[BUFSIZ]; int bytesRead; static int count = 0; int len; /* inname is of form "D.jlamiBCnnnn". Pick off the nnnn. */ len = strlen( inname ) - 1; while ( len >= 0 ) { if ( '0' <= inname[len] && inname[len] <= '9' ) --len; else break; } sprintf( filename, "%s/%s", newsdir, &inname[len+1] ); if ( (f = FOPEN( filename, "r", 't' )) != NULL ) { /* Already exists, so make a timestamped one. */ fclose( f ); tloc = time( (long *)NULL ); thetm = localtime( &tloc ); sprintf( filename, "%s/%02d%02d%02d%02d%02d%02d.%03d", newsdir, thetm->tm_year % 100, thetm->tm_mon, thetm->tm_mday, thetm->tm_hour, thetm->tm_min, thetm->tm_sec, count ); ++count; } if ( (f = FOPEN( filename, "w", 't' )) == (FILE *)NULL ) { fprintf( stderr, "rnews: can't open %s\n", filename ); onBreak(); } if ( (fin = FOPEN( inname, "r", 't' )) == NULL ) { fprintf( stderr, "rnews: Couldn't open %s\n", inname ); fclose( f ); onBreak(); } while(bytesRead = fread(buf, 1, BUFSIZ, fin)) { if(fwrite(buf, bytesRead, 1, f) != 1) { fprintf(stderr,"rnews: write error on %s\n", filename); fclose(f); onBreak(); } } fclose( f ); fclose( fin ); } /* if name is of the form user@domain or domain!user and domain is either */ /* DOMAIN or NODENAME then return user. Otherwise return name. */ /* Note: this function modifies it's argument. */ static char * getLocalName(name) char *name; { char *cp; if(cp = strchr(name, '@')) { if(!strcmp(cp + 1, domain) || !strcmp(cp + 1, nodename)) *cp = 0; } else if(cp = strchr(name, '!')) { *cp = 0; if(!strcmp(name, domain) || !strcmp(name, nodename)) return(cp + 1); *cp = '!'; } return(name); } /* shell */ char * getcwd(); shell( command, inname, outname, errname ) char * command; char * inname; char * outname; { char * argvec[50]; int rmail(); int rnews(); int argcp; char **argvp; char args; argcp = 0; argcp = getargs( command, argvec ); argvp = argvec; args = argcp; if ( debuglevel > 5 ) { while ( args ) fprintf( stderr, "arg: %d %s\n", args--, *argvp++ ); argvp = argvec; args = argcp; } /* */ if ( strcmp( *argvp, "rmail" ) == SAME ) { argvec[1] = getLocalName(argvec[1]); rmail( argcp, argvp, inname ); } else if ( strcmp( *argvp, "rnews" ) == SAME ) { /* proto = rnews; */ RNews( inname ); return; } else notimp( argcp, argvp ); } SHAR_EOF if test 5372 -ne "`wc -c ulib.c`" then echo shar: error transmitting ulib.c '(should have been 5372 characters)' fi echo shar: extracting uuhost.c '(1187 characters)' cat << \SHAR_EOF > uuhost.c /* uuhost.c */ #include <stdio.h> #include <setjmp.h> #include "host.h" char *orgDir; char *getcwd(); int chdir(); int debuglevel = 0; /* debuginglevel */ jmp_buf dcpexit; main( argc, argv ) int argc; char *argv[]; { int returnCode = 0; char orgDirBuf[100]; /* Amiga specific prolog */ loadenv(); orgDir = getcwd( orgDirBuf, sizeof(orgDirBuf) ); chdir( spooldir ); /* setup longjmp for error exit's */ if ( setjmp( dcpexit ) == 0 ) { returnCode = dcpmain( argc, argv ); } /* Amiga specific epilog */ exitenv(); chdir( orgDir ); exit( returnCode ); } /* canonical name conversion routines importpath canonical -> host exportpath host -> canonical host your local pathname format canonical unix style */ importpath( host, canon ) char * host; char * canon; { extern char *pubdir; *host = '\0'; if ( *canon == '~' ) { if ( canon[1] == '/' ) strcpy( host, pubdir ); else { strcpy( host, home ); strcat( host, "/" ); } } strcat( host, canon ); if ( *host == '/' ) *host = ':'; } exportpath( canon, host ) char * host; char * canon; { strcpy( canon, host ); if ( *canon == ':' ) *canon = '/'; } SHAR_EOF if test 1187 -ne "`wc -c uuhost.c`" then echo shar: error transmitting uuhost.c '(should have been 1187 characters)' fi # End of shell archive exit 0