RZ.C 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104
  1. #define VERSION "1.03 05-18-86"
  2. #define PUBDIR "/usr/spool/uucppublic"
  3. /*% cc -DNFGVMIN -K -O % -o rz; size rz
  4. *
  5. * rz.c By Chuck Forsberg
  6. *
  7. * cc -O rz.c -o rz USG (3.0) Unix
  8. * cc -O -DV7 rz.c -o rz Unix V7, BSD 2.8 - 4.3
  9. *
  10. * ln rz rb For either system
  11. *
  12. * ln rz /usr/bin/rbrmail For remote mail. Make this the
  13. * login shell. rbrmail then calls
  14. * rmail(1) to deliver mail.
  15. *
  16. * Unix is a trademark of Western Electric Company
  17. *
  18. * A program for Unix to receive files and commands from computers running
  19. * Professional-YAM, PowerCom, YAM, IMP, or programs supporting XMODEM.
  20. * rz uses Unix buffered input to reduce wasted CPU time.
  21. *
  22. * Iff the program is invoked by rzCOMMAND, output is piped to
  23. * "COMMAND filename"
  24. *
  25. * Some systems (Venix, Coherent, Regulus) may not support tty raw mode
  26. * read(2) the same way as Unix. ONEREAD must be defined to force one
  27. * character reads for these systems. Added 7-01-84 CAF
  28. *
  29. * Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF
  30. *
  31. * NFGVMIN Added 1-13-85 CAF for PC-AT Xenix systems where c_cc[VMIN]
  32. * doesn't seem to work (even though it compiles without error!).
  33. *
  34. * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
  35. */
  36. #define zperr vfile
  37. #include "rtthread.h"
  38. #include "finsh.h"
  39. #include "shell.h"
  40. #include"rtdef.h"
  41. #include <dfs.h>
  42. #include <dfs_file.h>
  43. #include <dfs_posix.h>
  44. #define OK 0
  45. #define FALSE 0
  46. #define TRUE 1
  47. #define ERROR (-1)
  48. #define HOWMANY 133
  49. int Zmodem=0; /* ZMODEM protocol requested */
  50. int Nozmodem = 0; /* If invoked as "rb" */
  51. unsigned Baudrate;
  52. #include "rbsb.c" /* most of the system dependent stuff here */
  53. int fout;
  54. /*
  55. * Routine to calculate the free bytes on the current file system
  56. * ~0 means many free bytes (unknown)
  57. */
  58. long getfree()
  59. {
  60. return(~0L); /* many free bytes ... */
  61. }
  62. char *Extensions[] = {
  63. ".A",
  64. ".ARC",
  65. ".CCC",
  66. ".CL",
  67. ".CMD",
  68. ".COM",
  69. ".CRL",
  70. ".DAT",
  71. ".DIR",
  72. ".EXE",
  73. ".O",
  74. ".OBJ",
  75. ".OVL",
  76. ".PAG",
  77. ".REL",
  78. ".SAV",
  79. ".SUB",
  80. ".SWP",
  81. ".SYS",
  82. ".TAR",
  83. ".UTL",
  84. ".a",
  85. ".arc",
  86. ".com",
  87. ".dat",
  88. ".o",
  89. ".obj",
  90. ".ovl",
  91. ".sys",
  92. ".tar",
  93. ""
  94. };
  95. /* Ward Christensen / CP/M parameters - Don't change these! */
  96. #define ENQ 005
  97. #define CAN ('X'&037)
  98. #define XOFF ('s'&037)
  99. #define XON ('q'&037)
  100. #define SOH 1
  101. #define STX 2
  102. #define EOT 4
  103. #define ACK 6
  104. #define NAK 025
  105. #define CPMEOF 032
  106. #define WANTCRC 0103 /* send C not NAK to get crc not checksum */
  107. #define TIMEOUT (-2)
  108. #define ERRORMAX 5
  109. #define RETRYMAX 5
  110. #define WCEOT (-10)
  111. #define SECSIZ 128 /* cp/m's Magic Number record size */
  112. #define PATHLEN 257 /* ready for 4.2 bsd ? */
  113. #define KSIZE 1024 /* record size with k option */
  114. #define UNIXFILE 0x8000 /* happens to the the S_IFREG file mask bit for stat */
  115. int Lastrx;
  116. int Crcflg;
  117. int Firstsec;
  118. int Eofseen; /* indicates cpm eof (^Z) has been received */
  119. int errors;
  120. int Restricted=0; /* restricted; no /.. or ../ in filenames */
  121. int Badclose = 0; /* Error on last close */
  122. #define ONEREAD 1
  123. #ifdef ONEREAD
  124. /* Sorry, Regulus and some others don't work right in raw mode! */
  125. int Readnum = 1; /* Number of bytes to ask for in read() from modem */
  126. #else
  127. int Readnum = KSIZE; /* Number of bytes to ask for in read() from modem */
  128. #endif
  129. #define DEFBYTL 2000000000L /* default rx file size */
  130. long Bytesleft; /* number of bytes of incoming file left */
  131. long Modtime; /* Unix style mod time for incoming file */
  132. short Filemode; /* Unix style mode for incoming file */
  133. char Pathname[PATHLEN];
  134. char *Progname; /* the name by which we were called */
  135. int Batch=0;
  136. int Wcsmask=0377;
  137. int Topipe=0;
  138. int MakeLCPathname=TRUE; /* make received pathname lower case */
  139. int Verbose=0;
  140. int Quiet=0; /* overrides logic that would otherwise set verbose */
  141. int Nflag = 0; /* Don't really transfer files */
  142. int Rxbinary=FALSE; /* receive all files in bin mode */
  143. int Thisbinary; /* current file is to be received in bin mode */
  144. int Blklen; /* record length of received packets */
  145. char secbuf[KSIZE];
  146. char linbuf[KSIZE];
  147. int Lleft=0; /* number of characters in linbuf */
  148. char zconv; /* ZMODEM file conversion request */
  149. char zmanag; /* ZMODEM file management request */
  150. char ztrans; /* ZMODEM file transport request */
  151. int purgeline(void);
  152. unsigned short int updcrc(int c, int crc);
  153. int procheader(char *name);
  154. int report(int sct);
  155. int tryz(void);
  156. int rzfiles(void);
  157. int rzfile(void);
  158. int closeit(void);
  159. int zmputs(char *s);
  160. int ackbibi(void);
  161. int wcreceive(int argc, char **argp);
  162. int wcrxpn(char *rpn);
  163. int wcrx(void);
  164. int wcgetsec(char *rxbuf, int maxtime);
  165. int readline(int timeout);
  166. int putsec(char *buf, int n);
  167. int sendline(int c);
  168. int xsendline(int c);
  169. int log(const char *s,...);
  170. int bttyout(int c);
  171. int flushmo(void);
  172. int canit(void);
  173. int sys2(char *s);
  174. int exec2(char *s);
  175. #include "zm.c"
  176. /* called by signal interrupt or terminate to clean things up */
  177. int bibi(int n)
  178. {
  179. if (Zmodem)
  180. zmputs(Attn);
  181. canit();
  182. mode(0);
  183. return 0;
  184. }
  185. int zrmain(void)
  186. {
  187. if (wcreceive(0, 0)==ERROR) {
  188. canit();
  189. zperr("received error,exit\n");
  190. return 1;
  191. }
  192. return 0;
  193. }
  194. int usage(void)
  195. {
  196. //rt_kprintf("%s %s for %s by Chuck Forsberg\n",
  197. // Progname, VERSION, OS);
  198. //rt_kprintf("Usage: rz [-1buv] (ZMODEM Batch)\n");
  199. //rt_kprintf("or rb [-1buv] (YMODEM Batch)\n");
  200. //rt_kprintf("or rz [-1bcv] file (XMODEM)\n");
  201. //rt_kprintf(" -1 For cu(1): Use fd 1 for input\n");
  202. //rt_kprintf(" -b Binary transfer for all files\n");
  203. //rt_kprintf(" -u Allow all UPPER CASE names\n");
  204. //rt_kprintf(" -v Verbose more v's give more info\n");
  205. //rt_kprintf(" -c Use 16 bit CRC (XMODEM)\n");
  206. //exit(1);
  207. return 0;
  208. }
  209. /*
  210. * Debugging information output interface routine
  211. */
  212. /* VARARGS1 */
  213. void vfile(const char *fmt,...)
  214. {
  215. return;
  216. }
  217. /*
  218. * Let's receive something already.
  219. */
  220. int wcreceive(int argc, char **argp)
  221. {
  222. int c;
  223. if (Batch || argc==0) {
  224. Crcflg=(Wcsmask==0377);
  225. if ( !Quiet)
  226. rt_kprintf("\nrz: ready...\n");
  227. c = tryz();
  228. if (c) {
  229. if (c == ZCOMPL)
  230. return OK;
  231. if (c == ERROR)
  232. goto fubar;
  233. c = rzfiles();
  234. if (c)
  235. goto fubar;
  236. } else {
  237. for (;;) {
  238. if (wcrxpn(secbuf)== ERROR)
  239. goto fubar;
  240. if (secbuf[0]==0)
  241. return OK;
  242. if (procheader(secbuf) == ERROR)
  243. goto fubar;
  244. if (wcrx()==ERROR)
  245. goto fubar;
  246. }
  247. }
  248. } else {
  249. Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
  250. strcpy(Pathname, *argp);
  251. //checkpath(Pathname);
  252. //rt_kprintf(stderr, "\nrz: ready to receive %s ", Pathname);
  253. //if ((fout=fopen(Pathname, "w")) == NULL)
  254. // return ERROR;
  255. if (wcrx()==ERROR)
  256. goto fubar;
  257. }
  258. return OK;
  259. fubar:
  260. canit();
  261. if (Topipe && fout) {
  262. close(fout); return ERROR;
  263. }
  264. if (fout)
  265. close(fout);
  266. if (Restricted) {
  267. unlink(Pathname);
  268. rt_kprintf("\r\nrz: %s removed.\r\n", Pathname);
  269. }
  270. return ERROR;
  271. }
  272. /*
  273. * Fetch a pathname from the other end as a C ctyle ASCIZ string.
  274. * Length is indeterminate as long as less than Blklen
  275. * A null string represents no more files (YMODEM)
  276. */
  277. int wcrxpn(char *rpn)
  278. {
  279. int c;
  280. #ifdef NFGVMIN
  281. readline(1);
  282. #else
  283. purgeline();
  284. #endif
  285. et_tu:
  286. Firstsec=TRUE; Eofseen=FALSE;
  287. sendline(Crcflg?WANTCRC:NAK);
  288. Lleft=0; /* Do read next time ... */
  289. while ((c = wcgetsec(rpn, 100)) != 0) {
  290. log( "Pathname fetch returned %d\n", c);
  291. if (c == WCEOT) {
  292. sendline(ACK);
  293. Lleft=0; /* Do read next time ... */
  294. readline(1);
  295. goto et_tu;
  296. }
  297. return ERROR;
  298. }
  299. sendline(ACK);
  300. return OK;
  301. }
  302. /*
  303. * Adapted from CMODEM13.C, written by
  304. * Jack M. Wierda and Roderick W. Hart
  305. */
  306. int wcrx(void)
  307. {
  308. register int sectnum, sectcurr;
  309. register char sendchar;
  310. register char *p;
  311. int cblklen; /* bytes to dump this block */
  312. Firstsec=TRUE;sectnum=0; Eofseen=FALSE;
  313. sendchar=Crcflg?WANTCRC:NAK;
  314. for (;;) {
  315. sendline(sendchar); /* send it now, we're ready! */
  316. Lleft=0; /* Do read next time ... */
  317. sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130);
  318. report(sectcurr);
  319. if (sectcurr==(sectnum+1 &Wcsmask)) {
  320. if (sectnum==0 && !Thisbinary) {
  321. p=secbuf; sectcurr=Blklen;
  322. if (*p == 032) /* A hack for .arc files */
  323. goto binbin;
  324. for (; *p != 032 && --sectcurr>=0; ++p)
  325. if (*p < 07 || (*p & 0200)) {
  326. binbin:
  327. Thisbinary++;
  328. if (Verbose)
  329. rt_kprintf("Changed to BIN\n");
  330. break;
  331. }
  332. }
  333. sectnum++;
  334. cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;
  335. if (putsec(secbuf, cblklen)==ERROR)
  336. return ERROR;
  337. if ((Bytesleft-=cblklen) < 0)
  338. Bytesleft = 0;
  339. sendchar=ACK;
  340. }
  341. else if (sectcurr==(sectnum&Wcsmask)) {
  342. log( "Received dup Sector\n");
  343. sendchar=ACK;
  344. }
  345. else if (sectcurr==WCEOT) {
  346. if (closeit())
  347. return ERROR;
  348. sendline(ACK);
  349. Lleft=0; /* Do read next time ... */
  350. return OK;
  351. }
  352. else if (sectcurr==ERROR)
  353. return ERROR;
  354. else {
  355. log( "Sync Error\n");
  356. return ERROR;
  357. }
  358. }
  359. }
  360. /*
  361. * Wcgetsec fetches a Ward Christensen type sector.
  362. * Returns sector number encountered or ERROR if valid sector not received,
  363. * or CAN CAN received
  364. * or WCEOT if eot sector
  365. * time is timeout for first char, set to 4 seconds thereafter
  366. ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
  367. * (Caller must do that when he is good and ready to get next sector)
  368. */
  369. int wcgetsec(char *rxbuf, int maxtime)
  370. {
  371. int checksum, wcj, firstch;
  372. unsigned short oldcrc;
  373. char *p;
  374. int sectcurr;
  375. for (Lastrx=errors=0; errors<RETRYMAX; errors++) {
  376. if ((firstch=readline(maxtime))==STX) {
  377. Blklen=KSIZE; goto get2;
  378. }
  379. if (firstch==SOH) {
  380. Blklen=SECSIZ;
  381. get2:
  382. sectcurr=readline(1);
  383. if ((sectcurr+(oldcrc=readline(1)))==Wcsmask) {
  384. oldcrc=checksum=0;
  385. for (p=rxbuf,wcj=Blklen; --wcj>=0; ) {
  386. if ((firstch=readline(1)) < 0)
  387. goto bilge;
  388. oldcrc=updcrc(firstch, oldcrc);
  389. checksum += (*p++ = firstch);
  390. }
  391. if ((firstch=readline(1)) < 0)
  392. goto bilge;
  393. if (Crcflg) {
  394. oldcrc=updcrc(firstch, oldcrc);
  395. if ((firstch=readline(1)) < 0)
  396. goto bilge;
  397. oldcrc=updcrc(firstch, oldcrc);
  398. if (oldcrc & 0xFFFF)
  399. log("CRC=0%o\n", oldcrc);
  400. else {
  401. Firstsec=FALSE;
  402. return sectcurr;
  403. }
  404. }
  405. else if (((checksum-firstch)&Wcsmask)==0) {
  406. Firstsec=FALSE;
  407. return sectcurr;
  408. }
  409. else
  410. log( "Checksum Error\n");
  411. }
  412. else
  413. log("Sector number garbled 0%o 0%o\n",
  414. sectcurr, oldcrc);
  415. }
  416. /* make sure eot really is eot and not just mixmash */
  417. #ifdef NFGVMIN
  418. else if (firstch==EOT && readline(1)==TIMEOUT)
  419. return WCEOT;
  420. #else
  421. else if (firstch==EOT && Lleft==0)
  422. return WCEOT;
  423. #endif
  424. else if (firstch==CAN) {
  425. if (Lastrx==CAN) {
  426. log("Sender CANcelled\n");
  427. return ERROR;
  428. } else {
  429. Lastrx=CAN;
  430. continue;
  431. }
  432. }
  433. else if (firstch==TIMEOUT) {
  434. if (Firstsec)
  435. goto humbug;
  436. bilge:
  437. log( "Timeout\n");
  438. }
  439. else
  440. log( "Got 0%o sector header\n", firstch);
  441. humbug:
  442. Lastrx=0;
  443. while(readline(1)!=TIMEOUT)
  444. ;
  445. if (Firstsec) {
  446. sendline(Crcflg?WANTCRC:NAK);
  447. Lleft=0; /* Do read next time ... */
  448. } else {
  449. maxtime=40; sendline(NAK);
  450. Lleft=0; /* Do read next time ... */
  451. }
  452. }
  453. /* try to stop the bubble machine. */
  454. canit();
  455. return ERROR;
  456. }
  457. /*
  458. * This version of readline is reasoably well suited for
  459. * reading many characters.
  460. * (except, currently, for the Regulus version!)
  461. *
  462. * timeout is in tenths of seconds
  463. */
  464. int readline(int timeout)
  465. {
  466. static char *cdq; /* pointer for removing chars from linbuf */
  467. static char data_buffer[8];
  468. if (--Lleft >= 0)
  469. {
  470. return (*cdq++ & Wcsmask);
  471. }
  472. while (1)
  473. {
  474. Lleft = zread(shell->device, 0, data_buffer, 1);
  475. if (Lleft)
  476. {
  477. Lleft = Lleft;
  478. cdq = &data_buffer[0];
  479. break;
  480. }
  481. }
  482. if (Lleft < 1)
  483. return TIMEOUT;
  484. --Lleft;
  485. return (*cdq++ & Wcsmask);
  486. }
  487. /*
  488. * Purge the modem input queue of all characters
  489. */
  490. int purgeline(void)
  491. {
  492. Lleft = 0;
  493. #ifdef USG
  494. ioctl(iofd, TCFLSH, 0);
  495. #else
  496. lseek(iofd, 0L, 2);
  497. #endif
  498. return 0;
  499. }
  500. /*
  501. * Update CRC CRC-16 used by XMODEM/CRC, YMODEM, and ZMODEM.
  502. * Note: Final result must be masked with 0xFFFF before testing
  503. * More efficient table driven routines exist.
  504. */
  505. unsigned short int
  506. updcrc(int c, int crc)
  507. {
  508. int count;
  509. for (count=8; --count>=0;) {
  510. if (crc & 0x8000) {
  511. crc <<= 1;
  512. crc += (((c<<=1) & 0400) != 0);
  513. crc ^= 0x1021;
  514. }
  515. else {
  516. crc <<= 1;
  517. crc += (((c<<=1) & 0400) != 0);
  518. }
  519. }
  520. return crc;
  521. }
  522. /*
  523. * Process incoming file information header
  524. */
  525. int procheader(char *name)
  526. {
  527. char *openmode, *ptr;
  528. unsigned char i;
  529. char fname[100];
  530. /* set default parameters */
  531. openmode = "w"; Thisbinary=Rxbinary;
  532. /*
  533. * Process ZMODEM remote file management requests
  534. */
  535. if (zconv == ZCNL) /* Remote ASCII override */
  536. Thisbinary = 0;
  537. if (zconv == ZCBIN) /* Remote Binary override */
  538. ++Thisbinary;
  539. else if (zmanag == ZMAPND)
  540. openmode = "a";
  541. openmode = openmode;
  542. Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
  543. for(i=0;i<100;i++) fname[i] = 0;
  544. for (i=1,ptr=name;i<strlen(name)+1;i++) /* get file name */
  545. fname[i]= *ptr++;
  546. fname[0] = '/'; /* working_directory */
  547. if ((fout = open(fname,DFS_O_CREAT|DFS_O_WRONLY,0)) < 0) /* create file */
  548. {
  549. return ERROR;
  550. }
  551. return OK;
  552. }
  553. /* Make string s lower case */
  554. int uncaps(char *s)
  555. {
  556. return 0;
  557. /*
  558. for ( ; *s; ++s)
  559. if (isupper(*s))
  560. *s = tolower(*s);
  561. */
  562. }
  563. /*
  564. * IsAnyLower returns TRUE if string s has lower case letters.
  565. */
  566. int IsAnyLower(char *s)
  567. {
  568. return 0;
  569. /*
  570. for ( ; *s; ++s)
  571. if (islower(*s))
  572. return TRUE;
  573. return FALSE;
  574. */
  575. }
  576. /*
  577. * Putsec writes the n characters of buf to receive file fout.
  578. * If not in binary mode, carriage returns, and all characters
  579. * starting with CPMEOF are discarded.
  580. */
  581. int putsec(char *buf, int n)
  582. {
  583. register char *p;
  584. if (Thisbinary) {
  585. for (p=buf; --n>=0; )
  586. write(fout,p++,1);
  587. }
  588. else {
  589. if (Eofseen)
  590. return OK;
  591. for (p=buf; --n>=0; ++p ) {
  592. if ( *p == '\r')
  593. continue;
  594. if (*p == CPMEOF) {
  595. Eofseen=TRUE; return OK;
  596. }
  597. write(fout,p,1);
  598. }
  599. }
  600. return OK;
  601. }
  602. /*
  603. * Send a character to modem. Small is beautiful.
  604. */
  605. int sendline(int c)
  606. {
  607. zwrite(c);
  608. return 0;
  609. }
  610. int xsendline(int c)
  611. {
  612. sendline(c);
  613. return 0;
  614. }
  615. int flushmo(void)
  616. {
  617. return 0;
  618. }
  619. /*
  620. * substr(string, token) searches for token in string s
  621. * returns pointer to token within string if found, NULL otherwise
  622. */
  623. char *
  624. substr(char *s, char *t)
  625. {
  626. register char *ss,*tt;
  627. /* search for first char of token */
  628. for (ss=s; *s; s++)
  629. if (*s == *t)
  630. /* compare token with substring */
  631. for (ss=s,tt=t; ;) {
  632. if (*tt == 0)
  633. return s;
  634. if (*ss++ != *tt++)
  635. break;
  636. }
  637. return NULL;
  638. }
  639. /*
  640. * Log an error
  641. */
  642. /*VARARGS1*/
  643. int log(const char *s,...)
  644. {
  645. return 0;
  646. }
  647. /* send cancel string to get the other end to shut up */
  648. int canit(void)
  649. { /*
  650. static char canistr[] = {
  651. ZPAD,ZPAD,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
  652. };
  653. */
  654. //printf(canistr);
  655. Lleft=0; /* Do read next time ... */
  656. //fflush(stdout);
  657. return 0;
  658. }
  659. /*
  660. * Return 1 iff stdout and stderr are different devices
  661. * indicating this program operating with a modem on a
  662. * different line
  663. */
  664. int fromcu(void)
  665. {
  666. struct stat a, b;
  667. fstat(1, &a);
  668. fstat(2, &b);
  669. //return (a.st_rdev != b.st_rdev);
  670. return 0;
  671. }
  672. int report(int sct)
  673. {
  674. //if (Verbose>1)
  675. // rt_kprintf(stderr,"%03d%c",sct,sct%10? ' ' : '\r');
  676. return 0;
  677. }
  678. /*
  679. * If called as [-][dir/../]vrzCOMMAND set Verbose to 1
  680. * If called as [-][dir/../]rzCOMMAND set the pipe flag
  681. * If called as rb use YMODEM protocol
  682. */
  683. int chkinvok(char *s)
  684. {
  685. register char *p;
  686. p = s;
  687. while (*p == '-')
  688. s = ++p;
  689. while (*p)
  690. if (*p++ == '/')
  691. s = p;
  692. if (*s == 'v') {
  693. Verbose=1; ++s;
  694. }
  695. Progname = s;
  696. if (s[0]=='r' && s[1]=='b')
  697. Nozmodem = TRUE;
  698. if (s[2] && s[0]=='r' && s[1]=='b')
  699. Topipe=TRUE;
  700. if (s[2] && s[0]=='r' && s[1]=='z')
  701. Topipe=TRUE;
  702. return 0;
  703. }
  704. /*
  705. * Totalitarian Communist pathname processing
  706. */
  707. int checkpath(char *name)
  708. {
  709. // if (Restricted) {
  710. // if (fopen(name, "r") != NULL) {
  711. // canit();
  712. //rt_kprintf(stderr, "\r\nrz: %s exists\n", name);
  713. // bibi();
  714. // }
  715. /* restrict pathnames to current tree or uucppublic */
  716. // if ( substr(name, "../")
  717. // || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
  718. // canit();
  719. //rt_kprintf(stderr,"\r\nrz:\tSecurity Violation\r\n");
  720. // bibi();
  721. // }
  722. // }
  723. return 0;
  724. }
  725. /*
  726. * Initialize for Zmodem receive attempt, try to activate Zmodem sender
  727. * Handles ZSINIT frame
  728. * Return ZFILE if Zmodem filename received, -1 on error,
  729. * ZCOMPL if transaction finished, else 0
  730. */
  731. int tryz(void)
  732. {
  733. int n;
  734. int cmdzack1flg;
  735. if (Nozmodem) /* Check for "rb" program name */
  736. return 0;
  737. Rxtimeout = 100;
  738. for (n=5; --n>=0; ) {
  739. /* Set buffer length (0) and capability flags */
  740. stohdr(0L);
  741. Txhdr[ZF0] = CANFDX|CANOVIO|CANBRK;
  742. zshhdr(Badclose?ZFERR:ZRINIT, Txhdr);
  743. again:
  744. switch (zgethdr(Rxhdr, 0)) {
  745. case ZRQINIT:
  746. continue;
  747. case ZEOF:
  748. continue;
  749. case TIMEOUT:
  750. continue;
  751. case ZFILE:
  752. zconv = Rxhdr[ZF0];
  753. zmanag = Rxhdr[ZF1];
  754. ztrans = Rxhdr[ZF2];
  755. Badclose = FALSE;
  756. if (zrbdata(secbuf, KSIZE) == GOTCRCW)
  757. return ZFILE;
  758. zshhdr(ZNAK, Txhdr);
  759. case ZSINIT:
  760. if (zrbdata(Attn, ZATTNLEN) == GOTCRCW) {
  761. zshhdr(ZACK, Txhdr);
  762. goto again;
  763. }
  764. zshhdr(ZNAK, Txhdr);
  765. continue;
  766. case ZFREECNT:
  767. stohdr(getfree());
  768. zshhdr(ZACK, Txhdr);
  769. goto again;
  770. case ZCOMMAND:
  771. cmdzack1flg = Rxhdr[ZF0];
  772. if (zrbdata(secbuf, KSIZE) == GOTCRCW) {
  773. if (cmdzack1flg & ZCACK1)
  774. stohdr(0L);
  775. else
  776. stohdr((long)sys2(secbuf));
  777. purgeline(); /* dump impatient questions */
  778. do {
  779. zshhdr(ZCOMPL, Txhdr);
  780. }
  781. while (++errors<10 && zgethdr(Rxhdr,1) != ZFIN);
  782. ackbibi();
  783. if (cmdzack1flg & ZCACK1)
  784. exec2(secbuf);
  785. return ZCOMPL;
  786. }
  787. zshhdr(ZNAK, Txhdr); goto again;
  788. case ZCOMPL:
  789. goto again;
  790. default:
  791. continue;
  792. case ZFIN:
  793. ackbibi(); return ZCOMPL;
  794. case ZCAN:
  795. return ERROR;
  796. }
  797. }
  798. return 0;
  799. }
  800. /*
  801. * Receive 1 or more files with ZMODEM protocol
  802. */
  803. int rzfiles(void)
  804. {
  805. int c;
  806. for (;;) {
  807. switch (c = rzfile()) {
  808. case ZEOF:
  809. case ZSKIP:
  810. switch (tryz()) {
  811. case ZCOMPL:
  812. return OK;
  813. default:
  814. return ERROR;
  815. case ZFILE:
  816. break;
  817. }
  818. continue;
  819. default:
  820. return c;
  821. case ERROR:
  822. return ERROR;
  823. }
  824. }
  825. }
  826. /*
  827. * Receive a file with ZMODEM protocol
  828. * Assumes file name frame is in secbuf
  829. */
  830. int rzfile(void)
  831. {
  832. int c, n;
  833. long int rxbytes;
  834. Eofseen=FALSE;
  835. if (procheader(secbuf) == ERROR) {
  836. zshhdr(ZSKIP, Txhdr);
  837. return ZSKIP;
  838. }
  839. n = 10; rxbytes = 0l;
  840. for (;;) {
  841. stohdr(rxbytes);
  842. zshhdr(ZRPOS, Txhdr);
  843. nxthdr:
  844. switch (c = zgethdr(Rxhdr, 0)) {
  845. default:
  846. vfile("rzfile: zgethdr returned %d", c);
  847. return ERROR;
  848. case ZNAK:
  849. case TIMEOUT:
  850. if ( --n < 0) {
  851. vfile("rzfile: zgethdr returned %d", c);
  852. return ERROR;
  853. }
  854. case ZFILE:
  855. continue;
  856. case ZEOF:
  857. if (rclhdr(Rxhdr) != rxbytes) {
  858. continue;
  859. }
  860. if (closeit()) {
  861. Badclose = TRUE;
  862. vfile("rzfile: closeit returned <> 0");
  863. return ERROR;
  864. }
  865. vfile("rzfile: normal EOF");
  866. return c;
  867. case ERROR: /* Too much garbage in header search error */
  868. if ( --n < 0) {
  869. vfile("rzfile: zgethdr returned %d", c);
  870. return ERROR;
  871. }
  872. zmputs(Attn);
  873. continue;
  874. case ZDATA:
  875. n = 10;
  876. if (rclhdr(Rxhdr) != rxbytes) {
  877. zmputs(Attn);
  878. continue;
  879. }
  880. moredata:
  881. switch (c = zrbdata(secbuf, KSIZE)) {
  882. case ZCAN:
  883. vfile("rzfile: zgethdr returned %d", c);
  884. return ERROR;
  885. case ERROR: /* CRC error */
  886. if ( --n < 0) {
  887. vfile("rzfile: zgethdr returned %d", c);
  888. return ERROR;
  889. }
  890. zmputs(Attn);
  891. continue;
  892. case TIMEOUT:
  893. if ( --n < 0) {
  894. vfile("rzfile: zgethdr returned %d", c);
  895. return ERROR;
  896. }
  897. continue;
  898. case GOTCRCW:
  899. putsec(secbuf, Rxcount);
  900. rxbytes += Rxcount;
  901. stohdr(rxbytes);
  902. zshhdr(ZACK, Txhdr);
  903. goto nxthdr;
  904. case GOTCRCQ:
  905. putsec(secbuf, Rxcount);
  906. rxbytes += Rxcount;
  907. stohdr(rxbytes);
  908. zshhdr(ZACK, Txhdr);
  909. goto moredata;
  910. case GOTCRCG:
  911. putsec(secbuf, Rxcount);
  912. rxbytes += Rxcount;
  913. goto moredata;
  914. case GOTCRCE:
  915. putsec(secbuf, Rxcount);
  916. rxbytes += Rxcount;
  917. goto nxthdr;
  918. }
  919. }
  920. }
  921. }
  922. /*
  923. * Send a string to the modem, processing for \336 (sleep 1 sec)
  924. * and \335 (break signal)
  925. */
  926. int zmputs(char *s)
  927. {
  928. int c;
  929. while (*s) {
  930. switch (c = *s++) {
  931. case '\336':
  932. //sleep(1);
  933. continue;
  934. case '\335':
  935. sendbrk(); continue;
  936. default:
  937. sendline(c);
  938. }
  939. }
  940. return 0;
  941. }
  942. /*
  943. * Close the receive dataset, return OK or ERROR
  944. */
  945. int closeit(void)
  946. {
  947. if (Topipe) {
  948. if (close(fout)) {
  949. return ERROR;
  950. }
  951. return OK;
  952. }
  953. if (close(fout)==ERROR) {
  954. //rt_kprintf(stderr, "file close ERROR\n");
  955. return ERROR;
  956. }
  957. // if (Modtime) {
  958. // timep[0] = time(NULL);
  959. // timep[1] = Modtime;
  960. // utime(Pathname, timep);
  961. //}
  962. //if (Filemode)
  963. //chmod(Pathname, (07777 & Filemode));
  964. return OK;
  965. }
  966. /*
  967. * Ack a ZFIN packet, let byegones be byegones
  968. */
  969. int ackbibi(void)
  970. {
  971. int n;
  972. vfile("ackbibi:");
  973. Readnum = 1;
  974. stohdr(0L);
  975. for (n=4; --n>=0; ) {
  976. zshhdr(ZFIN, Txhdr);
  977. for (;;) {
  978. switch (readline(100)) {
  979. case 'O':
  980. readline(1); /* Discard 2nd 'O' */
  981. /* ***** FALL THRU TO ***** */
  982. case TIMEOUT:
  983. vfile("ackbibi complete");
  984. return 0;
  985. default:
  986. break;
  987. }
  988. }
  989. }
  990. return 0;
  991. }
  992. /*
  993. * Local console output simulation
  994. */
  995. int bttyout(int c)
  996. {
  997. //if (Verbose || fromcu)
  998. //putc(c, stderr);
  999. return 0;
  1000. }
  1001. /*
  1002. * Strip leading ! if present, do shell escape.
  1003. */
  1004. int sys2(char *s)
  1005. {
  1006. if (*s == '!')
  1007. ++s;
  1008. return 0;
  1009. }
  1010. /*
  1011. * Strip leading ! if present, do exec.
  1012. */
  1013. int exec2(char *s)
  1014. {
  1015. if (*s == '!')
  1016. ++s;
  1017. mode(0);
  1018. return 0;
  1019. }