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 */

Defined functions

garbitch defined in line 404; used 3 times
noxrd7 defined in line 871; used 4 times
rclhdr defined in line 904; used 5 times
stohdr defined in line 894; used 19 times
zdlread defined in line 806; used 23 times
zgeth1 defined in line 780; used 1 times
zgethdr defined in line 421; used 9 times
zgethex defined in line 769; used 5 times
zputhex defined in line 713; used 5 times
zrbhd32 defined in line 621; used 4 times
zrbhdr defined in line 586; used 2 times
zrdat32 defined in line 346; used 1 times
zrdata defined in line 284; used 6 times
zrhhdr defined in line 665; used 2 times
zsbh32 defined in line 161; used 2 times
zsbhdr defined in line 115; used 7 times
zsda32 defined in line 255; used 1 times
zsdata defined in line 226; used 7 times
zsendline defined in line 730; used 25 times
zshhdr defined in line 185; used 17 times

Defined variables

Altcan defined in line 76; never used
Attn defined in line 75; used 5 times
Crc32r defined in line 71; used 10 times
Crc32t defined in line 69; used 4 times
Rxcount defined in line 63; used 18 times
Rxframeind defined in line 60; used 5 times
Rxhdr defined in line 64; used 23 times
Rxhlen defined in line 62; used 10 times
Rxpos defined in line 66; used 24 times
Rxtimeout defined in line 51; used 20 times
Rxtype defined in line 61; used 7 times
Txfcs32 defined in line 68; used 5 times
Txhdr defined in line 65; used 42 times
Txpos defined in line 67; used 8 times
Usevhdrs defined in line 73; used 16 times
Zendnames defined in line 225; used 3 times
Znulls defined in line 74; used 2 times
badcrc defined in line 112; used 5 times
frametypes defined in line 81; used 4 times

Defined macros

FRTYPES defined in line 108; used 2 times
FTOFFSET defined in line 86; used 4 times
UNSL defined in line 55; used 6 times

Usage of this include

Last modified: 1992-06-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3182
Valid CSS Valid XHTML 1.0 Strict