BSD 4_4 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Wed, 25 Nov 1992 05:28:47 +0000 (21:28 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Wed, 25 Nov 1992 05:28:47 +0000 (21:28 -0800)
Work on file usr/src/contrib/kermit-5A.188/ckcfns.c
Work on file usr/src/contrib/kermit-5A.188/ckcker.h

Synthesized-from: CSRG/cd3/4.4

usr/src/contrib/kermit-5A.188/ckcfns.c [new file with mode: 0644]
usr/src/contrib/kermit-5A.188/ckcker.h [new file with mode: 0644]

diff --git a/usr/src/contrib/kermit-5A.188/ckcfns.c b/usr/src/contrib/kermit-5A.188/ckcfns.c
new file mode 100644 (file)
index 0000000..c441db0
--- /dev/null
@@ -0,0 +1,2104 @@
+char *fnsv = "C-Kermit functions, 5A(080) 24 Nov 92";
+
+/*  C K C F N S  --  System-independent Kermit protocol support functions.  */
+
+/*  ...Part 1 (others moved to ckcfn2,3 to make this module small enough) */
+
+/*
+  Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
+  Columbia University Center for Computing Activities.
+  First released January 1985.
+  Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
+  York.  Permission is granted to any individual or institution to use this
+  software as long as it is not sold for profit.  This copyright notice must be
+  retained.  This software may not be included in commercial products without
+  written permission of Columbia University.
+*/
+/*
+ System-dependent primitives defined in:
+
+   ck?tio.c -- terminal i/o
+   cx?fio.c -- file i/o, directory structure
+*/
+#include "ckcsym.h"                    /* Once needed this for Mac... */
+#include "ckcasc.h"                    /* ASCII symbols */
+#include "ckcdeb.h"                    /* Debug formats, typedefs, etc. */
+#include "ckcker.h"                    /* Symbol definitions for Kermit */
+#include "ckcxla.h"                    /* Character set symbols */
+
+/* Externals from ckcmai.c */
+extern int spsiz, spmax, rpsiz, timint, srvtim, rtimo, npad, ebq, ebqflg,
+ rpt, rptq, rptflg, capas, keep, fncact, pkttim, autopar, spsizr;
+extern int pktnum, bctr, bctu, bctl, fmask, clfils, sbufnum,
+ size, osize, spktl, nfils, warn, timef, spsizf, sndtyp, success;
+extern int parity, turn, network, what, fsecs,
+ delay, displa, xflg, mypadn;
+extern long filcnt, ffc, flci, flco, tlci, tlco, tfc, fsize, speed;
+extern int fblksiz, frecl, frecfm, forg, fcctrl;
+extern int spackets, rpackets, timeouts, retrans, crunched, wmax;
+extern int hcflg, binary, savmod, fncnv, local, server, cxseen, czseen;
+extern int nakstate, discard;
+extern int rq, rqf, sq, wslots, wslotn, wslotr, winlo, urpsiz, rln;
+extern int atcapr, atcapb, atcapu;
+extern int lpcapr, lpcapb, lpcapu;
+extern int swcapr, swcapb, swcapu;
+extern int lscapr, lscapb, lscapu;
+extern int bsave, bsavef;
+extern int sseqtbl[];
+extern int numerrs;
+extern long rptn;
+extern int maxtry;
+
+#ifndef NOCSETS
+extern int tcharset, fcharset;
+extern int ntcsets;
+extern struct csinfo tcsinfo[], fcsinfo[];
+#endif /* NOCSETS */
+
+extern int
+  atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko,
+  attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso; 
+
+extern int bigsbsiz, bigrbsiz;
+
+#ifdef DYNAMIC
+  extern CHAR *srvcmd;
+#else
+  extern CHAR srvcmd[];
+#endif /* DYNAMIC */
+extern CHAR padch, mypadc, eol, seol, ctlq, myctlq, sstate;
+extern CHAR *recpkt, *data, padbuf[], stchr, mystch;
+extern CHAR *srvptr;
+extern CHAR *rdatap;
+extern char *cmarg, *cmarg2, *hlptxt, **cmlist, filnam[], fspec[];
+
+_PROTOTYP( CHAR *rpar, (void) );
+_PROTOTYP( int lslook, (unsigned int b) );     /* Locking Shift Lookahead */
+_PROTOTYP( int szeof, (CHAR *s) );
+
+/* International character sets */
+
+#ifndef NOCSETS
+/* Pointers to translation functions */
+#ifdef CK_ANSIC
+extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set */
+extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* translation functions */
+#else
+extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])();        /* Character set */
+extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])();        /* translation functions. */
+#endif /* CK_ANSIC */
+_PROTOTYP( CHAR (*rx), (CHAR) );       /* Input translation function */
+_PROTOTYP( CHAR (*sx), (CHAR) );       /* Output translation function */
+_PROTOTYP( CHAR ident, (CHAR) );       /* Identity translation function */
+#endif /* NOCSETS */
+
+/* Windowing things */
+
+extern int rseqtbl[];                  /* Rec'd-packet sequence # table */
+
+/* (PWP) external def. of things used in buffered file input and output */
+
+#ifdef DYNAMIC
+extern char *zinbuffer, *zoutbuffer;
+#else
+extern char zinbuffer[], zoutbuffer[];
+#endif
+extern char *zinptr, *zoutptr;
+extern int zincnt, zoutcnt;
+
+/* Variables defined in this module, but shared by ckcfn3, to which */
+/* several functions have been moved... */
+
+int sndsrc;            /* Flag for where to get names of files to send: */
+                                       /* -1: znext() function */
+                                       /*  0: stdin */
+                                       /* >0: list in cmlist */
+
+int  memstr;                           /* Flag for input from memory string */
+
+#ifdef pdp11
+CHAR myinit[25];                       /* Copy of my Send-Init data */
+#else
+CHAR myinit[100];                      /* Copy of my Send-Init data */
+#endif /* pdp11 */
+
+/* Variables local to this module */
+
+static char *memptr;                   /* Pointer for memory strings */
+
+#ifdef pdp11
+static char cmdstr[50];                        /* System command string. */
+#else
+static char cmdstr[100];
+#endif /* pdp11 */
+
+static int drain;                      /* For draining stacked-up ACKs. */
+
+static int first;                      /* Flag for first char from input */
+static CHAR t,                         /* Current character */
+    next;                              /* Next character */
+
+static int lsstate = 0;                        /* Locking shift state */
+static int lsquote = 0;                        /* Locking shift quote */
+
+#ifdef datageneral
+extern int quiet;
+#endif
+\f
+/*  E N C S T R  --  Encode a string from memory. */
+
+/*
+  Call this instead of getpkt() if source is a string, rather than a file.
+  Note: Character set translation is never done in this case.
+*/
+
+#ifdef pdp11
+#define ENCBUFL 100
+#else
+#define ENCBUFL 200
+#endif /* pdp11 */
+CHAR encbuf[ENCBUFL];
+
+int
+encstr(s) CHAR* s; {
+    int m; char *p;
+    CHAR *dsave;
+
+    if ((m = (int)strlen((char *)s)) > ENCBUFL) {
+       debug(F111,"encstr string too long for buffer",s,ENCBUFL);
+       s[ENCBUFL] = '\0';
+    }
+    if (m > spsiz-bctl-3) {
+       debug(F111,"encstr string too long for packet",s,spsiz-bctl-3);
+       s[spsiz-bctl-3] = '\0';
+    }
+    m = memstr; p = memptr;            /* Save these. */
+
+    memptr = (char *)s;                        /* Point to the string. */
+    memstr = 1;                                /* Flag memory string as source. */
+    first = 1;                         /* Initialize character lookahead. */
+    dsave = data;                      /* Boy is this ugly... */
+    data = encbuf + 7;                 /* Why + 7?  See spack()... */
+#ifdef COMMENT
+    getpkt(spsiz-bctl-3,0);            /* Fill a packet from the string. */
+#else
+    getpkt(spsiz,0);
+#endif /* COMMENT */
+    data = dsave;                      /* (sorry...) */
+    memstr = m;                                /* Restore memory string flag */
+    memptr = p;                                /* and pointer */
+    first = 1;                         /* Put this back as we found it. */
+    return(0);
+}
+\f
+#ifdef COMMENT
+/*
+  We don't use this routine any more -- the code has been incorporated
+  directly into getpkt() to reduce per-character function call overhead.
+  Also, watch out: it hasn't been updated since it was commented out a
+  long time ago.
+*/
+/* E N C O D E - Kermit packet encoding procedure */
+
+VOID
+encode(a) CHAR a; {                    /* The current character */
+    int a7;                            /* Low order 7 bits of character */
+    int b8;                            /* 8th bit of character */
+#ifndef NOCSETS
+    if (!binary && sx) a = (*sx)(a);   /* Translate. */
+#endif /* NOCSETS */
+
+    if (rptflg)        {                       /* Repeat processing? */
+        if (a == next && (first == 0)) { /* Got a run... */
+           if (++rpt < 94)             /* Below max, just count */
+                return;
+           else if (rpt == 94) {       /* Reached max, must dump */
+                data[size++] = rptq;
+                data[size++] = tochar(rpt);
+               rptn += rpt;            /* Count, for stats */
+                rpt = 0;
+           }
+        } else if (rpt == 1) {         /* Run broken, only 2? */
+            rpt = 0;                   /* Yes, reset repeat flag & count. */
+           encode(a);                  /* Do the character twice. */
+           if (size <= maxsize) osize = size;
+           rpt = 0;
+           encode(a);
+           return;
+       } else if (rpt > 1) {           /* More than two */
+            data[size++] = rptq;       /* Insert the repeat prefix */
+            data[size++] = tochar(++rpt); /* and count. */
+           rptn += rpt;
+            rpt = 0;                   /* Reset repeat counter. */
+        }
+    }
+    a7 = a & 0177;                     /* Isolate ASCII part */
+    b8 = a & 0200;                     /* and 8th (parity) bit. */
+
+    if (ebqflg && b8) {                        /* Do 8th bit prefix if necessary. */
+        data[size++] = ebq;
+        a = a7;
+    }
+    if ((a7 < SP) || (a7==DEL))        {       /* Do control prefix if necessary */
+        data[size++] = myctlq;
+       a = ctl(a);
+    }
+    if (a7 == myctlq)                  /* Prefix the control prefix */
+        data[size++] = myctlq;
+
+    if ((rptflg) && (a7 == rptq))      /* If it's the repeat prefix, */
+        data[size++] = myctlq;         /* quote it if doing repeat counts. */
+
+    if ((ebqflg) && (a7 == ebq))       /* Prefix the 8th bit prefix */
+        data[size++] = myctlq;         /* if doing 8th-bit prefixes */
+
+    data[size++] = a;                  /* Finally, insert the character */
+    data[size] = '\0';                 /* itself, and mark the end. */
+}
+#endif /* COMMENT */
+\f
+/*  Output functions passed to 'decode':  */
+
+int                           /*  Put character in server command buffer  */
+#ifdef CK_ANSIC
+putsrv(char c)
+#else
+putsrv(c) register char c;
+#endif /* CK_ANSIC */
+/* putsrv */ {
+    *srvptr++ = c;
+    *srvptr = '\0';            /* Make sure buffer is null-terminated */
+    return(0);
+}
+
+int                                    /*  Output character to console.  */
+#ifdef CK_ANSIC
+puttrm(char c)
+#else
+puttrm(c) register char c;
+#endif /* CK_ANSIC */
+/* puttrm */ {
+    conoc(c);
+    return(0);
+}
+
+int                                    /*  Output char to file. */
+#ifdef CK_ANSIC
+putfil(char c)
+#else
+putfil(c) register char c;
+#endif /* CK_ANSIC */
+/* putfil */ {
+    if (zchout(ZOFILE, (char) (c & fmask)) < 0) {
+       czseen = 1;                     /* If write error... */
+       debug(F101,"putfil zchout write error, setting czseen","",1);
+       return(-1);
+    }
+    return(0);
+}
+
+/* D E C O D E  --  Kermit packet decoding procedure */
+
+/*
+ Call with string to be decoded and an output function.
+ Returns 0 on success, -1 on failure (e.g. disk full).
+
+ This is the "inner loop" when receiving files, and must be coded as 
+ efficiently as possible.  Note some potential problems:  if a packet
+ is badly formed, having a prefixed sequence ending prematurely, this
+ function, as coded, could read past the end of the packet.  This has
+ never happened, thus the additional (time-consuming) tests have not
+ been added.
+*/
+
+static CHAR *xdbuf;    /* Global version of decode()'s buffer pointer */
+                        /* for use by translation functions. */
+
+/* Function for pushing a character onto decode()'s input stream. */
+
+VOID
+#ifdef CK_ANSIC
+zdstuff(CHAR c)
+#else
+zdstuff(c) CHAR c;
+#endif /* CK_ANSIC */
+/* zdstuff */ {        
+    xdbuf--;                           /* Back up the pointer. */
+    *xdbuf = c;                                /* Stuff the character. */
+}
+
+int
+#ifdef CK_ANSIC
+decode(CHAR *buf, int (*fn)(char), int xlate)
+#else
+decode(buf,fn,xlate) register CHAR *buf; register int (*fn)(); int xlate;
+#endif /* CK_ANSIC */
+/* decode */ {
+    register unsigned int a, a7, a8, b8; /* Various copies of current char */
+    int t;                             /* Int version of character */
+    int ssflg;                         /* Character was single-shifted */
+
+/*
+  Catch the case in which we are asked to decode into a file that is not open,
+  for example, if the user interrupted the transfer, but the other Kermit
+  keeps sending.
+*/
+    if ((cxseen || czseen || discard) && (fn == putfil))
+      return(0);
+
+    xdbuf = buf;                       /* Make global copy of pointer. */
+    rpt = 0;                           /* Initialize repeat count. */
+
+    while ((a = *xdbuf++ & 0xFF) != '\0') { /* Get next character. */
+       if (a == rptq && rptflg) {      /* Got a repeat prefix? */
+           rpt = xunchar(*xdbuf++ & 0xFF); /* Yes, get the repeat count, */
+           rptn += rpt;
+           a = *xdbuf++ & 0xFF;        /* and get the prefixed character. */
+       }
+       b8 = lsstate ? 0200 : 0;        /* 8th-bit value from SHIFT-STATE */
+       if (ebqflg && a == ebq) {       /* Have 8th-bit prefix? */
+           b8 ^= 0200;                 /* Yes, invert the 8th bit's value, */
+           ssflg = 1;                  /* remember we did this, */
+           a = *xdbuf++ & 0xFF;        /* and get the prefixed character. */
+       } else ssflg = 0;
+
+       if (a == ctlq) {                /* If control prefix, */
+           a  = *xdbuf++ & 0xFF;       /* get its operand */
+           a7 = a & 0x7F;              /* and its low 7 bits. */
+           if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') /* Controllify */
+             a = ctl(a);               /* if in control range. */
+           if (lscapu) {               /* If doing locking shifts... */
+               if (lsstate)            /* If SHIFTED */
+                 a8 = (a & ~b8) & 0xFF; /* Invert meaning of 8th bit */
+               else                    /* otherwise */
+                 a8 = a | b8;          /* OR in 8th bit */
+               /* If we're not in a quoted sequence */
+               if (!lsquote && (!lsstate || !ssflg)) {
+                   if (a8 == DLE) {    /* Check for DLE quote */
+                       lsquote = 1;    /* prefixed by single shift! */
+                       continue;
+                   } else if (a8 == SO) { /* Check for Shift-Out */
+                       lsstate = 1;    /* SHIFT-STATE = SHIFTED */
+                       continue;
+                   } else if (a8 == SI) { /* or Shift-In */
+                       lsstate = 0;    /* SHIFT-STATE = UNSHIFTED */
+                       continue;
+                   }
+               } else lsquote = 0;
+           }
+       }
+       a |= b8;                        /* OR in the 8th bit */
+       if (rpt == 0) rpt = 1;          /* If no repeats, then one */
+       if (!binary) {                  /* If in text mode, */
+#ifdef NLCHAR
+           if (a == CR) continue;      /* Discard carriage returns, */
+           if (a == LF) a = NLCHAR;    /* convert LF to system's newline. */
+#endif /* NLCHAR */
+
+#ifndef NOCSETS                                /* Character-set translation */
+#ifdef KANJI                           /* For Kanji transfers, */
+           if (tcharset != TC_JEUC)    /* postpone translation. */
+#endif /* KANJI */
+             if (xlate && rx) a = (*rx)((CHAR) a); /* Translate charset */
+#endif /* NOCSETS */
+       }
+       if (fn == putfil) { /* (PWP) speedup via buffered output and a macro */
+           for (; rpt > 0; rpt--) {    /* Output the char RPT times */
+#ifndef NOCSETS
+#ifdef KANJI
+               if (!binary && tcharset == TC_JEUC &&
+                   fcharset != FC_JEUC) { /* Translating from J-EUC */
+                   if (ffc == 0L) xkanjf();
+                   if (xkanji(a,fn) < 0)  /* to something else? */
+                     return(-1);
+               } else
+#endif /* KANJI */
+#endif /* NOCSETS */
+               if ((t = zmchout(a & fmask)) < 0) { /* zmchout is a macro */
+#ifdef COMMENT
+/* Too costly, uncomment these if you really need them. */
+                   debug(F101,"decode zmchout","",t);
+                   debug(F101,"decode zoutcnt","",zoutcnt);
+                   debug(F101,"decode a","",a);
+#endif /* COMMENT */
+                   return(-1);
+               }
+               ffc++;                  /* Count the character */
+           }
+       } else {                        /* Output to something else. */
+           a &= fmask;                 /* Apply file mask */
+           for (; rpt > 0; rpt--) {    /* Output the char RPT times */
+               if ((*fn)((char) a) < 0) return(-1); /* Send to output func. */
+               ffc++;
+           }
+       }
+    }
+    return(0);
+}
+\f
+/*  G E T P K T -- Fill a packet data field  */
+
+/*
+ Gets characters from the current source -- file or memory string.
+ Encodes the data into the packet, filling the packet optimally.
+ Set first = 1 when calling for the first time on a given input stream
+ (string or file).
+
+ Call with:
+ bufmax -- current send-packet size
+ xlate  -- flag: 0 to skip character-set translation, 1 to translate
+
+ Uses global variables:
+ t     -- current character.
+ first -- flag: 1 to start up, 0 for input in progress, -1 for EOF.
+ next  -- next character.
+ data  -- pointer to the packet data buffer.
+ size  -- number of characters in the data buffer.
+ memstr - flag that input is coming from a memory string instead of a file.
+ memptr - pointer to string in memory.
+ (*sx)()  character set translation function
+
+Returns the size as value of the function, and also sets global "size",
+and fills (and null-terminates) the global data array.  Returns 0 upon eof.
+
+Rewritten by Paul W. Placeway (PWP) of Ohio State University, March 1989.
+Incorporates old getchx() and encode() inline to reduce function calls,
+uses buffered input for much-improved efficiency, and clears up some
+confusion with line termination (CRLF vs LF vs CR).
+
+Rewritten again by Frank da Cruz to incorporate locking shift mechanism,
+May 1991.
+*/
+
+/*
+  Lookahead function to decide whether locking shift is worth it.  Looks at
+  the next four input characters to see if all of their 8th bits match the
+  argument.  Call with 0 or 0200.  Returns 1 if so, 0 if not.  If we don't
+  happen to have at least 4 more characters waiting in the input buffer,
+  returns 1.  Note that zinptr points two characters ahead of the current
+  character because of repeat-count lookahead.
+*/
+
+#ifdef KANJI
+int
+kgetf() {
+    return(zminchar());
+}
+
+int
+kgetm() {
+    int x;
+    if (x = *memptr++) return(x);
+    else return(-1);
+}
+#endif /* KANJI */
+
+int
+lslook(b) unsigned int b; {            /* Locking Shift Lookahead */
+    int i;
+    if (zincnt < 3)                    /* If not enough chars in buffer, */
+      return(1);                       /* force shift-state switch. */
+    b &= 0200;                         /* Force argument to proper form. */
+    for (i = -1; i < 3; i++)           /* Look at next 5 characters to */
+      if (((*(zinptr+i)) & 0200) != b) /* see if all their 8th bits match.  */
+       return(0);                      /* They don't. */
+    return(1);                         /* They do. */
+}
+
+int
+getpkt(bufmax,xlate) int bufmax, xlate; { /* Fill one packet buffer */
+    register CHAR rt = t, rnext = next; /* register shadows of the globals */
+    register CHAR *dp, *odp, *odp2, *p1, *p2; /* pointers... */
+    register int x;                    /* Loop index. */
+    register int a7;                   /* Low 7 bits of character */
+    static CHAR leftover[9] = { '\0','\0','\0','\0','\0','\0','\0','\0','\0' };
+    CHAR xxls, xxdl, xxrc, xxss, xxcq; /* Pieces of prefixed sequence */
+    int n;                             /* worker */
+
+/*
+  Assume bufmax is the receiver's total receive-packet buffer length.
+  Our whole packet has to fit into it, so we adjust the data field length.
+  We also decide optimally whether it is better to use a short-format or
+  long-format packet when we're near the borderline.
+*/
+    n = bufmax - 5;                    /* Space for Data and Checksum */
+    if (n > 92 && n < 96) n = 92;      /* "Short" Long packets don't pay */
+    if (n > 92 && lpcapu == 0)         /* If long packets needed, */
+      n = 92;                          /* make sure they've been negotiated */
+    bufmax = n - bctl;                 /* Space for data */
+    if (n > 92) bufmax -= 3;           /* Long packet needs header chksum */
+
+    if (first == 1) {          /* If first character of this file... */
+       ffc = 0L;               /* Reset file character counter */
+       first = 0;              /* Next character won't be first */
+       *leftover = '\0';       /* Discard any interrupted leftovers, */
+
+       /* get first character of file into rt, watching out for null file */
+
+#ifndef NOCSETS
+#ifdef KANJI
+       if (!binary && tcharset == TC_JEUC && xlate) {
+           x = zkanjf();
+           if ((x = zkanji( memstr ? kgetm : kgetf )) < 0) {
+               first = -1;
+               size = 0;
+               if (x == -2) {
+                   debug(F100,"getpkt(zkanji): input error","",0);
+                   cxseen = 1;
+               } else debug(F100,"getpkt(zkanji): empty string/file","",0);
+               return (0);
+           }
+           ffc++;
+           rt = x;
+       } else {
+#endif /* KANJI */
+#endif /* not NOCSETS */
+       if (memstr) {                   /* Reading data from memory string */
+           if ((rt = *memptr++) == '\0') { /* end of string ==> EOF */
+               first = -1;
+               size = 0;
+               debug(F100,"getpkt: empty string","",0);
+               return (0);
+           }
+
+       } else {                        /* Reading data from a file */
+
+           if ((x = zminchar()) < 0) { /* End of file or input error */
+               first = -1;
+               size = 0;
+               if (x == -2) {          /* Error */
+                   debug(F100,"getpkt: input error","",0);
+                   cxseen = 1;         /* Interrupt the file transfer */
+               } else debug(F100,"getpkt: empty file","",0); /* Empty file */
+               return(0);
+           }
+           ffc++;                      /* Count a file character */
+           rt = x;                     /* Convert int to char */
+           debug(F101,"getpkt zminchar","",rt);
+       }
+#ifndef NOCSETS
+#ifdef KANJI
+       }
+#endif /* KANJI */
+#endif /* not NOCSETS */
+
+       rt &= fmask;                    /* Apply SET FILE BYTESIZE mask */
+       debug(F101,"getpkt fmask","",fmask);
+       debug(F101,"getpkt new rt","",rt);
+
+#ifndef NOCSETS
+       if (xlate) {
+           debug(F101,"getpkt about to call translate function","",rt);
+           debug(F101,"tcharset","",tcharset);
+           debug(F101,"fcharset","",fcharset);
+       }
+#ifdef KANJI
+       if (tcharset != TC_JEUC)
+#endif /* KANJI */
+         if (!binary && sx && xlate) {
+             rt = (*sx)(rt); /* Translate */
+             debug(F101," translate function returns","",rt);
+         }
+#endif /* not NOCSETS */
+
+       /* PWP: handling of NLCHAR is done later (in the while loop)... */
+
+    } else if ((first == -1) && (*leftover == '\0')) /* EOF from last time? */
+        return(size = 0);
+/*
+  Here we handle characters that were encoded for the last packet but
+  did not fit, and so were saved in the "leftover" array.
+*/
+    dp = data;                         /* Point to packet data buffer */
+    for (p1 = leftover; (*dp = *p1) != '\0'; p1++, dp++) /* Copy leftovers */
+       ;
+    *leftover = '\0';                  /* Delete leftovers */
+    if (first == -1)                   /* Handle EOF */
+      return(size = (dp - data));
+  
+/* Now fill up the rest of the packet. */
+
+    rpt = 0;                           /* Initialize character repeat count */
+
+    while (first > -1) {               /* Until EOF... */
+#ifndef NOCSETS
+#ifdef KANJI
+       if (!binary && xlate && tcharset == TC_JEUC) {
+           if ((x = zkanji( memstr ? kgetm : kgetf )) < 0) {
+               first = -1;
+               if (x == -2) cxseen = 1;
+           }
+           ffc++;
+           rnext = x & fmask;
+       } else {
+#endif /* KANJI */
+#endif /* not NOCSETS */
+       if (memstr) {                   /* Get next char from memory string */
+           if ((x = *memptr++) == '\0') /* End of string means EOF */
+             first = -1;               /* Flag EOF for next time. */
+           rnext = x & fmask;          /* Apply file mask */
+       } else {
+           if ((x = zminchar()) < 0) { /* Real file, check for EOF */
+               first = -1;             /* Flag eof for next time. */
+               if (x == -2) cxseen = 1; /* If error, cancel this file. */
+           }
+           rnext = x & fmask;          /* Apply file mask */
+       } 
+       ffc++;                          /* Count the character */
+#ifndef NOCSETS
+#ifdef KANJI
+       }
+#endif /* KANJI */
+#endif /* not NOCSETS */
+
+       /*** debug(F101,"getpkt rnext","",rnext); ***/
+
+#ifndef NOCSETS
+#ifdef KANJI
+       if (tcharset != TC_JEUC)
+#endif /* KANJI */
+           if (!binary && sx && xlate) {
+               rnext = (*sx)(rnext); /* Translate */
+               debug(F101,"getpkt xlated rnext to","",rnext);
+           }
+#endif /* not NOCSETS */
+
+       odp = dp;                       /* Remember where we started. */
+       xxls = xxdl = xxrc = xxss = xxcq = NUL; /* Clear these. */
+
+/*
+  Now encode the character according to the options that are in effect:
+    binary: text or binary mode.
+    rptflg: repeat counts enabled.
+    ebqflg: 8th-bit prefixing enabled.
+    lscapu: locking shifts enabled.
+*/
+       if (rptflg) {                   /* Repeat processing is on? */
+           if (
+#ifdef NLCHAR
+               /*
+                * If the next char is really CRLF, then we cannot
+                * be doing a repeat (unless CR,CR,LF which becomes
+                * "~ <n-1> CR CR LF", which is OK but not most efficient).
+                * I just plain don't worry about this case.  The actual
+                * conversion from NL to CRLF is done after the rptflg if...
+                */
+           (binary || (rnext != NLCHAR)) &&
+#endif /* NLCHAR */
+           (rt == rnext) && (first == 0)) { /* Got a run... */
+               if (++rpt < 94) {       /* Below max, just count */
+                   continue;           /* go back and get another */
+               }
+               else if (rpt == 94) {   /* Reached max, must dump */
+                   xxrc = tochar(rpt); /* Put the repeat count here */
+                   rptn += rpt;        /* Accumulate it for statistics */
+                   rpt = 0;            /* And reset it */
+               }
+           } else if (rpt > 1) {       /* More than two */
+               xxrc = tochar(++rpt);   /* and count. */
+               rptn += rpt;
+               rpt = 0;                /* Reset repeat counter. */
+           }
+           /*
+             If (rpt == 1) we must encode exactly two characters.
+             This is done later, after the first character is encoded.
+           */
+       }
+
+#ifdef NLCHAR
+       if (!binary && (rt == NLCHAR)) { /* It's the newline character */
+           if (lscapu && lsstate) {    /* If SHIFT-STATE is SHIFTED */
+               if (ebqflg) {           /* If single shifts enabled, */
+                   *dp++ = ebq;        /* insert a single shift. */
+               } else {                /* Otherwise must shift in. */
+                   *dp++ = myctlq;     /* Insert shift-out code */
+                   *dp++ = 'O';
+                   lsstate = 0;        /* Change shift state */
+               }
+           }
+           *dp++ = myctlq;             /* Insert carriage return directly */
+           *dp++ = 'M';
+           rt = LF;                    /* Now make next char be linefeed. */
+       }
+#endif /* NLCHAR */
+
+/*
+  Now handle the 8th bit of the file character.  If we have an 8-bit
+  connection, we preserve the 8th bit.  If we have a 7-bit connection,
+  we employ either single or locking shifts (if they are enabled).
+*/
+       a7 = rt & 0177;                 /* Get low 7 bits of character */
+       if (rt & 0200) {                /* 8-bit character? */
+           if (lscapu) {               /* Locking shifts enabled? */
+               if (!lsstate) {         /* Not currently shifted? */
+                   x = lslook(0200);   /* Look ahead */
+                   if (x != 0 || ebqflg == 0) { /* Locking shift decision */
+                       xxls = 'N';        /* Need locking shift-out */
+                       lsstate = 1;       /* and change to shifted state */
+                   } else if (ebqflg) {   /* Not worth it */
+                       xxss = ebq;        /* Use single shift */
+                   }
+               }
+               rt = a7;                /* Replace character by 7-bit value */
+           } else if (ebqflg) {        /* 8th bit prefixing is on? */
+               xxss = ebq;             /* Insert single shift */
+               rt = a7;                /* Replace character by 7-bit value */
+           }
+
+       } else if (lscapu) {            /* 7-bit character */
+
+           if (lsstate) {              /* Comes while shifted out? */
+               x = lslook(0);          /* Yes, look ahead */
+               if (x || ebqflg == 0) { /* Time to shift in. */
+                   xxls = 'O';         /* Set shift-in code */
+                   lsstate = 0;        /* Exit shifted state */
+               } else if (ebqflg) {    /* Not worth it, stay shifted out */
+                   xxss = ebq;         /* Insert single shift */
+               }
+           }
+       }
+       /* If data character is significant to locking shift protocol... */
+       if (lscapu && (a7 == SO || a7 == SI || a7 == DLE))
+         xxdl = 'P';                   /* Insert datalink escape */
+
+       if ((a7 < SP) || (a7 == DEL)) { /* Do control prefixing if necessary */
+           xxcq = myctlq;              /* The prefix */
+           rt = ctl(rt);               /* Uncontrollify the character */
+       }
+       if (a7 == myctlq)               /* Always prefix the control prefix */
+         xxcq = myctlq;
+
+       if ((rptflg) && (a7 == rptq))   /* If it's the repeat prefix, */
+         xxcq = myctlq;                /* prefix it if doing repeat counts */
+
+       if ((ebqflg) && (a7 == ebq))    /* Prefix the 8th-bit prefix */
+         xxcq = myctlq;                /* if doing 8th-bit prefixes */
+
+/* Now construct the entire sequence */
+
+       if (xxls) { *dp++ = myctlq; *dp++ = xxls; } /* Locking shift */
+       odp2 = dp;                                  /* (Save this place) */
+       if (xxdl) { *dp++ = myctlq; *dp++ = xxdl; } /* Datalink escape */
+       if (xxrc) { *dp++ = rptq;   *dp++ = xxrc; } /* Repeat count */
+       if (xxss) { *dp++ = ebq; }                  /* Single shift */
+       if (xxcq) { *dp++ = myctlq; }               /* Control prefix */
+       *dp++ = rt;                     /* Finally, the character itself */
+
+       if (rpt == 1) {                 /* Exactly two copies? */
+           rpt = 0;
+           p2 = dp;                    /* Save place temporarily */
+           for (p1 = odp2; p1 < p2; p1++) /* Copy the old chars over again */
+             *dp++ = *p1;
+           if ((p2-data) <= bufmax) odp = p2; /* Check packet bounds */
+       }
+       rt = rnext;                     /* Next character is now current. */
+
+/* Done encoding the character.  Now take care of packet buffer overflow. */
+
+       if ((dp-data) >= bufmax) {      /* If too big, save some for next. */
+           size = (dp-data);           /* Calculate the size. */
+           *dp = '\0';                 /* Mark the end. */
+           if ((dp-data) > bufmax) {   /* if packet is overfull */
+               /* copy the part that doesn't fit into the leftover buffer, */
+               /* taking care not to split a prefixed sequence. */
+               for (p1 = leftover, p2=odp; (*p1 = *p2) != '\0'; p1++,p2++)
+                   ;
+               debug(F111,"getpkt leftover",leftover,size);
+               debug(F101," osize","",(odp-data));
+               size = (odp-data);      /* Return truncated packet. */
+               *odp = '\0';            /* Mark the new end */
+           }
+           t = rt; next = rnext;       /* save for next time */
+           return(size);
+       }
+    }                                  /* Otherwise, keep filling. */
+
+    size = (dp-data);                  /* End of file */
+    *dp = '\0';                                /* Mark the end of the data. */
+    debug(F111,"getpkt eof/eot",data,size); /* Fell thru before packet full, */
+    return(size);                   /* return partially filled last packet. */
+}
+\f
+/*  T I N I T  --  Initialize a transaction  */
+
+int
+tinit() {
+    int x;
+
+#ifndef NOCSETS
+    if (tcharset == TC_TRANSP) {       /* Character set translation */
+       rx = sx = NULL;                 /* Transparent, no translation */
+#ifdef KANJI
+    } else if (tcharset == TC_JEUC) {
+       rx = sx = NULL;                 /* Transparent, no translation */      
+#endif /* KANJI */
+    } else {                           /* otherwise */
+       rx = xlr[tcharset][fcharset];   /* Input translation function */
+       sx = xls[tcharset][fcharset];   /* Output translation function */
+    }
+    debug(F101,"tinit tcharset","",tcharset);
+    debug(F101,"tinit fcharset","",fcharset);
+#ifdef COMMENT
+    debug(F101,"tinit sx   ","",sx);
+    debug(F101,"tinit rx   ","",rx);
+#endif /* COMMENT */
+#endif /* NOCSETS */
+    myinit[0] = '\0';                  /* Haven't sent init string yet */
+    autopar = 0;                       /* Automatic parity detection flag */
+    retrans = 0;                       /* Packet retransmission count */
+    sndtyp = 0;                                /* No previous packet */
+    xflg = 0;                          /* Reset x-packet flag */
+    rqf = -1;                          /* Reset 8th-bit-quote request flag */
+    memstr = 0;                                /* Reset memory-string flag */
+    memptr = NULL;                     /*  and pointer */
+    bctu = bctl = 1;                   /* Reset block check type to 1 */
+    ebq = MYEBQ;                       /* Reset 8th-bit quoting stuff */
+    ebqflg = 0;
+    if (savmod) {                      /* If global file mode was saved, */
+       binary = savmod;                /*  restore it, */
+       savmod = 0;                     /*  unsave it. */
+    }
+    pktnum = 0;                                /* Initial packet number */
+    cxseen = czseen = discard = 0;     /* Reset interrupt flags */
+    *filnam = '\0';                    /* Clear file name */
+    spktl = 0;                         /* And its length */
+    nakstate = 0;                      /* Assume not in a NAK'ing state */
+    numerrs = 0;                       /* Transmission error counter */
+    if (server)                        /* If acting as server, */
+      timint = srvtim;                 /* Use server timeout interval. */
+    else                               /* Otherwise */
+      timint = chktimo(rtimo,timef);   /* Begin by using local value */
+    spsiz = spsizr;                    /* Initial send-packet size */
+    wslots = 1;                                /* One window slot */
+    wslotn = 1;                                /* No window negotiated yet */
+    winlo = 0;                         /* Packet 0 is at window-low */
+    x = mksbuf(1);                     /* Make a 1-slot send-packet buffer */
+    if (x < 0) return(x);
+    x = getsbuf(0);                    /* Allocate first send-buffer. */
+    debug(F101,"tinit getsbuf","",x);
+    if (x < 0) return(x);
+    dumpsbuf();
+    x = mkrbuf(wslots);                        /* & a 1-slot receive-packet buffer. */
+    if (x < 0) return(x);
+    what = W_NOTHING;                  /* Doing nothing so far... */
+    lsstate = 0;                       /* Initialize locking shift state */
+    return(0);
+}
+
+VOID
+pktinit() {                            /* Initialize packet sequence */
+    pktnum = 0;                                /* number & window low. */
+    winlo = 0;
+}
+
+/*  R I N I T  --  Respond to S or I packet  */
+
+VOID
+rinit(d) CHAR *d; {
+    char *tp;
+    ztime(&tp);
+    tlog(F110,"Transaction begins",tp,0L); /* Make transaction log entry */
+    if (binary)
+      tlog(F100,"Global file mode = binary","",0L);
+    else
+      tlog(F100,"Global file mode = text","",0L);
+    filcnt = 0;                                /* Init file counter */
+    spar(d);
+    ack1(rpar());
+#ifdef datageneral
+    if ((local) && (!quiet))            /* Only do this if local & not quiet */
+        consta_mt();                    /* Start the asynch read task */
+#endif /* datageneral */
+}
+
+
+/*  R E S E T C  --  Reset per-transaction character counters */
+
+VOID
+resetc() {
+    rptn = 0;                          /* Repeat counts */
+    fsecs = flci = flco = 0L;          /* File chars in and out */
+    tfc = tlci = tlco = 0L;            /* Total file, line chars in & out */
+#ifdef COMMENT
+    fsize = -1L;                       /* File size */
+#else
+    if (what != W_SEND)
+      fsize = -1L;
+    debug(F101,"resetc fsize","",fsize);
+#endif /* COMMENT */
+    timeouts = retrans = 0;            /* Timeouts, retransmissions */
+    spackets = rpackets = 0;           /* Packet counts out & in */
+    crunched = 0;                      /* Crunched packets */
+    wmax = 1;                          /* Maximum window size used */
+}
+\f
+/*  S I N I T  --  Get & verify first file name, then send Send-Init packet */
+/*
+ Returns:
+   1 if send operation begins successfully
+   0 if send operation fails
+*/
+#ifdef DYNAMIC
+char *cmargbuf = NULL;
+#else
+char cmargbuf[256];
+#endif /* DYNAMIC */
+char *cmargp[2];
+
+int
+sinit() {
+    int x;                             /* Worker int */
+    char *tp, *xp, *m;                 /* Worker string pointers */
+
+    filcnt = 0;                                /* Initialize file counter */
+    sndsrc = nfils;                    /* Source for filenames */
+#ifdef DYNAMIC
+    if (!cmargbuf && !(cmargbuf = malloc(256)))
+       fatal("sinit: no memory for cmargbuf");
+#endif /* DYNAMIC */
+    cmargbuf[0] = NUL;                 /* Initialize name buffer */
+
+    debug(F101,"sinit nfils","",nfils);
+    debug(F110,"sinit cmarg",cmarg,0);
+    debug(F110,"sinit cmarg2",cmarg2,0);
+    if (nfils == 0) {                  /* Sending from stdin or memory. */
+       if ((cmarg2 != NULL) && (*cmarg2)) {
+           cmarg = cmarg2;             /* If F packet, "as-name" is used */
+           cmarg2 = "";                /* if provided */
+       } else cmarg = "stdin";         /* otherwise just use "stdin" */
+       strcpy(cmargbuf,cmarg);
+       cmargp[0] = cmargbuf;
+       cmargp[1] = "";
+       cmlist = cmargp;
+       nfils = 1;
+    }
+#ifdef COMMENT
+    if (nfils < 1) {                   /* Filespec pointed to by cmarg */
+       if (nfils < 0) sndsrc = 1;
+       nfils = 1;                      /* Change it to cmlist */
+       strcpy(cmargbuf,cmarg);         /* so we have a consistent way */
+       cmargp[0] = cmargbuf;           /* of going thru the file list. */
+       cmargp[1] = "";
+       cmlist = cmargp;
+    }
+
+/* At this point, cmlist contains the list of filespecs to send */
+
+    debug(F111,"sinit *cmlist",*cmlist,nfils);
+
+    xp = *cmlist;                      /* Save this for messages */
+#else
+    xp = (nfils < 0) ? cmarg : *cmlist;
+#endif
+
+    x = gnfile();                      /* Get first filename. */
+    m = NULL;                          /* Error message pointer */
+    debug(F101,"sinit gnfil","",x);
+    switch (x) {
+      case -5: m = "Too many files match wildcard"; break;
+      case -4: m = "Cancelled"; break;
+      case -3: m = "Read access denied"; break;
+      case -2: m = "File is not readable"; break;
+      case -1: m = iswild(filnam) ? "No files match" : "File not found";
+       break;
+      case  0: m = "No filespec given!" ; break;
+      default:
+       break;
+    }
+    debug(F101,"sinit nfils","",nfils);
+    debug(F110,"sinit filnam",filnam,0);
+    debug(F110,"sinit cmdstr",cmdstr,0);
+    if (x < 1) {                       /* Didn't get a file. */
+       if (server)                     /* Doing GET command */
+         errpkt((CHAR *)m);            /* so send Error packet. */
+       else                            /* Doing SEND command */
+         screen(SCR_EM,0,0l,m);        /* so print message. */
+       tlog(F110,xp,m,0L);             /* Make transaction log entry. */
+       freerbuf(rseqtbl[0]);           /* Free the buffer the GET came in. */
+       return(0);                      /* Return failure code */
+    }
+    if (!local && !server) sleep(delay); /* Delay if requested */
+#ifdef datageneral
+    if ((local) && (!quiet))            /* Only do this if local & not quiet */
+        consta_mt();                    /* Start the asynch read task */
+#endif /* datageneral */
+    freerbuf(rseqtbl[0]);              /* Free the buffer the GET came in. */
+    sipkt('S');                                /* Send the Send-Init packet. */
+    ztime(&tp);                                /* Get current date/time */
+    tlog(F110,"Transaction begins",tp,0L); /* Make transaction log entry */
+    debug(F111,"sinit ok",filnam,0);
+    return(1);
+}
+
+int
+#ifdef CK_ANSIC
+sipkt(char c)                          /* Send S or I packet. */
+#else
+sipkt(c) char c;
+#endif
+/* sipkt */ {
+    CHAR *rp; int k;
+    debug(F101,"sipkt pktnum","",pktnum);
+    k = sseqtbl[pktnum];               /* Find slot for this packet */
+    debug(F101,"sipkt k","",k);
+    if (k < 0) {                       /* No slot? */
+       k = getsbuf(winlo = pktnum);    /* Make one. */
+       debug(F101,"sipkt getsbuf","",k);    
+    }
+    ttflui();                          /* Flush pending input. */
+    rp = rpar();                       /* Get protocol parameters. */
+    return(spack(c,pktnum,(int)strlen((char *)rp),rp)); /* Send them. */
+}
+
+/*  X S I N I T  --  Retransmit S-packet  */
+/*
+  For use in the GET-SEND sequence, when we start to send, but receive another
+  copy of the GET command because the receiver didn't get our S packet.
+  This retransmits the S packet and frees the receive buffer for the ACK.
+  The only reason this special case is necessary is that packet number zero
+  is being re-used.
+*/
+VOID
+xsinit() {
+    int k;     
+    k = rseqtbl[0];
+    debug(F101,"xsinit k","",k);
+    if (k > -1)
+      freerbuf(k);
+    resend(0);
+}        
+\f
+/*  R C V F I L -- Receive a file  */
+
+/*
+  Incoming filename is in data field of F packet.
+  This function decodes it into the srvcmd buffer, substituting an
+  alternate "as-name", if one was given.
+  Then it does any requested transformations (like converting to
+  lowercase), and finally if a file of the same name already exists, 
+  takes the desired collision action.
+*/
+#ifdef pdp11
+#define XNAMLEN 65
+#else
+#define XNAMLEN 256
+#endif /* pdp11 */
+
+int
+rcvfil(n) char *n; {
+    char xname[XNAMLEN], *xp;          /* Buffer for constructing name */
+#ifdef DTILDE
+    char *dirp, *tilde_expand();
+#endif /* DTILDE */
+
+    lsstate = 0;                       /* Cancel locking-shift state */
+    srvptr = srvcmd;                   /* Decode file name from packet. */
+    decode(rdatap,putsrv,0);           /* Don't xlate charsets. */
+    if (*srvcmd == '\0')               /* Watch out for null F packet. */
+      strcpy((char *)srvcmd,"NONAME");
+#ifdef DTILDE
+    dirp = tilde_expand((char *)srvcmd); /* Expand tilde, if any. */
+    if (*dirp != '\0') strcpy((char *)srvcmd,dirp);
+#endif /* DTILDE */
+    screen(SCR_FN,0,0l,(char *)srvcmd);        /* Put it on screen if local */
+    debug(F110,"rcvfil",(char *)srvcmd,0); /* Debug log entry */
+    debug(F101,"rcvfil cmarg2","",cmarg2);
+    tlog(F110,"Receiving",(char *)srvcmd,0L); /* Transaction log entry */
+    if (cmarg2 != NULL) {               /* Check for alternate name */
+        if (*cmarg2 != '\0') {
+            strcpy((char *)srvcmd,cmarg2); /* Got one, use it. */
+        }
+    } else cmarg2 = "";
+/*
+  NOTE: Much of this code should be moved to opena(), where the file is
+  actually opened, AFTER we have received the Attribute packet(s).  That
+  way, if the file is mail, or is being sent to the printer, we don't have
+  to fuss with collision options, etc, but instead we just pipe the data
+  straight into lpr or mail (in UNIX anyway), and then we can also have
+  nice subject lines for mail messages by using whatever is in the file
+  header packet data field, whether it's a legal filename or not.
+*/
+    if ((int)strlen((char *)srvcmd) > XNAMLEN) /* Watch out for overflow */
+      *(srvcmd + XNAMLEN - 1) = NUL;
+
+    xp = xname;                                /* OK to proceed. */
+    if (fncnv && !*cmarg2)
+      zrtol((char *)srvcmd,xp);                /* convert name to local form */
+    else                               /* otherwise, */
+      strcpy(xname,(char *)srvcmd);    /* use it literally */
+    cmarg2 = "";                       /* Remove alternate name */
+    debug(F110,"rcvfil as",xname,0);
+
+#ifdef COMMENT                         /* Old code... */
+    if (warn) {                                /* File collision avoidance? */
+       if (zchki(xname) != -1) {       /* Yes, file exists? */
+           znewn(xname,&xp);           /* Yes, make new name. */
+           strcpy(xname,xp);
+           debug(F110," exists, new name ",xname,0);
+        }
+    }
+#endif /* COMMENT */
+
+/* Filename collision action section. */
+
+    if (
+#ifdef UNIX
+       strcmp(xname,"/dev/null") &&    /* It's not the null device? */
+#endif /* UNIX */
+       (zchki(xname) != -1)            /* File of same name exists? */
+       ) {                             
+       debug(F111,"rcvfil exists",xname,fncact);
+       switch (fncact) {               /* Yes, do what user said. */
+         case XYFX_A:                  /* Append */
+           debug(F100,"rcvfil append","",0);
+           break;
+         case XYFX_Q:                  /* Query (Ask) */
+           break;                      /* not yet implemented */
+         case XYFX_B:                  /* Backup (rename old file) */
+           znewn(xname,&xp);           /* Get new unique name */
+           debug(F110,"rcvfil backup",xname,0);
+           debug(F110,"rcvfil backup",xp,0);
+           if (zrename(xname,xp) < 0) {
+               debug(F110,"rcvfil rename fails",xname,0);
+               return(0);
+           }
+           break;
+         case XYFX_D:                  /* Discard (refuse new file) */
+           discard = 1;
+           debug(F101,"rcvfil discard","",discard);
+           break;                      /* not yet implemented */
+         case XYFX_R:                  /* Rename new file */
+           znewn(xname,&xp);           /* Make new name. */
+           strcpy(xname,xp);
+           debug(F110,"rcvfil rename",xname,0);
+         case XYFX_X:                  /* Replace old file */
+           debug(F100,"rcvfil overwrite","",0);
+           break;
+         case XYFX_U:                  /* Refuse if older */
+           debug(F100,"rcvfil update","",0);
+           break;                      /* Not here, we don't have */
+                                       /* the attribute packet yet. */
+         default:
+           debug(F101,"rcvfil bad collision action","",fncact);
+           break;
+       }
+    }
+    debug(F110,"rcvfil: xname",xname,0);
+    screen(SCR_AN,0,0l,xname);         /* Display it */
+    strcpy(n,xname);                   /* Return pointer to actual name. */
+
+#ifndef NOICP
+#ifndef MAC
+/* Why not Mac? */
+    strcpy(fspec,xname);               /* Here too for \v(filespec) */
+#endif /* MAC */
+#endif /* NOICP */
+    debug(F110,"rcvfil: n",n,0);
+    ffc = 0L;                          /* Init per-file counters */
+    fsecs = gtimer();                  /* Time this file started */
+    filcnt++;
+    intmsg(filcnt);
+    return(1);                         /* Always succeeds */
+}
+
+
+/*  R E O F  --  Receive End Of File packet for incoming file */
+
+/*
+  Closes the received file.
+  Returns:
+    0 on success.
+   -1 if file could not be closed.
+    2 if disposition was mail, mail was sent, but temp file not deleted.
+    3 if disposition was print, file was printed, but not deleted.
+   -2 if disposition was mail and mail could not be sent
+   -3 if disposition was print and file could not be printed
+*/
+int
+reof(f,yy) char *f; struct zattr *yy; {
+    int x;
+    char *p;
+    char c;
+
+    debug(F111,"reof fncact",f,fncact);
+    debug(F101,"reof discard","",discard);
+    success = 1;                       /* Assume status is OK */
+    lsstate = 0;                       /* Cancel locking-shift state */
+    if (
+#ifdef COMMENT
+/*
+  If the discard flag is set, for whatever reason, we discard it, right?
+*/
+       (fncact == XYFX_D || fncact == XYFX_U) &&
+#endif /* COMMENT */
+       discard != 0) {    /* SET FILE COLLISION DISCARD or UPDATE */
+
+       debug(F101,"reof discarding","",0);
+       discard = 0;                    /* We never opened it, */
+       return(0);                      /* so we won't close it. */
+    }
+    if (cxseen == 0) cxseen = (*rdatap == 'D');        /* Got cancel directive? */
+    success = (cxseen || czseen) ? 0 : 1; /* Set SUCCESS flag appropriately */
+    x = clsof(cxseen || czseen);       /* Close the file (resets cxseen) */
+    if (x < 0) success = 0;            /* If failure to close, FAIL */
+    if (atcapu) zstime(f,yy,0);                /* Set file creation date */
+
+/* Handle dispositions from attribute packet... */
+
+#ifndef NOFRILLS
+    if (yy->disp.len != 0) {
+       p = yy->disp.val;
+       c = *p++;
+       if (c == 'M') {                 /* Mail to user. */
+           x = zmail(p,filnam);        /* Do the system's mail command */
+           if (x < 0) success = 0;     /* Remember status */
+           tlog(F110,"mailed",filnam,0L);
+           tlog(F110," to",p,0L);
+           zdelet(filnam);             /* Delete the file */
+       } else if (c == 'P') {          /* Print the file. */
+           x = zprint(p,filnam);       /* Do the system's print command */
+           if (x < 0) success = 0;     /* Remember status */
+           tlog(F110,"printed",filnam,0L);
+           tlog(F110," with options",p,0L);
+#ifndef VMS
+           if (zdelet(filnam) && x == 0) x = 3; /* Delete the file */
+#endif /* VMS */
+       }
+    }
+#endif /* NOFRILLS */
+    debug(F101,"reof returns","",x);
+    *filnam = '\0';
+    return(x);
+}
+
+/*  R E O T  --  Receive End Of Transaction  */
+
+VOID
+reot() {
+    cxseen = czseen = discard = 0;     /* Reset interruption flags */
+    tstats();
+}
+\f
+/*  S F I L E -- Send File header or teXt header packet  */
+
+/*  Call with x nonzero for X packet, zero for F packet  */
+/*  Returns 1 on success, 0 on failure                   */
+
+int
+sfile(x) int x; {
+#ifdef pdp11
+#define PKTNL 64
+#else
+#define PKTNL 256
+#endif /* pdp11 */
+    char pktnam[PKTNL+1];              /* Local copy of name */
+    char *s;
+
+    lsstate = 0;                       /* Cancel locking-shift state */
+    if (nxtpkt() < 0) return(0);       /* Bump packet number, get buffer */
+    if (x == 0) {                      /* F-Packet setup */
+
+       if (*cmarg2 != '\0') {          /* If we have a send-as name, */
+           strncpy(pktnam,cmarg2,PKTNL); /* copy it literally, */
+           cmarg2 = "";                /* and blank it out for next time. */
+       } else {                        /* Otherwise use actual file name: */
+           if (fncnv) {                /* If converting names, */
+               zltor(filnam,pktnam);   /* convert it to common form, */
+           } else {                    /* otherwise, */
+               strncpy(pktnam,filnam,PKTNL); /* copy it literally. */
+            }
+       }
+       debug(F110,"sfile",filnam,0);   /* Log debugging info */
+       debug(F110," pktnam",pktnam,0);
+       if (openi(filnam) == 0)         /* Try to open the file */
+         return(0);            
+       s = pktnam;                     /* Name for packet data field */
+
+    } else {                           /* X-packet setup */
+
+       debug(F110,"sxpack",cmdstr,0);  /* Log debugging info */
+       s = cmdstr;                     /* Name for data field */
+    }
+
+    encstr((CHAR *)s);                 /* Encode the name into encbuf[]. */
+                                       /* Send the F or X packet */
+    spack((char) (x ? 'X' : 'F'), pktnum, size, encbuf+7);
+
+    if (x == 0) {                      /* Display for F packet */
+       if (displa) {                   /* Screen */
+           screen(SCR_FN,'F',(long)pktnum,filnam);
+           screen(SCR_AN,0,0l,pktnam);
+           screen(SCR_FS,0,fsize,"");
+       }
+       tlog(F110,"Sending",filnam,0L); /* Transaction log entry */
+       tlog(F110," as",pktnam,0L);
+       if (binary) {                   /* Log file mode in transaction log */
+           tlog(F101," mode: binary","",(long) binary);
+       } else {                        /* If text mode, check character set */
+           tlog(F100," mode: text","",0L);
+#ifndef NOCSETS
+           tlog(F110," file character set",fcsinfo[fcharset].name,0L);
+           if (tcharset == TC_TRANSP)
+             tlog(F110," xfer character set","transparent",0L);
+           else
+             tlog(F110," xfer character set",tcsinfo[tcharset].name,0L);
+#endif /* NOCSETS */
+       }
+    } else {                           /* Display for X-packet */
+
+       screen(SCR_XD,'X',(long)pktnum,cmdstr); /* Screen */
+       tlog(F110,"Sending from:",cmdstr,0L);   /* Transaction log */
+    }
+    intmsg(++filcnt);                  /* Count file, give interrupt msg */
+    first = 1;                         /* Init file character lookahead. */
+    ffc = 0L;                          /* Init file character counter. */
+    fsecs = gtimer();                  /* Time this file started */
+    debug(F101,"SFILE fsecs","",fsecs);
+    return(1);
+}
+
+/*  S D A T A -- Send a data packet */
+
+/*
+  Returns -1 if no data to send (end of file).  If there is data, a data
+  packet is sent, and sdata() returns 1.
+
+  For window size greater than 1, keep sending data packets until window
+  is full or characters start to appear from the other Kermit, whichever
+  happens first.
+
+  In the windowing case, when there is no more data left to send (or when
+  sending has been interrupted), sdata() does nothing and returns 0 each time
+  it is called until the current packet number catches up to the last data
+  packet that was sent.
+*/
+
+int
+sdata() {
+    int i, x, len;
+    
+    debug(F101,"sdata entry, first","",first);
+    debug(F101," drain","",drain);
+
+/* The "drain" flag is used with window size > 1.  It means we have sent  */
+/* our last data packet.  If called and drain is not zero, then we return */
+/* 0 as if we had sent an empty data packet, until all data packets have  */
+/* been ACK'd, then then we can finally return -1 indicating EOF, so that */
+/* the protocol can switch to seof state.  This is a kludge, but at least */
+/* it's localized...  */
+
+    if (first == 1) drain = 0;         /* Start of file, init drain flag. */
+
+    if (drain) {                       /* If draining... */
+       debug(F101,"sdata draining, winlo","",winlo);
+       if (winlo == pktnum)            /* If all data packets are ACK'd */
+         return(-1);                   /* return EOF indication */
+       else                            /* otherwise */
+         return(0);                    /* pretend we sent a data packet. */
+    }
+    debug(F101,"sdata sbufnum","",sbufnum);
+    for (i = sbufnum; i > 0; i--) {
+        debug(F101,"sdata countdown","",i);
+       x = nxtpkt();                   /* Get next pkt number and buffer */
+       debug(F101,"sdata packet","",pktnum);
+       if (x < 0) return(0);
+/***   dumpsbuf(); */
+       if (cxseen || czseen) {         /* If interrupted, done. */
+           if (wslots > 1) {
+               drain = 1;
+               debug(F101,"sdata cx/zseen, drain","",cxseen);
+               return(0);
+           } else {
+               return(-1);
+           }
+       }
+#ifdef COMMENT
+       if (spsiz > 94)                 /* Fill the packet's data buffer */
+         len = getpkt(spsiz-bctl-6,1); /* long packet */
+       else                            /*  or */
+         len = getpkt(spsiz-bctl-3,1); /* short packet */
+#else
+       len = getpkt(spsiz,1);
+#endif /* COMMENT */
+       if (len == 0) {                 /* Done if no data. */
+           if (pktnum == winlo) return(-1);
+           drain = 1;                  /* But can't return -1 until all */
+           debug(F101,"sdata eof, drain","",drain);
+           return(0);                  /* ACKs are drained. */
+       }
+       spack('D',pktnum,len,data);     /* Send the data packet. */
+       x = ttchk();                    /* Peek at input buffer. */
+       debug(F101,"sdata ttchk","",x); /* ACKs waiting, maybe?  */
+       if (x) return(1);               /* Yes, stop sending data packets */
+    }                                  /* and go try to read the ACKs. */
+    return(1);
+}
+
+
+/*  S E O F -- Send an End-Of-File packet */
+
+/*  Call with a string pointer to character to put in the data field, */
+/*  or else a null pointer or "" for no data.  */
+
+/*
+  There are two "send-eof" functions.  seof() is used to send the normal eof
+  packet at the end of a file's data (even if the file has no data), or when
+  a file transfer is interrupted.  sxeof() is used to send an EOF packet that
+  occurs because of attribute refusal.  The difference is purely a matter of
+  buffer allocation and packet sequence number management.  Both functions
+  act as "front ends" to the common send-eof function, szeof().
+*/
+
+/* Code common to both seof() and sxeof() */
+
+int
+szeof(s) CHAR *s; {
+    lsstate = 0;                       /* Cancel locking-shift state */
+    if ((s != NULL) && (*s != '\0')) {
+       spack('Z',pktnum,1,s);
+       tlog(F100," *** interrupted, sending discard request","",0L);
+    } else {
+       spack('Z',pktnum,0,(CHAR *)"");
+    }
+    discard = 0;                       /* Turn off per-file discard flag */
+    return(0);
+}
+
+int
+seof(s) CHAR *s; {
+
+/*
+  ckcpro.w, before calling seof(), sets window size back to 1 and then calls
+  window(), which clears out the old buffers.  This is OK because the final
+  data packet for the file has been ACK'd.  However, sdata() has already
+  called nxtpkt(), which set the new value of pktnum which seof() will use.
+  So all we need to do here is is allocate a new send-buffer.
+*/
+    if (getsbuf(pktnum) < 0) { /* Get a buffer for packet n */
+       debug(F101,"seof can't get s-buffer","",pktnum);
+       return(-1);
+    }
+    return(szeof(s));
+}
+
+/*
+  Version of seof() to be called when sdata() has not been called before.  The
+  difference is that this version calls nxtpkt() to allocate a send-buffer and
+  get the next packet number.
+*/
+int
+sxeof(s) CHAR *s; {
+    int x;
+    x = nxtpkt();                      /* Get next pkt number and buffer */
+    if (x < 0)
+      debug(F101,"sxeof nxtpkt fails","",pktnum);
+    else
+      debug(F101,"sxeof packet","",pktnum);
+    return(szeof(s));
+}
+
+/*  S E O T -- Send an End-Of-Transaction packet */
+
+int
+seot() {
+    if (nxtpkt() < 0) return(-1);      /* Bump packet number, get buffer */
+    spack('B',pktnum,0,(CHAR *)"");    /* Send the EOT packet */
+    cxseen = czseen = discard = 0;     /* Reset interruption flags */
+    tstats();                          /* Log timing info */
+    return(0);
+}
+\f
+/*   R P A R -- Fill the data array with my send-init parameters  */
+
+
+CHAR dada[20];                         /* Use this instead of data[]. */
+                                       /* To avoid some kind of wierd */
+                                       /* addressing foulup in spack()... */
+                                       /* (which might be fixed now...) */
+
+CHAR *
+rpar() {
+    if (rpsiz > MAXPACK)               /* Biggest normal packet I want. */
+      dada[0] = tochar(MAXPACK);       /* If > 94, use 94, but specify */
+    else                               /* extended packet length below... */
+      dada[0] = tochar(rpsiz);         /* else use what the user said. */
+    dada[1] = tochar(chktimo(pkttim,0)); /* When I want to be timed out */
+    dada[2] = tochar(mypadn);          /* How much padding I need (none) */
+    dada[3] = ctl(mypadc);             /* Padding character I want */
+    dada[4] = tochar(eol);             /* End-Of-Line character I want */
+    dada[5] = '#';                     /* Control-Quote character I send */
+    switch (rqf) {                     /* 8th-bit prefix */
+       case -1:
+       case  1: if (parity) ebq = sq = '&'; break;
+       case  0:
+       case  2: break;
+    }
+    debug(F000,"rpar 8bq sq","",sq);
+    debug(F000,"rpar 8bq ebq","",ebq);
+    if (lscapu == 2)                   /* LOCKING-SHIFT FORCED */
+      dada[6] = 'N';                   /* means no single-shift */
+    else
+      dada[6] = sq;
+    dada[7] = (bctr == 4) ? 'B' : bctr + '0'; /* Block check type */
+    if (rptflg)                                /* Run length encoding */
+       dada[8] = rptq;                 /* If receiving, agree. */
+    else
+       dada[8] = '~';          
+    /* CAPAS mask */
+    dada[9] = tochar((lscapr ? lscapb : 0) | /* Locking shifts */
+                    (atcapr ? atcapb : 0) | /* Attribute packets */
+                    (lpcapr ? lpcapb : 0) | /* Long packets */
+                    (swcapr ? swcapb : 0)); /* Sliding windows */
+    dada[10] = tochar(swcapr ? wslotr : 1);  /* Window size */
+    rpsiz = urpsiz - 1;                        /* Long packets ... */
+    dada[11] = tochar(rpsiz / 95);     /* Long packet size, big part */
+    dada[12] = tochar(rpsiz % 95);     /* Long packet size, little part */
+    dada[13] = '\0';                   /* Terminate the init string */
+#ifdef DEBUG
+    if (deblog) {
+       debug(F110,"rpar",dada,0);
+       rdebu(dada,(int)strlen((char *)dada));
+    }
+#endif /* DEBUG */
+    strcpy((char *)myinit,(char *)dada);
+    return(dada);                      /* Return pointer to string. */
+}
+\f
+int
+spar(s) CHAR *s; {                     /* Set parameters */
+    int x, y, lpsiz;
+
+    debug(F110,"entering spar",s,0);
+
+    s--;                               /* Line up with field numbers. */
+
+/* Limit on size of outbound packets */
+    x = (rln >= 1) ? xunchar(s[1]) : 80;
+    lpsiz = spsizr;                    /* Remember what they SET. */
+    if (spsizf) {                      /* SET-command override? */
+       if (x < spsizr) spsiz = x;      /* Ignore LEN unless smaller */
+    } else {                           /* otherwise */
+       spsiz = (x < 10) ? 80 : x;      /* believe them if reasonable */
+    }
+    spmax = spsiz;                     /* Remember maximum size */
+
+/* Timeout on inbound packets */
+    if (timef) {
+       timint = rtimo;                 /* SET SEND TIMEOUT value overrides */
+    } else {                           /* Otherwise use requested value, */
+       x = (rln >= 2) ? xunchar(s[2]) : rtimo; /* if it is legal. */
+       timint = (x < 0) ? rtimo : x;
+    }
+    timint = chktimo(timint,timef);    /* Adjust if necessary */
+
+/* Outbound Padding */
+    npad = 0; padch = '\0';
+    if (rln >= 3) {
+       npad = xunchar(s[3]);
+       if (rln >= 4) padch = ctl(s[4]); else padch = 0;
+    }
+    if (npad) {
+       int i;
+       for (i = 0; i < npad; i++) padbuf[i] = dopar(padch);
+    }
+
+/* Outbound Packet Terminator */
+    seol = (rln >= 5) ? xunchar(s[5]) : CR;
+    if ((seol < 2) || (seol > 31)) seol = CR;
+
+/* Control prefix */
+    x = (rln >= 6) ? s[6] : '#';
+    myctlq = ((x > 32 && x < 63) || (x > 95 && x < 127)) ? x : '#';
+
+/* 8th-bit prefix */
+    rq = (rln >= 7) ? s[7] : 0;
+    if (rq == 'Y') rqf = 1;
+      else if ((rq > 32 && rq < 63) || (rq > 95 && rq < 127)) rqf = 2;
+        else rqf = 0;
+    debug(F000,"spar 8bq rq","",rq);
+    debug(F000,"spar 8bq sq","",sq);
+    debug(F000,"spar 8bq ebq","",ebq);
+    debug(F101,"spar 8bq rqf","",rqf);
+    switch (rqf) {
+       case 0: ebqflg = 0; break;
+       case 1: if (parity) { ebqflg = 1; ebq = '&'; } break;
+       case 2: if (ebqflg = (ebq == sq || sq == 'Y')) ebq = rq;
+    }
+    if (lscapu == 2) {     /* No single-shifts if LOCKING-SHIFT FORCED */
+       ebqflg = 0;
+       ebq = 'N';
+    }
+
+/* Block check */
+    x = 1;
+    if (rln >= 8) {
+       if (s[8] == 'B') x = 4;
+       else x = s[8] - '0';
+       if ((x < 1) || (x > 4)) x = 1;
+    }
+    bctr = x;
+
+/* Repeat prefix */
+    if (rln >= 9) {
+       rptq = s[9]; 
+       rptflg = ((rptq > 32 && rptq < 63) || (rptq > 95 && rptq < 127));
+    } else rptflg = 0;
+
+/* Capabilities */
+    atcapu = lpcapu = swcapu = 0;      /* Assume none of these */
+    if (lscapu != 2) lscapu = 0;       /* Assume no LS unless forced. */
+    y = 11;                            /* Position of next field, if any */
+    if (rln >= 10) {
+        x = xunchar(s[10]);
+       debug(F101,"spar capas","",x);
+        atcapu = (x & atcapb) && atcapr;
+       lpcapu = (x & lpcapb) && lpcapr;
+       swcapu = (x & swcapb) && swcapr;
+       debug(F101,"spar lscapu","",lscapu);
+       debug(F101,"spar lscapr","",lscapr);
+       debug(F101,"spar ebqflg","",ebqflg);
+       if (lscapu != 2) lscapu = ((x & lscapb) && lscapr && ebqflg) ? 1 : 0;
+       debug(F101,"spar swcapr","",swcapr);
+       debug(F101,"spar swcapu","",swcapu);
+       debug(F101,"spar lscapu","",lscapu);
+       for (y = 10; (xunchar(s[y]) & 1) && (rln >= y); y++) ;
+       debug(F101,"spar y","",y);
+    }
+
+/* Long Packets */
+    debug(F101,"spar lpcapu","",lpcapu);
+    if (lpcapu) {
+        if (rln > y+1) {
+           x = xunchar(s[y+2]) * 95 + xunchar(s[y+3]);
+           debug(F101,"spar lp len","",x);
+           if (spsizf) {               /* If overriding negotiations */
+               spsiz = (x < lpsiz) ? x : lpsiz; /* do this, */
+           } else {                             /* otherwise */
+               spsiz = (x > MAXSP) ? MAXSP : x; /* do this. */
+           }
+           if (spsiz < 10) spsiz = 80; /* Be defensive... */
+       }
+    }
+    /* (PWP) save current send packet size for optimal packet size calcs */
+    spmax = spsiz;
+    debug(F101,"spar lp spmax","",spmax);
+    timint = chktimo(timint,timef);    /* Recalculate the packet timeout! */
+    
+/* Sliding Windows... */
+
+    if (swcapr) {                      /* Only if requested... */
+        if (rln > y) {                 /* See what other Kermit says */
+           x = xunchar(s[y+1]);
+           debug(F101,"spar window","",x);
+           wslotn = (x > MAXWS) ? MAXWS : x;
+/*
+  wslotn = negotiated size (from other Kermit's S or I packet).
+  wslotr = requested window size (from this Kermit's SET WINDOW command).
+*/
+           if (wslotn > wslotr)        /* Use the smaller of the two */
+             wslotn = wslotr;
+           if (wslotn < 1)             /* Watch out for bad negotiation */
+             wslotn = 1;
+           if (wslotn > 1)
+             swcapu = 1; /* We do windows... */
+           debug(F101,"spar window after adjustment","",x);
+       } else {                        /* No window size specified. */
+           wslotn = 1;                 /* We don't do windows... */
+           debug(F101,"spar window","",x);
+           swcapu = 0;
+           debug(F101,"spar no windows","",wslotn);
+       }
+    }
+
+/* Now recalculate packet length based on number of windows.   */
+/* The nogotiated number of window slots will be allocated,    */
+/* and the maximum packet length will be reduced if necessary, */
+/* so that a windowful of packets can fit in the big buffer.   */
+
+    if (wslotn > 1) {                  /* Shrink to fit... */
+       x = adjpkl(spsiz,wslotn,bigsbsiz);
+       if (x < spsiz) {
+           spsiz = spmax = x;
+           debug(F101,"spar sending, redefine spsiz","",spsiz);
+       }
+    }
+
+/* Record parameters in debug log */
+#ifdef DEBUG
+    if (deblog) sdebu(rln);
+#endif /* DEBUG */
+    numerrs = 0;                       /* Start counting errors here. */
+    return(0);
+}
+\f
+/*  G N F I L E  --  Get name of next file to send  */
+/*
+  Expects global sndsrc to be:
+   -1: next filename to be obtained by calling znext().
+    0: no next file name
+    1: (or greater) next filename to be obtained from **cmlist.
+  Returns:
+    1, with name of next file in filnam.
+    0, no more files, with filnam set to empty string.
+   -1, file not found
+   -2, file is not readable
+   -3, read access denied
+   -4, cancelled
+   -5, too many files match wildcard
+*/
+
+int
+gnfile() {
+    int x; long y;
+    int retcode = 0;
+
+    debug(F101,"gnfile sndsrc","",sndsrc);
+    fsize = -1L;                       /* Initialize file size */
+    if (sndsrc == 0) {                 /* It's not really a file */
+       if (nfils > 0) {                /* It's a pipe, or stdin */
+           strcpy(filnam, *cmlist);    /* Copy its "name" */
+           nfils = 0;                  /* There is no next file */
+           return(1);                  /* OK this time */
+       } else return(0);               /* but not next time */
+    }
+
+/* If file group interruption (C-Z) occurred, fail.  */
+
+    if (czseen) {
+       tlog(F100,"Transaction cancelled","",0L);
+        debug(F100,"gnfile czseen","",0);
+       return(-4);
+    }
+
+/* Loop through file list till we find a readable, sendable file */
+
+    y = -1L;                           /* Loop exit (file size) variable */
+    while (y < 0L) {                   /* Keep trying till we get one... */
+       if (sndsrc > 0) {               /* File list in cmlist */
+           debug(F101,"gnfile nfils","",nfils);
+           if (nfils-- > 0) {          /* Still some left? */
+               strcpy(filnam,*cmlist++);
+               debug(F111,"gnfile cmlist filnam",filnam,nfils);
+               if (!clfils) {          /* Expand only if not from cmdline */
+                   x = zxpand(filnam);
+                   debug(F101,"gnfile zxpand","",x);
+                   if (x == 1) {
+                       znext(filnam);
+                       goto gotnam;
+                   }
+                   if (x == 0) {
+                       retcode = -1; /* None match */
+                       continue;
+                   }
+                   if (x < 0) return(-5); /* Too many to expand */
+                   sndsrc = -1;        /* Change send-source to znext() */
+               }
+           } else {                    /* We're out of files. */
+               debug(F101,"gnfile done","",nfils);
+               *filnam = '\0';
+               return(retcode);
+           }
+       }
+
+/* Otherwise, step to next element of internal wildcard expansion list. */
+
+       if (sndsrc < 0) {
+           x = znext(filnam);
+           debug(F111,"gnfile znext",filnam,x);
+           if (x == 0) {               /* If no more, */
+               sndsrc = 1;             /* go back to list */
+               continue;
+           }
+       }
+
+/* Get here with a filename. */
+
+gotnam:
+       if (sndsrc) {
+           y = zchki(filnam);          /* Check if file readable */
+           retcode = (int) y;          /* Possible return code */
+           if (y == -1L) {             /* If not found */
+               debug(F110,"gnfile skipping:",filnam,0);
+               tlog(F111,filnam,"not sent, reason",(long)y);
+               screen(SCR_ST,ST_SKIP,0l,filnam);
+               continue;
+           } else if (y < 0) {
+               continue;
+           } else {
+               fsize = y;
+               return(1);
+           }
+       } else return(1);               /* sndsrc is 0... */
+    }
+    *filnam = '\0';                    /* Should never get here */
+    return(0);
+}
+
+\f
+/*  S N D H L P  --  Routine to send builtin help  */
+
+int
+sndhlp() {
+#ifndef NOSERVER
+    nfils = 0;                         /* No files, no lists. */
+    xflg = 1;                          /* Flag we must send X packet. */
+    strcpy(cmdstr,"help text");                /* Data for X packet. */
+    first = 1;                         /* Init getchx lookahead */
+    memstr = 1;                                /* Just set the flag. */
+    memptr = hlptxt;                   /* And the pointer. */
+    if (binary) {                      /* If file mode is binary, */
+       savmod = binary;                /*  remember to restore it later. */
+       binary = 0;                     /*  turn it back to text for this, */
+    }
+    return(sinit());
+#else
+    return(0);
+#endif /* NOSERVER */
+}
+
+#ifdef OS2
+/*  S N D S P A C E -- send disk space message  */
+int
+sndspace(int drive) {
+#ifndef NOSERVER
+    static char spctext[64];
+    if (drive)
+      sprintf(spctext, " Drive %c: %ldK free\n", drive, 
+             zdskspace(drive - 'A' + 1) / 1024L);
+    else
+      sprintf(spctext, " Free space: %ldK\n", zdskspace(0)/1024L);
+    nfils = 0;                 /* No files, no lists. */
+    xflg = 1;                  /* Flag we must send X packet. */
+    strcpy(cmdstr,"free space");/* Data for X packet. */
+    first = 1;                 /* Init getchx lookahead */
+    memstr = 1;                        /* Just set the flag. */
+    memptr = spctext;          /* And the pointer. */
+    if (binary) {              /* If file mode is binary, */
+        savmod = binary;       /*  remember to restore it later. */
+        binary = 0;            /*  turn it back to text for this, */
+    }
+    return(sinit());
+#else
+    return(0);
+#endif /* NOSERVER */
+}
+#endif /* OS2 */
+
+/*  C W D  --  Change current working directory  */
+
+/*
+ String passed has first byte as length of directory name, rest of string
+ is name.  Fails if can't connect, else ACKs (with name) and succeeds. 
+*/
+
+int
+cwd(vdir) char *vdir; {
+    char *cdd, *zgtdir(), *dirp;
+
+    vdir[xunchar(*vdir) + 1] = '\0';   /* Terminate string with a null */
+    dirp = vdir+1;
+    tlog(F110,"Directory requested: ",dirp,0L);
+    if (zchdir(dirp)) {                /* Try to change */
+       cdd = zgtdir();         /* Get new working directory. */
+       debug(F110,"cwd",cdd,0);
+       encstr((CHAR *)cdd);
+       ack1((CHAR *)(encbuf+7));
+       tlog(F110,"Changed directory to",cdd,0L);
+       return(1); 
+    } else {
+       debug(F110,"cwd failed",dirp,0);
+       tlog(F110,"Failed to change directory to",dirp,0L);
+       return(0);
+    }
+}
+
+
+/*  S Y S C M D  --  Do a system command  */
+
+/*  Command string is formed by concatenating the two arguments.  */
+
+int
+syscmd(prefix,suffix) char *prefix, *suffix; {
+    char *cp;
+
+    if (prefix == NULL || *prefix == '\0') return(0);
+
+    for (cp = cmdstr; *prefix != '\0'; *cp++ = *prefix++) ;
+    while (*cp++ = *suffix++) ;                /* copy suffix */
+
+    debug(F110,"syscmd",cmdstr,0);
+    if (zxcmd(ZIFILE,cmdstr) > 0) {
+       debug(F110,"syscmd zxcmd ok",cmdstr,0);
+       nfils = sndsrc = 0;             /* Flag that input is from stdin */
+       xflg = hcflg = 1;               /* And special flags for pipe */
+       if (binary) {                   /* If file mode is binary, */
+           savmod = binary;            /*  remember to restore it later. */
+           binary = 0;                 /*  turn it back to text for this, */
+       }
+       return (sinit());               /* Send S packet */
+    } else {
+       debug(F100,"syscmd zxcmd failed",cmdstr,0);
+       return(0);
+    }
+}
+
+/*  R E M S E T  --  Remote Set  */
+/*  Called by server to set variables as commanded in REMOTE SET packets.  */
+/*  Returns 1 on success, 0 on failure.  */
+
+int
+remset(s) char *s; {
+    int len, i, x, y;
+    char *p;
+
+    len = xunchar(*s++);               /* Length of first field */
+    p = s + len;                       /* Pointer to second length field */
+    *p++ = '\0';                       /* Zero out second length field */
+    x = atoi(s);                       /* Value of first field */
+    debug(F111,"remset",s,x);
+    debug(F110,"remset",p,0);
+    switch (x) {                       /* Do the right thing */
+      case 132:                                /* Attributes (all, in) */
+       atcapr = atoi(p);
+       return(1);
+      case 133:                                /* File length attributes */
+      case 233:                                /* IN/OUT combined */
+      case 148:                                /* Both kinds of lengths */
+      case 248:
+       atleni = atleno = atoi(p);
+       return(1);
+      case 134:                                /* File Type (text/binary) */
+      case 234:
+       attypi = attypo = atoi(p);
+       return(1);
+      case 135:                                /* File creation date */
+      case 235:
+       atdati = atdato = atoi(p);
+       return(1);
+      case 139:                                /* File Blocksize */
+      case 239:
+       atblki = atblko = atoi(p);
+       return(1);
+      case 141:                                /* Encoding / Character Set */
+      case 241:
+       atenci = atenco = atoi(p);
+       return(1);
+      case 142:                                /* Disposition */
+      case 242:
+       atdisi = atdiso = atoi(p);
+       return(1);
+      case 145:                                /* System ID */
+      case 245:
+       atsidi = atsido = atoi(p);
+       return(1);
+      case 147:                                /* System-Dependent Info */
+      case 247:
+       atsysi = atsyso = atoi(p);
+       return(1);
+      case 232:                                /* Attributes (all, out) */
+       atcapr = atoi(p);
+       return(1);
+      case 300:                                /* File type (text, binary) */
+       binary = atoi(p);
+       return(1);
+      case 301:                                /* File name conversion */
+       fncnv = 1 - atoi(p);            /* (oops) */
+       return(1);
+      case 302:                                /* File name collision */
+       x = atoi(p);
+       if (x == XYFX_R) warn = 1;      /* Rename */
+       if (x == XYFX_X) warn = 0;      /* Replace */
+       fncact = x;
+       return(1);
+      case 310:                                /* Incomplete File Disposition */
+       keep = atoi(p);                 /* Keep, Discard */
+       return(1);
+      case 311:                                /* Blocksize */
+       fblksiz = atoi(p);
+       return(1);
+      case 312:                                /* Record Length */
+       frecl = atoi(p);
+       return(1);
+      case 313:                                /* Record format */
+       frecfm = atoi(p);
+       return(1);
+      case 314:                                /* File organization */
+       forg = atoi(p);
+       return(1);
+      case 315:                                /* File carriage control */
+       fcctrl = atoi(p);
+       return(1);
+      case 400:                                /* Block check */
+       y = atoi(p);
+       if (y < 5 && y > 0) {
+           bctr = y;
+           return(1);
+       } else if (*p == 'B') {
+           bctr = 4;
+           return(1);
+       }
+       return(0);
+      case 401:                                /* Receive packet-length */
+       urpsiz = atoi(p);
+       if (urpsiz > MAXRP) urpsiz = MAXRP;
+       urpsiz = adjpkl(urpsiz,wslots,bigrbsiz);
+       return(1);
+      case 402:                                /* Receive timeout */
+       y = atoi(p);                    /* Client is telling us */
+       if (y > -1 && y < 999) {        /* the timeout that it wants */
+           pkttim = chktimo(y,timef);  /* us to tell it to use. */
+           return(1);
+       } else return(0);
+      case 403:                                /* Retry limit */
+       y = atoi(p);
+       if (y > -1 && y < 95) {
+           maxtry = y;
+           return(1);
+       } else return(0);
+      case 404:                                /* Server timeout */
+       y = atoi(p);
+       if (y < 0) return(0);
+       srvtim = y;
+       return(1);
+
+#ifndef NOCSETS
+      case 405:                                /* Transfer character set */
+       for (i = 0; i < ntcsets; i++) { 
+           if (!strcmp(tcsinfo[i].designator,p)) break;
+       }
+       debug(F101,"remset xfer charset lookup","",i);
+       if (i == ntcsets) return(0);
+       tcharset = tcsinfo[i].code;     /* if known, use it */
+       if (tcharset == TC_TRANSP)
+         rx = NULL;
+       else
+         rx = xlr[tcharset][fcharset]; /* translation function */
+       return(1);
+#endif /* NOCSETS */
+
+      case 406:                                /* Window slots */
+       y = atoi(p);
+       if (y == 0) y = 1;
+       if (y < 1 && y > 31) return(0);
+       wslotr = y;
+       swcapr = 1;
+       urpsiz = adjpkl(urpsiz,wslots,bigrbsiz);
+       return(1);
+      default:                         /* Anything else... */
+       return(0);
+    }
+}
+
+/* Adjust packet length based on number of window slots and buffer size */
+
+int
+adjpkl(pktlen,slots,bufsiz) int pktlen, slots, bufsiz; {
+    debug(F101,"adjpkl len","",pktlen);
+    debug(F101,"adjpkl slots","",slots);
+    debug(F101,"adjpkl bufsiz","",bufsiz);
+    if (((pktlen + 6) * slots) > bufsiz)
+      pktlen = (bufsiz / slots) - 6;
+    debug(F101,"adjpkl new len","",pktlen);
+    return(pktlen);
+}
diff --git a/usr/src/contrib/kermit-5A.188/ckcker.h b/usr/src/contrib/kermit-5A.188/ckcker.h
new file mode 100644 (file)
index 0000000..464fd8c
--- /dev/null
@@ -0,0 +1,460 @@
+/* ckcker.h -- Symbol and macro definitions for C-Kermit */
+
+/*
+  Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
+  Columbia University Center for Computing Activities.
+  First released January 1985.
+  Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
+  York.  Permission is granted to any individual or institution to use this
+  software as long as it is not sold for profit.  This copyright notice must be
+  retained.  This software may not be included in commercial products without
+  written permission of Columbia University.
+*/
+
+#ifndef CKCKER_H
+#define CKCKER_H
+
+#ifdef NOICP                           /* No Interactive Command Parser */
+#ifndef NOSPL                          /* implies... */
+#define NOSPL                          /* No Script Programming Language */
+#endif /* NOSPL */
+#endif /* NOICP */
+
+/* Codes for what we are doing now */
+
+#define W_NOTHING  0                   /* Nothing */
+#define W_SEND     2                   /* SENDing or MAILing */
+#define W_RECV     4                   /* RECEIVEing or GETting */
+#define W_REMO     8                   /* Doing a REMOTE command */
+#define W_CONNECT 16                   /* CONNECT mode */
+#define W_COMMAND 32                   /* Command mode */
+
+/* Terminal types */
+#define VT100     0                    /* Also for VT52 mode */
+#define TEKTRONIX 1
+
+/* Normal packet and window size */
+
+#define MAXPACK 94                     /* Maximum unextended packet size */
+                                       /* Can't be more than 94! */
+#define MAXWS 31                       /* Maximum window size */
+                                       /* Can't be more than 31! */
+
+/* Maximum long packet size for sending packets */
+/* Override these from cc command line via -DMAXSP=nnn */
+
+#ifdef DYNAMIC
+#ifndef MAXSP
+#define MAXSP 9024
+#endif /* MAXSP */
+#else  /* not DYNAMIC */
+#ifndef MAXSP
+#define MAXSP 2048
+#endif /* MAXSP */
+#endif /* DYNAMIC */
+
+/* Maximum long packet size for receiving packets */
+/* Override these from cc command line via -DMAXRP=nnn */
+
+#ifdef DYNAMIC
+#ifndef MAXRP 
+#define MAXRP 9024
+#endif /* MAXRP */
+#else  /* not DYNAMIC */
+#ifndef MAXRP 
+#define MAXRP 2048
+#endif /* MAXRP */
+#endif /* DYNAMIC */
+
+#ifdef COMMENT                         /* Restriction removed in edit 185 */
+#ifdef VMS                             /* Dynamic or not, */
+#undef MAXSP                           /* VMS seems to have an intrinsic */
+#define MAXSP 1920                     /* limit of about 1920. */
+#undef MAXRP
+#define MAXRP 1920
+#endif /* VMS */
+#endif /* COMMENT */
+
+/* Default sizes for windowed packet buffers */
+/* Override these from cc command line via -DSBSIZ=nnn, -DRBSIZ=nnn */
+
+#ifdef DYNAMIC
+#ifndef SBSIZ 
+#define SBSIZ 9050
+#endif /* SBSIZ */
+#ifndef RBSIZ 
+#define RBSIZ 9050
+#endif /* RBSIZ */
+#else  /* not DYNAMIC */
+#ifndef SBSIZ
+#define SBSIZ (MAXPACK * (MAXWS + 1))
+#endif /* SBSIZ */
+#ifndef RBSIZ
+#define RBSIZ (MAXPACK * (MAXWS + 1))
+#endif /* RBSIZ */
+#endif /* DYNAMIC */
+
+#ifdef COMMENT                         /* Restriction removed in edit 185 */
+#ifdef VMS                             /* VMS again... */
+#undef SBSIZ
+#define SBSIZ 1930
+#undef RBSIZ
+#define RBSIZ 1930
+#endif /* VMS */
+#endif /* COMMENT */
+
+/* Kermit parameters and defaults */
+
+#define CTLQ      '#'                  /* Control char prefix I will use */
+#define MYEBQ     '&'                  /* 8th-Bit prefix char I will use */
+#define MYRPTQ    '~'                  /* Repeat count prefix I will use */
+
+#define MAXTRY     10                  /* Times to retry a packet */
+#define MYPADN     0                   /* How many padding chars I need */
+#define MYPADC     '\0'                /* Which padding character I need */
+
+#define DMYTIM     7                   /* Default timeout interval to use. */
+#define URTIME     10                  /* Timeout interval to use on me. */
+#define DSRVTIM     0                  /* Default server cmd wait timeout. */
+
+#define DEFTRN     0                   /* Default line turnaround handshake */
+#define DEFPAR     0                   /* Default parity */
+#define MYEOL      CR                  /* Incoming packet terminator. */
+
+#define DRPSIZ     90                  /* Default incoming packet size. */
+#define DSPSIZ     90                  /* Default outbound packet size. */
+
+#define DDELAY      5                  /* Default delay. */
+#define DSPEED     9600                /* Default line speed. */
+
+#ifdef OS2                             /* Default CONNECT-mode */
+#define DFESC 29                       /* escape character */
+#else
+#ifdef NEXT                            /* Ctrl-] for PC and NeXT */
+#define DFESC 29
+#else
+#ifdef GEMDOS                          /* And Atari ST */
+#define DFESC 29
+#else
+#define DFESC 28                       /* Ctrl-backslash for others */
+#endif /* GEMDOS */
+#endif /* NEXT */
+#endif /* OS2 */
+
+#ifdef NOPUSH                          /* NOPUSH implies NOJC */
+#ifndef NOJC                           /* (no job control) */
+#define NOJC
+#endif /* NOJC */
+#endif /* NOPUSH */
+
+#ifdef UNIX                            /* Default for SET SUSPEND */
+#ifdef NOJC                            /* UNIX but job control disabled */
+#define DFSUSP      0
+#else                                  /* UNIX, job control enabled. */
+#define DFSUSP      1
+#endif /* NOJC */
+#else
+#define DFSUSP      0
+#endif /* UNIX */
+
+/* Files */
+
+#define ZCTERM      0          /* Console terminal */
+#define ZSTDIO      1          /* Standard input/output */
+#define ZIFILE     2           /* Current input file (SEND, etc) (in) */
+#define ZOFILE      3          /* Current output file (RECEIVE, GET) (out) */
+#define ZDFILE      4          /* Current debugging log file (out) */
+#define ZTFILE      5          /* Current transaction log file (out) */
+#define ZPFILE      6          /* Current packet log file (out) */
+#define ZSFILE      7          /* Current session log file (out) */
+#define ZSYSFN     8           /* Input/Output from a system function */
+#define ZRFILE      9           /* Local file for READ (in) */
+#define ZWFILE     10           /* Local file for WRITE (out) */
+#define ZNFILS     11          /* How many defined file numbers */
+
+/*
+ Buffered file i/o is used to avoid gratuitous function calls while encoding a
+ packet.  The previous way involved 2 nested function calls for EACH character
+ of the file.  This way, we only do 2 calls per K of data.  This reduces
+ packet encoding time to 1% of its former cost.  Originally added by Paul
+ Placeway.
+*/
+#ifdef VMS             /* In VMS, allow for longest possible RMS record */
+#ifdef DYNAMIC
+#define INBUFSIZE 32768        /* File input buffer size */
+#define OBUFSIZE 32768         /* File output buffer size */
+#else
+#define INBUFSIZE 4096 /* File input buffer size */
+#define OBUFSIZE 4096  /* File output buffer size */
+#endif /* DYNAMIC */
+#else  /* Not VMS */   /* For all others, just use a 1K buffer */
+#define INBUFSIZE 1024
+#define OBUFSIZE 1024
+#endif /* VMS */
+
+/* get the next char; sorta like a getc() macro */
+#define zminchar() (((--zincnt)>=0) ? ((int)(*zinptr++) & 0377) : zinfill())
+
+/* stuff a character into the input buffer */
+#define zmstuff(c) zinptr--, *zinptr = c, zincnt++
+
+/* put a character to a file, like putchar() macro */
+#define zmchout(c) \
+((*zoutptr++=(char)(c)),(((++zoutcnt)>=OBUFSIZE)?zoutdump():0))
+
+/* Screen functions */
+
+#define SCR_FN 1       /* filename */
+#define SCR_AN 2       /* as-name */
+#define SCR_FS 3       /* file-size */
+#define SCR_XD 4       /* x-packet data */
+#define SCR_ST 5       /* File status: */
+#define   ST_OK   0    /*  Transferred OK */
+#define   ST_DISC 1    /*  Discarded */
+#define   ST_INT  2     /*  Interrupted */
+#define   ST_SKIP 3    /*  Skipped */
+#define   ST_ERR  4    /*  Fatal Error */
+#define   ST_REFU 5     /*  Refused (use Attribute codes for reason) */
+#define   ST_INC  6    /* Incompletely received */
+#define SCR_PN 6       /* packet number */
+#define SCR_PT 7       /* packet type or pseudotype */
+#define SCR_TC 8       /* transaction complete */
+#define SCR_EM 9       /* error message */
+#define SCR_WM 10      /* warning message */
+#define SCR_TU 11      /* arbitrary undelimited text */
+#define SCR_TN 12      /* arbitrary new text, delimited at beginning */
+#define SCR_TZ 13      /* arbitrary text, delimited at end */
+#define SCR_QE 14      /* quantity equals (e.g. "foo: 7") */
+#define SCR_CW 15      /* close screen window */
+
+/* Macros */
+
+#define tochar(ch)  (((ch) + SP ) & 0xFF )     /* Number to character */
+#define xunchar(ch) (((ch) - SP ) & 0xFF )     /* Character to number */
+#define ctl(ch)     (((ch) ^ 64 ) & 0xFF )     /* Controllify/Uncontrollify */
+#define unpar(ch)   (((ch) & 127) & 0xFF )     /* Clear parity bit */
+
+/* Symbols for File Attributes */
+
+#define AT_XALL  0                     /* All of them */
+#define AT_ALLY  1                     /* All of them on (Yes) */
+#define AT_ALLN  2                     /* All of them off (no) */
+#define AT_LENK  3                     /* Length in K */
+#define AT_FTYP  4                     /* File Type */
+#define AT_DATE  5                     /* Creation date */
+#define AT_CREA  6                     /* Creator */
+#define AT_ACCT  7                     /* Account */
+#define AT_AREA  8                     /* Area */
+#define AT_PSWD  9                     /* Password for area */
+#define AT_BLKS 10                     /* Blocksize */
+#define AT_ACCE 11                     /* Access */
+#define AT_ENCO 12                     /* Encoding */
+#define AT_DISP 13                     /* Disposition */
+#define AT_LPRO 14                     /* Local Protection */
+#define AT_GPRO 15                     /* Generic Protection */
+#define AT_SYSI 16                     /* System ID */
+#define AT_RECF 17                     /* Record Format */
+#define AT_SYSP 18                     /* System-Dependent Parameters */
+#define AT_LENB 19                     /* Length in Bytes */
+
+/* Kermit packet information structure */
+
+struct pktinfo {                       /* Packet information structure */
+    CHAR *bf_adr;                      /*  buffer address */
+    int   bf_len;                      /*  buffer length */
+    CHAR *pk_adr;                      /* Packet address within buffer */
+    int   pk_len;                      /*  length of data within buffer */
+    int   pk_typ;                      /*  packet type */
+    int   pk_seq;                      /*  packet sequence number */
+    int   pk_flg;                      /*  ack'd bit */
+    int   pk_rtr;                      /*  retransmission count */
+};
+
+/* File-related symbols and structures */
+
+#define   XYFILN 0     /*  Naming  */
+#define   XYFILT 1     /*  Type    */
+#define     XYFT_T 0    /*    Text  */
+#define     XYFT_B 1    /*    Binary */
+#define     XYFT_I 2    /*    Image or Block (VMS) */
+#define     XYFT_L 3   /*    Labeled (tagged binary) (VMS) */
+#define     XYFT_U 4    /*    Binary Undefined (VMS) */
+#define   XYFILW 2      /*  Warning */
+#define   XYFILD 3      /*  Display */
+#define     XYFD_N 0    /*    None, Off */
+#define     XYFD_R 1    /*    Regular, Dots */
+#define     XYFD_C 2    /*    Cursor-positioning (e.g. with curses) */
+#define     XYFD_S 3    /*    Simple counter */
+#define   XYFILC 4      /*  Character set */
+#define   XYFILF 5      /*  Record Format */
+#define     XYFF_S  0   /*    Stream */
+#define     XYFF_V  1   /*    Variable */
+#define     XYFF_VB 2   /*    Variable with RCW's */
+#define     XYFF_F  3   /*    Fixed length */
+#define     XYFF_U  4   /*    Undefined */
+#define   XYFILR 6      /*  Record length */
+#define   XYFILO 7      /*  Organization */
+#define     XYFO_S 0    /*    Sequential */
+#define     XYFO_I 1    /*    Indexed */
+#define     XYFO_R 2    /*    Relative */
+#define   XYFILP 8      /*  Printer carriage control */
+#define     XYFP_N 0    /*    Newline (imbedded control characters) */
+#define     XYFP_F 1    /*    FORTRAN (space, 1, +, etc, in column 1 */
+#define     XYFP_P 2    /*    Special printer carriage controls */
+#define     XYFP_X 4    /*    None */
+#define   XYFILX 9      /*  Collision Action */
+#define     XYFX_A 3    /*    Append */
+#define     XYFX_Q 5    /*    Ask */
+#define     XYFX_B 2    /*    Backup */
+#define     XYFX_D 4    /*    Discard */
+#define     XYFX_R 0    /*    Rename */
+#define     XYFX_X 1    /*    Replace */
+#define     XYFX_U 6    /*    Update */
+#define   XYFILB 10     /*  Blocksize */
+#define   XYFILZ 11     /*  Disposition */
+#define     XYFZ_N 0    /*    New, Create */
+#define     XYFZ_A 1    /*    New, append if file exists, else create */
+#define     XYFZ_O 2    /*    Old, file must exist */
+#define     XYFZ_X 3    /*    Output to pipe/process */
+#define     XYFZ_Y 4    /*    Input from pipe/process */
+#define   XYFILS 12     /*  File Byte Size */
+#define   XYFILL 13     /*  File Label (VMS) */
+#define   XYFILI 14     /*  File Incomplete */
+
+/* ANSI-style forward declarations for protocol-related functions. */
+
+_PROTOTYP( int input, (void) );
+_PROTOTYP( int inibufs, (int, int) );
+_PROTOTYP( int makebuf, (int, int, CHAR [], struct pktinfo *) );
+_PROTOTYP( int mksbuf, (int) );
+_PROTOTYP( int mkrbuf, (int) );
+_PROTOTYP( int spack, (char, int, int, CHAR *) );
+_PROTOTYP( VOID proto, (void) );
+_PROTOTYP( int rpack, (void) );
+_PROTOTYP( int ack1, (CHAR *) );
+_PROTOTYP( int ackn, (int) );
+_PROTOTYP( int ackns, (int, CHAR *) );
+_PROTOTYP( int nack, (int) );
+_PROTOTYP( int resend, (int) );
+_PROTOTYP( int errpkt, (CHAR *) );
+_PROTOTYP( VOID logpkt, (char, int, CHAR *) );
+_PROTOTYP( CHAR dopar, (CHAR) );
+_PROTOTYP( int chk1, (CHAR *) );
+_PROTOTYP( unsigned int chk2, (CHAR *) );
+_PROTOTYP( unsigned int chk3, (CHAR *) );
+_PROTOTYP( int sipkt, (char) );
+_PROTOTYP( int sinit, (void) );
+_PROTOTYP( VOID rinit, (CHAR *) );
+_PROTOTYP( int spar, (CHAR *) );
+_PROTOTYP( int rcvfil, (char *) );
+_PROTOTYP( CHAR * rpar, (void) );
+_PROTOTYP( CHAR * rpar, (void) );
+_PROTOTYP( int gnfile, (void) );
+_PROTOTYP( int getsbuf, (int) );
+_PROTOTYP( int getrbuf, (void) );
+_PROTOTYP( int freesbuf, (int) );
+_PROTOTYP( int freerbuf, (int) );
+_PROTOTYP( int dumpsbuf, (void) );
+_PROTOTYP( int dumprbuf, (void) );
+_PROTOTYP( VOID freerpkt, (int) );
+_PROTOTYP( int chkwin, (int, int, int) );
+_PROTOTYP( int rsattr, (CHAR *) );
+_PROTOTYP( char *getreason, (char *) );
+_PROTOTYP( int scmd, (char, CHAR *) );
+_PROTOTYP( int encstr, (CHAR *) );
+_PROTOTYP( int decode, (CHAR *, int (*)(char), int) );
+_PROTOTYP( int fnparse, (char *) );
+_PROTOTYP( int syscmd, (char *, char *) );
+_PROTOTYP( int cwd, (char *) );
+_PROTOTYP( VOID screen, (int, char, long, char *) );
+_PROTOTYP( int remset, (char *) );
+_PROTOTYP( int initattr, (struct zattr *) );
+_PROTOTYP( int gattr, (CHAR *, struct zattr *) );
+_PROTOTYP( int adebu, (char *, struct zattr *) );
+_PROTOTYP( int canned, (CHAR *) );
+_PROTOTYP( int opent, (struct zattr *) );
+_PROTOTYP( int opena, (char *, struct zattr *) );
+_PROTOTYP( int openi, (char *) );
+_PROTOTYP( int openo, (char *, struct zattr *, struct filinfo *) );
+_PROTOTYP( int reof, (char *, struct zattr *) );
+_PROTOTYP( VOID reot, (void) );
+_PROTOTYP( int sfile, (int) );
+_PROTOTYP( int sattr, (int) );
+_PROTOTYP( int sdata, (void) );
+_PROTOTYP( int seof, (CHAR *) );
+_PROTOTYP( int sxeof, (CHAR *) );
+_PROTOTYP( int seot, (void) );
+_PROTOTYP( int window, (int) );
+_PROTOTYP( int errmsg, (char *) );
+_PROTOTYP( int clsif, (void) );
+_PROTOTYP( int clsof, (int) );
+_PROTOTYP( CHAR setgen, (char, char *, char *, char *) );
+_PROTOTYP( int getpkt, (int, int) );
+_PROTOTYP( int putsrv, (char) );
+_PROTOTYP( int puttrm, (char) );
+_PROTOTYP( int putfil, (char) );
+_PROTOTYP( VOID zdstuff, (CHAR) );
+_PROTOTYP( int tinit, (void) );
+_PROTOTYP( VOID pktinit, (void) );
+_PROTOTYP( VOID rinit, (CHAR *) );
+_PROTOTYP( VOID resetc, (void) );
+_PROTOTYP( VOID xsinit, (void) );
+_PROTOTYP( int adjpkl, (int,int,int) );
+_PROTOTYP( int chktimo, (int,int) );
+_PROTOTYP( int nxtpkt, (void) );
+_PROTOTYP( int ack, (void) );
+_PROTOTYP( int ackns, (int, CHAR *) );
+_PROTOTYP( int ackn, (int) );
+_PROTOTYP( int ack1, (CHAR *) );
+_PROTOTYP( int nack, (int) );
+_PROTOTYP( VOID rcalcpsz, (void) );
+_PROTOTYP( int resend, (int) );
+_PROTOTYP( int errpkt, (CHAR *) );
+_PROTOTYP( VOID srinit, (void) );
+_PROTOTYP( VOID tstats, (void) );
+_PROTOTYP( VOID fstats, (void) );
+_PROTOTYP( VOID intmsg, (long) );
+_PROTOTYP( VOID ermsg, (char *) );
+_PROTOTYP( int chkint, (void) );
+_PROTOTYP( VOID sdebu, (int) );
+_PROTOTYP( VOID rdebu, (CHAR *, int) );
+_PROTOTYP( char * dbchr, ( int ) );
+#ifdef COMMENT
+_PROTOTYP( SIGTYP stptrap, (int, int) );
+_PROTOTYP( SIGTYP trap, (int, int) );
+#else
+_PROTOTYP( SIGTYP stptrap, (int) );
+_PROTOTYP( SIGTYP trap, (int) );
+#endif /* COMMENT */
+
+/* User interface functions needed by main program, etc. */
+
+_PROTOTYP( VOID prescan, (void) );
+_PROTOTYP( VOID setint, (void) );
+_PROTOTYP( VOID cmdini, (void) );
+_PROTOTYP( int dotake, (char *) );
+_PROTOTYP( int cmdlin, (void) );
+_PROTOTYP( int conect, (void) );
+_PROTOTYP( int ckcgetc, (int) );
+_PROTOTYP( int ckcputc, (int) );
+_PROTOTYP (int mdmhup, (void) );
+_PROTOTYP( VOID herald, (void) );
+_PROTOTYP( VOID fixcmd, (void) );
+_PROTOTYP( int doarg, (char) );
+_PROTOTYP( VOID usage, (void) );
+_PROTOTYP( VOID doclean, (void) );
+_PROTOTYP( int sndhlp, (void) );
+_PROTOTYP( VOID ckhost, (char *, int) );
+_PROTOTYP( int gettcs, (int, int) );
+
+#ifdef KANJI
+_PROTOTYP( int zkanji, (int (*)(void)) ); /* Kanji function prototypes */
+_PROTOTYP( int zkanjf, (void) );
+_PROTOTYP( int zkanjz, (void) );
+_PROTOTYP( int xkanjz, (int (*)(char) ) );
+_PROTOTYP( int xkanji, (int, int (*)(char) ) );
+#endif /* KANJI */
+
+#endif /* CKCKER_H */
+
+/* End of ckcker.h */