ZM.C 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /*
  2. * Z M . C
  3. * ZMODEM protocol primitives
  4. * 5-18-86 Chuck Forsberg Omen Technology Inc
  5. *
  6. * Entry point Functions:
  7. * zsbhdr(type, hdr) send binary header
  8. * zshhdr(type, hdr) send hex header
  9. * zgethdr(hdr, eflag) receive header - binary or hex
  10. * zsbdata(buf, len, frameend) send binary data
  11. * zrbdata(buf, len) receive binary data
  12. * stohdr(pos) store position data in Txhdr
  13. * long rclhdr(hdr) recover position offset from header
  14. */
  15. //#ifndef CANFDX
  16. #include "zmodem.h"
  17. int Rxtimeout = 100; /* Tenths of seconds to wait for something */
  18. //#endif
  19. #define ERROR (-1)
  20. static char *frametypes[] = {
  21. "TIMEOUT",
  22. "ERROR",
  23. "ZRQINIT",
  24. "ZRINIT",
  25. "ZSINIT",
  26. "ZACK",
  27. "ZFILE",
  28. "ZSKIP",
  29. "ZNAK",
  30. "ZABORT",
  31. "ZFIN",
  32. "ZRPOS",
  33. "ZDATA",
  34. "ZEOF",
  35. "ZFERR",
  36. "ZCRC",
  37. "ZCHALLENGE",
  38. "ZCOMPL",
  39. "ZCAN",
  40. "ZFREECNT",
  41. "ZCOMMAND",
  42. "ZCACK"
  43. #define FRTYPES 21 /* Total number of frame types in this array */
  44. };
  45. long int rclhdr(char *hdr);
  46. int zputhex(int c);
  47. int zsendline(int c);
  48. int zgethex(void);
  49. int zgeth1(void);
  50. int zrbhdr(char *hdr);
  51. int zrhhdr(char *hdr);
  52. int zdlread(void);
  53. int noxread7(void);
  54. /* Send ZMODEM binary header hdr of type type */
  55. int zsbhdr(int type, char *hdr)
  56. {
  57. int n;
  58. unsigned short oldcrc;
  59. vfile("zsbhdr: %s %lx", frametypes[type+2], rclhdr(hdr));
  60. xsendline(ZPAD); xsendline(ZDLE); xsendline(ZBIN);
  61. zsendline(type); oldcrc = updcrc(type, 0);
  62. for (n=4; --n >= 0;) {
  63. zsendline(*hdr);
  64. oldcrc = updcrc(*hdr++, oldcrc);
  65. }
  66. oldcrc = updcrc(0,updcrc(0,oldcrc));
  67. zsendline(oldcrc>>8);
  68. zsendline(oldcrc);
  69. if (type != ZDATA)
  70. flushmo();
  71. return 0;
  72. }
  73. /* Send ZMODEM HEX header hdr of type type */
  74. int zshhdr(int type, char *hdr)
  75. {
  76. int n;
  77. unsigned short oldcrc;
  78. vfile("zshhdr: %s %lx", frametypes[type+2], rclhdr(hdr));
  79. sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
  80. zputhex(type);
  81. oldcrc = updcrc(type, 0);
  82. for (n=4; --n >= 0;) {
  83. zputhex(*hdr); oldcrc = updcrc(*hdr++, oldcrc);
  84. }
  85. oldcrc = updcrc(0,updcrc(0,oldcrc));
  86. zputhex(oldcrc>>8); zputhex(oldcrc);
  87. /* Make it printable on remote machine */
  88. sendline(015); sendline(0212); /*012*/
  89. /*
  90. * Uncork the remote in case a fake XOFF has stopped data flow
  91. */
  92. if (type != ZFIN)
  93. sendline(021);
  94. flushmo();
  95. return 0;
  96. }
  97. /*
  98. * Send binary array buf of length length, with ending ZDLE sequence frameend
  99. */
  100. int zsbdata(char *buf, int length, int frameend)
  101. {
  102. register unsigned short oldcrc;
  103. vfile("zsbdata: length=%d end=%x", length, frameend);
  104. oldcrc = 0;
  105. for (;--length >= 0;) {
  106. zsendline(*buf);
  107. oldcrc = updcrc(*buf++, oldcrc);
  108. }
  109. xsendline(ZDLE); xsendline(frameend);
  110. oldcrc = updcrc(frameend, oldcrc);
  111. oldcrc = updcrc(0,updcrc(0,oldcrc));
  112. zsendline(oldcrc>>8);
  113. zsendline(oldcrc);
  114. if (frameend == ZCRCW)
  115. flushmo();
  116. return 0;
  117. }
  118. /*
  119. * Receive binary array buf of max length with ending ZDLE sequence
  120. * and CRC. Returns the ending character or error code.
  121. */
  122. int zrbdata(char *buf, int length)
  123. {
  124. int c;
  125. unsigned short oldcrc;
  126. int d;
  127. oldcrc = Rxcount = 0;
  128. for (;;) {
  129. if ((c = zdlread()) & ~0377) {
  130. switch (c) {
  131. case GOTCRCE:
  132. case GOTCRCG:
  133. case GOTCRCQ:
  134. case GOTCRCW:
  135. oldcrc = updcrc((d=c)&0377, oldcrc);
  136. if ((c = zdlread()) & ~0377)
  137. goto badcrc;
  138. oldcrc = updcrc(c, oldcrc);
  139. if ((c = zdlread()) & ~0377)
  140. goto badcrc;
  141. oldcrc = updcrc(c, oldcrc);
  142. if (oldcrc & 0xFFFF) {
  143. badcrc:
  144. zperr("Bad data packet CRC");
  145. return ERROR;
  146. }
  147. vfile("zrbdata: Rxcount = %d ret = %x",
  148. Rxcount, d);
  149. return d;
  150. case GOTCAN:
  151. zperr("ZMODEM: Sender Canceled");
  152. return ZCAN;
  153. case TIMEOUT:
  154. zperr("ZMODEM data packet TIMEOUT");
  155. return c;
  156. default:
  157. zperr("ZMODEM bad data packet ret=%x", c);
  158. return c;
  159. }
  160. }
  161. if (--length < 0) {
  162. zperr("ZMODEM binary data packet too long");
  163. return ERROR;
  164. }
  165. ++Rxcount;
  166. *buf++ = c;
  167. oldcrc = updcrc(c, oldcrc);
  168. continue;
  169. }
  170. }
  171. /*
  172. * Read a ZMODEM header to hdr, either binary or hex.
  173. * eflag controls local display of non zmodem characters:
  174. * 0: no display
  175. * 1: display printing characters only
  176. * 2: display all non ZMODEM characters
  177. * On success, set Zmodem to 1 and return type of header.
  178. * Otherwise return negative on error
  179. */
  180. int zgethdr(char *hdr, int eflag)
  181. {
  182. int c, n;
  183. n = Baudrate; /* Max characters before start of frame */
  184. again:
  185. Rxframeind = Rxtype = 0;
  186. switch (c = noxread7()) {
  187. case TIMEOUT:
  188. goto fifi;
  189. case ZDLE:
  190. if (noxread7() == ZDLE) {
  191. c = ZCAN; goto fifi;
  192. }
  193. /* **** FALL THRU TO **** */
  194. default:
  195. if ( --n == 0) {
  196. zperr("ZMODEM Garbage count exceeded");
  197. return(ERROR);
  198. }
  199. if (eflag && ((c &= 0177) & 0140))
  200. bttyout(c);
  201. else if (eflag > 1)
  202. bttyout(c);
  203. goto again;
  204. case ZPAD:
  205. break;
  206. }
  207. splat:
  208. switch (c = noxread7()) {
  209. case ZPAD:
  210. goto splat;
  211. case TIMEOUT:
  212. goto fifi;
  213. default:
  214. goto again;
  215. case ZDLE:
  216. break;
  217. }
  218. switch (c = noxread7()) {
  219. case TIMEOUT:
  220. goto fifi;
  221. case ZBIN:
  222. Rxframeind = ZBIN;
  223. c = zrbhdr(hdr);
  224. break;
  225. case ZHEX:
  226. Rxframeind = ZHEX;
  227. c = zrhhdr(hdr);
  228. break;
  229. case ZDLE:
  230. if (noxread7() == ZDLE) {
  231. c = ZCAN; goto fifi;
  232. }
  233. /* **** FALL THRU TO **** */
  234. default:
  235. goto again;
  236. }
  237. Rxpos = hdr[ZP3] & 0377;
  238. Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  239. Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  240. Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  241. fifi:
  242. switch (c) {
  243. case GOTCAN:
  244. c = ZCAN;
  245. /* **** FALL THRU TO **** */
  246. case ZNAK:
  247. case ZCAN:
  248. case ERROR:
  249. case TIMEOUT:
  250. zperr("ZMODEM: Got %s header", frametypes[c+2]);
  251. default:
  252. if (c >= -2 && c <= FRTYPES)
  253. vfile("zgethdr: %s %lx", frametypes[c+2], Rxpos);
  254. else
  255. vfile("zgethdr: %d %lx", c, Rxpos);
  256. }
  257. return c;
  258. }
  259. /* Receive a binary style header (type and position) */
  260. int zrbhdr(char *hdr)
  261. {
  262. int c, n;
  263. unsigned short oldcrc;
  264. if ((c = zdlread()) & ~0377)
  265. return c;
  266. Rxtype = c;
  267. oldcrc = updcrc(c, 0);
  268. for (n=4; --n >= 0;) {
  269. if ((c = zdlread()) & ~0377)
  270. return c;
  271. oldcrc = updcrc(c, oldcrc);
  272. *hdr++ = c;
  273. }
  274. if ((c = zdlread()) & ~0377)
  275. return c;
  276. oldcrc = updcrc(c, oldcrc);
  277. if ((c = zdlread()) & ~0377)
  278. return c;
  279. oldcrc = updcrc(c, oldcrc);
  280. if (oldcrc & 0xFFFF) {
  281. zperr("Bad Header CRC"); return ERROR;
  282. }
  283. Zmodem = 1;
  284. return Rxtype;
  285. }
  286. /* Receive a hex style header (type and position) */
  287. int zrhhdr(char *hdr)
  288. {
  289. int c;
  290. unsigned short oldcrc;
  291. int n;
  292. if ((c = zgethex()) < 0)
  293. return c;
  294. Rxtype = c;
  295. oldcrc = updcrc(c, 0);
  296. for (n=4; --n >= 0;) {
  297. if ((c = zgethex()) < 0)
  298. return c;
  299. oldcrc = updcrc(c, oldcrc);
  300. *hdr++ = c;
  301. }
  302. if ((c = zgethex()) < 0)
  303. return c;
  304. oldcrc = updcrc(c, oldcrc);
  305. if ((c = zgethex()) < 0)
  306. return c;
  307. oldcrc = updcrc(c, oldcrc);
  308. if (oldcrc & 0xFFFF) {
  309. zperr("Bad Header CRC"); return ERROR;
  310. }
  311. if (readline(1) == '\r') /* Throw away possible cr/lf */
  312. readline(1);
  313. Zmodem = 1; return Rxtype;
  314. }
  315. /* Send a byte as two hex digits */
  316. int zputhex(int c)
  317. {
  318. static char digits[] = "0123456789abcdef";
  319. if (Verbose>4)
  320. vfile("zputhex: %x", c);
  321. sendline(digits[(c&0xF0)>>4]);
  322. sendline(digits[(c)&0xF]);
  323. return 0;
  324. }
  325. /* Send character c with ZMODEM escape sequence encoding */
  326. int zsendline(int c)
  327. {
  328. switch (c & 0377) {
  329. case ZDLE:
  330. case 021:
  331. case 023:
  332. case 0221:
  333. case 0223:
  334. xsendline(ZDLE);
  335. c ^= 0100;
  336. /* **** FALL THRU TO **** */
  337. default:
  338. xsendline(c);
  339. }
  340. return 0;
  341. }
  342. /* Decode two lower case hex digits into an 8 bit byte value */
  343. int zgethex(void)
  344. {
  345. int c;
  346. c = zgeth1();
  347. if (Verbose>4)
  348. vfile("zgethex: %x", c);
  349. return c;
  350. }
  351. int zgeth1(void)
  352. {
  353. int c, n;
  354. if ((c = noxread7()) < 0)
  355. return c;
  356. n = c - '0';
  357. if (n > 9)
  358. n -= ('a' - ':');
  359. if (n & ~0xF)
  360. return ERROR;
  361. if ((c = noxread7()) < 0)
  362. return c;
  363. c -= '0';
  364. if (c > 9)
  365. c -= ('a' - ':');
  366. if (c & ~0xF)
  367. return ERROR;
  368. c += (n<<4);
  369. return c;
  370. }
  371. /*
  372. * Read a byte, checking for ZMODEM escape encoding
  373. * including CAN-CAN which represents a quick abort
  374. */
  375. int zdlread(void)
  376. {
  377. int c;
  378. if ((c = readline(Rxtimeout)) != ZDLE)
  379. return c;
  380. if ((c = readline(Rxtimeout)) < 0)
  381. return c;
  382. switch (c) {
  383. case ZDLE:
  384. return GOTCAN;
  385. case ZCRCE:
  386. case ZCRCG:
  387. case ZCRCQ:
  388. case ZCRCW:
  389. return (c | GOTOR);
  390. case ZRUB0:
  391. return 0177;
  392. case ZRUB1:
  393. return 0377;
  394. default:
  395. if ((c & 0140) == 0100)
  396. return (c ^ 0100);
  397. break;
  398. }
  399. zperr("Got bad ZMODEM escape sequence %x", c);
  400. return ERROR;
  401. }
  402. /*
  403. * Read a character from the modem line with timeout.
  404. * Eat parity, XON and XOFF characters.
  405. */
  406. int noxread7(void)
  407. {
  408. int c;
  409. for (;;) {
  410. if ((c = readline(Rxtimeout)) < 0)
  411. return c;
  412. switch (c &= 0177) {
  413. case XON:
  414. case XOFF:
  415. continue;
  416. default:
  417. return c;
  418. }
  419. }
  420. }
  421. /* Store long integer pos in Txhdr */
  422. int stohdr(long int pos)
  423. {
  424. Txhdr[ZP0] = pos;
  425. Txhdr[ZP1] = pos>>8;
  426. Txhdr[ZP2] = pos>>16;
  427. Txhdr[ZP3] = pos>>24;
  428. return 0;
  429. }
  430. /* Recover a long integer from a header */
  431. long
  432. int rclhdr(char *hdr)
  433. {
  434. long int l;
  435. l = (hdr[ZP3] & 0377);
  436. l = (l << 8) | (hdr[ZP2] & 0377);
  437. l = (l << 8) | (hdr[ZP1] & 0377);
  438. l = (l << 8) | (hdr[ZP0] & 0377);
  439. return l;
  440. }