home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume12 / zmodem / part02 < prev    next >
Encoding:
Internet Message Format  |  1987-10-18  |  24.4 KB

  1. Subject:  v12i022:  Zmodem file transfer programs, Part02/03
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: omen!caf
  7. Posting-number: Volume 12, Issue 22
  8. Archive-name: zmodem/part02
  9.  
  10. Source code for Unix ZMODEM programs rz.c and sz.c and related files follows.
  11. ZMODEM is the ideal protocol for file transfer to and from Unix systems
  12. using a serial port. The source code has also been used for numerous ZMODEM
  13. versions, including the Opus bulletin board (Fido replacemet).  ZMODEM's
  14. pleasant user interface with automatic file and command download allows a
  15. Makefile to control a DOS machine running Pro-YAM, dor example.
  16.  
  17. #!/bin/sh
  18. # to extract, remove the header and type "sh filename"
  19. if `test ! -s ./README`
  20. then
  21. echo "Writing ./README"
  22. cat > ./README << '\Rogue\Monster\'
  23. RZSZ.ZOO is designed to be uploaded to a Unix or Xenix system by
  24. ZCOMM, Professional-YAM or Powercom using the supplied zupl.t script.
  25. Connect to your Unix/Xenix system, select an empty directory, and then
  26. give the YAM/ZCOMM/PowerCom command: "source zupl.t".  This will
  27. upload minirb.c, compile it, and then use minirb to upload the rz/sz
  28. files.  At this time you should study rz.c, sz.c, and rbsb.c to
  29. determine which compile time flags are necessary for your system.
  30.  
  31. Compile instructions are located in the comments at the beginning of
  32. the rz.c ans sz.c files.  The main compiler flags are -DV7 for V7 and
  33. BSD systems and -DSVR2 for sVr2.  Other #ifdefs in the files may be
  34. activated to deal with various types of kernel brain damage if you
  35. have a mutant system.
  36.  
  37. Naturally, rz ans sz work best with comm programs that seamlessly
  38. support ZMODEM command and file AutoDownload (PowerCOm, Pro-YAM and
  39. ZCOMM).  Ths DOS "DSZ" sub-program allows ZMODEM file transfers with
  40. older programs, but it must be called manually.  DSZ provides a "mini
  41. term function" that supports ZMODEM AutoDownload.  DSZ (DSZ.ZOO) and
  42. the ZMODEM protocol description (YZMODEM.ZOO) are on TeleGodzilla and
  43. other bulletin boards.  They may be obtained via UUCP from site
  44. "omen", for which a direct UUCP login and telephone number are
  45. provided below.  You may uucp ~uucp/FILES first to determine the
  46. pathnames for the "goodies".
  47.  
  48. Chuck Forsberg WA7KGX Author of Pro-YAM communications Tools for PCDOS and Unix
  49. ..!tektronix!reed!omen!caf  Omen Technology Inc "The High Reliability Software"
  50.   17505-V Northwest Sauvie Island Road Portland OR 97231  Voice: 503-621-3406
  51. TeleGodzilla BBS: 621-3746 2400/1200  CIS:70007,2304  Genie:CAF  Source:TCE022
  52.   omen Any ACU 1200 1-503-621-3746 se:--se: link ord: Giznoid in:--in: uucp
  53.   omen!/usr/spool/uucppublic/FILES lists all uucp-able files, updated hourly
  54. \Rogue\Monster\
  55. else
  56.   echo "will not over write ./README"
  57. fi
  58. if [ `wc -c ./README | awk '{printf $1}'` -ne 1873 ]
  59. then
  60. echo `wc -c ./README | awk '{print "Got " $1 ", Expected " 1873}'`
  61. fi
  62. if `test ! -s ./Makefile`
  63. then
  64. echo "Writing ./Makefile"
  65. cat > ./Makefile << '\Rogue\Monster\'
  66. # Makefile for Unix/Xenix rz and sz programs
  67. # the makefile is not too well tested yet
  68.  
  69. nothing:
  70.     @echo
  71.     @echo "Please study the #ifdef's in rbsb.c, rz.c and sz.c,"
  72.     @echo "then type 'make system' where system is one of:"
  73.     @echo "    sysv    SYSTEM 5 Unix"
  74.     @echo "    xenix    SYSTEM 3/5 Xenix"
  75.     @echo "    x386    386 Xenix"
  76.     @echo "    bsd    Berkeley 4.x BSD, and Ultrix"
  77.     @echo
  78.  
  79. usenet:
  80.     shar -f /tmp/rzsz README Makefile zmodem.h zm.c sz.c rz.c rbsb.c \
  81.       minirb.c *.1 gz ptest.sh zupl.t
  82.  
  83. shar:
  84.      shar -f /tmp/rzsz1et2 -m 1000000 README Makefile zmodem.h zm.c \
  85.         sz.c rz.c rbsb.c minirb.c *.1 gz ptest.sh zupl.t
  86.  
  87. arc:
  88.     rm -f /tmp/rzsz.arc
  89.     arc a /tmp/rzsz README Makefile zmodem.h zm.c sz.c rz.c \
  90.         rbsb.c *.1 gz ptest.sh zupl.t minirb.c
  91.     chmod og-w /tmp/rzsz.arc
  92.     ln /tmp/rzsz.arc /usr/spool/uucppublic
  93.     mv /tmp/rzsz.arc /t/yam
  94.  
  95. zoo:
  96.     rm -f /tmp/rzsz.zoo
  97.     zoo a /tmp/rzsz README Makefile zmodem.h zm.c sz.c rz.c \
  98.         rbsb.c *.1 gz ptest.sh zupl.t minirb.c
  99.     chmod og-w /tmp/rzsz.zoo
  100.     ln /tmp/rzsz.zoo /usr/spool/uucppublic
  101.     mv /tmp/rzsz.zoo /t/yam
  102.  
  103. .PRECIOUS:rz sz
  104.  
  105. xenix:
  106.     cc -M0 -Ox -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz
  107.     size sz
  108.     -ln sz sb
  109.     -ln sz sx
  110.     cc -M0 -Ox -K -i rz.c -o rz
  111.     size rz
  112.     -ln rz rb
  113.     -ln rz rx
  114.  
  115. x386:
  116.     cc -Ox rz.c -o rz
  117.     size rz
  118.     -ln rz rb
  119.     -ln rz rx
  120.     cc -Ox -DNFGVMIN -DREADCHECK sz.c -lx -o sz
  121.     size sz
  122.     -ln sz sb
  123.     -ln sz sx
  124.  
  125. sysv:
  126.     cc -O rz.c -o rz
  127.     size rz
  128.     -ln rz rb
  129.     -ln rz rx
  130.     cc -DSVR2 -O -DNFGVMIN sz.c -o sz
  131.     size sz
  132.     -ln sz sb
  133.     -ln sz sx
  134.  
  135. bsd:
  136.     cc -DV7 -O rz.c -o rz
  137.     size rz
  138.     -ln rz rb
  139.     -ln rz rx
  140.     cc -DV7 -O -DNFGVMIN sz.c -o sz
  141.     size sz
  142.     -ln sz sb
  143.     -ln sz sx
  144.  
  145. sz: nothing
  146. sb: nothing
  147. rz: nothing
  148. rb: nothing
  149. \Rogue\Monster\
  150. else
  151.   echo "will not over write ./Makefile"
  152. fi
  153. if [ `wc -c ./Makefile | awk '{printf $1}'` -ne 1640 ]
  154. then
  155. echo `wc -c ./Makefile | awk '{print "Got " $1 ", Expected " 1640}'`
  156. fi
  157. if `test ! -s ./zmodem.h`
  158. then
  159. echo "Writing ./zmodem.h"
  160. cat > ./zmodem.h << '\Rogue\Monster\'
  161. /*
  162.  *   Z M O D E M . H     Manifest constants for ZMODEM
  163.  *    application to application file transfer protocol
  164.  *    05-23-87  Chuck Forsberg Omen Technology Inc
  165.  */
  166. #define ZPAD '*'    /* 052 Padding character begins frames */
  167. #define ZDLE 030    /* Ctrl-X Zmodem escape - `ala BISYNC DLE */
  168. #define ZDLEE (ZDLE^0100)    /* Escaped ZDLE as transmitted */
  169. #define ZBIN 'A'    /* Binary frame indicator */
  170. #define ZHEX 'B'    /* HEX frame indicator */
  171. #define ZBIN32 'C'    /* Binary frame with 32 bit FCS */
  172.  
  173. /* Frame types (see array "frametypes" in zm.c) */
  174. #define ZRQINIT    0    /* Request receive init */
  175. #define ZRINIT    1    /* Receive init */
  176. #define ZSINIT 2    /* Send init sequence (optional) */
  177. #define ZACK 3        /* ACK to above */
  178. #define ZFILE 4        /* File name from sender */
  179. #define ZSKIP 5        /* To sender: skip this file */
  180. #define ZNAK 6        /* Last packet was garbled */
  181. #define ZABORT 7    /* Abort batch transfers */
  182. #define ZFIN 8        /* Finish session */
  183. #define ZRPOS 9        /* Resume data trans at this position */
  184. #define ZDATA 10    /* Data packet(s) follow */
  185. #define ZEOF 11        /* End of file */
  186. #define ZFERR 12    /* Fatal Read or Write error Detected */
  187. #define ZCRC 13        /* Request for file CRC and response */
  188. #define ZCHALLENGE 14    /* Receiver's Challenge */
  189. #define ZCOMPL 15    /* Request is complete */
  190. #define ZCAN 16        /* Other end canned session with CAN*5 */
  191. #define ZFREECNT 17    /* Request for free bytes on filesystem */
  192. #define ZCOMMAND 18    /* Command from sending program */
  193. #define ZSTDERR 19    /* Output to standard error, data follows */
  194.  
  195. /* ZDLE sequences */
  196. #define ZCRCE 'h'    /* CRC next, frame ends, header packet follows */
  197. #define ZCRCG 'i'    /* CRC next, frame continues nonstop */
  198. #define ZCRCQ 'j'    /* CRC next, frame continues, ZACK expected */
  199. #define ZCRCW 'k'    /* CRC next, ZACK expected, end of frame */
  200. #define ZRUB0 'l'    /* Translate to rubout 0177 */
  201. #define ZRUB1 'm'    /* Translate to rubout 0377 */
  202.  
  203. /* zdlread return values (internal) */
  204. /* -1 is general error, -2 is timeout */
  205. #define GOTOR 0400
  206. #define GOTCRCE (ZCRCE|GOTOR)    /* ZDLE-ZCRCE received */
  207. #define GOTCRCG (ZCRCG|GOTOR)    /* ZDLE-ZCRCG received */
  208. #define GOTCRCQ (ZCRCQ|GOTOR)    /* ZDLE-ZCRCQ received */
  209. #define GOTCRCW (ZCRCW|GOTOR)    /* ZDLE-ZCRCW received */
  210. #define GOTCAN    (GOTOR|030)    /* CAN*5 seen */
  211.  
  212. /* Byte positions within header array */
  213. #define ZF0    3    /* First flags byte */
  214. #define ZF1    2
  215. #define ZF2    1
  216. #define ZF3    0
  217. #define ZP0    0    /* Low order 8 bits of position */
  218. #define ZP1    1
  219. #define ZP2    2
  220. #define ZP3    3    /* High order 8 bits of file position */
  221.  
  222. /* Bit Masks for ZRINIT flags byte ZF0 */
  223. #define CANFDX    01    /* Rx can send and receive true FDX */
  224. #define CANOVIO    02    /* Rx can receive data during disk I/O */
  225. #define CANBRK    04    /* Rx can send a break signal */
  226. #define CANCRY    010    /* Receiver can decrypt */
  227. #define CANLZW    020    /* Receiver can uncompress */
  228. #define CANFC32    040    /* Receiver can use 32 bit Frame Check */
  229. #define ESCCTL 0100    /* Receiver expects ctl chars to be escaped */
  230. #define ESC8   0200    /* Receiver expects 8th bit to be escaped */
  231.  
  232. /* Parameters for ZSINIT frame */
  233. #define ZATTNLEN 32    /* Max length of attention string */
  234. /* Bit Masks for ZSINIT flags byte ZF0 */
  235. #define TESCCTL 0100    /* Transmitter expects ctl chars to be escaped */
  236. #define TESC8   0200    /* Transmitter expects 8th bit to be escaped */
  237.  
  238. /* Parameters for ZFILE frame */
  239. /* Conversion options one of these in ZF0 */
  240. #define ZCBIN    1    /* Binary transfer - inhibit conversion */
  241. #define ZCNL    2    /* Convert NL to local end of line convention */
  242. #define ZCRESUM    3    /* Resume interrupted file transfer */
  243. /* Management include options, one of these ored in ZF1 */
  244. #define ZMSKNOLOC    0200    /* Skip file if not present at rx */
  245. /* Management options, one of these ored in ZF1 */
  246. #define ZMMASK    037    /* Mask for the choices below */
  247. #define ZMNEWL    1    /* Transfer if source newer or longer */
  248. #define ZMCRC    2    /* Transfer if different file CRC or length */
  249. #define ZMAPND    3    /* Append contents to existing file (if any) */
  250. #define ZMCLOB    4    /* Replace existing file */
  251. #define ZMNEW    5    /* Transfer if source newer */
  252.     /* Number 5 is alive ... */
  253. #define ZMDIFF    6    /* Transfer if dates or lengths different */
  254. #define ZMPROT    7    /* Protect destination file */
  255. /* Transport options, one of these in ZF2 */
  256. #define ZTLZW    1    /* Lempel-Ziv compression */
  257. #define ZTCRYPT    2    /* Encryption */
  258. #define ZTRLE    3    /* Run Length encoding */
  259. /* Extended options for ZF3, bit encoded */
  260. #define ZXSPARS    64    /* Encoding for sparse file operations */
  261.  
  262. /* Parameters for ZCOMMAND frame ZF0 (otherwise 0) */
  263. #define ZCACK1    1    /* Acknowledge, then do command */
  264.  
  265. long rclhdr();
  266.  
  267. /* Globals used by ZMODEM functions */
  268. extern Rxframeind;    /* ZBIN ZBIN32, or ZHEX type of frame received */
  269. extern Rxtype;        /* Type of header received */
  270. extern Rxcount;        /* Count of data bytes received */
  271. extern Zrwindow;    /* RX window size (controls garbage count) */
  272. extern Rxtimeout;    /* Tenths of seconds to wait for something */
  273. extern char Rxhdr[4];    /* Received header */
  274. extern char Txhdr[4];    /* Transmitted header */
  275. extern long Rxpos;    /* Received file position */
  276. extern long Txpos;    /* Transmitted file position */
  277. extern Txfcs32;        /* TURE means send binary frames with 32 bit FCS */
  278. extern Crc32t;        /* Display flag indicating 32 bit CRC being sent */
  279. extern Crc32;        /* Display flag indicating 32 bit CRC being received */
  280. extern Znulls;        /* Number of nulls to send at beginning of ZDATA hdr */
  281. extern char Attn[ZATTNLEN+1];    /* Attention string rx sends to tx on err */
  282.  
  283. /* End of ZMODEM.H */
  284. \Rogue\Monster\
  285. else
  286.   echo "will not over write ./zmodem.h"
  287. fi
  288. if [ `wc -c ./zmodem.h | awk '{printf $1}'` -ne 5487 ]
  289. then
  290. echo `wc -c ./zmodem.h | awk '{print "Got " $1 ", Expected " 5487}'`
  291. fi
  292. if `test ! -s ./zm.c`
  293. then
  294. echo "Writing ./zm.c"
  295. cat > ./zm.c << '\Rogue\Monster\'
  296. /*
  297.  *   Z M . C
  298.  *    ZMODEM protocol primitives
  299.  *    07-28-87  Chuck Forsberg Omen Technology Inc
  300.  *
  301.  * Entry point Functions:
  302.  *    zsbhdr(type, hdr) send binary header
  303.  *    zshhdr(type, hdr) send hex header
  304.  *    zgethdr(hdr, eflag) receive header - binary or hex
  305.  *    zsdata(buf, len, frameend) send data
  306.  *    zrdata(buf, len) receive data
  307.  *    stohdr(pos) store position data in Txhdr
  308.  *    long rclhdr(hdr) recover position offset from header
  309.  */
  310.  
  311. #ifndef CANFDX
  312. #include "zmodem.h"
  313. int Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  314. #endif
  315.  
  316. #ifndef UNSL
  317. #define UNSL
  318. #endif
  319.  
  320.  
  321. /* Globals used by ZMODEM functions */
  322. int Rxframeind;        /* ZBIN ZBIN32, or ZHEX type of frame received */
  323. int Rxtype;        /* Type of header received */
  324. int Rxcount;        /* Count of data bytes received */
  325. char Rxhdr[4];        /* Received header */
  326. char Txhdr[4];        /* Transmitted header */
  327. long Rxpos;        /* Received file position */
  328. long Txpos;        /* Transmitted file position */
  329. int Txfcs32;        /* TURE means send binary frames with 32 bit FCS */
  330. int Crc32t;        /* Display flag indicating 32 bit CRC being sent */
  331. int Crc32;        /* Display flag indicating 32 bit CRC being received */
  332. int Znulls;        /* Number of nulls to send at beginning of ZDATA hdr */
  333. char Attn[ZATTNLEN+1];    /* Attention string rx sends to tx on err */
  334.  
  335.  
  336. static char *frametypes[] = {
  337.     "Carrier Lost",        /* -3 */
  338.     "TIMEOUT",        /* -2 */
  339.     "ERROR",        /* -1 */
  340. #define FTOFFSET 3
  341.     "ZRQINIT",
  342.     "ZRINIT",
  343.     "ZSINIT",
  344.     "ZACK",
  345.     "ZFILE",
  346.     "ZSKIP",
  347.     "ZNAK",
  348.     "ZABORT",
  349.     "ZFIN",
  350.     "ZRPOS",
  351.     "ZDATA",
  352.     "ZEOF",
  353.     "ZFERR",
  354.     "ZCRC",
  355.     "ZCHALLENGE",
  356.     "ZCOMPL",
  357.     "ZCAN",
  358.     "ZFREECNT",
  359.     "ZCOMMAND",
  360.     "ZSTDERR",
  361.     "xxxxx"
  362. #define FRTYPES 22    /* Total number of frame types in this array */
  363.             /*  not including psuedo negative entries */
  364. };
  365.  
  366. /* Send ZMODEM binary header hdr of type type */
  367. zsbhdr(type, hdr)
  368. register char *hdr;
  369. {
  370.     register n;
  371.     register unsigned short crc;
  372.  
  373.     vfile("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
  374.     if (type == ZDATA)
  375.         for (n = Znulls; --n >=0; )
  376.             zsendline(0);
  377.  
  378.     xsendline(ZPAD); xsendline(ZDLE);
  379.  
  380.     if (Crc32t=Txfcs32)
  381.         zsbh32(hdr, type);
  382.     else {
  383.         xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
  384.  
  385.         for (n=4; --n >= 0; ++hdr) {
  386.             zsendline(*hdr);
  387.             crc = updcrc((0377& *hdr), crc);
  388.         }
  389.         crc = updcrc(0,updcrc(0,crc));
  390.         zsendline(crc>>8);
  391.         zsendline(crc);
  392.     }
  393.     if (type != ZDATA)
  394.         flushmo();
  395. }
  396.  
  397.  
  398. /* Send ZMODEM binary header hdr of type type */
  399. zsbh32(hdr, type)
  400. register char *hdr;
  401. {
  402.     register n;
  403.     register UNSL long crc;
  404.  
  405.     xsendline(ZBIN32);  zsendline(type);
  406.     crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
  407.  
  408.     for (n=4; --n >= 0; ++hdr) {
  409.         crc = UPDC32((0377 & *hdr), crc);
  410.         zsendline(*hdr);
  411.     }
  412.     crc = ~crc;
  413.     for (n=4; --n >= 0;) {
  414.         zsendline((int)crc);
  415.         crc >>= 8;
  416.     }
  417. }
  418.  
  419. /* Send ZMODEM HEX header hdr of type type */
  420. zshhdr(type, hdr)
  421. register char *hdr;
  422. {
  423.     register n;
  424.     register unsigned short crc;
  425.  
  426.     vfile("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
  427.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
  428.     zputhex(type);
  429.     Crc32t = 0;
  430.  
  431.     crc = updcrc(type, 0);
  432.     for (n=4; --n >= 0; ++hdr) {
  433.         zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
  434.     }
  435.     crc = updcrc(0,updcrc(0,crc));
  436.     zputhex(crc>>8); zputhex(crc);
  437.  
  438.     /* Make it printable on remote machine */
  439.     sendline(015); sendline(012);
  440.     /*
  441.      * Uncork the remote in case a fake XOFF has stopped data flow
  442.      */
  443.     if (type != ZFIN && type != ZACK)
  444.         sendline(021);
  445.     flushmo();
  446. }
  447.  
  448. /*
  449.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  450.  */
  451. zsdata(buf, length, frameend)
  452. register char *buf;
  453. {
  454.     register unsigned short crc;
  455.  
  456.     vfile("zsdata: length=%d end=%x", length, frameend);
  457.     if (Crc32t)
  458.         zsda32(buf, length, frameend);
  459.     else {
  460.         crc = 0;
  461.         for (;--length >= 0; ++buf) {
  462.             zsendline(*buf); crc = updcrc((0377 & *buf), crc);
  463.         }
  464.         xsendline(ZDLE); xsendline(frameend);
  465.         crc = updcrc(frameend, crc);
  466.  
  467.         crc = updcrc(0,updcrc(0,crc));
  468.         zsendline(crc>>8); zsendline(crc);
  469.     }
  470.     if (frameend == ZCRCW) {
  471.         xsendline(XON);  flushmo();
  472.     }
  473. }
  474.  
  475. zsda32(buf, length, frameend)
  476. register char *buf;
  477. {
  478.     register UNSL long crc;
  479.  
  480.     crc = 0xFFFFFFFFL;
  481.     for (;--length >= 0;++buf) {
  482.         crc = UPDC32((0377 & *buf), crc);
  483.         zsendline(*buf);
  484.     }
  485.     xsendline(ZDLE); xsendline(frameend);
  486.     crc = UPDC32(frameend, crc);
  487.  
  488.     crc = ~crc;
  489.     for (length=4; --length >= 0;) {
  490.         zsendline((int)crc);  crc >>= 8;
  491.     }
  492. }
  493.  
  494. /*
  495.  * Receive array buf of max length with ending ZDLE sequence
  496.  *  and CRC.  Returns the ending character or error code.
  497.  *  NB: On errors may store length+1 bytes!
  498.  */
  499. zrdata(buf, length)
  500. register char *buf;
  501. {
  502.     register c;
  503.     register unsigned short crc;
  504.     register char *end;
  505.     register d;
  506.  
  507.     if (Rxframeind == ZBIN32)
  508.         return zrdat32(buf, length);
  509.  
  510.     crc = Rxcount = 0;  end = buf + length;
  511.     while (buf <= end) {
  512.         if ((c = zdlread()) & ~0377) {
  513. crcfoo:
  514.             switch (c) {
  515.             case GOTCRCE:
  516.             case GOTCRCG:
  517.             case GOTCRCQ:
  518.             case GOTCRCW:
  519.                 crc = updcrc((d=c)&0377, crc);
  520.                 if ((c = zdlread()) & ~0377)
  521.                     goto crcfoo;
  522.                 crc = updcrc(c, crc);
  523.                 if ((c = zdlread()) & ~0377)
  524.                     goto crcfoo;
  525.                 crc = updcrc(c, crc);
  526.                 if (crc & 0xFFFF) {
  527.                     zperr("Bad data CRC");
  528.                     return ERROR;
  529.                 }
  530.                 Rxcount = length - (end - buf);
  531.                 vfile("zrdata: cnt = %d ret = %x", Rxcount, d);
  532.                 return d;
  533.             case GOTCAN:
  534.                 zperr("Sender Canceled");
  535.                 return ZCAN;
  536.             case TIMEOUT:
  537.                 zperr("TIMEOUT");
  538.                 return c;
  539.             default:
  540.                 zperr("Bad data subpacket");
  541.                 return c;
  542.             }
  543.         }
  544.         *buf++ = c;
  545.         crc = updcrc(c, crc);
  546.     }
  547.     zperr("Data subpacket too long");
  548.     return ERROR;
  549. }
  550.  
  551. zrdat32(buf, length)
  552. register char *buf;
  553. {
  554.     register c;
  555.     register UNSL long crc;
  556.     register char *end;
  557.     register d;
  558.  
  559.     crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
  560.     while (buf <= end) {
  561.         if ((c = zdlread()) & ~0377) {
  562. crcfoo:
  563.             switch (c) {
  564.             case GOTCRCE:
  565.             case GOTCRCG:
  566.             case GOTCRCQ:
  567.             case GOTCRCW:
  568.                 d = c;  c &= 0377;
  569.                 crc = UPDC32(c, crc);
  570.                 if ((c = zdlread()) & ~0377)
  571.                     goto crcfoo;
  572.                 crc = UPDC32(c, crc);
  573.                 if ((c = zdlread()) & ~0377)
  574.                     goto crcfoo;
  575.                 crc = UPDC32(c, crc);
  576.                 if ((c = zdlread()) & ~0377)
  577.                     goto crcfoo;
  578.                 crc = UPDC32(c, crc);
  579.                 if ((c = zdlread()) & ~0377)
  580.                     goto crcfoo;
  581.                 crc = UPDC32(c, crc);
  582.                 if (crc != 0xDEBB20E3) {
  583.                     zperr("Bad data CRC");
  584.                     return ERROR;
  585.                 }
  586.                 Rxcount = length - (end - buf);
  587.                 vfile("zrdat32: cnt = %d ret = %x", Rxcount, d);
  588.                 return d;
  589.             case GOTCAN:
  590.                 zperr("Sender Canceled");
  591.                 return ZCAN;
  592.             case TIMEOUT:
  593.                 zperr("TIMEOUT");
  594.                 return c;
  595.             default:
  596.                 zperr("Bad data subpacket");
  597.                 return c;
  598.             }
  599.         }
  600.         *buf++ = c;
  601.         crc = UPDC32(c, crc);
  602.     }
  603.     zperr("Data subpacket too long");
  604.     return ERROR;
  605. }
  606.  
  607.  
  608. /*
  609.  * Read a ZMODEM header to hdr, either binary or hex.
  610.  *  eflag controls local display of non zmodem characters:
  611.  *    0:  no display
  612.  *    1:  display printing characters only
  613.  *    2:  display all non ZMODEM characters
  614.  *  On success, set Zmodem to 1, set Rxpos and return type of header.
  615.  *   Otherwise return negative on error.
  616.  *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
  617.  */
  618. zgethdr(hdr, eflag)
  619. char *hdr;
  620. {
  621.     register c, n, cancount;
  622.  
  623.     n = Zrwindow + Baudrate;    /* Max bytes before start of frame */
  624.     Rxframeind = Rxtype = 0;
  625.  
  626. startover:
  627.     cancount = 5;
  628. again:
  629.     /* Return immediate ERROR if ZCRCW sequence seen */
  630.     switch (c = readline(Rxtimeout)) {
  631.     case RCDO:
  632.     case TIMEOUT:
  633.         goto fifi;
  634.     case CAN:
  635. gotcan:
  636.         if (--cancount <= 0) {
  637.             c = ZCAN; goto fifi;
  638.         }
  639.         switch (c = readline(1)) {
  640.         case TIMEOUT:
  641.             goto again;
  642.         case ZCRCW:
  643.             c = ERROR;
  644.         /* **** FALL THRU TO **** */
  645.         case RCDO:
  646.             goto fifi;
  647.         default:
  648.             break;
  649.         case CAN:
  650.             if (--cancount <= 0) {
  651.                 c = ZCAN; goto fifi;
  652.             }
  653.             goto again;
  654.         }
  655.     /* **** FALL THRU TO **** */
  656.     default:
  657. agn2:
  658.         if ( --n == 0) {
  659.             zperr("Garbage count exceeded");
  660.             return(ERROR);
  661.         }
  662.         if (eflag && ((c &= 0177) & 0140))
  663.             bttyout(c);
  664.         else if (eflag > 1)
  665.             bttyout(c);
  666.         goto startover;
  667.     case ZPAD|0200:        /* This is what we want. */
  668.     case ZPAD:        /* This is what we want. */
  669.         break;
  670.     }
  671.     cancount = 5;
  672. splat:
  673.     switch (c = noxrd7()) {
  674.     case ZPAD:
  675.         goto splat;
  676.     case RCDO:
  677.     case TIMEOUT:
  678.         goto fifi;
  679.     default:
  680.         goto agn2;
  681.     case ZDLE:        /* This is what we want. */
  682.         break;
  683.     }
  684.  
  685.     switch (c = noxrd7()) {
  686.     case RCDO:
  687.     case TIMEOUT:
  688.         goto fifi;
  689.     case ZBIN:
  690.         Rxframeind = ZBIN;  Crc32 = FALSE;
  691.         c =  zrbhdr(hdr);
  692.         break;
  693.     case ZBIN32:
  694.         Crc32 = Rxframeind = ZBIN32;
  695.         c =  zrbhdr32(hdr);
  696.         break;
  697.     case ZHEX:
  698.         Rxframeind = ZHEX;  Crc32 = FALSE;
  699.         c =  zrhhdr(hdr);
  700.         break;
  701.     case CAN:
  702.         goto gotcan;
  703.     default:
  704.         goto agn2;
  705.     }
  706.     Rxpos = hdr[ZP3] & 0377;
  707.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  708.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  709.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  710. fifi:
  711.     switch (c) {
  712.     case GOTCAN:
  713.         c = ZCAN;
  714.     /* **** FALL THRU TO **** */
  715.     case ZNAK:
  716.     case ZCAN:
  717.     case ERROR:
  718.     case TIMEOUT:
  719.     case RCDO:
  720.         zperr("Got %s", frametypes[c+FTOFFSET]);
  721.     /* **** FALL THRU TO **** */
  722.     default:
  723.         if (c >= -3 && c <= FRTYPES)
  724.             vfile("zgethdr: %s %lx", frametypes[c+FTOFFSET], Rxpos);
  725.         else
  726.             vfile("zgethdr: %d %lx", c, Rxpos);
  727.     }
  728.     return c;
  729. }
  730.  
  731. /* Receive a binary style header (type and position) */
  732. zrbhdr(hdr)
  733. register char *hdr;
  734. {
  735.     register c, n;
  736.     register unsigned short crc;
  737.  
  738.     if ((c = zdlread()) & ~0377)
  739.         return c;
  740.     Rxtype = c;
  741.     crc = updcrc(c, 0);
  742.  
  743.     for (n=4; --n >= 0; ++hdr) {
  744.         if ((c = zdlread()) & ~0377)
  745.             return c;
  746.         crc = updcrc(c, crc);
  747.         *hdr = c;
  748.     }
  749.     if ((c = zdlread()) & ~0377)
  750.         return c;
  751.     crc = updcrc(c, crc);
  752.     if ((c = zdlread()) & ~0377)
  753.         return c;
  754.     crc = updcrc(c, crc);
  755.     if (crc & 0xFFFF) {
  756.         zperr("Bad Header CRC"); return ERROR;
  757.     }
  758.     Zmodem = 1;
  759.     return Rxtype;
  760. }
  761.  
  762. /* Receive a binary style header (type and position) with 32 bit FCS */
  763. zrbhdr32(hdr)
  764. register char *hdr;
  765. {
  766.     register c, n;
  767.     register UNSL long crc;
  768.  
  769.     if ((c = zdlread()) & ~0377)
  770.         return c;
  771.     Rxtype = c;
  772.     crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
  773. #ifdef DEBUGZ
  774.     vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
  775. #endif
  776.  
  777.     for (n=4; --n >= 0; ++hdr) {
  778.         if ((c = zdlread()) & ~0377)
  779.             return c;
  780.         crc = UPDC32(c, crc);
  781.         *hdr = c;
  782. #ifdef DEBUGZ
  783.         vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
  784. #endif
  785.     }
  786.     for (n=4; --n >= 0;) {
  787.         if ((c = zdlread()) & ~0377)
  788.             return c;
  789.         crc = UPDC32(c, crc);
  790. #ifdef DEBUGZ
  791.         vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
  792. #endif
  793.     }
  794.     if (crc != 0xDEBB20E3) {
  795.         zperr("Bad Header CRC"); return ERROR;
  796.     }
  797.     Zmodem = 1;
  798.     return Rxtype;
  799. }
  800.  
  801.  
  802. /* Receive a hex style header (type and position) */
  803. zrhhdr(hdr)
  804. char *hdr;
  805. {
  806.     register c;
  807.     register unsigned short crc;
  808.     register n;
  809.  
  810.     if ((c = zgethex()) < 0)
  811.         return c;
  812.     Rxtype = c;
  813.     crc = updcrc(c, 0);
  814.  
  815.     for (n=4; --n >= 0; ++hdr) {
  816.         if ((c = zgethex()) < 0)
  817.             return c;
  818.         crc = updcrc(c, crc);
  819.         *hdr = c;
  820.     }
  821.     if ((c = zgethex()) < 0)
  822.         return c;
  823.     crc = updcrc(c, crc);
  824.     if ((c = zgethex()) < 0)
  825.         return c;
  826.     crc = updcrc(c, crc);
  827.     if (crc & 0xFFFF) {
  828.         zperr("Bad Header CRC"); return ERROR;
  829.     }
  830.     if (readline(1) == '\r')    /* Throw away possible cr/lf */
  831.         readline(1);
  832.     Zmodem = 1; return Rxtype;
  833. }
  834.  
  835. /* Send a byte as two hex digits */
  836. zputhex(c)
  837. register c;
  838. {
  839.     static char    digits[]    = "0123456789abcdef";
  840.  
  841.     if (Verbose>8)
  842.         vfile("zputhex: %02X", c);
  843.     sendline(digits[(c&0xF0)>>4]);
  844.     sendline(digits[(c)&0xF]);
  845. }
  846.  
  847. /*
  848.  * Send character c with ZMODEM escape sequence encoding.
  849.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  850.  */
  851. zsendline(c)
  852. register c;
  853. {
  854.     static lastsent;
  855.  
  856.     switch (c &= 0377) {
  857.     case ZDLE:
  858.         xsendline(ZDLE);
  859.         xsendline (lastsent = (c ^= 0100));
  860.         break;
  861.     case 015:
  862.     case 0215:
  863.         if (!Zctlesc && (lastsent & 0177) != '@')
  864.             goto sendit;
  865.     /* **** FALL THRU TO **** */
  866.     case 020:
  867.     case 021:
  868.     case 023:
  869.     case 0220:
  870.     case 0221:
  871.     case 0223:
  872.         xsendline(ZDLE);
  873.         c ^= 0100;
  874. sendit:
  875.         xsendline(lastsent = c);
  876.         break;
  877.     default:
  878.         if (Zctlesc && ! (c & 0140)) {
  879.             xsendline(ZDLE);
  880.             c ^= 0100;
  881.         }
  882.         xsendline(lastsent = c);
  883.     }
  884. }
  885.  
  886. /* Decode two lower case hex digits into an 8 bit byte value */
  887. zgethex()
  888. {
  889.     register c;
  890.  
  891.     c = zgeth1();
  892.     if (Verbose>8)
  893.         vfile("zgethex: %02X", c);
  894.     return c;
  895. }
  896. zgeth1()
  897. {
  898.     register c, n;
  899.  
  900.     if ((c = noxrd7()) < 0)
  901.         return c;
  902.     n = c - '0';
  903.     if (n > 9)
  904.         n -= ('a' - ':');
  905.     if (n & ~0xF)
  906.         return ERROR;
  907.     if ((c = noxrd7()) < 0)
  908.         return c;
  909.     c -= '0';
  910.     if (c > 9)
  911.         c -= ('a' - ':');
  912.     if (c & ~0xF)
  913.         return ERROR;
  914.     c += (n<<4);
  915.     return c;
  916. }
  917.  
  918. /*
  919.  * Read a byte, checking for ZMODEM escape encoding
  920.  *  including CAN*5 which represents a quick abort
  921.  */
  922. zdlread()
  923. {
  924.     register c;
  925.  
  926. again:
  927.     switch (c = readline(Rxtimeout)) {
  928.     case ZDLE:
  929.         break;
  930.     case 023:
  931.     case 0223:
  932.     case 021:
  933.     case 0221:
  934.         goto again;
  935.     default:
  936.         if (Zctlesc && !(c & 0140)) {
  937.             goto again;
  938.         }
  939.         return c;
  940.     }
  941. again2:
  942.     if ((c = readline(Rxtimeout)) < 0)
  943.         return c;
  944.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  945.         return c;
  946.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  947.         return c;
  948.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  949.         return c;
  950.     switch (c) {
  951.     case CAN:
  952.         return GOTCAN;
  953.     case ZCRCE:
  954.     case ZCRCG:
  955.     case ZCRCQ:
  956.     case ZCRCW:
  957.         return (c | GOTOR);
  958.     case ZRUB0:
  959.         return 0177;
  960.     case ZRUB1:
  961.         return 0377;
  962.     case 023:
  963.     case 0223:
  964.     case 021:
  965.     case 0221:
  966.         goto again2;
  967.     default:
  968.         if (Zctlesc && ! (c & 0140)) {
  969.             goto again2;
  970.         }
  971.         if ((c & 0140) ==  0100)
  972.             return (c ^ 0100);
  973.         break;
  974.     }
  975.     zperr("Bad escape sequence %x", c);
  976.     return ERROR;
  977. }
  978.  
  979. /*
  980.  * Read a character from the modem line with timeout.
  981.  *  Eat parity, XON and XOFF characters.
  982.  */
  983. noxrd7()
  984. {
  985.     register c;
  986.  
  987.     for (;;) {
  988.         if ((c = readline(Rxtimeout)) < 0)
  989.             return c;
  990.         switch (c &= 0177) {
  991.         case XON:
  992.         case XOFF:
  993.             continue;
  994.         default:
  995.             if (Zctlesc && !(c & 0140))
  996.                 continue;
  997.         case '\r':
  998.         case '\n':
  999.         case ZDLE:
  1000.             return c;
  1001.         }
  1002.     }
  1003. }
  1004.  
  1005. /* Store long integer pos in Txhdr */
  1006. stohdr(pos)
  1007. long pos;
  1008. {
  1009.     Txhdr[ZP0] = pos;
  1010.     Txhdr[ZP1] = pos>>8;
  1011.     Txhdr[ZP2] = pos>>16;
  1012.     Txhdr[ZP3] = pos>>24;
  1013. }
  1014.  
  1015. /* Recover a long integer from a header */
  1016. long
  1017. rclhdr(hdr)
  1018. register char *hdr;
  1019. {
  1020.     register long l;
  1021.  
  1022.     l = (hdr[ZP3] & 0377);
  1023.     l = (l << 8) | (hdr[ZP2] & 0377);
  1024.     l = (l << 8) | (hdr[ZP1] & 0377);
  1025.     l = (l << 8) | (hdr[ZP0] & 0377);
  1026.     return l;
  1027. }
  1028.  
  1029. /* End of zm.c */
  1030. \Rogue\Monster\
  1031. else
  1032.   echo "will not over write ./zm.c"
  1033. fi
  1034. if [ `wc -c ./zm.c | awk '{printf $1}'` -ne 14087 ]
  1035. then
  1036. echo `wc -c ./zm.c | awk '{print "Got " $1 ", Expected " 14087}'`
  1037. fi
  1038. echo "Finished archive 3 of 3"
  1039. exit
  1040.  
  1041.