Date: Mon, 21 Mar 88 00:13:12 EST
From: ain@j.cc.purdue.edu (Patrick White)
To: fys-ma@fintuvm.BITNET
Subject: posting to: news/comp/sources/amiga/volume4
 
Article 172 of comp.sources.amiga:
From: ain@j.cc.purdue.edu (Patrick White)
Newsgroups: comp.sources.amiga
Subject: uupc  version 1.1  (part 1 of 3)
Keywords: part 1 of 3, version 1.1, uupc, uncompiled
Date: 21 Mar 88 05:02:47 GMT
Organization: PUCC Land, USA
Approved: ain@j.cc.purdue.edu  (Pat White)
 
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
