home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / rzsz_3_36_3_src.lzh / rz.c < prev    next >
C/C++ Source or Header  |  1996-01-09  |  34KB  |  1,583 lines

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