Annotation of embedaddon/lrzsz/src/zm.c, revision 1.1.1.1
1.1 misho 1: /*
2: zm.c - zmodem protocol handling lowlevelstuff
3: Copyright (C) until 1998 Chuck Forsberg (OMEN Technology Inc)
4: Copyright (C) 1996, 1997 Uwe Ohse
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, or (at your option)
9: any later version.
10:
11: This program is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with this program; if not, write to the Free Software
18: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19: 02111-1307, USA.
20:
21: originally written by Chuck Forsberg
22: */
23: /* historical comment: -- uwe
24: * Z M . C
25: * ZMODEM protocol primitives
26: * 05-09-88 Chuck Forsberg Omen Technology Inc
27: *
28: * Entry point Functions:
29: * zsbhdr(type, hdr) send binary header
30: * zshhdr(type, hdr) send hex header
31: * zgethdr(hdr, eflag) receive header - binary or hex
32: * zsdata(buf, len, frameend) send data
33: * zrdata(buf, len, bytes_received) receive data
34: * stohdr(pos) store position data in Txhdr
35: * long rclhdr(hdr) recover position offset from header
36: */
37:
38:
39: #include "zglobal.h"
40:
41: #include <stdio.h>
42:
43: unsigned int Rxtimeout = 100; /* Tenths of seconds to wait for something */
44:
45: /* Globals used by ZMODEM functions */
46: int Rxframeind; /* ZBIN ZBIN32, or ZHEX type of frame received */
47: int Rxtype; /* Type of header received */
48: char Rxhdr[4]; /* Received header */
49: char Txhdr[4]; /* Transmitted header */
50: long Txpos; /* Transmitted file position */
51: int Txfcs32; /* TRUE means send binary frames with 32 bit FCS */
52: int Crc32t; /* Display flag indicating 32 bit CRC being sent */
53: int Crc32; /* Display flag indicating 32 bit CRC being received */
54: int Znulls; /* Number of nulls to send at beginning of ZDATA hdr */
55: char Attn[ZATTNLEN+1]; /* Attention string rx sends to tx on err */
56:
57: static char lastsent; /* Last char we sent */
58: int turbo_escape;
59: int bytes_per_error=0;
60:
61: static const char *frametypes[] = {
62: "Carrier Lost", /* -3 */
63: "TIMEOUT", /* -2 */
64: "ERROR", /* -1 */
65: #define FTOFFSET 3
66: "ZRQINIT",
67: "ZRINIT",
68: "ZSINIT",
69: "ZACK",
70: "ZFILE",
71: "ZSKIP",
72: "ZNAK",
73: "ZABORT",
74: "ZFIN",
75: "ZRPOS",
76: "ZDATA",
77: "ZEOF",
78: "ZFERR",
79: "ZCRC",
80: "ZCHALLENGE",
81: "ZCOMPL",
82: "ZCAN",
83: "ZFREECNT",
84: "ZCOMMAND",
85: "ZSTDERR",
86: "xxxxx"
87: #define FRTYPES 22 /* Total number of frame types in this array */
88: /* not including psuedo negative entries */
89: };
90:
91: #define badcrc _("Bad CRC")
92: /* static char *badcrc = "Bad CRC"; */
93: static inline int noxrd7 __P ((void));
94: static inline int zdlread __P ((void));
95: static int zdlread2 __P ((int)) LRZSZ_ATTRIB_REGPARM(1);
96: static inline int zgeth1 __P ((void));
97: static void zputhex __P ((int c, char *pos));
98: static inline int zgethex __P ((void));
99: static int zrbhdr __P ((char *hdr));
100: static int zrbhdr32 __P ((char *hdr));
101: static int zrhhdr __P ((char *hdr));
102: static char zsendline_tab[256];
103: static int zrdat32 __P ((char *buf, int length, size_t *));
104: static void zsbh32 __P ((char *hdr, int type));
105:
106: extern int zmodem_requested;
107:
108: #define sendline(c) putchar((c) & 0377)
109: #define xsendline(c) putchar(c)
110:
111: /*
112: * Read a character from the modem line with timeout.
113: * Eat parity, XON and XOFF characters.
114: */
115: static inline int
116: noxrd7(void)
117: {
118: register int c;
119:
120: for (;;) {
121: if ((c = READLINE_PF(Rxtimeout)) < 0)
122: return c;
123: switch (c &= 0177) {
124: case XON:
125: case XOFF:
126: continue;
127: default:
128: if (Zctlesc && !(c & 0140))
129: continue;
130: case '\r':
131: case '\n':
132: case ZDLE:
133: return c;
134: }
135: }
136: }
137:
138: static inline int
139: zgeth1(void)
140: {
141: register int c, n;
142:
143: if ((c = noxrd7()) < 0)
144: return c;
145: n = c - '0';
146: if (n > 9)
147: n -= ('a' - ':');
148: if (n & ~0xF)
149: return ERROR;
150: if ((c = noxrd7()) < 0)
151: return c;
152: c -= '0';
153: if (c > 9)
154: c -= ('a' - ':');
155: if (c & ~0xF)
156: return ERROR;
157: c += (n<<4);
158: return c;
159: }
160:
161: /* Decode two lower case hex digits into an 8 bit byte value */
162: static inline int
163: zgethex(void)
164: {
165: register int c;
166:
167: c = zgeth1();
168: VPRINTF(9,("zgethex: %02X", c));
169: return c;
170: }
171:
172: /*
173: * Read a byte, checking for ZMODEM escape encoding
174: * including CAN*5 which represents a quick abort
175: */
176: static inline int
177: zdlread(void)
178: {
179: int c;
180: /* Quick check for non control characters */
181: if ((c = READLINE_PF(Rxtimeout)) & 0140)
182: return c;
183: return zdlread2(c);
184: }
185: /* no, i don't like gotos. -- uwe */
186: static int
187: zdlread2(int c)
188: {
189: goto jump_over; /* bad style */
190:
191: again:
192: /* Quick check for non control characters */
193: if ((c = READLINE_PF(Rxtimeout)) & 0140)
194: return c;
195: jump_over:
196: switch (c) {
197: case ZDLE:
198: break;
199: case XON:
200: case (XON|0200):
201: case XOFF:
202: case (XOFF|0200):
203: goto again;
204: default:
205: if (Zctlesc && !(c & 0140)) {
206: goto again;
207: }
208: return c;
209: }
210: again2:
211: if ((c = READLINE_PF(Rxtimeout)) < 0)
212: return c;
213: if (c == CAN && (c = READLINE_PF(Rxtimeout)) < 0)
214: return c;
215: if (c == CAN && (c = READLINE_PF(Rxtimeout)) < 0)
216: return c;
217: if (c == CAN && (c = READLINE_PF(Rxtimeout)) < 0)
218: return c;
219: switch (c) {
220: case CAN:
221: return GOTCAN;
222: case ZCRCE:
223: case ZCRCG:
224: case ZCRCQ:
225: case ZCRCW:
226: return (c | GOTOR);
227: case ZRUB0:
228: return 0177;
229: case ZRUB1:
230: return 0377;
231: case XON:
232: case (XON|0200):
233: case XOFF:
234: case (XOFF|0200):
235: goto again2;
236: default:
237: if (Zctlesc && ! (c & 0140)) {
238: goto again2;
239: }
240: if ((c & 0140) == 0100)
241: return (c ^ 0100);
242: break;
243: }
244: VPRINTF(2,(_("Bad escape sequence %x"), c));
245: return ERROR;
246: }
247:
248:
249:
250: /*
251: * Send character c with ZMODEM escape sequence encoding.
252: * Escape XON, XOFF. Escape CR following @ (Telenet net escape)
253: */
254: inline void
255: zsendline(int c)
256: {
257:
258: switch(zsendline_tab[(unsigned) (c&=0377)])
259: {
260: case 0:
261: xsendline(lastsent = c);
262: break;
263: case 1:
264: xsendline(ZDLE);
265: c ^= 0100;
266: xsendline(lastsent = c);
267: break;
268: case 2:
269: if ((lastsent & 0177) != '@') {
270: xsendline(lastsent = c);
271: } else {
272: xsendline(ZDLE);
273: c ^= 0100;
274: xsendline(lastsent = c);
275: }
276: break;
277: }
278: }
279:
280: static inline void
281: zsendline_s(const char *s, size_t count)
282: {
283: const char *end=s+count;
284: while(s!=end) {
285: int last_esc=0;
286: const char *t=s;
287: while (t!=end) {
288: last_esc=zsendline_tab[(unsigned) ((*t) & 0377)];
289: if (last_esc)
290: break;
291: t++;
292: }
293: if (t!=s) {
294: fwrite(s,(size_t)(t-s),1,stdout);
295: lastsent=t[-1];
296: s=t;
297: }
298: if (last_esc) {
299: int c=*s;
300: switch(last_esc) {
301: case 0:
302: xsendline(lastsent = c);
303: break;
304: case 1:
305: xsendline(ZDLE);
306: c ^= 0100;
307: xsendline(lastsent = c);
308: break;
309: case 2:
310: if ((lastsent & 0177) != '@') {
311: xsendline(lastsent = c);
312: } else {
313: xsendline(ZDLE);
314: c ^= 0100;
315: xsendline(lastsent = c);
316: }
317: break;
318: }
319: s++;
320: }
321: }
322: }
323:
324:
325: /* Send ZMODEM binary header hdr of type type */
326: void
327: zsbhdr(int type, char *hdr)
328: {
329: register int n;
330: register unsigned short crc;
331:
332: VPRINTF(3,("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr)));
333: if (type == ZDATA)
334: for (n = Znulls; --n >=0; )
335: xsendline(0);
336:
337: xsendline(ZPAD); xsendline(ZDLE);
338:
339: Crc32t=Txfcs32;
340: if (Crc32t)
341: zsbh32(hdr, type);
342: else {
343: xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
344:
345: for (n=4; --n >= 0; ++hdr) {
346: zsendline(*hdr);
347: crc = updcrc((0377& *hdr), crc);
348: }
349: crc = updcrc(0,updcrc(0,crc));
350: zsendline(crc>>8);
351: zsendline(crc);
352: }
353: if (type != ZDATA)
354: flushmo();
355: }
356:
357:
358: /* Send ZMODEM binary header hdr of type type */
359: static void
360: zsbh32(char *hdr, int type)
361: {
362: register int n;
363: register unsigned long crc;
364:
365: xsendline(ZBIN32); zsendline(type);
366: crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
367:
368: for (n=4; --n >= 0; ++hdr) {
369: crc = UPDC32((0377 & *hdr), crc);
370: zsendline(*hdr);
371: }
372: crc = ~crc;
373: for (n=4; --n >= 0;) {
374: zsendline((int)crc);
375: crc >>= 8;
376: }
377: }
378:
379: /* Send ZMODEM HEX header hdr of type type */
380: void
381: zshhdr(int type, char *hdr)
382: {
383: register int n;
384: register unsigned short crc;
385: char s[30];
386: size_t len;
387:
388: VPRINTF(3,("zshhdr: %s %lx", frametypes[(type & 0x7f)+FTOFFSET], rclhdr(hdr)));
389: s[0]=ZPAD;
390: s[1]=ZPAD;
391: s[2]=ZDLE;
392: s[3]=ZHEX;
393: zputhex(type & 0x7f ,s+4);
394: len=6;
395: Crc32t = 0;
396:
397: crc = updcrc((type & 0x7f), 0);
398: for (n=4; --n >= 0; ++hdr) {
399: zputhex(*hdr,s+len);
400: len += 2;
401: crc = updcrc((0377 & *hdr), crc);
402: }
403: crc = updcrc(0,updcrc(0,crc));
404: zputhex(crc>>8,s+len);
405: zputhex(crc,s+len+2);
406: len+=4;
407:
408: /* Make it printable on remote machine */
409: s[len++]=015;
410: s[len++]=0212;
411: /*
412: * Uncork the remote in case a fake XOFF has stopped data flow
413: */
414: if (type != ZFIN && type != ZACK)
415: {
416: s[len++]=021;
417: }
418: flushmo();
419: write(1,s,len);
420: }
421:
422: /*
423: * Send binary array buf of length length, with ending ZDLE sequence frameend
424: */
425: static const char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
426: void
427: zsdata(const char *buf, size_t length, int frameend)
428: {
429: register unsigned short crc;
430:
431: VPRINTF(3,("zsdata: %lu %s", (unsigned long) length,
432: Zendnames[(frameend-ZCRCE)&3]));
433: crc = 0;
434: do {
435: zsendline(*buf); crc = updcrc((0377 & *buf), crc);
436: buf++;
437: } while (--length>0);
438: xsendline(ZDLE); xsendline(frameend);
439: crc = updcrc(frameend, crc);
440:
441: crc = updcrc(0,updcrc(0,crc));
442: zsendline(crc>>8); zsendline(crc);
443: if (frameend == ZCRCW) {
444: xsendline(XON); flushmo();
445: }
446: }
447:
448: void
449: zsda32(const char *buf, size_t length, int frameend)
450: {
451: int c;
452: unsigned long crc;
453: int i;
454: VPRINTF(3,("zsdat32: %d %s", length, Zendnames[(frameend-ZCRCE)&3]));
455:
456: crc = 0xFFFFFFFFL;
457: zsendline_s(buf,length);
458: for (; length; length--) {
459: c = *buf & 0377;
460: crc = UPDC32(c, crc);
461: buf++;
462: }
463: xsendline(ZDLE); xsendline(frameend);
464: crc = UPDC32(frameend, crc);
465:
466: crc = ~crc;
467: for (i=4; --i >= 0;) {
468: c=(int) crc;
469: if (c & 0140)
470: xsendline(lastsent = c);
471: else
472: zsendline(c);
473: crc >>= 8;
474: }
475: if (frameend == ZCRCW) {
476: xsendline(XON); flushmo();
477: }
478: }
479:
480: #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ <= 4)
481: # undef DEBUG_BLOCKSIZE
482: #endif
483:
484: #ifdef DEBUG_BLOCKSIZE
485: struct debug_blocksize {
486: int size;
487: long count;
488: };
489: struct debug_blocksize blocksizes[]={
490: {32,0},
491: {64,0},
492: {128,0},
493: {256,0},
494: {512,0},
495: {1024,0},
496: {2048,0},
497: {4096,0},
498: {8192,0},
499: {0,0}
500: };
501: static inline void
502: count_blk(int size)
503: {
504: int i;
505: for (i=0;blocksizes[i].size;i++) {
506: if (blocksizes[i].size==size) {
507: blocksizes[i].count++;
508: return;
509: }
510: }
511: blocksizes[i].count++;
512: }
513:
514: static void printout_blocksizes(void) __attribute__((__destructor__));
515: static void
516: printout_blocksizes(void)
517: {
518: int i;
519: for (i=0;blocksizes[i].size;i++) {
520: if (blocksizes[i].count) {
521: lsyslog(LOG_DEBUG,"%4d byte: %ld blocks\n",
522: blocksizes[i].size,blocksizes[i].count);
523: }
524: }
525: if (blocksizes[i].count) {
526: lsyslog(LOG_DEBUG,"unk. byte: %ld blocks",
527: blocksizes[i].count);
528: }
529: }
530: #define COUNT_BLK(x) count_blk(x)
531: #else
532: #define COUNT_BLK(x)
533: #endif
534:
535: /*
536: * Receive array buf of max length with ending ZDLE sequence
537: * and CRC. Returns the ending character or error code.
538: * NB: On errors may store length+1 bytes!
539: */
540: int
541: zrdata(char *buf, int length, size_t *bytes_received)
542: {
543: register int c;
544: register unsigned short crc;
545: register char *end;
546: register int d;
547:
548: *bytes_received=0;
549: if (Rxframeind == ZBIN32)
550: return zrdat32(buf, length, bytes_received);
551:
552: crc = 0; end = buf + length;
553: while (buf <= end) {
554: if ((c = zdlread()) & ~0377) {
555: crcfoo:
556: switch (c) {
557: case GOTCRCE:
558: case GOTCRCG:
559: case GOTCRCQ:
560: case GOTCRCW:
561: {
562: d = c;
563: c &= 0377;
564: crc = updcrc(c, crc);
565: if ((c = zdlread()) & ~0377)
566: goto crcfoo;
567: crc = updcrc(c, crc);
568: if ((c = zdlread()) & ~0377)
569: goto crcfoo;
570: crc = updcrc(c, crc);
571: if (crc & 0xFFFF) {
572: zperr(badcrc);
573: return ERROR;
574: }
575: *bytes_received = length - (end - buf);
576: COUNT_BLK(*bytes_received);
577: VPRINTF(3,("zrdata: %lu %s", (unsigned long) (*bytes_received),
578: Zendnames[(d-GOTCRCE)&3]));
579: return d;
580: }
581: case GOTCAN:
582: zperr(_("Sender Canceled"));
583: return ZCAN;
584: case TIMEOUT:
585: zperr(_("TIMEOUT"));
586: return c;
587: default:
588: zperr(_("Bad data subpacket"));
589: return c;
590: }
591: }
592: *buf++ = c;
593: crc = updcrc(c, crc);
594: }
595: zperr(_("Data subpacket too long"));
596: return ERROR;
597: }
598:
599: static int
600: zrdat32(char *buf, int length, size_t *bytes_received)
601: {
602: register int c;
603: register unsigned long crc;
604: register char *end;
605: register int d;
606:
607: crc = 0xFFFFFFFFL; end = buf + length;
608: while (buf <= end) {
609: if ((c = zdlread()) & ~0377) {
610: crcfoo:
611: switch (c) {
612: case GOTCRCE:
613: case GOTCRCG:
614: case GOTCRCQ:
615: case GOTCRCW:
616: d = c;
617: c &= 0377;
618: crc = UPDC32(c, crc);
619: if ((c = zdlread()) & ~0377)
620: goto crcfoo;
621: crc = UPDC32(c, crc);
622: if ((c = zdlread()) & ~0377)
623: goto crcfoo;
624: crc = UPDC32(c, crc);
625: if ((c = zdlread()) & ~0377)
626: goto crcfoo;
627: crc = UPDC32(c, crc);
628: if ((c = zdlread()) & ~0377)
629: goto crcfoo;
630: crc = UPDC32(c, crc);
631: if (crc != 0xDEBB20E3) {
632: zperr(badcrc);
633: return ERROR;
634: }
635: *bytes_received = length - (end - buf);
636: COUNT_BLK(*bytes_received);
637: VPRINTF(3,("zrdat32: %lu %s", (unsigned long) *bytes_received,
638: Zendnames[(d-GOTCRCE)&3]));
639: return d;
640: case GOTCAN:
641: zperr(_("Sender Canceled"));
642: return ZCAN;
643: case TIMEOUT:
644: zperr(_("TIMEOUT"));
645: return c;
646: default:
647: zperr(_("Bad data subpacket"));
648: return c;
649: }
650: }
651: *buf++ = c;
652: crc = UPDC32(c, crc);
653: }
654: zperr(_("Data subpacket too long"));
655: return ERROR;
656: }
657:
658: /*
659: * Read a ZMODEM header to hdr, either binary or hex.
660: * eflag controls local display of non zmodem characters:
661: * 0: no display
662: * 1: display printing characters only
663: * 2: display all non ZMODEM characters
664: * On success, set Zmodem to 1, set Rxpos and return type of header.
665: * Otherwise return negative on error.
666: * Return ERROR instantly if ZCRCW sequence, for fast error recovery.
667: */
668: int
669: zgethdr(char *hdr, int eflag, size_t *Rxpos)
670: {
671: register int c, cancount;
672: unsigned int max_garbage; /* Max bytes before start of frame */
673: size_t rxpos=0; /* keep gcc happy */
674:
675: max_garbage = Zrwindow + Baudrate;
676: Rxframeind = Rxtype = 0;
677:
678: startover:
679: cancount = 5;
680: again:
681: /* Return immediate ERROR if ZCRCW sequence seen */
682: switch (c = READLINE_PF(Rxtimeout)) {
683: case RCDO:
684: case TIMEOUT:
685: goto fifi;
686: case CAN:
687: gotcan:
688: if (--cancount <= 0) {
689: c = ZCAN; goto fifi;
690: }
691: switch (c = READLINE_PF(1)) {
692: case TIMEOUT:
693: goto again;
694: case ZCRCW:
695: c = ERROR;
696: /* **** FALL THRU TO **** */
697: case RCDO:
698: goto fifi;
699: default:
700: break;
701: case CAN:
702: if (--cancount <= 0) {
703: c = ZCAN; goto fifi;
704: }
705: goto again;
706: }
707: /* **** FALL THRU TO **** */
708: default:
709: agn2:
710: if ( --max_garbage == 0) {
711: zperr(_("Garbage count exceeded"));
712: return(ERROR);
713: }
714: if (eflag && ((c &= 0177) & 0140) && Verbose)
715: vchar(c);
716: else if (eflag > 1 && Verbose)
717: vchar(c);
718: goto startover;
719: case ZPAD|0200: /* This is what we want. */
720: case ZPAD: /* This is what we want. */
721: break;
722: }
723: cancount = 5;
724: splat:
725: switch (c = noxrd7()) {
726: case ZPAD:
727: goto splat;
728: case RCDO:
729: case TIMEOUT:
730: goto fifi;
731: default:
732: goto agn2;
733: case ZDLE: /* This is what we want. */
734: break;
735: }
736:
737: switch (c = noxrd7()) {
738: case RCDO:
739: case TIMEOUT:
740: goto fifi;
741: case ZBIN:
742: Rxframeind = ZBIN; Crc32 = FALSE;
743: c = zrbhdr(hdr);
744: break;
745: case ZBIN32:
746: Crc32 = Rxframeind = ZBIN32;
747: c = zrbhdr32(hdr);
748: break;
749: case ZHEX:
750: Rxframeind = ZHEX; Crc32 = FALSE;
751: c = zrhhdr(hdr);
752: break;
753: case CAN:
754: goto gotcan;
755: default:
756: goto agn2;
757: }
758: rxpos = hdr[ZP3] & 0377;
759: rxpos = (rxpos<<8) + (hdr[ZP2] & 0377);
760: rxpos = (rxpos<<8) + (hdr[ZP1] & 0377);
761: rxpos = (rxpos<<8) + (hdr[ZP0] & 0377);
762: fifi:
763: switch (c) {
764: case GOTCAN:
765: c = ZCAN;
766: /* **** FALL THRU TO **** */
767: case ZNAK:
768: case ZCAN:
769: case ERROR:
770: case TIMEOUT:
771: case RCDO:
772: zperr(_("Got %s"), frametypes[c+FTOFFSET]);
773: /* **** FALL THRU TO **** */
774: default:
775: if (c >= -3 && c <= FRTYPES)
776: VPRINTF(3,("zgethdr: %s %lx", frametypes[c+FTOFFSET], (unsigned long) rxpos));
777: else
778: VPRINTF(3,("zgethdr: %d %lx", c, (unsigned long) rxpos));
779: }
780: if (Rxpos)
781: *Rxpos=rxpos;
782: return c;
783: }
784:
785: /* Receive a binary style header (type and position) */
786: static int
787: zrbhdr(char *hdr)
788: {
789: register int c, n;
790: register unsigned short crc;
791:
792: if ((c = zdlread()) & ~0377)
793: return c;
794: Rxtype = c;
795: crc = updcrc(c, 0);
796:
797: for (n=4; --n >= 0; ++hdr) {
798: if ((c = zdlread()) & ~0377)
799: return c;
800: crc = updcrc(c, crc);
801: *hdr = c;
802: }
803: if ((c = zdlread()) & ~0377)
804: return c;
805: crc = updcrc(c, crc);
806: if ((c = zdlread()) & ~0377)
807: return c;
808: crc = updcrc(c, crc);
809: if (crc & 0xFFFF) {
810: zperr(badcrc);
811: return ERROR;
812: }
813: protocol = ZM_ZMODEM;
814: zmodem_requested=TRUE;
815: return Rxtype;
816: }
817:
818: /* Receive a binary style header (type and position) with 32 bit FCS */
819: static int
820: zrbhdr32(char *hdr)
821: {
822: register int c, n;
823: register unsigned long crc;
824:
825: if ((c = zdlread()) & ~0377)
826: return c;
827: Rxtype = c;
828: crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
829: #ifdef DEBUGZ
830: VPRINTF(3,("zrbhdr32 c=%X crc=%lX", c, crc)i);
831: #endif
832:
833: for (n=4; --n >= 0; ++hdr) {
834: if ((c = zdlread()) & ~0377)
835: return c;
836: crc = UPDC32(c, crc);
837: *hdr = c;
838: #ifdef DEBUGZ
839: VPRINTF(3,("zrbhdr32 c=%X crc=%lX", c, crc));
840: #endif
841: }
842: for (n=4; --n >= 0;) {
843: if ((c = zdlread()) & ~0377)
844: return c;
845: crc = UPDC32(c, crc);
846: #ifdef DEBUGZ
847: VPRINTF(3,("zrbhdr32 c=%X crc=%lX", c, crc));
848: #endif
849: }
850: if (crc != 0xDEBB20E3) {
851: zperr(badcrc);
852: return ERROR;
853: }
854: protocol = ZM_ZMODEM;
855: zmodem_requested=TRUE;
856: return Rxtype;
857: }
858:
859:
860: /* Receive a hex style header (type and position) */
861: static int
862: zrhhdr(char *hdr)
863: {
864: register int c;
865: register unsigned short crc;
866: register int n;
867:
868: if ((c = zgethex()) < 0)
869: return c;
870: Rxtype = c;
871: crc = updcrc(c, 0);
872:
873: for (n=4; --n >= 0; ++hdr) {
874: if ((c = zgethex()) < 0)
875: return c;
876: crc = updcrc(c, crc);
877: *hdr = c;
878: }
879: if ((c = zgethex()) < 0)
880: return c;
881: crc = updcrc(c, crc);
882: if ((c = zgethex()) < 0)
883: return c;
884: crc = updcrc(c, crc);
885: if (crc & 0xFFFF) {
886: zperr(badcrc); return ERROR;
887: }
888: switch ( c = READLINE_PF(1)) {
889: case 0215:
890: /* **** FALL THRU TO **** */
891: case 015:
892: /* Throw away possible cr/lf */
893: READLINE_PF(1);
894: break;
895: }
896: protocol = ZM_ZMODEM;
897: zmodem_requested=TRUE;
898: return Rxtype;
899: }
900:
901: /* Write a byte as two hex digits */
902: static void
903: zputhex(int c, char *pos)
904: {
905: static char digits[] = "0123456789abcdef";
906:
907: VPRINTF(9,("zputhex: %02X", c));
908: pos[0]=digits[(c&0xF0)>>4];
909: pos[1]=digits[c&0x0F];
910: }
911:
912: void
913: zsendline_init(void)
914: {
915: int i;
916: for (i=0;i<256;i++) {
917: if (i & 0140)
918: zsendline_tab[i]=0;
919: else {
920: switch(i)
921: {
922: case ZDLE:
923: case XOFF: /* ^Q */
924: case XON: /* ^S */
925: case (XOFF | 0200):
926: case (XON | 0200):
927: zsendline_tab[i]=1;
928: break;
929: case 020: /* ^P */
930: case 0220:
931: if (turbo_escape)
932: zsendline_tab[i]=0;
933: else
934: zsendline_tab[i]=1;
935: break;
936: case 015:
937: case 0215:
938: if (Zctlesc)
939: zsendline_tab[i]=1;
940: else if (!turbo_escape)
941: zsendline_tab[i]=2;
942: else
943: zsendline_tab[i]=0;
944: break;
945: default:
946: if (Zctlesc)
947: zsendline_tab[i]=1;
948: else
949: zsendline_tab[i]=0;
950: }
951: }
952: }
953: }
954:
955:
956:
957: /* Store pos in Txhdr */
958: void
959: stohdr(size_t pos)
960: {
961: long lpos=(long) pos;
962: Txhdr[ZP0] = lpos;
963: Txhdr[ZP1] = lpos>>8;
964: Txhdr[ZP2] = lpos>>16;
965: Txhdr[ZP3] = lpos>>24;
966: }
967:
968: /* Recover a long integer from a header */
969: long
970: rclhdr(char *hdr)
971: {
972: long l;
973:
974: l = (hdr[ZP3] & 0377);
975: l = (l << 8) | (hdr[ZP2] & 0377);
976: l = (l << 8) | (hdr[ZP1] & 0377);
977: l = (l << 8) | (hdr[ZP0] & 0377);
978: return l;
979: }
980:
981: /* End of zm.c */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>