SZ.C 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168
  1. #define VERSION "sz 1.03 05-18-86"
  2. #define PUBDIR "/usr/spool/uucppublic"
  3. /*% cc -O -K sz.c -o sz; size sz
  4. * sz.c By Chuck Forsberg
  5. *
  6. * cc -O sz.c -o sz USG (SYS III/V) Unix
  7. * cc -O -DV7 sz.c -o sz Unix Version 7, 2.8 - 4.3 BSD
  8. *
  9. * ******* Some systems (Venix, Coherent, Regulus) do not *******
  10. * ******* support tty raw mode read(2) identically to *******
  11. * ******* Unix. ONEREAD must be defined to force one *******
  12. * ******* character reads for these systems. *******
  13. *
  14. * A program for Unix to send files and commands to computers running
  15. * Professional-YAM, PowerCom, YAM, IMP, or programs supporting XMODEM.
  16. *
  17. * Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM.
  18. *
  19. * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
  20. */
  21. /*
  22. * Attention string to be executed by receiver to interrupt streaming data
  23. * when an error is detected. A pause (0336) may be needed before the
  24. * ^C (03) or after it.
  25. */
  26. char Myattn[] = { 03, 0336, 0 };
  27. unsigned updcrc();
  28. char *substr(), *getenv();
  29. #define LOGFILE "/tmp/szlog"
  30. #define zperr vfile
  31. /*
  32. #include <stdio.h>
  33. #include <signal.h>
  34. #include <setjmp.h>
  35. #include <ctype.h>
  36. */
  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. #include "zmodem.h"
  45. #define PATHLEN 256
  46. #define OK 0
  47. #define FALSE 0
  48. #define TRUE 1
  49. #define ERROR (-1)
  50. #define HOWMANY 2
  51. int Zmodem=0; /* ZMODEM protocol requested */
  52. unsigned Baudrate;
  53. #include "rbsb.c" /* most of the system dependent stuff here */
  54. int in;
  55. /* Ward Christensen / CP/M parameters - Don't change these! */
  56. #define ENQ 005
  57. #define CAN ('X'&037)
  58. #define XOFF ('s'&037)
  59. #define XON ('q'&037)
  60. #define SOH 1
  61. #define STX 2
  62. #define EOT 4
  63. #define ACK 6
  64. #define NAK 025
  65. #define CPMEOF 032
  66. #define WANTCRC 0103 /* send C not NAK to get crc not checksum */
  67. #define WANTG 0107 /* Send G not NAK to get nonstop batch xmsn */
  68. #define TIMEOUT (-2)
  69. #define RETRYMAX 10
  70. #define SECSIZ 128 /* cp/m's Magic Number record size */
  71. #define KSIZE 1024
  72. char Lastrx;
  73. char Crcflg;
  74. int Wcsmask=0377;
  75. int Verbose=0;
  76. int Modem=0; /* MODEM - don't send pathnames */
  77. int Restricted=0; /* restricted; no /.. or ../ in filenames */
  78. int Quiet=0; /* overrides logic that would otherwise set verbose */
  79. int Ascii=0; /* Add CR's for brain damaged programs */
  80. int Fullname=0; /* transmit full pathname */
  81. int Unlinkafter=0; /* Unlink file after it is sent */
  82. int Dottoslash=0; /* Change foo.bar.baz to foo/bar/baz */
  83. int firstsec;
  84. int errcnt=0; /* number of files unreadable */
  85. int blklen=SECSIZ; /* length of transmitted records */
  86. int Optiong; /* Let it rip no wait for sector ACK's */
  87. int Noeofseen;
  88. int Totsecs; /* total number of sectors this file */
  89. char txbuf[KSIZE];
  90. int Filcnt=0; /* count of number of files opened */
  91. int Lfseen=0;
  92. unsigned Rxbuflen = 16384; /* Receiver's max buffer length */
  93. int Rxflags = 0;
  94. char Lzconv; /* Local ZMODEM file conversion request */
  95. char Lzmanag; /* Local ZMODEM file management request */
  96. char Lztrans;
  97. char zconv; /* ZMODEM file conversion request */
  98. char zmanag; /* ZMODEM file management request */
  99. char ztrans; /* ZMODEM file transport request */
  100. int Command; /* Send a command, then exit. */
  101. char *Cmdstr; /* Pointer to the command string */
  102. int Cmdtries = 11;
  103. int Cmdack1; /* Rx ACKs command, then do it */
  104. int Exitcode;
  105. int Testattn; /* Force receiver to send Attn, etc with qbf. */
  106. char *qbf="The quick brown fox jumped over the lazy dog's back 1234567890\r\n";
  107. //jmp_buf tohere; /* For the interrupt on RX timeout */
  108. //jmp_buf intrjmp; /* For the interrupt on RX CAN */
  109. /* called by signal interrupt or terminate to clean things up */
  110. bibi(n)
  111. {
  112. canit();
  113. //fflush(stdout);
  114. mode(0);
  115. //rt_kprintf(stderr, "sz: caught signal %d; exiting\n", n);
  116. //if (n == SIGQUIT)
  117. // abort();
  118. //exit(128+n);
  119. }
  120. /* Called when Zmodem gets an interrupt (^X) */
  121. onintr()
  122. {
  123. //signal(SIGINT, SIG_IGN);
  124. //longjmp(intrjmp, -1);
  125. }
  126. //#define sendline(c) putchar(c & Wcsmask)
  127. //#define xsendline(c) putchar(c)
  128. int sendline (int c)
  129. {
  130. c = c&Wcsmask;
  131. zwrite(c);
  132. }
  133. int xsendline(int c)
  134. {
  135. zwrite(c);
  136. }
  137. flushmo()
  138. {
  139. //fflush(stdout);
  140. }
  141. #include "zm.c"
  142. zsmain(argc, argv)
  143. char *argv[];
  144. {
  145. register char *cp;
  146. register npats;
  147. int agcnt; char **agcv;
  148. char **patts;
  149. static char xXbuf[BUFSIZ];
  150. //if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rsh")))
  151. // Restricted=TRUE;
  152. Rxtimeout = 600;
  153. npats=0;
  154. /*
  155. if (argc<2)
  156. usage();
  157. //setbuf(stdout, xXbuf);
  158. while (--argc) {
  159. cp = *++argv;
  160. if (*cp++ == '-' && *cp) {
  161. while ( *cp) {
  162. switch(*cp++) {
  163. case '+':
  164. Lzmanag = ZMAPND; break;
  165. case '1':
  166. iofd = 1; break;
  167. case '7':
  168. Wcsmask=0177; break;
  169. case 'a':
  170. Lzconv = ZCNL;
  171. Ascii = TRUE; break;
  172. case 'b':
  173. Lzconv = ZCBIN; break;
  174. case 'C':
  175. if (--argc < 1) {
  176. usage();
  177. }
  178. Cmdtries = atoi(*++argv);
  179. break;
  180. case 'i':
  181. Cmdack1 = ZCACK1;
  182. //* **** FALL THROUGH TO ****
  183. case 'c':
  184. if (--argc != 1) {
  185. usage();
  186. }
  187. Command = TRUE;
  188. Cmdstr = *++argv;
  189. break;
  190. case 'd':
  191. ++Dottoslash;
  192. //* **** FALL THROUGH TO **** *
  193. case 'f':
  194. Fullname=TRUE; break;
  195. case 'k':
  196. blklen=KSIZE; break;
  197. case 'N':
  198. Lzmanag = ZMCRC; break;
  199. case 'n':
  200. Lzmanag = ZMNEW; break;
  201. case 'r':
  202. Lzconv = ZCRESUM;
  203. case 'q':
  204. Quiet=TRUE; Verbose=0; break;
  205. case 'T':
  206. Testattn = TRUE; break;
  207. case 'u':
  208. ++Unlinkafter; break;
  209. case 'v':
  210. ++Verbose; break;
  211. case 'X':
  212. ++Modem; break;
  213. case 'y':
  214. Lzmanag = ZMCLOB; break;
  215. default:
  216. usage();
  217. }
  218. }
  219. }
  220. else if ( !npats && argc>0) {
  221. if (argv[0][0]) {
  222. npats=argc;
  223. patts=argv;
  224. if ( !strcmp(*patts, "-"))
  225. iofd = 1;
  226. }
  227. }
  228. }
  229. if (npats < 1 && !Command)
  230. usage();
  231. if (Verbose) {
  232. if (freopen(LOGFILE, "a", stderr)==NULL) {
  233. printf("Can't open log file %s\n",LOGFILE);
  234. exit(0200);
  235. }
  236. setbuf(stderr, NULL);
  237. }
  238. if (fromcu() && !Quiet) {
  239. if (Verbose == 0)
  240. Verbose = 2;
  241. }
  242. mode(1);
  243. // if (signal(SIGINT, bibi) == SIG_IGN) {
  244. // signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
  245. // }
  246. // else {
  247. // signal(SIGINT, bibi); signal(SIGKILL, bibi);
  248. // signal(SIGQUIT, bibi);
  249. // }
  250. if ( !Modem) {
  251. if (!Command) {
  252. printf("rz\r"); fflush(stdout);
  253. }
  254. if (!Command && !Quiet && Verbose != 1) {
  255. rt_kprintf(stderr, "sz: %d file%s requested:\r\n",
  256. npats, npats>1?"s":"");
  257. for ( agcnt=npats, agcv=patts; --agcnt>=0; ) {
  258. rt_kprintf(stderr, "%s ", *agcv++);
  259. }
  260. rt_kprintf(stderr, "\r\n");
  261. printf("\r\n\bSending in Batch Mode\r\n");
  262. }
  263. stohdr(0L);
  264. if (Command)
  265. Txhdr[ZF0] = ZCOMMAND;
  266. zshhdr(ZRQINIT, Txhdr);
  267. }
  268. fflush(stdout);
  269. */
  270. if (Command) {
  271. if (getzrxinit()) {
  272. Exitcode=0200; canit();
  273. }
  274. else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
  275. Exitcode=0200; canit();
  276. }
  277. } else if (wcsend(npats, patts)==ERROR) {
  278. Exitcode=0200;
  279. canit();
  280. }
  281. //fflush(stdout);
  282. //mode(0);
  283. //exit((errcnt != 0) | Exitcode);
  284. /*NOTREACHED*/
  285. }
  286. wcsend(argc, argp)
  287. char *argp[];
  288. {
  289. register n;
  290. Crcflg=FALSE;
  291. firstsec=TRUE;
  292. //for (n=0; n<argc; ++n) {
  293. Totsecs = 0;
  294. if (wcs(argp[n])==ERROR)
  295. return ERROR;
  296. //}
  297. Totsecs = 0;
  298. if (Filcnt==0) { /* bitch if we couldn't open ANY files */
  299. //rt_kprintf(stderr,"\r\nCan't open any requested files.\r\n");
  300. return ERROR;
  301. }
  302. if (Zmodem)
  303. saybibi();
  304. else
  305. wctxpn("");
  306. return OK;
  307. }
  308. wcs(oname)
  309. char *oname;
  310. {
  311. register c;
  312. register char *p;
  313. struct stat f;
  314. char name[PATHLEN];
  315. char *filename ="/tt2.txt";
  316. oname = filename;
  317. strcpy(name, oname);
  318. if (Restricted) {
  319. /* restrict pathnames to current tree or uucppublic */
  320. if ( substr(name, "../")
  321. || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
  322. canit();
  323. //rt_kprintf(stderr,"\r\nsz:\tSecurity Violation\r\n");
  324. return ERROR;
  325. }
  326. }
  327. //if ( !strcmp(oname, "-")) {
  328. // if ((p = getenv("ONAME")) && *p)
  329. // strcpy(name, p);
  330. //else
  331. //sprintf(name, "s%d.sz", getpid());
  332. /////////////////////////////////////////////////////////////////////////////////////////////////
  333. //in = stdin;
  334. // }
  335. //else if ((in=fopen(oname, "r"))==NULL) {
  336. // ++errcnt;
  337. //return OK; /* pass over it, there may be others */
  338. //}
  339. if ((in=open(oname, DFS_O_RDONLY,0)) <0)
  340. {
  341. ++errcnt;
  342. return OK;
  343. }
  344. ++Noeofseen;
  345. /* Check for directory or block special files */
  346. fstat(in, &f);
  347. c = f.st_mode & S_IFMT;
  348. if (c == S_IFDIR || c == S_IFBLK) {
  349. close(in);
  350. return OK;
  351. }
  352. ++Filcnt;
  353. switch (wctxpn(name)) {
  354. case ERROR:
  355. return ERROR;
  356. case ZSKIP:
  357. return OK;
  358. }
  359. if (!Zmodem && wctx()==ERROR)
  360. return ERROR;
  361. if (Unlinkafter)
  362. unlink(oname);
  363. return 0;
  364. }
  365. /*
  366. * generate and transmit pathname block consisting of
  367. * pathname (null terminated),
  368. * file length, mode time and file mode in octal
  369. * as provided by the Unix fstat call.
  370. * N.B.: modifies the passed name, may extend it!
  371. */
  372. wctxpn(name)
  373. char *name;
  374. {
  375. register char *p, *q;
  376. char name2[PATHLEN];
  377. struct stat f;
  378. if (Modem) {
  379. //if ((in!=stdin) && *name && fstat(fileno(in), &f)!= -1) {
  380. // rt_kprintf(stderr, "Sending %s, %ld blocks: ",
  381. // name, f.st_size>>7);
  382. //}
  383. //rt_kprintf(stderr, "Give your local XMODEM receive command now.\r\n");
  384. return OK;
  385. }
  386. logent("\r\nAwaiting pathname nak for %s\r\n", *name?name:"<END>");
  387. if ( !Zmodem)
  388. if (getnak())
  389. return ERROR;
  390. q = (char *) 0;
  391. if (Dottoslash) { /* change . to . */
  392. for (p=name; *p; ++p) {
  393. if (*p == '/')
  394. q = p;
  395. else if (*p == '.')
  396. *(q=p) = '/';
  397. }
  398. if (q && strlen(++q) > 8) { /* If name>8 chars */
  399. q += 8; /* make it .ext */
  400. strcpy(name2, q); /* save excess of name */
  401. *q = '.';
  402. strcpy(++q, name2); /* add it back */
  403. }
  404. }
  405. for (p=name, q=txbuf ; *p; )
  406. if ((*q++ = *p++) == '/' && !Fullname)
  407. q = txbuf;
  408. *q++ = 0;
  409. p=q;
  410. while (q < (txbuf + KSIZE))
  411. *q++ = 0;
  412. //if (!Ascii && (in!=stdin) && *name && fstat(fileno(in), &f)!= -1)
  413. //sprintf(p, "%lu %lo %o", f.st_size, f.st_mtime, f.st_mode);
  414. fstat(in,&f);
  415. /* force 1k blocks if name won't fit in 128 byte block */
  416. if (txbuf[125])
  417. blklen=KSIZE;
  418. else { /* A little goodie for IMP/KMD */
  419. if (Zmodem)
  420. blklen = SECSIZ;
  421. txbuf[127] = f.st_size >>7;
  422. txbuf[126] = f.st_size >>15;
  423. }
  424. if (Zmodem)
  425. return zsendfile(txbuf, 1+strlen(p)+(p-txbuf));
  426. if (wcputsec(txbuf, 0, SECSIZ)==ERROR)
  427. return ERROR;
  428. return OK;
  429. }
  430. getnak()
  431. {
  432. register firstch;
  433. Lastrx = 0;
  434. for (;;) {
  435. switch (firstch = readock(800,1)) {
  436. case ZPAD:
  437. if (getzrxinit())
  438. return ERROR;
  439. Ascii = 0;
  440. return FALSE;
  441. case TIMEOUT:
  442. logent("Timeout on pathname\n");
  443. return TRUE;
  444. case WANTG:
  445. mode(2); /* Set cbreak, XON/XOFF, etc. */
  446. Optiong = TRUE;
  447. blklen=KSIZE;
  448. case WANTCRC:
  449. Crcflg = TRUE;
  450. case NAK:
  451. return FALSE;
  452. case CAN:
  453. if (Lastrx == CAN)
  454. return TRUE;
  455. default:
  456. break;
  457. }
  458. Lastrx = firstch;
  459. }
  460. }
  461. wctx()
  462. {
  463. register int sectnum, attempts, firstch;
  464. firstsec=TRUE;
  465. while ((firstch=readock(400, 2))!=NAK && firstch != WANTCRC
  466. && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN)
  467. ;
  468. if (firstch==CAN) {
  469. logent("Receiver CANcelled\n");
  470. return ERROR;
  471. }
  472. if (firstch==WANTCRC)
  473. Crcflg=TRUE;
  474. if (firstch==WANTG)
  475. Crcflg=TRUE;
  476. sectnum=1;
  477. while (filbuf(txbuf, blklen)) {
  478. if (wcputsec(txbuf, sectnum, blklen)==ERROR) {
  479. return ERROR;
  480. } else
  481. sectnum++;
  482. }
  483. //if (Verbose>1)
  484. // rt_kprintf(stderr, " Closing ");
  485. close(in);
  486. attempts=0;
  487. do {
  488. logent(" EOT ");
  489. purgeline();
  490. sendline(EOT);
  491. //fflush(stdout);
  492. ++attempts;
  493. }
  494. while ((firstch=(readock(100, 1)) != ACK) && attempts < RETRYMAX);
  495. if (attempts == RETRYMAX) {
  496. logent("No ACK on EOT\n");
  497. return ERROR;
  498. }
  499. else
  500. return OK;
  501. }
  502. wcputsec(buf, sectnum, cseclen)
  503. char *buf;
  504. int sectnum;
  505. int cseclen; /* data length of this sector to send */
  506. {
  507. register checksum, wcj;
  508. register char *cp;
  509. unsigned oldcrc;
  510. int firstch;
  511. int attempts;
  512. firstch=0; /* part of logic to detect CAN CAN */
  513. //if (Verbose>1)
  514. // rt_kprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs/8 );
  515. for (attempts=0; attempts <= RETRYMAX; attempts++) {
  516. Lastrx= firstch;
  517. sendline(cseclen==KSIZE?STX:SOH);
  518. sendline(sectnum);
  519. sendline(-sectnum -1);
  520. oldcrc=checksum=0;
  521. for (wcj=cseclen,cp=buf; --wcj>=0; ) {
  522. sendline(*cp);
  523. oldcrc=updcrc(*cp, oldcrc);
  524. checksum += *cp++;
  525. }
  526. if (Crcflg) {
  527. oldcrc=updcrc(0,updcrc(0,oldcrc));
  528. sendline((int)oldcrc>>8);
  529. sendline((int)oldcrc);
  530. }
  531. else
  532. sendline(checksum);
  533. if (Optiong) {
  534. firstsec = FALSE; return OK;
  535. }
  536. firstch = readock(400, (Noeofseen&&sectnum) ? 2:1);
  537. gotnak:
  538. switch (firstch) {
  539. case CAN:
  540. if(Lastrx == CAN) {
  541. cancan:
  542. logent("Cancelled\n"); return ERROR;
  543. }
  544. break;
  545. case TIMEOUT:
  546. logent("Timeout on sector ACK\n"); continue;
  547. case WANTCRC:
  548. if (firstsec)
  549. Crcflg = TRUE;
  550. case NAK:
  551. logent("NAK on sector\n"); continue;
  552. case ACK:
  553. firstsec=FALSE;
  554. Totsecs += (cseclen>>7);
  555. return OK;
  556. case ERROR:
  557. logent("Got burst for sector ACK\n"); break;
  558. default:
  559. logent("Got %02x for sector ACK\n", firstch); break;
  560. }
  561. for (;;) {
  562. Lastrx = firstch;
  563. if ((firstch = readock(400, 2)) == TIMEOUT)
  564. break;
  565. if (firstch == NAK || firstch == WANTCRC)
  566. goto gotnak;
  567. if (firstch == CAN && Lastrx == CAN)
  568. goto cancan;
  569. }
  570. }
  571. logent("Retry Count Exceeded\n");
  572. return ERROR;
  573. }
  574. /* fill buf with count chars padding with ^Z for CPM */
  575. filbuf(buf, count)
  576. register char *buf;
  577. {
  578. register c, m;
  579. if ( !Ascii) {
  580. m = read(in, buf, count);
  581. if (m <= 0)
  582. return 0;
  583. while (m < count)
  584. buf[m++] = 032;
  585. return count;
  586. }
  587. m=count;
  588. if (Lfseen) {
  589. *buf++ = 012; --m; Lfseen = 0;
  590. }
  591. /////////////////////////////////////////////////////////////////////////////////////
  592. /*
  593. while ((c=getc(in))!=EOF) {
  594. if (c == 012) {
  595. *buf++ = 015;
  596. if (--m == 0) {
  597. Lfseen = TRUE; break;
  598. }
  599. }
  600. *buf++ =c;
  601. if (--m == 0)
  602. break;
  603. }
  604. */
  605. if (m==count)
  606. return 0;
  607. else
  608. while (--m>=0)
  609. *buf++ = CPMEOF;
  610. return count;
  611. }
  612. /* fill buf with count chars */
  613. zfilbuf(buf, count)
  614. register char *buf;
  615. { //int read(int fd, void *buf, size_t len)
  616. int c, m;
  617. int res;
  618. m=count;
  619. res = 0;
  620. while (1) {
  621. res = read(in,&c,1);
  622. if (res == 0) break;
  623. *buf++ =c;
  624. res = 0;
  625. if (--m == 0)
  626. break;
  627. }
  628. return (count - m);
  629. }
  630. /* VARARGS1 */
  631. vfile(f, a, b, c)
  632. register char *f;
  633. {
  634. // if (Verbose > 1) {
  635. // rt_kprintf(stderr, f, a, b, c);
  636. // rt_kprintf(stderr, "\n");
  637. // }
  638. }
  639. alarm()
  640. {
  641. //longjmp(tohere, -1);
  642. }
  643. /*
  644. * readock(timeout, count) reads character(s) from file descriptor 0
  645. * (1 <= count <= 3)
  646. * it attempts to read count characters. If it gets more than one,
  647. * it is an error unless all are CAN
  648. * (otherwise, only normal response is ACK, CAN, or C)
  649. * Only looks for one if Optiong, which signifies cbreak, not raw input
  650. *
  651. * timeout is in tenths of seconds
  652. */
  653. readock(timeout, count)
  654. {
  655. register int c;
  656. static char byt[5];
  657. int ch;
  658. if (Optiong)
  659. count = 1; /* Special hack for cbreak */
  660. //fflush(stdout);
  661. //if (setjmp(tohere)) {
  662. // logent("TIMEOUT\n");
  663. // return TIMEOUT;
  664. //}
  665. c = 0;
  666. while (1)
  667. {
  668. c = zread(shell->device, 0, byt, 1);
  669. if (c > 0) break;
  670. }
  671. //if (Verbose>5)
  672. // rt_kprintf(stderr, "ret cnt=%d %x %x\n", c, byt[0], byt[1]);
  673. if (c<1)
  674. return TIMEOUT;
  675. if (c==1)
  676. return (byt[0]&0377);
  677. else
  678. while (c)
  679. if (byt[--c] != CAN)
  680. return ERROR;
  681. return CAN;
  682. }
  683. readline(n)
  684. {
  685. return (readock(n, 1));
  686. }
  687. purgeline()
  688. {
  689. #ifdef USG
  690. ioctl(iofd, TCFLSH, 0);
  691. #else
  692. lseek(iofd, 0L, 2);
  693. #endif
  694. }
  695. /* update CRC */
  696. unsigned
  697. updcrc(c, crc)
  698. register c;
  699. register unsigned crc;
  700. {
  701. register count;
  702. for (count=8; --count>=0;) {
  703. if (crc & 0x8000) {
  704. crc <<= 1;
  705. crc += (((c<<=1) & 0400) != 0);
  706. crc ^= 0x1021;
  707. }
  708. else {
  709. crc <<= 1;
  710. crc += (((c<<=1) & 0400) != 0);
  711. }
  712. }
  713. return crc;
  714. }
  715. /* send cancel string to get the other end to shut up */
  716. canit()
  717. {
  718. static char canistr[] = {
  719. ZPAD,ZPAD,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
  720. };
  721. //printf(canistr);
  722. //fflush(stdout);
  723. }
  724. /*VARARGS1*/
  725. logent(a, b, c)
  726. char *a, *b, *c;
  727. {
  728. // if(Verbose)
  729. // rt_kprintf(stderr, a, b, c);
  730. }
  731. /*
  732. * return 1 iff stdout and stderr are different devices
  733. * indicating this program operating with a modem on a
  734. * different line
  735. */
  736. fromcu()
  737. {
  738. struct stat a, b;
  739. fstat(1, &a); fstat(2, &b);
  740. // return (a.st_rdev != b.st_rdev);
  741. }
  742. /*
  743. * substr(string, token) searches for token in string s
  744. * returns pointer to token within string if found, NULL otherwise
  745. */
  746. char *
  747. substr(s, t)
  748. register char *s,*t;
  749. {
  750. register char *ss,*tt;
  751. /* search for first char of token */
  752. for (ss=s; *s; s++)
  753. if (*s == *t)
  754. /* compare token with substring */
  755. for (ss=s,tt=t; ;) {
  756. if (*tt == 0)
  757. return s;
  758. if (*ss++ != *tt++)
  759. break;
  760. }
  761. return NULL;
  762. }
  763. usage()
  764. {
  765. }
  766. /*
  767. * Get the receiver's init parameters
  768. */
  769. getzrxinit()
  770. {
  771. register n;
  772. struct stat f;
  773. for (n=10; --n>=0; ) {
  774. switch (zgethdr(Rxhdr, 1)) {
  775. case ZCHALLENGE: /* Echo receiver's challenge numbr */
  776. stohdr(Rxpos);
  777. zshhdr(ZACK, Txhdr);
  778. continue;
  779. case ZCOMMAND: /* They didn't see out ZRQINIT */
  780. stohdr(0L);
  781. zshhdr(ZRQINIT, Txhdr);
  782. continue;
  783. case ZRINIT:
  784. Rxflags = Rxhdr[ZF0];
  785. Rxbuflen = Rxhdr[ZP0] + (Rxhdr[ZP1]<<8);
  786. //signal(SIGINT, SIG_IGN);
  787. mode(2); /* Set cbreak, XON/XOFF, etc. */
  788. /* If using a pipe for testing set lower buf len */
  789. fstat(iofd, &f);
  790. if ((f.st_mode & S_IFMT) != S_IFCHR
  791. && (Rxbuflen == 0 || Rxbuflen > 4096))
  792. Rxbuflen = 4096;
  793. /*
  794. * If input is not a regular file, force ACK's each 1024
  795. * (A smarter strategey could be used here ...)
  796. */
  797. fstat(in, &f);
  798. if (((f.st_mode & S_IFMT) != S_IFREG)
  799. && (Rxbuflen == 0 || Rxbuflen > 1024))
  800. Rxbuflen = 1024;
  801. return (sendzsinit());
  802. case ZCAN:
  803. case TIMEOUT:
  804. return ERROR;
  805. case ZRQINIT:
  806. if (Rxhdr[ZF0] == ZCOMMAND)
  807. continue;
  808. default:
  809. zshhdr(ZNAK, Txhdr);
  810. continue;
  811. }
  812. }
  813. return ERROR;
  814. }
  815. /* Send send-init information */
  816. sendzsinit()
  817. {
  818. register c;
  819. register errors;
  820. errors = 0;
  821. for (;;) {
  822. stohdr(0L);
  823. zsbhdr(ZSINIT, Txhdr);
  824. zsbdata(Myattn, 1+strlen(Myattn), ZCRCW);
  825. c = zgethdr(Rxhdr, 1);
  826. switch (c) {
  827. case ZCAN:
  828. return ERROR;
  829. case ZACK:
  830. return OK;
  831. default:
  832. if (++errors > 9)
  833. return ERROR;
  834. continue;
  835. }
  836. }
  837. }
  838. /* Send file name and related info */
  839. zsendfile(buf, blen)
  840. char *buf;
  841. {
  842. register c;
  843. for (;;) {
  844. Txhdr[ZF0] = Lzconv; /* file conversion request */
  845. Txhdr[ZF1] = Lzmanag; /* file management request */
  846. Txhdr[ZF2] = Lztrans; /* file transport request */
  847. Txhdr[ZF3] = 0;
  848. zsbhdr(ZFILE, Txhdr);
  849. zsbdata(buf, blen, ZCRCW);
  850. again:
  851. c = zgethdr(Rxhdr, 1);
  852. switch (c) {
  853. case ZRINIT:
  854. goto again;
  855. case ZCAN:
  856. case TIMEOUT:
  857. case ZABORT:
  858. case ZFIN:
  859. return ERROR;
  860. case ZSKIP:
  861. close(in); return c;
  862. case ZRPOS:
  863. lseek(in, Rxpos, 0);
  864. Txpos = Rxpos;
  865. return zsendfdata();
  866. case ERROR:
  867. default:
  868. continue;
  869. }
  870. }
  871. }
  872. /* Send the data in the file */
  873. zsendfdata()
  874. {
  875. register c, e;
  876. register newcnt;
  877. register long tcount = 0;
  878. static int tleft = 6; /* Counter for test mode */
  879. if (Baudrate > 300)
  880. blklen = 256;
  881. if (Baudrate > 2400)
  882. blklen = KSIZE;
  883. if (Rxbuflen && blklen>Rxbuflen)
  884. blklen = Rxbuflen;
  885. somemore:
  886. //if (setjmp(intrjmp)) {
  887. waitack:
  888. // switch (c = getinsync()) {
  889. // default:
  890. // case ZCAN:
  891. // close(in);
  892. // return ERROR;
  893. // case ZSKIP:
  894. // close(in);
  895. // return c;
  896. // case ZACK:
  897. // case ZRPOS:
  898. // break;
  899. // }
  900. // }
  901. //signal(SIGINT, onintr);
  902. newcnt = Rxbuflen;
  903. stohdr(Txpos);
  904. zsbhdr(ZDATA, Txhdr);
  905. /*
  906. * Special testing mode. This should force receiver to Attn,ZRPOS
  907. * many times. Each time the signal should be caught, causing the
  908. * file to be started over from the beginning.
  909. */
  910. if (Testattn) {
  911. if ( --tleft)
  912. while (tcount < 20000) {
  913. //printf(qbf);
  914. //fflush(stdout);
  915. tcount += strlen(qbf);
  916. }
  917. //signal(SIGINT, SIG_IGN);
  918. canit();
  919. //sleep(3);
  920. purgeline(); mode(0);
  921. //printf("\nsz: Tcount = %ld\n", tcount);
  922. if (tleft) {
  923. //printf("ERROR: Interrupts Not Caught\n");
  924. //exit(1);
  925. }
  926. //exit(0);
  927. }
  928. do {
  929. c = zfilbuf(txbuf, blklen);
  930. if (c < blklen)
  931. e = ZCRCE;
  932. else if (Rxbuflen && (newcnt -= c) <= 0)
  933. e = ZCRCW;
  934. else
  935. e = ZCRCG;
  936. zsbdata(txbuf, c, e);
  937. Txpos += c;
  938. if (e == ZCRCW)
  939. goto waitack;
  940. #ifdef NOTDEF_DOS
  941. if ( !carrier()) {
  942. return ERROR;
  943. }
  944. /*
  945. * If the reverse channel can be tested for data,
  946. * this logic may be used to detect error packets
  947. * sent by the receiver, in place of setjmp/longjmp
  948. * miready() returns non 0 if a character is available
  949. */
  950. while (miready()) {
  951. if (readline(1) == ZPAD) {
  952. zsbdata(U.ubuf, 0, ZCRCW);
  953. goto somemore;
  954. }
  955. }
  956. #endif
  957. } while (c == blklen);
  958. //signal(SIGINT, SIG_IGN);
  959. for (;;) {
  960. stohdr(Txpos);
  961. zsbhdr(ZEOF, Txhdr);
  962. switch (getinsync()) {
  963. case ZRPOS:
  964. goto somemore;
  965. case ZRINIT:
  966. close(in);
  967. return OK;
  968. case ZSKIP:
  969. close(in);
  970. return c;
  971. default:
  972. close(in);
  973. return ERROR;
  974. }
  975. }
  976. }
  977. /*
  978. * Respond to receiver's complaint, get back in sync with receiver
  979. */
  980. getinsync()
  981. {
  982. register c;
  983. for (;;) {
  984. if (Testattn) {
  985. //printf("\r\n\n\n***** Signal Caught *****\r\n");
  986. Rxpos = 0; c = ZRPOS;
  987. } else
  988. c = zgethdr(Rxhdr, 0);
  989. switch (c) {
  990. case ZCAN:
  991. case ZABORT:
  992. case ZFIN:
  993. case TIMEOUT:
  994. return ERROR;
  995. case ZRPOS:
  996. //clearerr(in); /* In case file EOF seen */
  997. lseek(in, Rxpos, 0);
  998. Txpos = Rxpos;
  999. return c;
  1000. case ZACK:
  1001. return c;
  1002. case ZRINIT:
  1003. case ZSKIP:
  1004. close(in);
  1005. return c;
  1006. case ERROR:
  1007. default:
  1008. zsbhdr(ZNAK, Txhdr);
  1009. continue;
  1010. }
  1011. }
  1012. }
  1013. /* Say "bibi" to the receiver, try to do it cleanly */
  1014. saybibi()
  1015. {
  1016. for (;;) {
  1017. stohdr(0L);
  1018. zsbhdr(ZFIN, Txhdr);
  1019. switch (zgethdr(Rxhdr, 0)) {
  1020. case ZFIN:
  1021. sendline('O'); sendline('O'); flushmo();
  1022. case ZCAN:
  1023. case TIMEOUT:
  1024. return;
  1025. }
  1026. }
  1027. }
  1028. /* Local screen character display function */
  1029. bttyout(c)
  1030. {
  1031. //if (Verbose)
  1032. // putc(c, stderr);
  1033. }
  1034. /* Send command and related info */
  1035. zsendcmd(buf, blen)
  1036. char *buf;
  1037. {
  1038. register c, errors;
  1039. long cmdnum;
  1040. // cmdnum = getpid();
  1041. errors = 0;
  1042. for (;;) {
  1043. stohdr(cmdnum);
  1044. Txhdr[ZF0] = Cmdack1;
  1045. zsbhdr(ZCOMMAND, Txhdr);
  1046. zsbdata(buf, blen, ZCRCW);
  1047. listen:
  1048. Rxtimeout = 100; /* Ten second wait for resp. */
  1049. c = zgethdr(Rxhdr, 1);
  1050. switch (c) {
  1051. case ZRINIT:
  1052. continue;
  1053. case ERROR:
  1054. case TIMEOUT:
  1055. if (++errors > Cmdtries)
  1056. return ERROR;
  1057. continue;
  1058. case ZCAN:
  1059. case ZABORT:
  1060. case ZFIN:
  1061. case ZSKIP:
  1062. case ZRPOS:
  1063. return ERROR;
  1064. default:
  1065. if (++errors > 10)
  1066. return ERROR;
  1067. continue;
  1068. case ZCOMPL:
  1069. Exitcode = Rxpos;
  1070. saybibi();
  1071. return OK;
  1072. case ZRQINIT:
  1073. vfile("******** RZ *******");
  1074. system("rz");
  1075. vfile("******** SZ *******");
  1076. goto listen;
  1077. }
  1078. }
  1079. }