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

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

unix.superglobalmegacorp.com

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