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
dopar(register CHAR ch)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
rttinit()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
getrtt(nakstate,n)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
input()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
parchk(CHAR * s,CHAR start,int n)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
chktimo(timo,flag)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
spack(char pkttyp,int n,int len,CHAR * d)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
chk1(pkt,len)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
chk2(pkt,len)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
chk3(pkt,parity,len)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
chk3(pkt,len)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
nxtpkt()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
ack()1671 ack() {					/* Acknowledge the current packet. */
1672     return(ackns(winlo,(CHAR *)""));
1673 }
1674 
1675 #ifdef STREAMING
1676 int
fastack()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
ackns(n,s)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
ackn(n)1731 ackn(n) int n; {			/* Send ACK for packet number n */
1732     return(ackns(n,(CHAR *)""));
1733 }
1734 
1735 int
ack1(s)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
nack(n)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
rcalcpsz()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
resend(n)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
errpkt(reason)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
scmd(char t,CHAR * dat)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
sopkt()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
srinit(reget,retrieve,opkt)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
kstart(CHAR ch)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
zstart(CHAR ch)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
autodown(int ch)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
chkspkt(packet)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
rpack()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
logpkt(char c,int n,CHAR * s,int len)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
tstats()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
fcps()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
fstats()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