1: /* 2: * Z M . C 3: * ZMODEM protocol primitives 4: * 05-24-89 Chuck Forsberg Omen Technology Inc 5: * 6: * Entry point Functions: 7: * zsbhdr(type, hdr) send binary header 8: * zshhdr(type, hdr) send hex header 9: * zgethdr(hdr, eflag) receive header - binary or hex 10: * zsdata(buf, len, frameend) send data 11: * zrdata(buf, len) receive data 12: * stohdr(pos) store position data in Txhdr 13: * long rclhdr(hdr) recover position offset from header 14: * 15: * 16: * This version implements numerous enhancements including ZMODEM 17: * Run Length Encoding and variable length headers. These 18: * features were not funded by the original Telenet development 19: * contract. 20: * 21: * This software may be freely used for non commercial and 22: * educational (didactic only) purposes. This software may also 23: * be freely used to support file transfer operations to or from 24: * licensed Omen Technology products. Any programs which use 25: * part or all of this software must be provided in source form 26: * with this notice intact except by written permission from Omen 27: * Technology Incorporated. 28: * 29: * Use of this software for commercial or administrative purposes 30: * except when exclusively limited to interfacing Omen Technology 31: * products requires a per port license payment of $20.00 US per 32: * port (less in quantity). Use of this code by inclusion, 33: * decompilation, reverse engineering or any other means 34: * constitutes agreement to these conditions and acceptance of 35: * liability to license the materials and payment of reasonable 36: * legal costs necessary to enforce this license agreement. 37: * 38: * 39: * Omen Technology Inc FAX: 503-621-3745 40: * Post Office Box 4681 41: * Portland OR 97208 42: * 43: * This code is made available in the hope it will be useful, 44: * BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY 45: * DAMAGES OF ANY KIND. 46: * 47: */ 48: 49: #ifndef CANFDX 50: #include "zmodem.h" 51: int Rxtimeout = 100; /* Tenths of seconds to wait for something */ 52: #endif 53: 54: #ifndef UNSL 55: #define UNSL 56: #endif 57: 58: 59: /* Globals used by ZMODEM functions */ 60: int Rxframeind; /* ZBIN ZBIN32, or ZHEX type of frame */ 61: int Rxtype; /* Type of header received */ 62: int Rxhlen; /* Length of header received */ 63: int Rxcount; /* Count of data bytes received */ 64: char Rxhdr[ZMAXHLEN]; /* Received header */ 65: char Txhdr[ZMAXHLEN]; /* Transmitted header */ 66: long Rxpos; /* Received file position */ 67: long Txpos; /* Transmitted file position */ 68: int Txfcs32; /* TURE means send binary frames with 32 bit FCS */ 69: int Crc32t; /* Controls 32 bit CRC being sent */ 70: /* 1 == CRC32, 2 == CRC32 + RLE */ 71: int Crc32r; /* Indicates/controls 32 bit CRC being received */ 72: /* 0 == CRC16, 1 == CRC32, 2 == CRC32 + RLE */ 73: int Usevhdrs; /* Use variable length headers */ 74: int Znulls; /* Number of nulls to send at beginning of ZDATA hdr */ 75: char Attn[ZATTNLEN+1]; /* Attention string rx sends to tx on err */ 76: char *Altcan; /* Alternate canit string */ 77: 78: static lastsent; /* Last char we sent */ 79: static Not8bit; /* Seven bits seen on header */ 80: 81: static char *frametypes[] = { 82: "No Response to Error Correction Request", /* -4 */ 83: "No Carrier Detect", /* -3 */ 84: "TIMEOUT", /* -2 */ 85: "ERROR", /* -1 */ 86: #define FTOFFSET 4 87: "ZRQINIT", 88: "ZRINIT", 89: "ZSINIT", 90: "ZACK", 91: "ZFILE", 92: "ZSKIP", 93: "ZNAK", 94: "ZABORT", 95: "ZFIN", 96: "ZRPOS", 97: "ZDATA", 98: "ZEOF", 99: "ZFERR", 100: "ZCRC", 101: "ZCHALLENGE", 102: "ZCOMPL", 103: "ZCAN", 104: "ZFREECNT", 105: "ZCOMMAND", 106: "ZSTDERR", 107: "xxxxx" 108: #define FRTYPES 22 /* Total number of frame types in this array */ 109: /* not including psuedo negative entries */ 110: }; 111: 112: static char badcrc[] = "Bad CRC"; 113: 114: /* Send ZMODEM binary header hdr of type type */ 115: zsbhdr(len, type, hdr) 116: register char *hdr; 117: { 118: register int n; 119: register unsigned short crc; 120: 121: #ifndef DSZ 122: vfile("zsbhdr: %c %d %s %lx", Usevhdrs?'v':'f', len, 123: frametypes[type+FTOFFSET], rclhdr(hdr)); 124: #endif 125: if (type == ZDATA) 126: for (n = Znulls; --n >=0; ) 127: xsendline(0); 128: 129: xsendline(ZPAD); xsendline(ZDLE); 130: 131: switch (Crc32t=Txfcs32) { 132: case 2: 133: zsbh32(len, hdr, type, Usevhdrs?ZVBINR32:ZBINR32); 134: flushmo(); break; 135: case 1: 136: zsbh32(len, hdr, type, Usevhdrs?ZVBIN32:ZBIN32); break; 137: default: 138: if (Usevhdrs) { 139: xsendline(ZVBIN); 140: zsendline(len); 141: } 142: else 143: xsendline(ZBIN); 144: zsendline(type); 145: crc = updcrc(type, 0); 146: 147: for (n=len; --n >= 0; ++hdr) { 148: zsendline(*hdr); 149: crc = updcrc((0377& *hdr), crc); 150: } 151: crc = updcrc(0,updcrc(0,crc)); 152: zsendline(crc>>8); 153: zsendline(crc); 154: } 155: if (type != ZDATA) 156: flushmo(); 157: } 158: 159: 160: /* Send ZMODEM binary header hdr of type type */ 161: zsbh32(len, hdr, type, flavour) 162: register char *hdr; 163: { 164: register int n; 165: register UNSL long crc; 166: 167: xsendline(flavour); 168: if (Usevhdrs) 169: zsendline(len); 170: zsendline(type); 171: crc = 0xFFFFFFFFL; crc = UPDC32(type, crc); 172: 173: for (n=len; --n >= 0; ++hdr) { 174: crc = UPDC32((0377 & *hdr), crc); 175: zsendline(*hdr); 176: } 177: crc = ~crc; 178: for (n=4; --n >= 0;) { 179: zsendline((int)crc); 180: crc >>= 8; 181: } 182: } 183: 184: /* Send ZMODEM HEX header hdr of type type */ 185: zshhdr(len, type, hdr) 186: register char *hdr; 187: { 188: register int n; 189: register unsigned short crc; 190: 191: #ifndef DSZ 192: vfile("zshhdr: %c %d %s %lx", Usevhdrs?'v':'f', len, 193: frametypes[type+FTOFFSET], rclhdr(hdr)); 194: #endif 195: sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); 196: if (Usevhdrs) { 197: sendline(ZVHEX); 198: zputhex(len); 199: } 200: else 201: sendline(ZHEX); 202: zputhex(type); 203: Crc32t = 0; 204: 205: crc = updcrc(type, 0); 206: for (n=len; --n >= 0; ++hdr) { 207: zputhex(*hdr); crc = updcrc((0377 & *hdr), crc); 208: } 209: crc = updcrc(0,updcrc(0,crc)); 210: zputhex(crc>>8); zputhex(crc); 211: 212: /* Make it printable on remote machine */ 213: sendline(015); sendline(0212); 214: /* 215: * Uncork the remote in case a fake XOFF has stopped data flow 216: */ 217: if (type != ZFIN && type != ZACK) 218: sendline(021); 219: flushmo(); 220: } 221: 222: /* 223: * Send binary array buf of length length, with ending ZDLE sequence frameend 224: */ 225: static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"}; 226: zsdata(buf, length, frameend) 227: register char *buf; 228: { 229: register unsigned short crc; 230: 231: #ifndef DSZ 232: vfile("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]); 233: #endif 234: switch (Crc32t) { 235: case 1: 236: zsda32(buf, length, frameend); break; 237: case 2: 238: zsdar32(buf, length, frameend); break; 239: default: 240: crc = 0; 241: for (;--length >= 0; ++buf) { 242: zsendline(*buf); crc = updcrc((0377 & *buf), crc); 243: } 244: xsendline(ZDLE); xsendline(frameend); 245: crc = updcrc(frameend, crc); 246: 247: crc = updcrc(0,updcrc(0,crc)); 248: zsendline(crc>>8); zsendline(crc); 249: } 250: if (frameend == ZCRCW) { 251: xsendline(XON); flushmo(); 252: } 253: } 254: 255: zsda32(buf, length, frameend) 256: register char *buf; 257: { 258: register int c; 259: register UNSL long crc; 260: 261: crc = 0xFFFFFFFFL; 262: for (;--length >= 0; ++buf) { 263: c = *buf & 0377; 264: if (c & 0140) 265: xsendline(lastsent = c); 266: else 267: zsendline(c); 268: crc = UPDC32(c, crc); 269: } 270: xsendline(ZDLE); xsendline(frameend); 271: crc = UPDC32(frameend, crc); 272: 273: crc = ~crc; 274: for (c=4; --c >= 0;) { 275: zsendline((int)crc); crc >>= 8; 276: } 277: } 278: 279: /* 280: * Receive array buf of max length with ending ZDLE sequence 281: * and CRC. Returns the ending character or error code. 282: * NB: On errors may store length+1 bytes! 283: */ 284: zrdata(buf, length) 285: register char *buf; 286: { 287: register int c; 288: register unsigned short crc; 289: register char *end; 290: register int d; 291: 292: switch (Crc32r) { 293: case 1: 294: return zrdat32(buf, length); 295: case 2: 296: return zrdatr32(buf, length); 297: } 298: 299: crc = Rxcount = 0; end = buf + length; 300: while (buf <= end) { 301: if ((c = zdlread()) & ~0377) { 302: crcfoo: 303: switch (c) { 304: case GOTCRCE: 305: case GOTCRCG: 306: case GOTCRCQ: 307: case GOTCRCW: 308: crc = updcrc((d=c)&0377, crc); 309: if ((c = zdlread()) & ~0377) 310: goto crcfoo; 311: crc = updcrc(c, crc); 312: if ((c = zdlread()) & ~0377) 313: goto crcfoo; 314: crc = updcrc(c, crc); 315: if (crc & 0xFFFF) { 316: zperr(badcrc); 317: return ERROR; 318: } 319: Rxcount = length - (end - buf); 320: #ifndef DSZ 321: vfile("zrdata: %d %s", Rxcount, 322: Zendnames[d-GOTCRCE&3]); 323: #endif 324: return d; 325: case GOTCAN: 326: zperr("Sender Canceled"); 327: return ZCAN; 328: case TIMEOUT: 329: zperr("TIMEOUT"); 330: return c; 331: default: 332: garbitch(); return c; 333: } 334: } 335: *buf++ = c; 336: crc = updcrc(c, crc); 337: } 338: #ifdef DSZ 339: garbitch(); 340: #else 341: zperr("Data subpacket too long"); 342: #endif 343: return ERROR; 344: } 345: 346: zrdat32(buf, length) 347: register char *buf; 348: { 349: register int c; 350: register UNSL long crc; 351: register char *end; 352: register int d; 353: 354: crc = 0xFFFFFFFFL; Rxcount = 0; end = buf + length; 355: while (buf <= end) { 356: if ((c = zdlread()) & ~0377) { 357: crcfoo: 358: switch (c) { 359: case GOTCRCE: 360: case GOTCRCG: 361: case GOTCRCQ: 362: case GOTCRCW: 363: d = c; c &= 0377; 364: crc = UPDC32(c, crc); 365: if ((c = zdlread()) & ~0377) 366: goto crcfoo; 367: crc = UPDC32(c, crc); 368: if ((c = zdlread()) & ~0377) 369: goto crcfoo; 370: crc = UPDC32(c, crc); 371: if ((c = zdlread()) & ~0377) 372: goto crcfoo; 373: crc = UPDC32(c, crc); 374: if ((c = zdlread()) & ~0377) 375: goto crcfoo; 376: crc = UPDC32(c, crc); 377: if (crc != 0xDEBB20E3) { 378: zperr(badcrc); 379: return ERROR; 380: } 381: Rxcount = length - (end - buf); 382: #ifndef DSZ 383: vfile("zrdat32: %d %s", Rxcount, 384: Zendnames[d-GOTCRCE&3]); 385: #endif 386: return d; 387: case GOTCAN: 388: zperr("Sender Canceled"); 389: return ZCAN; 390: case TIMEOUT: 391: zperr("TIMEOUT"); 392: return c; 393: default: 394: garbitch(); return c; 395: } 396: } 397: *buf++ = c; 398: crc = UPDC32(c, crc); 399: } 400: zperr("Data subpacket too long"); 401: return ERROR; 402: } 403: 404: garbitch() 405: { 406: zperr("Garbled data subpacket"); 407: } 408: 409: /* 410: * Read a ZMODEM header to hdr, either binary or hex. 411: * eflag controls local display of non zmodem characters: 412: * 0: no display 413: * 1: display printing characters only 414: * 2: display all non ZMODEM characters 415: * 416: * Set Rxhlen to size of header (default 4) (valid iff good hdr) 417: * On success, set Zmodem to 1, set Rxpos and return type of header. 418: * Otherwise return negative on error. 419: * Return ERROR instantly if ZCRCW sequence, for fast error recovery. 420: */ 421: zgethdr(hdr, eflag) 422: char *hdr; 423: { 424: register int c, n, cancount; 425: 426: n = Zrwindow + Effbaud; /* Max bytes before start of frame */ 427: Rxframeind = Rxtype = 0; 428: 429: startover: 430: cancount = 5; 431: again: 432: /* Return immediate ERROR if ZCRCW sequence seen */ 433: switch (c = readline(Rxtimeout)) { 434: case 021: case 0221: 435: goto again; 436: case RCDO: 437: case TIMEOUT: 438: goto fifi; 439: case CAN: 440: gotcan: 441: if (--cancount <= 0) { 442: c = ZCAN; goto fifi; 443: } 444: switch (c = readline(1)) { 445: case TIMEOUT: 446: goto again; 447: case ZCRCW: 448: switch (readline(1)) { 449: case TIMEOUT: 450: c = ERROR; goto fifi; 451: case RCDO: 452: goto fifi; 453: default: 454: goto agn2; 455: } 456: case RCDO: 457: goto fifi; 458: default: 459: break; 460: case CAN: 461: if (--cancount <= 0) { 462: c = ZCAN; goto fifi; 463: } 464: goto again; 465: } 466: /* **** FALL THRU TO **** */ 467: default: 468: agn2: 469: if ( --n == 0) { 470: c = GCOUNT; goto fifi; 471: } 472: if (eflag && ((c &= 0177) & 0140)) 473: bttyout(c); 474: else if (eflag > 1) 475: bttyout(c); 476: #ifdef UNIX 477: fflush(stderr); 478: #endif 479: goto startover; 480: case ZPAD|0200: /* This is what we want. */ 481: Not8bit = c; 482: case ZPAD: /* This is what we want. */ 483: break; 484: } 485: cancount = 5; 486: splat: 487: switch (c = noxrd7()) { 488: case ZPAD: 489: goto splat; 490: case RCDO: 491: case TIMEOUT: 492: goto fifi; 493: default: 494: goto agn2; 495: case ZDLE: /* This is what we want. */ 496: break; 497: } 498: 499: 500: Rxhlen = 4; /* Set default length */ 501: Rxframeind = c = noxrd7(); 502: switch (c) { 503: case ZVBIN32: 504: if ((Rxhlen = c = zdlread()) < 0) 505: goto fifi; 506: if (c > ZMAXHLEN) 507: goto agn2; 508: Crc32r = 1; c = zrbhd32(hdr); break; 509: case ZBIN32: 510: if (Usevhdrs) 511: goto agn2; 512: Crc32r = 1; c = zrbhd32(hdr); break; 513: case ZVBINR32: 514: if ((Rxhlen = c = zdlread()) < 0) 515: goto fifi; 516: if (c > ZMAXHLEN) 517: goto agn2; 518: Crc32r = 2; c = zrbhd32(hdr); break; 519: case ZBINR32: 520: if (Usevhdrs) 521: goto agn2; 522: Crc32r = 2; c = zrbhd32(hdr); break; 523: case RCDO: 524: case TIMEOUT: 525: goto fifi; 526: case ZVBIN: 527: if ((Rxhlen = c = zdlread()) < 0) 528: goto fifi; 529: if (c > ZMAXHLEN) 530: goto agn2; 531: Crc32r = 0; c = zrbhdr(hdr); break; 532: case ZBIN: 533: if (Usevhdrs) 534: goto agn2; 535: Crc32r = 0; c = zrbhdr(hdr); break; 536: case ZVHEX: 537: if ((Rxhlen = c = zgethex()) < 0) 538: goto fifi; 539: if (c > ZMAXHLEN) 540: goto agn2; 541: Crc32r = 0; c = zrhhdr(hdr); break; 542: case ZHEX: 543: if (Usevhdrs) 544: goto agn2; 545: Crc32r = 0; c = zrhhdr(hdr); break; 546: case CAN: 547: goto gotcan; 548: default: 549: goto agn2; 550: } 551: for (n = Rxhlen; ++n < ZMAXHLEN; ) /* Clear unused hdr bytes */ 552: hdr[n] = 0; 553: Rxpos = hdr[ZP3] & 0377; 554: Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377); 555: Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377); 556: Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377); 557: fifi: 558: switch (c) { 559: case GOTCAN: 560: c = ZCAN; 561: /* **** FALL THRU TO **** */ 562: case ZNAK: 563: case ZCAN: 564: case ERROR: 565: case TIMEOUT: 566: case RCDO: 567: case GCOUNT: 568: zperr("Got %s", frametypes[c+FTOFFSET]); 569: /* **** FALL THRU TO **** */ 570: #ifndef DSZ 571: default: 572: if (c >= -4 && c <= FRTYPES) 573: vfile("zgethdr: %c %d %s %lx", Rxframeind, Rxhlen, 574: frametypes[c+FTOFFSET], Rxpos); 575: else 576: vfile("zgethdr: %c %d %lx", Rxframeind, c, Rxpos); 577: #endif 578: } 579: /* Use variable length headers if we got one */ 580: if (c >= 0 && c <= FRTYPES && Rxframeind & 040) 581: Usevhdrs = 1; 582: return c; 583: } 584: 585: /* Receive a binary style header (type and position) */ 586: zrbhdr(hdr) 587: register char *hdr; 588: { 589: register int c, n; 590: register unsigned short crc; 591: 592: if ((c = zdlread()) & ~0377) 593: return c; 594: Rxtype = c; 595: crc = updcrc(c, 0); 596: 597: for (n=Rxhlen; --n >= 0; ++hdr) { 598: if ((c = zdlread()) & ~0377) 599: return c; 600: crc = updcrc(c, crc); 601: *hdr = c; 602: } 603: if ((c = zdlread()) & ~0377) 604: return c; 605: crc = updcrc(c, crc); 606: if ((c = zdlread()) & ~0377) 607: return c; 608: crc = updcrc(c, crc); 609: if (crc & 0xFFFF) { 610: zperr(badcrc); 611: return ERROR; 612: } 613: #ifdef ZMODEM 614: Protocol = ZMODEM; 615: #endif 616: Zmodem = 1; 617: return Rxtype; 618: } 619: 620: /* Receive a binary style header (type and position) with 32 bit FCS */ 621: zrbhd32(hdr) 622: register char *hdr; 623: { 624: register int c, n; 625: register UNSL long crc; 626: 627: if ((c = zdlread()) & ~0377) 628: return c; 629: Rxtype = c; 630: crc = 0xFFFFFFFFL; crc = UPDC32(c, crc); 631: #ifdef DEBUGZ 632: vfile("zrbhd32 c=%X crc=%lX", c, crc); 633: #endif 634: 635: for (n=Rxhlen; --n >= 0; ++hdr) { 636: if ((c = zdlread()) & ~0377) 637: return c; 638: crc = UPDC32(c, crc); 639: *hdr = c; 640: #ifdef DEBUGZ 641: vfile("zrbhd32 c=%X crc=%lX", c, crc); 642: #endif 643: } 644: for (n=4; --n >= 0;) { 645: if ((c = zdlread()) & ~0377) 646: return c; 647: crc = UPDC32(c, crc); 648: #ifdef DEBUGZ 649: vfile("zrbhd32 c=%X crc=%lX", c, crc); 650: #endif 651: } 652: if (crc != 0xDEBB20E3) { 653: zperr(badcrc); 654: return ERROR; 655: } 656: #ifdef ZMODEM 657: Protocol = ZMODEM; 658: #endif 659: Zmodem = 1; 660: return Rxtype; 661: } 662: 663: 664: /* Receive a hex style header (type and position) */ 665: zrhhdr(hdr) 666: char *hdr; 667: { 668: register int c; 669: register unsigned short crc; 670: register int n; 671: 672: if ((c = zgethex()) < 0) 673: return c; 674: Rxtype = c; 675: crc = updcrc(c, 0); 676: 677: for (n=Rxhlen; --n >= 0; ++hdr) { 678: if ((c = zgethex()) < 0) 679: return c; 680: crc = updcrc(c, crc); 681: *hdr = c; 682: } 683: if ((c = zgethex()) < 0) 684: return c; 685: crc = updcrc(c, crc); 686: if ((c = zgethex()) < 0) 687: return c; 688: crc = updcrc(c, crc); 689: if (crc & 0xFFFF) { 690: zperr(badcrc); return ERROR; 691: } 692: switch ( c = readline(2)) { 693: case 0215: 694: Not8bit = c; 695: /* **** FALL THRU TO **** */ 696: case 015: 697: /* Throw away possible cr/lf */ 698: switch (c = readline(2)) { 699: case 012: 700: Not8bit |= c; 701: } 702: } 703: #ifdef ZMODEM 704: Protocol = ZMODEM; 705: #endif 706: Zmodem = 1; 707: if (c < 0) 708: return c; 709: return Rxtype; 710: } 711: 712: /* Send a byte as two hex digits */ 713: zputhex(c) 714: register int c; 715: { 716: static char digits[] = "0123456789abcdef"; 717: 718: #ifdef DEBUGZ 719: if (Verbose>8) 720: vfile("zputhex: %02X", c); 721: #endif 722: sendline(digits[(c&0xF0)>>4]); 723: sendline(digits[(c)&0xF]); 724: } 725: 726: /* 727: * Send character c with ZMODEM escape sequence encoding. 728: * Escape XON, XOFF. Escape CR following @ (Telenet net escape) 729: */ 730: zsendline(c) 731: { 732: 733: /* Quick check for non control characters */ 734: if (c & 0140) 735: xsendline(lastsent = c); 736: else { 737: switch (c &= 0377) { 738: case ZDLE: 739: xsendline(ZDLE); 740: xsendline (lastsent = (c ^= 0100)); 741: break; 742: case 015: 743: case 0215: 744: if (!Zctlesc && (lastsent & 0177) != '@') 745: goto sendit; 746: /* **** FALL THRU TO **** */ 747: case 020: 748: case 021: 749: case 023: 750: case 0220: 751: case 0221: 752: case 0223: 753: xsendline(ZDLE); 754: c ^= 0100; 755: sendit: 756: xsendline(lastsent = c); 757: break; 758: default: 759: if (Zctlesc && ! (c & 0140)) { 760: xsendline(ZDLE); 761: c ^= 0100; 762: } 763: xsendline(lastsent = c); 764: } 765: } 766: } 767: 768: /* Decode two lower case hex digits into an 8 bit byte value */ 769: zgethex() 770: { 771: register int c; 772: 773: c = zgeth1(); 774: #ifdef DEBUGZ 775: if (Verbose>8) 776: vfile("zgethex: %02X", c); 777: #endif 778: return c; 779: } 780: zgeth1() 781: { 782: register int c, n; 783: 784: if ((c = noxrd7()) < 0) 785: return c; 786: n = c - '0'; 787: if (n > 9) 788: n -= ('a' - ':'); 789: if (n & ~0xF) 790: return ERROR; 791: if ((c = noxrd7()) < 0) 792: return c; 793: c -= '0'; 794: if (c > 9) 795: c -= ('a' - ':'); 796: if (c & ~0xF) 797: return ERROR; 798: c += (n<<4); 799: return c; 800: } 801: 802: /* 803: * Read a byte, checking for ZMODEM escape encoding 804: * including CAN*5 which represents a quick abort 805: */ 806: zdlread() 807: { 808: register int c; 809: 810: again: 811: /* Quick check for non control characters */ 812: if ((c = readline(Rxtimeout)) & 0140) 813: return c; 814: switch (c) { 815: case ZDLE: 816: break; 817: case 023: 818: case 0223: 819: case 021: 820: case 0221: 821: goto again; 822: default: 823: if (Zctlesc && !(c & 0140)) { 824: goto again; 825: } 826: return c; 827: } 828: again2: 829: if ((c = readline(Rxtimeout)) < 0) 830: return c; 831: if (c == CAN && (c = readline(Rxtimeout)) < 0) 832: return c; 833: if (c == CAN && (c = readline(Rxtimeout)) < 0) 834: return c; 835: if (c == CAN && (c = readline(Rxtimeout)) < 0) 836: return c; 837: switch (c) { 838: case CAN: 839: return GOTCAN; 840: case ZCRCE: 841: case ZCRCG: 842: case ZCRCQ: 843: case ZCRCW: 844: return (c | GOTOR); 845: case ZRUB0: 846: return 0177; 847: case ZRUB1: 848: return 0377; 849: case 023: 850: case 0223: 851: case 021: 852: case 0221: 853: goto again2; 854: default: 855: if (Zctlesc && ! (c & 0140)) { 856: goto again2; 857: } 858: if ((c & 0140) == 0100) 859: return (c ^ 0100); 860: break; 861: } 862: if (Verbose>1) 863: zperr("Bad escape sequence %x", c); 864: return ERROR; 865: } 866: 867: /* 868: * Read a character from the modem line with timeout. 869: * Eat parity, XON and XOFF characters. 870: */ 871: noxrd7() 872: { 873: register int c; 874: 875: for (;;) { 876: if ((c = readline(Rxtimeout)) < 0) 877: return c; 878: switch (c &= 0177) { 879: case XON: 880: case XOFF: 881: continue; 882: default: 883: if (Zctlesc && !(c & 0140)) 884: continue; 885: case '\r': 886: case '\n': 887: case ZDLE: 888: return c; 889: } 890: } 891: } 892: 893: /* Store long integer pos in Txhdr */ 894: stohdr(pos) 895: long pos; 896: { 897: Txhdr[ZP0] = pos; 898: Txhdr[ZP1] = pos>>8; 899: Txhdr[ZP2] = pos>>16; 900: Txhdr[ZP3] = pos>>24; 901: } 902: 903: /* Recover a long integer from a header */ 904: long 905: rclhdr(hdr) 906: register char *hdr; 907: { 908: register long l; 909: 910: l = (hdr[ZP3] & 0377); 911: l = (l << 8) | (hdr[ZP2] & 0377); 912: l = (l << 8) | (hdr[ZP1] & 0377); 913: l = (l << 8) | (hdr[ZP0] & 0377); 914: return l; 915: } 916: 917: /* End of zm.c */