home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / cku302.tar.Z / cku302.tar / ckcfn2.c < prev    next >
C/C++ Source or Header  |  2011-06-06  |  100KB  |  3,351 lines

  1. /*  C K C F N 2  --  System-independent Kermit protocol support functions... */
  2.  
  3. /*  ...Part 2 (continued from ckcfns.c)  */
  4.  
  5. /*
  6.   Author: Frank da Cruz <fdc@columbia.edu>,
  7.   Columbia University Academic Information Systems, New York City.
  8.  
  9.   Copyright (C) 1985, 2011,
  10.     Trustees of Columbia University in the City of New York.
  11.     All rights reserved.  See the C-Kermit COPYING.TXT file or the
  12.     copyright text in the ckcmai.c module for disclaimer and permissions.
  13. */
  14. /*
  15.  Note -- if you change this file, please amend the version number and date at
  16.  the top of ckcfns.c accordingly.
  17. */
  18.  
  19. #include "ckcsym.h"            /* Compilation options */
  20. #include "ckcdeb.h"            /* Debugging and other symbols */
  21. #include "ckcasc.h"            /* ASCII symbols */
  22. #include "ckcker.h"            /* Kermit symbols */
  23. #include "ckcxla.h"            /* Translation */
  24. #include "ckcnet.h"            /* IKS and VMS #define TCPSOCKET */
  25. #ifdef TCPSOCKET            /* For TELNET business in spack() */
  26. extern int tn_nlm, ttnproto, tn_b_nlm;
  27. #endif /* TCPSOCKET */
  28.  
  29. extern int parity, network, local, interrupted, fatalio, wasclosed;
  30.  
  31. int kstartactive = 0;            /* Flag for kstart() in a packet */
  32.  
  33. static CHAR p_tbl[] = {            /* Even parity table for dopar(). */
  34.     (CHAR) '\000',            /* ANSI C casts '\ooo' constants  */
  35.     (CHAR) '\201',            /* to signed char, so we have to  */
  36.     (CHAR) '\202',            /* cast back to unsigned char...  */
  37.     (CHAR) '\003',
  38.     (CHAR) '\204',
  39.     (CHAR) '\005',
  40.     (CHAR) '\006',
  41.     (CHAR) '\207',
  42.     (CHAR) '\210',
  43.     (CHAR) '\011',
  44.     (CHAR) '\012',
  45.     (CHAR) '\213',
  46.     (CHAR) '\014',
  47.     (CHAR) '\215',
  48.     (CHAR) '\216',
  49.     (CHAR) '\017',
  50.     (CHAR) '\220',
  51.     (CHAR) '\021',
  52.     (CHAR) '\022',
  53.     (CHAR) '\223',
  54.     (CHAR) '\024',
  55.     (CHAR) '\225',
  56.     (CHAR) '\226',
  57.     (CHAR) '\027',
  58.     (CHAR) '\030',
  59.     (CHAR) '\231',
  60.     (CHAR) '\232',
  61.     (CHAR) '\033',
  62.     (CHAR) '\234',
  63.     (CHAR) '\035',
  64.     (CHAR) '\036',
  65.     (CHAR) '\237',
  66.     (CHAR) '\240',
  67.     (CHAR) '\041',
  68.     (CHAR) '\042',
  69.     (CHAR) '\243',
  70.     (CHAR) '\044',
  71.     (CHAR) '\245',
  72.     (CHAR) '\246',
  73.     (CHAR) '\047',
  74.     (CHAR) '\050',
  75.     (CHAR) '\251',
  76.     (CHAR) '\252',
  77.     (CHAR) '\053',
  78.     (CHAR) '\254',
  79.     (CHAR) '\055',
  80.     (CHAR) '\056',
  81.     (CHAR) '\257',
  82.     (CHAR) '\060',
  83.     (CHAR) '\261',
  84.     (CHAR) '\262',
  85.     (CHAR) '\063',
  86.     (CHAR) '\264',
  87.     (CHAR) '\065',
  88.     (CHAR) '\066',
  89.     (CHAR) '\267',
  90.     (CHAR) '\270',
  91.     (CHAR) '\071',
  92.     (CHAR) '\072',
  93.     (CHAR) '\273',
  94.     (CHAR) '\074',
  95.     (CHAR) '\275',
  96.     (CHAR) '\276',
  97.     (CHAR) '\077',
  98.     (CHAR) '\300',
  99.     (CHAR) '\101',
  100.     (CHAR) '\102',
  101.     (CHAR) '\303',
  102.     (CHAR) '\104',
  103.     (CHAR) '\305',
  104.     (CHAR) '\306',
  105.     (CHAR) '\107',
  106.     (CHAR) '\110',
  107.     (CHAR) '\311',
  108.     (CHAR) '\312',
  109.     (CHAR) '\113',
  110.     (CHAR) '\314',
  111.     (CHAR) '\115',
  112.     (CHAR) '\116',
  113.     (CHAR) '\317',
  114.     (CHAR) '\120',
  115.     (CHAR) '\321',
  116.     (CHAR) '\322',
  117.     (CHAR) '\123',
  118.     (CHAR) '\324',
  119.     (CHAR) '\125',
  120.     (CHAR) '\126',
  121.     (CHAR) '\327',
  122.     (CHAR) '\330',
  123.     (CHAR) '\131',
  124.     (CHAR) '\132',
  125.     (CHAR) '\333',
  126.     (CHAR) '\134',
  127.     (CHAR) '\335',
  128.     (CHAR) '\336',
  129.     (CHAR) '\137',
  130.     (CHAR) '\140',
  131.     (CHAR) '\341',
  132.     (CHAR) '\342',
  133.     (CHAR) '\143',
  134.     (CHAR) '\344',
  135.     (CHAR) '\145',
  136.     (CHAR) '\146',
  137.     (CHAR) '\347',
  138.     (CHAR) '\350',
  139.     (CHAR) '\151',
  140.     (CHAR) '\152',
  141.     (CHAR) '\353',
  142.     (CHAR) '\154',
  143.     (CHAR) '\355',
  144.     (CHAR) '\356',
  145.     (CHAR) '\157',
  146.     (CHAR) '\360',
  147.     (CHAR) '\161',
  148.     (CHAR) '\162',
  149.     (CHAR) '\363',
  150.     (CHAR) '\164',
  151.     (CHAR) '\365',
  152.     (CHAR) '\366',
  153.     (CHAR) '\167',
  154.     (CHAR) '\170',
  155.     (CHAR) '\371',
  156.     (CHAR) '\372',
  157.     (CHAR) '\173',
  158.     (CHAR) '\374',
  159.     (CHAR) '\175',
  160.     (CHAR) '\176',
  161.     (CHAR) '\377'
  162. };
  163.  
  164. /*  D O P A R  --  Add an appropriate parity bit to a character  */
  165.  
  166. CHAR
  167. #ifdef CK_ANSIC
  168. dopar(register CHAR ch)
  169. #else
  170. dopar(ch) register CHAR ch;
  171. #endif /* CK_ANSIC */
  172.     {
  173.     register unsigned int a;
  174.     if (!parity
  175. #ifdef TCPSOCKET
  176.         || (network && (ttnproto == NP_TELNET) && (TELOPT_ME(TELOPT_BINARY)))
  177. #ifndef NOXFER
  178.     || (!local && sstelnet)        /* TELNET BINARY MODE */
  179. #endif /* NOXFER */
  180. #endif /* TCPSOCKET */
  181.         ) return((CHAR) (ch & 255)); else a = ch & 127;
  182.     switch (parity) {
  183.     case 'e':  return(p_tbl[a]);                 /* Even */
  184.     case 'm':  return((CHAR) (a | 128));         /* Mark */
  185.     case 'o':  return((CHAR) (p_tbl[a] ^ 128));  /* Odd */
  186.     case 's':  return((CHAR) a);                 /* Space */
  187.     default:   return((CHAR) a);                 /* Something illegal */
  188.     }
  189. }
  190.  
  191. #ifndef NOXFER                /* Rest of this file... */
  192.  
  193. #define NEWDPL                /* New dynamic packet length method */
  194.  
  195. #ifdef VMS
  196. extern int batch;
  197. #else
  198. extern int backgrd;
  199. #endif /* VMS */
  200.  
  201. #ifdef DYNAMIC
  202. extern struct pktinfo *s_pkt;        /* array of pktinfo structures */
  203. extern struct pktinfo *r_pkt;        /* array of pktinfo structures */
  204. #else
  205. extern struct pktinfo s_pkt[];        /* array of pktinfo structures */
  206. extern struct pktinfo r_pkt[];        /* array of pktinfo structures */
  207. #endif /* DYNAMIC */
  208.  
  209. extern int sseqtbl[], rseqtbl[], sbufuse[], sacktbl[], wslots, winlo, wslotn,
  210.   sbufnum, rbufnum, pktpaus, reliable;
  211.  
  212. #ifdef STREAMING
  213. static int dontsend = 0;
  214. extern int streaming;
  215. #endif /* STREAMING */
  216.  
  217. extern int ttprty;            /* from ck*tio.c */
  218. extern int autopar;
  219.  
  220. extern int spsiz, spmax, rpsiz, timint, timef, npad, bestlen, maxsend;
  221. extern int rpt, rptq, rptflg, capas, spsizf, en_fin, tsecs, flow;
  222. extern int pktnum, sndtyp, rcvtyp, bctr, bctu, bctf, bctl, rsn, rln, maxtry;
  223. extern int size, osize, maxsize, spktl, rpktl, nfils, stdouf, fsecs;
  224. extern int turn, turnch, displa, pktlog, seslog, xflg, mypadn;
  225. extern int hcflg, server, cxseen, czseen, discard, slostart;
  226. extern int nakstate, quiet, success, xitsta, what, filestatus;
  227. extern int spackets, rpackets, timeouts, retrans, crunched, urpsiz;
  228. extern int carrier, fdispla, srvidl;
  229.  
  230. #ifdef GFTIMER
  231. extern CKFLOAT fptsecs, fpfsecs, fpxfsecs;
  232. #endif /* GFTIMER */
  233.  
  234. extern long filcnt, filrej, speed, filcps, tfcps;
  235. extern CK_OFF_T ffc, flci, flco, tlci, tlco, tfc;
  236.  
  237. extern char *cmarg, filnam[];
  238.  
  239. extern CHAR padch, mypadc, eol, seol, ctlq, sstate;
  240. extern CHAR *recpkt, *data, myinit[];
  241. extern CHAR *srvptr, stchr, mystch, *rdatap;
  242. extern CHAR padbuf[];
  243. extern CHAR * epktmsg;
  244. extern int epktrcvd, epktsent;
  245.  
  246. #ifdef OS2                /* AUTODOWNLOAD parameters */
  247. extern int adl_kmode, adl_zmode;    /* Match Packet to signal download */
  248. extern char * adl_kstr;            /* KERMIT Download String */
  249. extern char * adl_zstr;            /* ZMODEM Download String */
  250. #endif /* OS2 */
  251.  
  252. #ifdef CK_AUTODL
  253. CHAR ksbuf[96] = { NUL, NUL };        /* Autodownload "Kermit Start" buf */
  254. #endif /* CK_AUTODL */
  255.  
  256. int numerrs = 0;            /* Number of packet errors so far */
  257. int rcvtimo = 0;            /* Timeout for receiving a packet */
  258. int idletmo = 0;            /* Flag for idle timeout */
  259.  
  260. long filcps = 0L;            /* CPS most recent file transferred */
  261. long tfcps  = 0L;            /* CPS most recent transaction */
  262. long xfsecs = 0L;            /* Elapsed time for most recent file */
  263. #ifdef GFTIMER
  264. CKFLOAT fpxfsecs = 0.0;            /* Ditto, but floating point */
  265. #endif /* GFTIMER */
  266.  
  267. #ifdef CK_TIMERS
  268. int rrttbl[64], srttbl[64];        /* Packet timestamp tables */
  269. extern int rttflg;
  270. #define RTT_SCALE 1000
  271. long
  272.   rttsamples,                /* Round trip time samples */
  273.   rttdelay,                /* RTT delay */
  274.   pktintvl,                /* Interpacket arrival time */
  275.   rttvariance,                /* RTT variance */
  276.   rttstddev;                /* RTT standard deviation */
  277. #endif /* CK_TIMERS */
  278.  
  279. /* CRC generation tables */
  280.  
  281. long crcta[16] = { 0L, 010201L, 020402L, 030603L, 041004L,
  282.   051205L, 061406L, 071607L, 0102010L, 0112211L, 0122412L, 0132613L, 0143014L,
  283.   0153215L, 0163416L, 0173617L
  284. };
  285.  
  286. long crctb[16] = { 0L, 010611L, 021422L, 031233L, 043044L,
  287.   053655L, 062466L, 072277L, 0106110L, 0116701L, 0127532L, 0137323L, 0145154L,
  288.   0155745L, 0164576L, 0174367L
  289. };
  290.  
  291. #ifdef CK_TIMERS
  292. /*
  293.   Round-trip timer calculations adapted from Tim Kientzle's article,
  294.   "Improving Kermit Performance", Dr Dobb's Journal, February 1996.
  295. */
  296.  
  297.  
  298. /*  R T T I N I T  --  Initialize timers at start of transaction  */
  299.  
  300. VOID
  301. rttinit() {                /* Initialize round-trip timing */
  302.     int i;
  303.  
  304.     if (timint == 0)
  305.       return;
  306.  
  307.     rttsamples  = 0L;            /* Samples (packets) */
  308.     rttvariance = 0L;            /* Variance in delay */
  309.     rttdelay    = (long) timint * RTT_SCALE; /* Delay */
  310.     pktintvl    = (long) timint * RTT_SCALE; /* Delay */
  311.     rttstddev   = (long) timint * RTT_SCALE; /* Standard deviation of delay */
  312.  
  313.     /* Tables of timestamps indexed by packet sequence number */
  314.  
  315.     for (i = 0; i < 64; i++) {
  316.     rrttbl[i] = -1;            /* Time each packet was received */
  317.     srttbl[i] = -1;            /* Time each packet was sent */
  318.     }
  319.     rcvtimo = timint;            /* Initial timeout is what user said */
  320. }
  321.  
  322. /*  G E T R T T  --  Get packet round trip time  */
  323. /*
  324.   Call with nakstate == 0 if file sender, nonzero if receiver,
  325.   and n == packet sequence number of the packet we just received.
  326.  
  327.   Returns:
  328.   -1 on failure with rcvtimo set to timint (what the user said), or:
  329.    0 on success with rcvtimo set to dynamically calculated value:
  330.      1 <= rcvtimo <= timint * 3.
  331. */
  332. int
  333. getrtt(nakstate, n) int nakstate, n; {
  334.     extern int mintime, maxtime;
  335.     static int prevz = 0, prevr = 0;
  336.     int x, y, yy, z = 0, zz = 0;    /* How long did it take to get here? */
  337.  
  338.     rcvtimo = timint;            /* Default timeout is what user said */
  339.  
  340.     if (timint == 0)            /* We're not timing out. */
  341.       return(0);
  342.  
  343.     if (!rttflg)            /* Not supposed to be doing this? */
  344.       return(-1);            /*  So don't */
  345.  
  346.     if (!RTT_SCALE)            /* Paranoia... */
  347.       return(-1);
  348.  
  349.     /* rtimer() (reset timer) is not called until 1st data packet */
  350. #ifdef GFTIMER
  351.     /* rftimer(); */
  352. #endif /* GFTIMER */
  353.     /* S (F [ A ] D* Z)* B */
  354.  
  355.     /* NOTE: we calculate both the round-trip time AND the packet */
  356.     /* arrival rate.  We don't use the RTT for anything, we just display it. */
  357.     /* Timeouts are based on the packet arrival rate. */
  358.  
  359.     if (spackets > 3) {            /* Don't start till 4th packet */
  360.     if (nakstate) {            /* File receiver */
  361.         x = rrttbl[n];             /* Time when I got packet n */
  362.         y = rrttbl[n > 0 ? n - 1 : 63];  /* Time when I got packet n-1 */
  363.         yy = srttbl[n > 0 ? n - 1 : 63]; /* Time when I sent ACK(n-1) */
  364.         if (x > -1 && y > -1) {    /* Be careful */
  365.         z = x - y;        /* Packet rate */
  366.         zz = x - yy;        /* Round trip time */
  367.         z++;            /* So sender & receiver differ */
  368.         debug(F101,"RTT RECV","",z);
  369.         } else {            /* This shouldn't happen */
  370.         debug(F101,"RTT RECV ERROR spackets","",spackets);
  371.         debug(F101,"RTT RECV ERROR sequence","",n);
  372.         return(-1);
  373.         }
  374.     } else {            /* File sender */
  375.         x = rrttbl[n];        /* Time when I got ACK(n) */
  376.         y = rrttbl[n > 0 ? n - 1 : 63]; /* Time when I got packet n-1 */
  377.         yy = srttbl[n];        /* Time when I sent n */
  378.         if (x > -1 && y > -1) {
  379.         z = x - y;        /* Packet rate */
  380.         zz = x - yy;        /* Round trip time */
  381.         debug(F101,"RTT SEND","",z);
  382.         } else {
  383.         debug(F100,"RTT SEND ERROR","",0);
  384.         return(-1);
  385.         }
  386.     }
  387.     if (z < 1)            /* For fast connections */
  388.       z = RTT_SCALE / 2;        /* Convert to scale... */
  389.     else
  390.       z *= RTT_SCALE;
  391.     debug(F101,"RTT z scaled","",z);
  392.  
  393.     if (zz < 1)            /* For fast connections */
  394.       zz = RTT_SCALE / 2;        /* Convert to scale... */
  395.     else
  396.       zz *= RTT_SCALE;
  397.  
  398.     rttdelay = zz;            /* Round trip time of this packet */
  399. #ifdef COMMENT
  400. /*
  401.   This was used in C-Kermit 7.0 (and 6.0?) but not only is it overkill,
  402.   it also can produce ridiculously long timeouts under certain conditions.
  403.   Replaced in 8.0 by a far simpler and more aggressive strategy.
  404. */
  405.     if (rttsamples++ == 0L) {    /* First sample */
  406.         pktintvl = z;
  407.     } else {            /* Subsequent samples */
  408.         long oldavg = pktintvl;
  409.         long rttdiffsq;
  410.  
  411.         if (rttsamples > 30)    /* Use real average for first 30 */
  412.           rttsamples = 30;        /*  then decaying average. */
  413.  
  414.         /* Average delay, difference squared, variance, std deviation */
  415.  
  416.         pktintvl += (z - pktintvl) / rttsamples;
  417.         rttdiffsq = (z - oldavg) * (z - oldavg);
  418.         rttvariance += (rttdiffsq - rttvariance) / rttsamples;
  419.         debug(F101,"RTT stddev1","",rttstddev);
  420.         if (rttstddev < 1L)        /* It can be zero, in which case */
  421.           rttstddev = RTT_SCALE / 3; /* set it to something small... */
  422.         rttstddev = (rttstddev + rttvariance / rttstddev) / 2;
  423.     }
  424.     debug(F101,"RTT stddev2","",rttstddev);
  425.     debug(F101,"RTT delay  ","",pktintvl);
  426.     rcvtimo = (pktintvl + (3L * rttstddev)) / RTT_SCALE + 1;
  427.     if (rpackets < 32)        /* Allow for slow start */
  428.       rcvtimo += rcvtimo + 2;
  429.     else if (rpackets < 64)
  430.       rcvtimo += rcvtimo / 2 + 1;
  431.         /* On a reliable link, don't try too hard to time out. */
  432.     /* Especially on fast local network connections. */
  433.         if (server && what == W_NOTHING) /* Server command wait */
  434.       rcvtimo = rcvtimo;        /* == srvtim */
  435.         else if (reliable == SET_ON && rcvtimo > 0) /* Reliable */
  436.       rcvtimo = rcvtimo +15;    /* and not server command wait */
  437.         else                            /* Not reliable or server cmd wait */
  438.       rcvtimo = rcvtimo;
  439.     if (rcvtimo < mintime)        /* Lower bound */
  440.       rcvtimo = mintime;
  441.     if (maxtime > 0) {        /* User specified an upper bound */
  442.         if (rcvtimo > maxtime)
  443.           rcvtimo = maxtime;
  444.     } else if (maxtime == 0) {    /* User didn't specify */
  445.         if (rcvtimo > timint * 6)
  446.           rcvtimo = timint * 6;
  447.     }
  448. #else  /* COMMENT */
  449. #ifdef CKFLOAT
  450.     {
  451.         CKFLOAT x;
  452.         x = (CKFLOAT)(prevz + z + z) / 3.0;
  453.         rcvtimo = (int)((((CKFLOAT)x * 2.66) / RTT_SCALE) + 0.5);
  454.         debug(F101,"RTT rcvtimo (float)","",rcvtimo);
  455.     }
  456. #else
  457.     rcvtimo = (prevz + z + z) / RTT_SCALE;
  458.     debug(F101,"RTT rcvtimo (int)","",rcvtimo);
  459. #endif /* CKFLOAT */
  460. #endif /* COMMENT */
  461.  
  462.     zz = (rttdelay + 500) / 1000;
  463.     if (rcvtimo > (zz * 3))
  464.       rcvtimo = zz * 3;
  465.  
  466.     if (rcvtimo < 1)
  467.       rcvtimo = 1;
  468.     if (mintime > 0) {
  469.         if (rcvtimo < mintime)    /* Lower bound */
  470.           rcvtimo = mintime;
  471.     }
  472.     if (maxtime > 0) {        /* Upper bound */
  473.         if (rcvtimo > maxtime)
  474.           rcvtimo = maxtime;
  475.     }
  476.     if (rcvtimo == (prevr - 1))
  477.       rcvtimo++;
  478.  
  479.     debug(F101,"RTT final rcvtimo","",rcvtimo);
  480.     }
  481.     prevz = z;
  482.     prevr = rcvtimo;
  483.     return(0);
  484. }
  485. #endif /* CK_TIMERS */
  486.  
  487. /*  I N P U T  --  Attempt to read packet number 'pktnum'.  */
  488.  
  489. /*
  490.  This is the function that feeds input to Kermit's finite state machine,
  491.  in the form of a character in the range 32-126, normally a packet type
  492.  (uppercase letter) or pseudo-packet-type (lowercase letter).
  493.  
  494.  If a special start state is in effect, that state is returned as if it were
  495.  the type of an incoming packet.
  496. */
  497. int
  498. input() {
  499.     int type = 0, acktype;        /* Received packet type */
  500.     int x, y, k;            /* Workers */
  501.     int z, pi, nf;            /* Worker, packet index, NAK flag */
  502.     int nak2ack = 0;
  503.  
  504.     debug(F000,"input sstate","",sstate);
  505.     debug(F101,"input nakstate","",nakstate);
  506.     debug(F000,"input sndtyp","",sndtyp);
  507.     debug(F101,"input xitsta","",xitsta);
  508.     debug(F101,"input what","",what);
  509.  
  510.     while (1) {                /* Big loop... */
  511. /*
  512.   It is ttchk()'s responsibility to tell us if the connection is broken,
  513.   and to do so instantly and nondestructively -- no blocking, etc, that would
  514.   slow down file transfer.
  515. */
  516.     if (ttchk() < 0) {
  517.         debug(F100,"input CONNECTION BROKEN","",0);
  518.         fatalio = 1;
  519.         return('q');
  520.     }
  521.     if (sstate != 0) {        /* If a start state is in effect, */
  522.         type = sstate;        /* return it like a packet type, */
  523.         sstate = 0;            /* and then nullify it. */
  524.         numerrs = 0;        /* (PWP) no errors so far */
  525.         return(type);
  526.     }
  527.     if (nakstate) {            /* This section for file receiver. */
  528.         if (wslots > 1) {        /* If we're doing windows, */
  529.         x = rseqtbl[winlo];    /* see if desired packet already in. */
  530.         debug(F101,"input winlo","",winlo);
  531.         debug(F101,"input rseqtbl[winlo]","",rseqtbl[winlo]);
  532.         if (x > -1) {        /* Already there? */
  533.             if (r_pkt[x].pk_seq == winlo) { /* (double check) */
  534.             rsn = winlo;                /* Yes, return its info */
  535.             debug(F101,"input return pre-stashed packet","",rsn);
  536.             dumprbuf();
  537.             rdatap = r_pkt[x].pk_adr;   /* like rpack would do. */
  538.             rln = (int)strlen((char *) rdatap);
  539.             type = r_pkt[x].pk_typ;
  540.             break;
  541.             }
  542.         }
  543.         }
  544.         type = rpack();            /* Try to read a packet. */
  545.         debug(F101,"input rpack","",type);
  546.  
  547.         while (type == 'e') {    /* Handle echoes */
  548.         debug(F101,"input echo discarded","",type);
  549.         type = rpack();
  550.         }
  551. #ifdef DEBUG
  552.         if (deblog) {
  553.         if (type == 'D')
  554.           debug(F011,"input type D=",(char *)rdatap,39);
  555.         else
  556.           debug(F000,"input type",(char *)rdatap,type);
  557.         }
  558. #endif /* DEBUG */
  559. #ifndef OLDCHKINT
  560.         if (type == 'z') {
  561.         epktrcvd = 1;
  562.         errpkt((CHAR *)"User cancelled.");
  563.         type = 'E';
  564.         break;
  565.         }
  566. #endif /* OLDCHKINT */
  567.         if (type < -1) {
  568.         char * s;
  569.         s = (type == -2) ?
  570.           "FAILED - Interrupted" :
  571.             "FAILED - Connection lost";
  572.  
  573.         xxscreen(SCR_PT,'q',0L,s);
  574.         dologend();
  575.         return('q');        /* Ctrl-C or connection lost */
  576.         }
  577.         if (type < 0) {        /* Receive window full */
  578.         /* Another thing to do here would be to delete */
  579.         /* the highest packet and NAK winlo.  But that */
  580.         /* shouldn't be necessary since the other Kermit */
  581.         /* should not have sent a packet outside the window. */
  582. #ifdef COMMENT
  583.                 char foo[256];
  584.                 ckmakxmsg(foo,256,"Receive window full (rpack): wslots=",
  585.                           ckitoa(wslots)," winlo=",ckitoa(winlo)," pktnum=",
  586.                           ckitoa(pktnum), NULL,NULL,NULL,NULL,NULL,NULL);
  587.         errpkt((CHAR *)foo);
  588.                 debug(F100,foo,"",0);
  589. #else
  590.         errpkt((CHAR *)"Receive window full");
  591.         debug(F101,"rpack receive window full","",0);
  592.                 debug(F101," wslots","",wslots);
  593.                 debug(F101," winlo","",winlo);
  594.         debug(F101," pktnum","",pktnum);
  595. #endif
  596.         dumprbuf();
  597.         type = 'E';
  598.         break;
  599.         }
  600.         dumprbuf();
  601.  
  602. #ifdef OLDCHKINT
  603.         if (chkint() < 0) {        /* Check for console interrupts. */
  604.         errpkt((CHAR *)"User cancelled."); /* (old way) */
  605.         type = 'E';
  606.         break;
  607.         }
  608. #endif /* OLDCHKINT */
  609.  
  610. #ifdef STREAMING
  611.         if (streaming) {        /* Streaming */
  612.         if (type == 'Q' || type == 'T') { /* Errors are fatal. */
  613.             crunched++;        /* For statistics */
  614.             errpkt((CHAR *)"Transmission error on reliable link.");
  615.             type = 'E';
  616.         }
  617.         }
  618. #endif /* STREAMING */
  619.         if (type == 'E') {
  620.         debug(F101,"input got E, nakstate","",nakstate);
  621.         break;            /* Error packet */
  622.         }
  623.         if (type == 'Q') {        /* Crunched packet. */
  624.         crunched++;
  625.         numerrs++;
  626. /*
  627.   Packet arrived damaged.  It was most likely the packet we were expecting
  628.   next, so we send a NAK for that packet.  Prior to 5A(189), we always
  629.   NAK'd winlo here, but that was bad because if two (or more) different
  630.   packets were damaged, we would keep NAKing the first one and never NAK the
  631.   other ones, which could result in a lengthy series of timeouts.  Now we
  632.   NAK the oldest as-yet-unNAK'd missing packet.
  633. */
  634. #ifdef CK_TIMERS
  635.         rcvtimo++;        /* Stretch the timeout a little */
  636. #endif /* CK_TIMERS */
  637.         z = (winlo + wslots) % 64;  /* Search from winlo to z */
  638.         debug(F101,"ZZZ crunched z","",z);
  639.         nf = 0;                /* NAK flag not set yet */
  640.         for (x = winlo; x != z; x = (x + 1) % 64) {
  641.             debug(F101,"ZZZ x","",x);
  642.             if (rseqtbl[x] > -1) /* Have I received packet x? */
  643.               continue;         /* Yes, go on. */
  644.             debug(F101,"ZZZ x not recd yet","",x);
  645.             pi = sseqtbl[x];     /* No, have I NAK'd it yet? */
  646.             if (pi < 0 || s_pkt[pi].pk_rtr == 0) {
  647.             debug(F101,"ZZZ x not NAK'd yet","",x);
  648.             nack(x);     /* No, NAK it now. */
  649.             nf = 1;         /* Flag that I did. */
  650.             break;
  651.             }
  652.         }
  653.         if (!nf) {        /* If we didn't NAK anything above, */
  654.             debug(F101,"ZZZ NAKing winlo","",winlo);
  655.             if (nack(winlo) < 0) { /* we have to NAK winlo (again) */
  656.             errpkt((CHAR *)"Too many retries."); /* Too many */
  657.             type = 'E';
  658.             break;
  659.             }
  660.         }
  661.         continue;
  662.         }
  663.  
  664.         if (type == 'T') {        /* Timeout */
  665. #ifndef OS2
  666.         /* K95 does this its own way */
  667.         if (server && srvidl) {
  668.             idletmo = 1;
  669.             debug(F101,"SERVER IDLE TIMEOUT","",srvidl);
  670.             return('q');
  671.         }
  672. #endif /* OS2 */
  673. #ifdef CK_TIMERS
  674.         rcvtimo++;        /* Stretch the timeout a little */
  675. #endif /* CK_TIMERS */
  676.         timeouts++;
  677.         debug(F101,"input receive-state timeout, winlo","",winlo);
  678.         /* NAK only the packet at window-low */
  679.         debug(F101,"input sending NAK for winlo","",winlo);
  680.         x = ttchk();
  681.         if (x > 0)        /* Don't give up if there is still */
  682.           continue;        /* something to read. */
  683.         else if (x < 0) {
  684.             dologend();
  685.             fatalio = 1;
  686.             return('q');    /* Connection Lost */
  687.         }
  688.         if (nack(winlo) < 0) {
  689.             debug(F101,"input sent too many naks","",winlo);
  690.             errpkt((CHAR *)"Too many retries.");
  691.             type = 'E';
  692.             break;
  693.         } else continue;
  694.         }
  695.         if (rsn == winlo) {        /* Got the packet we want, done. */
  696. #ifdef CK_TIMERS
  697.         if (rttflg && timint)    /* Dynamic round trip timers? */
  698.           getrtt(nakstate, rsn); /* yes, do it. */
  699.                 else                     /* JHD 20100208 */
  700.                   rcvtimo = timint;      /* JHD 20100208 */
  701. #endif /* CK_TIMERS */
  702.         debug(F101,"input rsn=winlo","",rsn);
  703.         break;
  704.         }
  705.  
  706.         /* Got a packet out of order. */
  707.  
  708.         debug(F101,"input out of sequence, rsn","",rsn);
  709.         k = rseqtbl[rsn];        /* Get window slot of this packet. */
  710.         debug(F101,"input rseqtbl[rsn]","",k);
  711.         if (k < 0) {
  712.         debug(F101,"input recv can't find index for rcvd pkt","",rsn);
  713.         /* Was "Internal error 21" */
  714.         /* This should not happen  */
  715.         errpkt((CHAR *)"Sliding windows protocol error.");
  716.         type = 'E';
  717.         break;
  718.         }
  719.         y = chkwin(rsn,winlo,wslots); /* See what window it's in. */
  720.         debug(F101,"input recv chkwin","",y);
  721.         if (y == 1) {        /* From previous window. */
  722. #ifdef STREAMING
  723.         if (!streaming)        /* NO RESEND IF STREAMING! */
  724. #endif /* STREAMING */
  725.           resend(rsn);        /* Resend the ACK (might have data) */
  726.         freerpkt(rsn);        /* Get rid of received packet */
  727.         continue;        /* Back to wait for another packet */
  728.         } else {            /* In this window or out of range */
  729.         if (y < 0)        /* If out of range entirely, */
  730.           freerpkt(rsn);    /* release its buffer */
  731.  
  732. #ifdef STREAMING
  733.         if (streaming) {    /* Streaming (this shouldn't happen) */
  734.             errpkt((CHAR *)"Sequence error on reliable link.");
  735.             type = 'E';
  736.             break;
  737.         }
  738. #endif /* STREAMING */
  739.  
  740. /* If our receive window is full, NAK window-low */
  741.  
  742.         if (rbufnum < 1) {    /* Receive window full? */
  743.             if (nack(winlo) < 0) {    /* No choice, must NAK winlo. */
  744.             errpkt((CHAR *)"Too many retries."); /* Too many */
  745.             type = 'E';
  746.             break;
  747.             } else continue;
  748.         }
  749. /*
  750.   Receive window not full.  This is a packet in the current window but it is
  751.   not the desired packet at winlo.  So therefore there are gaps before this
  752.   packet.  So we find the "lowest" unNAK'd missing packet, if any, between
  753.   winlo and this one, and NAK it.  If there are no as-yet-unNAK'd missing
  754.   packets in the window, then we send nothing and go wait for another packet.
  755.   In theory, this could result in a timeout, but in practice it is likely that
  756.   the already-NAK'd missing packets are already on their way.  Note, we do not
  757.   NAK ahead of ourselves, as that only creates unnecessary retransmissions.
  758. */
  759.         for (x = winlo; x != rsn; x = (x + 1) % 64) {
  760.             if (rseqtbl[x] > -1) /* Have I received packet x? */
  761.               continue;         /* Yes, check next sequence number. */
  762.             pi = sseqtbl[x];     /* No, have I NAK'd it yet? */
  763.             if (pi < 0 || s_pkt[pi].pk_rtr == 0) {
  764.             nack(x);     /* No, NAK it now. */
  765.             break;
  766.             }
  767.         }
  768.         }
  769. /*!!!*/
  770.     } else {            /* Otherwise file sender... */
  771.  
  772. #ifdef STREAMING
  773.         if (streaming && sndtyp == 'D') {
  774.         debug(F101,"STREAMING input streaming","",streaming);
  775.         debug(F000,"STREAMING input sndtyp","",sndtyp);
  776.         rsn = winlo;
  777.         type = 'Y';        /* Pretend we got an ACK */
  778.         }
  779. #endif /* STREAMING */
  780.         if (!nak2ack) {        /* NAK(n+1) = ACK(n) */
  781.         if (wslots > 1) {    /* Packet at winlo already ACK'd? */
  782.             if (sacktbl[winlo]) { /* If so,  */
  783.             sacktbl[winlo] = 0; /* Turn off the ACK'd flag */
  784.             winlo = (winlo + 1) % 64; /* Rotate the window */
  785.             type = 'Y';    /* And return ACK */
  786.             debug(F101,
  787.                   "input send returning pre-stashed ACK","",
  788.                   winlo-1);
  789.             break;
  790.             }
  791.         }
  792. #ifdef STREAMING
  793.         if (!(streaming && sndtyp == 'D')) { /* Not streaming | data */
  794.             type = rpack();    /* Try to read an acknowledgement */
  795.         } else {        /* Streaming and in Data phase */
  796.             type = 'Y';        /* Assume all is normal */
  797.             if (chkint() < 0)    /* Check for console interrupts. */
  798.               type = 'z';
  799.             else if (ttchk() > 4 + bctu) /* Check for return traffic */
  800.               type = rpack();
  801.             debug(F000,"input streaming type","",type);
  802.         }
  803. #endif /* STREAMING */
  804.         debug(F111,"input send",(char *) rdatap,(int) type);
  805.         while (type == 'e') {    /* Handle echoes */
  806.             debug(F000,"echo discarded","",type);
  807.             type = rpack();
  808.         }
  809. #ifndef OLDCHKINT
  810.         if (type == 'z') {
  811.             epktrcvd = 1;
  812.             errpkt((CHAR *)"User cancelled.");
  813.             type = 'E';
  814.             break;
  815.         }
  816. #endif /* OLDCHKINT */
  817.         if (type < -1) {
  818.             xxscreen(SCR_PT,'q',0L,
  819.                ((char *)((type == -2) ?
  820.                "Interrupted" :
  821.                "Connection lost"))
  822.                );
  823.             if (type != -2)
  824.               dologend();
  825.             return('q');    /* Ctrl-C or connection lost */
  826.         }
  827.         if (type == -1) {
  828. #ifdef COMMENT
  829.                     char foo[256];
  830.                     ckmakxmsg(foo,256,
  831.                   "Receive window full (error 18): wslots=",
  832.                               ckitoa(wslots),
  833.                   " winlo=",ckitoa(winlo)," pktnum=",
  834.                               ckitoa(pktnum), NULL,NULL,NULL,NULL,NULL,NULL);
  835.             errpkt((CHAR *)foo);
  836.                     debug(F100,foo,"",0);
  837. #else
  838.             errpkt((CHAR *)"Receive window full"); /* was "internal */
  839.                     debug(F101," wslots","",wslots); /* error 18" */
  840.                     debug(F101," winlo","",winlo);
  841.             debug(F101," pktnum","",pktnum);
  842. #endif /* COMMENT */
  843.             dumprbuf();
  844.             type = 'E';
  845.             break;
  846.         }
  847.         dumprbuf();        /* Debugging */
  848.  
  849. #ifdef OLDCHKINT
  850.         if (chkint() < 0) {    /* Check for console interrupts. */
  851.             errpkt((CHAR *)"User cancelled.");
  852.             return(type = 'E');
  853.         }
  854. #endif /* OLDCHKINT */
  855.  
  856.         /* Got a packet */
  857.  
  858. #ifdef STREAMING
  859.         if (streaming) {        /* Streaming */
  860.             if (type == 'Q' || type == 'T') { /* Errors are fatal. */
  861.             crunched++;    /* For statistics */
  862.             errpkt((CHAR *)"Transmission error on reliable link.");
  863.             type = 'E';
  864.             }
  865.         }
  866. #endif /* STREAMING */
  867.         if (type == 'E') {
  868.             debug(F101,"input send got E, nakstate","",nakstate);
  869.             break;        /* Error packet */
  870.         }
  871.         if (type == 'Q') {    /* Crunched packet */
  872.             crunched++;        /* For statistics */
  873.             numerrs++;        /* For packet resizing */
  874.             x = resend(winlo);    /* Resend window-low */
  875.             if (x < 0) {
  876.             type = 'E';
  877.             errpkt((CHAR *)"Too many retries");
  878.             break;
  879.             }
  880.             continue;
  881.         }
  882.         if (type == 'T') {    /* Timeout waiting for ACKs. */
  883.             timeouts++;        /* Count it */
  884.             numerrs++;        /* Count an error too */
  885.             debug(F101,"input send state timeout, winlo","",winlo);
  886.  
  887.             /* Retransmit the oldest un-ACK'd packet. */
  888.  
  889.             debug(F101,"input send resending winlo","",winlo);
  890.             if (resend(winlo) < 0) { /* Check retries */
  891.             debug(F101,"input send too many resends","",maxtry);
  892.             errpkt((CHAR *)"Too many retries");
  893.             return(type = 'E');
  894.             }
  895. #ifdef NEWDPL
  896.             /* Reduce prevailing packet length */
  897.             x = sseqtbl[winlo];    /* Get length of packet we want ACKd */
  898.             if (x > -1) {    /* Only if we have a valid index */
  899.             if (s_pkt[x].pk_typ == 'D') { /* only for D packets */
  900.                 spsiz = (s_pkt[x].pk_len + 8) >> 1; /* halve it */
  901.                 if (spsiz < 20) spsiz = 20; /* within reason */
  902.                 debug(F101,"input T cut packet length","",spsiz);
  903.             }
  904.             }
  905. #endif /* NEWDPL */
  906.             continue;
  907.         }
  908.         }
  909.         /* Got an actual normal packet */
  910.  
  911.         nak2ack = 0;        /* Unset this flag. */
  912.         y = chkwin(rsn,winlo,wslots); /* Is it in the window? */
  913.         debug(F101,"input send rsn","",rsn);
  914.         debug(F101,"input send winlo","",winlo);
  915.         debug(F101,"input send chkwin","",y);
  916.  
  917.         if (type == 'Y') {        /* Got an ACK */
  918.         if (y == 0) {        /* In current window */
  919.             if (spackets < 4)    /* Error counter doesn't count */
  920.               numerrs = 0;    /* until data phase. */
  921.             sacktbl[rsn]++;    /* Mark the packet as ACK'd */
  922.             x = sseqtbl[rsn];    /* Get ACK'd packet's buffer index */
  923.             debug(F101,"bestlen ack x","",x);
  924. #ifdef NEWDPL
  925.             if (x > -1) {
  926.             acktype = s_pkt[x].pk_typ; /* Get type */
  927.             debug(F000,"bestlen ack type","",acktype);
  928.  
  929.             if (acktype == 'D') { /* Adjust data packet length */
  930.                 if (spsiz > bestlen) {
  931.                 bestlen = spsiz;
  932.                 debug(F101,"bestlen B","",bestlen);
  933.                 }
  934. #ifdef DEBUG
  935.                 if (deblog) {
  936.                 debug(F101,"bestlen retry","",s_pkt[x].pk_rtr);
  937.                 debug(F101,"bestlen len","",s_pkt[x].pk_len);
  938.                 debug(F101,"bestlen spackets","",spackets);
  939.                 }
  940. #endif /* DEBUG */
  941.                 /* Set new best length */
  942.                 if (s_pkt[x].pk_rtr == 0 &&
  943.                 s_pkt[x].pk_len + 8 > bestlen) {
  944.                 bestlen = s_pkt[x].pk_len + 8;
  945.                 if (bestlen > spmax)
  946.                   bestlen = spmax;
  947.                 debug(F101,"bestlen A","",bestlen);
  948.                 }
  949. #ifdef DEBUG
  950.                 if (deblog) {
  951.                 debug(F101,"bestlen wslots","",wslots);
  952.                 debug(F101,"bestlen maxsend","",maxsend);
  953.                 }
  954. #endif /* DEBUG */
  955.                 /* Slow start */
  956.                 if (slostart &&
  957.                 (maxsend <= spmax) &&
  958.                 (rpackets < 11) &&
  959.                 (numerrs == 0)) {
  960.                 spsiz = spsiz << 1;
  961.                 debug(F101,"bestlen spsiz A","",spsiz);
  962.  
  963.                 /* Creep up to best length */
  964.                 } else if ((spackets > 5) &&
  965.                        (spsiz < bestlen - 8)) {
  966.                 spsiz += (bestlen - spsiz) / 3;
  967.                 debug(F101,"bestlen spsiz B","",spsiz);
  968.  
  969.                 /* Push the envelope */
  970.                 } else if ((spackets % (wslots + 1) == 0) &&
  971.                        (spackets > 6) &&
  972.                        (bestlen < spmax - 8) &&
  973.                        (spsiz < spmax)) {
  974.                 spsiz += (spmax - bestlen) / 3;
  975.                 debug(F101,"bestlen spsiz C","",spsiz);
  976.                 }
  977.                 /* But not too far */
  978.                 if (spsiz > spmax) {
  979.                 spsiz = spmax;
  980.                 debug(F101,"bestlen spsiz D","",spsiz);
  981.                 }
  982.             }
  983.             }
  984. #endif /* NEWDPL */
  985.  
  986. #ifdef CK_TIMERS
  987.             if (rttflg && timint) /* If doing dynamic timers */
  988.               getrtt(nakstate, rsn); /* call routine to set it. */
  989.             else                     /* JHD 20100208 */
  990.               rcvtimo = timint;         /* JHD 20100208 */
  991. #endif /* CK_TIMERS */
  992. /*
  993.   NOTE: The following statement frees the buffer of the ACK we just got.
  994.   But the upper layers still need the data, like if it's the ACK to an I,
  995.   S, F, D, Z, or just about any kind of packet.  So for now, freerbuf()
  996.   deallocates the buffer, but does not erase the data or destroy the pointer
  997.   to it.  There's no other single place where these receive buffers can be
  998.   correctly freed (?) ...
  999. */
  1000.             freerpkt(rsn);    /* Free the ACK's buffer */
  1001.             freesbuf(rsn);    /* *** Free the sent packet's buffer */
  1002.             if (rsn == winlo) {    /* Got the one we want */
  1003.             sacktbl[winlo] = 0;
  1004.             winlo = (winlo + 1) % 64;
  1005.             debug(F101,"input send rotated send window","",winlo);
  1006.             break;        /* Return the ACK */
  1007.             } else {
  1008.             debug(F101,"input send mark pkt","",rsn);
  1009.             continue;    /* Otherwise go read another packet */
  1010.             }
  1011.         } else if (y == 1 && wslots < 2) { /* (190) ACK for previous */
  1012.             numerrs++;        /* == NAK for current, count error */
  1013.             debug(F101,"input send ACK for previous","",rsn);
  1014.             freerpkt(rsn);    /* Free NAK's buffer */
  1015.             x = resend(winlo);    /* Resend current packet */
  1016.             if (x < 0) {
  1017.             type = 'E';
  1018.             errpkt((CHAR *)"Too many retries");
  1019.             break;
  1020.             } else continue;    /* Resend ok, go read another packet */
  1021.         } else {        /* Other cases, just ignore */
  1022.             debug(F101,"input send ACK out of window","",rsn);
  1023.             freerpkt(rsn);
  1024.             continue;
  1025.         }
  1026.         }
  1027.         if (type == 'N') {        /* NAK */
  1028.         numerrs++;        /* Count an error */
  1029. #ifdef STREAMING
  1030.         if (streaming) {        /* Streaming */
  1031.             errpkt((CHAR *)"NAK received on reliable link.");
  1032.             type = 'E';
  1033.             break;
  1034.         }
  1035. #endif /* STREAMING */
  1036.  
  1037.         debug(F101,"input send NAK","",rsn);
  1038. #ifdef NEWDPL
  1039.         /* Reduce prevailing packet length */
  1040.         x = sseqtbl[rsn];    /* Length of packet that was NAK'd */
  1041.         if (x > -1) {        /* If it's a Data packet we've sent */
  1042.             if (s_pkt[x].pk_typ == 'D') {
  1043.             spsiz = (s_pkt[x].pk_len + 8) >> 1; /* Halve length */
  1044. #ifdef COMMENT
  1045.             /* This might be a good idea -- haven't tried it ... */
  1046.             if (bestlen > 0 && spsiz > bestlen)
  1047.               spsiz = bestlen;
  1048. #endif /* COMMENT */
  1049.             if (spsiz < 20) spsiz = 20;
  1050.             debug(F101,"input N cut packet length","",spsiz);
  1051.             }
  1052.         }
  1053. #endif /* NEWDPL */
  1054.         freerpkt(rsn);        /* Free buffer where NAK lies. */
  1055.         if (y == 0) {        /* In current window */
  1056.             debug(F100," in window","",0);
  1057.             k = sseqtbl[rsn];    /* Get pointer to NAK'd packet. */
  1058.             if (k < 0 || (k > -1 && s_pkt[k].pk_typ == ' ')) {
  1059.             x = resend(winlo); /* Packet we haven't sent yet. */
  1060.             } else {
  1061.             x = resend(rsn); /* Resend requested packet. */
  1062.             }
  1063.             if (x < 0) {    /* Resend error is fatal.  */
  1064.             type = 'E';
  1065.             errpkt((CHAR *)"Too many retries");
  1066.             break;
  1067.             } else continue;    /* Resend ok, go read another packet */
  1068.         } else if ((rsn == (pktnum + 1) % 64)) { /* NAK for next pkt */
  1069.             if (wslots > 1) {
  1070.             debug( F101,"NAK for next packet, windowing","",rsn);
  1071.             x = resend(winlo); /* Resend window-low */
  1072.             if (x < 0) {
  1073.                 type = 'E';
  1074.                 errpkt((CHAR *)"Too many retries");
  1075.                 break;
  1076.             }
  1077.             continue;    /* Go back and read another pkt */
  1078.             }
  1079.             debug(F101,"NAK for next packet, no windowing","",rsn);
  1080.             x = (rsn == 0) ? 63 : rsn - 1;
  1081.             if (x == 0 && (sndtyp == 'S' || sndtyp == 'I')) {
  1082.             resend(0);    /* ACK for S or I packet missing */
  1083.             continue;    /* so resend the S or I */
  1084.             }
  1085.             rsn = x;        /* Else, treat NAK(n+1) as ACK(n) */
  1086.             nak2ack = 1;    /* Go back and process the ACK */
  1087.             continue;
  1088.         } else if (y > 0) {    /* NAK for pkt we can't resend */
  1089.             debug(F101," NAK out of window","",rsn); /* bad... */
  1090.             type = 'E';
  1091.             errpkt((CHAR *)"NAK out of window");
  1092.             break;
  1093.         } else continue;    /* Ignore other NAKs */
  1094.         }                /* End of file-sender NAK handler */
  1095.  
  1096.             if (rsn == winlo) {        /* Not ACK, NAK, timeout, etc. */
  1097.         debug(F000,"input send unexpected type","",type);
  1098.         break;
  1099.         }
  1100.     }                /* End of file-sender section */
  1101.     }                    /* End of input() while() loop */
  1102. /*
  1103.   When the window size is 1 and we have the packet we want, there can not
  1104.   possibly be anything waiting for us on the connection that is useful to us.
  1105.   However, there might be redundant copies of a packet we already got, which
  1106.   would cause needless cycles of repeated packets.  Therefore we flush the
  1107.   communications input buffer now to try to get rid of undesired and unneeded
  1108.   packets that we have not read yet.
  1109.  
  1110.   Actually, the first sentence above is not entirely true: there could be an
  1111.   Error packet waiting to be read.  Flushing an E packet is bad because it
  1112.   will not be resent, and we'll go into a cycle of timing out and
  1113.   retransmitting up to the retry limit.  - fdc 2007/03/02
  1114. */
  1115.     if (wslotn == 1            /* (not wslots!) */
  1116. #ifdef STREAMING
  1117.     && !streaming            /* But not when streaming */
  1118. #endif /* STREAMING */
  1119.     ) {
  1120.     debug(F100,"input about to flush","",0);
  1121.     ttflui();        /* Got what we want, clear input buffer. */
  1122.     }
  1123. #ifndef NEWDPL
  1124.     if (!nakstate)            /* When sending */
  1125.       rcalcpsz();            /* recalculate size every packet */
  1126. #endif /* NEWDPL */
  1127.     if (type == 'E')
  1128.       xitsta |= (what ? what : 1);    /* Remember what failed. */
  1129.     debug(F101,"input winlo","",winlo);
  1130.     debug(F101,"input rsn","",rsn);
  1131.     debug(F000,"input returning type","",type);
  1132.     return(rcvtyp = type);        /* Success, return packet type. */
  1133. }
  1134.  
  1135. #ifdef PARSENSE
  1136. /*  P A R C H K  --  Check if Kermit packet has parity  */
  1137.  
  1138. /*
  1139.   Call with s = pointer to packet, start = packet start character, n = length.
  1140.   Returns 0 if packet has no parity, -1 on error, or, if packet has parity:
  1141.     'e' for even, 'o' for odd, 'm' for mark.  Space parity cannot be sensed.
  1142.   So a return value of 0 really means either space or none.
  1143.   Returns -2 if parity has already been checked during this protocol operation.
  1144. */
  1145. int
  1146. #ifdef CK_ANSIC
  1147. parchk(CHAR *s, CHAR start, int n)
  1148. #else
  1149. parchk(s,start,n) CHAR *s, start; int n;
  1150. #endif /* CK_ANSIC */
  1151. /* parchk */ {
  1152.     CHAR s0, s1, s2, s3;
  1153.  
  1154.     debug(F101,"parchk n","",n);
  1155.     debug(F101,"parchk start","",start);
  1156.  
  1157.     s0 = s[0] & 0x7f;            /* Mark field (usually Ctrl-A) */
  1158.  
  1159.     if (s0 != start || n < 5) return(-1); /* Not a valid packet */
  1160.  
  1161. /* Look at packet control fields, which never have 8th bit set */
  1162. /* First check for no parity, most common case. */
  1163.  
  1164.     if (((s[0] | s[1] | s[2] | s[3]) & 0x80) == 0)
  1165.       return(0);            /* No parity or space parity */
  1166.  
  1167. /* Check for mark parity */
  1168.  
  1169.     if (((s[0] & s[1] & s[2] & s[3]) & 0x80) == 0x80)
  1170.       return('m');            /* Mark parity */
  1171.  
  1172. /* Packet has some kind of parity */
  1173. /* Make 7-bit copies of control fields */
  1174.  
  1175.     s1 = s[1] & 0x7f;            /* LEN */
  1176.     s2 = s[2] & 0x7f;            /* SEQ */
  1177.     s3 = s[3] & 0x7f;            /* TYPE */
  1178.  
  1179. /* Check for even parity */
  1180.  
  1181.     if ((s[0] == p_tbl[s0]) &&
  1182.         (s[1] == p_tbl[s1]) &&
  1183.         (s[2] == p_tbl[s2]) &&
  1184.     (s[3] == p_tbl[s3]))
  1185.       return('e');
  1186.  
  1187. /* Check for odd parity */
  1188.  
  1189.     if ((s[0] != p_tbl[s0]) &&
  1190.         (s[1] != p_tbl[s1]) &&
  1191.         (s[2] != p_tbl[s2]) &&
  1192.     (s[3] != p_tbl[s3]))
  1193.       return('o');
  1194.  
  1195. /* Otherwise it's probably line noise.  Let checksum calculation catch it. */
  1196.  
  1197.     return(-1);
  1198. }
  1199. #endif /* PARSENSE */
  1200.  
  1201. /*
  1202.   Check to make sure timeout intervals are long enough to allow maximum
  1203.   length packets to get through before the timer goes off.  If not, the
  1204.   timeout interval is adjusted upwards.
  1205.  
  1206.   This routine is called at the beginning of a transaction, before we
  1207.   know anything about the delay characteristics of the line.  It works
  1208.   only for serial communication devices; it trusts the speed reported by
  1209.   the operating system.
  1210.  
  1211.   Call with a timout interval.  Returns it, adjusted if necessary.
  1212. */
  1213. int
  1214. chktimo(timo,flag) int timo, flag; {
  1215.     long cps, z; int x, y;
  1216. #ifdef STREAMING
  1217.     debug(F101,"chktimo streaming","",streaming);
  1218.     if (streaming)
  1219.       return(0);
  1220. #endif /* STREAMING */
  1221.  
  1222.     debug(F101,"chktimo timo","",timo); /* Timeout before adjustment */
  1223.     debug(F101,"chktimo flag","",flag);
  1224.  
  1225.     if (flag)                /* Don't change timeout if user */
  1226.       return(timo);            /* gave SET SEND TIMEOUT command. */
  1227.     debug(F101,"chktimo spmax","",spmax);
  1228.     debug(F101,"chktimo urpsiz","",urpsiz);
  1229.  
  1230.     if (!network) {            /* On serial connections... */
  1231.     speed = ttgspd();        /* Get current speed. */
  1232.     if (speed > 0L) {
  1233.         cps = speed / 10L;        /* Convert to chars per second */
  1234.         if (cps > 0L) {
  1235.         long plen;        /* Maximum of send and rcv pkt size */
  1236.         z = cps * (long) timo;    /* Chars per timeout interval */
  1237.         z -= z / 10L;        /* Less 10 percent */
  1238.         plen = spmax;
  1239.         if (urpsiz > spmax) plen = urpsiz;
  1240.         debug(F101,"chktimo plen","",plen);
  1241.         if (z < plen) {        /* Compare with packet size */
  1242.             x = (int) ((long) plen / cps); /* Adjust if necessary */
  1243.             y = x / 10;        /* Add 10 percent for safety */
  1244.             if (y < 2) y = 2;    /* Or 2 seconds, whichever is more */
  1245.             x += y;
  1246.             if (x > timo)    /* If this is greater than current */
  1247.               timo = x;        /* timeout, change the timeout */
  1248.             debug(F101,"chktimo new timo","",timo);
  1249.         }
  1250.         }
  1251.     }
  1252.     }
  1253.     return(timo);
  1254. }
  1255.  
  1256. /*  S P A C K  --  Construct and send a packet  */
  1257.  
  1258. /*
  1259.   spack() sends a packet of the given type, sequence number n, with len data
  1260.   characters pointed to by d, in either a regular or extended- length packet,
  1261.   depending on len.  Returns the number of bytes actually sent, or else -1
  1262.   upon failure.  Uses global npad, padch, mystch, bctu, data.  Leaves packet
  1263.   fully built and null-terminated for later retransmission by resend().
  1264.   Updates global sndpktl (send-packet length).
  1265.  
  1266.   NOTE: The global pointer "data" is assumed to point into the 7th position
  1267.   of a character array (presumably in packet buffer for the current packet).
  1268.   It was used by getpkt() to build the packet data field.  spack() fills in
  1269.   the header to the left of the data pointer (the data pointer is defined
  1270.   in getsbuf() in ckcfn3.c).  If the address "d" is the same as "data", then
  1271.   the packet's data field has been built "in place" and need not be copied.
  1272. */
  1273. int
  1274. #ifdef CK_ANSIC
  1275. spack(char pkttyp, int n, int len, CHAR *d)
  1276. #else
  1277. spack(pkttyp,n,len,d) char pkttyp; int n, len; CHAR *d;
  1278. #endif /* CK_ANSIC */
  1279. /* spack */ {
  1280.     register int i;
  1281.     int ix, j, k, x, lp, longpkt, copy, loglen;
  1282.  
  1283. #ifdef GFTIMER
  1284.     CKFLOAT t1 = 0.0, t2 = 0.0;
  1285. #endif /* GFTIMER */
  1286.  
  1287.     register CHAR *cp, *mydata;
  1288.     unsigned crc;
  1289.  
  1290.     copy = (d != data);            /* Flag whether data must be copied  */
  1291.  
  1292. #ifdef DEBUG
  1293.     if (deblog) {            /* Save lots of function calls! */
  1294.     debug(F101,"spack n","",n);
  1295. #ifdef COMMENT
  1296.     if (pkttyp != 'D') {        /* Data packets would be too long */
  1297.         debug(F111,"spack data",data,data);
  1298.         debug(F111,"spack d",d,d);
  1299.     }
  1300. #endif    /* COMMENT */
  1301.     debug(F101,"spack len","",len);
  1302.     debug(F101,"spack copy","",copy);
  1303.     }
  1304. #endif /* DEBUG */
  1305.  
  1306.     longpkt = (len + bctl + 2) > 94;    /* Decide whether it's a long packet */
  1307.     mydata = data - 7 + (longpkt ? 0 : 3); /* Starting position of header */
  1308.     k = sseqtbl[n];            /* Packet structure info for pkt n */
  1309. #ifdef COMMENT
  1310. #ifdef DEBUG
  1311.     if (deblog) {            /* Save 2 more function calls... */
  1312.     debug(F101,"spack mydata","",mydata);
  1313.     debug(F101,"spack sseqtbl[n]","",k);
  1314.     if (k < 0) {
  1315. #ifdef STREAMING
  1316.         if (!streaming)
  1317. #endif /* STREAMING */
  1318.           debug(F101,"spack sending packet out of window","",n);
  1319.     }
  1320.     }
  1321. #endif /* DEBUG */
  1322. #endif    /* COMMENT */
  1323.     if (k > -1) {
  1324.     s_pkt[k].pk_adr = mydata;    /* Remember address of packet. */
  1325.     s_pkt[k].pk_seq = n;        /* Record sequence number */
  1326.     s_pkt[k].pk_typ = pkttyp;    /* Record packet type */
  1327.     }
  1328.     spktl = 0;                /* Initialize length of this packet */
  1329.     i = 0;                /* and position in packet. */
  1330.  
  1331. /* Now fill the packet */
  1332.  
  1333.     mydata[i++] = mystch;        /* MARK */
  1334.     lp = i++;                /* Position of LEN, fill in later */
  1335.  
  1336.     mydata[i++] = tochar(n);        /* SEQ field */
  1337.     mydata[i++] = pkttyp;        /* TYPE field */
  1338.     j = len + bctl;            /* Length of data + block check */
  1339.     if (longpkt) {            /* Long packet? */
  1340.     int x;                /* Yes, work around SCO Xenix/286 */
  1341. #ifdef CKTUNING
  1342.     unsigned int chk;
  1343. #endif /* CKTUNING */
  1344.     x = j / 95;            /* compiler bug... */
  1345.         mydata[lp] = tochar(0);        /* Set LEN to zero */
  1346.         mydata[i++] = tochar(x);    /* Extended length, high byte */
  1347.         mydata[i++] = tochar(j % 95);    /* Extended length, low byte */
  1348. #ifdef CKTUNING
  1349.         /* Header checksum - skip the function calls and loops */
  1350.       chk = (unsigned) mydata[lp]   +
  1351.             (unsigned) mydata[lp+1] +
  1352.             (unsigned) mydata[lp+2] +
  1353.         (unsigned) mydata[lp+3] +
  1354.         (unsigned) mydata[lp+4] ;
  1355.     mydata[i++] = tochar((CHAR) ((((chk & 0300) >> 6) + chk) & 077));
  1356. #else
  1357.         mydata[i] = '\0';        /* Terminate for header checksum */
  1358.         mydata[i++] = tochar(chk1(mydata+lp,5));
  1359. #endif /* CKTUNING */
  1360.     } else mydata[lp] = tochar(j+2);    /* Normal LEN */
  1361. /*
  1362.   When sending a file, the data is already in the right place.  If it weren't,
  1363.   it might make sense to optimize this section by using memcpy or bcopy
  1364.   (neither of which are portable), but only if our packets were rather long.
  1365.   When receiving, we're only sending ACKs so it doesn't matter.  So count the
  1366.   following loop as a sleeping dog.
  1367. */
  1368.     if (copy)                /* Data field built in place? */
  1369.       for ( ; len--; i++) mydata[i] = *d++; /* No, must copy. */
  1370.     else                /* Otherwise, */
  1371.       i += len;                /* Just skip past data field. */
  1372.     mydata[i] = '\0';            /* Null-terminate for checksum calc. */
  1373.  
  1374.     switch (bctu) {            /* Block check */
  1375.         case 1:                /* 1 = 6-bit chksum */
  1376.         ix = i - lp;        /* Avoid "order of operation" error */
  1377.         mydata[i++] = tochar(chk1(mydata+lp,ix));
  1378.         break;
  1379.     case 2:                /* 2 = 12-bit chksum */
  1380.         j = chk2(mydata+lp,i-lp);
  1381.         mydata[i++] = (unsigned)tochar((j >> 6) & 077);
  1382.            mydata[i++] = (unsigned)tochar(j & 077);
  1383.         break;
  1384.         case 3:                /* 3 = 16-bit CRC */
  1385.         crc = chk3(mydata+lp,i-lp);
  1386.         mydata[i++] = (unsigned)tochar(((crc & 0170000)) >> 12);
  1387.         mydata[i++] = (unsigned)tochar((crc >> 6) & 077);
  1388.         mydata[i++] = (unsigned)tochar(crc & 077);
  1389.         break;
  1390.     case 4:                /* 2 = 12-bit chksum, blank-free */
  1391.         j = chk2(mydata+lp,i-lp);
  1392.         mydata[i++] =
  1393.           (unsigned)(tochar((unsigned)(((j >> 6) & 077) + 1)));
  1394.            mydata[i++] = (unsigned)(tochar((unsigned)((j & 077) + 1)));
  1395.         break;
  1396.     }
  1397.     loglen = i;
  1398.     mydata[i++] = seol;            /* End of line (packet terminator) */
  1399. #ifdef TCPSOCKET
  1400. /*
  1401.   If TELNET connection and packet terminator is carriage return,
  1402.   we must stuff either LF or NUL, according to SET TELNET NEWLINE-MODE
  1403.   (tn_nlm), to meet the TELNET NVT specification, unless user said RAW.
  1404.  
  1405.   If NEWLINE-MODE is set to LF instead of CR, we still send CR-NUL
  1406.   on a NVT connection and CR on a binary connection.
  1407. */
  1408.     if (
  1409. #ifdef STREAMING
  1410.     !dontsend &&
  1411. #endif /* STREAMING */
  1412.     ((network && ttnproto == NP_TELNET) || (!local && sstelnet))
  1413.     && seol == CR) {
  1414.         switch (TELOPT_ME(TELOPT_BINARY) ? tn_b_nlm : tn_nlm) {
  1415.       case TNL_CR:            /* NVT or BINARY */
  1416.         break;
  1417.       case TNL_CRNUL:
  1418.         mydata[i++] = NUL;
  1419.         break;
  1420.       case TNL_CRLF:
  1421.         mydata[i++] = LF;
  1422.         break;
  1423.     }
  1424.     }
  1425. #endif /* TCPSOCKET */
  1426.     mydata[i] = '\0';            /* Terminate string */
  1427.     if (
  1428. #ifdef STREAMING
  1429.     !dontsend &&
  1430. #endif /* STREAMING */
  1431.     pktlog
  1432.     )                /* Save a function call! */
  1433.       logpkt('s',n,mydata,loglen);    /* Log the packet */
  1434.  
  1435.     /* (PWP) add the parity quickly at the end */
  1436.     if (parity) {
  1437.     switch (parity) {
  1438.       case 'e':            /* Even */
  1439.         for (cp = &mydata[i-1]; cp >= mydata; cp--)
  1440.           *cp = p_tbl[*cp];
  1441.         break;
  1442.       case 'm':            /* Mark */
  1443.         for (cp = &mydata[i-1]; cp >= mydata; cp--)
  1444.           *cp |= 128;
  1445.         break;
  1446.       case 'o':            /* Odd */
  1447.         for (cp = &mydata[i-1]; cp >= mydata; cp--)
  1448.           *cp = p_tbl[*cp] ^ 128;
  1449.         break;
  1450.       case 's':            /* Space */
  1451.         for (cp = &mydata[i-1]; cp >= mydata; cp--)
  1452.           *cp &= 127;
  1453.         break;
  1454.     }
  1455.     }
  1456.     if (pktpaus) msleep(pktpaus);    /* Pause if requested */
  1457.     x = 0;
  1458.  
  1459.     if (npad) {
  1460. #ifdef STREAMING
  1461.     if (dontsend)
  1462.       x = 0;
  1463.     else
  1464. #endif /* STREAMING */
  1465.       x = ttol(padbuf,npad);    /* Send any padding */
  1466.     }
  1467.     if (x > -1) {
  1468. #ifdef CK_TIMERS
  1469.     if (timint > 0) {
  1470.         if (pkttyp == 'N')
  1471.           srttbl[n > 0 ? n-1 : 63] = gtimer();
  1472.         else
  1473.           srttbl[n] = gtimer();
  1474.     }
  1475. #endif /* CK_TIMERS */
  1476.     spktl = i;            /* Remember packet length */
  1477.     if (k > -1)
  1478.       s_pkt[k].pk_len = spktl;    /* also in packet info structure */
  1479.  
  1480. #ifdef DEBUG
  1481. #ifdef GFTIMER
  1482. /*
  1483.   This code shows (in the debug log) how long it takes write() to execute.
  1484.   Sometimes on a congested TCP connection, it can surprise you -- 90 seconds
  1485.   or more...
  1486. */
  1487.     if (
  1488. #ifdef STREAMING
  1489.         !dontsend &&
  1490. #endif /* STREAMING */
  1491.         deblog
  1492.         )
  1493.       t1 = gftimer();
  1494. #endif /* GFTIMER */
  1495. #endif /* DEBUG */
  1496.  
  1497. #ifdef STREAMING
  1498.     if (dontsend) {
  1499.         debug(F000,"STREAMING spack skipping","",pkttyp);
  1500.         x = 0;
  1501.     } else
  1502. #endif /* STREAMING */
  1503.     x = ttol(mydata,spktl);        /* Send the packet */
  1504.     }
  1505. #ifdef STREAMING
  1506.     if (!dontsend) {
  1507. #endif /* STREAMING */
  1508.     debug(F101,"spack spktl","",spktl);
  1509.     debug(F101,"spack ttol returns","",x);
  1510.     if (x < 0) {            /* Failed. */
  1511.         if (local && x < -1) {
  1512.         xxscreen(SCR_ST,ST_ERR,0L,"FAILED: Connection lost");
  1513.         /* We can't send an E packet because the connection is lost. */
  1514.         epktsent = 1;        /* So pretend we sent one. */
  1515.         fatalio = 1;        /* Remember we got a fatal i/o error */
  1516.         dologend();
  1517.         ckstrncpy((char *)epktmsg,"Connection lost",PKTMSGLEN);
  1518.         }
  1519.         return(x);
  1520.     }
  1521.     if (spktl > maxsend)        /* Keep track of longest packet sent */
  1522.       maxsend = spktl;
  1523. #ifdef DEBUG
  1524. #ifdef GFTIMER
  1525.     if (deblog)  {            /* Log elapsed time for write() */
  1526.         t2 = gftimer();
  1527.         debug(F101,"spack ttol msec","",(long)((t2-t1)*1000.0));
  1528.     }
  1529. #endif /* GFTIMER */
  1530. #endif /* DEBUG */
  1531. #ifdef STREAMING
  1532.     }
  1533. #endif /* STREAMING */
  1534.  
  1535.     sndtyp = pkttyp;            /* Remember packet type for echos */
  1536. #ifdef STREAMING
  1537.     if (!dontsend) {            /* If really sent, */
  1538.     spackets++;            /* count it. */
  1539.     flco += spktl;            /* Count the characters */
  1540.     tlco += spktl;            /* for statistics... */
  1541. #ifdef DEBUG
  1542.     if (deblog) {            /* Save two function calls! */
  1543.         dumpsbuf();            /* Dump send buffers to debug log */
  1544.         debug(F111,"spack calling screen, mydata=",mydata,n);
  1545.     }
  1546. #endif /* DEBUG */
  1547.     }
  1548. #endif /* STREAMING */
  1549.     if (local) {
  1550.     int x = 0;
  1551.     if (fdispla != XYFD_N) x = 1;
  1552.     if ((fdispla == XYFD_B) && (pkttyp == 'D' || pkttyp == 'Y')) x = 0;
  1553.     if (x)
  1554.       xxscreen(SCR_PT,pkttyp,(long)n,(char *)mydata); /* Update screen */
  1555.     }
  1556.     return(spktl);            /* Return length */
  1557. }
  1558.  
  1559. /*  C H K 1  --  Compute a type-1 Kermit 6-bit checksum.  */
  1560.  
  1561. int
  1562. chk1(pkt,len) register CHAR *pkt; register int len; {
  1563.     register unsigned int chk;
  1564. #ifdef CKTUNING
  1565. #ifdef COMMENT
  1566.     register unsigned int m;        /* Avoid function call */
  1567.     m = (parity) ? 0177 : 0377;
  1568.     for (chk = 0; len-- > 0; pkt++)
  1569.       chk += *pkt & m;
  1570. #else
  1571.     chk = 0;
  1572.     while (len-- > 0) chk += (unsigned) *pkt++;
  1573. #endif /* COMMENT */
  1574. #else
  1575.     chk = chk2(pkt,len);
  1576. #endif /* CKTUNING */
  1577.     chk = (((chk & 0300) >> 6) + chk) & 077;
  1578.     debug(F101,"chk1","",chk);
  1579.     return((int) chk);
  1580. }
  1581.  
  1582. /*  C H K 2  --  Compute the numeric sum of all the bytes in the packet.  */
  1583.  
  1584. unsigned int
  1585. chk2(pkt,len) register CHAR *pkt; register int len; {
  1586.     register long chk;
  1587. #ifdef COMMENT
  1588.     register unsigned int m;
  1589.     m = (parity) ? 0177 : 0377;
  1590.     for (chk = 0; len-- > 0; pkt++)
  1591.       chk += *pkt & m;
  1592. #else
  1593.     /* Parity has already been stripped */
  1594.     chk = 0L;
  1595.     while (len-- > 0) chk += (unsigned) *pkt++;
  1596. #endif /* COMMENT */
  1597.     debug(F101,"chk2","",(unsigned int) (chk & 07777));
  1598.     return((unsigned int) (chk & 07777));
  1599. }
  1600.  
  1601. /*  C H K 3  --  Compute a type-3 Kermit block check.  */
  1602. /*
  1603.  Calculate the 16-bit CRC-CCITT of a null-terminated string using a lookup
  1604.  table.  Assumes the argument string contains no embedded nulls.
  1605. */
  1606. #ifdef COMMENT
  1607. unsigned int
  1608. chk3(pkt,parity,len) register CHAR *pkt; int parity; register int len; {
  1609.     register long c, crc;
  1610.     register unsigned int m;
  1611.     m = (parity) ? 0177 : 0377;
  1612.     for (crc = 0; len-- > 0; pkt++) {
  1613.     c = crc ^ (long)(*pkt & m);
  1614.     crc = (crc >> 8) ^ (crcta[(c & 0xF0) >> 4] ^ crctb[c & 0x0F]);
  1615.     }
  1616.     return((unsigned int) (crc & 0xFFFF));
  1617. }
  1618. #else
  1619. unsigned int
  1620. chk3(pkt,len) register CHAR *pkt; register int len; {
  1621.     register long c, crc;
  1622.     for (crc = 0; len-- > 0; pkt++) {
  1623.     c = crc ^ (long)(*pkt);
  1624.     crc = (crc >> 8) ^ (crcta[(c & 0xF0) >> 4] ^ crctb[c & 0x0F]);
  1625.     }
  1626.     debug(F101,"chk3","",(unsigned int) (crc & 0xFFFF));
  1627.     return((unsigned int) (crc & 0xFFFF));
  1628. }
  1629. #endif /* COMMENT */
  1630.  
  1631. /*  N X T P K T  --  Next Packet  */
  1632. /*
  1633.   Get packet number of next packet to send and allocate a buffer for it.
  1634.   Returns:
  1635.     0 on success, with global pktnum set to the packet number;
  1636.    -1 on failure to allocate buffer (fatal);
  1637.    -2 if resulting packet number is outside the current window.
  1638. */
  1639. int
  1640. nxtpkt() {                /* Called by file sender */
  1641.     int j, n, x;
  1642.  
  1643.     debug(F101,"nxtpkt pktnum","",pktnum);
  1644.     debug(F101,"nxtpkt winlo ","",winlo);
  1645.     n = (pktnum + 1) % 64;        /* Increment packet number mod 64 */
  1646.     debug(F101,"nxtpkt n","",n);
  1647. #ifdef STREAMING
  1648.     if (!streaming) {
  1649.     x = chkwin(n,winlo,wslots);    /* Don't exceed window boundary */
  1650.     debug(F101,"nxtpkt chkwin","",x);
  1651.     if (x)
  1652.       return(-2);
  1653.     j = getsbuf(n);            /* Get a buffer for packet n */
  1654.     if (j < 0) {
  1655.         debug(F101,"nxtpkt getsbuf failure","",j);
  1656.         return(-1);
  1657.     }
  1658.     }
  1659. #endif /* STREAMING */
  1660.     pktnum = n;
  1661.     return(0);
  1662. }
  1663.  
  1664. /* Functions for sending ACKs and NAKs */
  1665.  
  1666. /* Note, we should only ACK the packet at window-low (winlo) */
  1667. /* However, if an old packet arrives again (e.g. because the ACK we sent */
  1668. /* earlier was lost), we ACK it again. */
  1669.  
  1670. int
  1671. ack() {                    /* Acknowledge the current packet. */
  1672.     return(ackns(winlo,(CHAR *)""));
  1673. }
  1674.  
  1675. #ifdef STREAMING
  1676. int
  1677. fastack() {                /* Acknowledge packet n */
  1678.     int j, k, n, x;
  1679.     n = winlo;
  1680.  
  1681.     k = rseqtbl[n];            /* First find received packet n. */
  1682.     debug(F101,"STREAMING fastack k","",k);
  1683.     freesbuf(n);            /* Free current send-buffer, if any */
  1684.     if ((j = getsbuf(n)) < 0) {
  1685.     /* This can happen if we have to re-ACK an old packet that has */
  1686.         /* already left the window.  It does no harm. */
  1687.     debug(F101,"STREAMING fastack can't getsbuf","",n);
  1688.     }
  1689.     dontsend = 1;
  1690.     x = spack('Y',n,0,(CHAR *)"");    /* Now send it (but not really) */
  1691.     dontsend = 0;
  1692.     if (x < 0) return(x);
  1693.     debug(F101,"STREAMING fastack x","",x);
  1694.     if (k > -1)
  1695.       freerbuf(k);            /* don't need it any more */
  1696.     if (j > -1)
  1697.       freesbuf(j);            /* and don't need to keep ACK either */
  1698.     winlo = (winlo + 1) % 64;
  1699.     return(0);
  1700. }
  1701. #endif /* STREAMING */
  1702.  
  1703. int
  1704. ackns(n,s) int n; CHAR *s; {        /* Acknowledge packet n */
  1705.     int j, k, x;
  1706.     debug(F111,"ackns",s,n);
  1707.  
  1708.     k = rseqtbl[n];            /* First find received packet n. */
  1709.     debug(F101,"ackns k","",k);
  1710.     freesbuf(n);            /* Free current send-buffer, if any */
  1711.     if ((j = getsbuf(n)) < 0) {
  1712.     /* This can happen if we have to re-ACK an old packet that has */
  1713.         /* already left the window.  It does no harm. */
  1714.     debug(F101,"ackns can't getsbuf","",n);
  1715.     }
  1716.     x = spack('Y',n,(int)strlen((char *)s),s); /* Now send it. */
  1717.     if (x < 0) return(x);
  1718.     debug(F101,"ackns winlo","",winlo);
  1719.     debug(F101,"ackns n","",n);
  1720.     if (n == winlo) {            /* If we're acking winlo */
  1721.     if (k > -1)
  1722.       freerbuf(k);            /* don't need it any more */
  1723.     if (j > -1)
  1724.       freesbuf(j);            /* and don't need to keep ACK either */
  1725.     winlo = (winlo + 1) % 64;
  1726.     }
  1727.     return(0);
  1728. }
  1729.  
  1730. int
  1731. ackn(n) int n; {            /* Send ACK for packet number n */
  1732.     return(ackns(n,(CHAR *)""));
  1733. }
  1734.  
  1735. int
  1736. ack1(s) CHAR *s; {            /* Send an ACK with data. */
  1737.     if (!s) s = (CHAR *)"";
  1738.     debug(F110,"ack1",(char *)s,0);
  1739.     return(ackns(winlo,s));
  1740. }
  1741.  
  1742. /* N A C K  --   Send a Negative ACKnowledgment. */
  1743. /*
  1744.  Call with the packet number, n, to be NAK'd.
  1745.  Returns -1 if that packet has been NAK'd too many times, otherwise 0.
  1746.  Btw, it is not right to return 0 under error conditions.  This is
  1747.  done because the -1 code is used for cancelling the file transfer.
  1748.  More work is needed here.
  1749. */
  1750. int
  1751. nack(n) int n; {
  1752.     int i, x;
  1753.  
  1754.     if (n < 0 || n > 63) {
  1755.     debug(F101,"nack bad pkt num","",n);
  1756.     return(0);
  1757.     } else debug(F101,"nack","",n);
  1758.     if ((i = sseqtbl[n]) < 0) {        /* If necessary */
  1759.     if (getsbuf(n) < 0) {        /* get a buffer for this NAK */
  1760.         debug(F101,"nack can't getsbuf","",n);
  1761.         return(0);
  1762.     } else i = sseqtbl[n];        /* New slot number */
  1763.     }
  1764.     if (maxtry > 0 && s_pkt[i].pk_rtr++ > maxtry) /* How many? */
  1765.       return(-1);            /* Too many... */
  1766.  
  1767. /* Note, don't free this buffer.  Eventually an ACK will come, and that */
  1768. /* will set it free.  If not, well, it's back to ground zero anyway...  */
  1769.  
  1770.     x = spack('N',n,0,(CHAR *) "");    /* NAKs never have data. */
  1771.     return(x);
  1772. }
  1773.  
  1774. #ifndef NEWDPL                /* This routine no longer used */
  1775. /*
  1776.  * (PWP) recalculate the optimal packet length in the face of errors.
  1777.  * This is a modified version of the algorithm by John Chandler in Kermit/370,
  1778.  * see "Dynamic Packet Size Control", Kermit News, V2 #1, June 1988.
  1779.  *
  1780.  * This implementation minimizes the total overhead equation, which is
  1781.  *
  1782.  *   Total chars = file_chars + (header_len * num_packs)
  1783.  *                            + (errors * (header_len + packet_len))
  1784.  *
  1785.  * Differentiate with respect to number of chars, solve for packet_len, get:
  1786.  *
  1787.  *   packet_len = sqrt (file_chars * header_len / errors)
  1788.  */
  1789.  
  1790. /*
  1791.  (FDC) New super-simple algorithm.  If there was an error in the most recent
  1792.  packet exchange, cut the send-packet size in half, down to a minimum of 20.
  1793.  If there was no error, increase the size by 5/4, up to the maximum negotiated
  1794.  length.  Seems to be much more responsive than previous algorithm, which took
  1795.  forever to recover the original packet length, and it also went crazy under
  1796.  certain conditions.
  1797.  
  1798.  Here's another idea for packet length resizing that keeps a history of the
  1799.  last n packets.  Push a 1 into the left end of an n-bit shift register if the
  1800.  current packet is good, otherwise push a zero.  The current n-bit value, w, of
  1801.  this register is a weighted sum of the noise hits for the last n packets, with
  1802.  the most recent weighing the most.  The current packet length is some function
  1803.  of w and the negotiated packet length, like:
  1804.  
  1805.    (2^n - w) / (2^n) * (negotiated length)
  1806.  
  1807.  If the present resizing method causes problems, think about this one a little
  1808.  more.
  1809. */
  1810. VOID
  1811. rcalcpsz() {
  1812.  
  1813. #ifdef COMMENT
  1814. /* Old way */
  1815.     register long x, q;
  1816.     if (numerrs == 0) return;        /* bounds check just in case */
  1817.  
  1818.     /* overhead on a data packet is npad+5+bctr, plus 3 if extended packet */
  1819.     /* an ACK is 5+bctr */
  1820.  
  1821.     /* first set x = per packet overhead */
  1822.     if (wslots > 1)            /* Sliding windows */
  1823.       x = (long) (npad+5+bctr);        /* packet only, don't count ack */
  1824.     else                /* Stop-n-wait */
  1825.       x = (long) (npad+5+3+bctr+5+bctr); /* count packet and ack. */
  1826.  
  1827.     /* then set x = packet length ** 2 */
  1828.     x = x * ( ffc / (CK_OFF_T) numerrs); /* careful of overflow */
  1829.  
  1830.     /* calculate the long integer sqrt(x) quickly */
  1831.     q = 500;
  1832.     q = (q + x/q) >> 1;
  1833.     q = (q + x/q) >> 1;
  1834.     q = (q + x/q) >> 1;
  1835.     q = (q + x/q) >> 1;        /* should converge in about 4 steps */
  1836.     if ((q > 94) && (q < 130))    /* break-even point for long packets */
  1837.       q = 94;
  1838.     if (q > spmax) q = spmax;    /* maximum bounds */
  1839.     if (q < 10) q = 10;        /* minimum bounds */
  1840.     spsiz = q;            /* set new send packet size */
  1841.     debug(F101,"rcalcpsiz","",q);
  1842. #else
  1843. /* New way */
  1844.     debug(F101,"rcalcpsiz numerrs","",numerrs);
  1845.     debug(F101,"rcalcpsiz spsiz","",spsiz);
  1846.     if (spackets < 3) {
  1847.     numerrs = 0;
  1848.     return;
  1849.     }
  1850.     if (numerrs)
  1851.       spsiz = spsiz / 2;
  1852.     else
  1853.       spsiz = (spsiz / 4) * 5;
  1854.     if (spsiz < 20) spsiz = 20;
  1855.     if (spsiz > spmax) spsiz = spmax;
  1856.     debug(F101,"rcalcpsiz new spsiz","",spsiz);
  1857.     numerrs = 0;
  1858. #endif /* COMMENT */
  1859. }
  1860. #endif /* NEWDPL */
  1861.  
  1862. /*  R E S E N D  --  Retransmit packet n.  */
  1863.  
  1864. /*
  1865.   Returns 0 or positive on success (the number of retries for packet n).
  1866.   On failure, returns a negative number, and an error message is placed
  1867.   in recpkt.
  1868. */
  1869. int
  1870. resend(n) int n; {            /* Send packet n again. */
  1871.     int j, k, x;
  1872. #ifdef GFTIMER
  1873.     CKFLOAT t1 = 0.0, t2 = 0.0;
  1874. #endif /* GFTIMER */
  1875.  
  1876.     debug(F101,"resend seq","",n);
  1877.  
  1878.     k = chkwin(n,winlo,wslots);        /* See if packet in current window */
  1879.     j = -1;                /* Assume it's lost */
  1880.     if (k == 0) j = sseqtbl[n];        /* See if we still have a copy of it */
  1881.     if (k != 0 || j < 0) {        /* If not.... */
  1882.     if (nakstate && k == 1) {
  1883. /*
  1884.   Packet n is in the previous window and we are the file receiver.
  1885.   We already sent the ACK and deallocated its buffer so we can't just
  1886.   retransmit the ACK.  Rather than give up, we try some tricks...
  1887. */
  1888.         if (n == 0 && spackets < 63 && myinit[0]) { /* ACK to Send-Init */
  1889. /*
  1890.   If the packet number is 0, and we're at the beginning of a protocol
  1891.   operation (spackets < 63), then we have to resend the ACK to an I or S
  1892.   packet, complete with parameters in the data field.  So we take a chance and
  1893.   send a copy of the parameters in an ACK packet with block check type 1.
  1894.   (Or 3 if SET BLOCK 5.)
  1895. */
  1896.         if (bctf) {        /* Force Type 3 on all packets? */
  1897.            x = spack('Y',0,(int)strlen((char *)myinit),(CHAR *)myinit);
  1898.             if (x < 0) return(x);
  1899.             logpkt('#',n,(CHAR *)"<reconstructed>",0); /* Log it */
  1900.         } else {        /* Regular Kermit protocol */
  1901.             int bctlsav;    /* Temporary storage */
  1902.             int bctusav;
  1903.             bctlsav = bctl;    /* Save current block check length */
  1904.             bctusav = bctu;    /* and type */
  1905.             bctu = bctl = 1;    /* Set block check to 1 */
  1906.            x = spack('Y',0,(int)strlen((char *)myinit),(CHAR *)myinit);
  1907.             if (x < 0) return(x);
  1908.             logpkt('#',n,(CHAR *)"<reconstructed>",0); /* Log it */
  1909.             bctu = bctusav;    /* Restore block check type */
  1910.             bctl = bctlsav;    /* and length */
  1911.         }
  1912.         } else {            /* Not the first packet */
  1913. /*
  1914.   It's not the first packet of the protocol operation.  It's some other packet
  1915.   that we have already ACK'd and forgotten about.  So we take a chance and
  1916.   send an empty ACK using the current block-check type.  Usually this will
  1917.   work out OK (like when acking Data packets), and no great harm will be done
  1918.   if it was some other kind of packet (F, etc).  If we are requesting an
  1919.   interruption of the file transfer, the flags are still set, so we'll catch
  1920.   up on the next packet.
  1921. */
  1922.         x = spack('Y',n,0,(CHAR *) "");
  1923.         if (x < 0) return(x);
  1924.         }
  1925.         retrans++;
  1926.         xxscreen(SCR_PT,'%',(long)pktnum,"Retransmission");
  1927.         return(0);
  1928.     } else {
  1929. /*
  1930.   Packet number is not in current or previous window.  We seem to hit this
  1931.   code occasionally at the beginning of a transaction, for apparently no good
  1932.   reason.  Let's just log it for debugging, send nothing, and try to proceed
  1933.   with the protocol rather than killing it.
  1934. */
  1935.         debug(F101,"resend PKT NOT IN WINDOW","",n);
  1936.         debug(F101,"resend k","",k);
  1937.         return(0);
  1938.     }
  1939.     }
  1940.  
  1941. /* OK, it's in the window and it's not lost. */
  1942.  
  1943.     debug(F101,"resend pktinfo index","",k);
  1944.  
  1945.     if (maxtry > 0 && s_pkt[j].pk_rtr++ > maxtry) { /* Over retry limit */
  1946.     xitsta |= what;
  1947.     return(-1);
  1948.     }
  1949.     debug(F101,"resend retry","",s_pkt[j].pk_rtr); /* OK so far */
  1950.     dumpsbuf();                /* (debugging) */
  1951.     if (s_pkt[j].pk_typ == ' ') {    /* Incompletely formed packet */
  1952.     if (nakstate) {            /* (This shouldn't happen any more) */
  1953.         nack(n);
  1954.         retrans++;
  1955.         xxscreen(SCR_PT,'%',(long)pktnum,"(resend)");
  1956.         return(s_pkt[j].pk_rtr);
  1957.     } else {            /* No packet to resend! */
  1958. #ifdef COMMENT
  1959. /*
  1960.   This happened (once) while sending a file with 2 window slots and typing
  1961.   X to the sender to cancel the file.  But since we're cancelling anyway,
  1962.   there's no need to give a scary message.
  1963. */
  1964.         sprintf((char *)epktmsg,
  1965.             "resend logic error: NPS, n=%d, j=%d.",n,j);
  1966.         return(-2);
  1967. #else
  1968. /* Just ignore it. */
  1969.         return(0);
  1970. #endif /* COMMENT */
  1971.     }
  1972.     }
  1973. #ifdef DEBUG
  1974. #ifdef GFTIMER
  1975.     if (deblog) t1 = gftimer();
  1976. #endif /* GFTIMER */
  1977. #endif /* DEBUG */
  1978.  
  1979.     /* Everything ok, send the packet */
  1980. #ifdef CK_TIMERS
  1981.     if (timint > 0)
  1982.       srttbl[n] = gtimer();        /* Update the timer */
  1983. #endif /* CK_TIMERS */
  1984.     x = ttol(s_pkt[j].pk_adr,s_pkt[j].pk_len);
  1985.  
  1986. #ifdef DEBUG
  1987. #ifdef GFTIMER
  1988.     if (deblog)  {
  1989.     t2 = gftimer();
  1990.     debug(F101,"resend ttol msec","",(long)((t2-t1)*1000.0));
  1991.     }
  1992. #endif /* GFTIMER */
  1993. #endif /* DEBUG */
  1994.     debug(F101,"resend ttol returns","",x);
  1995.  
  1996.     retrans++;                /* Count a retransmission */
  1997.     xxscreen(SCR_PT,'%',(long)pktnum,"(resend)"); /* Tell user about resend */
  1998.     logpkt('S',n,s_pkt[j].pk_adr, s_pkt[j].pk_len); /* Log the resent packet */
  1999.     return(s_pkt[j].pk_rtr);        /* Return the number of retries. */
  2000. }
  2001.  
  2002. /*  E R R P K T  --  Send an Error Packet  */
  2003.  
  2004. int
  2005. errpkt(reason) CHAR *reason; {        /* ...containing the reason given */
  2006.     extern int rtimo, state, justone;
  2007.     int x, y;
  2008.     czseen = 1;                /* Also cancels batch */
  2009.     state = 0;                /* Reset protocol state */
  2010.     debug(F110,"errpkt",reason,0);
  2011.     tlog(F110,"Protocol Error:",(char *)reason,0L);
  2012.     xxscreen(SCR_EM,0,0L,reason);
  2013.     encstr(reason);
  2014.     x = spack('E',pktnum,size,data);
  2015.     ckstrncpy((char *)epktmsg,(char *)reason,PKTMSGLEN);
  2016.     y = quiet; quiet = 1; epktsent = 1;    /* Close files silently. */
  2017.     clsif(); clsof(1);
  2018.     quiet = y;
  2019. /*
  2020.   I just sent an E-packet.  I'm in local mode, I was receiving a file,
  2021.   I'm not a server, and sliding windows are in use.  Therefore, there are
  2022.   likely to be a bunch of packets already "in the pipe" on their way to me
  2023.   by the time the remote sender gets the E-packet.  So the next time I
  2024.   CONNECT or try to start another protocol operation, I am likely to become
  2025.   terribly confused by torrents of incoming material.  To prevent this,
  2026.   the following code soaks up packets from the connection until there is an
  2027.   error or timeout, without wasting too much time waiting.
  2028.  
  2029.   Exactly the same problem occurs when I am in remote mode or if I am
  2030.   in server mode with the justone flag set.  In remote mode not only
  2031.   does the packet data potentially get echo'd back to the sender which
  2032.   is confusing to the user in CONNECT mode, but it also may result in the
  2033.   host performing bizarre actions such as suspending the process if ^Z is
  2034.   unprefixed, etc.
  2035.  
  2036.   Furthermore, thousands of packets bytes in the data stream prevent the
  2037.   client from being able to process Telnet Kermit Option negotiations
  2038.   properly.
  2039. */
  2040. #ifdef STREAMING
  2041.     /* Because streaming sets the timeout to 0... */
  2042.     if (streaming) {
  2043.     timint = rcvtimo = rtimo;
  2044.     streaming = 0;
  2045.     }
  2046. #endif /* STREAMING */
  2047.     if (what & W_RECV &&
  2048.         (!server || (server && justone)) &&
  2049.         (wslots > 1
  2050. #ifdef STREAMING
  2051.      || streaming
  2052. #endif /* STREAMING */
  2053.      )) {
  2054. #ifdef GFTIMER
  2055.     CKFLOAT oldsec, sec = (CKFLOAT) 0.0;
  2056. #else
  2057.     int oldsec, sec = 0;
  2058. #endif /* GFTIMER */
  2059.     debug(F101,"errpkt draining","",wslots);
  2060.     xxscreen(SCR_ST,ST_MSG,0l,"Draining incoming packets, wait...");
  2061.     while (x > -1) {        /* Don't bother if no connection */
  2062.         oldsec = sec;
  2063. #ifdef GFTIMER
  2064.         sec = gftimer();
  2065.         if (oldsec != (CKFLOAT) 0.0)
  2066.           timint = rcvtimo = (int) (sec - oldsec + 0.5);
  2067. #else
  2068.         sec = gtimer();
  2069.         if (oldsec != 0)
  2070.           timint = rcvtimo = sec - oldsec + 1;
  2071. #endif /* GFTIMER */
  2072.         if (timint < 1)
  2073.           timint = rcvtimo = 1;
  2074.         msleep(50);            /* Allow a bit of slop */
  2075.         x = rpack();        /* Read a packet */
  2076.         if (x == 'T' || x == 'z')    /* Timed out means we're done */
  2077.           break;
  2078.         xxscreen(SCR_PT,x,rsn,"");    /* Let user know */
  2079.     }
  2080.     xxscreen(SCR_ST,ST_MSG,0l,"Drain complete.");
  2081.     }
  2082.     if ((x = (what & W_KERMIT)))
  2083.       xitsta |= x;            /* Remember what failed. */
  2084.     success = 0;
  2085.     return(y);
  2086. }
  2087.  
  2088. /* scmd()  --  Send a packet of the given type */
  2089.  
  2090. int
  2091. #ifdef CK_ANSIC
  2092. scmd(char t, CHAR *dat)
  2093. #else
  2094. scmd(t,dat) char t; CHAR *dat;
  2095. #endif /* CK_ANSIC */
  2096. /* scmd */ {
  2097.     int x;
  2098.     extern char * srimsg;
  2099.     debug(F000,"scmd",dat,t);
  2100.     if (encstr(dat) < 0) {        /* Encode the command string */
  2101.     srimsg = "String too long";
  2102.     return(-1);
  2103.     }
  2104.     x = spack(t,pktnum,size,data);
  2105.     debug(F101,"scmd spack","",x);
  2106.     return(x);
  2107. }
  2108.  
  2109. /* Compose and Send GET packet */
  2110.  
  2111. struct opktparm {            /* O-Packet item list */
  2112.     CHAR * opktitem;
  2113.     struct opktparm * opktnext;
  2114. };
  2115.  
  2116. struct opktparm * opkthead = NULL;    /* Linked list of O-packet fields */
  2117. int opktcnt = 0;            /* O-Packet counter */
  2118. char * srimsg = NULL;            /* GET-Packet error message */
  2119.  
  2120. /* S O P K T  --  Send O-Packet */
  2121. /*
  2122.   Sends one O-Packet each time called, using first-fit method of filling
  2123.   the packet from linked list of parameters pointed to by opkthead.
  2124.   To be called repeatedly until list is empty or there is an error.
  2125.   Returns:
  2126.    -1 on failure.
  2127.     0 on success and no more fields left to send.
  2128.     1 on success but with more fields left to be sent.
  2129. */
  2130.  
  2131. int
  2132. sopkt() {
  2133.     int n = 0;                /* Field number in this packet */
  2134.     int rc = 0;                /* Return code */
  2135.     int len = 0;            /* Data field length */
  2136.     char c = NUL;
  2137.     struct opktparm * o = NULL;
  2138.     struct opktparm * t = NULL;
  2139.     struct opktparm * prev = NULL;
  2140.     CHAR * dsave = data;
  2141.     int x, ssave = spsiz;
  2142.  
  2143.     srimsg = NULL;            /* Error message */
  2144.     o = opkthead;            /* Point to head of list */
  2145.     if (!o) {                /* Oops, no list... */
  2146.     srimsg = "GET Packet Internal Error 1";
  2147.     debug(F100,"sopkt NULL list","",0);
  2148.     return(-1);
  2149.     }
  2150.     while (o) {                /* Go thru linked list... */
  2151.     c = *(o->opktitem);        /* Parameter code */
  2152.     debug(F000,"sopkt",o->opktitem,c);
  2153.     x = encstr((CHAR *)o->opktitem);
  2154.     debug(F111,"sopkt encstr",dsave,x);
  2155.     if (x < 0) {            /* Encode this item */
  2156.         if (n == 0) {        /* Failure, first field in packet */
  2157.         debug(F100,"sopkt overflow","",0);
  2158.         spsiz = ssave;        /* Restore these */
  2159.         data = dsave;
  2160.         o = opkthead;        /* Free linked list */
  2161.         while (o) {
  2162.             if (o->opktitem) free(o->opktitem);
  2163.             t = o->opktnext;
  2164.             free((char *)o);
  2165.             o = t;
  2166.         }
  2167.         opkthead = NULL;
  2168.         srimsg = "GET Packet Too Long for Server";
  2169.         return(-1);        /* Fail */
  2170.         } else {            /* Not first field in packet */
  2171.         debug(F110,"sopkt leftover",o->opktitem,0);
  2172.         prev = o;        /* Make this one the new previous */
  2173.         o = o->opktnext;    /* Get next */
  2174.         c = NUL;        /* So we know we're not done */
  2175.         *data = NUL;        /* Erase any partial encoding */
  2176.         continue;        /* We can try this one again later */
  2177.         }
  2178.     }
  2179.     n++;                /* Encoding was successful */
  2180.     debug(F111,"sopkt field",data,x);
  2181.     len += x;            /* Total data field length */
  2182.     data += x;            /* Set up for next field... */
  2183.     spsiz -= x;
  2184.     free(o->opktitem);        /* Free item just encoded */
  2185.     if (o == opkthead) {        /* If head */
  2186.         opkthead = o->opktnext;    /* Move head to next */
  2187.         free((char *)o);        /* Free this list node */
  2188.         o = opkthead;
  2189.     } else {            /* If not head */
  2190.         o = o->opktnext;        /* Get next */
  2191.         prev->opktnext = o;        /* Link previous to next */
  2192.     }
  2193.     if (c == '@')            /* Loop exit */
  2194.       break;
  2195.     if (!o && !opkthead) {        /* Set up End Of Parameters Field */
  2196.         o = (struct opktparm *)malloc(sizeof(struct opktparm));
  2197.         if (o) {
  2198.         opkthead = o;
  2199.         if (!(o->opktitem = (CHAR *)malloc(3))) {
  2200.             free((char *)o);
  2201.             srimsg = "GET Packet Internal Error 8";
  2202.             return(-1);
  2203.         }
  2204.         ckstrncpy((char *)(o->opktitem), "@ ", 3);
  2205.         debug(F111,"sopkt o->opktitem",o->opktitem,
  2206.               strlen((char *)(o->opktitem)));
  2207.         o->opktnext = NULL;
  2208.         }
  2209.     }
  2210.     }
  2211.     data = dsave;            /* Restore globals */
  2212.     spsiz = ssave;
  2213.     debug(F110,"sopkt data",data,0);
  2214.     debug(F101,"sopkt opktcnt","",opktcnt);
  2215.     if (opktcnt++ > 0) {
  2216.     if (nxtpkt() < 0) {        /* Get next packet number and buffer */
  2217.         srimsg = "GET Packet Internal Error 9";
  2218.         return(-1);
  2219.     }
  2220.     }
  2221.     debug(F101,"sopkt pktnum","",pktnum);
  2222.     rc = spack((char)'O',pktnum,len,data); /* Send O-Packet */
  2223.     debug(F101,"sopkt spack","",rc);
  2224.     if (rc < 0)                /* Failed */
  2225.       srimsg = "Send Packet Failure";    /* Set message */
  2226.     else                /* Succeeded */
  2227.       rc = (c == '@') ? 0 : 1;        /* 1 = come back for more, 0 = done */
  2228.     debug(F101,"sopkt rc","",rc);
  2229.     return(rc);
  2230. }
  2231.  
  2232. /* S R I N I T  --  Send GET packet  */
  2233. /*
  2234.   Sends the appropriate GET-Class packet.
  2235.   Returns:
  2236.   -1 on error
  2237.    0 if packet sent successfully and we can move on to the next state
  2238.    1 if an O-packet was sent OK but more O packets still need to be sent.
  2239. */
  2240. int
  2241. srinit(reget, retrieve, opkt) int reget, retrieve, opkt; {
  2242.     int x = 0, left = 0;
  2243.     extern int oopts, omode;
  2244.     CHAR * p = NULL;
  2245. #ifdef RECURSIVE
  2246.     extern int recursive;
  2247.     debug(F101,"srinit recursive","",recursive);
  2248. #endif /* RECURSIVE */
  2249.     debug(F101,"srinit reget","",reget);
  2250.     debug(F101,"srinit retrieve","",retrieve);
  2251.     debug(F101,"srinit opkt","",opkt);
  2252.     debug(F101,"srinit oopts","",oopts);
  2253.     debug(F101,"srinit omode","",omode);
  2254.     debug(F110,"srinit cmarg",cmarg,0);
  2255.     srimsg = NULL;
  2256.  
  2257.     opktcnt = 0;
  2258.     if (!cmarg) cmarg = "";
  2259.     if (!*cmarg) {
  2260.     srimsg = "GET with no filename";
  2261.     debug(F100,"srinit null cmarg","",0);
  2262.     return(-1);
  2263.     }
  2264.     if (opkt) {                /* Extended GET is totally different */
  2265.     char buf[16];
  2266.     struct opktparm * o = NULL;
  2267.     struct opktparm * prev = NULL;
  2268.  
  2269.         buf[0] = NUL;
  2270.  
  2271.     /* Build O-Packet fields and send (perhaps first) O-Packet */
  2272.  
  2273.     if (oopts > -1) {        /* Write Option flags */
  2274.         o = (struct opktparm *)malloc(sizeof(struct opktparm));
  2275.         if (!o) {
  2276.         srimsg = "GET Packet Internal Error 2";
  2277.         debug(F100,"srinit malloc fail O1","",0);
  2278.         return(-1);
  2279.         }
  2280.         sprintf(buf,"Ox%d",oopts);    /* safe */
  2281.         x = (int) strlen(buf+2);
  2282.         buf[1] = tochar(x);
  2283.         o->opktitem = (CHAR *)malloc(x + 3);
  2284.         if (!o->opktitem) {
  2285.         srimsg = "GET Packet Internal Error 3";
  2286.         debug(F100,"srinit malloc fail O2","",0);
  2287.         return(-1);
  2288.         }
  2289.         ckstrncpy((char *)(o->opktitem),buf,x+3);
  2290.         o->opktnext = NULL;
  2291.         if (!opkthead)
  2292.           opkthead = o;
  2293.         prev = o;
  2294.     }
  2295.     if (omode > -1) {        /* If Xfer Mode specified, write it */
  2296.         o = (struct opktparm *)malloc(sizeof(struct opktparm));
  2297.         if (!o) {
  2298.         srimsg = "GET Packet Internal Error 4";
  2299.         debug(F100,"srinit malloc fail M1","",0);
  2300.         return(-1);
  2301.         }
  2302.         sprintf(buf,"Mx%d",omode);    /* safe */
  2303.         x = (int) strlen(buf+2);
  2304.         buf[1] = tochar(x);
  2305.         o->opktitem = (CHAR *)malloc(x + 3);
  2306.         if (!o->opktitem) {
  2307.         srimsg = "GET Packet Internal Error 5";
  2308.         debug(F100,"srinit malloc fail O2","",0);
  2309.         return(-1);
  2310.         }
  2311.         ckstrncpy((char *)(o->opktitem),buf,x+3);
  2312.         o->opktnext = NULL;
  2313.         if (!opkthead)
  2314.           opkthead = o;
  2315.         else
  2316.           prev->opktnext = o;
  2317.         prev = o;
  2318.     }
  2319.  
  2320.     /* Same deal for oname and opath eventually but not needed now... */
  2321.  
  2322.     x = strlen(cmarg);        /* Now do filename */
  2323.     if (x > spsiz - 4) {
  2324.         srimsg = "GET Packet Too Long for Server";
  2325.         return(-1);
  2326.     }
  2327.     o = (struct opktparm *)malloc(sizeof(struct opktparm));
  2328.     if (!o) {
  2329.         srimsg = "GET Packet Internal Error 6";
  2330.         debug(F100,"srinit malloc fail F1","",0);
  2331.         return(-1);
  2332.     }
  2333.     left = x + 6;
  2334.     o->opktitem = (CHAR *)malloc(left + 1);
  2335.     if (!o->opktitem) {
  2336.         srimsg = "GET Packet Internal Error 7";
  2337.         debug(F100,"srinit malloc fail F2","",0);
  2338.         return(-1);
  2339.     }
  2340.     p = o->opktitem;
  2341.     *p++ = 'F';
  2342.     left--;
  2343.     if (x > 94) {            /* Too long for normal length */
  2344.         *p++ = SYN;            /* Escape length with Ctrl-V */
  2345.         *p++ = tochar(x / 95);
  2346.         *p++ = tochar(x % 95);
  2347.         left -= 3;
  2348.     } else {            /* Normal encoding for 94 or less */
  2349.         *p++ = tochar(x);
  2350.         left--;
  2351.     }
  2352.     ckstrncpy((char *)p,cmarg,left); /* Copy the filename */
  2353.     o->opktnext = NULL;
  2354.     if (!opkthead)
  2355.       opkthead = o;
  2356.     else
  2357.       prev->opktnext = o;
  2358.     prev = o;
  2359.  
  2360.     /* End of Parameters */
  2361.  
  2362.     prev->opktnext = NULL;        /* End of list. */
  2363.     return(sopkt());
  2364.     }
  2365.  
  2366.     /* Not Extended GET */
  2367.  
  2368.     if (encstr((CHAR *)cmarg) < 0) {    /* Encode the filename. */
  2369.     srimsg = "GET Packet Too Long for Server";
  2370.     return(-1);
  2371.     }
  2372.     if (retrieve) {            /* Send the packet. */
  2373. #ifdef RECURSIVE
  2374.     if (recursive)
  2375.       x = spack((char)'W',pktnum,size,data); /* GET /DELETE /RECURSIVE */
  2376.     else
  2377. #endif /* RECURSIVE */
  2378.       x = spack((char)'H',pktnum,size,data); /* GET /DELETE */
  2379.     }
  2380. #ifdef RECURSIVE
  2381.     else if (recursive)
  2382.       x = spack((char)'V',pktnum,size,data); /* GET /RECURSIVE */
  2383. #endif /* RECURSIVE */
  2384.     else
  2385.       x = spack((char)(reget ? 'J' : 'R'),pktnum,size,data); /* GET */
  2386.     if (x < 0)
  2387.       srimsg = "Send Packet Failure";
  2388.     return(x < 0 ? x : 0);
  2389. }
  2390.  
  2391.  
  2392. /*  K S T A R T  --  Checks for a Kermit packet while in terminal mode.  */
  2393.  
  2394. /*  (or command mode...)  */
  2395.  
  2396. #ifdef CK_AUTODL
  2397. int
  2398. #ifdef CK_ANSIC
  2399. kstart(CHAR ch)
  2400. #else
  2401. kstart(ch) CHAR ch;
  2402. #endif /* CK_ANSIC */
  2403. /* kstart */ {
  2404.     static CHAR * p = NULL;
  2405.  
  2406. #ifdef OS2
  2407.     static CHAR * pk = NULL;
  2408. #endif /* OS2 */
  2409.     ch &= 0177;                /* Strip 8th bit */
  2410.  
  2411.     /* Because we're in cooked mode at the command prompt... */
  2412.  
  2413.     if (ch == LF) {
  2414.     debug(F110,"kstart","ch == LF",0);
  2415.     if ((what == W_COMMAND || what == W_INIT || what == W_NOTHING)) {
  2416.         if (eol == CR) {
  2417.         ch = eol;
  2418.         debug(F110,"kstart","ch = CR",0);
  2419.         }
  2420.     }
  2421.     }
  2422.  
  2423. #ifdef OS2
  2424.     if (adl_kmode == ADL_STR) {
  2425.     if (!ch)
  2426.       return(0);
  2427.     if (!pk)
  2428.       pk = adl_kstr;
  2429.  
  2430.     if (ch == *pk) {
  2431.         pk++;
  2432.         if (*pk == '\0') {
  2433.         pk = adl_kstr;
  2434.         debug(F100, "kstart Kermit Start String","",0);
  2435.         return(PROTO_K + 1);
  2436.         }
  2437.     } else
  2438.       pk = adl_kstr;
  2439.     }
  2440. #endif /* OS2 */
  2441.  
  2442.     if (ch == stchr) {            /* Start of packet */
  2443.     kstartactive = 1;
  2444.     p = ksbuf;
  2445.     *p = ch;
  2446.     debug(F101,"kstart SOP","",ch);
  2447.     } else if (ch == eol) {        /* End of packet */
  2448.     kstartactive = 0;
  2449.     if (p) {
  2450.         debug(F101,"kstart EOL","",ch);
  2451.         p++;
  2452.         if (p - ksbuf < 94 ) {
  2453.         int rc = 0;
  2454.         *p++ = ch;
  2455.         *p = NUL;
  2456.         rc = chkspkt((char *)ksbuf);
  2457.         debug(F111,"kstart EOP chkspkt", ksbuf, rc);
  2458.         p = NULL;
  2459.         if (!rc) return(0);
  2460.         if (rc == 2) rc = -1;
  2461.         debug(F111,"kstart ksbuf",ksbuf,rc);
  2462.         return(rc);
  2463.         } else {
  2464.         debug(F110,"kstart","p - ksbuf >= 94",0);
  2465.         p = NULL;
  2466.         }
  2467.     }
  2468.     } else if (p) {
  2469.     if (ch < SP)
  2470.       kstartactive = 0;
  2471.     p++;
  2472.     if (p - ksbuf < 94) {
  2473.         *p = ch;
  2474.     } else {
  2475.         p = NULL;
  2476.         debug(F110,"kstart","p - ksbuf >= 94",0);
  2477.     }
  2478.     }
  2479.     return(0);
  2480. }
  2481.  
  2482. #ifdef CK_XYZ
  2483.  
  2484. /*  Z S T A R T  --  Checks for a ZMODEM packet while in terminal mode.  */
  2485.  
  2486. int
  2487. #ifdef CK_ANSIC
  2488. zstart(CHAR ch)
  2489. #else
  2490. zstart(ch) CHAR ch;
  2491. #endif /* CK_ANSIC */
  2492. /* zstart */ {
  2493.     static CHAR * matchstr = (CHAR *) "\030B00";
  2494.     /* "rz\r**\030B00000000000000\r\033J\021"; */
  2495.     static CHAR * p = NULL;
  2496.     extern int inserver;
  2497.  
  2498.     if (inserver)
  2499.       return(0);
  2500.  
  2501.     if (!ch)
  2502.       return(0);
  2503.     if (!p) {
  2504. #ifdef OS2
  2505.     p = adl_zmode == ADL_PACK ? matchstr : adl_zstr;
  2506. #else
  2507.     p = matchstr;
  2508. #endif /* OS2 */
  2509.     }
  2510.     if (ch == *p) {
  2511.     p++;
  2512.     if (*p == '\0') {
  2513. #ifdef OS2
  2514.         if (adl_zmode == ADL_PACK) {
  2515.         p = matchstr;
  2516.         debug(F100, "zstart Zmodem SOP","",0);
  2517.         } else {
  2518.         p = adl_zstr;
  2519.         debug(F100, "zstart Zmodem Start String","",0);
  2520.         }
  2521. #else
  2522.         p = matchstr;
  2523.         debug(F100, "zstart Zmodem SOP","",0);
  2524. #endif /* OS2 */
  2525.         return(PROTO_Z + 1);
  2526.     }
  2527.     } else {
  2528. #ifdef OS2
  2529.     p = adl_zmode == ADL_PACK ? matchstr : adl_zstr;
  2530. #else
  2531.     p = matchstr;
  2532. #endif /* OS2 */
  2533.     }
  2534.     return(0);
  2535. }
  2536. #endif /* CK_XYZ */
  2537.  
  2538. #ifndef NOICP
  2539. #ifdef CK_APC
  2540. /*  A U T O D O W N  */
  2541.  
  2542. #ifdef CK_ANSIC
  2543. VOID
  2544. autodown(int ch)
  2545. #else
  2546. VOID
  2547. autodown(ch) int ch;
  2548. #endif /* CK_ANSIC */
  2549. /* autodown */ {
  2550.  
  2551. /* The Kermit and Zmodem Auto-download calls go here */
  2552.  
  2553.     extern int justone;            /* From protocol module */
  2554.     extern int debses, protocol, apcactive, autodl, inautodl;
  2555. #ifdef DCMDBUF
  2556.     extern char *apcbuf;
  2557. #else
  2558.     extern char apcbuf[];
  2559. #endif /* DCMDBUF */
  2560. #ifdef OS2
  2561.     extern int apclength, term_io;
  2562. #endif /* OS2 */
  2563.     int k = 0;
  2564.  
  2565.     if ((autodl || inautodl
  2566. #ifdef IKS_OPTION
  2567.      || TELOPT_SB(TELOPT_KERMIT).kermit.me_start
  2568. #endif /* IKS_OPTION */
  2569.      ) && !debses) {
  2570. #ifdef CK_XYZ
  2571. #ifdef XYZ_INTERNAL
  2572.     extern int p_avail;
  2573. #else
  2574.     int p_avail = 1;
  2575. #endif /* XYZ_INTERNAL */
  2576.     if (p_avail && zstart((CHAR) ch)) {
  2577.         debug(F100, "Zmodem download","",0);
  2578. #ifdef OS2
  2579. #ifndef NOTERM
  2580.             apc_command(APC_LOCAL,"receive /protocol:zmodem");
  2581. #endif /* NOTERM */
  2582. #else /* OS2 */
  2583.             ckstrncpy(apcbuf,"receive /protocol:zmodem",APCBUFLEN);
  2584.         apcactive = APC_LOCAL;
  2585. #endif /* OS2 */
  2586.         return;
  2587.     }
  2588. #endif /* CK_XYZ */
  2589.  
  2590.     /* First try... */
  2591.     k = kstart((CHAR) ch);
  2592.     if (
  2593. #ifdef NOSERVER
  2594.         k > 0
  2595. #else /* NOSERVER */
  2596.         k
  2597. #endif /* NOSERVER */
  2598.         ) {                /* We saw a valid S or I packet */
  2599.         if (k < 0) {        /* Stuff RECEIVE into APC buffer */
  2600.         justone = 1;
  2601.         switch (protocol) {
  2602. #ifdef CK_XYZ
  2603.           case PROTO_G:
  2604.             ckstrncpy(apcbuf,
  2605.                   "set proto kermit, server, set protocol g",
  2606.                   APCBUFLEN
  2607.                   );
  2608.             break;
  2609.           case PROTO_X:
  2610.             ckstrncpy(apcbuf,
  2611.                   "set proto kermit,server,set proto xmodem",
  2612.                   APCBUFLEN
  2613.                   );
  2614.             break;
  2615.                   case PROTO_XC:
  2616.             ckstrncpy(apcbuf,
  2617.                "set proto kermit,server,set proto xmodem-crc",
  2618.                   APCBUFLEN
  2619.                   );
  2620.                       break;
  2621.           case PROTO_Y:
  2622.             ckstrncpy(apcbuf,
  2623.                   "set proto kermit,server, set protocol y",
  2624.                   APCBUFLEN
  2625.                   );
  2626.             break;
  2627.           case PROTO_Z:
  2628.             ckstrncpy(apcbuf,
  2629.                   "set proto kermit,server,set proto zmodem",
  2630.                   APCBUFLEN
  2631.                   );
  2632.             break;
  2633. #endif /* CK_XYZ */
  2634.           case PROTO_K:
  2635.             ckstrncpy(apcbuf,"server",APCBUFLEN);
  2636.             break;
  2637.         }
  2638.         } else {
  2639.         justone = 0;
  2640.                 ckstrncpy(apcbuf,"receive /protocol:kermit",APCBUFLEN);
  2641.         }
  2642. #ifdef OS2
  2643. #ifndef NOTERM
  2644.             apc_command(APC_LOCAL,apcbuf);
  2645. #endif /* NOTERM */
  2646. #else /* OS2 */
  2647.             ckstrncpy(apcbuf,"receive /protocol:zmodem",APCBUFLEN);
  2648.         apcactive = APC_LOCAL;
  2649. #endif /* OS2 */
  2650.         return;
  2651.     }
  2652.     }
  2653. }
  2654. #endif /* CK_APC */
  2655. #endif /* NOICP */
  2656.  
  2657. /*  C H K S P K T  --  Check if buf contains a valid S or I packet  */
  2658.  
  2659. int
  2660. chkspkt(packet) char *packet; {
  2661.     int i;
  2662.     int buflen;
  2663.     int len = -1;
  2664.     CHAR chk;
  2665.     char type = 0;
  2666.     char *s = NULL;
  2667.     char *buf = NULL;
  2668.     char tmpbuf[100];            /* Longest S/I packet is about 30 */
  2669.  
  2670.     if (!packet) return(0);
  2671.     buflen = ckstrncpy(tmpbuf,packet,100); /* Make a pokeable copy */
  2672.     if (buflen < 5) return(0);        /* Too short */
  2673.     if (buflen > 100) return(0);     /* Too long to be an S or I packet */
  2674.     s = buf = tmpbuf;            /* Point to beginning of copy */
  2675.  
  2676.     if (*s++ != stchr) return(0);    /* SOH */
  2677.     len = xunchar(*s++);        /* Length */
  2678.     if (len < 0) return(0);
  2679.     if (*s++ != SP) return(0);        /* Sequence number */
  2680.     type = *s++;            /* Type */
  2681.     if (type != 'S' && type != 'I')
  2682.       return(0);
  2683.     if (buflen < len + 2) return(0);
  2684.     s += (len - 3);            /* Position of checksum */
  2685.     chk = (CHAR) (*s);            /* Checksum */
  2686.     *s = NUL;               /* Temporarily null-terminate data field */
  2687.     if (xunchar(chk) != chk1((CHAR *)(buf+1),buflen-2)) { /* Check it */
  2688.     /*
  2689.       In C-Kermit 9.0 and later, an S or I packet can have a 
  2690.       Type 3 Block check ("help set block-check" for details).
  2691.     */
  2692.     unsigned crc;            /* Failed... Try Type 3 block check */
  2693.     *s = chk;            /* Replace last byte */
  2694.     s -= 2;                /* Back up two bytes */
  2695.     crc = (xunchar(s[0]) << 12)    /* Convert 3 bytes to numeric CRC */
  2696.         | (xunchar(s[1]) << 6)
  2697.         | (xunchar(s[2]));
  2698.     chk = (CHAR)(*s);        /* Copy 1st byte of 3-byte CRC */
  2699.     *s = NUL;            /* Null-terminate data field */
  2700.     if (crc != chk3((CHAR *)(buf+1),strlen(buf+1)))
  2701.       return(0);
  2702.     }
  2703.     return(type == 'S' ? 1 : 2);
  2704. }
  2705. #endif /* CK_AUTODL */
  2706.  
  2707. /* R P A C K  --  Read a Packet */
  2708.  
  2709. /*
  2710.   rpack reads a packet and returns the packet type, or else Q if the
  2711.   packet was invalid, or T if a timeout occurred.  Upon successful return,
  2712.   sets the values of global rsn (received sequence number),  rln (received
  2713.   data length), and rdatap (pointer to null-terminated data field), and
  2714.   returns the packet type.  NOTE: This is an inner-loop function so must be
  2715.   efficient.  Protect function calls by if-tests where possible, e.g.
  2716.   "if (pktlog) logpkt(...);".
  2717. */
  2718. int
  2719. rpack() {
  2720.     register int i, j, x, lp;        /* Local variables */
  2721. #ifdef CKTUNING
  2722.     unsigned int chk;
  2723. #endif /* CKTUNING */
  2724.     int k, type, chklen;
  2725.     unsigned crc;
  2726.     CHAR pbc[5];            /* Packet block check */
  2727.     CHAR *sohp;                /* Pointer to SOH */
  2728.     CHAR e;                /* Packet end character */
  2729.  
  2730. #ifdef GFTIMER
  2731.     CKFLOAT t1 = 0.0, t2 = 0.0;
  2732. #endif /* GFTIMER */
  2733.  
  2734.     debug(F101,"rpack pktnum","",pktnum);
  2735.  
  2736. #ifndef OLDCHKINT
  2737.     if (chkint() < 0)            /* Check for console interrupts. */
  2738.       return('z');
  2739. #endif /* OLDCHKINT */
  2740.  
  2741.     k = getrbuf();            /* Get a new packet input buffer. */
  2742.     debug(F101,"rpack getrbuf","",k);
  2743.     if (k < 0) {            /* Return like this if none free. */
  2744.     return(-1);
  2745.     }
  2746.     recpkt = r_pkt[k].bf_adr;
  2747.     *recpkt = '\0';            /* Clear receive buffer. */
  2748.     sohp = recpkt;            /* Initialize pointers to it. */
  2749.     rdatap = recpkt;
  2750.     rsn = rln = -1;            /* In case of failure. */
  2751.     e = (turn) ? turnch : eol;        /* Use any handshake char for eol */
  2752.  
  2753. /* Try to get a "line". */
  2754.  
  2755. #ifdef CK_AUTODL
  2756.     debug(F110,"rpack ksbuf",ksbuf,0);
  2757.     if (ksbuf[0]) {            /* Kermit packet already */
  2758.     int x;                /* collected for us in CONNECT mode */
  2759.     CHAR *s1 = recpkt, *s2 = ksbuf;
  2760.     j = 0;
  2761.     while (*s2) {            /* Copy and get length */
  2762.         *s1++ = *s2++;        /* No point optimizing this since */
  2763.         j++;            /* it's never more than ~20 chars */
  2764.     }
  2765.     *s1 = NUL;
  2766. #ifdef PARSENSE
  2767.     x = parchk(recpkt, stchr, j);    /* Check parity */
  2768.     debug(F000,"autodownload parity","",parity);
  2769.     debug(F000,"autodownload parchk","",x);
  2770.     if (x > 0 && parity != x) {
  2771.         autopar = 1;
  2772.         parity = x;
  2773.     }
  2774. #endif /* PARSENSE */
  2775.     ksbuf[0] = NUL;            /* Don't do this next time! */
  2776.  
  2777.     } else {                /* Normally go read a packet */
  2778. #endif /* CK_AUTODL */
  2779.  
  2780. #ifdef DEBUG
  2781.     if (deblog) {
  2782.         debug(F101,"rpack timint","",timint);
  2783.         debug(F101,"rpack rcvtimo","",rcvtimo);
  2784. #ifdef STREAMING
  2785.         debug(F101,"rpack streaming","",streaming);
  2786. #endif /* STREAMING */
  2787. #ifdef GFTIMER
  2788.         /* Measure how long it takes to read a packet */
  2789.         t1 = gftimer();
  2790. #endif /* GFTIMER */
  2791.     }
  2792. #endif /* DEBUG */
  2793.  
  2794. /* JUST IN CASE (otherwise this could clobber streaming) */
  2795.  
  2796.     if ((timint == 0
  2797. #ifdef STREAMING
  2798.          || streaming
  2799. #endif /* STREAMING */
  2800.          ) && (rcvtimo != 0)) {
  2801.         debug(F101,"rpack timint 0 || streaming but rcvtimo","",rcvtimo);
  2802.         rcvtimo = 0;
  2803.     }
  2804.  
  2805. #ifdef PARSENSE
  2806. #ifdef UNIX
  2807. /*
  2808.   So far the final turn argument is only for ck[uvdl]tio.c.  Should be added
  2809.   to the others too.  (turn == handshake character.)
  2810. */
  2811.     j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
  2812. #else
  2813. #ifdef VMS
  2814.     j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
  2815. #else
  2816. #ifdef datageneral
  2817.     j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
  2818. #else
  2819. #ifdef STRATUS
  2820.     j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
  2821. #else
  2822. #ifdef OS2
  2823.     j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
  2824. #else
  2825. #ifdef OSK
  2826.     j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
  2827. #else
  2828.     j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr);
  2829. #endif /* OSK */
  2830. #endif /* OS2 */
  2831. #endif /* STRATUS */
  2832. #endif /* datageneral */
  2833. #endif /* VMS */
  2834. #endif /* UNIX */
  2835.     if (parity != 0 && parity != 's' && ttprty != 0) {
  2836.         if (parity != ttprty) autopar = 1;
  2837.         parity = ttprty;
  2838.     }
  2839. #else /* !PARSENSE */
  2840.     j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e);
  2841. #endif /* PARSENSE */
  2842.  
  2843. #ifdef DEBUG
  2844.     if (deblog)  {
  2845.         debug(F101,"rpack ttinl len","",j);
  2846. #ifdef GFTIMER
  2847.         t2 = gftimer();
  2848.         debug(F101,"rpack ttinl msec","",(long)((t2-t1)*1000.0));
  2849. #endif /* GFTIMER */
  2850.     }
  2851. #endif /* DEBUG */
  2852.  
  2853. #ifdef STREAMING
  2854.     if (streaming && sndtyp == 'D' && j == 0)
  2855.         return('Y');
  2856. #endif /* STREAMING */
  2857.  
  2858.     if (j < 0) {
  2859.         /* -1 == timeout, -2 == ^C, -3 == connection lost or fatal i/o */
  2860.         debug(F101,"rpack: ttinl fails","",j); /* Otherwise, */
  2861.         freerbuf(k);        /* Free this buffer */
  2862.         if (j < -1) {        /* Bail out if ^C^C typed. */
  2863.         if (j == -2) {
  2864.             interrupted = 1;
  2865.             debug(F101,"rpack ^C server","",server);
  2866.             debug(F101,"rpack ^C en_fin","",en_fin);
  2867.         } else if (j == -3) {
  2868.             fatalio = 1;
  2869.             debug(F101,"rpack fatalio","",en_fin);
  2870.         }
  2871.         return(j);
  2872.         }
  2873.         if (nakstate)        /* j == -1 is a read timeout */
  2874.           xxscreen(SCR_PT,'T',(long)winlo,"");
  2875.         else
  2876.           xxscreen(SCR_PT,'T',(long)pktnum,"");
  2877.         logpkt('r',-1,(CHAR *)"<timeout>",0);
  2878.         if (flow == 1) ttoc(XON);    /* In case of Xoff blockage. */
  2879.         return('T');
  2880.     }
  2881. #ifdef CK_AUTODL
  2882.     }
  2883. #endif /* CK_AUTODL */
  2884.  
  2885.     rpktl = j;
  2886.     tlci += j;                /* All OK, Count the characters. */
  2887.     flci += j;
  2888.  
  2889. /* Find start of packet */
  2890.  
  2891. #ifndef PARSENSE
  2892.     for (i = 0; (recpkt[i] != stchr) && (i < j); i++)
  2893.       sohp++;                /* Find mark */
  2894.     if (i++ >= j) {            /* Didn't find it. */
  2895.     logpkt('r',-1,"<timeout>",0);
  2896.     freerbuf(k);
  2897.     return('T');
  2898.     }
  2899. #else
  2900.     i = 1;                /* ttinl does this for us */
  2901. #endif /* PARSENSE */
  2902.  
  2903.     rpackets++;                /* Count received packet. */
  2904.     lp = i;                /* Remember LEN position. */
  2905.     if ((j = xunchar(recpkt[i++])) == 0) { /* Get packet length.  */
  2906.         if ((j = lp+5) > MAXRP) {    /* Long packet */
  2907.         return('Q');        /* Too long */
  2908.     }
  2909.  
  2910. #ifdef CKTUNING
  2911.     /* Save some function-call and loop overhead... */
  2912. #ifdef COMMENT
  2913.     /* ttinl() already removed parity */
  2914.     if (parity)
  2915. #endif /* COMMENT */
  2916.       chk = (unsigned) ((unsigned) recpkt[i-1] +
  2917.                 (unsigned) recpkt[i]   +
  2918.                 (unsigned) recpkt[i+1] +
  2919.                 (unsigned) recpkt[i+2] +
  2920.                 (unsigned) recpkt[i+3]
  2921.                 );
  2922. #ifdef COMMENT
  2923.     else
  2924.       chk = (unsigned) ((unsigned) (recpkt[i-1] & 077) +
  2925.                 (unsigned) (recpkt[i]   & 077) +
  2926.                 (unsigned) (recpkt[i+1] & 077) +
  2927.                 (unsigned) (recpkt[i+2] & 077) +
  2928.                 (unsigned) (recpkt[i+3] & 077)
  2929.                 );
  2930. #endif /* COMMENT */
  2931.     if (xunchar(recpkt[j]) != ((((chk & 0300) >> 6) + chk) & 077))
  2932. #else
  2933.     x = recpkt[j];            /* Header checksum. */
  2934.     recpkt[j] = '\0';        /* Calculate & compare. */
  2935.     if (xunchar(x) != chk1(recpkt+lp,5))
  2936. #endif /* CKTUNING */
  2937.       {
  2938.           freerbuf(k);
  2939.           logpkt('r',-1,(CHAR *)"<crunched:hdr>",0);
  2940.           xxscreen(SCR_PT,'%',(long)pktnum,"Bad packet header");
  2941.           return('Q');
  2942.       }
  2943. #ifndef CKTUNING
  2944.     recpkt[j] = x;            /* Checksum ok, put it back. */
  2945. #endif /* CKTUNING */
  2946.     rln = xunchar(recpkt[j-2]) * 95 + xunchar(recpkt[j-1]) - bctl;
  2947.     j = 3;                /* Data offset. */
  2948.     } else if (j < 3) {
  2949.     debug(F101,"rpack packet length less than 3","",j);
  2950.     freerbuf(k);
  2951.     logpkt('r',-1,(CHAR *)"<crunched:len>",0);
  2952.     xxscreen(SCR_PT,'%',(long)pktnum,"Bad packet length");
  2953.     return('Q');
  2954.     } else {
  2955.     rln = j - bctl - 2;        /* Regular packet */
  2956.     j = 0;                /* No extended header */
  2957.     }
  2958.     rsn = xunchar(recpkt[i++]);        /* Sequence number */
  2959.     if (pktlog)                /* Save a function call! */
  2960.       logpkt('r',rsn,sohp,rln+bctl+j+4);
  2961.     if (rsn < 0 || rsn > 63) {
  2962.     debug(F101,"rpack bad sequence number","",rsn);
  2963.     freerbuf(k);
  2964.     if (pktlog)
  2965.       logpkt('r',rsn,(CHAR *)"<crunched:seq>",0);
  2966.     xxscreen(SCR_PT,'%',(long)pktnum,"Bad sequence number");
  2967.     return('Q');
  2968.     }
  2969. /*
  2970.   If this packet has the same type as the packet just sent, assume it is
  2971.   an echo and ignore it.  Don't even bother with the block check calculation:
  2972.   even if the packet is corrupted, we don't want to NAK an echoed packet.
  2973.   Nor must we NAK an ACK or NAK.
  2974. */
  2975.     type = recpkt[i++];            /* Get packet's TYPE field */
  2976.     if (type == sndtyp || (nakstate && (type == 'N' /* || type == 'Y' */ ))) {
  2977.     debug(F000,"rpack echo","",type); /* If it's an echo */
  2978.     freerbuf(k);            /* Free this buffer */
  2979.     logpkt('#',rsn,(CHAR *)"<echo:ignored>",0);
  2980.     return('e');            /* Return special (lowercase) code */
  2981.     }
  2982. /*
  2983.   Separate the data from the block check, accounting for the case where
  2984.   a packet was retransmitted after the block check switched.  The "Type 3
  2985.   Forced" business is new to C-Kermit 9.0.
  2986. */
  2987.     if (bctf) {             /* Type 3 forced on all packets */
  2988.     bctl = chklen = 3;
  2989.     } else if ((type == 'I' || type == 'S')) { /* Otherwise... */
  2990.     if (recpkt[11] == '5') {    /* Sender is forcing Type 3 */
  2991.         bctf = 1;            /* So we will too */
  2992.         bctl = chklen = 3;
  2993.         debug(F100,"RECOGNIZE BLOCK CHECK TYPE 5","",0);
  2994.     } else {            /* Normal case */
  2995.         /* I & S packets always have type 1 */
  2996.         chklen = 1;
  2997.         rln = rln + bctl - 1;
  2998.     }
  2999.     } else if (type == 'N') {        /* A NAK packet never has data */
  3000.     chklen = xunchar(recpkt[lp]) - 2;
  3001.     if (chklen < 1 || chklen > 3) {    /* JHD 13 Apr 2010 */
  3002.         debug(F101,"rpack bad nak chklen","",chklen);
  3003.         freerbuf(k);
  3004.         logpkt('r',-1,(CHAR *)"<crunched:chklen>",0);
  3005.         xxscreen(SCR_PT,'%',(long)pktnum,"(bad nak)");
  3006.         return('Q');
  3007.     }
  3008.     rln = rln + bctl - chklen;
  3009.     } else chklen = bctl;
  3010. #ifdef DEBUG
  3011.     if (deblog) {            /* Save 2 function calls */
  3012.     debug(F101,"rpack bctl","",bctl);
  3013.     debug(F101,"rpack chklen","",chklen);
  3014.     }
  3015. #endif /* DEBUG */
  3016.     i += j;                /* Buffer index of DATA field */
  3017.     rdatap = recpkt+i;            /* Pointer to DATA field */
  3018.     if ((j = rln + i) > r_pkt[k].bf_len) { /* Make sure it fits */
  3019.     debug(F101,"packet too long","",j);
  3020.     freerbuf(k);
  3021.     logpkt('r',rsn,(CHAR *)"<overflow>",0);
  3022.     return('Q');
  3023.     }
  3024.     for (x = 0; x < chklen; x++)    /* Copy the block check */
  3025.       pbc[x] = recpkt[j+x];        /* 3 bytes at most. */
  3026.     pbc[x] = '\0';            /* Null-terminate block check string */
  3027.     recpkt[j] = '\0';            /* and the packet Data field. */
  3028.  
  3029.     if (chklen == 2 && bctu == 4) {    /* Adjust for Blank-Free-2 */
  3030.     chklen = 4;            /* (chklen is now a misnomer...) */
  3031.     debug(F100,"rpack block check B","",0);
  3032.     }
  3033.     switch (chklen) {            /* Check the block check */
  3034.       case 1:                /* Type 1, 6-bit checksum */
  3035.     if (xunchar(*pbc) != chk1(recpkt+lp,j-lp)) {
  3036. #ifdef DEBUG
  3037.         if (deblog) {
  3038.         debug(F110,"checked chars",recpkt+lp,0);
  3039.         debug(F101,"block check (1)","",(int) xunchar(*pbc));
  3040.         debug(F101,"should be (1)","",chk1(recpkt+lp,j-lp));
  3041.         }
  3042. #endif /* DEBUG */
  3043.         freerbuf(k);
  3044.         logpkt('r',-1,(CHAR *)"<crunched:chk1>",0);
  3045.         xxscreen(SCR_PT,'%',(long)pktnum,"Checksum error");
  3046.         return('Q');
  3047.     }
  3048.     break;
  3049.       case 2:                /* Type 2, 12-bit checksum */
  3050.     x = xunchar(*pbc) << 6 | xunchar(pbc[1]);
  3051.     if (x != chk2(recpkt+lp,j-lp)) { /* No match */
  3052.         if (type == 'E') {        /* Allow E packets to have type 1 */
  3053.         recpkt[j++] = pbc[0];
  3054.         recpkt[j] = '\0';
  3055.         if (xunchar(pbc[1]) == chk1(recpkt+lp,j-lp))
  3056.           break;
  3057.         else
  3058.           recpkt[--j] = '\0';
  3059.         }
  3060. #ifdef DEBUG
  3061.         if (deblog) {
  3062.         debug(F110,"checked chars",recpkt+lp,0);
  3063.         debug(F101,"block check (2)","", x);
  3064.         debug(F101,"should be (2)","", (int) chk2(recpkt+lp,j-lp));
  3065.         }
  3066. #endif /* DEBUG */
  3067.         freerbuf(k);
  3068.         logpkt('r',-1,(CHAR *)"<crunched:chk2>",0);
  3069.         xxscreen(SCR_PT,'%',(long)pktnum,"Checksum error");
  3070.         return('Q');
  3071.     }
  3072.     break;
  3073.       case 3:                /* Type 3, 16-bit CRC */
  3074.     crc = (xunchar(pbc[0]) << 12)
  3075.         | (xunchar(pbc[1]) << 6)
  3076.         | (xunchar(pbc[2]));
  3077.     if (crc != chk3(recpkt+lp,j-lp)) {
  3078.         if (type == 'E') {        /* Allow E packets to have type 1 */
  3079.         recpkt[j++] = pbc[0];
  3080.         recpkt[j++] = pbc[1];
  3081.         recpkt[j] = '\0';
  3082.         if (xunchar(pbc[2]) == chk1(recpkt+lp,j-lp))
  3083.           break;
  3084.         else { j -=2; recpkt[j] = '\0'; }
  3085.         }
  3086. #ifdef DEBUG
  3087.         if (deblog) {
  3088.         debug(F110,"checked chars",recpkt+lp,0);
  3089.         debug(F101,"block check (3)","",crc);
  3090.         debug(F101,"should be (3)","",(int) chk3(recpkt+lp,j-lp));
  3091.         }
  3092. #endif /* DEBUG */
  3093.         freerbuf(k);
  3094.         logpkt('r',-1,(CHAR *)"<crunched:chk3>",0);
  3095.         xxscreen(SCR_PT,'%',(long)pktnum,"CRC error");
  3096.         return('Q');
  3097.     }
  3098.     break;
  3099.       case 4:                /* Type 4 = Type 2, no blanks. */
  3100.     x = (unsigned)((xunchar(*pbc) - 1) << 6) |
  3101.       (unsigned)(xunchar(pbc[1]) - 1);
  3102.     if (x != chk2(recpkt+lp,j-lp)) {
  3103.         if (type == 'E') {    /* Allow E packets to have type 1 */
  3104.         recpkt[j++] = pbc[0];
  3105.         recpkt[j] = '\0';
  3106.         if (xunchar(pbc[1]) == chk1(recpkt+lp,j-lp))
  3107.           break;
  3108.         else
  3109.           recpkt[--j] = '\0';
  3110.         }
  3111.         debug(F101,"bad type B block check","",x);
  3112.         freerbuf(k);
  3113.         logpkt('r',-1,(CHAR *)"<crunched:chkb>",0);
  3114.         xxscreen(SCR_PT,'%',(long)pktnum,"Checksum error");
  3115.         return('Q');
  3116.     }
  3117.     break;
  3118.       default:            /* Shouldn't happen... */
  3119.     freerbuf(k);
  3120.     logpkt('r',-1,(CHAR *)"<crunched:chkx>",0);
  3121.     xxscreen(SCR_PT,'%',(long)pktnum,"(crunched)");
  3122.     return('Q');
  3123.     }
  3124.     debug(F101,"rpack block check OK","",rsn);
  3125.  
  3126. /* Now we can believe the sequence number, and other fields. */
  3127. /* Here we violate strict principles of layering, etc, and look at the  */
  3128. /* packet sequence number.  If there's already a packet with the same   */
  3129. /* number in the window, we remove this one so that the window will not */
  3130. /* fill up. */
  3131.  
  3132.     if ((x = rseqtbl[rsn]) != -1) {    /* Already a packet with this number */
  3133.     retrans++;            /* Count it for statistics */
  3134.     debug(F101,"rpack got dup","",rsn);
  3135.     logpkt('r',rsn,(CHAR *)"<duplicate>",0);
  3136.     freerbuf(x);            /* Free old buffer, keep new packet. */
  3137.     r_pkt[k].pk_rtr++;        /* Count this as a retransmission. */
  3138.     }
  3139.  
  3140. /* New packet, not seen before, enter it into the receive window. */
  3141.  
  3142. #ifdef CK_TIMERS
  3143.     if (timint > 0)
  3144.       rrttbl[rsn] = gtimer();        /* Timestamp */
  3145. #endif /* CK_TIMERS */
  3146.  
  3147.     rseqtbl[rsn] = k;            /* Make back pointer */
  3148.     r_pkt[k].pk_seq = rsn;        /* Record in packet info structure */
  3149.     r_pkt[k].pk_typ = type;        /* Sequence, type,... */
  3150.     r_pkt[k].pk_adr = rdatap;        /* pointer to data buffer */
  3151.     if (local) {            /* Save a function call! */
  3152.     int x = 0;
  3153.     if (fdispla != XYFD_N) x = 1;
  3154.     if (fdispla == XYFD_B && (type == 'D' || sndtyp == 'D')) x = 0;
  3155.     if (x)                /* Update screen */
  3156.       xxscreen(SCR_PT,(char)type,(long)rsn,(char *)sohp);
  3157.     }
  3158.     return(type);            /* Return packet type */
  3159. }
  3160.  
  3161. /*  L O G P K T  --  Log packet number n, pointed to by s.  */
  3162.  
  3163. /* c = 's' (send) or 'r' (receive) */
  3164.  
  3165. VOID
  3166. #ifdef CK_ANSIC
  3167. logpkt(char c,int n, CHAR *s, int len)
  3168. #else
  3169. logpkt(c,n,s,len) char c; int n; CHAR *s; int len;
  3170. #endif /* CK_ANSIC */
  3171. /* logpkt */ {
  3172.     char plog[20];
  3173.     if (!s) s = (CHAR *)"";
  3174.     if (pktlog) if (chkfn(ZPFILE) > 0) {
  3175.     if (n < 0)            /* Construct entry header */
  3176.       sprintf(plog,"%c-xx-%02d-",c,(gtimer()%60)); /* safe */
  3177.     else
  3178.       sprintf(plog,"%c-%02d-%02d-",c,n,(gtimer()%60)); /* safe */
  3179.     if (zsoutx(ZPFILE,plog,(int)strlen(plog)) < 0) {
  3180.         pktlog = 0;
  3181.         return;
  3182.     } else {
  3183.         if (len == 0)
  3184.           len = strlen((char *)s);
  3185.         if (len > 0) {
  3186.         char * p;        /* Make SOP printable */
  3187.         int x;            /* so we can look at logs without */
  3188.         p = dbchr(*s);        /* triggering autodownload. */
  3189.         x = strlen(dbchr(*s));
  3190.         if (*s < 32 || (*s > 127 && *s < 160)) {
  3191.             if (zsoutx(ZPFILE,p,x) < 0) {
  3192.             pktlog = 0;
  3193.             return;
  3194.             } else {
  3195.             len--;
  3196.             s++;
  3197.             }
  3198.         }
  3199.         }
  3200.         if (zsoutx(ZPFILE,(char *)s,len) < 0) {
  3201.         pktlog = 0;
  3202.         return;
  3203.         } else if (zsoutx(ZPFILE,
  3204. #ifdef UNIX
  3205.                   "\n", 1
  3206. #else
  3207. #ifdef datageneral
  3208.                   "\n", 1
  3209. #else
  3210. #ifdef OSK
  3211.                   "\r", 1
  3212. #else
  3213. #ifdef MAC
  3214.                   "\r", 1
  3215. #else
  3216.                   "\015\012", 2
  3217. #endif /* MAC */
  3218. #endif /* OSK */
  3219. #endif /* datageneral */
  3220. #endif /* UNIX */
  3221.                   ) < 0) {
  3222.         pktlog = 0;
  3223.         }
  3224.     }
  3225.     }
  3226. }
  3227.  
  3228. /*  T S T A T S  --  Record statistics in transaction log  */
  3229.  
  3230. VOID
  3231. tstats() {
  3232.     char *tp = NULL;
  3233. #ifdef GFTIMER
  3234.     CKFLOAT xx;                /* Elapsed time divisor */
  3235. #endif /* GFTIMER */
  3236.  
  3237.     debug(F101,"tstats xfsecs","",xfsecs);
  3238.     debug(F101,"tstats filcnt","",filcnt);
  3239.     if (filcnt == 1) {            /* Get timing for statistics */
  3240.     tsecs = xfsecs;            /* Single file, we already have it */
  3241. #ifdef GFTIMER
  3242.     debug(F101,"tstats fpxfsecs","",(int)fpxfsecs);
  3243.     fptsecs = fpxfsecs;
  3244. #endif /* GFTIMER */
  3245.     } else {                /* Multiple files */
  3246.     tsecs = gtimer();        /* Get current time */
  3247. #ifdef GFTIMER
  3248.     fptsecs = gftimer();
  3249. #endif /* GFTIMER */
  3250.     }
  3251. #ifdef GFTIMER
  3252.     if (fptsecs <= GFMINTIME)        /* Calculate CPS */
  3253.       fptsecs = (CKFLOAT) GFMINTIME;
  3254.     debug(F101,"tstats fptsecs","",(int)fptsecs);
  3255.     xx = (CKFLOAT) tfc / fptsecs;
  3256.     if (sizeof(long) <= 4) {        /* doesn't account for 16-bit longs */
  3257.     if (xx  > 2147483647.0)
  3258.       tfcps = 2147483647L;            /* 31 bits */
  3259.     else
  3260.       tfcps = (long) xx;
  3261.     } else
  3262.       tfcps = (long) xx;
  3263. #else
  3264.     if (tsecs < 2L)
  3265.       tsecs = 1L;
  3266.     debug(F101,"tstats tsecs","",tsecs);
  3267.     tfcps = tfc / tsecs;
  3268. #endif /* GFTIMER */
  3269.  
  3270.     ztime(&tp);                /* Get time stamp */
  3271.     tlog(F100,"","",0L);        /* Leave a blank line */
  3272.     tlog(F110,"Transaction complete",tp,0L);  /* Record it */
  3273.  
  3274.     if (filcnt < 1) return;        /* If no files, done. */
  3275.  
  3276. /* If multiple files, record character totals for all files */
  3277.  
  3278.     if (filcnt > 1) {
  3279.     tlog(F101," files transferred       ","",filcnt - filrej);
  3280.     tlog(F101," total file characters   ","",tfc);
  3281.     tlog(F101," communication line in   ","",tlci);
  3282.     tlog(F101," communication line out  ","",tlco);
  3283.     }
  3284.  
  3285. /* Record timing info for one or more files */
  3286.  
  3287. #ifdef GFTIMER
  3288.     if (filcnt - filrej == 1) {
  3289.     tlog(F101," elapsed time (seconds)  ","",(long) fpxfsecs);
  3290.     tlog(F101," effective data rate     ","",filcps);
  3291.     } else {
  3292.     tlog(F101," elapsed time (seconds)  ","",(long) fptsecs);
  3293.     tlog(F101," effective data rate     ","",(long) xx);
  3294.     }
  3295. #else
  3296.     tlog(F101," elapsed time (seconds)  ","",tsecs);
  3297.     if (tsecs > 0)
  3298.       tlog(F101," effective data rate     ","",(tfc / tsecs));
  3299. #endif /* GFTIMER */
  3300.  
  3301.     tlog(F100,"","",0L);        /* Leave a blank line */
  3302. }
  3303.  
  3304. /*  F S T A T S  --  Record file statistics in transaction log  */
  3305.  
  3306. VOID
  3307. fcps() {
  3308. #ifdef GFTIMER
  3309.     double xx;
  3310.     fpxfsecs = gftimer() - fpfsecs;
  3311.     if (fpxfsecs <= GFMINTIME)
  3312.       fpxfsecs = (CKFLOAT) GFMINTIME;
  3313.     xx = (CKFLOAT) ffc / fpxfsecs;
  3314.     if (sizeof(long) <= 4) {
  3315.     if (xx  > 2147483647.0)
  3316.       tfcps = 2147483647L;        /* 31 bits */
  3317.     else
  3318.       filcps = (long) xx;
  3319.     } else
  3320.       filcps = (long) xx;
  3321.     if (sizeof(int) >= 4)
  3322.       xfsecs = (int) fpxfsecs;
  3323.     else if (fpxfsecs < 32768.0)
  3324.       xfsecs = (int) fpxfsecs;
  3325.     else
  3326.       xfsecs = 32767;
  3327. #else /* GFTIMER */
  3328.     xfsecs = gtimer() - fsecs;
  3329.     if (xfsecs < 1L) xfsecs = 1L;
  3330.     filcps = ffc / xfsecs;
  3331. #endif /* GFTIMER */
  3332. }
  3333.  
  3334. VOID
  3335. fstats() {
  3336.     tfc += ffc;
  3337. #ifdef DEBUG
  3338.     if (deblog) {
  3339.     debug(F101,"fstats tfc","",tfc);
  3340.     debug(F101,"fstats what","",what);
  3341.     debug(F110,"fstats epktmsg",epktmsg,0);
  3342.     }
  3343. #endif /* DEBUG */
  3344. #ifdef TLOG
  3345.     if (!discard && !cxseen && !czseen && what != W_NOTHING && !*epktmsg)
  3346.       tlog(F101," complete, size","",ffc);
  3347. #endif /* TLOG */
  3348. }
  3349.  
  3350. #endif /* NOXFER */
  3351.