1 /*
2 * binkleyforce -- unix FTN mailer project
3 *
4 * Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * $Id: prot_zmmisc.c,v 1.1.1.1 2004/09/09 09:52:39 kstepanenkov Exp $
12 */
13
14 #include "includes.h"
15 #include "confread.h"
16 #include "logger.h"
17 #include "util.h"
18 #include "io.h"
19 #include "prot_zmodem.h"
20
21 int Z_Rxexp; /* True means timer expired */
22 int Z_Rxtout; /* Seconds to wait for receiving whole block */
23 int Z_Rxwait; /* Seconds to wait for character available */
24 int Z_Rxframeind; /* ZBIN ZBIN32, or ZHEX type of frame received */
25 int Z_Rxtype; /* Type of header received */
26 int Z_Rxcount; /* Count of data bytes received */
27 int Z_Txnulls; /* Number of nulls to send at beginning of ZDATA hdr */
28 char Z_Rxhdr[4]; /* Received header */
29 char Z_Txhdr[4]; /* Transmitted header */
30 long Z_Rxpos; /* Received file position */
31 int Z_Txfcs32; /* TRUE means send binary frames with 32 bit FCS */
32 int Z_Txcrc32; /* Display flag indicating 32 bit CRC being sent */
33 int Z_Rxcrc32; /* Display flag indicating 32 bit CRC being received */
34 char Z_Attn[ZATTNLEN+1];/* Attention string rx sends to tx on err */
35 int Z_Ctlesc; /* Encode control characters */
36 int Z_Lastsent; /* Character we sent last */
37
38 #ifdef DEBUG
39 static const char *FrameTypes[] =
40 {
41 "Unused", /* (-7) */
42 "Unused", /* (-6) */
43 "CRC error", /* ZCRCERR (-5) */
44 "Bad frame", /* ZERROR (-4) */
45 "I/O Error", /* ZEXIT (-3) */
46 "Carrier Lost", /* ZHANGUP (-2) */
47 "Timer out", /* ZTIMER (-1) */
48 #define FTOFFSET 7
49 "ZRQINIT",
50 "ZRINIT",
51 "ZSINIT",
52 "ZACK",
53 "ZFILE",
54 "ZSKIP",
55 "ZNAK",
56 "ZABORT",
57 "ZFIN",
58 "ZRPOS",
59 "ZDATA",
60 "ZEOF",
61 "ZFERR",
62 "ZCRC",
63 "ZCHALLENGE",
64 "ZCOMPL",
65 "ZCAN",
66 "ZFREECNT",
67 "ZCOMMAND",
68 "ZSTDERR",
69 "Unused"
70 #define FRTYPES 22 /* Total number of frame types in this array */
71 /* not including psuedo negative entries */
72 };
73 #endif
74
75 static int zrbhdr16(char *hdr);
76 static int zrbhdr32(char *hdr);
77 static int zrhhdr(char *hdr);
78 static int zrdat32(char *buf, int length, long pos);
79 static int zrdat16(char *buf, int length, long pos);
80 static int zgethex(void);
81 static int noxrd7(void);
82 static int zdlread(void);
83 static int zputhex(int c);
84 static void zsendline_init(char *);
85
zalarmh(int sig_no)86 static void zalarmh(int sig_no)
87 {
88 DEB((D_PROT, "zalarmh: got SIGALRM (timer expired!)"));
89 Z_Rxexp = 1;
90 }
91
setalarm(int sec)92 void setalarm(int sec)
93 {
94 static int allready = 0;
95
96 if( !sec )
97 {
98 alarm(0); return;
99 }
100
101 Z_Rxexp = 0;
102
103 if( allready == 0 )
104 {
105 if( signal(SIGALRM, zalarmh) == SIG_ERR )
106 {
107 logerr("can't setup SIGALRM handler");
108 return;
109 }
110 allready = 1;
111 }
112
113 alarm(sec);
114 }
115
116 /* ------------------------------------------------------------------------- */
117 /* Read a byte, checking for ZMODEM escape encoding */
118 /* including five CAN which represents a quick abort */
119 /* ------------------------------------------------------------------------- */
zmodem_getbyte(void)120 static int zmodem_getbyte(void)
121 {
122 int c;
123 int cancount = 0;
124 int gotdle = 0;
125
126 while(1)
127 {
128 if( Z_Rxexp )
129 return ZTIMER;
130
131 if( (c = GETCHAR(Z_Rxwait)) < 0 )
132 return c;
133
134 if( gotdle )
135 {
136 if( c != CAN )
137 cancount = 0;
138
139 switch( c ) {
140 case CAN:
141 if( ++cancount > 5 )
142 return GOTCAN;
143 break;
144 case ZCRCE:
145 case ZCRCG:
146 case ZCRCQ:
147 case ZCRCW:
148 return c|GOTOR;
149 case ZRUB0:
150 return 0177;
151 case ZRUB1:
152 return 0377;
153 case XON:
154 case XOFF:
155 case XON|0200:
156 case XOFF|0200:
157 break;
158 default:
159 if( !Z_Ctlesc || (c & 140) )
160 {
161 if( (c & 0140) == 0100 )
162 return c^0100;
163 else
164 bf_log("zmodem: got bad escape sequence 0x%x", c);
165 }
166 }
167 }
168 else
169 {
170 switch(c) {
171 case ZDLE:
172 gotdle = 1;
173 break;
174 case XON:
175 case XOFF:
176 case XON|0200:
177 case XOFF|0200:
178 break;
179 default:
180 if( !Z_Ctlesc || (c & 0140) )
181 {
182 return c;
183 }
184 }
185 }
186 }
187
188 return 0;
189 }
190
zmodem_getbyte_raw(void)191 static int zmodem_getbyte_raw(void)
192 {
193 int c;
194
195 while(1)
196 {
197 if( Z_Rxexp )
198 return ZTIMER;
199
200 if( (c = GETCHAR(Z_Rxwait)) < 0 )
201 return c;
202
203 c &= 0177;
204
205 switch(c) {
206 case XON:
207 case XOFF:
208 break;
209 case '\r':
210 case '\n':
211 case ZDLE:
212 return c;
213 default:
214 if( !Z_Ctlesc || (c & 0140) )
215 return c;
216 }
217 }
218
219 return 0;
220 }
221
zmodem_putbyte(int c)222 static int zmodem_putbyte(int c)
223 {
224 static int last_esc = -2;
225 static char tab[256];
226 int rc;
227
228 if( Z_Ctlesc != last_esc )
229 {
230 zsendline_init(tab);
231 last_esc = Z_Ctlesc;
232 }
233
234 switch( tab[(unsigned char)(c)] ) {
235 case 0:
236 if( (rc = BUFCHAR(Z_Lastsent = c)) < 0 )
237 return rc;
238 break;
239
240 case 1:
241 if( (rc = BUFCHAR(ZDLE)) < 0 )
242 return rc;
243 c ^= 0100;
244 if( (rc = BUFCHAR(Z_Lastsent = c)) < 0 )
245 return rc;
246 break;
247
248 case 2:
249 /* Escape for telnet escape sequence */
250 if( (Z_Lastsent & 0177) != '@' )
251 {
252 if( (rc = BUFCHAR(Z_Lastsent = c)) < 0 )
253 return rc;
254 }
255 else
256 {
257 c ^= 0100;
258 if( (rc = BUFCHAR(ZDLE)) < 0 )
259 return rc;
260 if( (rc = BUFCHAR(Z_Lastsent = c)) < 0 )
261 return rc;
262 }
263 break;
264
265 default:
266 ASSERT_MSG();
267 }
268
269 return ZOK;
270 }
271
zdlread(void)272 static int zdlread(void)
273 {
274 int c, cancnt = 0;
275
276 /* Quick check for non control characters */
277 for(;;)
278 {
279 if( Z_Rxexp )
280 return(ZTIMER);
281
282 c = GETCHAR(Z_Rxwait);
283
284 if( (c & 0140) || (c < 0) )
285 return(c);
286
287 switch( c ) {
288 case ZDLE:
289 break;
290 case XON:
291 case XOFF:
292 case XON|0200:
293 case XOFF|0200:
294 continue;
295 default:
296 if( Z_Ctlesc && !(c & 0140) )
297 continue;
298 return(c);
299 }
300 break;
301 }
302
303 for(;;)
304 {
305 if( Z_Rxexp )
306 return(ZTIMER);
307
308 if( (c = GETCHAR(Z_Rxwait)) < 0 )
309 return(c);
310
311 if( c != CAN )
312 cancnt = 0;
313
314 switch( c ) {
315 case CAN:
316 if( ++cancnt >= 5 )
317 return(GOTCAN);
318 continue;
319 case ZCRCE:
320 case ZCRCG:
321 case ZCRCQ:
322 case ZCRCW:
323 return(c | GOTOR);
324 case ZRUB0:
325 return(0177);
326 case ZRUB1:
327 return(0377);
328 case XON:
329 case XOFF:
330 case XON|0200:
331 case XOFF|0200:
332 continue;
333 default:
334 if( Z_Ctlesc && !(c & 0140) )
335 continue;
336 if( (c & 0140) == 0100 )
337 return(c^0100);
338
339 /* It was unknown escape sequence */
340 DEB((D_PROT, "zdlread: bad escape sequence 0x%x", c));
341
342 return(ZERROR);
343 }
344 }
345 }
346
347 /* ------------------------------------------------------------------------- */
348 /* Read a character from the modem line with timeout. */
349 /* Eat parity, XON and XOFF characters. */
350 /* ------------------------------------------------------------------------- */
noxrd7(void)351 static int noxrd7(void)
352 {
353 int c;
354
355 for(;;)
356 {
357 if( Z_Rxexp )
358 return(ZTIMER);
359
360 if( (c = GETCHAR(Z_Rxwait)) < 0 )
361 return(c);
362
363 switch( c &= 0177 ) {
364 case XON:
365 case XOFF:
366 continue;
367 default:
368 if( Z_Ctlesc && !(c & 0140) )
369 continue;
370 case '\r':
371 case '\n':
372 case ZDLE:
373 return(c);
374 }
375 }
376 }
377
378 /* ------------------------------------------------------------------------- */
379 /* Send character $c with ZMODEM escape sequence encoding. */
380 /* Escape XON, XOFF. Escape CR following @ (Telenet net escape) */
381 /* Warning: Put result to buffer with BUFCHAR function! Use FLUSHBUF later! */
382 /* ------------------------------------------------------------------------- */
zsendline(char c)383 int zsendline(char c)
384 {
385 static int last_esc = -2;
386 static char tab[256];
387 int rc;
388
389 if( Z_Ctlesc != last_esc )
390 {
391 zsendline_init(tab);
392 last_esc = Z_Ctlesc;
393 }
394
395 switch( tab[(unsigned char)(c)] ) {
396 case 0:
397 if( (rc = BUFCHAR(Z_Lastsent = c)) < 0 )
398 return(rc);
399 break;
400 case 1:
401 if( (rc = BUFCHAR(ZDLE)) < 0 )
402 return(rc);
403 c ^= 0100;
404 if( (rc = BUFCHAR(Z_Lastsent = c)) < 0 )
405 return(rc);
406 break;
407 case 2:
408 /* Escape for telnet escape sequence */
409 if( (Z_Lastsent & 0177) != '@' )
410 {
411 if( (rc = BUFCHAR(Z_Lastsent = c)) < 0 )
412 return(rc);
413 }
414 else
415 {
416 c ^= 0100;
417 if( (rc = BUFCHAR(ZDLE)) < 0 )
418 return(rc);
419 if( (rc = BUFCHAR(Z_Lastsent = c)) < 0 )
420 return(rc);
421 }
422 break;
423 }
424
425 return(ZOK);
426 }
427
428 /* ------------------------------------------------------------------------- */
429 /* Send ZMODEM binary header hdr of type $type */
430 /* ------------------------------------------------------------------------- */
zsbhdr(int type,char * hdr)431 int zsbhdr(int type, char *hdr)
432 {
433 int n, rc;
434 unsigned short crc;
435 unsigned long crc32;
436
437 DEB((D_PROT, "zsbhdr: %s %lx (CRC%s)", FrameTypes[type+FTOFFSET],
438 rclhdr(hdr), Z_Txfcs32?"32":"16"));
439
440 if( type == ZDATA )
441 for( n=Z_Txnulls; --n >= 0; )
442 {
443 if( (rc = BUFCHAR('\0')) < 0 )
444 return(rc);
445 }
446
447 if( (rc = BUFCHAR(ZPAD)) < 0 )
448 return(rc);
449 if( (rc = BUFCHAR(ZDLE)) < 0 )
450 return(rc);
451
452 Z_Txcrc32 = Z_Txfcs32;
453
454 if( Z_Txcrc32 )
455 {
456 /* Use CRC32 */
457 crc32 = 0xFFFFFFFFL;
458
459 if( (rc = BUFCHAR(ZBIN32)) < 0 )
460 return(rc);
461 if( (rc = zsendline(type)) < 0 )
462 return(rc);
463 crc32 = updcrc32(type, crc32);
464
465 for( n = 4; --n >= 0; ++hdr )
466 {
467 crc32 = updcrc32((0377 & *hdr), crc32);
468 if( (rc = zsendline((*hdr) & 0377)) < 0 )
469 return(rc);
470 }
471
472 crc32 = ~crc32;
473
474 for( n = 4; --n >= 0; )
475 {
476 if( (rc = zsendline(crc32 & 0377)) < 0 )
477 return(rc);
478 crc32 >>= 8;
479 }
480 }
481 else /* CRC-16 */
482 {
483 crc = 0;
484
485 if( (rc = BUFCHAR(ZBIN)) < 0 )
486 return rc;
487 if( (rc = zsendline(type)) < 0 )
488 return(rc);
489 crc = updcrc16(type, crc);
490
491 for( n = 4; --n >= 0; ++hdr )
492 {
493 if( (rc = zsendline((*hdr) & 0377)) < 0 )
494 return(rc);
495 crc = updcrc16(((*hdr) & 0377), crc);
496 }
497
498 crc = updcrc16(0,updcrc16(0,crc));
499 if( (rc = zsendline((crc>>8) & 0377)) < 0 )
500 return(rc);
501 if( (rc = zsendline((crc ) & 0377)) < 0 )
502 return(rc);
503 }
504
505 if( (rc = FLUSHBUF()) < 0 )
506 return(rc);
507 if( type != ZDATA && (rc = FLUSHOUT()) < 0 )
508 return rc;
509
510 return(0);
511 }
512
513 /* ------------------------------------------------------------------------- */
514 /* Send ZMODEM HEX header hdr of type $type */
515 /* ------------------------------------------------------------------------- */
zshhdr(int type,char * hdr)516 int zshhdr(int type, char *hdr)
517 {
518 int n, rc;
519 unsigned short crc;
520
521 DEB((D_PROT, "zshhdr: %s %lx (CRC16)",
522 FrameTypes[(type & 0x7f)+FTOFFSET], rclhdr(hdr)));
523
524 Z_Txcrc32 = 0;
525
526 if( (rc = BUFCHAR(ZPAD)) < 0 ) return(rc);
527 if( (rc = BUFCHAR(ZPAD)) < 0 ) return(rc);
528 if( (rc = BUFCHAR(ZDLE)) < 0 ) return(rc);
529 if( (rc = BUFCHAR(ZHEX)) < 0 ) return(rc);
530 if( (rc = zputhex(type)) < 0 ) return(rc);
531
532 crc = updcrc16(type, 0);
533 for( n = 4; --n >= 0; ++hdr )
534 {
535 if( (rc = zputhex(*hdr & 0377)) < 0 )
536 return(rc);
537 crc = updcrc16((*hdr & 0377), crc);
538 }
539
540 crc = updcrc16(0, updcrc16(0,crc));
541 if( (rc = zputhex((crc>>8)&0377)) < 0 ) return(rc);
542 if( (rc = zputhex((crc )&0377)) < 0 ) return(rc);
543
544 /* Make it printable on remote machine */
545 if( (rc = BUFCHAR('\r')) < 0 ) return(rc);
546 if( (rc = BUFCHAR('\n')) < 0 ) return(rc);
547
548 /* Uncork the remote in case a fake XOFF has stopped data flow */
549 if( type != ZFIN && type != ZACK )
550 {
551 if( (rc = BUFCHAR(XON)) < 0 )
552 return(rc);
553 }
554
555 if( (rc = FLUSHBUF()) < 0 ) return(rc);
556 if( (rc = FLUSHOUT()) < 0 ) return(rc);
557
558 return(0);
559 }
560
561 /* ------------------------------------------------------------------------- */
562 /* Send binary array buf of length length, with ending ZDLE sequence frameend*/
563 /* $pos must point to current offset of sending file (for logging only) */
564 /* ------------------------------------------------------------------------- */
565 #ifdef DEBUG
566 static const char *Zendnames[] = {"ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
567 #endif
568
zsdata(const char * buf,int length,int frameend,long pos)569 int zsdata(const char *buf, int length, int frameend, long pos)
570 {
571 int n, rc;
572 unsigned short crc;
573 unsigned long crc32;
574
575 DEB((D_PROT, "zsdata: %d %s (CRC%s) from %d pos", length,
576 Zendnames[(frameend-ZCRCE)&3], Z_Txcrc32?"32":"16", pos));
577
578 if( Z_Txcrc32 )
579 {
580 crc32 = 0xFFFFFFFFL;
581
582 for( ; --length >= 0; ++buf )
583 {
584 if( (rc = zsendline((*buf) & 0377)) < 0 )
585 return(rc);
586 crc32 = updcrc32(((*buf) & 0377), crc32);
587 }
588
589 if( (rc = BUFCHAR(ZDLE)) < 0 )
590 return(rc);
591 if( (rc = BUFCHAR(frameend)) < 0 )
592 return(rc);
593 crc32 = updcrc32(frameend, crc32);
594
595 crc32 = ~crc32;
596 for( n = 4; --n >= 0; )
597 {
598 if( (rc = zsendline(crc32 & 0377)) < 0 )
599 return(rc);
600 crc32 >>= 8;
601 }
602 }
603 else /* CRC-16 */
604 {
605 crc = 0;
606 for( ; --length >= 0; ++buf )
607 {
608 if( (rc = zsendline((*buf) & 0377)) < 0 )
609 return(rc);
610 crc = updcrc16((*buf & 0377), crc);
611 }
612
613 if( (rc = BUFCHAR(ZDLE)) < 0 )
614 return(rc);
615 if( (rc = BUFCHAR(frameend)) < 0 )
616 return(rc);
617 crc = updcrc16(frameend, crc);
618
619 crc = updcrc16(0, updcrc16(0, crc));
620 if( (rc = zsendline((crc>>8) & 0377)) < 0
621 || (rc = zsendline((crc ) & 0377)) < 0 )
622 return(rc);
623 }
624
625 if( (rc = FLUSHBUF()) < 0 )
626 return(rc);
627
628 if( frameend == ZCRCW )
629 {
630 if( (rc = PUTCHAR(XON)) < 0 )
631 return(rc);
632 if( (rc = FLUSHOUT()) < 0 )
633 return(rc);
634 }
635
636 return(0);
637 }
638
639 /* ------------------------------------------------------------------------- */
640 /* Receive array buf of max length+1 with ending ZDLE sequence */
641 /* and CRC. Returns the ending character or error code. */
642 /* $pos must contatain current offset of receiving file (for logging only!) */
643 /* ------------------------------------------------------------------------- */
zrdata(char * buf,int length,long pos)644 int zrdata(char *buf, int length, long pos)
645 {
646 return (Z_Rxframeind == ZBIN32) ? zrdat32(buf, length, pos)
647 : zrdat16(buf, length, pos);
648 }
649
zrdat16(char * buf,int length,long pos)650 static int zrdat16(char *buf, int length, long pos)
651 {
652 int c;
653 unsigned short crc;
654 char *end;
655 int d;
656
657 Z_Rxcount = 0;
658 crc = 0;
659 end = buf + length;
660
661 while( buf <= end )
662 {
663 if( (c=zdlread()) & ~0377 )
664 {
665 switch_again:
666 switch( c ) {
667 case GOTCRCE:
668 case GOTCRCG:
669 case GOTCRCQ:
670 case GOTCRCW:
671 d = c;
672 c &= 0377;
673 crc = updcrc16(c, crc);
674
675 if( (c=zdlread()) & ~0377 ) goto switch_again;
676 crc = updcrc16(c, crc);
677
678 if( (c=zdlread()) & ~0377 ) goto switch_again;
679 crc = updcrc16(c, crc);
680
681 Z_Rxcount = length - (end - buf);
682
683 if( crc & 0xFFFF )
684 {
685 DEB((D_PROT, "zrdat16: %d %s : Bad CRC",
686 Z_Rxcount, Zendnames[(d-GOTCRCE)&3]));;
687 bf_log("ZDATA with bad CRC");
688
689 return ZCRCERR;
690 }
691
692 DEB((D_PROT, "zrdat16: %d %s (CRC16) at %d pos",
693 Z_Rxcount, Zendnames[(d-GOTCRCE)&3], pos));
694
695 return d;
696
697 case GOTCAN:
698 DEB((D_PROT, "zrdat16: Sender CANceled"));
699 return ZCAN;
700
701 case ZHANGUP:
702 case ZTIMER:
703 case ZEXIT:
704 DEB((D_PROT, "zrdat16: zdlread() return %s",
705 ( c == ZHANGUP ) ? "ZHANGUP":
706 ( c == ZEXIT ) ? "ZEXIT":
707 ( c == ZTIMER ) ? "ZTIMER" : "Unknown"));
708 return c;
709
710 default:
711 DEB((D_PROT, "zrdat16: $zdlread return %d", c));
712 return c;
713 }
714 }
715 *buf++ = c;
716 crc = updcrc16(c, crc);
717 }
718
719 bf_log("zmodem: data packet too long");
720 DEB((D_PROT, "zrdat16: data packet too long"));
721
722 return ZERROR;
723 }
724
zrdat32(char * buf,int length,long pos)725 static int zrdat32(char *buf, int length, long pos)
726 {
727 int c, d;
728 unsigned long crc;
729 char *end;
730
731 Z_Rxcount = 0;
732 crc = 0xFFFFFFFFL;
733 end = buf + length;
734
735 while( buf <= end )
736 {
737 if( (c = zdlread()) & ~0377 )
738 {
739 switch_again:
740 switch( c ) {
741 case GOTCRCE:
742 case GOTCRCG:
743 case GOTCRCQ:
744 case GOTCRCW:
745 d = c;
746 c &= 0377;
747 crc = updcrc32(c, crc);
748 if( (c = zdlread()) & ~0377 ) goto switch_again;
749 crc = updcrc32(c, crc);
750
751 if( (c = zdlread()) & ~0377 ) goto switch_again;
752 crc = updcrc32(c, crc);
753
754 if( (c = zdlread()) & ~0377 ) goto switch_again;
755 crc = updcrc32(c, crc);
756
757 if( (c = zdlread()) & ~0377 ) goto switch_again;
758 crc = updcrc32(c, crc);
759
760 Z_Rxcount = length - (end - buf);
761
762 if( crc != 0xDEBB20E3 )
763 {
764 DEB((D_PROT, "zrdat32: %d %s : Bad CRC",
765 Z_Rxcount, Zendnames[(d-GOTCRCE)&3]));
766 bf_log("DATA with bad CRC");
767
768 return ZCRCERR;
769 }
770
771 DEB((D_PROT, "zrdat32: %d %s (CRC32) at %d pos",
772 Z_Rxcount, Zendnames[(d-GOTCRCE)&3], pos));
773
774 return d;
775
776 case GOTCAN:
777 DEB((D_PROT, "zrdat32: Sender CANceled"));
778 return ZCAN;
779
780 case ZEXIT:
781 case ZTIMER:
782 case ZHANGUP:
783 DEB((D_PROT, "zrdat32: zdlread() return %s",
784 ( c == ZHANGUP ) ? "ZHANGUP":
785 ( c == ZEXIT ) ? "ZEXIT":
786 ( c == ZTIMER ) ? "ZTIMER" : "Unknown"));
787 return c;
788
789 default:
790 DEB((D_PROT, "zrdat32: $zdlread return %d", c));
791 return c;
792 }
793 }
794 *buf++ = c;
795 crc = updcrc32(c, crc);
796 }
797
798 bf_log("zmodem: data packet too long");
799 DEB((D_PROT, "zrdat32: data packet too long"));
800
801 return ZERROR;
802 }
803
804 /* ------------------------------------------------------------------------- */
805 /* Read a ZMODEM header to hdr, either binary or hex. */
806 /* On success, set Z_Rxpos and return type of header. */
807 /* Otherwise return negative on error. */
808 /* Return ZERROR instantly if ZCRCW sequence, for fast error recovery. */
809 /* ------------------------------------------------------------------------- */
zgethdr(char * hdr)810 int zgethdr(char *hdr)
811 {
812 int c, n, cancount;
813
814 n = 8192; /* Maximum number of garbage chars */
815 cancount = 5; /* CANcel on this can number */
816
817 Z_Rxframeind = 0;
818 Z_Rxtype = 0;
819
820 again:
821 if( Z_Rxexp ) { c = ZTIMER; goto fifi; }
822
823 switch( c = GETCHAR(Z_Rxwait) ) {
824 case ZEXIT:
825 case ZHANGUP:
826 case ZTIMER:
827 goto fifi;
828 case CAN:
829 gotcan:
830 if( --cancount == 0 )
831 {
832 c = ZCAN; goto fifi;
833 }
834
835 if( Z_Rxexp ) { c = ZTIMER; goto fifi; }
836
837 switch( c = GETCHAR(Z_Rxwait) ) {
838 case ZCRCW:
839 /* Return immediate ERROR if ZCRCW sequence seen */
840 c = ZERROR;
841 case ZEXIT:
842 case ZHANGUP:
843 case ZTIMER:
844 goto fifi;
845 default:
846 break;
847 case CAN:
848 if( --cancount == 0 )
849 {
850 c = ZCAN; goto fifi;
851 }
852 goto again;
853 }
854 default:
855 if( --n == 0 ) {
856 DEB((D_PROT, "zgethdr: garbage count exceeded"));
857 c = ZERROR; goto fifi;
858 }
859 cancount = 5;
860 goto again;
861 case ZPAD|0200: /* This is what we want. */
862 case ZPAD: /* This is what we want. */
863 break;
864 }
865 cancount = 5;
866
867 splat:
868 switch( c = noxrd7() ) {
869 case ZPAD:
870 goto splat;
871 case ZEXIT:
872 case ZHANGUP:
873 case ZTIMER:
874 goto fifi;
875 default:
876 if( --n == 0 ) {
877 DEB((D_PROT, "zgethdr: garbage count exceeded"));
878 c = ZERROR; goto fifi;
879 }
880 goto again;
881 case ZDLE: /* This is what we want. */
882 break;
883 }
884
885 switch( c=noxrd7() ) {
886 case ZEXIT:
887 case ZHANGUP:
888 case ZTIMER:
889 goto fifi;
890 case ZBIN:
891 /* receive binary header with crc16 */
892 Z_Rxcrc32 = 0;
893 Z_Rxframeind = ZBIN;
894 c = zrbhdr16(hdr);
895 break;
896 case ZBIN32:
897 /* receive binary header with crc32 */
898 Z_Rxcrc32 = 1;
899 Z_Rxframeind = ZBIN32;
900 c = zrbhdr32(hdr);
901 break;
902 case ZHEX:
903 /* receive hex header (all hex headers have crc16) */
904 Z_Rxcrc32 = 0;
905 Z_Rxframeind = ZHEX;
906 c = zrhhdr(hdr);
907 break;
908 case CAN:
909 goto gotcan;
910 default:
911 if( --n == 0 ) {
912 DEB((D_PROT, "zgethdr: garbage count exceeded"));
913 c = ZERROR; goto fifi;
914 }
915 goto again;
916 }
917
918 if( c >= 0 )
919 {
920 Z_Rxpos = hdr[ZP3] & 0377;
921 Z_Rxpos = (Z_Rxpos<<8) + (hdr[ZP2] & 0377);
922 Z_Rxpos = (Z_Rxpos<<8) + (hdr[ZP1] & 0377);
923 Z_Rxpos = (Z_Rxpos<<8) + (hdr[ZP0] & 0377);
924 }
925
926 fifi:
927 if( c == GOTCAN )
928 c = ZCAN;
929
930 #ifdef DEBUG
931 if( (c >= -7) && (c <= FRTYPES) )
932 DEB((D_PROT, "zgethdr: %s %lx", FrameTypes[c+FTOFFSET], Z_Rxpos));
933 else
934 DEB((D_PROT, "zgethdr: %d %lx", c, Z_Rxpos));
935 #endif
936
937 return(c);
938 }
939
940 /* ------------------------------------------------------------------------- */
941 /* Receive a binary style header (type and position) */
942 /* ------------------------------------------------------------------------- */
zrbhdr16(char * hdr)943 static int zrbhdr16(char *hdr)
944 {
945 int c, n;
946 unsigned short crc;
947
948 if( (c = zdlread()) < 0 )
949 return(c);
950 Z_Rxtype = c;
951 crc = updcrc16(c, 0);
952
953 for( n = 4; --n >= 0; ++hdr )
954 {
955 if( (c = zdlread()) < 0 )
956 return(c);
957 crc = updcrc16(c, crc);
958 *hdr = c;
959 }
960
961 if( (c = zdlread()) < 0 )
962 return(c);
963 crc = updcrc16(c, crc);
964
965 if( (c = zdlread()) < 0 )
966 return(c);
967 crc = updcrc16(c, crc);
968
969 if( crc & 0xFFFF )
970 {
971 DEB((D_PROT, "zrbhdr: Bad CRC"));
972 bf_log("Bad CRC");
973 return(ZCRCERR);
974 }
975
976 return(Z_Rxtype);
977 }
978
979 /* ------------------------------------------------------------------------- */
980 /* Receive a binary style header (type and position) with 32 bit FCS */
981 /* ------------------------------------------------------------------------- */
zrbhdr32(char * hdr)982 static int zrbhdr32(char *hdr)
983 {
984 int c, n;
985 unsigned long crc;
986
987 if( (c = zdlread()) < 0 )
988 return c;
989 Z_Rxtype = c;
990 crc = 0xFFFFFFFFL;
991 crc = updcrc32(c, crc);
992
993 for( n = 4; --n >= 0; ++hdr )
994 {
995 if( (c = zdlread()) < 0 )
996 return(c);
997 crc = updcrc32(c, crc);
998 *hdr = c;
999 }
1000
1001 for( n = 4; --n >= 0; )
1002 {
1003 if( (c = zdlread()) < 0 )
1004 return(c);
1005 crc = updcrc32(c, crc);
1006 }
1007
1008 if( crc != 0xDEBB20E3 )
1009 {
1010 DEB((D_PROT, "zrbhdr32: Bad CRC"));
1011 bf_log("Bad CRC");
1012 return(ZCRCERR);
1013 }
1014
1015 return(Z_Rxtype);
1016 }
1017
1018
1019 /* ------------------------------------------------------------------------- */
1020 /* Receive a hex style header (type and position) */
1021 /* ------------------------------------------------------------------------- */
zrhhdr(char * hdr)1022 static int zrhhdr(char *hdr)
1023 {
1024 int c, n;
1025 unsigned short crc;
1026
1027 if( (c = zgethex()) < 0 )
1028 return(c);
1029 Z_Rxtype = c; crc = updcrc16(c, 0);
1030
1031 for( n = 4; --n >= 0; )
1032 {
1033 if( (c = zgethex()) < 0 )
1034 return(c);
1035 crc = updcrc16(c, crc);
1036 *hdr++ = c;
1037 }
1038
1039 if( (c = zgethex()) < 0 )
1040 return(c);
1041 crc = updcrc16(c, crc);
1042
1043 if( (c = zgethex()) < 0 )
1044 return(c);
1045 crc = updcrc16(c, crc);
1046
1047 if( crc & 0xFFFF )
1048 {
1049 DEB((D_PROT, "zrhhdr: Bad CRC"));
1050 bf_log("Bad CRC");
1051 return(ZCRCERR);
1052 }
1053
1054 if( CHARWAIT(0) )
1055 {
1056 /* There is some characters available.. */
1057
1058 switch( (c = GETCHAR(1)) ) {
1059 case 0215:
1060 case 015:
1061 /* Throw away possible cr/lf */
1062 if( (c = GETCHAR(1)) < 0 && c != ZTIMER )
1063 return(c);
1064 break;
1065 case ZEXIT:
1066 case ZHANGUP:
1067 return(c);
1068 }
1069 }
1070
1071 return(Z_Rxtype);
1072 }
1073
1074 /* ------------------------------------------------------------------------- */
1075 /* Write a byte as two hex digits */
1076 /* ------------------------------------------------------------------------- */
zputhex(int c)1077 static int zputhex(int c)
1078 {
1079 static char digits[] = "0123456789abcdef";
1080 int rc;
1081
1082 if( (rc = BUFCHAR(digits[(c&0xF0)>>4])) < 0
1083 || (rc = BUFCHAR(digits[(c&0x0F) ])) < 0 )
1084 return rc;
1085
1086 return(0);
1087 }
1088
1089 /* ------------------------------------------------------------------------- */
1090 /* Init an array of 256 entries, mark codes we must escape with value > 0 */
1091 /* ------------------------------------------------------------------------- */
zsendline_init(char * tab)1092 static void zsendline_init(char *tab)
1093 {
1094 int i;
1095
1096 for( i = 0; i < 256; i++ )
1097 {
1098 if( i & 0140 )
1099 tab[i] = 0;
1100 else
1101 {
1102 switch( i ) {
1103 case ZDLE:
1104 case XOFF: /* ^Q */
1105 case XON: /* ^S */
1106 case 020: /* ^P */
1107 case (XOFF | 0200):
1108 case (XON | 0200):
1109 case (020 | 0200):
1110 tab[i] = 1;
1111 break;
1112 case 015:
1113 case (015 | 0200):
1114 if( Z_Ctlesc )
1115 tab[i] = 1;
1116 else
1117 tab[i] = 2;
1118 break;
1119 default:
1120 if( Z_Ctlesc )
1121 tab[i] = 1;
1122 else
1123 tab[i] = 0;
1124 }
1125 } /* end of if */
1126 } /* end of for */
1127 }
1128
1129 /* ------------------------------------------------------------------------- */
1130 /* Decode two lower case hex digits into an 8 bit byte value */
1131 /* ------------------------------------------------------------------------- */
zgethex(void)1132 static int zgethex(void)
1133 {
1134 int c, n;
1135
1136 if( (c = noxrd7()) < 0 )
1137 return(c);
1138
1139 n = c - '0';
1140 if( n > 9 ) n -= ('a' - ':');
1141
1142 if( n & ~0xF )
1143 return(ZERROR);
1144 if( (c = noxrd7()) < 0 )
1145 return(c);
1146
1147 c -= '0';
1148 if( c > 9 ) c -= ('a' - ':');
1149 if( c & ~0xF )
1150 return(ZERROR);
1151
1152 c += (n<<4);
1153
1154 return(c);
1155 }
1156
1157 /* ------------------------------------------------------------------------- */
1158 /* Store long integer pos in hdr */
1159 /* ------------------------------------------------------------------------- */
stohdr(char * hdr,long pos)1160 void stohdr(char *hdr, long pos)
1161 {
1162 hdr[ZP0] = (pos ) & 0377;
1163 hdr[ZP1] = (pos>>8 ) & 0377;
1164 hdr[ZP2] = (pos>>16) & 0377;
1165 hdr[ZP3] = (pos>>24) & 0377;
1166 }
1167
1168 /* ------------------------------------------------------------------------- */
1169 /* Recover a long integer from a header */
1170 /* ------------------------------------------------------------------------- */
rclhdr(char * hdr)1171 long rclhdr(char *hdr)
1172 {
1173 register long l;
1174
1175 l = (hdr[ZP3] & 0377);
1176 l = (l << 8) | (hdr[ZP2] & 0377);
1177 l = (l << 8) | (hdr[ZP1] & 0377);
1178 l = (l << 8) | (hdr[ZP0] & 0377);
1179 return(l);
1180 }
1181