home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / rzsz_3_24_src.lzh / rz.c < prev    next >
C/C++ Source or Header  |  1993-11-04  |  32KB  |  1,537 lines

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