Annotation of coherent/e/bin/ckermit/ckcfns.c, revision 1.1

1.1     ! root        1: char *fnsv = "C-Kermit functions, 5A(079) 23 Nov 92";
        !             2: 
        !             3: /*  C K C F N S  --  System-independent Kermit protocol support functions.  */
        !             4: 
        !             5: /*  ...Part 1 (others moved to ckcfn2,3 to make this module small enough) */
        !             6: 
        !             7: /*
        !             8:   Author: Frank da Cruz ([email protected], [email protected]),
        !             9:   Columbia University Center for Computing Activities.
        !            10:   First released January 1985.
        !            11:   Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
        !            12:   York.  Permission is granted to any individual or institution to use this
        !            13:   software as long as it is not sold for profit.  This copyright notice must be
        !            14:   retained.  This software may not be included in commercial products without
        !            15:   written permission of Columbia University.
        !            16: */
        !            17: /*
        !            18:  System-dependent primitives defined in:
        !            19: 
        !            20:    ck?tio.c -- terminal i/o
        !            21:    cx?fio.c -- file i/o, directory structure
        !            22: */
        !            23: #include "ckcsym.h"                    /* Once needed this for Mac... */
        !            24: #include "ckcasc.h"                    /* ASCII symbols */
        !            25: #include "ckcdeb.h"                    /* Debug formats, typedefs, etc. */
        !            26: #include "ckcker.h"                    /* Symbol definitions for Kermit */
        !            27: #include "ckcxla.h"                    /* Character set symbols */
        !            28: 
        !            29: /* Externals from ckcmai.c */
        !            30: extern int spsiz, spmax, rpsiz, timint, srvtim, rtimo, npad, ebq, ebqflg,
        !            31:  rpt, rptq, rptflg, capas, keep, fncact, pkttim, autopar, spsizr;
        !            32: extern int pktnum, bctr, bctu, bctl, fmask, clfils, sbufnum,
        !            33:  size, osize, spktl, nfils, warn, timef, spsizf, sndtyp, success;
        !            34: extern int parity, turn, network, what, fsecs,
        !            35:  delay, displa, xflg, mypadn;
        !            36: extern long filcnt, ffc, flci, flco, tlci, tlco, tfc, fsize, speed;
        !            37: extern int fblksiz, frecl, frecfm, forg, fcctrl;
        !            38: extern int spackets, rpackets, timeouts, retrans, crunched, wmax;
        !            39: extern int hcflg, binary, savmod, fncnv, local, server, cxseen, czseen;
        !            40: extern int nakstate, discard;
        !            41: extern int rq, rqf, sq, wslots, wslotn, wslotr, winlo, urpsiz, rln;
        !            42: extern int atcapr, atcapb, atcapu;
        !            43: extern int lpcapr, lpcapb, lpcapu;
        !            44: extern int swcapr, swcapb, swcapu;
        !            45: extern int lscapr, lscapb, lscapu;
        !            46: extern int bsave, bsavef;
        !            47: extern int sseqtbl[];
        !            48: extern int numerrs;
        !            49: extern long rptn;
        !            50: extern int maxtry;
        !            51: 
        !            52: #ifndef NOCSETS
        !            53: extern int tcharset, fcharset;
        !            54: extern int ntcsets;
        !            55: extern struct csinfo tcsinfo[], fcsinfo[];
        !            56: #endif /* NOCSETS */
        !            57: 
        !            58: extern int
        !            59:   atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko,
        !            60:   attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso; 
        !            61: 
        !            62: extern int bigsbsiz, bigrbsiz;
        !            63: 
        !            64: #ifdef DYNAMIC
        !            65:   extern CHAR *srvcmd;
        !            66: #else
        !            67:   extern CHAR srvcmd[];
        !            68: #endif /* DYNAMIC */
        !            69: extern CHAR padch, mypadc, eol, seol, ctlq, myctlq, sstate;
        !            70: extern CHAR *recpkt, *data, padbuf[], stchr, mystch;
        !            71: extern CHAR *srvptr;
        !            72: extern CHAR *rdatap;
        !            73: extern char *cmarg, *cmarg2, *hlptxt, **cmlist, filnam[], fspec[];
        !            74: 
        !            75: _PROTOTYP( CHAR *rpar, (void) );
        !            76: _PROTOTYP( int lslook, (unsigned int b) );     /* Locking Shift Lookahead */
        !            77: _PROTOTYP( int szeof, (CHAR *s) );
        !            78: 
        !            79: /* International character sets */
        !            80: 
        !            81: #ifndef NOCSETS
        !            82: /* Pointers to translation functions */
        !            83: #ifdef CK_ANSIC
        !            84: extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set */
        !            85: extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* translation functions */
        !            86: #else
        !            87: extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])();        /* Character set */
        !            88: extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])();        /* translation functions. */
        !            89: #endif /* CK_ANSIC */
        !            90: _PROTOTYP( CHAR (*rx), (CHAR) );       /* Input translation function */
        !            91: _PROTOTYP( CHAR (*sx), (CHAR) );       /* Output translation function */
        !            92: _PROTOTYP( CHAR ident, (CHAR) );       /* Identity translation function */
        !            93: #endif /* NOCSETS */
        !            94: 
        !            95: /* Windowing things */
        !            96: 
        !            97: extern int rseqtbl[];                  /* Rec'd-packet sequence # table */
        !            98: 
        !            99: /* (PWP) external def. of things used in buffered file input and output */
        !           100: 
        !           101: #ifdef DYNAMIC
        !           102: extern char *zinbuffer, *zoutbuffer;
        !           103: #else
        !           104: extern char zinbuffer[], zoutbuffer[];
        !           105: #endif
        !           106: extern char *zinptr, *zoutptr;
        !           107: extern int zincnt, zoutcnt;
        !           108: 
        !           109: /* Variables defined in this module, but shared by ckcfn3, to which */
        !           110: /* several functions have been moved... */
        !           111: 
        !           112: int sndsrc;            /* Flag for where to get names of files to send: */
        !           113:                                        /* -1: znext() function */
        !           114:                                        /*  0: stdin */
        !           115:                                        /* >0: list in cmlist */
        !           116: 
        !           117: int  memstr;                           /* Flag for input from memory string */
        !           118: 
        !           119: #ifdef pdp11
        !           120: CHAR myinit[25];                       /* Copy of my Send-Init data */
        !           121: #else
        !           122: CHAR myinit[100];                      /* Copy of my Send-Init data */
        !           123: #endif /* pdp11 */
        !           124: 
        !           125: /* Variables local to this module */
        !           126: 
        !           127: static char *memptr;                   /* Pointer for memory strings */
        !           128: 
        !           129: #ifdef pdp11
        !           130: static char cmdstr[50];                        /* System command string. */
        !           131: #else
        !           132: static char cmdstr[100];
        !           133: #endif /* pdp11 */
        !           134: 
        !           135: static int drain;                      /* For draining stacked-up ACKs. */
        !           136: 
        !           137: static int first;                      /* Flag for first char from input */
        !           138: static CHAR t,                         /* Current character */
        !           139:     next;                              /* Next character */
        !           140: 
        !           141: static int lsstate = 0;                        /* Locking shift state */
        !           142: static int lsquote = 0;                        /* Locking shift quote */
        !           143: 
        !           144: #ifdef datageneral
        !           145: extern int quiet;
        !           146: #endif
        !           147: 
        !           148: /*  E N C S T R  --  Encode a string from memory. */
        !           149: 
        !           150: /*
        !           151:   Call this instead of getpkt() if source is a string, rather than a file.
        !           152:   Note: Character set translation is never done in this case.
        !           153: */
        !           154: 
        !           155: #ifdef pdp11
        !           156: #define ENCBUFL 100
        !           157: #else
        !           158: #define ENCBUFL 200
        !           159: #endif /* pdp11 */
        !           160: CHAR encbuf[ENCBUFL];
        !           161: 
        !           162: int
        !           163: encstr(s) CHAR* s; {
        !           164:     int m; char *p;
        !           165:     CHAR *dsave;
        !           166: 
        !           167:     if ((m = (int)strlen((char *)s)) > ENCBUFL) {
        !           168:        debug(F111,"encstr string too long for buffer",s,ENCBUFL);
        !           169:        s[ENCBUFL] = '\0';
        !           170:     }
        !           171:     if (m > spsiz-bctl-3) {
        !           172:        debug(F111,"encstr string too long for packet",s,spsiz-bctl-3);
        !           173:        s[spsiz-bctl-3] = '\0';
        !           174:     }
        !           175:     m = memstr; p = memptr;            /* Save these. */
        !           176: 
        !           177:     memptr = (char *)s;                        /* Point to the string. */
        !           178:     memstr = 1;                                /* Flag memory string as source. */
        !           179:     first = 1;                         /* Initialize character lookahead. */
        !           180:     dsave = data;                      /* Boy is this ugly... */
        !           181:     data = encbuf + 7;                 /* Why + 7?  See spack()... */
        !           182: #ifdef COMMENT
        !           183:     getpkt(spsiz-bctl-3,0);            /* Fill a packet from the string. */
        !           184: #else
        !           185:     getpkt(spsiz,0);
        !           186: #endif /* COMMENT */
        !           187:     data = dsave;                      /* (sorry...) */
        !           188:     memstr = m;                                /* Restore memory string flag */
        !           189:     memptr = p;                                /* and pointer */
        !           190:     first = 1;                         /* Put this back as we found it. */
        !           191:     return(0);
        !           192: }
        !           193: 
        !           194: #ifdef COMMENT
        !           195: /*
        !           196:   We don't use this routine any more -- the code has been incorporated
        !           197:   directly into getpkt() to reduce per-character function call overhead.
        !           198:   Also, watch out: it hasn't been updated since it was commented out a
        !           199:   long time ago.
        !           200: */
        !           201: /* E N C O D E - Kermit packet encoding procedure */
        !           202: 
        !           203: VOID
        !           204: encode(a) CHAR a; {                    /* The current character */
        !           205:     int a7;                            /* Low order 7 bits of character */
        !           206:     int b8;                            /* 8th bit of character */
        !           207:  
        !           208: #ifndef NOCSETS
        !           209:     if (!binary && sx) a = (*sx)(a);   /* Translate. */
        !           210: #endif /* NOCSETS */
        !           211: 
        !           212:     if (rptflg)        {                       /* Repeat processing? */
        !           213:         if (a == next && (first == 0)) { /* Got a run... */
        !           214:            if (++rpt < 94)             /* Below max, just count */
        !           215:                 return;
        !           216:            else if (rpt == 94) {       /* Reached max, must dump */
        !           217:                 data[size++] = rptq;
        !           218:                 data[size++] = tochar(rpt);
        !           219:                rptn += rpt;            /* Count, for stats */
        !           220:                 rpt = 0;
        !           221:            }
        !           222:         } else if (rpt == 1) {         /* Run broken, only 2? */
        !           223:             rpt = 0;                   /* Yes, reset repeat flag & count. */
        !           224:            encode(a);                  /* Do the character twice. */
        !           225:            if (size <= maxsize) osize = size;
        !           226:            rpt = 0;
        !           227:            encode(a);
        !           228:            return;
        !           229:        } else if (rpt > 1) {           /* More than two */
        !           230:             data[size++] = rptq;       /* Insert the repeat prefix */
        !           231:             data[size++] = tochar(++rpt); /* and count. */
        !           232:            rptn += rpt;
        !           233:             rpt = 0;                   /* Reset repeat counter. */
        !           234:         }
        !           235:     }
        !           236:     a7 = a & 0177;                     /* Isolate ASCII part */
        !           237:     b8 = a & 0200;                     /* and 8th (parity) bit. */
        !           238: 
        !           239:     if (ebqflg && b8) {                        /* Do 8th bit prefix if necessary. */
        !           240:         data[size++] = ebq;
        !           241:         a = a7;
        !           242:     }
        !           243:     if ((a7 < SP) || (a7==DEL))        {       /* Do control prefix if necessary */
        !           244:         data[size++] = myctlq;
        !           245:        a = ctl(a);
        !           246:     }
        !           247:     if (a7 == myctlq)                  /* Prefix the control prefix */
        !           248:         data[size++] = myctlq;
        !           249: 
        !           250:     if ((rptflg) && (a7 == rptq))      /* If it's the repeat prefix, */
        !           251:         data[size++] = myctlq;         /* quote it if doing repeat counts. */
        !           252: 
        !           253:     if ((ebqflg) && (a7 == ebq))       /* Prefix the 8th bit prefix */
        !           254:         data[size++] = myctlq;         /* if doing 8th-bit prefixes */
        !           255: 
        !           256:     data[size++] = a;                  /* Finally, insert the character */
        !           257:     data[size] = '\0';                 /* itself, and mark the end. */
        !           258: }
        !           259: #endif /* COMMENT */
        !           260: 
        !           261: /*  Output functions passed to 'decode':  */
        !           262: 
        !           263: int                           /*  Put character in server command buffer  */
        !           264: #ifdef CK_ANSIC
        !           265: putsrv(char c)
        !           266: #else
        !           267: putsrv(c) register char c;
        !           268: #endif /* CK_ANSIC */
        !           269: /* putsrv */ {
        !           270:     *srvptr++ = c;
        !           271:     *srvptr = '\0';            /* Make sure buffer is null-terminated */
        !           272:     return(0);
        !           273: }
        !           274: 
        !           275: int                                    /*  Output character to console.  */
        !           276: #ifdef CK_ANSIC
        !           277: puttrm(char c)
        !           278: #else
        !           279: puttrm(c) register char c;
        !           280: #endif /* CK_ANSIC */
        !           281: /* puttrm */ {
        !           282:     conoc(c);
        !           283:     return(0);
        !           284: }
        !           285: 
        !           286: int                                    /*  Output char to file. */
        !           287: #ifdef CK_ANSIC
        !           288: putfil(char c)
        !           289: #else
        !           290: putfil(c) register char c;
        !           291: #endif /* CK_ANSIC */
        !           292: /* putfil */ {
        !           293:     if (zchout(ZOFILE, (char) (c & fmask)) < 0) {
        !           294:        czseen = 1;                     /* If write error... */
        !           295:        debug(F101,"putfil zchout write error, setting czseen","",1);
        !           296:        return(-1);
        !           297:     }
        !           298:     return(0);
        !           299: }
        !           300: 
        !           301: /* D E C O D E  --  Kermit packet decoding procedure */
        !           302: 
        !           303: /*
        !           304:  Call with string to be decoded and an output function.
        !           305:  Returns 0 on success, -1 on failure (e.g. disk full).
        !           306: 
        !           307:  This is the "inner loop" when receiving files, and must be coded as 
        !           308:  efficiently as possible.  Note some potential problems:  if a packet
        !           309:  is badly formed, having a prefixed sequence ending prematurely, this
        !           310:  function, as coded, could read past the end of the packet.  This has
        !           311:  never happened, thus the additional (time-consuming) tests have not
        !           312:  been added.
        !           313: */
        !           314: 
        !           315: static CHAR *xdbuf;    /* Global version of decode()'s buffer pointer */
        !           316:                         /* for use by translation functions. */
        !           317: 
        !           318: /* Function for pushing a character onto decode()'s input stream. */
        !           319: 
        !           320: VOID
        !           321: #ifdef CK_ANSIC
        !           322: zdstuff(CHAR c)
        !           323: #else
        !           324: zdstuff(c) CHAR c;
        !           325: #endif /* CK_ANSIC */
        !           326: /* zdstuff */ {        
        !           327:     xdbuf--;                           /* Back up the pointer. */
        !           328:     *xdbuf = c;                                /* Stuff the character. */
        !           329: }
        !           330: 
        !           331: int
        !           332: #ifdef CK_ANSIC
        !           333: decode(CHAR *buf, int (*fn)(char), int xlate)
        !           334: #else
        !           335: decode(buf,fn,xlate) register CHAR *buf; register int (*fn)(); int xlate;
        !           336: #endif /* CK_ANSIC */
        !           337: /* decode */ {
        !           338:     register unsigned int a, a7, a8, b8; /* Various copies of current char */
        !           339:     int t;                             /* Int version of character */
        !           340:     int ssflg;                         /* Character was single-shifted */
        !           341: 
        !           342: /*
        !           343:   Catch the case in which we are asked to decode into a file that is not open,
        !           344:   for example, if the user interrupted the transfer, but the other Kermit
        !           345:   keeps sending.
        !           346: */
        !           347:     if ((cxseen || czseen || discard) && (fn == putfil))
        !           348:       return(0);
        !           349: 
        !           350:     xdbuf = buf;                       /* Make global copy of pointer. */
        !           351:     rpt = 0;                           /* Initialize repeat count. */
        !           352: 
        !           353:     while ((a = *xdbuf++ & 0xFF) != '\0') { /* Get next character. */
        !           354:        if (a == rptq && rptflg) {      /* Got a repeat prefix? */
        !           355:            rpt = xunchar(*xdbuf++ & 0xFF); /* Yes, get the repeat count, */
        !           356:            rptn += rpt;
        !           357:            a = *xdbuf++ & 0xFF;        /* and get the prefixed character. */
        !           358:        }
        !           359:        b8 = lsstate ? 0200 : 0;        /* 8th-bit value from SHIFT-STATE */
        !           360:        if (ebqflg && a == ebq) {       /* Have 8th-bit prefix? */
        !           361:            b8 ^= 0200;                 /* Yes, invert the 8th bit's value, */
        !           362:            ssflg = 1;                  /* remember we did this, */
        !           363:            a = *xdbuf++ & 0xFF;        /* and get the prefixed character. */
        !           364:        } else ssflg = 0;
        !           365: 
        !           366:        if (a == ctlq) {                /* If control prefix, */
        !           367:            a  = *xdbuf++ & 0xFF;       /* get its operand */
        !           368:            a7 = a & 0x7F;              /* and its low 7 bits. */
        !           369:            if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') /* Controllify */
        !           370:              a = ctl(a);               /* if in control range. */
        !           371:            if (lscapu) {               /* If doing locking shifts... */
        !           372:                if (lsstate)            /* If SHIFTED */
        !           373:                  a8 = (a & ~b8) & 0xFF; /* Invert meaning of 8th bit */
        !           374:                else                    /* otherwise */
        !           375:                  a8 = a | b8;          /* OR in 8th bit */
        !           376:                /* If we're not in a quoted sequence */
        !           377:                if (!lsquote && (!lsstate || !ssflg)) {
        !           378:                    if (a8 == DLE) {    /* Check for DLE quote */
        !           379:                        lsquote = 1;    /* prefixed by single shift! */
        !           380:                        continue;
        !           381:                    } else if (a8 == SO) { /* Check for Shift-Out */
        !           382:                        lsstate = 1;    /* SHIFT-STATE = SHIFTED */
        !           383:                        continue;
        !           384:                    } else if (a8 == SI) { /* or Shift-In */
        !           385:                        lsstate = 0;    /* SHIFT-STATE = UNSHIFTED */
        !           386:                        continue;
        !           387:                    }
        !           388:                } else lsquote = 0;
        !           389:            }
        !           390:        }
        !           391:        a |= b8;                        /* OR in the 8th bit */
        !           392:        if (rpt == 0) rpt = 1;          /* If no repeats, then one */
        !           393:        if (!binary) {                  /* If in text mode, */
        !           394: #ifdef NLCHAR
        !           395:            if (a == CR) continue;      /* Discard carriage returns, */
        !           396:            if (a == LF) a = NLCHAR;    /* convert LF to system's newline. */
        !           397: #endif /* NLCHAR */
        !           398: 
        !           399: #ifndef NOCSETS                                /* Character-set translation */
        !           400: #ifdef KANJI                           /* For Kanji transfers, */
        !           401:            if (tcharset != TC_JEUC)    /* postpone translation. */
        !           402: #endif /* KANJI */
        !           403:              if (xlate && rx) a = (*rx)((CHAR) a); /* Translate charset */
        !           404: #endif /* NOCSETS */
        !           405:        }
        !           406:        if (fn == putfil) { /* (PWP) speedup via buffered output and a macro */
        !           407:            for (; rpt > 0; rpt--) {    /* Output the char RPT times */
        !           408: #ifndef NOCSETS
        !           409: #ifdef KANJI
        !           410:                if (!binary && tcharset == TC_JEUC &&
        !           411:                    fcharset != FC_JEUC) { /* Translating from J-EUC */
        !           412:                    if (ffc == 0L) xkanjf();
        !           413:                    if (xkanji(a,fn) < 0)  /* to something else? */
        !           414:                      return(-1);
        !           415:                } else
        !           416: #endif /* KANJI */
        !           417: #endif /* NOCSETS */
        !           418:                if ((t = zmchout(a & fmask)) < 0) { /* zmchout is a macro */
        !           419: #ifdef COMMENT
        !           420: /* Too costly, uncomment these if you really need them. */
        !           421:                    debug(F101,"decode zmchout","",t);
        !           422:                    debug(F101,"decode zoutcnt","",zoutcnt);
        !           423:                    debug(F101,"decode a","",a);
        !           424: #endif /* COMMENT */
        !           425:                    return(-1);
        !           426:                }
        !           427:                ffc++;                  /* Count the character */
        !           428:            }
        !           429:        } else {                        /* Output to something else. */
        !           430:            a &= fmask;                 /* Apply file mask */
        !           431:            for (; rpt > 0; rpt--) {    /* Output the char RPT times */
        !           432:                if ((*fn)((char) a) < 0) return(-1); /* Send to output func. */
        !           433:                ffc++;
        !           434:            }
        !           435:        }
        !           436:     }
        !           437:     return(0);
        !           438: }
        !           439: 
        !           440: /*  G E T P K T -- Fill a packet data field  */
        !           441: 
        !           442: /*
        !           443:  Gets characters from the current source -- file or memory string.
        !           444:  Encodes the data into the packet, filling the packet optimally.
        !           445:  Set first = 1 when calling for the first time on a given input stream
        !           446:  (string or file).
        !           447: 
        !           448:  Call with:
        !           449:  bufmax -- current send-packet size
        !           450:  xlate  -- flag: 0 to skip character-set translation, 1 to translate
        !           451: 
        !           452:  Uses global variables:
        !           453:  t     -- current character.
        !           454:  first -- flag: 1 to start up, 0 for input in progress, -1 for EOF.
        !           455:  next  -- next character.
        !           456:  data  -- pointer to the packet data buffer.
        !           457:  size  -- number of characters in the data buffer.
        !           458:  memstr - flag that input is coming from a memory string instead of a file.
        !           459:  memptr - pointer to string in memory.
        !           460:  (*sx)()  character set translation function
        !           461: 
        !           462: Returns the size as value of the function, and also sets global "size",
        !           463: and fills (and null-terminates) the global data array.  Returns 0 upon eof.
        !           464: 
        !           465: Rewritten by Paul W. Placeway (PWP) of Ohio State University, March 1989.
        !           466: Incorporates old getchx() and encode() inline to reduce function calls,
        !           467: uses buffered input for much-improved efficiency, and clears up some
        !           468: confusion with line termination (CRLF vs LF vs CR).
        !           469: 
        !           470: Rewritten again by Frank da Cruz to incorporate locking shift mechanism,
        !           471: May 1991.
        !           472: */
        !           473: 
        !           474: /*
        !           475:   Lookahead function to decide whether locking shift is worth it.  Looks at
        !           476:   the next four input characters to see if all of their 8th bits match the
        !           477:   argument.  Call with 0 or 0200.  Returns 1 if so, 0 if not.  If we don't
        !           478:   happen to have at least 4 more characters waiting in the input buffer,
        !           479:   returns 1.  Note that zinptr points two characters ahead of the current
        !           480:   character because of repeat-count lookahead.
        !           481: */
        !           482: 
        !           483: #ifdef KANJI
        !           484: int
        !           485: kgetf() {
        !           486:     return(zminchar());
        !           487: }
        !           488: 
        !           489: int
        !           490: kgetm() {
        !           491:     int x;
        !           492:     if (x = *memptr++) return(x);
        !           493:     else return(-1);
        !           494: }
        !           495: #endif /* KANJI */
        !           496: 
        !           497: int
        !           498: lslook(b) unsigned int b; {            /* Locking Shift Lookahead */
        !           499:     int i;
        !           500:     if (zincnt < 3)                    /* If not enough chars in buffer, */
        !           501:       return(1);                       /* force shift-state switch. */
        !           502:     b &= 0200;                         /* Force argument to proper form. */
        !           503:     for (i = -1; i < 3; i++)           /* Look at next 5 characters to */
        !           504:       if (((*(zinptr+i)) & 0200) != b) /* see if all their 8th bits match.  */
        !           505:        return(0);                      /* They don't. */
        !           506:     return(1);                         /* They do. */
        !           507: }
        !           508: 
        !           509: int
        !           510: getpkt(bufmax,xlate) int bufmax, xlate; { /* Fill one packet buffer */
        !           511:     register CHAR rt = t, rnext = next; /* register shadows of the globals */
        !           512:     register CHAR *dp, *odp, *odp2, *p1, *p2; /* pointers... */
        !           513:     register int x;                    /* Loop index. */
        !           514:     register int a7;                   /* Low 7 bits of character */
        !           515:     static CHAR leftover[9] = { '\0','\0','\0','\0','\0','\0','\0','\0','\0' };
        !           516:     CHAR xxls, xxdl, xxrc, xxss, xxcq; /* Pieces of prefixed sequence */
        !           517:     int n;                             /* worker */
        !           518: 
        !           519: /*
        !           520:   Assume bufmax is the receiver's total receive-packet buffer length.
        !           521:   Our whole packet has to fit into it, so we adjust the data field length.
        !           522:   We also decide optimally whether it is better to use a short-format or
        !           523:   long-format packet when we're near the borderline.
        !           524: */
        !           525:     n = bufmax - 5;                    /* Space for Data and Checksum */
        !           526:     if (n > 92 && n < 96) n = 92;      /* "Short" Long packets don't pay */
        !           527:     if (n > 92 && lpcapu == 0)         /* If long packets needed, */
        !           528:       n = 92;                          /* make sure they've been negotiated */
        !           529:     bufmax = n - bctl;                 /* Space for data */
        !           530:     if (n > 92) bufmax -= 3;           /* Long packet needs header chksum */
        !           531: 
        !           532:     if (first == 1) {          /* If first character of this file... */
        !           533:        ffc = 0L;               /* Reset file character counter */
        !           534:        first = 0;              /* Next character won't be first */
        !           535:        *leftover = '\0';       /* Discard any interrupted leftovers, */
        !           536: 
        !           537:        /* get first character of file into rt, watching out for null file */
        !           538: 
        !           539: #ifndef NOCSETS
        !           540: #ifdef KANJI
        !           541:        if (!binary && tcharset == TC_JEUC && xlate) {
        !           542:            x = zkanjf();
        !           543:            if ((x = zkanji( memstr ? kgetm : kgetf )) < 0) {
        !           544:                first = -1;
        !           545:                size = 0;
        !           546:                if (x == -2) {
        !           547:                    debug(F100,"getpkt(zkanji): input error","",0);
        !           548:                    cxseen = 1;
        !           549:                } else debug(F100,"getpkt(zkanji): empty string/file","",0);
        !           550:                return (0);
        !           551:            }
        !           552:            ffc++;
        !           553:            rt = x;
        !           554:        } else {
        !           555: #endif /* KANJI */
        !           556: #endif /* not NOCSETS */
        !           557:        if (memstr) {                   /* Reading data from memory string */
        !           558:            if ((rt = *memptr++) == '\0') { /* end of string ==> EOF */
        !           559:                first = -1;
        !           560:                size = 0;
        !           561:                debug(F100,"getpkt: empty string","",0);
        !           562:                return (0);
        !           563:            }
        !           564: 
        !           565:        } else {                        /* Reading data from a file */
        !           566: 
        !           567:            if ((x = zminchar()) < 0) { /* End of file or input error */
        !           568:                first = -1;
        !           569:                size = 0;
        !           570:                if (x == -2) {          /* Error */
        !           571:                    debug(F100,"getpkt: input error","",0);
        !           572:                    cxseen = 1;         /* Interrupt the file transfer */
        !           573:                } else debug(F100,"getpkt: empty file","",0); /* Empty file */
        !           574:                return(0);
        !           575:            }
        !           576:            ffc++;                      /* Count a file character */
        !           577:            rt = x;                     /* Convert int to char */
        !           578:            debug(F101,"getpkt zminchar","",rt);
        !           579:        }
        !           580: #ifndef NOCSETS
        !           581: #ifdef KANJI
        !           582:        }
        !           583: #endif /* KANJI */
        !           584: #endif /* not NOCSETS */
        !           585: 
        !           586:        rt &= fmask;                    /* Apply SET FILE BYTESIZE mask */
        !           587:        debug(F101,"getpkt fmask","",fmask);
        !           588:        debug(F101,"getpkt new rt","",rt);
        !           589: 
        !           590: #ifndef NOCSETS
        !           591:        if (xlate) {
        !           592:            debug(F101,"getpkt about to call translate function","",rt);
        !           593:            debug(F101,"tcharset","",tcharset);
        !           594:            debug(F101,"fcharset","",fcharset);
        !           595:        }
        !           596: #ifdef KANJI
        !           597:        if (tcharset != TC_JEUC)
        !           598: #endif /* KANJI */
        !           599:          if (!binary && sx && xlate) {
        !           600:              rt = (*sx)(rt); /* Translate */
        !           601:              debug(F101," translate function returns","",rt);
        !           602:          }
        !           603: #endif /* not NOCSETS */
        !           604: 
        !           605:        /* PWP: handling of NLCHAR is done later (in the while loop)... */
        !           606: 
        !           607:     } else if ((first == -1) && (*leftover == '\0')) /* EOF from last time? */
        !           608:         return(size = 0);
        !           609: /*
        !           610:   Here we handle characters that were encoded for the last packet but
        !           611:   did not fit, and so were saved in the "leftover" array.
        !           612: */
        !           613:     dp = data;                         /* Point to packet data buffer */
        !           614:     for (p1 = leftover; (*dp = *p1) != '\0'; p1++, dp++) /* Copy leftovers */
        !           615:        ;
        !           616:     *leftover = '\0';                  /* Delete leftovers */
        !           617:     if (first == -1)                   /* Handle EOF */
        !           618:       return(size = (dp - data));
        !           619:   
        !           620: /* Now fill up the rest of the packet. */
        !           621: 
        !           622:     rpt = 0;                           /* Initialize character repeat count */
        !           623: 
        !           624:     while (first > -1) {               /* Until EOF... */
        !           625: #ifndef NOCSETS
        !           626: #ifdef KANJI
        !           627:        if (!binary && xlate && tcharset == TC_JEUC) {
        !           628:            if ((x = zkanji( memstr ? kgetm : kgetf )) < 0) {
        !           629:                first = -1;
        !           630:                if (x == -2) cxseen = 1;
        !           631:            }
        !           632:            ffc++;
        !           633:            rnext = x & fmask;
        !           634:        } else {
        !           635: #endif /* KANJI */
        !           636: #endif /* not NOCSETS */
        !           637:        if (memstr) {                   /* Get next char from memory string */
        !           638:            if ((x = *memptr++) == '\0') /* End of string means EOF */
        !           639:              first = -1;               /* Flag EOF for next time. */
        !           640:            rnext = x & fmask;          /* Apply file mask */
        !           641:        } else {
        !           642:            if ((x = zminchar()) < 0) { /* Real file, check for EOF */
        !           643:                first = -1;             /* Flag eof for next time. */
        !           644:                if (x == -2) cxseen = 1; /* If error, cancel this file. */
        !           645:            }
        !           646:            rnext = x & fmask;          /* Apply file mask */
        !           647:        } 
        !           648:        ffc++;                          /* Count the character */
        !           649: #ifndef NOCSETS
        !           650: #ifdef KANJI
        !           651:        }
        !           652: #endif /* KANJI */
        !           653: #endif /* not NOCSETS */
        !           654: 
        !           655:        /*** debug(F101,"getpkt rnext","",rnext); ***/
        !           656: 
        !           657: #ifndef NOCSETS
        !           658: #ifdef KANJI
        !           659:        if (tcharset != TC_JEUC)
        !           660: #endif /* KANJI */
        !           661:            if (!binary && sx && xlate) {
        !           662:                rnext = (*sx)(rnext); /* Translate */
        !           663:                debug(F101,"getpkt xlated rnext to","",rnext);
        !           664:            }
        !           665: #endif /* not NOCSETS */
        !           666: 
        !           667:        odp = dp;                       /* Remember where we started. */
        !           668:        xxls = xxdl = xxrc = xxss = xxcq = NUL; /* Clear these. */
        !           669: 
        !           670: /*
        !           671:   Now encode the character according to the options that are in effect:
        !           672:     binary: text or binary mode.
        !           673:     rptflg: repeat counts enabled.
        !           674:     ebqflg: 8th-bit prefixing enabled.
        !           675:     lscapu: locking shifts enabled.
        !           676: */
        !           677:        if (rptflg) {                   /* Repeat processing is on? */
        !           678:            if (
        !           679: #ifdef NLCHAR
        !           680:                /*
        !           681:                 * If the next char is really CRLF, then we cannot
        !           682:                 * be doing a repeat (unless CR,CR,LF which becomes
        !           683:                 * "~ <n-1> CR CR LF", which is OK but not most efficient).
        !           684:                 * I just plain don't worry about this case.  The actual
        !           685:                 * conversion from NL to CRLF is done after the rptflg if...
        !           686:                 */
        !           687:            (binary || (rnext != NLCHAR)) &&
        !           688: #endif /* NLCHAR */
        !           689:            (rt == rnext) && (first == 0)) { /* Got a run... */
        !           690:                if (++rpt < 94) {       /* Below max, just count */
        !           691:                    continue;           /* go back and get another */
        !           692:                }
        !           693:                else if (rpt == 94) {   /* Reached max, must dump */
        !           694:                    xxrc = tochar(rpt); /* Put the repeat count here */
        !           695:                    rptn += rpt;        /* Accumulate it for statistics */
        !           696:                    rpt = 0;            /* And reset it */
        !           697:                }
        !           698:            } else if (rpt > 1) {       /* More than two */
        !           699:                xxrc = tochar(++rpt);   /* and count. */
        !           700:                rptn += rpt;
        !           701:                rpt = 0;                /* Reset repeat counter. */
        !           702:            }
        !           703:            /*
        !           704:              If (rpt == 1) we must encode exactly two characters.
        !           705:              This is done later, after the first character is encoded.
        !           706:            */
        !           707:        }
        !           708: 
        !           709: #ifdef NLCHAR
        !           710:        if (!binary && (rt == NLCHAR)) { /* It's the newline character */
        !           711:            if (lscapu && lsstate) {    /* If SHIFT-STATE is SHIFTED */
        !           712:                if (ebqflg) {           /* If single shifts enabled, */
        !           713:                    *dp++ = ebq;        /* insert a single shift. */
        !           714:                } else {                /* Otherwise must shift in. */
        !           715:                    *dp++ = myctlq;     /* Insert shift-out code */
        !           716:                    *dp++ = 'O';
        !           717:                    lsstate = 0;        /* Change shift state */
        !           718:                }
        !           719:            }
        !           720:            *dp++ = myctlq;             /* Insert carriage return directly */
        !           721:            *dp++ = 'M';
        !           722:            rt = LF;                    /* Now make next char be linefeed. */
        !           723:        }
        !           724: #endif /* NLCHAR */
        !           725: 
        !           726: /*
        !           727:   Now handle the 8th bit of the file character.  If we have an 8-bit
        !           728:   connection, we preserve the 8th bit.  If we have a 7-bit connection,
        !           729:   we employ either single or locking shifts (if they are enabled).
        !           730: */
        !           731:        a7 = rt & 0177;                 /* Get low 7 bits of character */
        !           732:        if (rt & 0200) {                /* 8-bit character? */
        !           733:            if (lscapu) {               /* Locking shifts enabled? */
        !           734:                if (!lsstate) {         /* Not currently shifted? */
        !           735:                    x = lslook(0200);   /* Look ahead */
        !           736:                    if (x != 0 || ebqflg == 0) { /* Locking shift decision */
        !           737:                        xxls = 'N';        /* Need locking shift-out */
        !           738:                        lsstate = 1;       /* and change to shifted state */
        !           739:                    } else if (ebqflg) {   /* Not worth it */
        !           740:                        xxss = ebq;        /* Use single shift */
        !           741:                    }
        !           742:                }
        !           743:                rt = a7;                /* Replace character by 7-bit value */
        !           744:            } else if (ebqflg) {        /* 8th bit prefixing is on? */
        !           745:                xxss = ebq;             /* Insert single shift */
        !           746:                rt = a7;                /* Replace character by 7-bit value */
        !           747:            }
        !           748: 
        !           749:        } else if (lscapu) {            /* 7-bit character */
        !           750: 
        !           751:            if (lsstate) {              /* Comes while shifted out? */
        !           752:                x = lslook(0);          /* Yes, look ahead */
        !           753:                if (x || ebqflg == 0) { /* Time to shift in. */
        !           754:                    xxls = 'O';         /* Set shift-in code */
        !           755:                    lsstate = 0;        /* Exit shifted state */
        !           756:                } else if (ebqflg) {    /* Not worth it, stay shifted out */
        !           757:                    xxss = ebq;         /* Insert single shift */
        !           758:                }
        !           759:            }
        !           760:        }
        !           761:        /* If data character is significant to locking shift protocol... */
        !           762:        if (lscapu && (a7 == SO || a7 == SI || a7 == DLE))
        !           763:          xxdl = 'P';                   /* Insert datalink escape */
        !           764: 
        !           765:        if ((a7 < SP) || (a7 == DEL)) { /* Do control prefixing if necessary */
        !           766:            xxcq = myctlq;              /* The prefix */
        !           767:            rt = ctl(rt);               /* Uncontrollify the character */
        !           768:        }
        !           769:        if (a7 == myctlq)               /* Always prefix the control prefix */
        !           770:          xxcq = myctlq;
        !           771: 
        !           772:        if ((rptflg) && (a7 == rptq))   /* If it's the repeat prefix, */
        !           773:          xxcq = myctlq;                /* prefix it if doing repeat counts */
        !           774: 
        !           775:        if ((ebqflg) && (a7 == ebq))    /* Prefix the 8th-bit prefix */
        !           776:          xxcq = myctlq;                /* if doing 8th-bit prefixes */
        !           777: 
        !           778: /* Now construct the entire sequence */
        !           779: 
        !           780:        if (xxls) { *dp++ = myctlq; *dp++ = xxls; } /* Locking shift */
        !           781:        odp2 = dp;                                  /* (Save this place) */
        !           782:        if (xxdl) { *dp++ = myctlq; *dp++ = xxdl; } /* Datalink escape */
        !           783:        if (xxrc) { *dp++ = rptq;   *dp++ = xxrc; } /* Repeat count */
        !           784:        if (xxss) { *dp++ = ebq; }                  /* Single shift */
        !           785:        if (xxcq) { *dp++ = myctlq; }               /* Control prefix */
        !           786:        *dp++ = rt;                     /* Finally, the character itself */
        !           787: 
        !           788:        if (rpt == 1) {                 /* Exactly two copies? */
        !           789:            rpt = 0;
        !           790:            p2 = dp;                    /* Save place temporarily */
        !           791:            for (p1 = odp2; p1 < p2; p1++) /* Copy the old chars over again */
        !           792:              *dp++ = *p1;
        !           793:            if ((p2-data) <= bufmax) odp = p2; /* Check packet bounds */
        !           794:        }
        !           795:        rt = rnext;                     /* Next character is now current. */
        !           796: 
        !           797: /* Done encoding the character.  Now take care of packet buffer overflow. */
        !           798: 
        !           799:        if ((dp-data) >= bufmax) {      /* If too big, save some for next. */
        !           800:            size = (dp-data);           /* Calculate the size. */
        !           801:            *dp = '\0';                 /* Mark the end. */
        !           802:            if ((dp-data) > bufmax) {   /* if packet is overfull */
        !           803:                /* copy the part that doesn't fit into the leftover buffer, */
        !           804:                /* taking care not to split a prefixed sequence. */
        !           805:                for (p1 = leftover, p2=odp; (*p1 = *p2) != '\0'; p1++,p2++)
        !           806:                    ;
        !           807:                debug(F111,"getpkt leftover",leftover,size);
        !           808:                debug(F101," osize","",(odp-data));
        !           809:                size = (odp-data);      /* Return truncated packet. */
        !           810:                *odp = '\0';            /* Mark the new end */
        !           811:            }
        !           812:            t = rt; next = rnext;       /* save for next time */
        !           813:            return(size);
        !           814:        }
        !           815:     }                                  /* Otherwise, keep filling. */
        !           816: 
        !           817:     size = (dp-data);                  /* End of file */
        !           818:     *dp = '\0';                                /* Mark the end of the data. */
        !           819:     debug(F111,"getpkt eof/eot",data,size); /* Fell thru before packet full, */
        !           820:     return(size);                   /* return partially filled last packet. */
        !           821: }
        !           822: 
        !           823: /*  T I N I T  --  Initialize a transaction  */
        !           824: 
        !           825: int
        !           826: tinit() {
        !           827:     int x;
        !           828: 
        !           829: #ifndef NOCSETS
        !           830:     if (tcharset == TC_TRANSP) {       /* Character set translation */
        !           831:        rx = sx = NULL;                 /* Transparent, no translation */
        !           832: #ifdef KANJI
        !           833:     } else if (tcharset == TC_JEUC) {
        !           834:        rx = sx = NULL;                 /* Transparent, no translation */      
        !           835: #endif /* KANJI */
        !           836:     } else {                           /* otherwise */
        !           837:        rx = xlr[tcharset][fcharset];   /* Input translation function */
        !           838:        sx = xls[tcharset][fcharset];   /* Output translation function */
        !           839:     }
        !           840:     debug(F101,"tinit tcharset","",tcharset);
        !           841:     debug(F101,"tinit fcharset","",fcharset);
        !           842: #ifdef COMMENT
        !           843:     debug(F101,"tinit sx   ","",sx);
        !           844:     debug(F101,"tinit rx   ","",rx);
        !           845: #endif /* COMMENT */
        !           846: #endif /* NOCSETS */
        !           847:     myinit[0] = '\0';                  /* Haven't sent init string yet */
        !           848:     autopar = 0;                       /* Automatic parity detection flag */
        !           849:     retrans = 0;                       /* Packet retransmission count */
        !           850:     sndtyp = 0;                                /* No previous packet */
        !           851:     xflg = 0;                          /* Reset x-packet flag */
        !           852:     rqf = -1;                          /* Reset 8th-bit-quote request flag */
        !           853:     memstr = 0;                                /* Reset memory-string flag */
        !           854:     memptr = NULL;                     /*  and pointer */
        !           855:     bctu = bctl = 1;                   /* Reset block check type to 1 */
        !           856:     ebq = MYEBQ;                       /* Reset 8th-bit quoting stuff */
        !           857:     ebqflg = 0;
        !           858:     if (savmod) {                      /* If global file mode was saved, */
        !           859:        binary = savmod;                /*  restore it, */
        !           860:        savmod = 0;                     /*  unsave it. */
        !           861:     }
        !           862:     pktnum = 0;                                /* Initial packet number */
        !           863:     cxseen = czseen = discard = 0;     /* Reset interrupt flags */
        !           864:     *filnam = '\0';                    /* Clear file name */
        !           865:     spktl = 0;                         /* And its length */
        !           866:     nakstate = 0;                      /* Assume not in a NAK'ing state */
        !           867:     numerrs = 0;                       /* Transmission error counter */
        !           868:     if (server)                        /* If acting as server, */
        !           869:       timint = srvtim;                 /* Use server timeout interval. */
        !           870:     else                               /* Otherwise */
        !           871:       timint = chktimo(rtimo,timef);   /* Begin by using local value */
        !           872:     spsiz = spsizr;                    /* Initial send-packet size */
        !           873:     wslots = 1;                                /* One window slot */
        !           874:     wslotn = 1;                                /* No window negotiated yet */
        !           875:     winlo = 0;                         /* Packet 0 is at window-low */
        !           876:     x = mksbuf(1);                     /* Make a 1-slot send-packet buffer */
        !           877:     if (x < 0) return(x);
        !           878:     x = getsbuf(0);                    /* Allocate first send-buffer. */
        !           879:     debug(F101,"tinit getsbuf","",x);
        !           880:     if (x < 0) return(x);
        !           881:     dumpsbuf();
        !           882:     x = mkrbuf(wslots);                        /* & a 1-slot receive-packet buffer. */
        !           883:     if (x < 0) return(x);
        !           884:     what = W_NOTHING;                  /* Doing nothing so far... */
        !           885:     lsstate = 0;                       /* Initialize locking shift state */
        !           886:     return(0);
        !           887: }
        !           888: 
        !           889: VOID
        !           890: pktinit() {                            /* Initialize packet sequence */
        !           891:     pktnum = 0;                                /* number & window low. */
        !           892:     winlo = 0;
        !           893: }
        !           894: 
        !           895: /*  R I N I T  --  Respond to S or I packet  */
        !           896: 
        !           897: VOID
        !           898: rinit(d) CHAR *d; {
        !           899:     char *tp;
        !           900:     ztime(&tp);
        !           901:     tlog(F110,"Transaction begins",tp,0L); /* Make transaction log entry */
        !           902:     if (binary)
        !           903:       tlog(F100,"Global file mode = binary","",0L);
        !           904:     else
        !           905:       tlog(F100,"Global file mode = text","",0L);
        !           906:     filcnt = 0;                                /* Init file counter */
        !           907:     spar(d);
        !           908:     ack1(rpar());
        !           909: #ifdef datageneral
        !           910:     if ((local) && (!quiet))            /* Only do this if local & not quiet */
        !           911:         consta_mt();                    /* Start the asynch read task */
        !           912: #endif /* datageneral */
        !           913: }
        !           914: 
        !           915: 
        !           916: /*  R E S E T C  --  Reset per-transaction character counters */
        !           917: 
        !           918: VOID
        !           919: resetc() {
        !           920:     rptn = 0;                          /* Repeat counts */
        !           921:     fsecs = flci = flco = 0L;          /* File chars in and out */
        !           922:     tfc = tlci = tlco = 0L;            /* Total file, line chars in & out */
        !           923: #ifdef COMMENT
        !           924:     fsize = -1L;                       /* File size */
        !           925: #else
        !           926:     if (what != W_SEND)
        !           927:       fsize = -1L;
        !           928:     debug(F101,"resetc fsize","",fsize);
        !           929: #endif /* COMMENT */
        !           930:     timeouts = retrans = 0;            /* Timeouts, retransmissions */
        !           931:     spackets = rpackets = 0;           /* Packet counts out & in */
        !           932:     crunched = 0;                      /* Crunched packets */
        !           933:     wmax = 1;                          /* Maximum window size used */
        !           934: }
        !           935: 
        !           936: /*  S I N I T  --  Get & verify first file name, then send Send-Init packet */
        !           937: /*
        !           938:  Returns:
        !           939:    1 if send operation begins successfully
        !           940:    0 if send operation fails
        !           941: */
        !           942: #ifdef DYNAMIC
        !           943: char *cmargbuf = NULL;
        !           944: #else
        !           945: char cmargbuf[256];
        !           946: #endif /* DYNAMIC */
        !           947: char *cmargp[2];
        !           948: 
        !           949: int
        !           950: sinit() {
        !           951:     int x;                             /* Worker int */
        !           952:     char *tp, *xp, *m;                 /* Worker string pointers */
        !           953: 
        !           954:     filcnt = 0;                                /* Initialize file counter */
        !           955:     sndsrc = nfils;                    /* Source for filenames */
        !           956: #ifdef DYNAMIC
        !           957:     if (!cmargbuf && !(cmargbuf = malloc(256)))
        !           958:        fatal("sinit: no memory for cmargbuf");
        !           959: #endif /* DYNAMIC */
        !           960:     cmargbuf[0] = NUL;                 /* Initialize name buffer */
        !           961: 
        !           962:     debug(F101,"sinit nfils","",nfils);
        !           963:     debug(F110,"sinit cmarg",cmarg,0);
        !           964:     debug(F110,"sinit cmarg2",cmarg2,0);
        !           965:     if (nfils == 0) {                  /* Sending from stdin or memory. */
        !           966:        if ((cmarg2 != NULL) && (*cmarg2)) {
        !           967:            cmarg = cmarg2;             /* If F packet, "as-name" is used */
        !           968:            cmarg2 = "";                /* if provided */
        !           969:        } else cmarg = "stdin";         /* otherwise just use "stdin" */
        !           970:        strcpy(cmargbuf,cmarg);
        !           971:        cmargp[0] = cmargbuf;
        !           972:        cmargp[1] = "";
        !           973:        cmlist = cmargp;
        !           974:        nfils = 1;
        !           975:     }
        !           976: #ifdef COMMENT
        !           977:     if (nfils < 1) {                   /* Filespec pointed to by cmarg */
        !           978:        if (nfils < 0) sndsrc = 1;
        !           979:        nfils = 1;                      /* Change it to cmlist */
        !           980:        strcpy(cmargbuf,cmarg);         /* so we have a consistent way */
        !           981:        cmargp[0] = cmargbuf;           /* of going thru the file list. */
        !           982:        cmargp[1] = "";
        !           983:        cmlist = cmargp;
        !           984:     }
        !           985: 
        !           986: /* At this point, cmlist contains the list of filespecs to send */
        !           987: 
        !           988:     debug(F111,"sinit *cmlist",*cmlist,nfils);
        !           989: 
        !           990:     xp = *cmlist;                      /* Save this for messages */
        !           991: #else
        !           992:     xp = (nfils < 0) ? cmarg : *cmlist;
        !           993: #endif
        !           994: 
        !           995:     x = gnfile();                      /* Get first filename. */
        !           996:     m = NULL;                          /* Error message pointer */
        !           997:     debug(F101,"sinit gnfil","",x);
        !           998:     switch (x) {
        !           999:       case -5: m = "Too many files match wildcard"; break;
        !          1000:       case -4: m = "Cancelled"; break;
        !          1001:       case -3: m = "Read access denied"; break;
        !          1002:       case -2: m = "File is not readable"; break;
        !          1003:       case -1: m = iswild(filnam) ? "No files match" : "File not found";
        !          1004:        break;
        !          1005:       case  0: m = "No filespec given!" ; break;
        !          1006:       default:
        !          1007:        break;
        !          1008:     }
        !          1009:     debug(F101,"sinit nfils","",nfils);
        !          1010:     debug(F110,"sinit filnam",filnam,0);
        !          1011:     debug(F110,"sinit cmdstr",cmdstr,0);
        !          1012:     if (x < 1) {                       /* Didn't get a file. */
        !          1013:        if (server)                     /* Doing GET command */
        !          1014:          errpkt((CHAR *)m);            /* so send Error packet. */
        !          1015:        else                            /* Doing SEND command */
        !          1016:          screen(SCR_EM,0,0l,m);        /* so print message. */
        !          1017:        tlog(F110,xp,m,0L);             /* Make transaction log entry. */
        !          1018:        freerbuf(rseqtbl[0]);           /* Free the buffer the GET came in. */
        !          1019:        return(0);                      /* Return failure code */
        !          1020:     }
        !          1021:     if (!local && !server) sleep(delay); /* Delay if requested */
        !          1022: #ifdef datageneral
        !          1023:     if ((local) && (!quiet))            /* Only do this if local & not quiet */
        !          1024:         consta_mt();                    /* Start the asynch read task */
        !          1025: #endif /* datageneral */
        !          1026:     freerbuf(rseqtbl[0]);              /* Free the buffer the GET came in. */
        !          1027:     sipkt('S');                                /* Send the Send-Init packet. */
        !          1028:     ztime(&tp);                                /* Get current date/time */
        !          1029:     tlog(F110,"Transaction begins",tp,0L); /* Make transaction log entry */
        !          1030:     debug(F111,"sinit ok",filnam,0);
        !          1031:     return(1);
        !          1032: }
        !          1033: 
        !          1034: int
        !          1035: #ifdef CK_ANSIC
        !          1036: sipkt(char c)                          /* Send S or I packet. */
        !          1037: #else
        !          1038: sipkt(c) char c;
        !          1039: #endif
        !          1040: /* sipkt */ {
        !          1041:     CHAR *rp; int k;
        !          1042:     debug(F101,"sipkt pktnum","",pktnum);
        !          1043:     k = sseqtbl[pktnum];               /* Find slot for this packet */
        !          1044:     debug(F101,"sipkt k","",k);
        !          1045:     if (k < 0) {                       /* No slot? */
        !          1046:        k = getsbuf(winlo = pktnum);    /* Make one. */
        !          1047:        debug(F101,"sipkt getsbuf","",k);    
        !          1048:     }
        !          1049:     ttflui();                          /* Flush pending input. */
        !          1050:     rp = rpar();                       /* Get protocol parameters. */
        !          1051:     return(spack(c,pktnum,(int)strlen((char *)rp),rp)); /* Send them. */
        !          1052: }
        !          1053: 
        !          1054: /*  X S I N I T  --  Retransmit S-packet  */
        !          1055: /*
        !          1056:   For use in the GET-SEND sequence, when we start to send, but receive another
        !          1057:   copy of the GET command because the receiver didn't get our S packet.
        !          1058:   This retransmits the S packet and frees the receive buffer for the ACK.
        !          1059:   The only reason this special case is necessary is that packet number zero
        !          1060:   is being re-used.
        !          1061: */
        !          1062: VOID
        !          1063: xsinit() {
        !          1064:     int k;     
        !          1065:     k = rseqtbl[0];
        !          1066:     debug(F101,"xsinit k","",k);
        !          1067:     if (k > -1)
        !          1068:       freerbuf(k);
        !          1069:     resend(0);
        !          1070: }        
        !          1071: 
        !          1072: /*  R C V F I L -- Receive a file  */
        !          1073: 
        !          1074: /*
        !          1075:   Incoming filename is in data field of F packet.
        !          1076:   This function decodes it into the srvcmd buffer, substituting an
        !          1077:   alternate "as-name", if one was given.
        !          1078:   Then it does any requested transformations (like converting to
        !          1079:   lowercase), and finally if a file of the same name already exists, 
        !          1080:   takes the desired collision action.
        !          1081: */
        !          1082: #ifdef pdp11
        !          1083: #define XNAMLEN 256
        !          1084: #else
        !          1085: #define XNAMLEN 65
        !          1086: #endif /* pdp11 */
        !          1087: 
        !          1088: int
        !          1089: rcvfil(n) char *n; {
        !          1090:     char xname[XNAMLEN], *xp;          /* Buffer for constructing name */
        !          1091: #ifdef DTILDE
        !          1092:     char *dirp, *tilde_expand();
        !          1093: #endif /* DTILDE */
        !          1094: 
        !          1095:     lsstate = 0;                       /* Cancel locking-shift state */
        !          1096:     srvptr = srvcmd;                   /* Decode file name from packet. */
        !          1097:     decode(rdatap,putsrv,0);           /* Don't xlate charsets. */
        !          1098:     if (*srvcmd == '\0')               /* Watch out for null F packet. */
        !          1099:       strcpy((char *)srvcmd,"NONAME");
        !          1100: #ifdef DTILDE
        !          1101:     dirp = tilde_expand((char *)srvcmd); /* Expand tilde, if any. */
        !          1102:     if (*dirp != '\0') strcpy((char *)srvcmd,dirp);
        !          1103: #endif /* DTILDE */
        !          1104:     screen(SCR_FN,0,0l,(char *)srvcmd);        /* Put it on screen if local */
        !          1105:     debug(F110,"rcvfil",(char *)srvcmd,0); /* Debug log entry */
        !          1106:     debug(F101,"rcvfil cmarg2","",cmarg2);
        !          1107:     tlog(F110,"Receiving",(char *)srvcmd,0L); /* Transaction log entry */
        !          1108:     if (cmarg2 != NULL) {               /* Check for alternate name */
        !          1109:         if (*cmarg2 != '\0') {
        !          1110:             strcpy((char *)srvcmd,cmarg2); /* Got one, use it. */
        !          1111:         }
        !          1112:     } else cmarg2 = "";
        !          1113: /*
        !          1114:   NOTE: Much of this code should be moved to opena(), where the file is
        !          1115:   actually opened, AFTER we have received the Attribute packet(s).  That
        !          1116:   way, if the file is mail, or is being sent to the printer, we don't have
        !          1117:   to fuss with collision options, etc, but instead we just pipe the data
        !          1118:   straight into lpr or mail (in UNIX anyway), and then we can also have
        !          1119:   nice subject lines for mail messages by using whatever is in the file
        !          1120:   header packet data field, whether it's a legal filename or not.
        !          1121: */
        !          1122:     if ((int)strlen((char *)srvcmd) > XNAMLEN) /* Watch out for overflow */
        !          1123:       *(srvcmd + XNAMLEN - 1) = NUL;
        !          1124: 
        !          1125:     xp = xname;                                /* OK to proceed. */
        !          1126:     if (fncnv && !*cmarg2)
        !          1127:       zrtol((char *)srvcmd,xp);                /* convert name to local form */
        !          1128:     else                               /* otherwise, */
        !          1129:       strcpy(xname,(char *)srvcmd);    /* use it literally */
        !          1130:     cmarg2 = "";                       /* Remove alternate name */
        !          1131:     debug(F110,"rcvfil as",xname,0);
        !          1132: 
        !          1133: #ifdef COMMENT                         /* Old code... */
        !          1134:     if (warn) {                                /* File collision avoidance? */
        !          1135:        if (zchki(xname) != -1) {       /* Yes, file exists? */
        !          1136:            znewn(xname,&xp);           /* Yes, make new name. */
        !          1137:            strcpy(xname,xp);
        !          1138:            debug(F110," exists, new name ",xname,0);
        !          1139:         }
        !          1140:     }
        !          1141: #endif /* COMMENT */
        !          1142: 
        !          1143: /* Filename collision action section. */
        !          1144: 
        !          1145:     if (
        !          1146: #ifdef UNIX
        !          1147:        strcmp(xname,"/dev/null") &&    /* It's not the null device? */
        !          1148: #endif /* UNIX */
        !          1149:        (zchki(xname) != -1)            /* File of same name exists? */
        !          1150:        ) {                             
        !          1151:        debug(F111,"rcvfil exists",xname,fncact);
        !          1152:        switch (fncact) {               /* Yes, do what user said. */
        !          1153:          case XYFX_A:                  /* Append */
        !          1154:            debug(F100,"rcvfil append","",0);
        !          1155:            break;
        !          1156:          case XYFX_Q:                  /* Query (Ask) */
        !          1157:            break;                      /* not yet implemented */
        !          1158:          case XYFX_B:                  /* Backup (rename old file) */
        !          1159:            znewn(xname,&xp);           /* Get new unique name */
        !          1160:            debug(F110,"rcvfil backup",xname,0);
        !          1161:            debug(F110,"rcvfil backup",xp,0);
        !          1162:            if (zrename(xname,xp) < 0) {
        !          1163:                debug(F110,"rcvfil rename fails",xname,0);
        !          1164:                return(0);
        !          1165:            }
        !          1166:            break;
        !          1167:          case XYFX_D:                  /* Discard (refuse new file) */
        !          1168:            discard = 1;
        !          1169:            debug(F101,"rcvfil discard","",discard);
        !          1170:            break;                      /* not yet implemented */
        !          1171:          case XYFX_R:                  /* Rename new file */
        !          1172:            znewn(xname,&xp);           /* Make new name. */
        !          1173:            strcpy(xname,xp);
        !          1174:            debug(F110,"rcvfil rename",xname,0);
        !          1175:          case XYFX_X:                  /* Replace old file */
        !          1176:            debug(F100,"rcvfil overwrite","",0);
        !          1177:            break;
        !          1178:          case XYFX_U:                  /* Refuse if older */
        !          1179:            debug(F100,"rcvfil update","",0);
        !          1180:            break;                      /* Not here, we don't have */
        !          1181:                                        /* the attribute packet yet. */
        !          1182:          default:
        !          1183:            debug(F101,"rcvfil bad collision action","",fncact);
        !          1184:            break;
        !          1185:        }
        !          1186:     }
        !          1187:     debug(F110,"rcvfil: xname",xname,0);
        !          1188:     screen(SCR_AN,0,0l,xname);         /* Display it */
        !          1189:     strcpy(n,xname);                   /* Return pointer to actual name. */
        !          1190: 
        !          1191: #ifndef NOICP
        !          1192: #ifndef MAC
        !          1193: /* Why not Mac? */
        !          1194:     strcpy(fspec,xname);               /* Here too for \v(filespec) */
        !          1195: #endif /* MAC */
        !          1196: #endif /* NOICP */
        !          1197:     debug(F110,"rcvfil: n",n,0);
        !          1198:     ffc = 0L;                          /* Init per-file counters */
        !          1199:     fsecs = gtimer();                  /* Time this file started */
        !          1200:     filcnt++;
        !          1201:     intmsg(filcnt);
        !          1202:     return(1);                         /* Always succeeds */
        !          1203: }
        !          1204: 
        !          1205: 
        !          1206: /*  R E O F  --  Receive End Of File packet for incoming file */
        !          1207: 
        !          1208: /*
        !          1209:   Closes the received file.
        !          1210:   Returns:
        !          1211:     0 on success.
        !          1212:    -1 if file could not be closed.
        !          1213:     2 if disposition was mail, mail was sent, but temp file not deleted.
        !          1214:     3 if disposition was print, file was printed, but not deleted.
        !          1215:    -2 if disposition was mail and mail could not be sent
        !          1216:    -3 if disposition was print and file could not be printed
        !          1217: */
        !          1218: int
        !          1219: reof(f,yy) char *f; struct zattr *yy; {
        !          1220:     int x;
        !          1221:     char *p;
        !          1222:     char c;
        !          1223: 
        !          1224:     debug(F111,"reof fncact",f,fncact);
        !          1225:     debug(F101,"reof discard","",discard);
        !          1226:     success = 1;                       /* Assume status is OK */
        !          1227:     lsstate = 0;                       /* Cancel locking-shift state */
        !          1228:     if (
        !          1229: #ifdef COMMENT
        !          1230: /*
        !          1231:   If the discard flag is set, for whatever reason, we discard it, right?
        !          1232: */
        !          1233:        (fncact == XYFX_D || fncact == XYFX_U) &&
        !          1234: #endif /* COMMENT */
        !          1235:        discard != 0) {    /* SET FILE COLLISION DISCARD or UPDATE */
        !          1236: 
        !          1237:        debug(F101,"reof discarding","",0);
        !          1238:        discard = 0;                    /* We never opened it, */
        !          1239:        return(0);                      /* so we won't close it. */
        !          1240:     }
        !          1241:     if (cxseen == 0) cxseen = (*rdatap == 'D');        /* Got cancel directive? */
        !          1242:     success = (cxseen || czseen) ? 0 : 1; /* Set SUCCESS flag appropriately */
        !          1243:     x = clsof(cxseen || czseen);       /* Close the file (resets cxseen) */
        !          1244:     if (x < 0) success = 0;            /* If failure to close, FAIL */
        !          1245:     if (atcapu) zstime(f,yy,0);                /* Set file creation date */
        !          1246: 
        !          1247: /* Handle dispositions from attribute packet... */
        !          1248: 
        !          1249: #ifndef NOFRILLS
        !          1250:     if (yy->disp.len != 0) {
        !          1251:        p = yy->disp.val;
        !          1252:        c = *p++;
        !          1253:        if (c == 'M') {                 /* Mail to user. */
        !          1254:            x = zmail(p,filnam);        /* Do the system's mail command */
        !          1255:            if (x < 0) success = 0;     /* Remember status */
        !          1256:            tlog(F110,"mailed",filnam,0L);
        !          1257:            tlog(F110," to",p,0L);
        !          1258:            zdelet(filnam);             /* Delete the file */
        !          1259:        } else if (c == 'P') {          /* Print the file. */
        !          1260:            x = zprint(p,filnam);       /* Do the system's print command */
        !          1261:            if (x < 0) success = 0;     /* Remember status */
        !          1262:            tlog(F110,"printed",filnam,0L);
        !          1263:            tlog(F110," with options",p,0L);
        !          1264: #ifndef VMS
        !          1265:            if (zdelet(filnam) && x == 0) x = 3; /* Delete the file */
        !          1266: #endif /* VMS */
        !          1267:        }
        !          1268:     }
        !          1269: #endif /* NOFRILLS */
        !          1270:     debug(F101,"reof returns","",x);
        !          1271:     *filnam = '\0';
        !          1272:     return(x);
        !          1273: }
        !          1274: 
        !          1275: /*  R E O T  --  Receive End Of Transaction  */
        !          1276: 
        !          1277: VOID
        !          1278: reot() {
        !          1279:     cxseen = czseen = discard = 0;     /* Reset interruption flags */
        !          1280:     tstats();
        !          1281: }
        !          1282: 
        !          1283: /*  S F I L E -- Send File header or teXt header packet  */
        !          1284: 
        !          1285: /*  Call with x nonzero for X packet, zero for F packet  */
        !          1286: /*  Returns 1 on success, 0 on failure                   */
        !          1287: 
        !          1288: int
        !          1289: sfile(x) int x; {
        !          1290: #ifdef pdp11
        !          1291: #define PKTNL 64
        !          1292: #else
        !          1293: #define PKTNL 256
        !          1294: #endif /* pdp11 */
        !          1295:     char pktnam[PKTNL+1];              /* Local copy of name */
        !          1296:     char *s;
        !          1297: 
        !          1298:     lsstate = 0;                       /* Cancel locking-shift state */
        !          1299:     if (nxtpkt() < 0) return(0);       /* Bump packet number, get buffer */
        !          1300:     if (x == 0) {                      /* F-Packet setup */
        !          1301: 
        !          1302:        if (*cmarg2 != '\0') {          /* If we have a send-as name, */
        !          1303:            strncpy(pktnam,cmarg2,PKTNL); /* copy it literally, */
        !          1304:            cmarg2 = "";                /* and blank it out for next time. */
        !          1305:        } else {                        /* Otherwise use actual file name: */
        !          1306:            if (fncnv) {                /* If converting names, */
        !          1307:                zltor(filnam,pktnam);   /* convert it to common form, */
        !          1308:            } else {                    /* otherwise, */
        !          1309:                strncpy(pktnam,filnam,PKTNL); /* copy it literally. */
        !          1310:             }
        !          1311:        }
        !          1312:        debug(F110,"sfile",filnam,0);   /* Log debugging info */
        !          1313:        debug(F110," pktnam",pktnam,0);
        !          1314:        if (openi(filnam) == 0)         /* Try to open the file */
        !          1315:          return(0);            
        !          1316:        s = pktnam;                     /* Name for packet data field */
        !          1317: 
        !          1318:     } else {                           /* X-packet setup */
        !          1319: 
        !          1320:        debug(F110,"sxpack",cmdstr,0);  /* Log debugging info */
        !          1321:        s = cmdstr;                     /* Name for data field */
        !          1322:     }
        !          1323: 
        !          1324:     encstr((CHAR *)s);                 /* Encode the name into encbuf[]. */
        !          1325:                                        /* Send the F or X packet */
        !          1326:     spack((char) (x ? 'X' : 'F'), pktnum, size, encbuf+7);
        !          1327: 
        !          1328:     if (x == 0) {                      /* Display for F packet */
        !          1329:        if (displa) {                   /* Screen */
        !          1330:            screen(SCR_FN,'F',(long)pktnum,filnam);
        !          1331:            screen(SCR_AN,0,0l,pktnam);
        !          1332:            screen(SCR_FS,0,fsize,"");
        !          1333:        }
        !          1334:        tlog(F110,"Sending",filnam,0L); /* Transaction log entry */
        !          1335:        tlog(F110," as",pktnam,0L);
        !          1336:        if (binary) {                   /* Log file mode in transaction log */
        !          1337:            tlog(F101," mode: binary","",(long) binary);
        !          1338:        } else {                        /* If text mode, check character set */
        !          1339:            tlog(F100," mode: text","",0L);
        !          1340: #ifndef NOCSETS
        !          1341:            tlog(F110," file character set",fcsinfo[fcharset].name,0L);
        !          1342:            if (tcharset == TC_TRANSP)
        !          1343:              tlog(F110," xfer character set","transparent",0L);
        !          1344:            else
        !          1345:              tlog(F110," xfer character set",tcsinfo[tcharset].name,0L);
        !          1346: #endif /* NOCSETS */
        !          1347:        }
        !          1348:     } else {                           /* Display for X-packet */
        !          1349: 
        !          1350:        screen(SCR_XD,'X',(long)pktnum,cmdstr); /* Screen */
        !          1351:        tlog(F110,"Sending from:",cmdstr,0L);   /* Transaction log */
        !          1352:     }
        !          1353:     intmsg(++filcnt);                  /* Count file, give interrupt msg */
        !          1354:     first = 1;                         /* Init file character lookahead. */
        !          1355:     ffc = 0L;                          /* Init file character counter. */
        !          1356:     fsecs = gtimer();                  /* Time this file started */
        !          1357:     debug(F101,"SFILE fsecs","",fsecs);
        !          1358:     return(1);
        !          1359: }
        !          1360: 
        !          1361: /*  S D A T A -- Send a data packet */
        !          1362: 
        !          1363: /*
        !          1364:   Returns -1 if no data to send (end of file).  If there is data, a data
        !          1365:   packet is sent, and sdata() returns 1.
        !          1366: 
        !          1367:   For window size greater than 1, keep sending data packets until window
        !          1368:   is full or characters start to appear from the other Kermit, whichever
        !          1369:   happens first.
        !          1370: 
        !          1371:   In the windowing case, when there is no more data left to send (or when
        !          1372:   sending has been interrupted), sdata() does nothing and returns 0 each time
        !          1373:   it is called until the current packet number catches up to the last data
        !          1374:   packet that was sent.
        !          1375: */
        !          1376: 
        !          1377: int
        !          1378: sdata() {
        !          1379:     int i, x, len;
        !          1380:     
        !          1381:     debug(F101,"sdata entry, first","",first);
        !          1382:     debug(F101," drain","",drain);
        !          1383: 
        !          1384: /* The "drain" flag is used with window size > 1.  It means we have sent  */
        !          1385: /* our last data packet.  If called and drain is not zero, then we return */
        !          1386: /* 0 as if we had sent an empty data packet, until all data packets have  */
        !          1387: /* been ACK'd, then then we can finally return -1 indicating EOF, so that */
        !          1388: /* the protocol can switch to seof state.  This is a kludge, but at least */
        !          1389: /* it's localized...  */
        !          1390: 
        !          1391:     if (first == 1) drain = 0;         /* Start of file, init drain flag. */
        !          1392: 
        !          1393:     if (drain) {                       /* If draining... */
        !          1394:        debug(F101,"sdata draining, winlo","",winlo);
        !          1395:        if (winlo == pktnum)            /* If all data packets are ACK'd */
        !          1396:          return(-1);                   /* return EOF indication */
        !          1397:        else                            /* otherwise */
        !          1398:          return(0);                    /* pretend we sent a data packet. */
        !          1399:     }
        !          1400:     debug(F101,"sdata sbufnum","",sbufnum);
        !          1401:     for (i = sbufnum; i > 0; i--) {
        !          1402:         debug(F101,"sdata countdown","",i);
        !          1403:        x = nxtpkt();                   /* Get next pkt number and buffer */
        !          1404:        debug(F101,"sdata packet","",pktnum);
        !          1405:        if (x < 0) return(0);
        !          1406: /***   dumpsbuf(); */
        !          1407:        if (cxseen || czseen) {         /* If interrupted, done. */
        !          1408:            if (wslots > 1) {
        !          1409:                drain = 1;
        !          1410:                debug(F101,"sdata cx/zseen, drain","",cxseen);
        !          1411:                return(0);
        !          1412:            } else {
        !          1413:                return(-1);
        !          1414:            }
        !          1415:        }
        !          1416: #ifdef COMMENT
        !          1417:        if (spsiz > 94)                 /* Fill the packet's data buffer */
        !          1418:          len = getpkt(spsiz-bctl-6,1); /* long packet */
        !          1419:        else                            /*  or */
        !          1420:          len = getpkt(spsiz-bctl-3,1); /* short packet */
        !          1421: #else
        !          1422:        len = getpkt(spsiz,1);
        !          1423: #endif /* COMMENT */
        !          1424:        if (len == 0) {                 /* Done if no data. */
        !          1425:            if (pktnum == winlo) return(-1);
        !          1426:            drain = 1;                  /* But can't return -1 until all */
        !          1427:            debug(F101,"sdata eof, drain","",drain);
        !          1428:            return(0);                  /* ACKs are drained. */
        !          1429:        }
        !          1430:        spack('D',pktnum,len,data);     /* Send the data packet. */
        !          1431:        x = ttchk();                    /* Peek at input buffer. */
        !          1432:        debug(F101,"sdata ttchk","",x); /* ACKs waiting, maybe?  */
        !          1433:        if (x) return(1);               /* Yes, stop sending data packets */
        !          1434:     }                                  /* and go try to read the ACKs. */
        !          1435:     return(1);
        !          1436: }
        !          1437: 
        !          1438: 
        !          1439: /*  S E O F -- Send an End-Of-File packet */
        !          1440: 
        !          1441: /*  Call with a string pointer to character to put in the data field, */
        !          1442: /*  or else a null pointer or "" for no data.  */
        !          1443: 
        !          1444: /*
        !          1445:   There are two "send-eof" functions.  seof() is used to send the normal eof
        !          1446:   packet at the end of a file's data (even if the file has no data), or when
        !          1447:   a file transfer is interrupted.  sxeof() is used to send an EOF packet that
        !          1448:   occurs because of attribute refusal.  The difference is purely a matter of
        !          1449:   buffer allocation and packet sequence number management.  Both functions
        !          1450:   act as "front ends" to the common send-eof function, szeof().
        !          1451: */
        !          1452: 
        !          1453: /* Code common to both seof() and sxeof() */
        !          1454: 
        !          1455: int
        !          1456: szeof(s) CHAR *s; {
        !          1457:     lsstate = 0;                       /* Cancel locking-shift state */
        !          1458:     if ((s != NULL) && (*s != '\0')) {
        !          1459:        spack('Z',pktnum,1,s);
        !          1460:        tlog(F100," *** interrupted, sending discard request","",0L);
        !          1461:     } else {
        !          1462:        spack('Z',pktnum,0,(CHAR *)"");
        !          1463:     }
        !          1464:     discard = 0;                       /* Turn off per-file discard flag */
        !          1465:     return(0);
        !          1466: }
        !          1467: 
        !          1468: int
        !          1469: seof(s) CHAR *s; {
        !          1470: 
        !          1471: /*
        !          1472:   ckcpro.w, before calling seof(), sets window size back to 1 and then calls
        !          1473:   window(), which clears out the old buffers.  This is OK because the final
        !          1474:   data packet for the file has been ACK'd.  However, sdata() has already
        !          1475:   called nxtpkt(), which set the new value of pktnum which seof() will use.
        !          1476:   So all we need to do here is is allocate a new send-buffer.
        !          1477: */
        !          1478:     if (getsbuf(pktnum) < 0) { /* Get a buffer for packet n */
        !          1479:        debug(F101,"seof can't get s-buffer","",pktnum);
        !          1480:        return(-1);
        !          1481:     }
        !          1482:     return(szeof(s));
        !          1483: }
        !          1484: 
        !          1485: /*
        !          1486:   Version of seof() to be called when sdata() has not been called before.  The
        !          1487:   difference is that this version calls nxtpkt() to allocate a send-buffer and
        !          1488:   get the next packet number.
        !          1489: */
        !          1490: int
        !          1491: sxeof(s) CHAR *s; {
        !          1492:     int x;
        !          1493:     x = nxtpkt();                      /* Get next pkt number and buffer */
        !          1494:     if (x < 0)
        !          1495:       debug(F101,"sxeof nxtpkt fails","",pktnum);
        !          1496:     else
        !          1497:       debug(F101,"sxeof packet","",pktnum);
        !          1498:     return(szeof(s));
        !          1499: }
        !          1500: 
        !          1501: /*  S E O T -- Send an End-Of-Transaction packet */
        !          1502: 
        !          1503: int
        !          1504: seot() {
        !          1505:     if (nxtpkt() < 0) return(-1);      /* Bump packet number, get buffer */
        !          1506:     spack('B',pktnum,0,(CHAR *)"");    /* Send the EOT packet */
        !          1507:     cxseen = czseen = discard = 0;     /* Reset interruption flags */
        !          1508:     tstats();                          /* Log timing info */
        !          1509:     return(0);
        !          1510: }
        !          1511: 
        !          1512: /*   R P A R -- Fill the data array with my send-init parameters  */
        !          1513: 
        !          1514: 
        !          1515: CHAR dada[20];                         /* Use this instead of data[]. */
        !          1516:                                        /* To avoid some kind of wierd */
        !          1517:                                        /* addressing foulup in spack()... */
        !          1518:                                        /* (which might be fixed now...) */
        !          1519: 
        !          1520: CHAR *
        !          1521: rpar() {
        !          1522:     if (rpsiz > MAXPACK)               /* Biggest normal packet I want. */
        !          1523:       dada[0] = tochar(MAXPACK);       /* If > 94, use 94, but specify */
        !          1524:     else                               /* extended packet length below... */
        !          1525:       dada[0] = tochar(rpsiz);         /* else use what the user said. */
        !          1526:     dada[1] = tochar(chktimo(pkttim,0)); /* When I want to be timed out */
        !          1527:     dada[2] = tochar(mypadn);          /* How much padding I need (none) */
        !          1528:     dada[3] = ctl(mypadc);             /* Padding character I want */
        !          1529:     dada[4] = tochar(eol);             /* End-Of-Line character I want */
        !          1530:     dada[5] = '#';                     /* Control-Quote character I send */
        !          1531:     switch (rqf) {                     /* 8th-bit prefix */
        !          1532:        case -1:
        !          1533:        case  1: if (parity) ebq = sq = '&'; break;
        !          1534:        case  0:
        !          1535:        case  2: break;
        !          1536:     }
        !          1537:     debug(F000,"rpar 8bq sq","",sq);
        !          1538:     debug(F000,"rpar 8bq ebq","",ebq);
        !          1539:     if (lscapu == 2)                   /* LOCKING-SHIFT FORCED */
        !          1540:       dada[6] = 'N';                   /* means no single-shift */
        !          1541:     else
        !          1542:       dada[6] = sq;
        !          1543:     dada[7] = (bctr == 4) ? 'B' : bctr + '0'; /* Block check type */
        !          1544:     if (rptflg)                                /* Run length encoding */
        !          1545:        dada[8] = rptq;                 /* If receiving, agree. */
        !          1546:     else
        !          1547:        dada[8] = '~';          
        !          1548:     /* CAPAS mask */
        !          1549:     dada[9] = tochar((lscapr ? lscapb : 0) | /* Locking shifts */
        !          1550:                     (atcapr ? atcapb : 0) | /* Attribute packets */
        !          1551:                     (lpcapr ? lpcapb : 0) | /* Long packets */
        !          1552:                     (swcapr ? swcapb : 0)); /* Sliding windows */
        !          1553:     dada[10] = tochar(swcapr ? wslotr : 1);  /* Window size */
        !          1554:     rpsiz = urpsiz - 1;                        /* Long packets ... */
        !          1555:     dada[11] = tochar(rpsiz / 95);     /* Long packet size, big part */
        !          1556:     dada[12] = tochar(rpsiz % 95);     /* Long packet size, little part */
        !          1557:     dada[13] = '\0';                   /* Terminate the init string */
        !          1558: #ifdef DEBUG
        !          1559:     if (deblog) {
        !          1560:        debug(F110,"rpar",dada,0);
        !          1561:        rdebu(dada,(int)strlen((char *)dada));
        !          1562:     }
        !          1563: #endif /* DEBUG */
        !          1564:     strcpy((char *)myinit,(char *)dada);
        !          1565:     return(dada);                      /* Return pointer to string. */
        !          1566: }
        !          1567: 
        !          1568: int
        !          1569: spar(s) CHAR *s; {                     /* Set parameters */
        !          1570:     int x, y, lpsiz;
        !          1571: 
        !          1572:     debug(F110,"entering spar",s,0);
        !          1573: 
        !          1574:     s--;                               /* Line up with field numbers. */
        !          1575: 
        !          1576: /* Limit on size of outbound packets */
        !          1577:     x = (rln >= 1) ? xunchar(s[1]) : 80;
        !          1578:     lpsiz = spsizr;                    /* Remember what they SET. */
        !          1579:     if (spsizf) {                      /* SET-command override? */
        !          1580:        if (x < spsizr) spsiz = x;      /* Ignore LEN unless smaller */
        !          1581:     } else {                           /* otherwise */
        !          1582:        spsiz = (x < 10) ? 80 : x;      /* believe them if reasonable */
        !          1583:     }
        !          1584:     spmax = spsiz;                     /* Remember maximum size */
        !          1585: 
        !          1586: /* Timeout on inbound packets */
        !          1587:     if (timef) {
        !          1588:        timint = rtimo;                 /* SET SEND TIMEOUT value overrides */
        !          1589:     } else {                           /* Otherwise use requested value, */
        !          1590:        x = (rln >= 2) ? xunchar(s[2]) : rtimo; /* if it is legal. */
        !          1591:        timint = (x < 0) ? rtimo : x;
        !          1592:     }
        !          1593:     timint = chktimo(timint,timef);    /* Adjust if necessary */
        !          1594: 
        !          1595: /* Outbound Padding */
        !          1596:     npad = 0; padch = '\0';
        !          1597:     if (rln >= 3) {
        !          1598:        npad = xunchar(s[3]);
        !          1599:        if (rln >= 4) padch = ctl(s[4]); else padch = 0;
        !          1600:     }
        !          1601:     if (npad) {
        !          1602:        int i;
        !          1603:        for (i = 0; i < npad; i++) padbuf[i] = dopar(padch);
        !          1604:     }
        !          1605: 
        !          1606: /* Outbound Packet Terminator */
        !          1607:     seol = (rln >= 5) ? xunchar(s[5]) : CR;
        !          1608:     if ((seol < 2) || (seol > 31)) seol = CR;
        !          1609: 
        !          1610: /* Control prefix */
        !          1611:     x = (rln >= 6) ? s[6] : '#';
        !          1612:     myctlq = ((x > 32 && x < 63) || (x > 95 && x < 127)) ? x : '#';
        !          1613: 
        !          1614: /* 8th-bit prefix */
        !          1615:     rq = (rln >= 7) ? s[7] : 0;
        !          1616:     if (rq == 'Y') rqf = 1;
        !          1617:       else if ((rq > 32 && rq < 63) || (rq > 95 && rq < 127)) rqf = 2;
        !          1618:         else rqf = 0;
        !          1619:     debug(F000,"spar 8bq rq","",rq);
        !          1620:     debug(F000,"spar 8bq sq","",sq);
        !          1621:     debug(F000,"spar 8bq ebq","",ebq);
        !          1622:     debug(F101,"spar 8bq rqf","",rqf);
        !          1623:     switch (rqf) {
        !          1624:        case 0: ebqflg = 0; break;
        !          1625:        case 1: if (parity) { ebqflg = 1; ebq = '&'; } break;
        !          1626:        case 2: if (ebqflg = (ebq == sq || sq == 'Y')) ebq = rq;
        !          1627:     }
        !          1628:     if (lscapu == 2) {     /* No single-shifts if LOCKING-SHIFT FORCED */
        !          1629:        ebqflg = 0;
        !          1630:        ebq = 'N';
        !          1631:     }
        !          1632: 
        !          1633: /* Block check */
        !          1634:     x = 1;
        !          1635:     if (rln >= 8) {
        !          1636:        if (s[8] == 'B') x = 4;
        !          1637:        else x = s[8] - '0';
        !          1638:        if ((x < 1) || (x > 4)) x = 1;
        !          1639:     }
        !          1640:     bctr = x;
        !          1641: 
        !          1642: /* Repeat prefix */
        !          1643:     if (rln >= 9) {
        !          1644:        rptq = s[9]; 
        !          1645:        rptflg = ((rptq > 32 && rptq < 63) || (rptq > 95 && rptq < 127));
        !          1646:     } else rptflg = 0;
        !          1647: 
        !          1648: /* Capabilities */
        !          1649:     atcapu = lpcapu = swcapu = 0;      /* Assume none of these */
        !          1650:     if (lscapu != 2) lscapu = 0;       /* Assume no LS unless forced. */
        !          1651:     y = 11;                            /* Position of next field, if any */
        !          1652:     if (rln >= 10) {
        !          1653:         x = xunchar(s[10]);
        !          1654:        debug(F101,"spar capas","",x);
        !          1655:         atcapu = (x & atcapb) && atcapr;
        !          1656:        lpcapu = (x & lpcapb) && lpcapr;
        !          1657:        swcapu = (x & swcapb) && swcapr;
        !          1658:        debug(F101,"spar lscapu","",lscapu);
        !          1659:        debug(F101,"spar lscapr","",lscapr);
        !          1660:        debug(F101,"spar ebqflg","",ebqflg);
        !          1661:        if (lscapu != 2) lscapu = ((x & lscapb) && lscapr && ebqflg) ? 1 : 0;
        !          1662:        debug(F101,"spar swcapr","",swcapr);
        !          1663:        debug(F101,"spar swcapu","",swcapu);
        !          1664:        debug(F101,"spar lscapu","",lscapu);
        !          1665:        for (y = 10; (xunchar(s[y]) & 1) && (rln >= y); y++) ;
        !          1666:        debug(F101,"spar y","",y);
        !          1667:     }
        !          1668: 
        !          1669: /* Long Packets */
        !          1670:     debug(F101,"spar lpcapu","",lpcapu);
        !          1671:     if (lpcapu) {
        !          1672:         if (rln > y+1) {
        !          1673:            x = xunchar(s[y+2]) * 95 + xunchar(s[y+3]);
        !          1674:            debug(F101,"spar lp len","",x);
        !          1675:            if (spsizf) {               /* If overriding negotiations */
        !          1676:                spsiz = (x < lpsiz) ? x : lpsiz; /* do this, */
        !          1677:            } else {                             /* otherwise */
        !          1678:                spsiz = (x > MAXSP) ? MAXSP : x; /* do this. */
        !          1679:            }
        !          1680:            if (spsiz < 10) spsiz = 80; /* Be defensive... */
        !          1681:        }
        !          1682:     }
        !          1683:     /* (PWP) save current send packet size for optimal packet size calcs */
        !          1684:     spmax = spsiz;
        !          1685:     debug(F101,"spar lp spmax","",spmax);
        !          1686:     timint = chktimo(timint,timef);    /* Recalculate the packet timeout! */
        !          1687:     
        !          1688: /* Sliding Windows... */
        !          1689: 
        !          1690:     if (swcapr) {                      /* Only if requested... */
        !          1691:         if (rln > y) {                 /* See what other Kermit says */
        !          1692:            x = xunchar(s[y+1]);
        !          1693:            debug(F101,"spar window","",x);
        !          1694:            wslotn = (x > MAXWS) ? MAXWS : x;
        !          1695: /*
        !          1696:   wslotn = negotiated size (from other Kermit's S or I packet).
        !          1697:   wslotr = requested window size (from this Kermit's SET WINDOW command).
        !          1698: */
        !          1699:            if (wslotn > wslotr)        /* Use the smaller of the two */
        !          1700:              wslotn = wslotr;
        !          1701:            if (wslotn < 1)             /* Watch out for bad negotiation */
        !          1702:              wslotn = 1;
        !          1703:            if (wslotn > 1)
        !          1704:              swcapu = 1; /* We do windows... */
        !          1705:            debug(F101,"spar window after adjustment","",x);
        !          1706:        } else {                        /* No window size specified. */
        !          1707:            wslotn = 1;                 /* We don't do windows... */
        !          1708:            debug(F101,"spar window","",x);
        !          1709:            swcapu = 0;
        !          1710:            debug(F101,"spar no windows","",wslotn);
        !          1711:        }
        !          1712:     }
        !          1713: 
        !          1714: /* Now recalculate packet length based on number of windows.   */
        !          1715: /* The nogotiated number of window slots will be allocated,    */
        !          1716: /* and the maximum packet length will be reduced if necessary, */
        !          1717: /* so that a windowful of packets can fit in the big buffer.   */
        !          1718: 
        !          1719:     if (wslotn > 1) {                  /* Shrink to fit... */
        !          1720:        x = adjpkl(spsiz,wslotn,bigsbsiz);
        !          1721:        if (x < spsiz) {
        !          1722:            spsiz = spmax = x;
        !          1723:            debug(F101,"spar sending, redefine spsiz","",spsiz);
        !          1724:        }
        !          1725:     }
        !          1726: 
        !          1727: /* Record parameters in debug log */
        !          1728: #ifdef DEBUG
        !          1729:     if (deblog) sdebu(rln);
        !          1730: #endif /* DEBUG */
        !          1731:     numerrs = 0;                       /* Start counting errors here. */
        !          1732:     return(0);
        !          1733: }
        !          1734: 
        !          1735: /*  G N F I L E  --  Get name of next file to send  */
        !          1736: /*
        !          1737:   Expects global sndsrc to be:
        !          1738:    -1: next filename to be obtained by calling znext().
        !          1739:     0: no next file name
        !          1740:     1: (or greater) next filename to be obtained from **cmlist.
        !          1741:   Returns:
        !          1742:     1, with name of next file in filnam.
        !          1743:     0, no more files, with filnam set to empty string.
        !          1744:    -1, file not found
        !          1745:    -2, file is not readable
        !          1746:    -3, read access denied
        !          1747:    -4, cancelled
        !          1748:    -5, too many files match wildcard
        !          1749: */
        !          1750: 
        !          1751: int
        !          1752: gnfile() {
        !          1753:     int x; long y;
        !          1754:     int retcode = 0;
        !          1755: 
        !          1756:     debug(F101,"gnfile sndsrc","",sndsrc);
        !          1757:     fsize = -1L;                       /* Initialize file size */
        !          1758:     if (sndsrc == 0) {                 /* It's not really a file */
        !          1759:        if (nfils > 0) {                /* It's a pipe, or stdin */
        !          1760:            strcpy(filnam, *cmlist);    /* Copy its "name" */
        !          1761:            nfils = 0;                  /* There is no next file */
        !          1762:            return(1);                  /* OK this time */
        !          1763:        } else return(0);               /* but not next time */
        !          1764:     }
        !          1765: 
        !          1766: /* If file group interruption (C-Z) occurred, fail.  */
        !          1767: 
        !          1768:     if (czseen) {
        !          1769:        tlog(F100,"Transaction cancelled","",0L);
        !          1770:         debug(F100,"gnfile czseen","",0);
        !          1771:        return(-4);
        !          1772:     }
        !          1773: 
        !          1774: /* Loop through file list till we find a readable, sendable file */
        !          1775: 
        !          1776:     y = -1L;                           /* Loop exit (file size) variable */
        !          1777:     while (y < 0L) {                   /* Keep trying till we get one... */
        !          1778:        if (sndsrc > 0) {               /* File list in cmlist */
        !          1779:            debug(F101,"gnfile nfils","",nfils);
        !          1780:            if (nfils-- > 0) {          /* Still some left? */
        !          1781:                strcpy(filnam,*cmlist++);
        !          1782:                debug(F111,"gnfile cmlist filnam",filnam,nfils);
        !          1783:                if (!clfils) {          /* Expand only if not from cmdline */
        !          1784:                    x = zxpand(filnam);
        !          1785:                    debug(F101,"gnfile zxpand","",x);
        !          1786:                    if (x == 1) {
        !          1787:                        znext(filnam);
        !          1788:                        goto gotnam;
        !          1789:                    }
        !          1790:                    if (x == 0) {
        !          1791:                        retcode = -1; /* None match */
        !          1792:                        continue;
        !          1793:                    }
        !          1794:                    if (x < 0) return(-5); /* Too many to expand */
        !          1795:                    sndsrc = -1;        /* Change send-source to znext() */
        !          1796:                }
        !          1797:            } else {                    /* We're out of files. */
        !          1798:                debug(F101,"gnfile done","",nfils);
        !          1799:                *filnam = '\0';
        !          1800:                return(retcode);
        !          1801:            }
        !          1802:        }
        !          1803: 
        !          1804: /* Otherwise, step to next element of internal wildcard expansion list. */
        !          1805: 
        !          1806:        if (sndsrc < 0) {
        !          1807:            x = znext(filnam);
        !          1808:            debug(F111,"gnfile znext",filnam,x);
        !          1809:            if (x == 0) {               /* If no more, */
        !          1810:                sndsrc = 1;             /* go back to list */
        !          1811:                continue;
        !          1812:            }
        !          1813:        }
        !          1814: 
        !          1815: /* Get here with a filename. */
        !          1816: 
        !          1817: gotnam:
        !          1818:        if (sndsrc) {
        !          1819:            y = zchki(filnam);          /* Check if file readable */
        !          1820:            retcode = (int) y;          /* Possible return code */
        !          1821:            if (y == -1L) {             /* If not found */
        !          1822:                debug(F110,"gnfile skipping:",filnam,0);
        !          1823:                tlog(F111,filnam,"not sent, reason",(long)y);
        !          1824:                screen(SCR_ST,ST_SKIP,0l,filnam);
        !          1825:                continue;
        !          1826:            } else if (y < 0) {
        !          1827:                continue;
        !          1828:            } else {
        !          1829:                fsize = y;
        !          1830:                return(1);
        !          1831:            }
        !          1832:        } else return(1);               /* sndsrc is 0... */
        !          1833:     }
        !          1834:     *filnam = '\0';                    /* Should never get here */
        !          1835:     return(0);
        !          1836: }
        !          1837: 
        !          1838: 
        !          1839: /*  S N D H L P  --  Routine to send builtin help  */
        !          1840: 
        !          1841: int
        !          1842: sndhlp() {
        !          1843: #ifndef NOSERVER
        !          1844:     nfils = 0;                         /* No files, no lists. */
        !          1845:     xflg = 1;                          /* Flag we must send X packet. */
        !          1846:     strcpy(cmdstr,"help text");                /* Data for X packet. */
        !          1847:     first = 1;                         /* Init getchx lookahead */
        !          1848:     memstr = 1;                                /* Just set the flag. */
        !          1849:     memptr = hlptxt;                   /* And the pointer. */
        !          1850:     if (binary) {                      /* If file mode is binary, */
        !          1851:        savmod = binary;                /*  remember to restore it later. */
        !          1852:        binary = 0;                     /*  turn it back to text for this, */
        !          1853:     }
        !          1854:     return(sinit());
        !          1855: #else
        !          1856:     return(0);
        !          1857: #endif /* NOSERVER */
        !          1858: }
        !          1859: 
        !          1860: #ifdef OS2
        !          1861: /*  S N D S P A C E -- send disk space message  */
        !          1862: int
        !          1863: sndspace(int drive) {
        !          1864: #ifndef NOSERVER
        !          1865:     static char spctext[64];
        !          1866:     if (drive)
        !          1867:       sprintf(spctext, " Drive %c: %ldK free\n", drive, 
        !          1868:              zdskspace(drive - 'A' + 1) / 1024L);
        !          1869:     else
        !          1870:       sprintf(spctext, " Free space: %ldK\n", zdskspace(0)/1024L);
        !          1871:     nfils = 0;                 /* No files, no lists. */
        !          1872:     xflg = 1;                  /* Flag we must send X packet. */
        !          1873:     strcpy(cmdstr,"free space");/* Data for X packet. */
        !          1874:     first = 1;                 /* Init getchx lookahead */
        !          1875:     memstr = 1;                        /* Just set the flag. */
        !          1876:     memptr = spctext;          /* And the pointer. */
        !          1877:     if (binary) {              /* If file mode is binary, */
        !          1878:         savmod = binary;       /*  remember to restore it later. */
        !          1879:         binary = 0;            /*  turn it back to text for this, */
        !          1880:     }
        !          1881:     return(sinit());
        !          1882: #else
        !          1883:     return(0);
        !          1884: #endif /* NOSERVER */
        !          1885: }
        !          1886: #endif /* OS2 */
        !          1887: 
        !          1888: /*  C W D  --  Change current working directory  */
        !          1889: 
        !          1890: /*
        !          1891:  String passed has first byte as length of directory name, rest of string
        !          1892:  is name.  Fails if can't connect, else ACKs (with name) and succeeds. 
        !          1893: */
        !          1894: 
        !          1895: int
        !          1896: cwd(vdir) char *vdir; {
        !          1897:     char *cdd, *zgtdir(), *dirp;
        !          1898: 
        !          1899:     vdir[xunchar(*vdir) + 1] = '\0';   /* Terminate string with a null */
        !          1900:     dirp = vdir+1;
        !          1901:     tlog(F110,"Directory requested: ",dirp,0L);
        !          1902:     if (zchdir(dirp)) {                /* Try to change */
        !          1903:        cdd = zgtdir();         /* Get new working directory. */
        !          1904:        debug(F110,"cwd",cdd,0);
        !          1905:        encstr((CHAR *)cdd);
        !          1906:        ack1((CHAR *)(encbuf+7));
        !          1907:        tlog(F110,"Changed directory to",cdd,0L);
        !          1908:        return(1)        !          1909:     } else {
        !          1910:        debug(F110,"cwd failed",dirp,0);
        !          1911:        tlog(F110,"Failed to change directory to",dirp,0L);
        !          1912:        return(0);
        !          1913:     }
        !          1914: }
        !          1915: 
        !          1916: 
        !          1917: /*  S Y S C M D  --  Do a system command  */
        !          1918: 
        !          1919: /*  Command string is formed by concatenating the two arguments.  */
        !          1920: 
        !          1921: int
        !          1922: syscmd(prefix,suffix) char *prefix, *suffix; {
        !          1923:     char *cp;
        !          1924: 
        !          1925:     if (prefix == NULL || *prefix == '\0') return(0);
        !          1926: 
        !          1927:     for (cp = cmdstr; *prefix != '\0'; *cp++ = *prefix++) ;
        !          1928:     while (*cp++ = *suffix++) ;                /* copy suffix */
        !          1929: 
        !          1930:     debug(F110,"syscmd",cmdstr,0);
        !          1931:     if (zxcmd(ZIFILE,cmdstr) > 0) {
        !          1932:        debug(F110,"syscmd zxcmd ok",cmdstr,0);
        !          1933:        nfils = sndsrc = 0;             /* Flag that input is from stdin */
        !          1934:        xflg = hcflg = 1;               /* And special flags for pipe */
        !          1935:        if (binary) {                   /* If file mode is binary, */
        !          1936:            savmod = binary;            /*  remember to restore it later. */
        !          1937:            binary = 0;                 /*  turn it back to text for this, */
        !          1938:        }
        !          1939:        return (sinit());               /* Send S packet */
        !          1940:     } else {
        !          1941:        debug(F100,"syscmd zxcmd failed",cmdstr,0);
        !          1942:        return(0);
        !          1943:     }
        !          1944: }
        !          1945: 
        !          1946: /*  R E M S E T  --  Remote Set  */
        !          1947: /*  Called by server to set variables as commanded in REMOTE SET packets.  */
        !          1948: /*  Returns 1 on success, 0 on failure.  */
        !          1949: 
        !          1950: int
        !          1951: remset(s) char *s; {
        !          1952:     int len, i, x, y;
        !          1953:     char *p;
        !          1954: 
        !          1955:     len = xunchar(*s++);               /* Length of first field */
        !          1956:     p = s + len;                       /* Pointer to second length field */
        !          1957:     *p++ = '\0';                       /* Zero out second length field */
        !          1958:     x = atoi(s);                       /* Value of first field */
        !          1959:     debug(F111,"remset",s,x);
        !          1960:     debug(F110,"remset",p,0);
        !          1961:     switch (x) {                       /* Do the right thing */
        !          1962:       case 132:                                /* Attributes (all, in) */
        !          1963:        atcapr = atoi(p);
        !          1964:        return(1);
        !          1965:       case 133:                                /* File length attributes */
        !          1966:       case 233:                                /* IN/OUT combined */
        !          1967:       case 148:                                /* Both kinds of lengths */
        !          1968:       case 248:
        !          1969:        atleni = atleno = atoi(p);
        !          1970:        return(1);
        !          1971:       case 134:                                /* File Type (text/binary) */
        !          1972:       case 234:
        !          1973:        attypi = attypo = atoi(p);
        !          1974:        return(1);
        !          1975:       case 135:                                /* File creation date */
        !          1976:       case 235:
        !          1977:        atdati = atdato = atoi(p);
        !          1978:        return(1);
        !          1979:       case 139:                                /* File Blocksize */
        !          1980:       case 239:
        !          1981:        atblki = atblko = atoi(p);
        !          1982:        return(1);
        !          1983:       case 141:                                /* Encoding / Character Set */
        !          1984:       case 241:
        !          1985:        atenci = atenco = atoi(p);
        !          1986:        return(1);
        !          1987:       case 142:                                /* Disposition */
        !          1988:       case 242:
        !          1989:        atdisi = atdiso = atoi(p);
        !          1990:        return(1);
        !          1991:       case 145:                                /* System ID */
        !          1992:       case 245:
        !          1993:        atsidi = atsido = atoi(p);
        !          1994:        return(1);
        !          1995:       case 147:                                /* System-Dependent Info */
        !          1996:       case 247:
        !          1997:        atsysi = atsyso = atoi(p);
        !          1998:        return(1);
        !          1999:       case 232:                                /* Attributes (all, out) */
        !          2000:        atcapr = atoi(p);
        !          2001:        return(1);
        !          2002:       case 300:                                /* File type (text, binary) */
        !          2003:        binary = atoi(p);
        !          2004:        return(1);
        !          2005:       case 301:                                /* File name conversion */
        !          2006:        fncnv = 1 - atoi(p);            /* (oops) */
        !          2007:        return(1);
        !          2008:       case 302:                                /* File name collision */
        !          2009:        x = atoi(p);
        !          2010:        if (x == XYFX_R) warn = 1;      /* Rename */
        !          2011:        if (x == XYFX_X) warn = 0;      /* Replace */
        !          2012:        fncact = x;
        !          2013:        return(1);
        !          2014:       case 310:                                /* Incomplete File Disposition */
        !          2015:        keep = atoi(p);                 /* Keep, Discard */
        !          2016:        return(1);
        !          2017:       case 311:                                /* Blocksize */
        !          2018:        fblksiz = atoi(p);
        !          2019:        return(1);
        !          2020:       case 312:                                /* Record Length */
        !          2021:        frecl = atoi(p);
        !          2022:        return(1);
        !          2023:       case 313:                                /* Record format */
        !          2024:        frecfm = atoi(p);
        !          2025:        return(1);
        !          2026:       case 314:                                /* File organization */
        !          2027:        forg = atoi(p);
        !          2028:        return(1);
        !          2029:       case 315:                                /* File carriage control */
        !          2030:        fcctrl = atoi(p);
        !          2031:        return(1);
        !          2032:       case 400:                                /* Block check */
        !          2033:        y = atoi(p);
        !          2034:        if (y < 5 && y > 0) {
        !          2035:            bctr = y;
        !          2036:            return(1);
        !          2037:        } else if (*p == 'B') {
        !          2038:            bctr = 4;
        !          2039:            return(1);
        !          2040:        }
        !          2041:        return(0);
        !          2042:       case 401:                                /* Receive packet-length */
        !          2043:        urpsiz = atoi(p);
        !          2044:        if (urpsiz > MAXRP) urpsiz = MAXRP;
        !          2045:        urpsiz = adjpkl(urpsiz,wslots,bigrbsiz);
        !          2046:        return(1);
        !          2047:       case 402:                                /* Receive timeout */
        !          2048:        y = atoi(p);                    /* Client is telling us */
        !          2049:        if (y > -1 && y < 999) {        /* the timeout that it wants */
        !          2050:            pkttim = chktimo(y,timef);  /* us to tell it to use. */
        !          2051:            return(1);
        !          2052:        } else return(0);
        !          2053:       case 403:                                /* Retry limit */
        !          2054:        y = atoi(p);
        !          2055:        if (y > -1 && y < 95) {
        !          2056:            maxtry = y;
        !          2057:            return(1);
        !          2058:        } else return(0);
        !          2059:       case 404:                                /* Server timeout */
        !          2060:        y = atoi(p);
        !          2061:        if (y < 0) return(0);
        !          2062:        srvtim = y;
        !          2063:        return(1);
        !          2064: 
        !          2065: #ifndef NOCSETS
        !          2066:       case 405:                                /* Transfer character set */
        !          2067:        for (i = 0; i < ntcsets; i++) { 
        !          2068:            if (!strcmp(tcsinfo[i].designator,p)) break;
        !          2069:        }
        !          2070:        debug(F101,"remset xfer charset lookup","",i);
        !          2071:        if (i == ntcsets) return(0);
        !          2072:        tcharset = tcsinfo[i].code;     /* if known, use it */
        !          2073:        if (tcharset == TC_TRANSP)
        !          2074:          rx = NULL;
        !          2075:        else
        !          2076:          rx = xlr[tcharset][fcharset]; /* translation function */
        !          2077:        return(1);
        !          2078: #endif /* NOCSETS */
        !          2079: 
        !          2080:       case 406:                                /* Window slots */
        !          2081:        y = atoi(p);
        !          2082:        if (y == 0) y = 1;
        !          2083:        if (y < 1 && y > 31) return(0);
        !          2084:        wslotr = y;
        !          2085:        swcapr = 1;
        !          2086:        urpsiz = adjpkl(urpsiz,wslots,bigrbsiz);
        !          2087:        return(1);
        !          2088:       default:                         /* Anything else... */
        !          2089:        return(0);
        !          2090:     }
        !          2091: }
        !          2092: 
        !          2093: /* Adjust packet length based on number of window slots and buffer size */
        !          2094: 
        !          2095: int
        !          2096: adjpkl(pktlen,slots,bufsiz) int pktlen, slots, bufsiz; {
        !          2097:     debug(F101,"adjpkl len","",pktlen);
        !          2098:     debug(F101,"adjpkl slots","",slots);
        !          2099:     debug(F101,"adjpkl bufsiz","",bufsiz);
        !          2100:     if (((pktlen + 6) * slots) > bufsiz)
        !          2101:       pktlen = (bufsiz / slots) - 6;
        !          2102:     debug(F101,"adjpkl new len","",pktlen);
        !          2103:     return(pktlen);
        !          2104: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.