xref: /netbsd-src/external/bsd/ekermit/dist/kermit.c (revision 250ad67d8ece5c4fa0200159a0183f377ebff96b)
1 #define KERMIT_C
2 /*
3   Embedded Kermit protocol module
4   Version: 1.7
5   Most Recent Update: Mon Jun  6 15:36:26 2011
6 
7   No stdio or other runtime library calls, no system calls, no system
8   includes, no static data, and no global variables in this module.
9 
10   Warning: you can't use debug() in any routine whose argument list
11   does not include "struct k_data * k".  Thus most routines in this
12   module include this arg, even if they don't use it.
13 
14   Author: Frank da Cruz.
15   As of version 1.6 of 30 March 2011, E-Kermit is Open Source software under
16   the Revised 3-Clause BSD license which follows.  E-Kermit 1.6 is identical
17   to version 1.51 except for the new license.
18 
19   Author: Frank da Cruz.
20 
21   Copyright (C) 1995, 2011,
22   Trustees of Columbia University in the City of New York.
23   All rights reserved.
24 
25   Redistribution and use in source and binary forms, with or without
26   modification, are permitted provided that the following conditions are met:
27 
28   * Redistributions of source code must retain the above copyright notice,
29     this list of conditions and the following disclaimer.
30 
31   * Redistributions in binary form must reproduce the above copyright notice,
32     this list of conditions and the following disclaimer in the documentation
33     and/or other materials provided with the distribution.
34 
35   * Neither the name of Columbia University nor the names of its contributors
36     may be used to endorse or promote products derived from this software
37     without specific prior written permission.
38 
39   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
40   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
43   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
44   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
45   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
46   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49   POSSIBILITY OF SUCH DAMAGE.
50 */
51 #include "cdefs.h"			/* C language defs for all modules */
52 #include "debug.h"			/* Debugging */
53 #include "kermit.h"			/* Kermit protocol definitions */
54 
55 #define zgetc() \
56 ((--(k->zincnt))>=0)?((int)(*(k->zinptr)++)&0xff):(*(k->readf))(k)
57 
58 /* See cdefs.h for meaning of STATIC, ULONG, and UCHAR */
59 
60 STATIC ULONG stringnum(UCHAR *, struct k_data *);
61 STATIC UCHAR * numstring(ULONG, UCHAR *, int, struct k_data *);
62 int STATIC spkt(char, short, int, UCHAR *, struct k_data *);
63 int STATIC ack(struct k_data *, short, UCHAR * text);
64 int STATIC nak(struct k_data *, short, short);
65 int STATIC chk1(UCHAR *, struct k_data *);
66 STATIC USHORT chk2(UCHAR *, struct k_data *);
67 #ifdef F_CRC
68 STATIC USHORT chk3(UCHAR *, struct k_data *);
69 #endif /* F_CRC */
70 void STATIC spar(struct k_data *, UCHAR *, int);
71 int STATIC rpar(struct k_data *, char);
72 int STATIC decode(struct k_data *, struct k_response *, short, UCHAR *);
73 #ifdef F_AT
74 int STATIC gattr(struct k_data *, UCHAR *, struct k_response *);
75 int STATIC sattr(struct k_data *, struct k_response *);
76 #endif /* F_AT */
77 #ifndef RECVONLY
78 int STATIC sdata(struct k_data *, struct k_response *);
79 #endif /* RECVONLY */
80 void STATIC epkt(char *, struct k_data *);
81 int STATIC getpkt(struct k_data *, struct k_response *);
82 int STATIC encstr(UCHAR *, struct k_data *, struct k_response *);
83 void STATIC decstr(UCHAR *, struct k_data *, struct k_response *);
84 void STATIC encode(int, int, struct k_data *);
85 int STATIC nxtpkt(struct k_data *);
86 int STATIC resend(struct k_data *);
87 #ifdef DEBUG
88 int xerror(void);
89 #endif /* DEBUG */
90 
91 int					/* The kermit() function */
kermit(short f,struct k_data * k,short r_slot,int len,char * msg,struct k_response * r)92 kermit(short f,				/* Function code */
93        struct k_data *k,		/* The control struct */
94        short r_slot,			/* Received packet slot number */
95        int len,				/* Length of packet in slot */
96        char *msg,			/* Message for error packet */
97        struct k_response *r) {		/* Response struct */
98 
99     int i, j, rc;			/* Workers */
100     int datalen;                        /* Length of packet data field */
101     UCHAR *p;                           /* Pointer to packet data field */
102     UCHAR *q;                           /* Pointer to data to be checked */
103     UCHAR *s;				/* Worker string pointer */
104     UCHAR c, t;                         /* Worker chars */
105     UCHAR pbc[4];                       /* Copy of packet block check */
106     short seq, prev;			/* Copies of sequence numbers */
107     short chklen;                       /* Length of packet block check */
108 #ifdef F_CRC
109     unsigned int crc;                   /* 16-bit CRC */
110 #endif /* F_CRC */
111     int ok;
112 
113     debug(DB_MSG,"----------",0,0);	/* Marks each entry */
114     debug(DB_LOG,"f",0,f);
115     debug(DB_LOG,"state",0,k->state);
116     debug(DB_LOG,"zincnt",0,(k->zincnt));
117 
118     if (f == K_INIT) {			/* Initialize packet buffers etc */
119 
120 	k->version = (UCHAR *)VERSION;	/* Version of this module */
121         r->filename[0] = '\0';		/* No filename yet. */
122         r->filedate[0] = '\0';		/* No filedate yet. */
123         r->filesize = 0L;               /* No filesize yet. */
124 	r->sofar = 0L;			/* No bytes transferred yet */
125 
126         for (i = 0; i < P_WSLOTS; i++) { /* Packet info for each window slot */
127 	    freerslot(k,i);
128 	    freesslot(k,i);
129 	}
130 #ifdef F_TSW
131         for (i = 0; i < 64; i++) {	/* Packet finder array */
132 	    k->r_pw[i] = -1;		/* initialized to "no packets yet" */
133 	    k->s_pw[i] = -1;		/* initialized to "no packets yet" */
134 	}
135 #endif /* F_TSW */
136 
137 /* Initialize the k_data structure */
138 
139 	for (i = 0; i < 6; i++)
140 	  k->s_remain[i] = '\0';
141 
142         k->state    = R_WAIT;		/* Beginning protocol state */
143 	r->status   = R_WAIT;
144 	k->what     = W_RECV;		/* Default action */
145 	k->s_first  = 1;		/* Beginning of file */
146         k->r_soh    = k->s_soh = SOH;	/* Packet start */
147         k->r_eom    = k->s_eom = CR;	/* Packet end */
148         k->s_seq    = k->r_seq =  0;	/* Packet sequence number */
149         k->s_type   = k->r_type = 0;	/* Packet type */
150         k->r_timo   = P_R_TIMO;		/* Timeout interval for me to use */
151         k->s_timo   = P_S_TIMO;		/* Timeout for other Kermit to use */
152         k->r_maxlen = P_PKTLEN;         /* Maximum packet length */
153         k->s_maxlen = P_PKTLEN;         /* Maximum packet length */
154         k->window   = P_WSLOTS;		/* Maximum window slots */
155         k->wslots   = 1;		/* Current window slots */
156 	k->zincnt   = 0;
157 	k->dummy    = 0;
158 	k->filename = (UCHAR *)0;
159 
160         /* Parity must be filled in by the caller */
161 
162         k->retry  = P_RETRY;            /* Retransmission limit */
163         k->s_ctlq = k->r_ctlq = '#';    /* Control prefix */
164         k->ebq    = 'Y';		/* 8th-bit prefix negotiation */
165 	k->ebqflg = 0;			/* 8th-bit prefixing flag */
166         k->rptq   = '~';		/* Send repeat prefix */
167         k->rptflg = 0;                  /* Repeat counts negotiated */
168 	k->s_rpt  = 0;			/* Current repeat count */
169         k->capas  = 0                   /* Capabilities */
170 #ifdef F_LP
171           | CAP_LP                      /* Long packets */
172 #endif /* F_LP */
173 #ifdef F_SW
174             | CAP_SW                    /* Sliding windows */
175 #endif /* F_SW */
176 #ifdef F_AT
177               | CAP_AT                  /* Attribute packets */
178 #endif /* F_AT */
179                 ;
180 
181 	k->opktbuf[0] = '\0';		/* No packets sent yet. */
182 	k->opktlen = 0;
183 
184 #ifdef F_CRC
185 /* This is the only way to initialize these tables -- no static data. */
186 
187         k->crcta[ 0] =       0;		/* CRC generation table A */
188         k->crcta[ 1] =  010201;
189         k->crcta[ 2] =  020402;
190         k->crcta[ 3] =  030603;
191         k->crcta[ 4] =  041004;
192         k->crcta[ 5] =  051205;
193         k->crcta[ 6] =  061406;
194         k->crcta[ 7] =  071607;
195         k->crcta[ 8] = 0102010;
196         k->crcta[ 9] = 0112211;
197         k->crcta[10] = 0122412;
198         k->crcta[11] = 0132613;
199         k->crcta[12] = 0143014,
200         k->crcta[13] = 0153215;
201         k->crcta[14] = 0163416;
202         k->crcta[15] = 0173617;
203 
204         k->crctb[ 0] =       0;        /* CRC table B */
205         k->crctb[ 1] =  010611;
206         k->crctb[ 2] =  021422;
207         k->crctb[ 3] =  031233;
208         k->crctb[ 4] =  043044;
209         k->crctb[ 5] =  053655;
210         k->crctb[ 6] =  062466;
211         k->crctb[ 7] =  072277;
212         k->crctb[ 8] = 0106110;
213         k->crctb[ 9] = 0116701;
214         k->crctb[10] = 0127532;
215         k->crctb[11] = 0137323;
216         k->crctb[12] = 0145154;
217         k->crctb[13] = 0155745;
218         k->crctb[14] = 0164576;
219         k->crctb[15] = 0174367;
220 #endif /* F_CRC */
221 
222 	return(X_OK);
223 
224 #ifndef RECVONLY
225     } else if (f == K_SEND) {
226 	if (rpar(k,'S') != X_OK)	/* Send S packet with my parameters */
227 	  return(X_ERROR);		/* I/O error, quit. */
228 	k->state = S_INIT;		/* All OK, switch states */
229 	r->status = S_INIT;
230 	k->what = W_SEND;		/* Act like a sender */
231         return(X_OK);
232 #endif /* RECVONLY */
233 
234     } else if (f == K_STATUS) {         /* Status report requested. */
235         return(X_STATUS);               /* File name, date, size, if any. */
236 
237     } else if (f == K_QUIT) {           /* You told me to quit */
238         return(X_DONE);                 /* so I quit. */
239 
240     } else if (f == K_ERROR) {          /* Send an error packet... */
241         epkt(msg,k);
242 	k->closef(k,0,(k->state == S_DATA) ? 1 : 2); /* Close file */
243         return(X_DONE);                 /* and quit. */
244 
245     } else if (f != K_RUN) {            /* Anything else is an error. */
246         return(X_ERROR);
247     }
248     if (k->state == R_NONE)             /* (probably unnecessary) */
249       return(X_OK);
250 
251 /* If we're in the protocol, check to make sure we got a new packet */
252 
253     debug(DB_LOG,"r_slot",0,r_slot);
254     debug(DB_LOG,"len",0,len);
255 
256     if (r_slot < 0)			/* We should have a slot here */
257       return(K_ERROR);
258     else
259       k->ipktinfo[r_slot].len = len;	/* Copy packet length to ipktinfo. */
260 
261     if (len < 4) {			/* Packet obviously no good? */
262 #ifdef RECVONLY
263 	return(nak(k,k->r_seq,r_slot)); /* Send NAK for the packet we want */
264 #else
265 	if (k->what == W_RECV)		/* If receiving */
266 	  return(nak(k,k->r_seq,r_slot)); /* Send NAK for the packet we want */
267 	else				/* If sending */
268 	  return(resend(k));		/* retransmit last packet. */
269 #endif /* RECVONLY */
270     }
271 
272 /* Parse the packet */
273 
274     if (k->what == W_RECV) {		/* If we're sending ACKs */
275 	switch(k->cancel) {		/* Get cancellation code if any */
276 	  case 0: s = (UCHAR *)0;   break;
277 	  case 1: s = (UCHAR *)"X"; break;
278 	  case 2: s = (UCHAR *)"Z"; break;
279 	}
280     }
281     p = &(k->ipktbuf[0][r_slot]);	/* Point to it */
282 
283     q = p;                              /* Pointer to data to be checked */
284     k->ipktinfo[r_slot].len = xunchar(*p++); /* Length field */
285     seq = k->ipktinfo[r_slot].seq = xunchar(*p++); /* Sequence number */
286     t = k->ipktinfo[r_slot].typ = *p++;	/* Type */
287 
288     if (
289 #ifndef RECVONLY
290 	(k->what == W_RECV) &&		/* Echo (it happens), ignore */
291 #endif /* RECVONLY */
292 	(t == 'N' || t  == 'Y')) {
293         freerslot(k,r_slot);
294         return(X_OK);
295     }
296     k->ipktinfo[r_slot].dat = p;	/* Data field, maybe */
297 #ifdef F_LP
298     if (k->ipktinfo[r_slot].len == 0) {	/* Length 0 means long packet */
299         c = p[2];                       /* Get header checksum */
300         p[2] = '\0';
301         if (xunchar(c) != chk1(p-3,k)) {  /* Check it */
302             freerslot(k,r_slot);	/* Bad */
303 	    debug(DB_MSG,"HDR CHKSUM BAD",0,0);
304 #ifdef RECVONLY
305 	    return(nak(k,k->r_seq,r_slot)); /* Send NAK */
306 #else
307 	    if (k->what == W_RECV)
308 	      return(nak(k,k->r_seq,r_slot)); /* Send NAK */
309 	    else
310 	      return(resend(k));
311 #endif /* RECVONLY */
312         }
313 	debug(DB_MSG,"HDR CHKSUM OK",0,0);
314         p[2] = c;                       /* Put checksum back */
315 	/* Data length */
316         datalen = xunchar(p[0])*95 + xunchar(p[1]) - ((k->bctf) ? 3 : k->bct);
317         p += 3;                         /* Fix data pointer */
318         k->ipktinfo[r_slot].dat = p;	/* Permanent record of data pointer */
319     } else {                            /* Regular packet */
320 #endif /* F_LP */
321         datalen = k->ipktinfo[r_slot].len - k->bct - 2; /* Data length */
322 #ifdef F_LP
323     }
324 #endif /* F_LP */
325 #ifdef F_CRC
326     if (k->bctf) {			/* FORCE 3 */
327 	chklen = 3;
328     } else {
329 	if (t == 'S' || k->state == S_INIT) { /* S-packet was retransmitted? */
330 	    if (q[10] == '5') {		/* Block check type requested is 5 */
331 		k->bctf = 1;		/* FORCE 3 */
332 		chklen = 3;
333 	    }
334 	    chklen = 1;			/* Block check is always type 1 */
335 	    datalen = k->ipktinfo[r_slot].len - 3; /* Data length */
336 	} else {
337 	    chklen = k->bct;
338 	}
339     }
340 #else
341     chklen = 1;				/* Block check is always type 1 */
342     datalen = k->ipktinfo[r_slot].len - 3; /* Data length */
343 #endif /* F_CRC */
344     debug(DB_LOG,"bct",0,(k->bct));
345     debug(DB_LOG,"datalen",0,datalen);
346     debug(DB_LOG,"chkalen",0,chklen);
347 
348 #ifdef F_CRC
349     for (i = 0; i < chklen; i++)        /* Copy the block check */
350       pbc[i] = p[datalen+i];
351     pbc[i] = '\0';			/* Null-terminate block check string */
352 #else
353     pbc[0] = p[datalen];
354     pbc[1] = '\0';
355 #endif /* F_CRC */
356     p[datalen] = '\0';			/* and the packet DATA field. */
357 #ifdef F_CRC
358     switch (chklen) {                   /* Check the block check  */
359       case 1:				/* Type 1, 6-bit checksum */
360 #endif /* F_CRC */
361 	ok = (xunchar(*pbc) == chk1(q,k));
362 #ifdef DEBUG
363 	if (ok && xerror()) ok = 0;
364 #endif /* DEBUG */
365 	if (!ok) {
366 	    freerslot(k,r_slot);
367 #ifdef RECVONLY
368 	    nak(k,k->r_seq,r_slot);
369 #else
370 	    if (k->what == W_RECV)
371 	      nak(k,k->r_seq,r_slot);
372 	    else
373 	      resend(k);
374 #endif /* RECVONLY */
375 	    return(X_OK);
376 	}
377 #ifdef F_CRC
378 	break;
379 
380       case 2:                         /* Type 2, 12-bit checksum */
381 	i = xunchar(*pbc) << 6 | xunchar(pbc[1]);
382 	ok = (i == chk2(q,k));
383 #ifdef DEBUG
384 	if (ok && xerror()) ok = 0;
385 #endif /* DEBUG */
386 	if (!ok) {			/* No match */
387 	    if (t == 'E') {		/* Allow E packets to have type 1 */
388 		int j;
389 		j = datalen;
390 		p[j++] = pbc[0];
391 		p[j] = '\0';
392 		if (xunchar(pbc[1]) == chk1(q,k))
393 		  break;
394 		else
395 		  p[--j] = '\0';
396 	    }
397 	    freerslot(k,r_slot);
398 #ifdef RECVONLY
399 	    nak(k,k->r_seq,r_slot);
400 #else
401 	    if (k->what == W_RECV)
402 	      nak(k,k->r_seq,r_slot);
403 	    else
404 	      resend(k);
405 #endif /* RECVONLY */
406 	    return(X_OK);
407 	}
408 	break;
409 
410       case 3:				/* Type 3, 16-bit CRC */
411 	crc = (xunchar(pbc[0]) << 12)
412 	  | (xunchar(pbc[1]) << 6)
413 	    | (xunchar(pbc[2]));
414 	ok = (crc == chk3(q,k));
415 #ifdef DEBUG
416 	if (ok && xerror()) {
417 	    ok = 0;
418 	    debug(DB_MSG,"CRC ERROR INJECTED",0,0);
419 	}
420 #endif /* DEBUG */
421 	if (!ok) {
422 	    debug(DB_LOG,"CRC ERROR t",0,t);
423 	    if (t == 'E') {		/* Allow E packets to have type 1 */
424 		int j;
425 		j = datalen;
426 		p[j++] = pbc[0];
427 		p[j++] = pbc[1];
428 		p[j] = '\0';
429 		if (xunchar(pbc[2]) == chk1(q,k))
430 		  break;
431 		else { j -=2; p[j] = '\0'; }
432 	    }
433 	    freerslot(k,r_slot);
434 #ifdef RECVONLY
435 	    nak(k,k->r_seq,r_slot);
436 #else
437 	    if (k->what == W_RECV)
438 	      nak(k,k->r_seq,r_slot);
439 	    else
440 	      resend(k);
441 #endif /* RECVONLY */
442 	    return(X_OK);
443 	}
444     }
445 #endif /* F_CRC */
446     if (t == 'E')			/* (AND CLOSE FILES?) */
447       return(X_ERROR);
448 
449     prev = k->r_seq - 1;		/* Get sequence of previous packet */
450     if (prev < 0)
451       prev = 63;
452 
453     debug(DB_LOG,"Seq",0,seq);
454     debug(DB_LOG,"Prev",0,prev);
455 
456     if (seq == k->r_seq) {		/* Is this the packet we want? */
457 	k->ipktinfo[r_slot].rtr = 0;	/* Yes */
458     } else {
459         freerslot(k,r_slot);		/* No, discard it. */
460 
461         if (seq == prev) {              /* If it's the previous packet again */
462 	    debug(DB_LOG,"PREVIOUS PKT RETRIES",0,
463 		  (long)(k->ipktinfo[r_slot].rtr));
464             if (k->ipktinfo[r_slot].rtr++ > k->retry) { /* Count retries */
465                 epkt("Too many retries", k); /* Too may */
466                 return(X_ERROR);	/* Give up */
467             } else {			/* Otherwise */
468 		return(resend(k));	/* Send old outbound packet buffer */
469             }
470 #ifdef RECVONLY
471 	} else {
472 	    return(nak(k,k->r_seq,r_slot));
473 #else
474         } else if (k->what == W_RECV) {	/* Otherwise NAK the one we want */
475 	    return(nak(k,k->r_seq,r_slot));
476 	} else {			/* or whatever... */
477 	    return(resend(k));
478 #endif /* RECVONLY */
479 	}
480     }
481 #ifndef RECVONLY
482     if (k->what == W_SEND) {		/* Sending, check for ACK */
483 	if (t != 'Y') {			/* Not an ACK */
484 	    debug(DB_LOG,"t!=Y t",0,t);
485 	    freerslot(k,r_slot);	/* added 2004-06-30 -- JHD */
486 	    return(resend(k));
487 	}
488 	if (k->state == S_DATA) {	/* ACK to Data packet?*/
489 	    if (k->cancel ||		/* Cancellation requested by caller? */
490 		*p == 'X' || *p == 'Z') { /* Or by receiver? */
491 		k->closef(k,*p,1);	  /* Close input file*/
492 		nxtpkt(k);		  /* Next packet sequence number */
493 		if ((rc = spkt('Z',k->s_seq,0,(UCHAR *)0,k)) != X_OK)
494 		  return(rc);
495 		if (*p == 'Z' || k->cancel == I_GROUP) { /* Cancel Group? */
496 		    debug(DB_MSG,"Group Cancel (Send)",0,0);
497 		    while (*(k->filelist)) { /* Go to end of file list */
498 			debug(DB_LOG,"Skip",*(k->filelist),0);
499 			(k->filelist)++;
500 		    }
501 		}
502 		k->state = S_EOF;	/* Wait for ACK to EOF */
503 		r->status = S_EOF;
504 		k->r_seq = k->s_seq;	/* Sequence number of packet we want */
505 		return(X_OK);
506 	    }
507 	}
508 	freerslot(k,r_slot);		/* It is, free the ACK. */
509     }
510 #endif /* RECVONLY */
511 
512 /* Now we have an incoming packet with the expected sequence number. */
513 
514     debug(DB_CHR,"Packet OK",0,t);
515     debug(DB_LOG,"State",0,k->state);
516 
517     switch (k->state) {                 /* Kermit protocol state switcher */
518 
519 #ifndef RECVONLY
520       case S_INIT:			/* Got other Kermit's parameters */
521       case S_EOF:			/* Got ACK to EOF packet */
522 	nxtpkt(k);			/* Get next packet number etc */
523 	if (k->state == S_INIT) {	/* Got ACK to S packet? */
524 	    spar(k,p,datalen);		/* Set negotiated parameters */
525 	    debug(DB_CHR,"Parity",0,k->parity);
526 	    debug(DB_LOG,"Ebqflg",0,(k->ebqflg));
527 	    debug(DB_CHR,"Ebq",0,(k->ebq));
528 	}
529 	k->filename = *(k->filelist);	/* Get next filename */
530 	if (k->filename) {		/* If there is one */
531 	    int i;
532 	    for (i = 0; i < FN_MAX; i++) { /* Copy name to result struct */
533 		r->filename[i] = k->filename[i];
534 		if (!(r->filename[i]))
535 		    break;
536 	    }
537 	    (k->filelist)++;
538 	    debug(DB_LOG,"Filename",k->filename,0);
539 	    if ((rc = (k->openf)(k,k->filename,1)) != X_OK) /* Try to open */
540 	      return(rc);
541 	    encstr(k->filename,k,r);	/* Encode the name for transmission */
542 	    if ((rc = spkt('F',k->s_seq,-1,k->xdata,k)) != X_OK)
543 	      return(rc);		/* Send F packet */
544 	    r->sofar = 0L;
545 	    k->state = S_FILE;		/* Wait for ACK */
546 	    r->status = S_FILE;
547 	} else {			/* No more files - we're done */
548 	    if ((rc = spkt('B',k->s_seq,0,(UCHAR *)0,k)) != X_OK)
549 	      return(rc);		/* Send EOT packet */
550 	    k->state = S_EOT;		/* Wait for ACK */
551 	    r->status = S_EOT;
552 	}
553 	k->r_seq = k->s_seq;		/* Sequence number of packet we want */
554 	return(X_OK);			/* Return to control program */
555 
556       case S_FILE:			/* Got ACK to F packet */
557 	nxtpkt(k);			/* Get next packet number etc */
558 #ifdef F_AT
559 	if (k->capas & CAP_AT) {	/* A-packets negotiated? */
560 	    if ((rc = sattr(k,r)) != X_OK) /* Yes, send Attribute packet */
561 	      return(rc);
562 	    k->state = S_ATTR;		/* And wait for its ACK */
563 	    r->status = S_ATTR;
564 	} else
565 #endif /* F_AT */
566 	  if (sdata(k,r) == 0) {	/* No A packets - send first data */
567 	    /* File is empty so send EOF packet */
568 	    if ((rc = spkt('Z',k->s_seq,0,(UCHAR *)0,k)) != X_OK)
569 	      return(rc);
570 	    k->closef(k,*p,1);		/* Close input file*/
571 	    k->state = S_EOF;		/* Wait for ACK to EOF */
572 	    r->status = S_EOF;
573 	} else {			/* Sent some data */
574 	    k->state = S_DATA;		/* Wait for ACK to first data */
575 	    r->status = S_DATA;
576 	}
577 	k->r_seq = k->s_seq;		/* Sequence number to wait for */
578 	return(X_OK);
579 
580       case S_ATTR:			/* Got ACK to A packet */
581       case S_DATA:			/* Got ACK to D packet */
582 	nxtpkt(k);			/* Get next packet number */
583 	if (k->state == S_ATTR) {
584 	    /* CHECK ATTRIBUTE RESPONSE */
585 	    /* IF REJECTED do the right thing... */
586 	    k->state = S_DATA;
587 	    r->status = S_DATA;
588 	}
589 	rc = sdata(k,r);		/* Send first or next data packet */
590 
591 	debug(DB_LOG,"Seq",0,(k->s_seq));
592 	debug(DB_LOG,"sdata()",0,rc);
593 
594 	if (rc == 0) {			/* If there was no data to send */
595 	    if ((rc = spkt('Z',k->s_seq,0,(UCHAR *)0,k)) != X_OK)
596 	      return(rc);		/* Send EOF */
597 	    k->closef(k,*p,1);		/* Close input file*/
598 	    k->state = S_EOF;		/* And wait for ACK */
599 	    r->status = S_EOF;
600 	}				/* Otherwise stay in data state */
601 	k->r_seq = k->s_seq;		/* Sequence number to wait for */
602 	return(X_OK);
603 
604       case S_EOT:			/* Get ACK to EOT packet */
605         return(X_DONE);			/* (or X_ERROR) */
606 #endif /* RECVONLY */
607 
608       case R_WAIT:                      /* Waiting for the S packet */
609         if (t == 'S') {                 /* Got it */
610             spar(k,p,datalen);          /* Set parameters from it */
611             rc = rpar(k,'Y');		/* ACK with my parameters */
612 	    debug(DB_LOG,"rpar rc",0,rc);
613             if (rc != X_OK)
614               return(X_ERROR);          /* I/O error, quit. */
615             k->state = R_FILE;          /* All OK, switch states */
616             r->status = R_FILE;
617         } else {                        /* Wrong kind of packet, send NAK */
618             epkt("Unexpected packet type",k);
619             rc = X_ERROR;
620         }
621         freerslot(k,r_slot);		/* Free packet slot */
622         return(rc);
623 
624       case R_FILE:                      /* Want an F or B packet */
625         if (t == 'F') {                 /* File name */
626             if ((rc = decode(k, r, 0, p)) == X_OK) /* Decode and save */
627               k->state = R_ATTR;        /* Switch to next state */
628 	    r->status = k->state;
629 	    debug(DB_LOG,"R_FILE decode rc",0,rc);
630 	    debug(DB_LOG,"R_FILE FILENAME",r->filename,0);
631             if (rc == X_OK) {		/* All OK so far */
632 		r->filedate[0] = '\0';	/* No file date yet */
633 		r->filesize = 0L;	/* Or file size */
634 		r->sofar = 0L;		/* Or bytes transferred yet */
635 		rc = ack(k, k->r_seq, r->filename); /* so ACK the F packet */
636 	    } else {
637 		epkt("Filename error",k); /* Error decoding filename */
638 	    }
639         } else if (t == 'B') {          /* Break, end of transaction */
640             freerslot(k,r_slot);
641             rc = (ack(k, k->r_seq, (UCHAR *)0) == X_OK) ? X_DONE : X_ERROR;
642 
643         } else {
644             epkt("Unexpected packet type",k);
645             rc = X_ERROR;
646         }
647         freerslot(k,r_slot);
648         return(rc);
649 
650       case R_ATTR:                      /* Want A, D, or Z packet */
651 #ifdef F_AT
652         if (t == 'A') {                 /* Attribute packet */
653 	    int x;
654             x = gattr(k, p, r);		/* Read the attributes */
655 	    if (x > -1)
656 	      k->binary = x;
657             freerslot(k,r_slot);
658             ack(k, k->r_seq, (UCHAR *) "Y"); /* Always accept the file */
659             return(X_OK);
660         } else
661 #endif /* F_AT */
662 	  if (t == 'D') {		/* First data packet */
663             k->obufpos = 0;             /* Initialize output buffer */
664 	    k->filename = r->filename;
665 	    r->sofar = 0L;
666             if ((rc = (*(k->openf))(k,r->filename, 2)) == X_OK) {
667                 k->state = R_DATA;      /* Switch to Data state */
668 		r->status = k->state;
669                 rc = decode(k, r, 1, p); /* Write out first data packet */
670                 freerslot(k,r_slot);
671             } else {
672                 epkt("File refused or can't be opened", k);
673                 freerslot(k,r_slot);
674                 return(rc);
675             }
676             if (rc == X_OK)
677               rc = ack(k, k->r_seq, s);
678             else
679               epkt("Error writing data", k);
680             return(rc);
681 	} else if (t == 'Z') {		/* Empty file */
682 	    debug(DB_LOG,"R_ATTR empty file",r->filename,0);
683             k->obufpos = 0;             /* Initialize output buffer */
684 	    k->filename = r->filename;
685 	    r->sofar = 0L;		/* Open and close the file */
686             if ((rc = (*(k->openf))(k,r->filename, 2)) == X_OK) {
687 		if (((rc = (*(k->closef))(k,*p,2)) == X_OK)) {
688 		    k->state = R_FILE;
689 		    rc = ack(k, k->r_seq, s);
690 		} else {
691 		    epkt("Error closing empty file", k);
692 		    freerslot(k,r_slot);
693 		    return(rc);
694 		}
695             } else {
696                 epkt("File refused or can't be opened", k);
697                 freerslot(k,r_slot);
698                 return(rc);
699             }
700 	    r->status = k->state;
701             freerslot(k,r_slot);
702 
703         } else {
704             epkt("Unexpected packet type",k);
705             return(X_ERROR);
706         }
707         break;
708 
709       case R_DATA:                      /* Want a D or Z packet */
710 	debug(DB_CHR,"R_DATA t",0,t);
711         if (t == 'D') {                 /* Data */
712             rc = decode(k, r, 1, p);	/* Decode it */
713             freerslot(k,r_slot);
714         } else if (t == 'Z') {          /* End of file */
715 	    debug(DB_CHR,"R_DATA",0,t);
716             if (k->obufpos > 0) {       /* Flush output buffer */
717                 rc = (*(k->writef))(k,k->obuf,k->obufpos);
718 		debug(DB_LOG,"R_DATA writef rc",0,rc);
719 		r->sofar += k->obufpos;
720                 k->obufpos = 0;
721             }
722             if (((rc = (*(k->closef))(k,*p,2)) == X_OK) && (rc == X_OK))
723               k->state = R_FILE;
724 	    debug(DB_LOG,"R_DATA closef rc",0,rc);
725 	    r->status = k->state;
726             freerslot(k,r_slot);
727         } else {
728             epkt("Unexpected packet type",k);
729             return(X_ERROR);
730         }
731         if (rc == X_OK)
732           rc = ack(k, k->r_seq, s);
733         else
734           epkt(t == 'Z' ? "Can't close file" : "Error writing data",k);
735         return(rc);
736 
737       case R_ERROR:                     /* Canceled from above */
738       default:
739         epkt(msg,k);
740         return(X_ERROR);
741     }
742     return(X_ERROR);
743 }
744 
745 /* Utility routines */
746 
747 UCHAR *
getrslot(struct k_data * k,short * n)748 getrslot(struct k_data *k, short *n) {   /* Find a free packet buffer */
749     register int i;
750 /*
751   Note: We don't clear the retry count here.
752   It is cleared only after the NEXT packet arrives, which
753   indicates that the other Kermit got our ACK for THIS packet.
754 */
755     for (i = 0; i < P_WSLOTS; i++) {    /* Search */
756         if (k->ipktinfo[i].len < 1) {
757             *n = i;                     /* Slot number */
758             k->ipktinfo[i].len = -1;	/* Mark it as allocated but not used */
759             k->ipktinfo[i].seq = -1;
760             k->ipktinfo[i].typ = SP;
761             /* k->ipktinfo[i].rtr =  0; */  /* (see comment above) */
762             k->ipktinfo[i].dat = (UCHAR *)0;
763             return(&(k->ipktbuf[0][i]));
764         }
765     }
766     *n = -1;
767     return((UCHAR *)0);
768 }
769 
770 void					/* Initialize a window slot */
freerslot(struct k_data * k,short n)771 freerslot(struct k_data *k, short n) {
772     k->ipktinfo[n].len = 0;		/* Packet length */
773 #ifdef COMMENT
774     k->ipktinfo[n].seq = 0;		/* Sequence number */
775     k->ipktinfo[n].typ = (char)0;	/* Type */
776     k->ipktinfo[n].rtr = 0;		/* Retry count */
777     k->ipktinfo[n].flg = 0;		/* Flags */
778 #endif /* COMMENT */
779 }
780 
781 UCHAR *
getsslot(struct k_data * k,short * n)782 getsslot(struct k_data *k, short *n) {   /* Find a free packet buffer */
783 #ifdef COMMENT
784     register int i;
785     for (i = 0; i < P_WSLOTS; i++) {    /* Search */
786         if (k->opktinfo[i].len < 1) {
787             *n = i;                     /* Slot number */
788             k->opktinfo[i].len = -1;	/* Mark it as allocated but not used */
789             k->opktinfo[i].seq = -1;
790             k->opktinfo[i].typ = SP;
791             k->opktinfo[i].rtr =  0;
792             k->opktinfo[i].dat = (UCHAR *)0;
793             return(&(k->opktbuf[0][i]));
794         }
795     }
796     *n = -1;
797     return((UCHAR *)0);
798 #else
799     *n = 0;
800     return(k->opktbuf);
801 #endif /* COMMENT */
802 }
803 
804 void                                    /* Initialize a window slot */
freesslot(struct k_data * k,short n)805 freesslot(struct k_data * k, short n) {
806     k->opktinfo[n].len = 0;		/* Packet length */
807     k->opktinfo[n].seq = 0;		/* Sequence number */
808     k->opktinfo[n].typ = (char)0;	/* Type */
809     k->opktinfo[n].rtr = 0;		/* Retry count */
810     k->opktinfo[n].flg = 0;		/* Flags */
811 }
812 
813 /*  C H K 1  --  Compute a type-1 Kermit 6-bit checksum.  */
814 
815 STATIC int
chk1(UCHAR * pkt,struct k_data * k)816 chk1(UCHAR *pkt, struct k_data * k) {
817     register unsigned int chk;
818     chk = chk2(pkt,k);
819     chk = (((chk & 0300) >> 6) + chk) & 077;
820     return((int) chk);
821 }
822 
823 /*  C H K 2  --  Numeric sum of all the bytes in the packet, 12 bits.  */
824 
825 STATIC USHORT
chk2(UCHAR * pkt,struct k_data * k)826 chk2(UCHAR *pkt,struct k_data * k) {
827     register USHORT chk;
828     for (chk = 0; *pkt != '\0'; pkt++)
829       chk += *pkt;
830     return(chk);
831 }
832 
833 #ifdef F_CRC
834 
835 /*  C H K 3  --  Compute a type-3 Kermit block check.  */
836 /*
837  Calculate the 16-bit CRC-CCITT of a null-terminated string using a lookup
838  table.  Assumes the argument string contains no embedded nulls.
839 */
840 STATIC USHORT
chk3(UCHAR * pkt,struct k_data * k)841 chk3(UCHAR *pkt, struct k_data * k) {
842     register USHORT c, crc;
843     for (crc = 0; *pkt != '\0'; pkt++) {
844 #ifdef COMMENT
845         c = crc ^ (long)(*pkt);
846         crc = (crc >> 8) ^ (k->crcta[(c & 0xF0) >> 4] ^ k->crctb[c & 0x0F]);
847 #else
848 	c = crc ^ (*pkt);
849        crc = (crc >> 8) ^ ((k->crcta[(c & 0xF0) >> 4]) ^ (k->crctb[c & 0x0F]));
850 #endif	/*  COMMENT */
851     }
852     return(crc);
853 }
854 #endif /* F_CRC */
855 
856 /*   S P K T  --  Send a packet.  */
857 /*
858   Call with packet type, sequence number, data length, data, Kermit struct.
859   Returns:
860     X_OK on success
861     X_ERROR on i/o error
862 */
863 STATIC int
spkt(char typ,short seq,int len,UCHAR * data,struct k_data * k)864 spkt(char typ, short seq, int len, UCHAR * data, struct k_data * k) {
865 
866     unsigned int crc;                   /* For building CRC */
867     int i, j, lenpos, m, n, x;		/* Workers */
868     UCHAR * s, * buf;
869 
870     debug(DB_LOG,"spkt len 1",0,len);
871     if (len < 0) {			/* Calculate data length ourselves? */
872 	len = 0;
873 	s = data;
874 	while (*s++) len++;
875     }
876     debug(DB_LOG,"spkt len 2",0,len);
877     buf = k->opktbuf;			/* Where to put packet (FOR NOW) */
878 
879     i = 0;                              /* Packet buffer position */
880     buf[i++] = k->s_soh;		/* SOH */
881     lenpos = i++;			/* Remember this place */
882     buf[i++] = tochar(seq);		/* Sequence number */
883     buf[i++] = typ;			/* Packet type */
884     j = len + k->bct;
885 #ifdef F_LP
886     if ((len + k->bct + 2) > 94) {	/* If long packet */
887 	buf[lenpos] = tochar(0);	/* Put blank in LEN field */
888 	buf[i++] = tochar(j / 95);	/* Make extended header: Big part */
889 	buf[i++] = tochar(j % 95);	/* and small part of length. */
890         buf[i] = NUL;			/* Terminate for header checksum */
891         buf[i++] = tochar(chk1(&buf[lenpos],k)); /* Insert header checksum */
892     } else {				/* Short packet */
893 #endif /* F_LP */
894 	buf[lenpos] = tochar(j+2);	/* Single-byte length in LEN field */
895 #ifdef F_LP
896     }
897 #endif /* F_LP */
898     if (data)                           /* Copy data, if any */
899       for ( ; len--; i++)
900         buf[i] = *data++;
901     buf[i] = '\0';
902 
903 #ifdef F_CRC
904     switch (k->bct) {                   /* Add block check */
905       case 1:                           /* 1 = 6-bit chksum */
906 	buf[i++] = tochar(chk1(&buf[lenpos],k));
907         break;
908       case 2:                           /* 2 = 12-bit chksum */
909         j = chk2(&buf[lenpos],k);
910 #ifdef XAC
911 	/* HiTech's XAC compiler silently ruins the regular code. */
912 	/* An intermediate variable provides a work-around. */
913 	/* 2004-06-29 -- JHD */
914 	{
915 	    USHORT jj;
916 	    jj = (j >> 6) & 077; buf[i++] = tochar(jj);
917 	    jj = j & 077;        buf[i++] = tochar(jj);
918 	}
919 #else
920         buf[i++] = (unsigned)tochar((j >> 6) & 077);
921         buf[i++] = (unsigned)tochar(j & 077);
922 #endif /* XAC */
923         break;
924       case 3:                           /* 3 = 16-bit CRC */
925         crc = chk3(&buf[lenpos],k);
926 #ifdef XAC
927 	/* HiTech's XAC compiler silently ruins the above code. */
928 	/* An intermediate variable provides a work-around. */
929 	/* 2004-06-29 -- JHD */
930 	{
931 	    USHORT jj;
932 	    jj = (crc >> 12) & 0x0f; buf[i++] = tochar(jj);
933 	    jj = (crc >>  6) & 0x3f; buf[i++] = tochar(jj);
934 	    jj =  crc        & 0x3f; buf[i++] = tochar(jj);
935 	}
936 #else
937         buf[i++] = (unsigned)tochar(((crc & 0170000)) >> 12);
938         buf[i++] = (unsigned)tochar((crc >> 6) & 077);
939         buf[i++] = (unsigned)tochar(crc & 077);
940 #endif /* XAC */
941         break;
942     }
943 #else
944     buf[i++] = tochar(chk1(&buf[lenpos],k));
945 #endif /* F_CRC */
946 
947     buf[i++] = k->s_eom;		/* Packet terminator */
948     buf[i] = '\0';			/* String terminator */
949     k->s_seq = seq;                     /* Remember sequence number */
950 
951     k->opktlen = i;			/* Remember length for retransmit */
952 
953 #ifdef DEBUG
954 /* CORRUPT THE PACKET SENT BUT NOT THE ONE WE SAVE */
955     if (xerror()) {
956 	UCHAR p[P_PKTLEN+8];
957 	int i;
958 	for (i = 0; i < P_PKTLEN; i++)
959 	  if (!(p[i] = buf[i]))
960 	    break;
961 	p[i-2] = 'X';
962 	debug(DB_PKT,"XPKT",(char *)&p[1],0);
963 	return((*(k->txd))(k,p,k->opktlen)); /* Send it. */
964     }
965     debug(DB_PKT,"SPKT",(char *)&buf[1],0);
966 #endif /* DEBUG */
967 
968     return((*(k->txd))(k,buf,k->opktlen)); /* Send it. */
969 }
970 
971 /*  N A K  --  Send a NAK (negative acknowledgement)  */
972 
973 STATIC int
nak(struct k_data * k,short seq,short slot)974 nak(struct k_data * k, short seq, short slot) {
975     int rc;
976     rc = spkt('N', seq, 0, (UCHAR *)0, k);
977     if (k->ipktinfo[slot].rtr++ > k->retry)
978       rc = X_ERROR;
979     return(rc);
980 }
981 
982 /*  A C K  --  Send an ACK (positive acknowledgement)  */
983 
984 STATIC int
ack(struct k_data * k,short seq,UCHAR * text)985 ack(struct k_data * k, short seq, UCHAR * text) {
986     int len, rc;
987     len = 0;
988     if (text) {                         /* Get length of data */
989         UCHAR *p;
990         p = text;
991         for ( ; *p++; len++) ;
992     }
993     rc = spkt('Y', seq, len, text, k);  /* Send the packet */
994     debug(DB_LOG,"ack spkt rc",0,rc);
995     if (rc == X_OK)                     /* If OK */
996       k->r_seq = (k->r_seq + 1) % 64;   /* bump the packet number */
997     return(rc);
998 }
999 
1000 /*  S P A R  --  Set parameters requested by other Kermit  */
1001 
1002 STATIC void
spar(struct k_data * k,UCHAR * s,int datalen)1003 spar(struct k_data * k, UCHAR *s, int datalen) {
1004     int x, y;
1005     UCHAR c;
1006 
1007     s--;                                /* Line up with field numbers. */
1008 
1009     if (datalen >= 1)                   /* Max packet length to send */
1010       k->s_maxlen = xunchar(s[1]);
1011 
1012     if (datalen >= 2)                   /* Timeout on inbound packets */
1013       k->r_timo = xunchar(s[2]);
1014 
1015     /* No padding */
1016 
1017     if (datalen >= 5)                   /* Outbound Packet Terminator */
1018       k->s_eom = xunchar(s[5]);
1019 
1020     if (datalen >= 6)                   /* Incoming control prefix */
1021       k->r_ctlq = s[6];
1022 
1023     if (datalen >= 7) {                 /* 8th bit prefix */
1024         k->ebq = s[7];
1025         if ((s[7] > 32 && s[7] < 63) || (s[7] > 95 && s[7] < 127)) {
1026 	    if (!k->parity)		/* They want it */
1027 	      k->parity = 1;		/* Set parity to something nonzero */
1028 	    k->ebqflg = 1;
1029 	} else if (s[7] == 'Y' && k->parity) {
1030 	    k->ebqflg = 1;
1031 	    k->ebq = '&';
1032 	} else if (s[7] == 'N') {
1033 	    /* WHAT? */
1034 	}
1035     }
1036     if (datalen >= 8) {                 /* Block check */
1037         k->bct = s[8] - '0';
1038 #ifdef F_CRC
1039         if ((k->bct < 1) || (k->bct > 3))
1040 #endif /* F_CRC */
1041 	  k->bct = 1;
1042 	if (k->bctf) k->bct = 3;
1043     }
1044     if (datalen >= 9) {                 /* Repeat counts */
1045         if ((s[9] > 32 && s[9] < 63) || (s[9] > 95 && s[9] < 127)) {
1046             k->rptq = s[9];
1047             k->rptflg = 1;
1048         }
1049     }
1050     if (datalen >= 10) {                /* Capability bits */
1051         x = xunchar(s[10]);
1052 
1053 #ifdef F_LP                             /* Long packets */
1054         if (!(x & CAP_LP))
1055 #endif /* F_LP */
1056           k->capas &= ~CAP_LP;
1057 
1058 #ifdef F_SW                             /* Sliding Windows */
1059         if (!(x & CAP_SW))
1060 #endif /* F_SW */
1061           k->capas &= ~CAP_SW;
1062 
1063 #ifdef F_AT                             /* Attributes */
1064         if (!(x & CAP_AT))
1065 #endif /* F_AT */
1066           k->capas &= ~CAP_AT;
1067 
1068 #ifdef F_RS                             /* Recovery */
1069         if (!(x & CAP_RS))
1070 #endif /* F_RS */
1071           k->capas &= ~CAP_RS;
1072 
1073 #ifdef F_LS                             /* Locking shifts */
1074         if (!(x & CAP_LS))
1075 #endif /* F_LS */
1076           k->capas &= ~CAP_LS;
1077 
1078         /* In case other Kermit sends addt'l capas fields ... */
1079 
1080         for (y = 10; (xunchar(s[y]) & 1) && (datalen >= y); y++) ;
1081     }
1082 
1083 #ifdef F_LP                             /* Long Packets */
1084     if (k->capas & CAP_LP) {
1085         if (datalen > y+1) {
1086             x = xunchar(s[y+2]) * 95 + xunchar(s[y+3]);
1087             k->s_maxlen = (x > P_PKTLEN) ? P_PKTLEN : x;
1088             if (k->s_maxlen < 10)
1089               k->s_maxlen = 60;
1090         }
1091     }
1092 #endif /* F_LP */
1093 
1094     debug(DB_LOG,"S_MAXLEN",0,k->s_maxlen);
1095 
1096 #ifdef F_SW
1097     if (k->capas & CAP_SW) {
1098         if (datalen > y) {
1099             x = xunchar(s[y+1]);
1100             k->window = (x > P_WSLOTS) ? P_WSLOTS : x;
1101             if (k->window < 1)          /* Watch out for bad negotiation */
1102               k->window = 1;
1103             if (k->window > 1)
1104               if (k->window > k->retry)   /* Retry limit must be greater */
1105                 k->retry = k->window + 1; /* than window size. */
1106         }
1107     }
1108 #endif /* F_SW */
1109 }
1110 
1111 /*  R P A R  --  Send my parameters to other Kermit  */
1112 
1113 STATIC int
rpar(struct k_data * k,char type)1114 rpar(struct k_data * k, char type) {
1115     UCHAR *d;
1116     int rc, len;
1117 #ifdef F_CRC
1118     short b;
1119 #endif /* F_CRC */
1120 
1121     d = k->ack_s;                       /* Where to put it */
1122     d[ 0] = tochar(94);                 /* Maximum short-packet length */
1123     d[ 1] = tochar(k->s_timo);          /* When I want to be timed out */
1124     d[ 2] = tochar(0);                  /* How much padding I need */
1125     d[ 3] = ctl(0);                     /* Padding character I want */
1126     d[ 4] = tochar(k->r_eom);           /* End-of message character I want */
1127     d[ 5] = k->s_ctlq;                  /* Control prefix I send */
1128     if ((k->ebq == 'Y') && (k->parity)) /* 8th-bit prefix */
1129       d[ 6] = k->ebq = '&';           /* I need to request it */
1130     else                                /* else just agree with other Kermit */
1131       d[ 6] = k->ebq;
1132     if (k->bctf)			/* Block check type */
1133       d[7] = '5';			/* FORCE 3 */
1134     else
1135       d[7] = k->bct + '0';		/* Normal */
1136     d[ 8] = k->rptq;			/* Repeat prefix */
1137     d[ 9] = tochar(k->capas);           /* Capability bits */
1138     d[10] = tochar(k->window);          /* Window size */
1139 
1140 #ifdef F_LP
1141     d[11] = tochar(k->r_maxlen / 95);   /* Long packet size, big part */
1142     d[12] = tochar(k->r_maxlen % 95);   /* Long packet size, little part */
1143     d[13] = '\0';			/* Terminate the init string */
1144     len = 13;
1145 #else
1146     d[11] = '\0';
1147     len = 11;
1148 #endif /* F_LP */
1149 
1150 #ifdef F_CRC
1151     if (!(k->bctf)) {			/* Unless FORCE 3 */
1152 	b = k->bct;
1153 	k->bct = 1;			/* Always use block check type 1 */
1154     }
1155 #endif /* F_CRC */
1156     switch (type) {
1157       case 'Y':				/* This is an ACK for packet 0 */
1158 	rc = ack(k,0,d);
1159 	break;
1160       case 'S':				/* It's an S packet */
1161 	rc = spkt('S', 0, len, d, k);
1162 	break;
1163       default:
1164 	rc = -1;
1165     }
1166 #ifdef F_CRC
1167     if (!(k->bctf)) {			/* Unless FORCE 3 */
1168 	k->bct = b;
1169     }
1170 #endif /* F_CRC */
1171     return(rc);                         /* Pass along return code. */
1172 }
1173 
1174 /*  D E C O D E  --  Decode data field of Kermit packet - binary mode only */
1175 /*
1176   Call with:
1177     k = kermit data structure
1178     r = kermit response structure
1179     f = function code
1180       0 = decode filename
1181       1 = decode file data
1182     inbuf = pointer to packet data to be decoded
1183   Returns:
1184     X_OK on success
1185     X_ERROR if output function fails
1186 */
1187 STATIC int
decode(struct k_data * k,struct k_response * r,short f,UCHAR * inbuf)1188 decode(struct k_data * k, struct k_response * r, short f, UCHAR *inbuf) {
1189 
1190     register unsigned int a, a7;        /* Current character */
1191     unsigned int b8;                    /* 8th bit */
1192     int rpt;                            /* Repeat count */
1193     int rc;				/* Return code */
1194     UCHAR *p;
1195 
1196     rc = X_OK;
1197     rpt = 0;                            /* Initialize repeat count. */
1198     if (f == 0)                         /* Output function... */
1199       p = r->filename;
1200 
1201     while ((a = *inbuf++ & 0xFF) != '\0') { /* Character loop */
1202         if (k->rptflg && a == k->rptq) { /* Got a repeat prefix? */
1203             rpt = xunchar(*inbuf++ & 0xFF); /* Yes, get the repeat count, */
1204             a = *inbuf++ & 0xFF;        /* and get the prefixed character. */
1205         }
1206         b8 = 0;                         /* 8th-bit value */
1207         if (k->parity && (a == k->ebq)) { /* Have 8th-bit prefix? */
1208             b8 = 0200;                  /* Yes, flag the 8th bit */
1209             a = *inbuf++ & 0x7F;        /* and get the prefixed character. */
1210         }
1211         if (a == k->r_ctlq) {           /* If control prefix, */
1212             a  = *inbuf++ & 0xFF;       /* get its operand */
1213             a7 = a & 0x7F;              /* and its low 7 bits. */
1214             if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') /* Controllify */
1215               a = ctl(a);               /* if in control range. */
1216         }
1217         a |= b8;                        /* OR in the 8th bit */
1218 
1219         if (rpt == 0) rpt = 1;          /* If no repeats, then one */
1220 
1221         for (; rpt > 0; rpt--) {        /* Output the char 'rpt' times */
1222             if (f == 0) {
1223                 *p++ = (UCHAR) a;       /* to memory */
1224             } else {                    /* or to file */
1225                 k->obuf[k->obufpos++] = (UCHAR) a; /* Deposit the byte */
1226                 if (k->obufpos == k->obuflen) { /* Buffer full? */
1227                     rc = (*(k->writef))(k,k->obuf,k->obuflen); /* Dump it. */
1228 		    r->sofar += k->obuflen;
1229 		    if (rc != X_OK) break;
1230                     k->obufpos = 0;
1231                 }
1232             }
1233         }
1234     }
1235     if (f == 0)                         /* If writing to memory */
1236       *p = '\0';			/* terminate the string */
1237     return(rc);
1238 }
1239 
1240 STATIC ULONG				/* Convert decimal string to number  */
stringnum(UCHAR * s,struct k_data * k)1241 stringnum(UCHAR *s, struct k_data * k) {
1242     long n;
1243     n = 0L;
1244     while (*s == SP)
1245       s++;
1246     while(*s >= '0' && *s <= '9')
1247       n = n * 10 + (*s++ - '0');
1248     return(n);
1249 }
1250 
1251 STATIC UCHAR *				/* Convert number to string */
numstring(ULONG n,UCHAR * buf,int buflen,struct k_data * k)1252 numstring(ULONG n, UCHAR * buf, int buflen, struct k_data * k) {
1253     int i, x;
1254     buf[buflen - 1] = '\0';
1255     for (i = buflen - 2; i > 0; i--) {
1256 	x = n % 10L;
1257 	buf[i] = x + '0';
1258 	n /= 10L;
1259 	if (!n)
1260 	  break;
1261     }
1262     if (n) {
1263 	return((UCHAR *)0);
1264     }
1265     if (i > 0) {
1266 	UCHAR * p, * s;
1267 	s = &buf[i];
1268 	p = buf;
1269 	while ((*p++ = *s++)) ;
1270 	*(p-1) = '\0';
1271     }
1272     return((UCHAR *)buf);
1273 }
1274 
1275 #ifdef F_AT
1276 
1277 /*
1278   G A T T R  --  Read incoming attributes.
1279 
1280   Returns:
1281    -1 if no transfer mode (text/binary) was announced.
1282     0 if text was announced.
1283     1 if binary was announced.
1284 */
1285 
1286 #define SIZEBUFL 32                     /* For number conversions */
1287 
1288 STATIC int
gattr(struct k_data * k,UCHAR * s,struct k_response * r)1289 gattr(struct k_data * k, UCHAR * s, struct k_response * r) {
1290     long fsize, fsizek;                 /* File size */
1291     UCHAR c;                            /* Workers */
1292     int aln, i, rc;
1293 
1294     UCHAR sizebuf[SIZEBUFL+1];
1295 
1296     rc = -1;
1297     while ((c = *s++)) {		/* Get attribute tag */
1298         aln = xunchar(*s++);            /* Length of attribute string */
1299         switch (c) {
1300           case '!':                     /* File length in K */
1301 	  case '"':			/* File type */
1302             for (i = 0; (i < aln) && (i < SIZEBUFL); i++) /* Copy it */
1303               sizebuf[i] = *s++;
1304             sizebuf[i] = '\0';           /* Terminate with null */
1305             if (i < aln) s += (aln - i); /* If field was too long for buffer */
1306 	    if (c == '!') {		     /* Length */
1307 		fsizek = stringnum(sizebuf,k); /* Convert to number */
1308 	    } else {			     /* Type */
1309 		if (sizebuf[0] == 'A')	     /* Text */
1310 		  rc = 0;
1311 		else if (sizebuf[0] == 'B')  /* Binary */
1312 		  rc = 1;
1313 		debug(DB_LOG,"gattr rc",0,rc);
1314 		debug(DB_LOG,"gattr size",sizebuf,0);
1315 	    }
1316             break;
1317 
1318           case '#':                     /* File creation date */
1319             for (i = 0; (i < aln) && (i < DATE_MAX); i++)
1320               r->filedate[i] = *s++;    /* Copy it into a static string */
1321             if (i < aln) s += (aln - i);
1322             r->filedate[i] = '\0';
1323             break;
1324 
1325           case '1':                     /* File length in bytes */
1326             for (i = 0; (i < aln) && (i < SIZEBUFL); i++) /* Copy it */
1327               sizebuf[i] = *s++;
1328             sizebuf[i] = '\0';           /* Terminate with null */
1329             if (i < aln) s += (aln - i);
1330             fsize = stringnum(sizebuf,k); /* Convert to number */
1331             break;
1332 
1333 	  default:			/* Unknown attribute */
1334 	    s += aln;			/* Just skip past it */
1335 	    break;
1336         }
1337     }
1338     if (fsize > -1L) {			/* Remember the file size */
1339         r->filesize = fsize;
1340     } else if (fsizek > -1L) {
1341         r->filesize = fsizek * 1024L;
1342     }
1343     debug(DB_LOG,"gattr r->filesize",0,(r->filesize));
1344     debug(DB_LOG,"gattr r->filedate=",r->filedate,0);
1345     return(rc);
1346 }
1347 
1348 #define ATTRLEN 48
1349 
1350 STATIC int
sattr(struct k_data * k,struct k_response * r)1351 sattr(struct k_data *k, struct k_response *r) {	/* Build and send A packet */
1352     int i, x, aln;
1353     short tmp;
1354     long filelength;
1355     UCHAR datebuf[DATE_MAX], * p;
1356 
1357     debug(DB_LOG,"sattr k->zincnt 0",0,(k->zincnt));
1358 
1359     tmp = k->binary;
1360     filelength = (*(k->finfo))
1361 	(k,k->filename,datebuf,DATE_MAX,&tmp,k->xfermode);
1362     k->binary = tmp;
1363 
1364     debug(DB_LOG,"sattr filename: ",k->filename,0);
1365     debug(DB_LOG,"sattr filedate: ",datebuf,0);
1366     debug(DB_LOG,"sattr filelength",0,filelength);
1367     debug(DB_LOG,"sattr binary",0,(k->binary));
1368 
1369     i = 0;
1370 
1371     k->xdata[i++] = '"';
1372     if (k->binary) {			/* Binary */
1373 	k->xdata[i++] = tochar(2);	/*  Two characters */
1374 	k->xdata[i++] = 'B';		/*  B for Binary */
1375 	k->xdata[i++] = '8';		/*  8-bit bytes (note assumption...) */
1376     } else {				/* Text */
1377 	k->xdata[i++] = tochar(3);	/*  Three characters */
1378 	k->xdata[i++] = 'A';		/*  A = (extended) ASCII with CRLFs */
1379 	k->xdata[i++] = 'M';		/*  M for carriage return */
1380 	k->xdata[i++] = 'J';		/*  J for linefeed */
1381 	k->xdata[i++] = '*';		/* Encoding */
1382 	k->xdata[i++] = tochar(1);	/* Length of value is 1 */
1383 	k->xdata[i++] = 'A';		/* A for ASCII */
1384     }
1385     if (filelength > -1L) {		/* File length in bytes */
1386 	UCHAR lenbuf[16];
1387 	r->filesize = filelength;
1388 	p = numstring(filelength,lenbuf,16,k);
1389 	if (p) {
1390 	    for (x = 0; p[x]; x++) ;	/* Get length of length string */
1391 	    if (i + x < ATTRLEN - 3) {	/* Don't overflow buffer */
1392 		k->xdata[i++] = '1';	/* Length-in-Bytes attribute */
1393 		k->xdata[i++] = tochar(x);
1394 		while (*p)
1395 		  k->xdata[i++] = *p++;
1396 	    }
1397 	}
1398     }
1399     debug(DB_LOG,"sattr DATEBUF: ",datebuf,0);
1400 
1401     if (datebuf[0]) {			/* File modtime */
1402 	p = datebuf;
1403 	for (x = 0; p[x]; x++) ;	/* Length of modtime */
1404 	if (i + x < ATTRLEN - 3) {	/* If it will fit */
1405 	    k->xdata[i++] = '#';	/* Add modtime attribute */
1406 	    k->xdata[i++] = tochar(x);	/* Its length */
1407 	    while (*p)			/* And itself */
1408 	      k->xdata[i++] = *p++;
1409 	    /* Also copy modtime to result struct */
1410 	    for (x = 0; x < DATE_MAX-1 && datebuf[x]; x++)
1411 	      r->filedate[x] = datebuf[x];
1412 	    r->filedate[x] = '\0';
1413 	}
1414     }
1415     k->xdata[i++] = '@';		/* End of Attributes */
1416     k->xdata[i++] = ' ';
1417     k->xdata[i] = '\0';			/* Terminate attribute string */
1418     debug(DB_LOG,"sattr k->xdata: ",k->xdata,0);
1419     return(spkt('A',k->s_seq,-1,k->xdata,k));
1420 }
1421 #endif /* F_AT */
1422 
1423 STATIC int
getpkt(struct k_data * k,struct k_response * r)1424 getpkt(struct k_data *k, struct k_response *r) { /* Fill a packet from file */
1425     int i, next, rpt, maxlen;
1426     static int c;			/* PUT THIS IN STRUCT */
1427 
1428     debug(DB_LOG,"getpkt k->s_first",0,(k->s_first));
1429     debug(DB_LOG,"getpkt k->s_remain=",k->s_remain,0);
1430 
1431     maxlen = k->s_maxlen - k->bct - 3;	/* Maximum data length */
1432     if (k->s_first == 1) {		/* If first time thru...  */
1433 	k->s_first = 0;			/* don't do this next time, */
1434 	k->s_remain[0] = '\0';		/* discard any old leftovers. */
1435 	if (k->istring) {		/* Get first byte. */
1436 	    c = *(k->istring)++;	/* Of memory string... */
1437 	    if (!c) c = -1;
1438 	} else {			/* or file... */
1439 #ifdef DEBUG
1440 	    k->zincnt = -1234;
1441 	    k->dummy = 0;
1442 #endif /* DEBUG */
1443 	    c = zgetc();
1444 
1445 #ifdef DEBUG
1446 	    if (k->dummy) debug(DB_LOG,"DUMMY CLOBBERED (A)",0,0);
1447 #endif /* DEBUG */
1448 	}
1449 	if (c < 0) {			/* Watch out for empty file. */
1450 	    debug(DB_CHR,"getpkt first c",0,c);
1451 	    k->s_first = -1;
1452 	    return(k->size = 0);
1453 	}
1454 	r->sofar++;
1455 	debug(DB_LOG,"getpkt first c",0,c);
1456     } else if (k->s_first == -1 && !k->s_remain[0]) { /* EOF from last time? */
1457         return(k->size = 0);
1458     }
1459     for (k->size = 0;
1460 	 (k->xdata[k->size] = k->s_remain[k->size]) != '\0';
1461 	 (k->size)++)
1462       ;
1463     k->s_remain[0] = '\0';
1464     if (k->s_first == -1)
1465       return(k->size);
1466 
1467     rpt = 0;				/* Initialize repeat counter. */
1468     while (k->s_first > -1) {		/* Until end of file or string... */
1469 	if (k->istring) {
1470 	    next = *(k->istring)++;
1471 	    if (!next) next = -1;
1472 	} else {
1473 #ifdef DEBUG
1474 	    k->dummy = 0;
1475 #endif /* DEBUG */
1476 	    next = zgetc();
1477 #ifdef DEBUG
1478 	    if (k->dummy) debug(DB_LOG,"DUMMY CLOBBERED B",0,k->dummy);
1479 #endif /* DEBUG */
1480 	}
1481 	if (next < 0) {			/* If none, we're at EOF. */
1482 	    k->s_first = -1;
1483 	} else {			/* Otherwise */
1484 	    r->sofar++;			/* count this byte */
1485 	}
1486         k->osize = k->size;		/* Remember current size. */
1487         encode(c,next,k);		/* Encode the character. */
1488 	/* k->xdata[k->size] = '\0'; */
1489 	c = next;			/* Old next char is now current. */
1490 
1491         if (k->size == maxlen)		/* Just at end, done. */
1492 	  return(k->size);
1493 
1494         if (k->size > maxlen) {		/* Past end, must save some. */
1495             for (i = 0;
1496 		 (k->s_remain[i] = k->xdata[(k->osize)+i]) != '\0';
1497 		 i++)
1498 	      ;
1499             k->size = k->osize;
1500             k->xdata[k->size] = '\0';
1501             return(k->size);		/* Return size. */
1502         }
1503     }
1504     return(k->size);			/* EOF, return size. */
1505 }
1506 
1507 #ifndef RECVONLY
1508 STATIC int
sdata(struct k_data * k,struct k_response * r)1509 sdata(struct k_data *k,struct k_response *r) { /* Send a data packet */
1510     int len, rc;
1511     if (k->cancel) {			/* Interrupted */
1512 	debug(DB_LOG,"sdata interrupted k->cancel",0,(k->cancel));
1513 	return(0);
1514     }
1515     len = getpkt(k,r);			/* Fill data field from input file */
1516     debug(DB_LOG,"sdata getpkt",0,len);
1517     if (len < 1)
1518       return(0);
1519     rc = spkt('D',k->s_seq,len,k->xdata,k); /* Send the packet */
1520     debug(DB_LOG,"sdata spkt",0,rc);
1521     return((rc == X_ERROR) ? rc : len);
1522 }
1523 #endif /* RECVONLY */
1524 
1525 /*  E P K T  --  Send a (fatal) Error packet with the given message  */
1526 
1527 STATIC void
epkt(char * msg,struct k_data * k)1528 epkt(char * msg, struct k_data * k) {
1529     if (!(k->bctf)) {			/* Unless FORCE 3 */
1530 	k->bct = 1;
1531     }
1532     (void) spkt('E', 0, -1, (UCHAR *) msg, k);
1533 }
1534 
1535 STATIC int				/* Fill a packet from string s. */
encstr(UCHAR * s,struct k_data * k,struct k_response * r)1536 encstr(UCHAR * s, struct k_data * k, struct k_response *r) {
1537     k->s_first = 1;			/* Start lookahead. */
1538     k->istring = s;			/* Set input string pointer */
1539     getpkt(k,r);			/* Fill a packet */
1540     k->istring = (UCHAR *)0;		/* Reset input string pointer */
1541     k->s_first = 1;			/* "Rewind" */
1542     return(k->size);			/* Return data field length */
1543 }
1544 
1545 /* Decode packet data into a string */
1546 
1547 STATIC void
decstr(UCHAR * s,struct k_data * k,struct k_response * r)1548 decstr(UCHAR * s, struct k_data * k, struct k_response * r) {
1549     k->ostring = s;			/* Set output string pointer  */
1550     (void) decode(k, r, 0, s);
1551     *(k->ostring) = '\0';		/* Terminate with null */
1552     k->ostring = (UCHAR *)0;		/* Reset output string pointer */
1553 }
1554 
1555 STATIC void
encode(int a,int next,struct k_data * k)1556 encode(int a, int next, struct k_data * k) { /* Encode character into packet */
1557     int a7, b8, maxlen;
1558 
1559     maxlen = k->s_maxlen - 4;
1560     if (k->rptflg) {			/* Doing run-length encoding? */
1561 	if (a == next) {		/* Yes, got a run? */
1562 	    if (++(k->s_rpt) < 94) {	/* Yes, count. */
1563 		return;
1564 	    } else if (k->s_rpt == 94) { /* If at maximum */
1565 	    	k->xdata[(k->size)++] = k->rptq; /* Emit prefix, */
1566 		k->xdata[(k->size)++] = tochar(k->s_rpt); /* and count, */
1567 		k->s_rpt = 0;		/* and reset counter. */
1568 	    }
1569 	} else if (k->s_rpt == 1) {	/* Run broken, only two? */
1570 	    k->s_rpt = 0;		/* Yes, do the character twice */
1571 	    encode(a,-1,k);		/* by calling self recursively. */
1572 	    if (k->size <= maxlen)	/* Watch boundary. */
1573 	      k->osize = k->size;
1574 	    k->s_rpt = 0;		/* Call self second time. */
1575 	    encode(a,-1,k);
1576 	    return;
1577 	} else if (k->s_rpt > 1) {	/* Run broken, more than two? */
1578 	    k->xdata[(k->size)++] = k->rptq; /* Yes, emit prefix and count */
1579 	    k->xdata[(k->size)++] = tochar(++(k->s_rpt));
1580 	    k->s_rpt = 0;		/* and reset counter. */
1581 	}
1582     }
1583     a7 = a & 127;			/* Get low 7 bits of character */
1584     b8 = a & 128;			/* And "parity" bit */
1585 
1586     if (k->ebqflg && b8) {		/* If doing 8th bit prefixing */
1587 	k->xdata[(k->size)++] = k->ebq; /* and 8th bit on, insert prefix */
1588 	a = a7;				/* and clear the 8th bit. */
1589     }
1590     if (a7 < 32 || a7 == 127) {		   /* If in control range */
1591         k->xdata[(k->size)++] = k->s_ctlq; /* insert control prefix */
1592         a = ctl(a);			 /* and make character printable. */
1593     } else if (a7 == k->s_ctlq)		 /* If data is control prefix, */
1594       k->xdata[(k->size)++] = k->s_ctlq; /* prefix it. */
1595     else if (k->ebqflg && a7 == k->ebq)  /* If doing 8th-bit prefixing, */
1596       k->xdata[(k->size)++] = k->s_ctlq; /* ditto for 8th-bit prefix. */
1597     else if (k->rptflg && a7 == k->rptq) /* If doing run-length encoding, */
1598       k->xdata[(k->size)++] = k->s_ctlq; /* ditto for repeat prefix. */
1599 
1600     k->xdata[(k->size)++] = a;		/* Finally, emit the character. */
1601     k->xdata[(k->size)] = '\0';		/* Terminate string with null. */
1602 }
1603 
1604 STATIC int
nxtpkt(struct k_data * k)1605 nxtpkt(struct k_data * k) {		/* Get next packet to send */
1606     k->s_seq = (k->s_seq + 1) & 63;	/* Next sequence number */
1607     k->xdata = k->xdatabuf;
1608     return(0);
1609 }
1610 
1611 STATIC int
resend(struct k_data * k)1612 resend(struct k_data * k) {
1613     UCHAR * buf;
1614     if (!k->opktlen)			/* Nothing to resend */
1615       return(X_OK);
1616     buf = k->opktbuf;
1617     debug(DB_PKT,">PKT",&buf[1],k->opktlen);
1618     return((*(k->txd))(k,buf,k->opktlen));
1619 }
1620