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