🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.sys.atari.st
Article #24793

Uemail source (4 of 12)

#24793
From: RDROYA01
Date: Thu, 05 Feb 1987 11:24
1587 lines
58159 bytes
#       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:
#       kermit.c
#       kertrans.c
#       kerrec.c
#       kertty.c
# This archive created: Tue Feb  3 17:54:14 1987
cat << \SHAR_EOF > kermit.c
/* kermit.c  support routines and main entry point for Uemail file transfer
 * functions.  Kermit send, receive, get, put, finish, and bye supported.
 * Buffer logging and direct ASCII transfer also available.  All actions are
 * ASCII 7 bit files.  Transfers are made into and out of Uemail buffers.
 */
 
#include <stdio.h>
#include <osbind.h>
#include <ctype.h>
#include "ed.h"
#include "kermit.h"
 
 
int emacsfile;          /* if TRUE then \r become \n on ASCII transfers */
char getfiln[NFILEN];   /* name for remote file get or put */
char deflow[] = "XON/XOFF";
static unsigned char *tsr_ptr = (char *)0x00fffa2d; /* See St internals */
static long *hz_200 =  (long *)0x000004ba;
int *aaddress(); /* thanks Jwahar R. Bammi for this line A code */
int *aline_addr; /* Ptr to base of Aline variables */
int sav_row, sav_col;
int flow = DEFLO;       /* default flow control */
int defbaud = 7;
int bps = DEFBPS;
unsigned long *hpterm;  /* HOST */
 
/* KERMIT CTRL command prompt for action and switch to appropriate state.
 * Returns TRUE on success. !TRUE on failures.  Bound to ^_ and HELP on ST.
 */
kermit(flg, _n)
register int flg, _n;
{
        static char command[9]; /* command */
        register char key;
        register int owf;
 
        owf = curwp->w_flag;            /* save for redraw */
 
        if ((_n=mlreply("Kermit-ST> ",command,8)) != TRUE)
                return(_n==FALSE ? FALSE : ABORT);
 
        /* Initialize these values */
        /* Hope the first packet will get across OK */
 
        eol = CR;               /* EOL for outgoing packets */
        quotech = '#';          /* Standard control-quote char "#" */
        pad = 0;                /* No padding */
        padchar = '\0';         /* Use null if any padding wanted */
        timint = DEFTIME;       /* Default timeout */
        parity = DEFPAR;        /* Default to no parity */
        logfile = 0;            /* Capture flag */
        emacsfile = 0;          /* Trans to emacs (no EOF) */
        en8quote(FALSE);
 
        key = tolower(command[0]);
        switch (key)
                {
                case 'b':               /* B = Bye */
                        if(mlyesno("Logout remote")==TRUE)
                                if(gencmdsw('L')==FALSE)
                                        {
                                        mlwrite("Remote does not ACK BYE");
                                        (*term.t_beep)();
                                        return(FALSE);
                                        }
                        return(TRUE);   /* No update */
                case 'c':              /* C = Connect command */
                        connect();
                        break;
                case 'e':              /* E = transmit to GNU_EMACS command */
                        if(usebuffer(NULL,NULL) != TRUE)
                                return(FALSE);
                        gotobob(NULL, 1);
                        update();
                        mlwrite("[Transmitting %s to remote EMACS]",curbp->b_bna
me);
                        emacsfile = 1;
                        trans();
                        emacsfile = 0;
                        connect();
                        break;
                case 'f':               /* F = Finish */
                        if(gencmdsw('F')==FALSE)
                                {
                                mlwrite("Remote does not ACK FINISH");
                                (*term.t_beep)();
                                return(FALSE);
                                }
                        return(TRUE);   /* No update */
                case 'g':              /* G = Get command */
                        if((_n=mlreply("Remote filename: ",getfiln,NFILEN))!=TRU
E)
                                return(_n);
                        if(usebuffer(NULL,NULL) != TRUE)
                                return(FALSE);
                        gotoeob(NULL, 1);
                        update();
                        if((_n=getsw()) == FALSE)
                                {
                                (*term.t_beep)();
                                mlreply("Get failed. Type <CR>",command,2);
                                }
                        break;
                case 'l':       /* L = Log session */
                        if(usebuffer(NULL,NULL) != TRUE)
                                return(FALSE);
                        gotoeob(NULL, 1);
                        logfile = TRUE;
                        connect();
                        break;
                case 'r':              /* R = Receive command */
                        if(usebuffer(NULL,NULL) != TRUE)
                                return(FALSE);
                        gotoeob(NULL, 1);
                        update();
                        if((_n=recsw()) == FALSE)
                                {
                                (*term.t_beep)();
                                mlreply("Receive failed. Type <CR>",command,2);
                                }
                        break;
                case 'p':               /* P = Put command */
                        if((_n=mlreply("Remote filename: ",getfiln,NFILEN))!=TRU
E)
                                return(_n);
                case 's':               /* S = Send command */
                        if(usebuffer(NULL,NULL) != TRUE)
                                return(FALSE);
                        if (key == 's')
                                strcpy(getfiln,curbp->b_bname);
                        gotobob(NULL, 1);
                        update();
                        if((_n=sendsw()) == FALSE)
                                {
                                if (key == 's')
                                        mlwrite("Send failed");
                                else
                                        mlwrite("Put failed");
                                (*term.t_beep)();
                                }
                        if (key == 's')
                                connect();
                        break;
                case 't':              /* T = transmit command */
                        if(usebuffer(NULL,NULL) != TRUE)
                                return(FALSE);
                        gotobob(NULL, 1);
                        update();
                        mlwrite("[Transmitting: %s]",curbp->b_bname);
                        trans();
                        connect();
                        break;
                default:
                        mlwrite("Connect, Send, Receive, Get, Put, Finish, Bye\
, Log, Transfer");
 
                        return(FALSE);
                }
        /* Restore controlling tty's modes */
 
        owf |= WFHARD; owf |= WFMODE;
        curwp->w_flag |= owf;
        sgarbf = TRUE;  /* we know screen is garbage after connect */
        update();
        return(TRUE);
}
 
/*
*      c o n n e c t
*
* Establish a virtual terminal connection with the remote host, over an
* assigned tty line.
*/
 
connect()
{
        register int c;
 
        setterm(REMOTE);
        while (1)
                {
                if (Bconstat(2))
                        if(readcon() == FALSE)
                                break;
                if (Bconstat(1))
                        {
                        c=readaux();
                        ttputc(c);
                        if (logfile)
                                {
                                if (c=='\n')
                                        {
                                        lnewline();
                                        continue;
                                        }
                                if (c=='\r')
                                        continue;
                                linsert(1,c);
                                }
                        }
                }
        setterm(HOST);
        return(FALSE);
}
 
/* set up terminal's screen and allow it to be saved for later.
 */
setterm(f)
int f;
{
        static char scrbase[0x7d10];
        static unsigned char firsttime = TRUE;
        extern int deskcol;
 
        if (hpterm == NULL)
                hpterm = Physbase();    /* init TERM screen address */
        if (f == REMOTE)
                {
                Bconout(2,0x1b);        /* disable cursor */
                Bconout(2,'f');
                copy(scrbase,hpterm,0x7d00);
                if (firsttime)
                        {
                        aline_addr = aaddress();
                        Bconout(2,0x1b);        /* clear screen */
                        Bconout(2,'E');
                        showhelp();
                        sav_row = aline_addr[-13];/* save cursor position */
                        sav_col = aline_addr[-14];
                        Rsconf(defbaud,flow,-1,-1,-1,-1);
                        mtwrite("[%s active at %dbps]",deflow,bps);
                        firsttime = FALSE;
                        }
                (*term.t_move)(sav_row,sav_col);
                Bconout(2,0x1b);        /* enable cursor */
                Bconout(2,'e');
                return(TRUE);
                }
        else if (f == HOST)
                {
                sav_row = aline_addr[-13];      /* save cursor position */
                sav_col = aline_addr[-14];
                Bconout(2,0x1b);        /* disable cursor */
                Bconout(2,'f');
                copy(hpterm,scrbase,0x7d00);
                ttopen();               /* restore uemail screen */
                Bconout(2,0x1b);        /* enable cursor */
                Bconout(2,'e');
                return(TRUE);
                }
        else if (f == SHOWHELP)
                {
                sav_row = aline_addr[-13];      /* save cursor position */
                sav_col = aline_addr[-14];
                Bconout(2,0x1b);                /* disable cursor */
                Bconout(2,'f');
                copy(hpterm,scrbase,0x7d00);    /* save current screen */
                showhelp();                     /* write help message */
                while(ttgetc())                 /* wait for */
                        if (scancode == 0x62)   /* HELP key */
                                break;
                copy(scrbase,hpterm,0x7d00);    /* restore old screen */
                (*term.t_move)(sav_row,sav_col);
                Bconout(2,0x1b);                /* enable cursor */
                Bconout(2,'e');
                return(TRUE);
                }
}
 
/*
 * return the base address of the line A variables
 * Bammi @ Case
 */
int *
aaddress()
{
        asm("dc.w $A000");/* Line A trap - 0000 is init line-A  */
        /* d0 and a0 now contain the address
         * so we can just return and the result
         * will be valid
         */
}
 
/* a mini-mlwrite for the terminal mode */
/* VARARGS */
mtwrite(fmt,arg1,arg2,arg3,arg4)
register char *fmt;
register long arg1,arg2,arg3,arg4;
{
        static char buf[128];
 
        sprintf(buf,fmt,arg1,arg2,arg3,arg4);
        ttputc(0x1b);ttputc('j');       /* save cursor */
        (*term.t_move)(term.t_nrow,0);
        ttputc(0x1b);ttputc('l');       /* delete line */
        Cconws(buf);
        ttputc(0x1b);ttputc('k');       /* restore cursor */
        return(TRUE);
}
 
/* A modicum of help for the RS232 connection module */
int
showhelp()
{
        register int i;
        i = 5;
 
        Crawio(0x1b);
        Crawio('p');    /* rev video on */
        (*term.t_move)(i++,17);
        Cconws("                                     ");
        (*term.t_move)(i++,17);
        Cconws("   ALT-UNDO    return to Uemail      ");
        (*term.t_move)(i++,17);
        Cconws("   ALT-B       set the baud rate     ");
        (*term.t_move)(i++,17);
        Cconws("   ALT-C       change color          ");
        (*term.t_move)(i++,17);
        Cconws("   ALT-E       load an alias file    ");
        (*term.t_move)(i++,17);
        Cconws("   ALT-L       load a macro file     ");
        (*term.t_move)(i++,17);
        Cconws("   ALT-O       turn off flow control ");
        (*term.t_move)(i++,17);
        Cconws("   ALT-R       turn on RTS/CTS       ");
        (*term.t_move)(i++,17);
        Cconws("   ALT-X       turn on XON/XOFF      ");
        (*term.t_move)(i++,17);
        Cconws("   ALT-T       show the current time ");
        (*term.t_move)(i++,17);
        Cconws("   ALT-CTRL-B  send a break          ");
        (*term.t_move)(i++,17);
        Cconws("   ALT-CTRL-C  run a program         ");
        (*term.t_move)(i++,17);
        Cconws("   ALT-?       this help message     ");
        (*term.t_move)(i++,17);
        Cconws("   HELP        this help message     ");
        (*term.t_move)(i++,17);
        Cconws("                                     \r\n");
        Crawio(0x1b);
        Crawio('q');    /* rev video off */
        return(TRUE);
}
 
/* setbaud for RS232 (default is 1200) */
 
int
setbaud()
{
        register int c;
 
        mtwrite("Baud rate [a/b/c/d/e] a = 300, \
b = 1200, c = 2400, d = 9600, e = 19,200");
        c = ttgetc();
        switch(c)
                {
                case 'a':
                case 'A':
                        defbaud = 9;
                        bps = 300;
                        Rsconf(defbaud,flow,-1,-1,-1,-1);
                        mtwrite("[Baud = %dbps]",bps);
                        return(TRUE);
                case 'b':
                case 'B':
                        defbaud = 7;
                        bps = 1200;
                        Rsconf(defbaud,flow,-1,-1,-1,-1);
                        mtwrite("[Baud = %dbps]",bps);
                        return(TRUE);
                case 'c':
                case 'C':
                        defbaud = 4;
                        bps = 2400;
                        Rsconf(defbaud,flow,-1,-1,-1,-1);
                        mtwrite("[Baud = %dbps]",bps);
                        return(TRUE);
                case 'd':
                case 'D':
                        defbaud = 1;
                        bps = 9600;
                        Rsconf(defbaud,flow,-1,-1,-1,-1);
                        mtwrite("[Baud = %dbps]",bps);
                        return(TRUE);
                case 'e':
                case 'E':
                        defbaud = 0;
                        bps = 19200;
                        Rsconf(defbaud,flow,-1,-1,-1,-1);
                        mtwrite("[Baud = %dbps]",bps);
                        return(TRUE);
                default:
                        Rsconf(defbaud,flow,-1,-1,-1,-1);
                        mtwrite("[Baud = %dbps]",bps);
                        return(TRUE);
                }
}
 
/*
*      KERMIT utilities.
*/
 
/* generic command for BYE and FINish */
gencmdsw(cmd)
char cmd;
{
        int num, len;              /* Packet number, length */
        packet[0] = cmd;              /* Generic command */
        spack('G', 0, 1, packet);     /* Send Generic command  */
 
        switch(rpack(&len,&num,packet))  /* Get packet */
                {
                case 'Y':
                        return(TRUE);
                case 'E':
                        prerrpkt(packet);
                        return(FALSE);
                default:
                        return(FALSE);
                }
 
}
 
/*
*      b u f i l l
*
* Get a bufferful of data from the buffer that's being sent.
* Only control-quoting and 8-bit quoting is done;
* repeat count prefixes are not handled.
*/
 
bufill(buffer)
char buffer[];                    /* Buffer */
{
        register char t;                         /* Char read from file */
        register char *buffend;          /* End of buffer pointer */
        register char *buffp;              /* Pointer into buffer */
        register int unprintable;              /* Is a character printable ?*/
        short eolflag = FALSE;                  /* kludge for VAX */
 
        buffend = &buffer[spsiz-9];     /* set up end of buffer pointer */
        buffp=buffer;              /* and the current position */
 
        while(curwp->w_dotp != curbp->b_linep)
                {
                t = lgetc(curwp->w_dotp, curwp->w_doto);
                if (curwp->w_doto == llength(curwp->w_dotp))
                        {
                        t = eol;
                        eolflag = TRUE; /* kludge for VAX */
                        }
 
                unprintable = ((t<SP)||(t==DEL));
 
                /* Does this char require special handling? */
                if ((unprintable) || t==quotech)
                        {
                        *buffp++ = quotech;       /* Quote the character */
                        if (unprintable)
                                t = ctl(t);          /* and uncontrolify */
                        }
                *buffp++ = t;
                if (eolflag)
                        {
                        eolflag = FALSE;        /* be sure it gets \r\n pair */
                        *buffp++ = quotech;     /* this is for VAX/VMS */
                        *buffp++ = ctl(LF);
                        }
                forwchar(FALSE,1);
                /* Check length */
                if (buffp>=buffend)     /* this is how you avoid pointer */
                        return((int)buffp-(int)buffer); /* subtraction */
                }                       /* not (int)(buffp-buffer) */
        if (buffp == buffer)
                return(EOF);
        return((int)buffp-(int)buffer); /* Handle partial buffer */
}
 
/*
*      b u f e m p
*
* Put data from an incoming packet into the default buffer.
*/
 
bufemp(buffer,len)
char buffer[];                    /* Buffer */
int len;                                /* Length */
{
        register int i;          /* Counter */
        register char t;                /* Character holder */
        register int highbit;      /* place to hold quoted highbit */
 
        highbit = 0;
        for (i=0; i<len; i++)      /* Loop thru the data field */
                {
                t = buffer[i];            /* Get a character */
                if (t == MYQUOTE)              /* Control quote? */
                        {                              /* Yes */
                        t = buffer[++i];        /* Get the quoted character */
                        /* Low order bits match quote char? */
                        if (((t & 0177) != MYQUOTE) &&
                            (!qflag || ((t & 0x7F)!=qbin)))
                                t = ctl(t);     /* No, uncontrollify it */
                        }
                t |= highbit;   /* set top bit if needed */
                highbit=0;
                if (t==eol)
                        {
                        lnewline();
                        continue;
                        }
                if (t=='\n')
                        continue;
                linsert(1,t);
        }
}
 
int
readaux()
{
        int i;
 
        while(!Bconstat(1))     /* loop until line is ready or */
                if (i++ >= 32000)       /* time is up */
                        return(FALSE);
        return ((int)Bconin(1));        /* char not masked when read */
}
 
sauxstr(buf,len)
char *buf;
int len;
{
        for(;len>0;len--)
                sendaux(*buf++);
}
 
sendaux(c)
int c;
{
        while(!Bcostat(1))
                {
                if (Bconstat(2))
                        if (ttgetc()==0x07)
                                return(FALSE);
                }
        Bconout(1,c);   /* Send character */
}
 
/*
*      p r e r r p k t
*
* Print contents of error packet received from remote host.
*/
prerrpkt(msg)
char *msg;
{
        mlwrite("ABORT: %s",msg);
        return;
}
 
en8quote(t)
int t;
{
        qflag = t;
/* no binary files allowed */
}
 
/* tsr_ptr points to the 8 bit TSR register of the 68901
 * From Jwahar R. Bammi
 * send a break
 * Modifies Bit 3 in the TSR (reg 23) of the Mfp
 */
 
sendbrk()
{
        register long save_ssp;
        register long time;
 
        save_ssp = Super(0L);   /* Super Mode */
 
        /* set bit 3 of the TSR */
        *tsr_ptr |= (unsigned char)8;
 
        /* wait for 250 ms -- you can adjust the duration
         * 250 ms seems to be almost a universal figure for break
         * duration.
         */
        time = *hz_200 + 50;
        while(*hz_200 < time)
        /* wait */ ;
        /* reset bit 3 of the tsr */
        *tsr_ptr &= (unsigned char)~8;
 
        Super(save_ssp);        /* Back to user Mode */
}
 
/*
 *  f l u s h i n p u t
 *
 *  Dump all pending input to clear stacked up NACK's.
 */
flushinput()
{
        /* TOS Clear AUX receive buffer */
        while (Cauxis())
                Cauxin();
}
SHAR_EOF
cat << \SHAR_EOF > kertrans.c
/* kertrans.c transfer and send functions to support file sends through
 * ueMail.  All functions available only through kermit().
 */
 
#include <stdio.h>
#include <osbind.h>
#include "ed.h"
#include "kermit.h"
 
/* ASCII transmit.  Some delay ability.  Use for short files only or over
 * a direct link.
 */
extern int emacsfile;
extern char getfiln[NFILEN];
 
int
trans()
{
        register int c;
        register int ln = 0;
 
        while (curwp->w_dotp != curbp->b_linep)
                {
                c = lgetc(curwp->w_dotp, curwp->w_doto);
                if (curwp->w_doto == llength(curwp->w_dotp))
                        {
                        mlwrite("[Transmitting line: %d]",++ln);
                        if (!emacsfile)
                                c = '\r';
                        else
                                c = '\n';
                        }
                while (!(int)Bcostat(1))        /* check for line ready */
                        {
                        if (Bconstat(2))
                                if (ttgetc()==0x07)
                                        return(FALSE);
                        }
                sendaux(c);
                if (!forwchar(FALSE, 1))
                        return(FALSE);
                }
        if(!emacsfile)
                {
                while (!(int)Bcostat(1))
                        {
                        if (Bconstat(2))
                                if (ttgetc()==0x07)
                                        return(FALSE);
                        }
                sendaux(CLEAR);
                }
        return(ln);
}
 
/*
*      s e n d s w
*
* Sendsw is the state table switcher for sending files. It loops until
* either it finishes, or an error is encountered. The routines called
* by sendsw are responsible for changing the state.
*
*/
int
sendsw()
{
 
        state = 'S';        /* Send initiate is the start state */
        n = np = 0;               /* Initialize message number */
        numtry = 0;          /* Say no tries yet */
        while(TRUE)          /* Do this as long as necessary */
        {
                switch(state)
                {
                case 'S':
                        mlwrite("[Sending init packet]");
                        state = sinit();
                        break; /* Send-Init */
                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':
                        state = sbreak();
                        break; /* Send-Break */
                case 'C':
                        return (TRUE);    /* Complete */
                case 'A':
                        return (FALSE);  /* "Abort" */
                default:
                        return (FALSE);  /* Unknown, fail */
                }
        }
}
 
 
/*
*      s i n i t
*
* Send Initiate: send this host's parameters and get other side's back.
*/
 
char sinit()
{
        int num, len;              /* Packet number, length */
        /* If too many tries, give up */
        if (numtry++ > MAXTRY) return('A');
        len = spar(packet);                  /* Fill up init info packet */
 
 
        spack('S',n,len,packet);                /* Send an S packet */
        switch(rpack(&len,&num,recpkt)) /* What was the reply? */
        {
        case 'N':
                return(state);    /* NAK, try it again */
 
        case 'Y':                      /* ACK */
                if (n != num)      /* If wrong ACK, stay in S state */
                        return(state);  /* and try again */
                rpar(recpkt,len);       /* Get other side's init info */
 
                numtry = 0;          /* Reset try counter */
                n = (n+1)%64;      /* Bump packet count */
                return('F');        /* OK, switch state to F */
 
        case 'E':                      /* Error packet received */
                prerrpkt(recpkt);       /* Print it out and */
                return('A');        /* abort */
 
        case FALSE:
                return(state);    /* Receive failure, try again */
 
        default:
                return('A');        /* Anything else, just "abort" */
        }
}
 
 
/*
*      s f i l e
*
* Send File Header.
*/
 
char sfile()
{
        int num, len;              /* Packet number, length */
 
        /* If too many tries, give up */
        if (numtry++ > MAXTRY) return('A');
        len = strlen(getfiln);
        mlwrite("[Sending %s as %s]",curbp->b_bname,getfiln);
        spack('F',n,len,getfiln);            /* Send an F packet */
        switch(rpack(&len,&num,recpkt))  /* What was the reply? */
        {
        case 'N':                      /* NAK, just stay in this state, */
                /* unless it's NAK for next packet */
                num = (--num<0 ? 63:num);
                if (n != num)      /* which is just like an ACK for */
                        return(state);  /* this packet so fall thru to... */
 
        case 'Y':                      /* ACK */
                if (n != num) return(state); /* If wrong ACK, stay in F state */
                numtry = 0;          /* Reset try counter */
                n = (n+1)%64;      /* Bump packet count */
                size = bufill(packet);  /* Get first data from file */
                return('D');        /* Switch state to D */
 
        case 'E':                      /* Error packet received */
                prerrpkt(recpkt);       /* Print it out and */
                return('A');        /* abort */
 
        case FALSE:
                return(state);    /* Receive failure, stay in F state */
 
        default:
                return('A');        /* Something else, just "abort" */
        }
}
 
 
/*
*      s d a t a
*
* Send File Data
*/
 
char sdata()
{
        int num, len;              /* Packet number, length */
 
        if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */
 
        spack('D',n,(int)size,packet);         /* Send a D packet */
        switch(rpack(&len,&num,recpkt))  /* What was the reply? */
        {
        case 'N':                      /* NAK, just stay in this state, */
                /* unless it's NAK for next packet */
                num = (--num<0 ? 63:num);
                if (n != num)      /* which is just like an ACK for */
                        return(state);  /* this packet so fall thru to... */
 
        case 'Y':                      /* ACK */
                if (n != num) return(state); /* If wrong ACK, fail */
                numtry = 0;          /* Reset try counter */
                n = (n+1)%64;      /* Bump packet count */
                mlwrite("[Sending packet: %d]",++np);
                if ((size=bufill(packet))==EOF) /* Get data from file */
                        return('Z');    /* If EOF set state to that */
                return('D');        /* Got data, stay in state D */
 
        case 'E':                      /* Error packet received */
                prerrpkt(recpkt);       /* Print it out and */
                return('A');        /* abort */
 
        case FALSE:
                return(state);    /* Receive failure, stay in D */
 
        default:
                return('A');    /* Anything else, "abort" */
        }
}
 
 
/*
*      s e o f
*
* Send End-Of-File.
*/
 
char seof()
{
        int num, len;              /* Packet number, length */
        if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */
 
        spack('Z',n,0,packet);    /* Send a 'Z' packet */
        switch(rpack(&len,&num,recpkt))  /* What was the reply? */
        {
        case 'N':                      /* NAK, just stay in this state, */
                /* unless it's NAK for next packet, */
                num = (--num<0 ? 63:num);
                if (n != num)      /* which is just like an ACK for */
                        return(state);  /* this packet so fall thru to... */
 
        case 'Y':                      /* ACK */
                if (n != num) return(state); /* If wrong ACK, hold out */
                numtry = 0;                  /* Reset try counter */
                n = (n+1)%64;              /* and bump packet count */
                        return('B');    /* if not, break, EOT, all done */
 
        case 'E':                      /* Error packet received */
                prerrpkt(recpkt);       /* Print it out and */
                return('A');        /* abort */
 
        case FALSE:
                return(state);    /* Receive failure, stay in Z */
 
        default:
                return('A');    /* Something else, "abort" */
        }
}
 
 
/*
*      s b r e a k
*
* Send Break (EOT)
*/
 
char sbreak()
{
        int num, len;              /* Packet number, length */
        if (numtry++ > MAXTRY) return('A'); /* If too many tries "abort" */
 
        spack('B',n,0,packet);    /* Send a B packet */
        switch (rpack(&len,&num,recpkt))        /* What was the reply? */
        {
        case 'N':                      /* NAK, just stay in this state, */
                /* unless NAK for previous packet, */
                num = (--num<0 ? 63:num);
                if (n != num)      /* which is just like an ACK for */
                        return(state);  /* this packet so fall thru to... */
 
        case 'Y':                      /* ACK */
                if (n != num) return(state); /* If wrong ACK, fail */
                numtry = 0;          /* Reset try counter */
                n = (n+1)%64;      /* and bump packet count */
                return('C');        /* Switch state to Complete */
 
        case 'E':                      /* Error packet received */
                prerrpkt(recpkt);       /* Print it out and */
                return('A');        /* abort */
 
        case FALSE:
                return(state);    /* Receive failure, stay in B */
 
        default:
                return ('A');      /* Other, "abort" */
        }
}
SHAR_EOF
cat << \SHAR_EOF > kerrec.c
/* kerrec.c kermit protocol file receive support.
 */
 
#include <stdio.h>
#include <osbind.h>
#include "ed.h"
#include "kermit.h"
 
extern char getfiln[NFILEN];
 
/*
*      r e c s w
*
* This is the state table switcher for receiving files.
*/
 
recsw()
{
 
        state = 'R';                /* Receive-Init is the start state */
        n = np = 0;                       /* Initialize message number */
        numtry = 0;                  /* Say no tries yet */
 
        while(TRUE)
        {
        switch(state)              /* Do until done */
                {
                case 'R':
                        state = rinit();
                        mlwrite("[Awaiting remote init]");
                        break; /* Receive-Init */
                case 'F':
                        state = rfile();
                        break; /* Receive-File */
                case 'D':
                        state = rdata();
                        break; /* Receive-Data */
                case 'C':
                        return(TRUE);      /* Complete state */
                case 'A':
                        return(FALSE);    /* "Abort" state */
                }
        }
}
 
/*
 * astget.c server function GET
 * implemented by B. Nebel
 */
getsw()
{
        int result;
 
        flushinput();
        spack('R',0,strlen(getfiln),getfiln);
        result = recsw();
        return (result);
}
 
/*
*      r i n i t
*
* Receive Initialization
*/
 
char rinit()
{
        int len, num;              /* Packet length, number */
 
        if (numtry++ > MAXTRY) return('A');     /* If too many tries, "abort" */
 
        switch(rpack(&len,&num,packet))  /* Get a packet */
        {
        case 'S':                      /* Send-Init */
                rpar(packet,len);       /* Get the other side's init data */
                len = spar(packet);     /* Fill up packet with my init info */
                spack('Y',n,len,packet);        /* ACK with my parameters */
                oldtry = numtry;                /* Save old try count */
                numtry = 0;                  /* Start a new counter */
                n = (n+1)%64;      /* Bump packet number, mod 64 */
                return('F');        /* Enter File-Receive state */
 
        case 'E':                      /* Error packet received */
                prerrpkt(recpkt);       /* Print it out and */
                return('A');        /* abort */
 
        case FALSE:                  /* Didn't get packet */
                spack('N',n,0,NULLPTR);    /* Return a NAK */
                return(state);    /* Keep trying */
 
        default:
                return('A');        /* Some other packet type, "abort" */
        }
}
 
 
/*
*      r f i l e
*
* Receive File Header
*/
 
char rfile()
{
        int num, len;              /* Packet number, length */
 
        if (numtry++ > MAXTRY) return('A');     /* "abort" if too many tries */
 
        switch(rpack(&len,&num,packet))  /* Get a packet */
        {
        case 'S':                      /* Send-Init, maybe our ACK lost */
                /* If too many tries "abort" */
                if (oldtry++ > MAXTRY) return('A');
                if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */
                {                              /* Yes, ACK it again with */
                        len = spar(packet);     /* our Send-Init parameters */
                        spack('Y',num,len,packet);
                        numtry = 0;          /* Reset try counter */
                        return(state);    /* Stay in this state */
                }
                else return('A');       /* Not previous packet, "abort" */
 
        case 'Z':                      /* End-Of-File */
                if (oldtry++ > MAXTRY) return('A');
                if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */
                {                              /* Yes, ACK it again. */
                        spack('Y',num,0,NULLPTR);
                        numtry = 0;
                        return(state);    /* Stay in this state */
                }
                else return('A');       /* Not previous packet, "abort" */
 
        case 'F':                      /* File Header (just what we want) */
                /* The packet number must be right */
                if (num != n) return('A');
                mlwrite("[Receiving %s as %s]",packet,curbp->b_bname);
 
                spack('Y',n,0,NULLPTR);    /* Acknowledge the file header */
                oldtry = numtry;        /* Reset try counters */
                numtry = 0;
                n = (n+1)%64;      /* Bump packet number, mod 64 */
                return('D');        /* Switch to Data state */
 
        case 'B':                      /* Break transmission (EOT) */
                if (num != n) return ('A'); /* Need right packet number here */
                spack('Y',n,0,NULLPTR);     /* Say OK */
                return('C');        /* Go to complete state */
 
        case 'E':                      /* Error packet received */
                prerrpkt(recpkt);       /* Print it out and */
                return('A');        /* abort */
 
        case FALSE:                  /* Didn't get packet */
                spack('N',n,0,NULLPTR);    /* Return a NAK */
                return(state);    /* Keep trying */
 
        default:
                return ('A');      /* Some other packet, "abort" */
        }
}
 
 
/*
*      r d a t a
*
* Receive Data
*/
 
char rdata()
{
        int num, len;              /* Packet number, length */
        if (numtry++ > MAXTRY) return('A');     /* "abort" if too many tries */
 
        switch(rpack(&len,&num,packet))  /* Get packet */
        {
        case 'D':                      /* Got Data packet */
                if (num != n)      /* Right packet? */
                {                              /* No */
                        if (oldtry++ > MAXTRY)
                                return('A');    /* If too many tries, abort */
                        if (num == ((n==0) ? 63:n-1))
                        { /* Else check previous packet again? */
                                spack('Y',num,0,NULLPTR); /* Yes, re-ACK it */
                                numtry = 0;     /* Reset try counter */
                                return(state);  /* Don't write out data! */
                        }
                        else return('A');       /* sorry, wrong number */
                }
                /* Got data with right packet number */
                bufemp(packet,len);          /* Write the data to the file */
                spack('Y',n,0,NULLPTR);     /* Acknowledge the packet */
                oldtry = numtry;                /* Reset the try counters */
                numtry = 0;                  /* ... */
                mlwrite("[Receiving packet: %d]", ++np);
                n = (n+1)%64;      /* Bump packet number, mod 64 */
                return('D');        /* Remain in data state */
 
        case 'F':                      /* Got a File Header */
                if (oldtry++ > MAXTRY)
                        return('A');        /* If too many tries, "abort" */
                if (num == ((n==0) ? 63:n-1))   /* Else check packet number */
                {                              /* It was the previous one */
                        spack('Y',num,0,NULLPTR);  /* ACK it again */
                        numtry = 0;          /* Reset try counter */
                        return(state);    /* Stay in Data state */
                }
                else return('A');       /* Not previous packet, "abort" */
 
        case 'Z':                      /* End-Of-File */
                /* Must have right packet number */
                if (num != n) return('A');
                spack('Y',n,0,NULLPTR);     /* OK, ACK it. */
                n = (n+1)%64;      /* Bump packet number */
                return('F');        /* Go back to Receive File state */
 
        case 'E':                      /* Error packet received */
                prerrpkt(recpkt);              /* Print it out and */
                return('A');        /* abort */
 
        case FALSE:                  /* Didn't get packet */
                spack('N',n,0,NULLPTR);     /* Return a NAK */
                return(state);    /* Keep trying */
 
        default:
                return('A');        /* Some other packet, "abort" */
        }
}
 
/*
*      r p a c k
*
* Read a Packet
*/
 
char
rpack(len,num,data)
int *len, *num;                  /* Packet length, number */
char *data;                          /* Packet data */
{
        register int i, done;       /* Data character number, loop exit */
        register char t,         /* Current input character */
        cchksum,                /* Our (computed) checksum */
        rchksum,                        /* Checksum received from other host */
        type;              /* Packet type */
 
        do
        {
                if (Bconstat(2))
                        if (ttgetc() == 0x07) /* ^G abort */
                                {
                                mlwrite("User ABORT");
                                (*term.t_beep)();
                                return('A');
                                }
                if (!Cauxis())
                        continue;
                else
                        t = (char)readaux()& 0x7f;
        }while (t != SOH);                    /* Wait for packet header */
 
        done = FALSE;              /* Got SOH, init loop */
        while (!done)              /* Loop to get a packet */
        {
                if (Bconstat(2))
                        if (ttgetc() == 0x07) /* ^G abort */
                                {
                                mlwrite("User ABORT");
                                (*term.t_beep)();
                                return('A');
                                }
                t = (char)readaux();        /* Get character */
                if (t == SOH) continue;  /* Resynchronize if SOH */
                cchksum = t;                /* Start the checksum */
                *len = unchar(t)-3;          /* Character count */
 
                t = (char)readaux();        /* Get character */
                if (t == SOH) continue;  /* Resynchronize if SOH */
                cchksum += t;              /* Update checksum */
                *num = unchar(t);              /* Packet number */
 
                t = (char)readaux();        /* Get character */
                if (t == SOH) continue;  /* Resynchronize if SOH */
                cchksum += t;              /* Update checksum */
                type = t;                      /* Packet type */
 
                for (i=0; i<*len; i++)    /* The data itself, if any */
                {                              /* Loop for character count */
                        if (Bconstat(2))
                                if (ttgetc() == 0x07) /* ^G abort */
                                        {
                                        mlwrite("User ABORT");
                                        (*term.t_beep)();
                                        return('A');
                                        }
                        t = (char)readaux();    /* Get character */
                        if (t == SOH) continue; /* Resynch if SOH */
                        cchksum += t;      /* Update checksum */
                        data[i] = t;        /* Put it in the data buffer */
                }
                data[*len] = 0;          /* Mark the end of the data */
 
                t = (char)readaux();        /* Get last character (checksum) */
                rchksum = unchar(t);        /* Convert to numeric */
                t = (char)readaux();       /* get EOL character and toss it */
                if (t == SOH) continue;  /* Resynchronize if SOH */
                done = TRUE;                /* Got checksum, done */
        }
        /* Fold in bits 7,8 to compute */
        cchksum = (((cchksum&0300) >> 6)+cchksum)&077; /* final checksum */
 
        if (cchksum != rchksum) return((char)FALSE);
        return(type);              /* All OK, return packet type */
}
 
/*      r p a r
*
* Get the other host's send-init parameters
*
*/
 
void
rpar(data,len)
char data[];
int len;
{
        spsiz = DEFMAXL;        /* default packet size */
        timint = DEFTIME;
        pad = DEFPAD;
        padchar = DEFPADC;
        eol = DEFEOL;
        quotech = DEFQUOTE;
        qbin = DEFQBIN;
        switch (len){
        default:
        case 10:        /* attributes */
        case 9:         /* repeat count */
        case 8:         /* Check type */
        case 7:         /* 8 bit quoting */
                qbin = data[6];
                if (((qbin >='!') && (qbin <= '>'))
                    || ((qbin >= '`')&&(qbin <= '~')))
                     /*   qflag = TRUE; */ en8quote(TRUE);     /* jgc dec 25th.
1985 */
        case 6:         /* Incoming data quote character */
                quotech = data[5];
        case 5:         /* EOL character I must send */
                eol = unchar(data[4]);
        case 4:         /* Padding character I must send */
                padchar = ctl(data[3]);
        case 3:         /* Number of pads to send */
                pad = unchar(data[2]);
        case 2:         /* When I should time out */
                timint = unchar(data[1]);
                if ((timint > MAXTIM) || (timint < MINTIM)) timint = MYTIME;
        case 1:         /* Maximum send packet size */
                spsiz = unchar(data[0]);
        case 0:
                break;
        }
        if (qflag) {
                if (qbin == 'N') mlwrite("Can't do 8 bit quoting");
                else if (qbin == 'Y') qbin = QBIN;
        }
}
 
/*
*      s p a r
*
* Fill the data array with my send-init parameters
*
*/
 
int
spar(data)
char data[];
{
        data[0] = tochar(MYPACKSIZ);    /* Biggest packet I can receive */
        data[1] = tochar(MYTIME);       /* When I want to be timed out */
        data[2] = tochar(MYPAD);        /* How much padding I need */
        data[3] = ctl(MYPCHAR);  /* Padding character I want */
        data[4] = tochar(MYEOL);        /* End-Of-Line character I want */
        data[5] = MYQUOTE;            /* Control-Quote character I send */
        data[6] = qflag?QBIN:'Y';       /* Request 8 bit quoting */
        return (7);                  /* return number of parameters */
}
 
/*
*      s p a c k
*
* Send a Packet
*/
 
void
spack(type,num,len,data)
char type, *data;
int num, len;
{
        register int i;                   /* Character loop counter */
        char chksum, buffer[100];       /* Checksum, packet buffer */
        register char *bufp;        /* Buffer pointer */
 
 
        bufp = buffer;            /* Set up buffer pointer */
        for (i=1; i<=pad; i++) sendaux(padchar); /* Issue any padding */
 
        *bufp++ = SOH;            /* Packet marker, ASCII 1 (SOH) */
        *bufp++ = tochar(len+3);        /* Send the character count */
        chksum = tochar(len+3);  /* Initialize the checksum */
        *bufp++ = tochar(num);    /* Packet number */
        chksum += tochar(num);    /* Update checksum */
        *bufp++ = type;          /* Packet type */
        chksum += type;          /* Update checksum */
 
        for (i=0; i<len; i++)      /* Loop for all data characters */
        {
                *bufp++ = data[i];            /* Get a character */
                chksum += data[i];            /* Update checksum */
        }
        chksum = (((chksum&0300) >> 6)+chksum)&077; /* Compute final checksum */
        *bufp++ = tochar(chksum);       /* Put it in the packet */
        *bufp = eol;                /* Extra-packet line terminator */
        sauxstr( buffer,((int)bufp-(int)buffer+1)); /* Send the packet */
}
SHAR_EOF
cat << \SHAR_EOF > kertty.c
#include <stdio.h>
#include <ctype.h>
#include <osbind.h>
#include "ed.h"
#include "kermit.h"
 
#ifndef ESC
#define ESC 0x1b
#endif
#ifndef DEL
#define DEL 0x7f
#endif
 
extern  int *aline_addr; /* Ptr to base of Aline variables */
extern  int sav_row, sav_col;
 
typedef struct MACTAB {
        struct  MACTAB  *m_fmac;        /* next MACTAB  */
        short   *keymac;                /* pointer to the macro */
        char    key;                    /* the key      */
} MACTAB;
 
/* Do a direct read of the console. The present scheme does not always
 * work with a minimal NULL modem (i.e. only lines 1,2,&3 connected).
 */
readcon()
{
 
        register int c,i;
        extern MACTAB *mheadp, *mcralloc();
        register MACTAB *mt;
        char fname[16];
        extern char *getfname();
        extern short getktpcode();
 
        c=getkkey();    /* Read the keyboard and get mask */
        if (c == '`')   /* keyboard macro */
                {
                c = (*term.t_getchar)();
                if (c == '`')
                        {
                        sendaux('`');
                        return(TRUE);
                        }
                if (mheadp==NULL || mheadp->m_fmac == NULL)
                        {
                        mtwrite("No defineable macros assigned");
                        return(TRUE);
                        }
                if((mt=mcralloc(FALSE,c))!= (MACTAB *)NULL)
                        sendmacro(mt->keymac);
                }
        else if (shiftstatus == 12 && scancode == 0x30) /* CTRL-ALT-B */
                sendbrk();
        else if (shiftstatus == 12 && scancode == 0x2e) /* CTRL-ALT-C */
                {
                setterm(HOST);
                shell(FALSE,HUGE);
                setterm(REMOTE);
                }
        else if (shiftstatus == 17 || shiftstatus == 18) /* C-Lock + Shift */
                {
                i=tolower(c);
                sendaux(i);
                }
        else if (shiftstatus == 0 && scancode == 0x62) /* HELP Key */
                setterm(SHOWHELP);
        else if (shiftstatus == 8)      /* ALT key pressed */
                {
                switch(scancode)
                        {
                        case 0x12:      /* E */
                        /* save cursor position */
                                sav_row = aline_addr[-13];
                                sav_col = aline_addr[-14];
                                commfil(TRUE,TRUE);
                                ttopen();       /* update color */
                                (*term.t_move)(sav_row,sav_col);
                                return(TRUE);
                        case 0x61:      /* UNDO */
                                return(FALSE);
                        case 0x2e:      /* C */
                        /* save cursor position */
                                sav_row = aline_addr[-13];
                                sav_col = aline_addr[-14];
                                paintbuffer(TRUE,TRUE);
                                (*term.t_move)(sav_row,sav_col);
                                return(TRUE);
                        case 0x30:      /* B */
                                return(setbaud());
                        case 0x26:      /* L */
                                sav_row = aline_addr[-13];
                                sav_col = aline_addr[-14];
                                loadmac(TRUE);
                                (*term.t_move)(sav_row,sav_col);
                                return(TRUE);
                        case 0x18:      /* O */
                                /* Turn off flow control */
                                flow = NOFLO;
                                Rsconf(-1,flow,-1,-1,-1,-1);
                                mtwrite("[Handshaking disabled]");
                                return(TRUE);
                        case 0x13:      /* R */
                                flow = RTS;
                                Rsconf(-1,flow,-1,-1,-1,-1);
                                mtwrite("[RTS/CTS active]");
                                return(TRUE);
                        case 0x14:
                                showtime(TRUE,HUGE);
                                return(TRUE);
                        case 0x2d:      /* X */
                                flow = XON;
                                Rsconf(-1,flow,-1,-1,-1,-1);
                                mtwrite("[XON/XOFF active]");
                                return(TRUE);
                        case 0x35:      /* / ? */
                                setterm(SHOWHELP);
                                return(TRUE);
                        default:
                                sendaux(c);
                                return(TRUE);
                        }
                }
        else
                {
                if (c & SPEC)
                        if (getfname(c,fname)!=(char *)NULL)
                                c = (int)getktpcode(fname);
                if (c & META)
                        {
                        i = c & ~META;
                        sendaux(ESC);
                        c = i;
                        }
                if (c & CTLX)
                        {
                        i = c & ~CTLX;
                        sendaux(0x18);
                        c = i;
                        }
                if (c & CTRL)
                        {
                        i = c & ~CTRL;
                        c = i - '@';
                        }
                sendaux(c);
                }
        return(TRUE);
}
 
/* pratically identical to getkey in main.c but that one uses mlwrite
 * which would damage the terminal screen when it tried to update.
 */
getkkey()
{
        register int c;
        extern char keyscan[];
 
        c = (*term.t_getchar)();
#if     ST
        if (scancode == 0x70 && shiftstatus != 16)
                return (CTRL|'X');
#endif
        if (c == DEL)
                return(c);
        if (c == METACH) {                      /* Apply M- prefix      */
                mtwrite("Meta: ");
                c = (*term.t_getchar)();
                return (META | c);
        }
#if     ST
        /* use special keys or number pad (code >= 0x63) ?
         * 0x03 = scancode for ^@ (setmark).
         */
        if ((c == NULL && scancode != 0x03) || scancode >= 0x4a)
                if (scancode > 0x32)
                        {
                        /* if CapsLock and number pad, use real numbers */
                        if (shiftstatus == 16 && (scancode > 0x62 ||
                                scancode == 0x4a || scancode == 0x4e))
                                return(c);
                        else
                                return (SPEC | scancode);
                        }
                else    {
                        c = keyscan[scancode];
                        return (META | c);
                        }
#endif
        if (c>=0x00 && c<=0x1F)                 /* C0 control -> C-     */
                c = CTRL | (c+'@');
        return (c);
}
 
/* Allows keyboard macros to go through completely on a slow and noisy line */
 
sendmacro(buf)
register short *buf;
{
        register int c;
        char fname[16];
 
        while(*buf != (CTLX|')'))
                {
                while(!(int)Cauxos())   /* wait for line to clear */
                        ;
                if (*buf & SPEC)
                        if (getfname(*buf,fname)!=(char *)NULL)
                                *buf = (int)getktpcode(fname);
                if (*buf & META)
                        {
                        c = *buf & ~META;
                        sendaux(ESC);
                        *buf = c;
                        }
                if (*buf & CTLX)
                        {
                        c = *buf & ~CTLX;
                        sendaux(0x18);
                        *buf = c;
                        }
                if (*buf & CTRL)
                        {
                        c = *buf & ~CTRL;
                        *buf = c - '@';
                        }
                sendaux(*buf++);
                }
}
SHAR_EOF
#       End of shell archive
exit 0
%NONAME-W-NOMSG, Message number 00000000
Technical Details
Message-ID: <8702052241.AA16292@ucbvax.Berkeley.EDU>
Path: arc1-ca.pugleaf.net!utzoo!watmath!clyde!rutgers!mit-eddie!genrad!decvax!ucbvax!ULKYVX.BITNET!RDROYA01

Show Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: arc1-ca.pugleaf.net!utzoo!watmath!clyde!rutgers!mit-eddie!genrad!decvax!ucbvax!ULKYVX.BITNET!RDROYA01
From: RDROYA01@ULKYVX.BITNET.UUCP
Newsgroups: comp.sys.atari.st
Subject: Uemail source (4 of 12)
Message-ID: <8702052241.AA16292@ucbvax.Berkeley.EDU>
Date: Thu, 5-Feb-87 06:24:00 EST
Article-I.D.: ucbvax.8702052241.AA16292
Posted: Thu Feb  5 06:24:00 1987
Date-Received: Sat, 7-Feb-87 16:36:38 EST
Sender: daemon@ucbvax.BERKELEY.EDU
Organization: University of Louisville
Lines: 1587