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