Annotation of embedaddon/lrzsz/src/zm.c, revision 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>