1: #define VERSION "3.02 6-04-89"
   2: #define PUBDIR "/usr/spool/uucppublic"
   3: 
   4: /*% cc -compat -M2 -Ox -K -i -DMD % -o rz; size rz;
   5: <-xtx-*> cc386 -Ox -DMD rz.c -o $B/rz;  size $B/rz
   6:  *
   7:  * rz.c By Chuck Forsberg
   8:  *
   9:  *	cc -O rz.c -o rz		USG (3.0) Unix
  10:  * 	cc -O -DV7  rz.c -o rz		Unix V7, BSD 2.8 - 4.3
  11:  *
  12:  *	ln rz rb;  ln rz rx			For either system
  13:  *
  14:  *	ln rz /usr/bin/rzrmail		For remote mail.  Make this the
  15:  *					login shell. rzrmail then calls
  16:  *					rmail(1) to deliver mail.
  17:  *
  18:  * To compile on VMS:
  19:  *
  20:  *	define LNK$LIBRARY   SYS$LIBRARY:VAXCRTL.OLB
  21:  *	cc rz.c
  22:  *	cc vvmodem.c
  23:  *	link rz,vvmodem
  24:  *	rz :== $disk:[username.subdir]rz.exe
  25:  *      For high speed, try increasing the SYSGEN parameter TTY_TYPAHDSZ to 256.
  26:  *
  27:  *
  28:  *  Unix is a trademark of Western Electric Company
  29:  *
  30:  * A program for Unix to receive files and commands from computers running
  31:  *  Professional-YAM, PowerCom, YAM, IMP, or programs supporting XMODEM.
  32:  *  rz uses Unix buffered input to reduce wasted CPU time.
  33:  *
  34:  *
  35:  *	This version implements numerous enhancements including ZMODEM
  36:  *	Run Length Encoding and variable length headers.  These
  37:  *	features were not funded by the original Telenet development
  38:  *	contract.
  39:  *
  40:  * This software may be freely used for non commercial and
  41:  * educational (didactic only) purposes.  This software may also
  42:  * be freely used to support file transfer operations to or from
  43:  * licensed Omen Technology products.  Any programs which use
  44:  * part or all of this software must be provided in source form
  45:  * with this notice intact except by written permission from Omen
  46:  * Technology Incorporated.
  47:  *
  48:  * Use of this software for commercial or administrative purposes
  49:  * except when exclusively limited to interfacing Omen Technology
  50:  * products requires a per port license payment of $20.00 US per
  51:  * port (less in quantity).  Use of this code by inclusion,
  52:  * decompilation, reverse engineering or any other means
  53:  * constitutes agreement to these conditions and acceptance of
  54:  * liability to license the materials and payment of reasonable
  55:  * legal costs necessary to enforce this license agreement.
  56:  *
  57:  *
  58:  *		Omen Technology Inc		FAX: 503-621-3745
  59:  *		Post Office Box 4681
  60:  *		Portland OR 97208
  61:  *
  62:  *	This code is made available in the hope it will be useful,
  63:  *	BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  64:  *	DAMAGES OF ANY KIND.
  65:  *
  66:  *
  67:  *
  68:  * Iff the program is invoked by rzCOMMAND, output is piped to
  69:  * "COMMAND filename"  (Unix only)
  70:  *
  71:  *  Some systems (Venix, Coherent, Regulus) may not support tty raw mode
  72:  *  read(2) the same way as Unix. ONEREAD must be defined to force one
  73:  *  character reads for these systems. Added 7-01-84 CAF
  74:  *
  75:  *  Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF
  76:  *
  77:  *  BIX added 6-30-87 to support BIX(TM) upload protocol used by the
  78:  *  Byte Information Exchange.
  79:  *
  80:  *  NFGVMIN Updated 2-18-87 CAF for Xenix systems where c_cc[VMIN]
  81:  *  doesn't work properly (even though it compiles without error!),
  82:  *
  83:  *  SEGMENTS=n added 2-21-88 as a model for CP/M programs
  84:  *    for CP/M-80 systems that cannot overlap modem and disk I/O.
  85:  *
  86:  *  VMS flavor hacks begin with rz version 2.00
  87:  *
  88:  *  -DMD may be added to compiler command line to compile in
  89:  *    Directory-creating routines from Public Domain TAR by John Gilmore
  90:  *
  91:  *  HOWMANY may be tuned for best performance
  92:  *
  93:  *  USG UNIX (3.0) ioctl conventions courtesy  Jeff Martin
  94:  */
  95: 
  96: #ifdef vax11c
  97: #include <types.h>
  98: #include <stat.h>
  99: #define LOGFILE "rzlog.tmp"
 100: #include <stdio.h>
 101: #include <signal.h>
 102: #include <setjmp.h>
 103: #include <ctype.h>
 104: #include <errno.h>
 105: #define OS "VMS"
 106: #define BUFREAD
 107: extern int errno;
 108: #define SS_NORMAL SS$_NORMAL
 109: 
 110: #ifndef PROGNAME
 111: #define PROGNAME "rz"
 112: #endif
 113: 
 114: 
 115: #else
 116: 
 117: 
 118: #define SS_NORMAL 0
 119: #define LOGFILE "/tmp/rzlog"
 120: #include <stdio.h>
 121: #include <signal.h>
 122: #include <setjmp.h>
 123: #include <ctype.h>
 124: #include <errno.h>
 125: extern int errno;
 126: FILE *popen();
 127: #endif
 128: 
 129: #define OK 0
 130: #define FALSE 0
 131: #define TRUE 1
 132: #define ERROR (-1)
 133: 
 134: /*
 135:  * Max value for HOWMANY is 255.
 136:  *   A larger value reduces system overhead but may evoke kernel bugs.
 137:  *   133 corresponds to an XMODEM/CRC sector
 138:  */
 139: #ifndef HOWMANY
 140: #define HOWMANY 133
 141: #endif
 142: 
 143: /* Ward Christensen / CP/M parameters - Don't change these! */
 144: #define ENQ 005
 145: #define CAN ('X'&037)
 146: #define XOFF ('s'&037)
 147: #define XON ('q'&037)
 148: #define SOH 1
 149: #define STX 2
 150: #define EOT 4
 151: #define ACK 6
 152: #define NAK 025
 153: #define CPMEOF 032
 154: #define WANTCRC 0103    /* send C not NAK to get crc not checksum */
 155: #define TIMEOUT (-2)
 156: #define RCDO (-3)
 157: #define GCOUNT (-4)
 158: #define ERRORMAX 5
 159: #define RETRYMAX 5
 160: #define WCEOT (-10)
 161: #define PATHLEN 257 /* ready for 4.2 bsd ? */
 162: #define UNIXFILE 0xF000 /* The S_IFMT file mask bit for stat */
 163: 
 164: int Zmodem=0;       /* ZMODEM protocol requested */
 165: int Nozmodem = 0;   /* If invoked as "rb" */
 166: unsigned Baudrate = 2400;
 167: unsigned Effbaud = 2400;
 168: #ifdef vax11c
 169: #include "vrzsz.c"  /* most of the system dependent stuff here */
 170: #else
 171: #include "rbsb.c"   /* most of the system dependent stuff here */
 172: #endif
 173: #include "crctab.c"
 174: 
 175: char *substr();
 176: FILE *fout;
 177: 
 178: /*
 179:  * Routine to calculate the free bytes on the current file system
 180:  *  ~0 means many free bytes (unknown)
 181:  */
 182: long getfree()
 183: {
 184:     return(~0L);    /* many free bytes ... */
 185: }
 186: 
 187: int Lastrx;
 188: int Crcflg;
 189: int Firstsec;
 190: int Eofseen;        /* indicates cpm eof (^Z) has been received */
 191: int errors;
 192: int Restricted=0;   /* restricted; no /.. or ../ in filenames */
 193: #ifdef ONEREAD
 194: /* Sorry, Regulus and some others don't work right in raw mode! */
 195: int Readnum = 1;    /* Number of bytes to ask for in read() from modem */
 196: #else
 197: int Readnum = HOWMANY;  /* Number of bytes to ask for in read() from modem */
 198: #endif
 199: 
 200: #define DEFBYTL 2000000000L /* default rx file size */
 201: long Bytesleft;     /* number of bytes of incoming file left */
 202: long Modtime;       /* Unix style mod time for incoming file */
 203: int Filemode;       /* Unix style mode for incoming file */
 204: char Pathname[PATHLEN];
 205: char *Progname;     /* the name by which we were called */
 206: 
 207: int Batch=0;
 208: int Topipe=0;
 209: int MakeLCPathname=TRUE;    /* make received pathname lower case */
 210: int Verbose=0;
 211: int Quiet=0;        /* overrides logic that would otherwise set verbose */
 212: int Nflag = 0;      /* Don't really transfer files */
 213: int Rxclob=FALSE;   /* Clobber existing file */
 214: int Rxbinary=FALSE; /* receive all files in bin mode */
 215: int Rxascii=FALSE;  /* receive files in ascii (translate) mode */
 216: int Thisbinary;     /* current file is to be received in bin mode */
 217: int Blklen;     /* record length of received packets */
 218: 
 219: #ifdef SEGMENTS
 220: int chinseg = 0;    /* Number of characters received in this data seg */
 221: char secbuf[1+(SEGMENTS+1)*1024];
 222: #else
 223: char secbuf[1025];
 224: #endif
 225: 
 226: 
 227: char linbuf[HOWMANY];
 228: int Lleft=0;        /* number of characters in linbuf */
 229: time_t timep[2];
 230: char Lzmanag;       /* Local file management request */
 231: char zconv;     /* ZMODEM file conversion request */
 232: char zmanag;        /* ZMODEM file management request */
 233: char ztrans;        /* ZMODEM file transport request */
 234: int Zctlesc;        /* Encode control characters */
 235: int Zrwindow = 1400;    /* RX window size (controls garbage count) */
 236: 
 237: jmp_buf tohere;     /* For the interrupt on RX timeout */
 238: 
 239: #define xsendline(c) sendline(c)
 240: 
 241: #include "zm.c"
 242: 
 243: #include "zmr.c"
 244: 
 245: int tryzhdrtype=ZRINIT; /* Header type to send corresponding to Last rx close */
 246: 
 247: alrm()
 248: {
 249:     longjmp(tohere, -1);
 250: }
 251: 
 252: /* called by signal interrupt or terminate to clean things up */
 253: bibi(n)
 254: {
 255:     if (Zmodem)
 256:         zmputs(Attn);
 257:     canit(); mode(0);
 258:     fprintf(stderr, "rz: caught signal %d; exiting", n);
 259:     cucheck();
 260:     exit(128+n);
 261: }
 262: 
 263: main(argc, argv)
 264: char *argv[];
 265: {
 266:     register char *cp;
 267:     register npats;
 268:     char *virgin, **patts;
 269:     char *getenv();
 270:     int exitcode;
 271: 
 272:     Rxtimeout = 100;
 273:     setbuf(stderr, NULL);
 274:     if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
 275:         Restricted=TRUE;
 276: 
 277:     from_cu();
 278: #ifdef vax11c
 279:     chkinvok(virgin = PROGNAME);
 280: #else
 281:     chkinvok(virgin=argv[0]);   /* if called as [-]rzCOMMAND set flag */
 282: #endif
 283:     npats = 0;
 284:     while (--argc) {
 285:         cp = *++argv;
 286:         if (*cp == '-') {
 287:             while( *++cp) {
 288:                 switch(*cp) {
 289:                 case '\\':
 290:                      cp[1] = toupper(cp[1]);  continue;
 291:                 case '+':
 292:                     Lzmanag = ZMAPND; break;
 293:                 case 'a':
 294:                     Rxascii=TRUE;  break;
 295:                 case 'b':
 296:                     Rxbinary=TRUE; break;
 297:                 case 'c':
 298:                     Crcflg=TRUE; break;
 299: #ifndef vax11c
 300:                 case 'D':
 301:                     Nflag = TRUE; break;
 302: #endif
 303:                 case 'e':
 304:                     Zctlesc = 1; break;
 305:                 case 'p':
 306:                     Lzmanag = ZMPROT;  break;
 307:                 case 'q':
 308:                     Quiet=TRUE; Verbose=0; break;
 309:                 case 't':
 310:                     if (--argc < 1) {
 311:                         usage();
 312:                     }
 313:                     Rxtimeout = atoi(*++argv);
 314:                     if (Rxtimeout<10 || Rxtimeout>1000)
 315:                         usage();
 316:                     break;
 317:                 case 'w':
 318:                     if (--argc < 1) {
 319:                         usage();
 320:                     }
 321:                     Zrwindow = atoi(*++argv);
 322:                     break;
 323:                 case 'u':
 324:                     MakeLCPathname=FALSE; break;
 325:                 case 'v':
 326:                     ++Verbose; break;
 327:                 case 'y':
 328:                     Rxclob=TRUE; break;
 329:                 default:
 330:                     usage();
 331:                 }
 332:             }
 333:         }
 334:         else if ( !npats && argc>0) {
 335:             if (argv[0][0]) {
 336:                 npats=argc;
 337:                 patts=argv;
 338:             }
 339:         }
 340:     }
 341:     if (npats > 1)
 342:         usage();
 343:     if (Batch && npats)
 344:         usage();
 345:     if (Verbose) {
 346:         if (freopen(LOGFILE, "a", stderr)==NULL) {
 347:             printf("Can't open log file %s\n",LOGFILE);
 348:             exit(0200);
 349:         }
 350:         setbuf(stderr, NULL);
 351:         fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);
 352:     }
 353:     if (Fromcu && !Quiet) {
 354:         if (Verbose == 0)
 355:             Verbose = 2;
 356:     }
 357:     vfile("%s %s for %s\n", Progname, VERSION, OS);
 358:     mode(1);
 359:     if (signal(SIGINT, bibi) == SIG_IGN) {
 360:         signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
 361:     }
 362:     else {
 363:         signal(SIGINT, bibi); signal(SIGKILL, bibi);
 364:     }
 365:     signal(SIGTERM, bibi);
 366:     if (wcreceive(npats, patts)==ERROR) {
 367:         exitcode=0200;
 368:         canit();
 369:     }
 370:     mode(0);
 371:     if (exitcode && !Zmodem)    /* bellow again with all thy might. */
 372:         canit();
 373:     if (exitcode)
 374:         cucheck();
 375:     exit(exitcode ? exitcode:SS_NORMAL);
 376: }
 377: 
 378: 
 379: usage()
 380: {
 381:     cucheck();
 382:     fprintf(stderr,"Usage:	rz [-abeuvy]		(ZMODEM)\n");
 383:     fprintf(stderr,"or	rb [-abuvy]		(YMODEM)\n");
 384:     fprintf(stderr,"or	rx [-abcv] file	(XMODEM or XMODEM-1k)\n");
 385:     fprintf(stderr,"	  -a ASCII transfer (strip CR)\n");
 386:     fprintf(stderr,"	  -b Binary transfer for all files\n");
 387: #ifndef vax11c
 388:     fprintf(stderr,"	  -c Use 16 bit CRC	(XMODEM)\n");
 389: #endif
 390:     fprintf(stderr,"	  -e Escape control characters	(ZMODEM)\n");
 391:     fprintf(stderr,"	  -v Verbose more v's give more info\n");
 392:     fprintf(stderr,"	  -y Yes, clobber existing file if any\n");
 393:     fprintf(stderr,"%s %s for %s by Chuck Forsberg, Omen Technology INC\n",
 394:       Progname, VERSION, OS);
 395:     fprintf(stderr, "\t\t\042The High Reliability Software\042\n");
 396:     exit(SS_NORMAL);
 397: }
 398: /*
 399:  *  Debugging information output interface routine
 400:  */
 401: /* VARARGS1 */
 402: vfile(f, a, b, c, d)
 403: long a, b, c, d;
 404: {
 405:     if (Verbose > 2) {
 406:         fprintf(stderr, f, a, b, c, d);
 407:         fprintf(stderr, "\n");
 408:     }
 409: }
 410: 
 411: /*
 412:  * Let's receive something already.
 413:  */
 414: 
 415: char *rbmsg =
 416: "%s ready. To begin transfer, type \"%s file ...\" to your modem program\r\n\n";
 417: 
 418: wcreceive(argc, argp)
 419: char **argp;
 420: {
 421:     register c;
 422: 
 423:     if (Batch || argc==0) {
 424:         Crcflg=1;
 425:         if ( !Quiet)
 426:             fprintf(stderr, rbmsg, Progname, Nozmodem?"sb":"sz");
 427:         if (c=tryz()) {
 428:             if (c == ZCOMPL)
 429:                 return OK;
 430:             if (c == ERROR)
 431:                 goto fubar;
 432:             c = rzfiles();
 433:             if (c)
 434:                 goto fubar;
 435:         } else {
 436:             for (;;) {
 437:                 if (wcrxpn(secbuf)== ERROR)
 438:                     goto fubar;
 439:                 if (secbuf[0]==0)
 440:                     return OK;
 441:                 if (procheader(secbuf) == ERROR)
 442:                     goto fubar;
 443:                 if (wcrx()==ERROR)
 444:                     goto fubar;
 445:             }
 446:         }
 447:     } else {
 448:         Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
 449: 
 450:         procheader(""); strcpy(Pathname, *argp); checkpath(Pathname);
 451:         fprintf(stderr, "\nrz: ready to receive %s\r\n", Pathname);
 452:         if ((fout=fopen(Pathname, "w")) == NULL)
 453:             return ERROR;
 454:         if (wcrx()==ERROR)
 455:             goto fubar;
 456:     }
 457:     return OK;
 458: fubar:
 459:     canit();
 460: #ifndef vax11c
 461:     if (Topipe && fout) {
 462:         pclose(fout);  return ERROR;
 463:     }
 464: #endif
 465:     Modtime = 1;
 466:     if (fout)
 467:         fclose(fout);
 468: #ifndef vax11c
 469:     if (Restricted) {
 470:         unlink(Pathname);
 471:         fprintf(stderr, "\r\nrz: %s removed.\r\n", Pathname);
 472:     }
 473: #endif
 474:     return ERROR;
 475: }
 476: 
 477: 
 478: /*
 479:  * Fetch a pathname from the other end as a C ctyle ASCIZ string.
 480:  * Length is indeterminate as long as less than Blklen
 481:  * A null string represents no more files (YMODEM)
 482:  */
 483: wcrxpn(rpn)
 484: char *rpn;  /* receive a pathname */
 485: {
 486:     register c;
 487: 
 488: #ifdef NFGVMIN
 489:     readline(1);
 490: #else
 491:     purgeline();
 492: #endif
 493: 
 494: et_tu:
 495:     Firstsec=TRUE;  Eofseen=FALSE;
 496:     sendline(Crcflg?WANTCRC:NAK);
 497:     Lleft=0;    /* Do read next time ... */
 498:     while ((c = wcgetsec(rpn, 100)) != 0) {
 499:         if (c == WCEOT) {
 500:             zperr( "Pathname fetch returned %d", c);
 501:             sendline(ACK);
 502:             Lleft=0;    /* Do read next time ... */
 503:             readline(1);
 504:             goto et_tu;
 505:         }
 506:         return ERROR;
 507:     }
 508:     sendline(ACK);
 509:     return OK;
 510: }
 511: 
 512: /*
 513:  * Adapted from CMODEM13.C, written by
 514:  * Jack M. Wierda and Roderick W. Hart
 515:  */
 516: 
 517: wcrx()
 518: {
 519:     register int sectnum, sectcurr;
 520:     register char sendchar;
 521:     register char *p;
 522:     int cblklen;            /* bytes to dump this block */
 523: 
 524:     Firstsec=TRUE;sectnum=0; Eofseen=FALSE;
 525:     sendchar=Crcflg?WANTCRC:NAK;
 526: 
 527:     for (;;) {
 528:         sendline(sendchar); /* send it now, we're ready! */
 529:         Lleft=0;    /* Do read next time ... */
 530:         sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130);
 531:         report(sectcurr);
 532:         if (sectcurr==(sectnum+1 &0377)) {
 533:             sectnum++;
 534:             cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;
 535:             if (putsec(secbuf, cblklen)==ERROR)
 536:                 return ERROR;
 537:             if ((Bytesleft-=cblklen) < 0)
 538:                 Bytesleft = 0;
 539:             sendchar=ACK;
 540:         }
 541:         else if (sectcurr==(sectnum&0377)) {
 542:             zperr( "Received dup Sector");
 543:             sendchar=ACK;
 544:         }
 545:         else if (sectcurr==WCEOT) {
 546:             if (closeit())
 547:                 return ERROR;
 548:             sendline(ACK);
 549:             Lleft=0;    /* Do read next time ... */
 550:             return OK;
 551:         }
 552:         else if (sectcurr==ERROR)
 553:             return ERROR;
 554:         else {
 555:             zperr( "Sync Error");
 556:             return ERROR;
 557:         }
 558:     }
 559: }
 560: 
 561: /*
 562:  * Wcgetsec fetches a Ward Christensen type sector.
 563:  * Returns sector number encountered or ERROR if valid sector not received,
 564:  * or CAN CAN received
 565:  * or WCEOT if eot sector
 566:  * time is timeout for first char, set to 4 seconds thereafter
 567:  ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
 568:  *    (Caller must do that when he is good and ready to get next sector)
 569:  */
 570: 
 571: wcgetsec(rxbuf, maxtime)
 572: char *rxbuf;
 573: int maxtime;
 574: {
 575:     register checksum, wcj, firstch;
 576:     register unsigned short oldcrc;
 577:     register char *p;
 578:     int sectcurr;
 579: 
 580:     for (Lastrx=errors=0; errors<RETRYMAX; errors++) {
 581: 
 582:         if ((firstch=readline(maxtime))==STX) {
 583:             Blklen=1024; goto get2;
 584:         }
 585:         if (firstch==SOH) {
 586:             Blklen=128;
 587: get2:
 588:             sectcurr=readline(1);
 589:             if ((sectcurr+(oldcrc=readline(1)))==0377) {
 590:                 oldcrc=checksum=0;
 591:                 for (p=rxbuf,wcj=Blklen; --wcj>=0; ) {
 592:                     if ((firstch=readline(1)) < 0)
 593:                         goto bilge;
 594:                     oldcrc=updcrc(firstch, oldcrc);
 595:                     checksum += (*p++ = firstch);
 596:                 }
 597:                 if ((firstch=readline(1)) < 0)
 598:                     goto bilge;
 599:                 if (Crcflg) {
 600:                     oldcrc=updcrc(firstch, oldcrc);
 601:                     if ((firstch=readline(1)) < 0)
 602:                         goto bilge;
 603:                     oldcrc=updcrc(firstch, oldcrc);
 604:                     if (oldcrc & 0xFFFF)
 605:                         zperr( "CRC");
 606:                     else {
 607:                         Firstsec=FALSE;
 608:                         return sectcurr;
 609:                     }
 610:                 }
 611:                 else if (((checksum-firstch)&0377)==0) {
 612:                     Firstsec=FALSE;
 613:                     return sectcurr;
 614:                 }
 615:                 else
 616:                     zperr( "Checksum");
 617:             }
 618:             else
 619:                 zperr("Sector number garbled");
 620:         }
 621:         /* make sure eot really is eot and not just mixmash */
 622: #ifdef NFGVMIN
 623:         else if (firstch==EOT && readline(1)==TIMEOUT)
 624:             return WCEOT;
 625: #else
 626:         else if (firstch==EOT && Lleft==0)
 627:             return WCEOT;
 628: #endif
 629:         else if (firstch==CAN) {
 630:             if (Lastrx==CAN) {
 631:                 zperr( "Sender CANcelled");
 632:                 return ERROR;
 633:             } else {
 634:                 Lastrx=CAN;
 635:                 continue;
 636:             }
 637:         }
 638:         else if (firstch==TIMEOUT) {
 639:             if (Firstsec)
 640:                 goto humbug;
 641: bilge:
 642:             zperr( "TIMEOUT");
 643:         }
 644:         else
 645:             zperr( "Got 0%o sector header", firstch);
 646: 
 647: humbug:
 648:         Lastrx=0;
 649:         while(readline(1)!=TIMEOUT)
 650:             ;
 651:         if (Firstsec) {
 652:             sendline(Crcflg?WANTCRC:NAK);
 653:             Lleft=0;    /* Do read next time ... */
 654:         } else {
 655:             maxtime=40; sendline(NAK);
 656:             Lleft=0;    /* Do read next time ... */
 657:         }
 658:     }
 659:     /* try to stop the bubble machine. */
 660:     canit();
 661:     return ERROR;
 662: }
 663: 
 664: #ifndef vax11c
 665: /*
 666:  * This version of readline is reasoably well suited for
 667:  * reading many characters.
 668:  *  (except, currently, for the Regulus version!)
 669:  *
 670:  * timeout is in tenths of seconds
 671:  */
 672: readline(timeout)
 673: int timeout;
 674: {
 675:     register n;
 676:     static char *cdq;   /* pointer for removing chars from linbuf */
 677: 
 678:     if (--Lleft >= 0) {
 679:         if (Verbose > 8) {
 680:             fprintf(stderr, "%02x ", *cdq&0377);
 681:         }
 682:         return (*cdq++ & 0377);
 683:     }
 684:     n = timeout/10;
 685:     if (n < 2)
 686:         n = 3;
 687:     if (Verbose > 5)
 688:         fprintf(stderr, "Calling read: alarm=%d  Readnum=%d ",
 689:           n, Readnum);
 690:     if (setjmp(tohere)) {
 691: #ifdef TIOCFLUSH
 692: /*		ioctl(0, TIOCFLUSH, 0); */
 693: #endif
 694:         Lleft = 0;
 695:         if (Verbose>1)
 696:             fprintf(stderr, "Readline:TIMEOUT\n");
 697:         return TIMEOUT;
 698:     }
 699:     signal(SIGALRM, alrm); alarm(n);
 700:     Lleft=read(0, cdq=linbuf, Readnum);
 701:     alarm(0);
 702:     if (Verbose > 5) {
 703:         fprintf(stderr, "Read returned %d bytes\n", Lleft);
 704:     }
 705:     if (Lleft < 1)
 706:         return TIMEOUT;
 707:     --Lleft;
 708:     if (Verbose > 8) {
 709:         fprintf(stderr, "%02x ", *cdq&0377);
 710:     }
 711:     return (*cdq++ & 0377);
 712: }
 713: 
 714: 
 715: 
 716: /*
 717:  * Purge the modem input queue of all characters
 718:  */
 719: purgeline()
 720: {
 721:     Lleft = 0;
 722: #ifdef USG
 723:     ioctl(0, TCFLSH, 0);
 724: #else
 725:     lseek(0, 0L, 2);
 726: #endif
 727: }
 728: #endif
 729: 
 730: 
 731: /*
 732:  * Process incoming file information header
 733:  */
 734: procheader(name)
 735: char *name;
 736: {
 737:     register char *openmode, *p, **pp;
 738: 
 739:     /* set default parameters and overrides */
 740:     openmode = "w";
 741:     Thisbinary = (!Rxascii) || Rxbinary;
 742:     if (Lzmanag)
 743:         zmanag = Lzmanag;
 744: 
 745:     /*
 746: 	 *  Process ZMODEM remote file management requests
 747: 	 */
 748:     if (!Rxbinary && zconv == ZCNL) /* Remote ASCII override */
 749:         Thisbinary = 0;
 750:     if (zconv == ZCBIN) /* Remote Binary override */
 751:         Thisbinary = TRUE;
 752:     else if (zmanag == ZMAPND)
 753:         openmode = "a";
 754: 
 755: #ifndef BIX
 756:     /* Check for existing file */
 757:     if (!Rxclob && (zmanag&ZMMASK) != ZMCLOB && (fout=fopen(name, "r"))) {
 758:         fclose(fout);  return ERROR;
 759:     }
 760: #endif
 761: 
 762:     Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
 763: 
 764:     p = name + 1 + strlen(name);
 765:     if (*p) {   /* file coming from Unix or DOS system */
 766:         sscanf(p, "%ld%lo%o", &Bytesleft, &Modtime, &Filemode);
 767: #ifndef vax11c
 768:         if (Filemode & UNIXFILE)
 769:             ++Thisbinary;
 770: #endif
 771:         if (Verbose) {
 772:             fprintf(stderr,  "Incoming: %s %ld %lo %o\n",
 773:               name, Bytesleft, Modtime, Filemode);
 774:         }
 775:     }
 776: 
 777: #ifdef BIX
 778:     if ((fout=fopen("scratchpad", openmode)) == NULL)
 779:         return ERROR;
 780:     return OK;
 781: #else
 782: 
 783:     else {      /* File coming from CP/M system */
 784:         for (p=name; *p; ++p)       /* change / to _ */
 785:             if ( *p == '/')
 786:                 *p = '_';
 787: 
 788:         if ( *--p == '.')       /* zap trailing period */
 789:             *p = 0;
 790:     }
 791: 
 792: #ifndef vax11c
 793:     if (!Zmodem && MakeLCPathname && !IsAnyLower(name)
 794:       && !(Filemode&UNIXFILE))
 795:         uncaps(name);
 796: #endif
 797:     if (Topipe > 0) {
 798:         sprintf(Pathname, "%s %s", Progname+2, name);
 799:         if (Verbose)
 800:             fprintf(stderr,  "Topipe: %s %s\n",
 801:               Pathname, Thisbinary?"BIN":"ASCII");
 802: #ifndef vax11c
 803:         if ((fout=popen(Pathname, "w")) == NULL)
 804:             return ERROR;
 805: #endif
 806:     } else {
 807:         strcpy(Pathname, name);
 808:         if (Verbose) {
 809:             fprintf(stderr,  "Receiving %s %s %s\n",
 810:               name, Thisbinary?"BIN":"ASCII", openmode);
 811:         }
 812:         checkpath(name);
 813:         if (Nflag)
 814:             name = "/dev/null";
 815: #ifndef vax11c
 816:         if (name[0] == '!' || name[0] == '|') {
 817:             if ( !(fout = popen(name+1, "w"))) {
 818:                 return ERROR;
 819:             }
 820:             Topipe = -1;  return(OK);
 821:         }
 822: #endif
 823: #ifdef MD
 824:         fout = fopen(name, openmode);
 825:         if ( !fout)
 826:             if (make_dirs(name))
 827:                 fout = fopen(name, openmode);
 828: #else
 829:         fout = fopen(name, openmode);
 830: #endif
 831:         if ( !fout)
 832:             return ERROR;
 833:     }
 834:     return OK;
 835: #endif /* BIX */
 836: }
 837: 
 838: #ifdef MD
 839: /*
 840:  *  Directory-creating routines from Public Domain TAR by John Gilmore
 841:  */
 842: 
 843: /*
 844:  * After a file/link/symlink/dir creation has failed, see if
 845:  * it's because some required directory was not present, and if
 846:  * so, create all required dirs.
 847:  */
 848: make_dirs(pathname)
 849: register char *pathname;
 850: {
 851:     register char *p;       /* Points into path */
 852:     int madeone = 0;        /* Did we do anything yet? */
 853:     int save_errno = errno;     /* Remember caller's errno */
 854:     char *strchr();
 855: 
 856:     if (errno != ENOENT)
 857:         return 0;       /* Not our problem */
 858: 
 859:     for (p = strchr(pathname, '/'); p != NULL; p = strchr(p+1, '/')) {
 860:         /* Avoid mkdir of empty string, if leading or double '/' */
 861:         if (p == pathname || p[-1] == '/')
 862:             continue;
 863:         /* Avoid mkdir where last part of path is '.' */
 864:         if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
 865:             continue;
 866:         *p = 0;             /* Truncate the path there */
 867:         if ( !mkdir(pathname, 0777)) {  /* Try to create it as a dir */
 868:             vfile("Made directory %s\n", pathname);
 869:             madeone++;      /* Remember if we made one */
 870:             *p = '/';
 871:             continue;
 872:         }
 873:         *p = '/';
 874:         if (errno == EEXIST)        /* Directory already exists */
 875:             continue;
 876:         /*
 877: 		 * Some other error in the mkdir.  We return to the caller.
 878: 		 */
 879:         break;
 880:     }
 881:     errno = save_errno;     /* Restore caller's errno */
 882:     return madeone;         /* Tell them to retry if we made one */
 883: }
 884: 
 885: #if (MD != 2)
 886: #define TERM_SIGNAL(status) ((status) & 0x7F)
 887: #define TERM_COREDUMP(status)   (((status) & 0x80) != 0)
 888: #define TERM_VALUE(status)  ((status) >> 8)
 889: /*
 890:  * Make a directory.  Compatible with the mkdir() system call on 4.2BSD.
 891:  */
 892: mkdir(dpath, dmode)
 893: char *dpath;
 894: int dmode;
 895: {
 896:     int cpid, status;
 897:     struct stat statbuf;
 898: 
 899:     if (stat(dpath,&statbuf) == 0) {
 900:         errno = EEXIST;     /* Stat worked, so it already exists */
 901:         return -1;
 902:     }
 903: 
 904:     /* If stat fails for a reason other than non-existence, return error */
 905:     if (errno != ENOENT) return -1;
 906: 
 907:     switch (cpid = fork()) {
 908: 
 909:     case -1:            /* Error in fork() */
 910:         return(-1);     /* Errno is set already */
 911: 
 912:     case 0:             /* Child process */
 913:         /*
 914: 		 * Cheap hack to set mode of new directory.  Since this
 915: 		 * child process is going away anyway, we zap its umask.
 916: 		 * FIXME, this won't suffice to set SUID, SGID, etc. on this
 917: 		 * directory.  Does anybody care?
 918: 		 */
 919:         status = umask(0);  /* Get current umask */
 920:         status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
 921:         execl("/bin/mkdir", "mkdir", dpath, (char *)0);
 922:         _exit(-1);      /* Can't exec /bin/mkdir */
 923: 
 924:     default:            /* Parent process */
 925:         while (cpid != wait(&status)) ; /* Wait for kid to finish */
 926:     }
 927: 
 928:     if (TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0) {
 929:         errno = EIO;        /* We don't know why, but */
 930:         return -1;      /* /bin/mkdir failed */
 931:     }
 932: 
 933:     return 0;
 934: }
 935: #endif /* MD != 2 */
 936: #endif /* MD */
 937: 
 938: /*
 939:  * Putsec writes the n characters of buf to receive file fout.
 940:  *  If not in binary mode, carriage returns, and all characters
 941:  *  starting with CPMEOF are discarded.
 942:  */
 943: putsec(buf, n)
 944: char *buf;
 945: register n;
 946: {
 947:     register char *p;
 948: 
 949:     if (n == 0)
 950:         return OK;
 951:     if (Thisbinary) {
 952:         for (p=buf; --n>=0; )
 953:             putc( *p++, fout);
 954:     }
 955:     else {
 956:         if (Eofseen)
 957:             return OK;
 958:         for (p=buf; --n>=0; ++p ) {
 959:             if ( *p == '\r')
 960:                 continue;
 961:             if (*p == CPMEOF) {
 962:                 Eofseen=TRUE; return OK;
 963:             }
 964:             putc(*p ,fout);
 965:         }
 966:     }
 967:     return OK;
 968: }
 969: 
 970: #ifndef vax11c
 971: /*
 972:  *  Send a character to modem.  Small is beautiful.
 973:  */
 974: sendline(c)
 975: {
 976:     char d;
 977: 
 978:     d = c;
 979:     if (Verbose>6)
 980:         fprintf(stderr, "Sendline: %x\n", c);
 981:     write(1, &d, 1);
 982: }
 983: 
 984: flushmo() {}
 985: #endif
 986: 
 987: 
 988: 
 989: 
 990: 
 991: /* make string s lower case */
 992: uncaps(s)
 993: register char *s;
 994: {
 995:     for ( ; *s; ++s)
 996:         if (isupper(*s))
 997:             *s = tolower(*s);
 998: }
 999: /*
1000:  * IsAnyLower returns TRUE if string s has lower case letters.
1001:  */
1002: IsAnyLower(s)
1003: register char *s;
1004: {
1005:     for ( ; *s; ++s)
1006:         if (islower(*s))
1007:             return TRUE;
1008:     return FALSE;
1009: }
1010: 
1011: /*
1012:  * substr(string, token) searches for token in string s
1013:  * returns pointer to token within string if found, NULL otherwise
1014:  */
1015: char *
1016: substr(s, t)
1017: register char *s,*t;
1018: {
1019:     register char *ss,*tt;
1020:     /* search for first char of token */
1021:     for (ss=s; *s; s++)
1022:         if (*s == *t)
1023:             /* compare token with substring */
1024:             for (ss=s,tt=t; ;) {
1025:                 if (*tt == 0)
1026:                     return s;
1027:                 if (*ss++ != *tt++)
1028:                     break;
1029:             }
1030:     return NULL;
1031: }
1032: 
1033: /*
1034:  * Log an error
1035:  */
1036: /*VARARGS1*/
1037: zperr(s,p,u)
1038: char *s, *p, *u;
1039: {
1040:     if (Verbose <= 0)
1041:         return;
1042:     fprintf(stderr, "Retry %d: ", errors);
1043:     fprintf(stderr, s, p, u);
1044:     fprintf(stderr, "\n");
1045: }
1046: 
1047: /* send cancel string to get the other end to shut up */
1048: canit()
1049: {
1050:     static char canistr[] = {
1051:      24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
1052:     };
1053: 
1054: #ifdef vax11c
1055:     raw_wbuf(strlen(canistr), canistr);
1056:     purgeline();
1057: #else
1058:     printf(canistr);
1059:     Lleft=0;    /* Do read next time ... */
1060:     fflush(stdout);
1061: #endif
1062: }
1063: 
1064: 
1065: report(sct)
1066: int sct;
1067: {
1068:     if (Verbose>1)
1069:         fprintf(stderr,"%03d%c",sct,sct%10? ' ' : '\r');
1070: }
1071: 
1072: /*
1073:  * If called as [-][dir/../]vrzCOMMAND set Verbose to 1
1074:  * If called as [-][dir/../]rzCOMMAND set the pipe flag
1075:  * If called as rb use YMODEM protocol
1076:  */
1077: chkinvok(s)
1078: char *s;
1079: {
1080:     register char *p;
1081: 
1082:     p = s;
1083:     while (*p == '-')
1084:         s = ++p;
1085:     while (*p)
1086:         if (*p++ == '/')
1087:             s = p;
1088:     if (*s == 'v') {
1089:         Verbose=1; ++s;
1090:     }
1091:     Progname = s;
1092:     if (s[0]=='r' && s[1]=='z')
1093:         Batch = TRUE;
1094:     if (s[0]=='r' && s[1]=='b')
1095:         Batch = Nozmodem = TRUE;
1096:     if (s[2] && s[0]=='r' && s[1]=='b')
1097:         Topipe = 1;
1098:     if (s[2] && s[0]=='r' && s[1]=='z')
1099:         Topipe = 1;
1100: }
1101: 
1102: /*
1103:  * Totalitarian Communist pathname processing
1104:  */
1105: checkpath(name)
1106: char *name;
1107: {
1108:     if (Restricted) {
1109:         if (fopen(name, "r") != NULL) {
1110:             canit();
1111:             fprintf(stderr, "\r\nrz: %s exists\n", name);
1112:             bibi(-1);
1113:         }
1114:         /* restrict pathnames to current tree or uucppublic */
1115:         if ( substr(name, "../")
1116:          || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
1117:             canit();
1118:             fprintf(stderr,"\r\nrz:\tSecurity Violation\r\n");
1119:             bibi(-1);
1120:         }
1121:     }
1122: }
1123: 
1124: /*
1125:  * Initialize for Zmodem receive attempt, try to activate Zmodem sender
1126:  *  Handles ZSINIT frame
1127:  *  Return ZFILE if Zmodem filename received, -1 on error,
1128:  *   ZCOMPL if transaction finished,  else 0
1129:  */
1130: tryz()
1131: {
1132:     register c, n;
1133:     register cmdzack1flg;
1134: 
1135:     if (Nozmodem)       /* Check for "rb" program name */
1136:         return 0;
1137: 
1138: 
1139:     for (n=Zmodem?15:5; --n>=0; ) {
1140:         /* Set buffer length (0) and capability flags */
1141: #ifdef SEGMENTS
1142:         stohdr(SEGMENTS*1024L);
1143: #else
1144:         stohdr(0L);
1145: #endif
1146: #ifdef CANBREAK
1147:         Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
1148: #else
1149:         Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
1150: #endif
1151:         if (Zctlesc)
1152:             Txhdr[ZF0] |= TESCCTL;
1153:         Txhdr[ZF0] |= CANRLE;
1154:         Txhdr[ZF1] = CANVHDR;
1155:         /* tryzhdrtype may == ZRINIT */
1156:         zshhdr(4,tryzhdrtype, Txhdr);
1157:         if (tryzhdrtype == ZSKIP)   /* Don't skip too far */
1158:             tryzhdrtype = ZRINIT;   /* CAF 8-21-87 */
1159: again:
1160:         switch (zgethdr(Rxhdr, 0)) {
1161:         case ZRQINIT:
1162:             if (Rxhdr[ZF3] & 0x80)
1163:                 Usevhdrs = 1;   /* we can var header */
1164:             continue;
1165:         case ZEOF:
1166:             continue;
1167:         case TIMEOUT:
1168:             continue;
1169:         case ZFILE:
1170:             zconv = Rxhdr[ZF0];
1171:             zmanag = Rxhdr[ZF1];
1172:             ztrans = Rxhdr[ZF2];
1173:             if (Rxhdr[ZF3] & ZCANVHDR)
1174:                 Usevhdrs = TRUE;
1175:             tryzhdrtype = ZRINIT;
1176:             c = zrdata(secbuf, 1024);
1177:             mode(3);
1178:             if (c == GOTCRCW)
1179:                 return ZFILE;
1180:             zshhdr(4,ZNAK, Txhdr);
1181:             goto again;
1182:         case ZSINIT:
1183:             Zctlesc = TESCCTL & Rxhdr[ZF0];
1184:             if (zrdata(Attn, ZATTNLEN) == GOTCRCW) {
1185:                 stohdr(1L);
1186:                 zshhdr(4,ZACK, Txhdr);
1187:                 goto again;
1188:             }
1189:             zshhdr(4,ZNAK, Txhdr);
1190:             goto again;
1191:         case ZFREECNT:
1192:             stohdr(getfree());
1193:             zshhdr(4,ZACK, Txhdr);
1194:             goto again;
1195:         case ZCOMMAND:
1196: #ifdef vax11c
1197:             return ERROR;
1198: #else
1199:             cmdzack1flg = Rxhdr[ZF0];
1200:             if (zrdata(secbuf, 1024) == GOTCRCW) {
1201:                 if (cmdzack1flg & ZCACK1)
1202:                     stohdr(0L);
1203:                 else
1204:                     stohdr((long)sys2(secbuf));
1205:                 purgeline();    /* dump impatient questions */
1206:                 do {
1207:                     zshhdr(4,ZCOMPL, Txhdr);
1208:                 }
1209:                 while (++errors<20 && zgethdr(Rxhdr,1) != ZFIN);
1210:                 ackbibi();
1211:                 if (cmdzack1flg & ZCACK1)
1212:                     exec2(secbuf);
1213:                 return ZCOMPL;
1214:             }
1215:             zshhdr(4,ZNAK, Txhdr); goto again;
1216: #endif
1217:         case ZCOMPL:
1218:             goto again;
1219:         default:
1220:             continue;
1221:         case ZFIN:
1222:             ackbibi(); return ZCOMPL;
1223:         case ZCAN:
1224:             return ERROR;
1225:         }
1226:     }
1227:     return 0;
1228: }
1229: 
1230: /*
1231:  * Receive 1 or more files with ZMODEM protocol
1232:  */
1233: rzfiles()
1234: {
1235:     register c;
1236: 
1237:     for (;;) {
1238:         switch (c = rzfile()) {
1239:         case ZEOF:
1240:         case ZSKIP:
1241:             switch (tryz()) {
1242:             case ZCOMPL:
1243:                 return OK;
1244:             default:
1245:                 return ERROR;
1246:             case ZFILE:
1247:                 break;
1248:             }
1249:             continue;
1250:         default:
1251:             return c;
1252:         case ERROR:
1253:             return ERROR;
1254:         }
1255:     }
1256: }
1257: 
1258: /*
1259:  * Receive a file with ZMODEM protocol
1260:  *  Assumes file name frame is in secbuf
1261:  */
1262: rzfile()
1263: {
1264:     register c, n;
1265:     long rxbytes;
1266: 
1267:     Eofseen=FALSE;
1268:     if (procheader(secbuf) == ERROR) {
1269:         return (tryzhdrtype = ZSKIP);
1270:     }
1271: 
1272:     n = 20; rxbytes = 0l;
1273: 
1274:     for (;;) {
1275: #ifdef SEGMENTS
1276:         chinseg = 0;
1277: #endif
1278:         stohdr(rxbytes);
1279:         zshhdr(4,ZRPOS, Txhdr);
1280: nxthdr:
1281:         switch (c = zgethdr(Rxhdr, 0)) {
1282:         default:
1283:             vfile("rzfile: zgethdr returned %d", c);
1284:             return ERROR;
1285:         case ZNAK:
1286:         case TIMEOUT:
1287: #ifdef SEGMENTS
1288:             putsec(secbuf, chinseg);
1289:             chinseg = 0;
1290: #endif
1291:             if ( --n < 0) {
1292:                 vfile("rzfile: zgethdr returned %d", c);
1293:                 return ERROR;
1294:             }
1295:         case ZFILE:
1296:             zrdata(secbuf, 1024);
1297:             continue;
1298:         case ZEOF:
1299: #ifdef SEGMENTS
1300:             putsec(secbuf, chinseg);
1301:             chinseg = 0;
1302: #endif
1303:             if (rclhdr(Rxhdr) != rxbytes) {
1304:                 /*
1305: 				 * Ignore eof if it's at wrong place - force
1306: 				 *  a timeout because the eof might have gone
1307: 				 *  out before we sent our zrpos.
1308: 				 */
1309:                 errors = 0;  goto nxthdr;
1310:             }
1311:             if (closeit()) {
1312:                 tryzhdrtype = ZFERR;
1313:                 vfile("rzfile: closeit returned <> 0");
1314:                 return ERROR;
1315:             }
1316:             vfile("rzfile: normal EOF");
1317:             return c;
1318:         case ERROR: /* Too much garbage in header search error */
1319: #ifdef SEGMENTS
1320:             putsec(secbuf, chinseg);
1321:             chinseg = 0;
1322: #endif
1323:             if ( --n < 0) {
1324:                 vfile("rzfile: zgethdr returned %d", c);
1325:                 return ERROR;
1326:             }
1327:             zmputs(Attn);
1328:             continue;
1329:         case ZSKIP:
1330: #ifdef SEGMENTS
1331:             putsec(secbuf, chinseg);
1332:             chinseg = 0;
1333: #endif
1334:             Modtime = 1;
1335:             closeit();
1336:             vfile("rzfile: Sender SKIPPED file");
1337:             return c;
1338:         case ZDATA:
1339:             if (rclhdr(Rxhdr) != rxbytes) {
1340:                 if ( --n < 0) {
1341:                     return ERROR;
1342:                 }
1343: #ifdef SEGMENTS
1344:                 putsec(secbuf, chinseg);
1345:                 chinseg = 0;
1346: #endif
1347:                 zmputs(Attn);  continue;
1348:             }
1349: moredata:
1350:             if (Verbose>1)
1351:                 fprintf(stderr, "\r%7ld ZMODEM%s    ",
1352:                   rxbytes, Crc32r?" CRC-32":"");
1353: #ifdef SEGMENTS
1354:             if (chinseg >= (1024 * SEGMENTS)) {
1355:                 putsec(secbuf, chinseg);
1356:                 chinseg = 0;
1357:             }
1358:             switch (c = zrdata(secbuf+chinseg, 1024))
1359: #else
1360:             switch (c = zrdata(secbuf, 1024))
1361: #endif
1362:             {
1363:             case ZCAN:
1364: #ifdef SEGMENTS
1365:                 putsec(secbuf, chinseg);
1366:                 chinseg = 0;
1367: #endif
1368:                 vfile("rzfile: zgethdr returned %d", c);
1369:                 return ERROR;
1370:             case ERROR: /* CRC error */
1371: #ifdef SEGMENTS
1372:                 putsec(secbuf, chinseg);
1373:                 chinseg = 0;
1374: #endif
1375:                 if ( --n < 0) {
1376:                     vfile("rzfile: zgethdr returned %d", c);
1377:                     return ERROR;
1378:                 }
1379:                 zmputs(Attn);
1380:                 continue;
1381:             case TIMEOUT:
1382: #ifdef SEGMENTS
1383:                 putsec(secbuf, chinseg);
1384:                 chinseg = 0;
1385: #endif
1386:                 if ( --n < 0) {
1387:                     vfile("rzfile: zgethdr returned %d", c);
1388:                     return ERROR;
1389:                 }
1390:                 continue;
1391:             case GOTCRCW:
1392:                 n = 20;
1393: #ifdef SEGMENTS
1394:                 chinseg += Rxcount;
1395:                 putsec(secbuf, chinseg);
1396:                 chinseg = 0;
1397: #else
1398:                 putsec(secbuf, Rxcount);
1399: #endif
1400:                 rxbytes += Rxcount;
1401:                 stohdr(rxbytes);
1402:                 zshhdr(4,ZACK, Txhdr);
1403:                 sendline(XON);
1404:                 goto nxthdr;
1405:             case GOTCRCQ:
1406:                 n = 20;
1407: #ifdef SEGMENTS
1408:                 chinseg += Rxcount;
1409: #else
1410:                 putsec(secbuf, Rxcount);
1411: #endif
1412:                 rxbytes += Rxcount;
1413:                 stohdr(rxbytes);
1414:                 zshhdr(4,ZACK, Txhdr);
1415:                 goto moredata;
1416:             case GOTCRCG:
1417:                 n = 20;
1418: #ifdef SEGMENTS
1419:                 chinseg += Rxcount;
1420: #else
1421:                 putsec(secbuf, Rxcount);
1422: #endif
1423:                 rxbytes += Rxcount;
1424:                 goto moredata;
1425:             case GOTCRCE:
1426:                 n = 20;
1427: #ifdef SEGMENTS
1428:                 chinseg += Rxcount;
1429: #else
1430:                 putsec(secbuf, Rxcount);
1431: #endif
1432:                 rxbytes += Rxcount;
1433:                 goto nxthdr;
1434:             }
1435:         }
1436:     }
1437: }
1438: 
1439: /*
1440:  * Send a string to the modem, processing for \336 (sleep 1 sec)
1441:  *   and \335 (break signal)
1442:  */
1443: zmputs(s)
1444: char *s;
1445: {
1446:     register c;
1447: 
1448:     while (*s) {
1449:         switch (c = *s++) {
1450:         case '\336':
1451:             sleep(1); continue;
1452:         case '\335':
1453:             sendbrk(); continue;
1454:         default:
1455:             sendline(c);
1456:         }
1457:     }
1458: }
1459: 
1460: /*
1461:  * Close the receive dataset, return OK or ERROR
1462:  */
1463: closeit()
1464: {
1465:     time_t time();
1466: 
1467: #ifndef vax11c
1468:     if (Topipe) {
1469:         if (pclose(fout)) {
1470:             return ERROR;
1471:         }
1472:         return OK;
1473:     }
1474: #endif
1475:     if (fclose(fout)==ERROR) {
1476:         fprintf(stderr, "file close ERROR\n");
1477:         return ERROR;
1478:     }
1479: #ifndef vax11c
1480:     if (Modtime) {
1481:         timep[0] = time(NULL);
1482:         timep[1] = Modtime;
1483:         utime(Pathname, timep);
1484:     }
1485: #endif
1486:     if ((Filemode&S_IFMT) == S_IFREG)
1487:         chmod(Pathname, (07777 & Filemode));
1488:     return OK;
1489: }
1490: 
1491: /*
1492:  * Ack a ZFIN packet, let byegones be byegones
1493:  */
1494: ackbibi()
1495: {
1496:     register n;
1497: 
1498:     vfile("ackbibi:");
1499:     Readnum = 1;
1500:     stohdr(0L);
1501:     for (n=3; --n>=0; ) {
1502:         purgeline();
1503:         zshhdr(4,ZFIN, Txhdr);
1504:         switch (readline(100)) {
1505:         case 'O':
1506:             readline(1);    /* Discard 2nd 'O' */
1507:             vfile("ackbibi complete");
1508:             return;
1509:         case RCDO:
1510:             return;
1511:         case TIMEOUT:
1512:         default:
1513:             break;
1514:         }
1515:     }
1516: }
1517: 
1518: 
1519: 
1520: /*
1521:  * Local console output simulation
1522:  */
1523: bttyout(c)
1524: {
1525:     if (Verbose || Fromcu)
1526:         putc(c, stderr);
1527: }
1528: 
1529: #ifndef vax11c
1530: /*
1531:  * Strip leading ! if present, do shell escape.
1532:  */
1533: sys2(s)
1534: register char *s;
1535: {
1536:     if (*s == '!')
1537:         ++s;
1538:     return system(s);
1539: }
1540: /*
1541:  * Strip leading ! if present, do exec.
1542:  */
1543: exec2(s)
1544: register char *s;
1545: {
1546:     if (*s == '!')
1547:         ++s;
1548:     mode(0);
1549:     execl("/bin/sh", "sh", "-c", s);
1550: }
1551: #endif
1552: /* End of rz.c */

Defined functions

IsAnyLower defined in line 1002; used 1 times
ackbibi defined in line 1494; used 2 times
alrm defined in line 247; used 1 times
bibi defined in line 253; used 7 times
bttyout defined in line 1523; used 2 times
canit defined in line 1048; used 7 times
checkpath defined in line 1105; used 2 times
chkinvok defined in line 1077; used 2 times
closeit defined in line 1463; used 3 times
exec2 defined in line 1543; used 1 times
flushmo defined in line 984; never used
getfree defined in line 182; used 1 times
main defined in line 263; never used
make_dirs defined in line 848; used 1 times
mkdir defined in line 892; used 1 times
procheader defined in line 734; used 3 times
purgeline defined in line 719; used 4 times
putsec defined in line 943; used 15 times
readline defined in line 672; used 12 times
report defined in line 1065; used 1 times
rzfile defined in line 1262; used 1 times
rzfiles defined in line 1233; used 1 times
sendline defined in line 974; used 10 times
substr defined in line 1015; used 4 times
sys2 defined in line 1533; used 1 times
tryz defined in line 1130; used 2 times
uncaps defined in line 992; used 1 times
usage defined in line 379; used 6 times
wcgetsec defined in line 571; used 2 times
wcreceive defined in line 418; used 1 times
wcrx defined in line 517; used 2 times
wcrxpn defined in line 483; used 1 times
zmputs defined in line 1443; used 4 times
zperr defined in line 1037; used 28 times

Defined variables

Batch defined in line 207; used 4 times
Baudrate defined in line 166; never used
Blklen defined in line 217; used 5 times
Bytesleft defined in line 201; used 8 times
Crcflg defined in line 188; used 6 times
Effbaud defined in line 167; never used
Eofseen defined in line 190; used 5 times
Filemode defined in line 203; used 8 times
Firstsec defined in line 189; used 6 times
Lastrx defined in line 187; used 4 times
Lleft defined in line 228; used 15 times
Lzmanag defined in line 230; used 4 times
MakeLCPathname defined in line 209; used 2 times
Modtime defined in line 202; used 8 times
Nflag defined in line 212; used 2 times
Nozmodem defined in line 165; used 3 times
Pathname defined in line 204; used 12 times
Progname defined in line 205; used 6 times
Quiet defined in line 211; used 3 times
Readnum defined in line 197; used 3 times
Restricted defined in line 192; used 3 times
Rxascii defined in line 215; used 2 times
Rxbinary defined in line 214; used 3 times
Rxclob defined in line 213; used 2 times
Thisbinary defined in line 216; used 7 times
Topipe defined in line 208; used 6 times
Verbose defined in line 210; used 20 times
Zctlesc defined in line 234; used 3 times
Zmodem defined in line 164; used 4 times
Zrwindow defined in line 235; used 1 times
chinseg defined in line 220; used 27 times
errors defined in line 191; used 6 times
linbuf defined in line 227; used 1 times
rbmsg defined in line 415; used 1 times
secbuf defined in line 223; used 27 times
timep defined in line 229; used 3 times
tohere defined in line 237; used 2 times
tryzhdrtype defined in line 245; used 6 times
zconv defined in line 231; used 3 times
zmanag defined in line 232; used 4 times
ztrans defined in line 233; used 1 times

Defined macros

ACK defined in line 151; used 5 times
BUFREAD defined in line 106; never used
CAN defined in line 145; used 3 times
CPMEOF defined in line 153; used 1 times
DEFBYTL defined in line 200; used 2 times
ENQ defined in line 144; never used
EOT defined in line 150; used 2 times
ERROR defined in line 132; used 39 times
ERRORMAX defined in line 158; never used
FALSE defined in line 130; used 10 times
GCOUNT defined in line 157; never used
HOWMANY defined in line 140; used 3 times
LOGFILE defined in line 119; used 2 times
NAK defined in line 152; used 4 times
OK defined in line 129; used 15 times
OS defined in line 105; used 2 times
PATHLEN defined in line 161; used 1 times
PROGNAME defined in line 111; used 2 times
PUBDIR defined in line 2; used 2 times
RCDO defined in line 156; never used
RETRYMAX defined in line 159; used 1 times
SOH defined in line 148; used 1 times
SS_NORMAL defined in line 118; used 2 times
STX defined in line 149; used 1 times
TERM_COREDUMP defined in line 887; never used
TERM_SIGNAL defined in line 886; used 1 times
TERM_VALUE defined in line 888; used 1 times
TIMEOUT defined in line 155; used 5 times
TRUE defined in line 131; used 16 times
UNIXFILE defined in line 162; used 2 times
VERSION defined in line 1; used 2 times
WANTCRC defined in line 154; used 3 times
WCEOT defined in line 160; used 4 times
XOFF defined in line 146; never used
XON defined in line 147; used 1 times
xsendline defined in line 239; never used
Last modified: 1992-06-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 12351
Valid CSS Valid XHTML 1.0 Strict