koreth@ssyx.ucsc.edu (Steven Grimm) (07/30/88)
Submitted-by: koreth@ssyx.ucsc.edu (Steven Grimm) Posting-number: Volume 1, Issue 65 Archive-name: uupc/part01 This is the version of UUPC that I've been working on. It allows you to use your ST as a UUCP node. Please look at the file "readme.1st" before proceeding; it contains configuration instructions and some caveats about the code. It's about halfway through part03 if you don't want to unshar before reading it. #!/bin/sh # shar: Shell Archiver (v1.22) # # This is part 1 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # # Run the following text with /bin/sh to create: # chekname.c # dcp.c # dcp.h # dcpgpkt.c # dcpsys.c # dcpxfer.c # dirsubs.c # dmymath.c # fgets.c # genv.c # genv.h # getargs.c # getenv.c # getone.c # host.c # host.h # inoutpth.c # lib.c # lmail.c # mail.c # mailhost.c # makefile # mlib.c # ndir.c # ndir.h # pcmail.c # printmsg.c # readme.1st # readme.dcp # readme.inf # readme.por # readme.st # readme.uup # rmail.c # shell.c # systems # time.c # time.h # ulib.c # uuhost.c # uusup.c # if test -r s2_seq_.tmp then echo "Must unpack archives in sequence!" next=`cat s2_seq_.tmp`; echo "Please unpack part $next next" exit 1; fi sed 's/^X//' << 'SHAR_EOF' > chekname.c && X#include "dcp.h" X#include <ctype.h> X Xextern char s_systems[]; XFILE *FOPEN(); X X/* X** X**checkname X** Do we know the guy ? X*/ Xcheckname(name) Xchar name[]; X{ X FILE *ff; X char line[BUFSIZ], tmp[20]; /* can change to 8 if %8s works */ X X if ( ( ff = FOPEN( s_systems, "r", 't' )) == (char *)NULL ) X return( FAILED ); X X while ( fgets( line, BUFSIZ, ff ) ){ X sscanf( line, "%8s ", tmp ); X if ( strncmp( tmp, name, 7 ) == 0 ) { X fclose( ff ); X return ( OK ); /*OK I like you */ X } X } X fclose( ff ); X return( FAILED ); /* Who are you ? */ X X} X X/* X * Non case-sensitive string compare X */ Xstrncom(s1, s2, n) Xregister char *s1, *s2; X{ X register int t1, t2; X X while ((*s1 || *s2) && n--) X if ((t1 = toupper(*s1++)) < (t2 = toupper(*s2++))) X return -1; X else if (t1 > t2) X return 1; X X return 0; X} SHAR_EOF chmod 0600 chekname.c || echo "restore of chekname.c fails" sed 's/^X//' << 'SHAR_EOF' > dcp.c && X/* dcp.c X X Revised edition of dcp X X Stuart Lynne May/87 X X Copyright (c) Richard H. Lamb 1985, 1986, 1987 X Changes Copyright (c) Stuart Lynne 1987 X X*/ X/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */ X/* This program implements a uucico type file transfer and remote Xexecution type protocol. X*/ X#include "dcp.h" X/**/ Xint pktsize; /* packet size for pro */ XFILE *logfile; /* system log file */ XFILE *syslog; /* system log file */ XFILE *fw; /* cfile pointer */ Xchar state; /* system state*/ Xchar cfile[80]; /* work file pointer */ Xint remote; /* -1 means we're remote ..7*/ Xint msgtime; /* timout setting */ Xchar fromfile[132]; Xchar hostfile[132]; /* host version of fromfile */ Xchar tofile[132]; Xint fp; /* current disk file ptr */ Xint size; /* nbytes in buff */ XFILE *fsys; Xchar Rmtname[20]; Xchar rmtname[20]; Xchar * cctime; Xchar proto[5]; X/* char loginseq[256]; */ Xchar sysline[BUFSIZ]; Xchar s_systems[64]; Xchar s_logfile[64]; Xchar s_syslog[64]; Xchar *flds[60]; Xint kflds; Xint debuglevel; /* debugging flag */ X Xunsigned int checksum(); X X X/**/ X/* new usage X X dcp [-xn] -r0 slave mode X dcp [-xn] -shost call host X dcp [-xn] -sall call all hosts X X dcp [-xn] call any hosts as required by C. files X X*/ X Xcomplain( s ) Xchar *s; X{ X fprintf( stderr, "Please set your %s environment variable.", s ); X} X Xstatic void cant( file ) Xchar *file; X{ X fprintf( stderr, "Can't open: \"%s\"\n", file ); X exit( NULL ); X} X Xdcpmain( argc, argv ) Xint argc; Xchar*argv[]; X{ X FILE *ftmp; X char line[132]; X X if ( name == NULL || *name == '\0' ) { X complain( NAME ); X exit( -1 ); X } X if ( nodename == NULL || *nodename == '\0' ) { X complain( NODENAME ); X exit( -1 ); X } X X mkfilename( s_logfile, spooldir, LOGFILE ); X mkfilename( s_syslog, spooldir, SYSLOG ); X mkfilename( s_systems, confdir, SYSTEMS ); X X if ( (logfile = FOPEN( s_logfile, "a", 't' )) == NULL ) X cant( s_logfile ); X if ( (syslog = FOPEN( s_syslog, "a", 't' )) == NULL ) X cant( s_syslog ); X X remote = MASTER; X debuglevel = 1; X fp = -1; X fw = (char *)NULL; X X X remote = MASTER; X strcpy( Rmtname, "any" ); X X while ( --argc ) { X if ( **++argv == '-') { X switch(argv[0][1]) { X case 'x': X debuglevel = atoi( &argv[0][2] ); X break; X case 's': X sprintf( Rmtname, "%.7s", &argv[0][2] ); X break; X case 'r': X remote = atoi( &argv[0][2] ); X break; X X default: X break; X } X } X } X X X if ( remote == MASTER ) { X printmsg( 0, "Calling %s, debuglevel=%d", Rmtname, debuglevel ); X if (( fsys = FOPEN( s_systems, "r", 't' )) == (char *)NULL ) X exit( FAILED ); X state = 'I'; X X while (TRUE) { X printmsg( 4, "Mstate = %c", state ); X switch (state) { X case 'I': X state = getsystem(); X break; X case 'S': X state = callup(); X break; X case 'P': X state = startup(); X break; X case 'D': X state = master(); X break; X case 'Y': X state = sysend(); X break; X case 'G': X state = 'I'; X break; X } X if (state == 'A') X break; X } X fclose( fsys ); X } else X { X if (openline( device, speed ) == -1) X return(FALSE); X state = 'L'; X while (TRUE) { X printmsg( 4, "Sstate = %c", state ); X switch (state) { X case 'L': X state = login(); X break; X case 'I': X state = startup(); X break; X case 'R': X state = slave(); X break; X case 'Y': X state = sysend(); X break; X } X if (state == 'A') X break; X } X closeline(); X } X X printmsg( 2, "calling dcxqt" ); X if (dcxqt()) X printmsg( 0, "ERROR in DCXQT" ); X X /* scan and process any recieved files */ X X fclose( syslog ); X fclose( logfile ); X return 0; X} X X X/**/ X/* X** X** X**master X** X** X*/ Xmaster() X{ X state = 'I'; X while (TRUE) { X printmsg( 4, "Top level state (master mode) %c", state ); X switch (state) { X case 'I': X state = sinit(); X break; X case 'B': X state = scandir(); X break; X case 'S': X state = send(); X break; X case 'Q': X state = sbreak(); X break; X case 'G': X state = receive(); X break; X case 'C': X state = 'Y'; X break; X case 'Y': X state = endp(); X break; X case 'P': X return('Y'); X case 'A': X return('A'); X default: X return('A'); X } X } X} X X X/**/ X/* X** X** X**slave X** X** X*/ Xslave() X{ X state = 'I'; X while (TRUE) { X printmsg( 4, "Top level state (slave mode) %c", state ); X switch (state) { X case 'I': X state = rinit(); X break; X case 'F': X state = receive(); X break; X case 'C': X state = schkdir(); X break; X case 'T': X state = 'B'; X break; X case 'B': X state = scandir(); X break; X case 'S': X state = send(); X break; X case 'Q': X state = sbreak(); X break; X case 'G': X return('Y'); X case 'Y': X state = endp(); X break; X case 'P': X return('Y'); X case 'A': X return('A'); X default: X return('A'); X } X } X} X X X/**/ X/* X * r e c e i v e X * X * This is the state table switcher for receiving files. X */ X Xreceive() X{ X X state = 'F';/* Receive-Init is the start state */ X X while (TRUE) { X printmsg( 4, " receive state: %c", state ); X switch (state)/* Do until done */ { X case 'F': X state = rfile(); X break; /* Receive-File */ X case 'D': X state = rdata(); X break; /* Receive-Data */ X case 'C': X return('C');/* Complete state */ X case 'A': X return('Y');/* "Abort" state */ X default: X return('Y'); X } X } X} X X X/**/ X/* X * s e n d X * X * Sendsw is the state table switcher for sending files. It loops until X * either it finishes, or an error is encountered. The routines called X * by sendsw are responsible for changing the state. X * X */ Xsend() X{ X fp = -1; /* reset file getter/opener */ X state = 'F';/* Send initiate is the start state */ X while (TRUE)/* Do this as long as necessary */ { X printmsg( 4, "send state: %c", state ); X switch (state) { X case 'F': X state = sfile(); X break; /* Send-File */ X case 'D': X state = sdata(); X break; /* Send-Data */ X case 'Z': X state = seof(); X break; /* Send-End-of-File */ X case 'B': X return ('B'); /* Complete */ X case 'A': X return ('Y'); /* "Abort" */ X default: X return ('Y'); /* Unknown, fail */ X } X } X} X X X/**/ X/* A command formatter for DCP. RH Lamb */ X/* sets up stdin and stdout on various machines */ X/* There is NO command checking so watch what you send and who you */ X/* let accsess your machine. "C rm /usr/*.*" could be executed. */ Xdcxqt() X{ X int i; X char command[60], input[60], output[60], line[BUFSIZ]; X char *cp; X X rmtname[0] = '\0'; X X while (dscandir()) { X strcpy( line, cfile ); X fw = FOPEN( line, "r", 'b' );/* imported X file */ X strcpy(cfile, line); X printmsg( 2, "dcxqt:%s %ld", cfile, fw ); X input[0] = '\0'; X output[0] = '\0'; X command[0] = '\0'; X while ( fgets( line, BUFSIZ, fw ) ) { X X cp = index( line, '\n' ); X if ( cp != (char *)NULL ) X *cp = '\0'; X X printmsg( 8, "dcxqt: %s", line ); X switch (line[0]) { X case 'U': X break; X case 'I': X strcpy( input, &line[2] ); X break; X case 'O': X strcpy( output, &line[2] ); X break; X case 'C': X strcpy( command, &line[2] ); X break; X case 'R': X break; X default : X break; X } X } X fclose( fw ); X X printmsg( 0, "xqt: %s\n", command ); X X shell( command, input, output, (char *)NULL ); X X X unlink(cfile); X importpath( hostfile, input ); X unlink(hostfile); X importpath( hostfile, output ); X unlink(hostfile); X } X return(0); X} X X/**/ X/* X * p r i n t m s g X * X * Print error message on standard output if not remote. X */ X/*VARARGS1*/ Xprintmsg(level, fmt, a1, a2, a3, a4, a5) Xint level; Xchar *fmt; Xchar *a1, *a2, *a3, *a4, *a5; X{ X char msg[256]; X X if ( debuglevel > level ) { X sprintf( msg, fmt, a1, a2, a3, a4, a5 ); X strcat( msg, "\n" ); X if ( remote == MASTER ) X fputs( msg, stdout ); X fputs( msg, logfile ); X } X} X X X X SHAR_EOF chmod 0600 dcp.c || echo "restore of dcp.c fails" sed 's/^X//' << 'SHAR_EOF' > dcp.h && X/* DCP a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */ X#include <stdio.h> /* Standard UNIX definitions */ X#include "host.h" /* Host specific definitions */ X XFILE * FOPEN(); Xint CREAT(); X X#define SYSTEMS "systems" X#define LOGFILE "LOGFILE" X#define SYSLOG "SYSLOG" X X#define MSGTIME 20 X#define MAXPACK 256 X X#define ACK 4 /* general definitions */ X#define NAK 2 X#define DATA 0 X#define CLOSE 1 X#define ERROR 10 X#define EMPTY 11 X X X X#define SLAVE 0 X#define MASTER 1 X X#ifndef TRUE X#define TRUE (-1) X#define FALSE 0 X#endif X X#ifndef SAME X#define SAME 0 X#endif X#define FAILED -1 X#define OK 0 X X X/* L.sys field defines */ X X#define FLD_REMOTE 0 X#define FLD_CCTIME 1 X#define FLD_DEVICE 2 X#define FLD_TYPE 3 X#define FLD_SPEED 4 X#define FLD_PROTO 5 X#define FLD_EXPECT 6 X#define FLD_SEND 7 X X/**/ Xtypedef int (*procref)(); X Xtypedef struct { X char type; X procref a; X procref b; X procref c; X procref d; X} Proto; X X/* the various protocols available. Add here for others */ Xextern procref getpkt, sendpkt, openpk, closepk; X Xextern int ggetpkt(), gsendpkt(), gopenpk(), gclosepk(); X/* Xextern int kgetpkt(), ksendpkt(), kopenpk(), kclosepk(); Xextern int rgetpkt(), rsendpkt(), ropenpk(), rclosepk(); Xextern int tgetpkt(), tsendpkt(), topenpk(), tclosepk(); X*/ X X/**/ Xextern int pktsize; /* packet size for this pro*/ Xextern FILE *logfile; /* system log file */ Xextern FILE *syslog; /* system log file */ Xextern FILE *fw; /* cfile pointer */ Xextern char cfile[80]; /* work file pointer */ Xextern int remote; /* -1 means we're remote*/ Xextern int findwork; Xextern int msgtime; /* timout setting */ Xextern char fromfile[132]; Xextern char hostfile[132]; /* host version of fromfile */ Xextern char tofile[132]; Xextern char state; /* present state */ Xextern int fp; /* current disk file ptr */ Xextern int size; /* nbytes in buff */ Xextern FILE *fsys; Xextern char Rmtname[20]; Xextern char rmtname[20]; Xextern char *cctime; Xextern char proto[5]; X Xextern char sysline[BUFSIZ]; Xextern char s_systems[64]; Xextern char s_logfile[64]; Xextern char s_syslog[64]; Xextern char *flds[60]; Xextern int kflds; X Xextern int debuglevel; /* debugging flag */ Xextern unsigned int checksum(); Xextern char *index(); Xextern char *rindex(); X Xextern char *curdir; X X X SHAR_EOF chmod 0600 dcp.h || echo "restore of dcp.h fails" sed 's/^X//' << 'SHAR_EOF' > dcpgpkt.c && X/* dcpgpkt.c X X Revised edition of dcp X X Stuart Lynne May/87 X X Copyright (c) Richard H. Lamb 1985, 1986, 1987 X Changes Copyright (c) Stuart Lynne 1987 X X*/ X/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */ X/* 3-window "g" ptotocol */ X/* Thanks got to John Gilmore for sending me a copy of Greg Chesson's XUUCP protocol description-- Obviously invaluable XThanks also go to Andrew Tannenbaum for the section on Siding window Xprotocols with a program example in his "Computer Networks" book X*/ X#include "dcp.h" X#define PKTSIZE 64 X#define PKTSIZ2 2 X#define HDRSIZE 6 X#define MAXTRY 4 X X#define MAXERR 200 /* Dont want to quit in a middle of a long file*/ X#define TIMEOUT 4 /* could be longer */ X#define KPKT 1024/PKTSIZE X#define POK -1 X X#define SWINDOW 3 /* fixed now, U make it variable */ X#define RWINDOW 3 X#define NBUF 8 /* always SAME as MAXSEQ ? */ X#define MAXSEQ 8 X X#define between(a,b,c) ((a<=b && b<c) || (c<a && a<=b) || (b<c && c<a)) X X/* packet defin */ Xstatic int rwl, swl, swu, rwu, nerr, nbuffers, npkt, irec, timeout, GOT_SYNC, GOT_HDR; Xstatic int fseq[NBUF], outlen[NBUF], inlen[NBUF], arr[NBUF]; Xstatic char outbuf[NBUF][PKTSIZE+1], inbuf[NBUF][PKTSIZE+1]; Xstatic unsigned char grpkt[HDRSIZE+1]; Xstatic long ftimer[NBUF], acktmr, naktmr; X/**/ X/******************SUB SUB SUB PACKET HANDLER************/ Xgopenpk() X{ X int i, j, n1, n2, len; X char tmp[PKTSIZE+1]; X pktsize = PKTSIZE; /* change it later after the init */ X msgtime = MSGTIME; /* not sure I need this for "g" proto */ X /* initialize proto parameters */ X swl = nerr = nbuffers = npkt = 0; X swl = swu = 1; X rwl = 0; X rwu = RWINDOW - 1; X for (i = 0; i < NBUF; i++) { X ftimer[i] = 0; X arr[i] = FALSE; X } X GOT_SYNC = GOT_HDR = FALSE; X /* 3-way handshake */ X timeout = 1; /* want some timeout capability here */ X gspack(7, 0, 0, 0, tmp); Xrsrt: X if (nerr >= MAXERR) X return(-1); X /* INIT sequence. Easy fix for variable pktsize and windows. */ X /* I didnt since all the machines I talk to use W=3 PKTSZ=64 */ X /* If you do this make sure to reflect the changes in "grpack" */ X /* and "gspack" */ X switch (grpack(&n1, &n2, &len, tmp)) { X case 7: X gspack(6, 0, 0, 0, tmp); X goto rsrt; X case 6: X gspack(5, 0, 0, 0, tmp); X goto rsrt; X case 5: X break; X default: X nerr++; X gspack(7, 0, 0, 0, tmp); X goto rsrt; X } X nerr = 0; X return(0); /* channel open */ X} X X Xgclosepk() X{ X int i; X char tmp[PKTSIZE+1]; X timeout = 1; X for (i = 0; i < MAXTRY; i++) { X gspack(CLOSE, 0, 0, 0, tmp); X if (gmachine() == CLOSE) X break; X } X printmsg( 0, "number of errors %d and pkts xfered %d", nerr, npkt ); X return(0); X} X X X/* X * X * ggetpkt X ***** description: Gets no more than a packet's worth of data from X**** the "packet i/o state machine". May have to X**** periodically run the pkt machine to get some X**** packets. X* on input: dont care getpkt(data,&len) char *data int len X* on return: data+\0 and length in len. ret(0) if alls well X* ret(-1) if problems.(fail) X */ Xggetpkt(cdata, len) Xint *len; Xchar cdata[]; X{ X int i2; X irec = 1; X timeout = 0; X /* WAIT FOR THE DESIRED PACKET */ X while ((arr[rwl]) == FALSE) X if (gmachine() != POK) X return(-1); X /* GOT A PKT ! */ X i2 = rwl; /*<-- mod(,rwindow) for larger than 8 seq no.s */ X *len = inlen[i2]; X strncpy(cdata, inbuf[i2], *len); X arr[i2] = FALSE; X rwu = (1 + rwu) % MAXSEQ; /* bump rec window */ X npkt++; X return(0); X} X X X/* X * X * sendpkt X * X***** description: Put at most a packet's worth of data in the pkt state X **** machine for xmission. X***** May have to run the pkt machine a few times to get X***** an available output slot. X * X * on input: char *data int len,flg; len=length of data in data. X * flg=2 just send the packet with no wait for ack. X * flg>0 zero out the unused part of the buffer. (for UUCP "msg" X * pkts) X * flg=0 normal data X * return: ret(0) if alls well ret(-1) if problems (fail) X * X*/ Xgsendpkt(cdata, len, flg) Xint len, flg; Xchar *cdata; X{ X int i, i1; X long ttmp; X irec = 0; X timeout = 0; /* non-blocking reads */ X /* WAIT FOR INPUT i.e. if weve sent SWINDOW pkts and none have been */ X /* acked, wait for acks */ X while (nbuffers >= SWINDOW) X if (gmachine() != POK) X return(-1); X i1 = swu; /* <--If we ever have more than 8 seq no.s, must mod() here*/ X /* PLACE PACKET IN TABLE AND MARK UNACKED */ X /* fill with zeros or not */ X if (flg) { X strcpy(outbuf[i1], cdata); X len = PKTSIZE; X for (i = strlen(cdata); i < len; i++) X outbuf[i1][i] = '\0'; X } else { X strncpy(outbuf[i1], cdata, len); X outbuf[i1][len] = '\0'; X } X /* mark packet */ X outlen[i1] = len; X ftimer[i1] = time(&ttmp); X fseq[i1] = swu; X swu = (1 + swu) % MAXSEQ; /* bump send window */ X nbuffers++; X npkt++; X /* send it */ X gspack(DATA, rwl, fseq[i1], outlen[i1], outbuf[i1]); X /* send it once then let the pkt machine take it. wouldnt need this for */ X /* mtasking systems */ X /* sl gmachine(); */ X return(0); X} X X X/************ packet machine ****** RH Lamb 3/87 */ X/* Idealy we would like to fork this process off in an infinite loop */ X/* and send and rec pkts thru "inbuf" and "outbuf". Cant do this in MS-DOS*/ X/* so we setup "getpkt" and "sendpkt" to call this routine often and return */ X/* only when the input buffer is empty thus "blocking" the pkt-machine task. */ Xgmachine() X{ X int rack, rseq, rlen, i1, i2, dflg; X char rdata[PKTSIZE+1]; X long ttmp, itmp; Xreply: X printmsg( 6, "*send %d<W<%d, rec %d<W<%d, err %d", swl, swu, rwl, rwu, nerr ); X /* waiting for ACKs for swl to swu-1. Next pkt to send=swu */ X /* rwl=expected pkt */ X printmsg( 7, "Kbytes transfered %d errors %d\r", npkt / KPKT, nerr ); X if (nerr >= MAXERR) X goto close; X dflg = 0; X switch (grpack(&rack, &rseq, &rlen, rdata)) { X case CLOSE: X printmsg( 5, "**got CLOSE"); X goto close; X case NAK: X nerr++; X acktmr = naktmr = 0; /* stop ack/nak timer */ X printmsg( 5, "**got NAK %d", rack ); Xnloop: X if (between(swl, rack, swu)) { /* resend rack->(swu-1) */ X i1 = rack; X gspack(DATA, rwl, rack, outlen[i1], outbuf[i1]); X printmsg( 5, "***resent %d", rack ); X ftimer[i1] = time(&ttmp); X rack = (1 + rack) % MAXSEQ; X goto nloop; X } X if (dflg) X return(POK); X goto reply; /* any other stuff ? */ X X case EMPTY: X printmsg( 5, "**got EMPTY" ); X itmp = time(&ttmp); X if (acktmr) X if ((itmp - acktmr) >= TIMEOUT) { /* ack timed out*/ X gspack(ACK, rwl, 0, 0, rdata); X acktmr = itmp; X } X if (naktmr) X if ((itmp - naktmr) >= TIMEOUT) { /*nak timed out*/ X gspack(NAK, rwl, 0, 0, rdata); X naktmr = itmp; X } X /* resend any timed out un-acked pkts */ X for (i2 = swl; between(swl, i2, swu); i2 = (1 + i2) % MAXSEQ) { X acktmr = naktmr = 0; /* reset ack/nak */ X i1 = i2; X printmsg( 5, "--->seq,elapst %d %ld", i2, (itmp - ftimer[i1]) ); X if ((itmp - ftimer[i1]) >= TIMEOUT) { X printmsg( 5, "***timeout %d", i2 ); X /* since "g" is "go-back-N", when we time out we */ X /* must send the last N pkts in order. The generalized*/ X /* sliding window scheme relaxes this reqirment */ X nerr++; X dflg = 1; /* same hack */ X rack = i2; X goto nloop; X } X } X return(POK); X case ACK: X printmsg( 5, "**got ACK %d", rack ); X acktmr = naktmr = 0; /* disable ack/nak's */ Xaloop: X if (between(swl, rack, swu)) { /* S<-- -->(S+W-1)%8 */ X printmsg( 5, "***ACK %d", swl ); X ftimer[swl] = 0; X nbuffers--; X swl = (1 + swl) % MAXSEQ; X dflg = 1; /* same hack */ /* sl */ X goto aloop; X } X if (dflg) X return(POK); /* hack for non-mtask sys's */ X /* to empty "inbuf[]" */ X goto reply; X case DATA: X printmsg( 5, "**got DATA %d %d", rack, rseq ); X i1 = (1 + rwl) % MAXSEQ; /* (R+1)%8 <-- -->(R+W)%8 */ X i2 = (1 + rwu) % MAXSEQ; X if (between(i1, rseq, i2)) { X if (i1 == rseq) { X i1 = rseq; X arr[i1] = TRUE; X inlen[i1] = rlen; X strncpy(inbuf[i1], rdata, rlen); X rwl = (rwl + 1) % MAXSEQ; X printmsg( 5, "***ACK d %d", rwl ); X gspack(ACK, rwl, 0, 0, rdata); X acktmr = time(&ttmp); /* enable ack/nak tmout*/ X dflg = 1; /*return to call when finished*/ X /* in a mtask system, unneccesary */ X } else { X nerr++; X printmsg( 5, "***unexpect %d ne %d", rseq, rwl ); X } X } else { X nerr++; X printmsg( 5, "***wrong seq %d", rseq ); X } X goto aloop; X case ERROR: X nerr++; X printmsg( 5, "**got BAD CHK" ); X gspack(NAK, rwl, 0, 0, rdata); X naktmr = time(&ttmp); /* set nak timer */ X printmsg( 5, "***NAK d %d", rwl ); X goto reply; X default: X printmsg( 5, "**got SCREW UP" ); X goto reply; /* ignore it */ X } Xclose: X gspack(CLOSE, 0, 0, 0, rdata); X return(CLOSE); X} X X X/**/ X/*************** FRAMMING *****************************/ X/* X * X * X * send a packet X * nt2=type nt3=pkrec nt4=pksent len=length<=PKTSIZE cnt1= data * ret(0) always X */ Xgspack(nt2, nt3, nt4, len, cnt1) Xint nt2, nt3, nt4, len; Xchar cnt1[]; X{ X unsigned int check, i; X unsigned char c2, pkt[HDRSIZE+1], dpkerr[10]; X if (len > 64) X len = 64; X if (len == 0) X cnt1[0] = '\0'; X/**Link testing mods- create artificial errors ***/ /* Xprintf("**n:normal,e:error,l:lost,p:partial,h:bad header,s:new seq--> "); Xgets(dpkerr); X if(dpkerr[0] == 's') { sscanf(&dpkerr[1],"%d",&nt4); } /**/ X /** End Link testing mods ***/ X printmsg( 5, "send packet type %d, num=%d, n=%d, len=%d", nt2, nt3, nt4, len ); X printmsg( 5, "data =\n|%s|", cnt1 ); X c2 = '\0'; X pkt[0] = '\020'; X pkt[4] = nt2 << 3; X nt2 &= 7; X switch (nt2) { X case 1: X break; /* stop protocol */ X case 2: X pkt[4] += nt3; X break; /* reject */ X case 3: X break; X case 4: X pkt[4] += nt3; X break; /* ack */ X case 5: X pkt[4] += SWINDOW; X break; /* 3 windows */ X case 6: X pkt[4] += 1; X break; /* pktsiz = 64 (1) */ X case 7: X pkt[4] += SWINDOW; X break; /* 3 windows */ X case 0: X pkt[4] += 0x80 + nt3 + (nt4 << 3); X c2 = (PKTSIZE - len) & 0xff; X /* havnt set it up for VERY LONG pkts with a few */ X /* bytes yet (-128) */ X if (c2) { /* short packet handling */ X pkt[4] += 0x40; /* if len < PKTSIZE */ X for (i = PKTSIZE - 1; i > 0; i--) X cnt1[i] = cnt1[i-1]; X cnt1[0] = c2; X } X break; X } X pkt[4] &= 0xff; X if (nt2) { X pkt[1] = 9; /* control packet size = 0 (9) */ X check = (0xaaaa - pkt[4]) & 0xffff; X } else { X pkt[1] = PKTSIZ2; /* data packet size = 64 (2) */ X check = checksum(cnt1, PKTSIZE); X i = pkt[4];/* got to do this on PC for ex-or high bits */ X i &= 0xff; X check = (check ^ i) & 0xffff; X check = (0xaaaa - check) & 0xffff; X } X pkt[2] = check & 0xff; X pkt[3] = (check >> 8) & 0xff; X pkt[5] = (pkt[1] ^ pkt[2] ^ pkt[3] ^ pkt[4]) & 0xff; X/***More Link testing MODS ******/ /* Xswitch(dpkerr[0]) { Xcase 'e': cnt1[10] = -cnt1[10]; X break; Xcase 'h': pkt[5] = -pkt[5]; X break; Xcase 'l': return; Xcase 'p': swrite(pkt,HDRSIZE); X if(pkt[1] != 9) swrite(cnt1,PKTSIZE-3); X return; Xdefault: break; X } /**/ X /******End Link Testing Mods **********/ X swrite(pkt, HDRSIZE); /* header is 6-bytes long */ X /* write(flog,pkt,HDRSIZE); */ X if (pkt[1] != 9) { X swrite(cnt1, PKTSIZE); /* data is always 64 X bytes long */ X /* write(flog,cnt1,PKTSIZE); */ X } X} X X X/**/ X/* X * X * read packet X * on return: nt3=pkrec nt4=pksent len=length <=PKTSIZE cnt1=data * X * ret(type) ok; ret(EMPTY) input buf empty; ret(ERROR) bad header; X * ret(EMPTY) lost pkt timeout; ret(ERROR) checksum error;ret(-5) ? X****NOTE : X***sread(buf,n,timeout) X while(TRUE) { X if(# of chars available >= n) (without dec internal counter) X read n chars into buf (decrenent internal char counter) X break X else X if(time>timeout) break X } X return(# of chars available) X****END NOTE X */ Xgrpack(nt3, nt4, len, cnt1) Xint *nt3, *nt4, *len; Xchar cnt1[]; X{ X unsigned int nt1, check, checkchk, i; X unsigned char c, c2; X int ii; X if (GOT_SYNC) X goto get_hdr; X if (GOT_HDR) X goto get_data; X c = '\0'; X while ((c & 0x7f) != '\020') X if (sread(&c, 1, timeout) == 0) X return(EMPTY); X GOT_SYNC = TRUE; Xget_hdr: X if (sread(&grpkt[1], HDRSIZE - 1, timeout) < (HDRSIZE - 1)) X return(EMPTY); X GOT_SYNC = FALSE; X /*i = grpkt[1] ^ grpkt[2] ^ grpkt[3] ^ grpkt[4] ^ grpkt[5];*/ X i = (unsigned)grpkt[1] ^ (unsigned)grpkt[2] ^ X (unsigned)grpkt[3] ^ (unsigned)grpkt[4] ^ X (unsigned)grpkt[5]; X X i &= 0xff; X printmsg( 10, "prpkt %02x %02x %02x %02x %02x .. %02x ", X grpkt[1], grpkt[2], grpkt[3], grpkt[4], grpkt[5], X i X ); X X if (i) { /* bad header */ X printmsg( 0, "****bad header****" ); X return(ERROR); /* Im not sure whether "g" considers it an empty or error */ X } X GOT_HDR = TRUE; X if ((grpkt[1] &= 0x7f) == 9) { /* control packet */ X *len = 0; X c = grpkt[4] & 0xff; X nt1 = c >> 3; X *nt3 = c & 7; X *nt4 = 0; X check = 0; X checkchk = 0; X cnt1[*len] = '\0'; X GOT_HDR = FALSE; X } else { /* data packet */ X if (grpkt[1] != PKTSIZ2) X return(-5); /* cant handle other than 64*/ Xget_data: X if (sread(cnt1, PKTSIZE, timeout) < PKTSIZE) X return(EMPTY); X GOT_HDR = FALSE; X nt1 = 0; X c2 = grpkt[4] & 0xff; X c = c2 & 0x3f; X *nt4 = c >> 3; X *nt3 = c & 7; X i = grpkt[3]; X i = (i << 8) & 0xff00; X check = grpkt[2]; X check = i | (check & 0xff); X checkchk = checksum(cnt1, PKTSIZE); X i = grpkt[4] | 0x80; X i &= 0xff; X checkchk = 0xaaaa - (checkchk ^ i); X checkchk &= 0xffff; X if (checkchk != check) { X printmsg( 4, "***checksum error***" ); X return(ERROR); X } X *len = PKTSIZE; X /* havnt set it up for very long pkts yet (>128) RH Lamb */ X if (c2 & 0x40) { X ii = (cnt1[0] & 0xff); X *len = (*len - ii) & 0xff; X for (ii = 0; ii < *len; ii++) X cnt1[ii] = cnt1[ii+1]; X } X cnt1[*len] = '\0'; X } X printmsg( 5, "rec packet type %d, num=%d, n=%d, len=%d", nt1, *nt3, *nt4, *len ); X printmsg( 6, " checksum rec = %x comp = %x, data=\n|%s|", check, checkchk, cnt1 ); X ii = nt1; X return(ii); X} X X Xunsigned checksum(data, len) Xint len; Xchar data[]; X{ X unsigned int i, j, tmp, chk1, chk2; X chk1 = 0xffff; X chk2 = 0; X j = len; X for (i = 0; i < len; i++) { X if (chk1 & 0x8000) { X chk1 <<= 1; X chk1++; X } else { X chk1 <<= 1; X } X tmp = chk1; X chk1 += (data[i] & 0xff); X chk2 += chk1 ^ j; X if ((chk1 & 0xffff) <= (tmp & 0xffff)) X chk1 ^= chk2; X j--; X } X return(chk1 & 0xffff); X} X X X/* */ X/* Xgwrmsg X send a null terminated string out X*/ Xgwrmsg( typ, buf ) Xchar typ; Xchar *buf; /* null terminated */ X{ X} X X/* Xgrdmsg X read a null terminated string X*/ Xgrdmsg( buf ) Xchar * buf; X{ X X} X X/* Xgwrdata X read a file and send it out X*/ Xgwrdata( f ) X{ X} X X/* Xgrrdata X read in data and send to file X*/ Xgrrdata( f ) X{ X} X X X/* Xgrdblk X read a block of data in X*/ Xgrdblk( blk, len ) X{ X} X X/* Xgwrblk X write out a block of data X*/ Xgwrblk( blk, len ) X{ X} X SHAR_EOF chmod 0600 dcpgpkt.c || echo "restore of dcpgpkt.c fails" sed 's/^X//' << 'SHAR_EOF' > dcpsys.c && X X/* dcpsys.c X X Revised edition of dcp X X Stuart Lynne May/87 X X Copyright (c) Richard H. Lamb 1985, 1986, 1987 X Changes Copyright (c) Stuart Lynne 1987 X X*/ X/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */ X/* Get the next system, and other support routines */ X#include "dcp.h" X/*#define PROTOS "trkg"*/ X#define PROTOS "g" X#define MAXLOGTRY 3 X XProto Protolst[] = { X 'g', ggetpkt, gsendpkt, gopenpk, gclosepk, X/* X 'k', kgetpkt, ksendpkt, kopenpk, kclosepk, X 'r', rgetpkt, rsendpkt, ropenpk, rclosepk, X 't', tgetpkt, tsendpkt, topenpk, tclosepk, X*/ X '0'}; X X#define EOTMSG "\004\r\004\r" X Xprocref getpkt, sendpkt, openpk, closepk; X X/**/ X X/***************************************************************/ X/*** Sub Systems */ X/* X** X**getsystem X** Process an "systems" file entry (like L.sys) X*/ Xgetsystem() X{ X int i; X X do { X if ( ! fgets( sysline, BUFSIZ, fsys ) ) X return( 'A' ); X printmsg( 2, "%s", sysline ); X } while (sysline[0] == '#'); X X kflds = getargs( sysline, flds ); X strcpy( rmtname, flds[FLD_REMOTE] ); X cctime = flds[FLD_CCTIME]; X strcpy( device, flds[FLD_DEVICE] ); X X /* strcpy( type, flds[FLD_TYPE] ); */ X strcpy( speed, flds[FLD_SPEED] ); X strcpy( proto, flds[FLD_PROTO] ); X X X if (debuglevel > 3) X for (i = FLD_EXPECT; i < kflds; i += 2) X fprintf( stderr, "expect[%02d]:\t%s\nsend [%02d]:\t%s\n", X i, flds[i], i+1, flds[i+1] ); X X printmsg( 2, "rmt= %s ctm= %s", rmtname, flds[FLD_CCTIME] ); X printmsg( 2, "dev= %s ", device ); X printmsg( 2, "spd= %s pro= %s", speed, proto ); X fw = (FILE *)NULL; X if ( X /* (checktime( cctime )) || */ X ( strncom( Rmtname, "all", 4 ) == SAME ) || X ( strncom( Rmtname, rmtname, -1 ) == SAME ) || X ( (strncom( Rmtname, "any", 4 ) == SAME) && scandir() == 'S' ) X ) X { X if ( fw != (FILE *)NULL ) X fclose( fw ); /* in case we matched with scandir */ X return( 'S' ); /* startup this system */ X } X else X return('G'); X} X X/* X** X**checktime X** check if we may make a call at this time X**------------>to be implemented. Again. Didnt think it crucial X*/ Xchecktime(xtime) Xchar xtime[]; X{ X return(0); /* OK go to it */ X} X X X X/**/ X/* X** X**sysend X** end UUCP session negotiation X*/ Xsysend() X{ X char msg[80]; X X msg[1] = '\0'; X msgtime = 2 * MSGTIME; X /* while (msg[1] != 'O') { */ X wmsg("OOOOOO", 2); X if (rmsg(msg, 2) == -1) X goto hang; X /*}*/ Xhang: X wmsg("OOOOOO", 2); X closeline(); X if ( remote == MASTER ) X return('I'); X return('A'); X} X X X/**/ X/* X** X** delay X** X*/ X/*ddelay(dtime) Xint dtime; X{ X int i, j; X for (i = 0; i < dtime; i++) { X } X} X*/ X X/**/ X/* X** X**wmsg X** write a ^P type msg to the remote uucp X*/ Xwmsg(msg, syn) Xchar *msg; Xint syn; X{ X int len; X len = strlen(msg); X if (syn == 2) X swrite("\020", 1); X swrite(msg, len); X if (syn == 2) X swrite("\n", 2); X} X X X/* X** X**rmsg X** read a ^P msg from UUCP X*/ Xrmsg(msg, syn) Xint syn; Xchar msg[]; X{ X int ii; X char c, cc[5]; X /* *msg0;*/ X /*msg0 = msg;*/ X c = 'a'; X if (syn == 2) { X while ((c & 0x7f) != '\020') { X if (sread(cc, 1, msgtime) < 1) X return(-1); X c = cc[0]; /* Dont ask. MSC needs more than a byte to breathe */ X /* printf("Hello im in rmsg c=%x\n",c); */ X } X } X for (ii = 0; ii < 132 && c ; ii++) { X if (sread(cc, 1, msgtime) < 1) X return(-1); X c = cc[0] & 0x7f; X if (c == '\r' || c == '\n') X c = '\0'; X msg[ii] = c; X /*if(c == '\020') msg = msg0; */ X } X return(strlen(msg)); X} X X X X/**/ X/* X** X** X**startup X** X** X*/ Xstartup() X{ X char msg[80], tmp1[20], tmp2[20]; X if ( remote == MASTER ) { X msgtime = 2 * MSGTIME; X if (rmsg(msg, 2) == -1) X return('Y'); X printmsg( 2, "1st msg = %s", msg ); X if (msg[5] == '=' && strncmp(&msg[6], rmtname, 7)) X return('Y'); X X /*sprintf(msg, "S%.7s -Q0 -x%d", nodename, debuglevel);*/ /* -Q0 -x16 remote debuglevel set */ X sprintf(msg, "S%.7s", nodename); X X wmsg(msg, 2); X if (rmsg(msg, 2) == -1) X return('Y'); X printmsg( 2, "2nd msg = %s", msg ); X if (strncmp(&msg[1], "OK", 2)) X return('Y'); X if (rmsg(msg, 2) == -1) X return('Y'); X printmsg( 2, "3rd msg = %s", msg ); X if (msg[0] != 'P' || index(&msg[1], proto[0]) == (char *)NULL) { X wmsg("UN", 2); X return('Y'); X } X sprintf(msg, "U%c", proto[0]); X wmsg(msg, 2); X setproto(proto[0]); X return('D'); X } else { X msgtime = 2 * MSGTIME; X sprintf(msg, "Shere=%s", nodename); X wmsg(msg, 2); X if (rmsg(msg, 2) == -1) X return('Y'); X sscanf(&msg[1], "%s %s %s", rmtname, tmp1, tmp2); X sscanf(tmp2, "-x%d", &debuglevel); X printmsg( 1, "debuglevel level = %d", debuglevel ); X printmsg( 2, "1st msg from remote = %s", msg ); X if (checkname(rmtname)) X return('Y'); X wmsg("ROK", 2); X sprintf(msg, "P%s", PROTOS); X wmsg(msg, 2); X if (rmsg(msg, 2) == -1) X return('Y'); X if (msg[0] != 'U' || index(PROTOS, msg[1]) == (char *)NULL ) X return('Y'); X proto[0] = msg[1]; X setproto(proto[0]); X return('R'); X } X} X X X/******* set the protocol **********/ Xsetproto(pr) Xchar pr; X{ X int i; X Proto * tproto; X for (tproto = Protolst; tproto->type != '\0' && pr != tproto->type; tproto++) { X printmsg( 3, "setproto: %c %c", pr, tproto->type ); X } X if (tproto->type == '\0') { X printmsg( 0, "setproto:You said I had it but I cant find it" ); X exit(1); X } X getpkt = tproto->a; X sendpkt = tproto->b; X openpk = tproto->c; X closepk = tproto->d; X} X X X X/**/ Xint prefix(sh,lg) Xchar *sh,*lg; X{ X return( strncmp(sh,lg,strlen(sh)) == SAME); X} X Xint notin(sh,lg) Xchar *sh,*lg; X{ X while (*lg) { X if (prefix(sh,lg++)) X return( FALSE ); X } X return( TRUE ); X} X X#define MAXR 300 Xint expectstr( str, timeout ) Xchar *str; X{ X static char rdvec[MAXR]; X char *rp = rdvec; X int kr; X char nextch; X X printmsg( 0, "wanted %s", str ); X X if ( strcmp(str, "\"\"") == SAME ) { X return( TRUE ); X } X *rp = 0; X while ( notin( str,rdvec ) ) { X /* fprintf(stderr, "---------->%s<------\n", rdvec);/**/ X kr = sread( &nextch, 1, timeout /* 40 */ ); X /* nextch &= 0177; X fprintf(stderr, "kr - %2d '%c'\n", kr, nextch); */ X if (kr <= 0) { X return( FALSE ); X } X if ((*rp = nextch & 0177) != '\0') { X rp++; X } X *rp = '\0'; X if (rp >= rdvec + MAXR) { X return( FALSE ); X } X } X return( TRUE ); X} X Xint writestr(s) X register char *s; X{ X register char last; X register char * m; X int nocr; X last = '\0'; X nocr = FALSE; X while (*s) { X if (last == '\\') { X switch (*s) { X case 'd': X case 'D': /* delay */ X sleep(2); X break; X case 'c': X case 'C': /* end string don't output CR */ X nocr = TRUE; X break; X case 'r': X case 'R': /* carriage return */ X case 'm': X case 'M': X swrite( "\r", 1 ); X break; X case 'n': X case 'N': X swrite( "\n", 1 ); X break; X case 'b': X case 'B': X swrite( "\b", 1 ); X break; X case 't': X case 'T': X swrite( "\t", 1 ); X break; X case 's': X case 'S': X swrite( " ", 1 ); X break; X case 'z': X case 'Z': X SIOSpeed( ++s ); X while ( *s != '\0' && *s != '\\' ) X s++; X if ( *s == '\\' ) X s++; X break; X default: X swrite( s, 1 ); X } X last = '\0'; X } X else if (*s != '\\') { X swrite( s, 1 ); X /* fputc(*s,stderr); */ X } X else { X last = *s; X } X s++; X } X return( nocr ); X} X X/*** X * void sendthem(str) send line of login sequence X * char *str; X * X * return codes: none X */ X Xvoid sendstr(str) Xchar *str; X{ X int nw, ns; X int nulls; X X printmsg( 2, "sending %s", str ); X X#ifdef BREAK X if (prefix("BREAK", str)) { X sscanf(&str[5], "%1d", &nulls); X if (nulls <= 0 || nulls > 10) X nulls = 3; X /* send break */ X ssendbrk(nulls); X return; X } X#endif X X if ( strcmp(str, "EOT") == SAME ) { X swrite(EOTMSG, strlen(EOTMSG)); X return; X } X X if ( strcmp(str,"\"\"") == SAME ) X *str = '\0'; X /*fprintf(stderr,"'%s'\n",str);*/ X X if ( strcmp(str,"") != SAME ) { X if (!writestr(str)) { X swrite ("\r", 1); X } X } X else { X swrite("\r", 1); X } X return; X} X Xint sendexpect( s, e, timeout ) Xchar * s; Xchar * e; X{ X sendstr( s ); X return( expectstr( e, timeout ) ); X} X Xdial() X{ X int flg, kk, jj, ll, firstflg; X char buf[4], *prsend; X X char *exp; X char *alternate; X int ok; X int doofosity=0; X int i; X X if ( strcmp( flds[FLD_TYPE], "HAYES" ) != SAME ) { X printmsg( 0, "dial: unsupported dialer %s", flds[FLD_TYPE] ); X return( FALSE ); X } X X printmsg( 3, "calling host %s", rmtname ); X if (openline(device, "2400" )) X return( FALSE ); X/* X printmsg( 0, "hayes: trying 2400" ); X if ( sendexpect( "\\r\\dATZ", "OK", 4 ) != TRUE ) { X sendexpect( "\\d+++\\d", "OK", 2 ); X if ( sendexpect( "ATZ", "OK", 2 ) != TRUE ) { X printmsg( 0, "hayes: trying 1200" ); X SIOSpeed( "1200" ); X if ( sendexpect( "ATZ", "OK", 2 ) != TRUE ) { X sendexpect( "\\d+++\\d", "OK", 2 ); X if ( sendexpect( "ATZ", "OK", 2 ) != TRUE ) X return( FALSE); X } X } X } X printmsg( 0, "hayes: got modem response" ); X*/ X /*(sendstr( "\\d\\dATS7=30" ); X expectstr( "OK", 40 );*/ X X sendstr( "\\dATX4\\c" ); X sendstr( speed ); X X if ( sendexpect( "", "CONNECT ", 40 ) == TRUE ) { X printmsg( 3, "hayes: got CONNECT" ); X X if ( sread( buf, 4, 4 ) == 4 ) { X printmsg( 0, "hayes: speed select %s", buf ); X /* set speed appropriately */ X SIOSpeed( buf ); X } X return( TRUE ); X } X return( FALSE ); X} X X X/* X** X**callup X** script processor - nothing fancy! X*/ Xcallup() X{ X int flg, kk, jj, ll, firstflg; X char *prsend; X X char *exp; X char *alternate; X int ok; X int i; X X printmsg( 0, "calling host %s", rmtname ); X X if ( strcmp( flds[FLD_TYPE], "DIR" ) != SAME ) { X if ( dial() == FALSE ) X return( 'G' ); X } X else if (openline(device, speed)) X return( 'G' ); X X for (i = 6; i < kflds; i+=2) { X X exp = flds[i]; X printmsg( 2, "callup: expect %d of %d \"%s\"", i, kflds, exp ); X X ok = FALSE; X while (ok != TRUE) { X int time = 30; X char *timel; X X timel = index( exp, '~' ); X if (timel != (char *)NULL) X { X time = atoi(timel+1); X alternate = timel+1; X while (isdigit(*alternate)) X alternate++; X strcpy(timel, alternate); X } X X alternate = index( exp, '-' ); X if (alternate != (char *)NULL) X *alternate++ = '\0'; X X ok = expectstr( exp, time ); X X printmsg( 1, "got %s", ok != TRUE ? "?" : "that" ); X X if ( ok == TRUE ) { X printmsg( 0, "got that" ); X break; X } X X if ( alternate == (char *)NULL ) { X printmsg( 0, "LOGIN FAILED" ); X return( 'Y' ); X } X X exp = index( alternate, '-' ); X if ( exp != (char *)NULL ) X *exp++ = '\0'; X X printmsg( 0, "send alternate" ); X X sendstr( alternate ); X } X X printmsg( 2, "callup: send %d of %d \"%s\"", i+1, kflds, flds[i+1] ); X sleep(1); /* (1)*/ X sendstr(flds[i+1]); X } X return('P'); X X} X X/**/ X/* X** X** slowrite X** comunication slow write. needed for auto-baud modems X*/ X/*slowrite(st) Xregister char *st; X{ X int len, j; X char c; X len = strlen(st); X printmsg( 2, "sent %s", st ); X for (j = 0; j < len; j++) { X swrite(&st[j], 1); X ddelay(80000); X } X} X*/ X X/**/ X/* X** X**scandir X** X*/ X X#include "ndir.h" X X X/* scandir X X scan work dir for C. files matching current remote host (rmtname) X X return X X A - abort X Y - can't open file X S - ok X Q - no files X X*/ Xscandir() X{ X int fn, len, i; X char cname[40], tmp[132]; X X DIR *dirp; X struct direct *dp; X X if ((dirp = opendir( spooldir )) == (DIR *)NULL ) { X fprintf( stderr, "couldn't open dir %s\n", spooldir ); X return( 'A' ); X } X sprintf(cname, CALLFILE, rmtname); X len = strlen(cname); X while ((dp = readdir(dirp)) != (struct direct *)NULL) { X printmsg( 4, "scandir: %s", dp->d_name ); X if ( strncom( cname, dp->d_name, len ) == SAME ) { X printmsg( 4, "scandir: match!!" ); X strcpy(cfile, dp->d_name); X closedir( dirp ); X if ((fw = FOPEN( cfile, "r", 't' )) == (char *)NULL ) X return('Y'); X return('S'); X } X } X closedir( dirp ); X return('Q'); X X} X X X/**/ X/* X** X**dscandir X** scan the directory X*/ X Xdscandir() X{ X int fn, len, i; X char cname[40], tmp[132]; X X DIR *dirp; X struct direct *dp; X X X if ((dirp = opendir( spooldir )) == (DIR *)NULL ) { X fprintf( stderr, "couldn't open dir %s\n", spooldir ); X return(0); SHAR_EOF echo "End of part 1, continue with part 2" echo "2" > s2_seq_.tmp exit 0