Improve the process for GNU tools
[minix3.git] / minix / commands / zmodem / sz.c
blobcc256d6f15bb68c61f4b423ea07d7499e5bed5bd
1 #define VERSION "sz 2.12 05-29-88"
2 #define PUBDIR "/usr/spool/uucppublic"
4 /*% cc -compat -M2 -Ox -K -i -DTXBSIZE=16384 -DNFGVMIN -DREADCHECK sz.c -lx -o sz; size sz
6 Following is used for testing, might not be reasonable for production
7 <-xtx-*> cc -Osal -DTXBSIZE=32768 -DSV sz.c -lx -o $B/sz; size $B/sz
9 ****************************************************************************
11 * sz.c By Chuck Forsberg, Omen Technology INC
13 ****************************************************************************
15 * Typical Unix/Xenix/Clone compiles:
17 * cc -O sz.c -o sz USG (SYS III/V) Unix
18 * cc -O -DSV sz.c -o sz Sys V Release 2 with non-blocking input
19 * Define to allow reverse channel checking
20 * cc -O -DV7 sz.c -o sz Unix Version 7, 2.8 - 4.3 BSD
22 * cc -O -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz Classic Xenix
24 * ln sz sb **** All versions ****
25 * ln sz sx **** All versions ****
27 ****************************************************************************
29 * Typical VMS compile and install sequence:
31 * define LNK$LIBRARY SYS$LIBRARY:VAXCRTL.OLB
32 * cc sz.c
33 * cc vvmodem.c
34 * link sz,vvmodem
35 * sz :== $disk$user2:[username.subdir]sz.exe
37 * If you feel adventureous, remove the #define BADSYNC line
38 * immediately following the #ifdef vax11c line! Some VMS
39 * systems know how to fseek, some don't.
41 ****************************************************************************
44 * A program for Unix to send files and commands to computers running
45 * Professional-YAM, PowerCom, YAM, IMP, or programs supporting Y/XMODEM.
47 * Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM.
49 * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
51 * 2.1x hacks to avoid VMS fseek() bogosity, allow input from pipe
52 * -DBADSEEK -DTXBSIZE=32768
53 * 2.x has mods for VMS flavor
55 * 1.34 implements tx backchannel garbage count and ZCRCW after ZRPOS
56 * in accordance with the 7-31-87 ZMODEM Protocol Description
60 #include <sys/types.h>
62 #ifdef vax11c
63 #define BADSEEK
64 #define TXBSIZE 32768 /* Must be power of two, < MAXINT */
65 #include <types.h>
66 #include <stat.h>
67 #define LOGFILE "szlog.tmp"
68 #define OS "VMS"
69 #define READCHECK
70 #define BUFWRITE
71 #define iofd
72 extern int errno;
73 #define SS_NORMAL SS$_NORMAL
74 #define xsendline(c) sendline(c)
77 #else /* vax11c */
80 #define SS_NORMAL 0
81 #define LOGFILE "/tmp/szlog"
83 #define sendline(c) putchar((c) & 0377)
84 #define xsendline(c) putchar(c)
86 #endif
88 #include <signal.h>
89 #include <setjmp.h>
90 #include <ctype.h>
91 #include <errno.h>
92 #include <stdlib.h>
93 #include <string.h>
94 #include <stdlib.h>
95 #include <unistd.h>
96 #include <utime.h>
97 #include <stdio.h>
98 #include <stdarg.h>
100 #define PATHLEN 256
101 #define OK 0
102 #define FALSE 0
103 #define TRUE 1
104 #undef ERROR
105 #define ERROR (-1)
106 /* Ward Christensen / CP/M parameters - Don't change these! */
107 #define ENQ 005
108 #define CAN ('X'&037)
109 #define XOFF ('s'&037)
110 #define XON ('q'&037)
111 #define SOH 1
112 #define STX 2
113 #define EOT 4
114 #define ACK 6
115 #define NAK 025
116 #define CPMEOF 032
117 #define WANTCRC 0103 /* send C not NAK to get crc not checksum */
118 #define WANTG 0107 /* Send G not NAK to get nonstop batch xmsn */
119 #define TIMEOUT (-2)
120 #define RCDO (-3)
121 #define RETRYMAX 10
124 #define HOWMANY 2
125 int Zmodem=0; /* ZMODEM protocol requested by receiver */
126 unsigned Baudrate=2400; /* Default, should be set by first mode() call */
127 unsigned Txwindow; /* Control the size of the transmitted window */
128 unsigned Txwspac; /* Spacing between zcrcq requests */
129 unsigned Txwcnt; /* Counter used to space ack requests */
130 long Lrxpos; /* Receiver's last reported offset */
131 int errors;
133 #ifdef vax11c
134 #include "vrzsz.c" /* most of the system dependent stuff here */
135 #else
136 #include "rbsb.c" /* most of the system dependent stuff here */
137 #endif
138 #include "crctab.c"
140 int Filesleft;
141 long Totalleft;
144 * Attention string to be executed by receiver to interrupt streaming data
145 * when an error is detected. A pause (0336) may be needed before the
146 * ^C (03) or after it.
148 #ifdef READCHECK
149 char Myattn[] = { 0 };
150 #else
151 #ifdef USG
152 char Myattn[] = { 03, 0336, 0 };
153 #else
154 char Myattn[] = { 0 };
155 #endif
156 #endif
158 FILE *in;
160 #ifdef BADSEEK
161 int Canseek = 0; /* 1: Can seek 0: only rewind -1: neither (pipe) */
162 #ifndef TXBSIZE
163 #define TXBSIZE 16384 /* Must be power of two, < MAXINT */
164 #endif
165 #else
166 int Canseek = 1; /* 1: Can seek 0: only rewind -1: neither (pipe) */
167 #endif
169 #ifdef TXBSIZE
170 #define TXBMASK (TXBSIZE-1)
171 char Txb[TXBSIZE]; /* Circular buffer for file reads */
172 char *txbuf = Txb; /* Pointer to current file segment */
173 #else
174 char txbuf[1024];
175 #endif
176 long vpos = 0; /* Number of bytes read from file */
178 char Lastrx;
179 char Crcflg;
180 int Verbose=0;
181 int Modem2=0; /* XMODEM Protocol - don't send pathnames */
182 int Restricted=0; /* restricted; no /.. or ../ in filenames */
183 int Quiet=0; /* overrides logic that would otherwise set verbose */
184 int Ascii=0; /* Add CR's for brain damaged programs */
185 int Fullname=0; /* transmit full pathname */
186 int Unlinkafter=0; /* Unlink file after it is sent */
187 int Dottoslash=0; /* Change foo.bar.baz to foo/bar/baz */
188 int firstsec;
189 int errcnt=0; /* number of files unreadable */
190 int blklen=128; /* length of transmitted records */
191 int Optiong; /* Let it rip no wait for sector ACK's */
192 int Eofseen; /* EOF seen on input set by zfilbuf */
193 int BEofseen; /* EOF seen on input set by fooseek */
194 int Totsecs; /* total number of sectors this file */
195 int Filcnt=0; /* count of number of files opened */
196 int Lfseen=0;
197 unsigned Rxbuflen = 16384; /* Receiver's max buffer length */
198 int Tframlen = 0; /* Override for tx frame length */
199 int blkopt=0; /* Override value for zmodem blklen */
200 int Rxflags = 0;
201 long bytcnt;
202 int Wantfcs32 = TRUE; /* want to send 32 bit FCS */
203 char Lzconv; /* Local ZMODEM file conversion request */
204 char Lzmanag; /* Local ZMODEM file management request */
205 int Lskipnocor;
206 char Lztrans;
207 char zconv; /* ZMODEM file conversion request */
208 char zmanag; /* ZMODEM file management request */
209 char ztrans; /* ZMODEM file transport request */
210 int Command; /* Send a command, then exit. */
211 char *Cmdstr; /* Pointer to the command string */
212 int Cmdtries = 11;
213 int Cmdack1; /* Rx ACKs command, then do it */
214 int Exitcode = 0;
215 int Test; /* 1= Force receiver to send Attn, etc with qbf. */
216 /* 2= Character transparency test */
217 char *qbf="The quick brown fox jumped over the lazy dog's back 1234567890\r\n";
218 long Lastsync; /* Last offset to which we got a ZRPOS */
219 int Beenhereb4; /* How many times we've been ZRPOS'd same place */
221 jmp_buf tohere; /* For the interrupt on RX timeout */
222 jmp_buf intrjmp; /* For the interrupt on RX CAN */
224 void onintr(int sig );
225 int main(int argc , char *argv []);
226 int wcsend(int argc , char *argp []);
227 int wcs(char *oname );
228 int wctxpn(char *name );
229 int getnak(void);
230 int wctx(long flen );
231 int wcputsec(char *buf , int sectnum , int cseclen );
232 int filbuf(char *buf , int count );
233 int zfilbuf(void);
234 int fooseek(FILE *fptr , long pos , int whence );
235 void alrm(int sig );
236 int readline(int timeout );
237 void flushmo(void);
238 void purgeline(void);
239 void canit(void);
240 void zperr();
241 char *substr(char *s , char *t );
242 int usage(void);
243 int getzrxinit(void);
244 int sendzsinit(void);
245 int zsendfile(char *buf , int blen );
246 int zsendfdata(void);
247 int getinsync(int flag );
248 void saybibi(void);
249 void bttyout(int c );
250 int zsendcmd(char *buf , int blen );
251 void chkinvok(char *s );
252 void countem(int argc , char **argv );
253 void chartest(int m );
255 /* called by signal interrupt or terminate to clean things up */
256 void bibi(int n)
258 canit(); fflush(stdout); mode(0);
259 fprintf(stderr, "sz: caught signal %d; exiting\n", n);
260 if (n == SIGQUIT)
261 abort();
262 if (n == 99)
263 fprintf(stderr, "mode(2) in rbsb.c not implemented!!\n");
264 cucheck();
265 exit(128+n);
267 /* Called when ZMODEM gets an interrupt (^X) */
268 void onintr(int sig)
270 signal(SIGINT, SIG_IGN);
271 longjmp(intrjmp, -1);
274 int Zctlesc; /* Encode control characters */
275 int Nozmodem = 0; /* If invoked as "sb" */
276 char *Progname = "sz";
277 int Zrwindow = 1400; /* RX window size (controls garbage count) */
278 #include "zm.c"
281 int main(int argc, char *argv[])
283 register char *cp;
284 register int npats;
285 int dm;
286 char **patts;
287 static char xXbuf[BUFSIZ];
289 if ((cp = getenv("ZNULLS")) && *cp)
290 Znulls = atoi(cp);
291 if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
292 Restricted=TRUE;
293 from_cu();
294 chkinvok(argv[0]);
296 Rxtimeout = 600;
297 npats=0;
298 if (argc<2)
299 usage();
300 setbuf(stdout, xXbuf);
301 while (--argc) {
302 cp = *++argv;
303 if (*cp++ == '-' && *cp) {
304 while ( *cp) {
305 switch(*cp++) {
306 case '\\':
307 *cp = toupper(*cp); continue;
308 case '+':
309 Lzmanag = ZMAPND; break;
310 #ifdef CSTOPB
311 case '2':
312 Twostop = TRUE; break;
313 #endif
314 case 'a':
315 Lzconv = ZCNL;
316 Ascii = TRUE; break;
317 case 'b':
318 Lzconv = ZCBIN; break;
319 case 'C':
320 if (--argc < 1) {
321 usage();
323 Cmdtries = atoi(*++argv);
324 break;
325 case 'i':
326 Cmdack1 = ZCACK1;
327 /* **** FALL THROUGH TO **** */
328 case 'c':
329 if (--argc != 1) {
330 usage();
332 Command = TRUE;
333 Cmdstr = *++argv;
334 break;
335 case 'd':
336 ++Dottoslash;
337 /* **** FALL THROUGH TO **** */
338 case 'f':
339 Fullname=TRUE; break;
340 case 'e':
341 Zctlesc = 1; break;
342 case 'k':
343 blklen=1024; break;
344 case 'L':
345 if (--argc < 1) {
346 usage();
348 blkopt = atoi(*++argv);
349 if (blkopt<24 || blkopt>1024)
350 usage();
351 break;
352 case 'l':
353 if (--argc < 1) {
354 usage();
356 Tframlen = atoi(*++argv);
357 if (Tframlen<32 || Tframlen>1024)
358 usage();
359 break;
360 case 'N':
361 Lzmanag = ZMNEWL; break;
362 case 'n':
363 Lzmanag = ZMNEW; break;
364 case 'o':
365 Wantfcs32 = FALSE; break;
366 case 'p':
367 Lzmanag = ZMPROT; break;
368 case 'r':
369 Lzconv = ZCRESUM;
370 case 'q':
371 Quiet=TRUE; Verbose=0; break;
372 case 't':
373 if (--argc < 1) {
374 usage();
376 Rxtimeout = atoi(*++argv);
377 if (Rxtimeout<10 || Rxtimeout>1000)
378 usage();
379 break;
380 case 'T':
381 if (++Test > 1) {
382 chartest(1); chartest(2);
383 mode(0); exit(0);
385 break;
386 #ifndef vax11c
387 case 'u':
388 ++Unlinkafter; break;
389 #endif
390 case 'v':
391 ++Verbose; break;
392 case 'w':
393 if (--argc < 1) {
394 usage();
396 Txwindow = atoi(*++argv);
397 if (Txwindow < 256)
398 Txwindow = 256;
399 Txwindow = (Txwindow/64) * 64;
400 Txwspac = Txwindow/4;
401 if (blkopt > Txwspac
402 || (!blkopt && Txwspac < 1024))
403 blkopt = Txwspac;
404 break;
405 case 'X':
406 ++Modem2; break;
407 case 'Y':
408 Lskipnocor = TRUE;
409 /* **** FALLL THROUGH TO **** */
410 case 'y':
411 Lzmanag = ZMCLOB; break;
412 default:
413 usage();
417 else if ( !npats && argc>0) {
418 if (argv[0][0]) {
419 npats=argc;
420 patts=argv;
421 #ifndef vax11c
422 if ( !strcmp(*patts, "-"))
423 iofd = 1;
424 #endif
428 if (npats < 1 && !Command && !Test)
429 usage();
430 if (Verbose) {
431 if (freopen(LOGFILE, "a", stderr)==NULL) {
432 printf("Can't open log file %s\n",LOGFILE);
433 exit(0200);
435 setbuf(stderr, (char *)NULL);
437 if (Fromcu && !Quiet) {
438 if (Verbose == 0)
439 Verbose = 2;
441 vfile("%s %s for %s\n", Progname, VERSION, OS);
443 mode(1);
445 if (signal(SIGINT, bibi) == SIG_IGN) {
446 signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
447 } else {
448 signal(SIGINT, bibi); signal(SIGKILL, bibi);
450 if ( !Fromcu)
451 signal(SIGQUIT, SIG_IGN);
452 signal(SIGTERM, bibi);
454 if ( !Modem2) {
455 if (!Nozmodem) {
456 printf("rz\r"); fflush(stdout);
458 countem(npats, patts);
459 if (!Nozmodem) {
460 stohdr(0L);
461 if (Command)
462 Txhdr[ZF0] = ZCOMMAND;
463 zshhdr(ZRQINIT, Txhdr);
466 fflush(stdout);
468 if (Command) {
469 if (getzrxinit()) {
470 Exitcode=0200; canit();
472 else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
473 Exitcode=0200; canit();
475 } else if (wcsend(npats, patts)==ERROR) {
476 Exitcode=0200;
477 canit();
479 fflush(stdout);
480 mode(0);
481 dm = ((errcnt != 0) | Exitcode);
482 if (dm) {
483 cucheck(); exit(dm);
485 putc('\n',stderr);
486 exit(SS_NORMAL);
487 /*NOTREACHED*/
490 int wcsend(int argc, char *argp[])
492 register int n;
494 Crcflg=FALSE;
495 firstsec=TRUE;
496 bytcnt = -1;
497 for (n=0; n<argc; ++n) {
498 Totsecs = 0;
499 if (wcs(argp[n])==ERROR)
500 return ERROR;
502 Totsecs = 0;
503 if (Filcnt==0) { /* bitch if we couldn't open ANY files */
504 if ( !Modem2) {
505 Command = TRUE;
506 Cmdstr = "echo \"sz: Can't open any requested files\"";
507 if (getnak()) {
508 Exitcode=0200; canit();
510 if (!Zmodem)
511 canit();
512 else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
513 Exitcode=0200; canit();
515 Exitcode = 1; return OK;
517 canit();
518 fprintf(stderr,"\r\nCan't open any requested files.\r\n");
519 return ERROR;
521 if (Zmodem)
522 saybibi();
523 else if ( !Modem2)
524 wctxpn("");
525 return OK;
528 int wcs(char *oname)
530 register int c;
531 register char *p;
532 struct stat f;
533 char name[PATHLEN];
535 strcpy(name, oname);
537 if (Restricted) {
538 /* restrict pathnames to current tree or uucppublic */
539 if ( substr(name, "../")
540 || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
541 canit();
542 fprintf(stderr,"\r\nsz:\tSecurity Violation\r\n");
543 return ERROR;
547 if ( !strcmp(oname, "-")) {
548 if ((p = getenv("ONAME")) && *p)
549 strcpy(name, p);
550 else
551 sprintf(name, "s%d.sz", getpid());
552 in = stdin;
554 else if ((in=fopen(oname, "r"))==NULL) {
555 ++errcnt;
556 return OK; /* pass over it, there may be others */
558 BEofseen = Eofseen = 0; vpos = 0;
559 /* Check for directory or block special files */
560 fstat(fileno(in), &f);
561 c = f.st_mode & S_IFMT;
562 if (c == S_IFDIR || c == S_IFBLK) {
563 fclose(in);
564 return OK;
567 ++Filcnt;
568 switch (wctxpn(name)) {
569 case ERROR:
570 return ERROR;
571 case ZSKIP:
572 return OK;
574 if (!Zmodem && wctx(f.st_size)==ERROR)
575 return ERROR;
576 #ifndef vax11c
577 if (Unlinkafter)
578 unlink(oname);
579 #endif
580 return 0;
584 * generate and transmit pathname block consisting of
585 * pathname (null terminated),
586 * file length, mode time and file mode in octal
587 * as provided by the Unix fstat call.
588 * N.B.: modifies the passed name, may extend it!
590 int wctxpn(char *name)
592 register char *p, *q;
593 char name2[PATHLEN];
594 struct stat f;
596 if (Modem2) {
597 if ((in!=stdin) && *name && fstat(fileno(in), &f)!= -1) {
598 fprintf(stderr, "Sending %s, %lld blocks: ",
599 name, f.st_size>>7);
601 fprintf(stderr, "Give your local XMODEM receive command now.\r\n");
602 return OK;
604 zperr("Awaiting pathname nak for %s", *name?name:"<END>");
605 if ( !Zmodem)
606 if (getnak())
607 return ERROR;
609 q = (char *) 0;
610 if (Dottoslash) { /* change . to . */
611 for (p=name; *p; ++p) {
612 if (*p == '/')
613 q = p;
614 else if (*p == '.')
615 *(q=p) = '/';
617 if (q && strlen(++q) > 8) { /* If name>8 chars */
618 q += 8; /* make it .ext */
619 strcpy(name2, q); /* save excess of name */
620 *q = '.';
621 strcpy(++q, name2); /* add it back */
625 for (p=name, q=txbuf ; *p; )
626 if ((*q++ = *p++) == '/' && !Fullname)
627 q = txbuf;
628 *q++ = 0;
629 p=q;
630 while (q < (txbuf + 1024))
631 *q++ = 0;
632 if (!Ascii && (in!=stdin) && *name && fstat(fileno(in), &f)!= -1)
633 sprintf(p, "%llu %llo %o 0 %d %ld", f.st_size, f.st_mtime,
634 f.st_mode, Filesleft, Totalleft);
635 Totalleft -= f.st_size;
636 if (--Filesleft <= 0)
637 Totalleft = 0;
638 if (Totalleft < 0)
639 Totalleft = 0;
641 /* force 1k blocks if name won't fit in 128 byte block */
642 if (txbuf[125])
643 blklen=1024;
644 else { /* A little goodie for IMP/KMD */
645 txbuf[127] = (f.st_size + 127) >>7;
646 txbuf[126] = (f.st_size + 127) >>15;
648 if (Zmodem)
649 return zsendfile(txbuf, 1+strlen(p)+(p-txbuf));
650 if (wcputsec(txbuf, 0, 128)==ERROR)
651 return ERROR;
652 return OK;
655 int getnak()
657 register int firstch;
659 Lastrx = 0;
660 for (;;) {
661 switch (firstch = readline(800)) {
662 case ZPAD:
663 if (getzrxinit())
664 return ERROR;
665 Ascii = 0; /* Receiver does the conversion */
666 return FALSE;
667 case TIMEOUT:
668 zperr("Timeout on pathname");
669 return TRUE;
670 case WANTG:
671 #ifdef MODE2OK
672 mode(2); /* Set cbreak, XON/XOFF, etc. */
673 #endif
674 Optiong = TRUE;
675 blklen=1024;
676 case WANTCRC:
677 Crcflg = TRUE;
678 case NAK:
679 return FALSE;
680 case CAN:
681 if ((firstch = readline(20)) == CAN && Lastrx == CAN)
682 return TRUE;
683 default:
684 break;
686 Lastrx = firstch;
691 int wctx(long flen)
693 register int thisblklen;
694 register int sectnum, attempts, firstch;
695 long charssent;
697 charssent = 0; firstsec=TRUE; thisblklen = blklen;
698 vfile("wctx:file length=%ld", flen);
700 while ((firstch=readline(Rxtimeout))!=NAK && firstch != WANTCRC
701 && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN)
703 if (firstch==CAN) {
704 zperr("Receiver CANcelled");
705 return ERROR;
707 if (firstch==WANTCRC)
708 Crcflg=TRUE;
709 if (firstch==WANTG)
710 Crcflg=TRUE;
711 sectnum=0;
712 for (;;) {
713 if (flen <= (charssent + 896L))
714 thisblklen = 128;
715 if ( !filbuf(txbuf, thisblklen))
716 break;
717 if (wcputsec(txbuf, ++sectnum, thisblklen)==ERROR)
718 return ERROR;
719 charssent += thisblklen;
721 fclose(in);
722 attempts=0;
723 do {
724 purgeline();
725 sendline(EOT);
726 fflush(stdout);
727 ++attempts;
729 while ((firstch = readline(Rxtimeout)) != ACK &&
730 attempts < RETRYMAX);
731 if (attempts == RETRYMAX) {
732 zperr("No ACK on EOT");
733 return ERROR;
735 else
736 return OK;
739 * @param cseclen :data length of this sector to send
741 int wcputsec(char *buf, int sectnum, int cseclen)
743 register int checksum, wcj;
744 register char *cp;
745 unsigned oldcrc;
746 int firstch;
747 int attempts;
749 firstch=0; /* part of logic to detect CAN CAN */
751 if (Verbose>2)
752 fprintf(stderr, "Sector %3d %2dk\n", Totsecs, Totsecs/8 );
753 else if (Verbose>1)
754 fprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs/8 );
755 for (attempts=0; attempts <= RETRYMAX; attempts++) {
756 Lastrx= firstch;
757 sendline(cseclen==1024?STX:SOH);
758 sendline(sectnum);
759 sendline(-sectnum -1);
760 oldcrc=checksum=0;
761 for (wcj=cseclen,cp=buf; --wcj>=0; ) {
762 sendline(*cp);
763 oldcrc=updcrc((0377& *cp), oldcrc);
764 checksum += *cp++;
766 if (Crcflg) {
767 oldcrc=updcrc(0,updcrc(0,oldcrc));
768 sendline((int)oldcrc>>8);
769 sendline((int)oldcrc);
771 else
772 sendline(checksum);
774 if (Optiong) {
775 firstsec = FALSE; return OK;
777 firstch = readline(Rxtimeout);
778 gotnak:
779 switch (firstch) {
780 case CAN:
781 if(Lastrx == CAN) {
782 cancan:
783 zperr("Cancelled"); return ERROR;
785 break;
786 case TIMEOUT:
787 zperr("Timeout on sector ACK"); continue;
788 case WANTCRC:
789 if (firstsec)
790 Crcflg = TRUE;
791 case NAK:
792 zperr("NAK on sector"); continue;
793 case ACK:
794 firstsec=FALSE;
795 Totsecs += (cseclen>>7);
796 return OK;
797 case ERROR:
798 zperr("Got burst for sector ACK"); break;
799 default:
800 zperr("Got %02x for sector ACK", firstch); break;
802 for (;;) {
803 Lastrx = firstch;
804 if ((firstch = readline(Rxtimeout)) == TIMEOUT)
805 break;
806 if (firstch == NAK || firstch == WANTCRC)
807 goto gotnak;
808 if (firstch == CAN && Lastrx == CAN)
809 goto cancan;
812 zperr("Retry Count Exceeded");
813 return ERROR;
816 /* fill buf with count chars padding with ^Z for CPM */
817 int filbuf(char *buf, int count)
819 register int c, m;
821 if ( !Ascii) {
822 m = read(fileno(in), buf, count);
823 if (m <= 0)
824 return 0;
825 while (m < count)
826 buf[m++] = 032;
827 return count;
829 m=count;
830 if (Lfseen) {
831 *buf++ = 012; --m; Lfseen = 0;
833 while ((c=getc(in))!=EOF) {
834 if (c == 012) {
835 *buf++ = 015;
836 if (--m == 0) {
837 Lfseen = TRUE; break;
840 *buf++ =c;
841 if (--m == 0)
842 break;
844 if (m==count)
845 return 0;
846 else
847 while (--m>=0)
848 *buf++ = CPMEOF;
849 return count;
852 /* Fill buffer with blklen chars */
853 int zfilbuf()
855 int n;
857 #ifdef TXBSIZE
858 /* We assume request is within buffer, or just beyond */
859 txbuf = Txb + (bytcnt & TXBMASK);
860 if (vpos <= bytcnt) {
861 n = fread(txbuf, 1, blklen, in);
862 vpos += n;
863 if (n < blklen)
864 Eofseen = 1;
865 return n;
867 if (vpos >= (bytcnt+blklen))
868 return blklen;
869 /* May be a short block if crash recovery etc. */
870 Eofseen = BEofseen;
871 return (vpos - bytcnt);
872 #else
873 n = fread(txbuf, 1, blklen, in);
874 if (n < blklen)
875 Eofseen = 1;
876 return n;
877 #endif
880 #ifdef TXBSIZE
881 int fooseek(FILE *fptr, long pos, int whence)
883 int m, n;
885 vfile("fooseek: pos =%lu vpos=%lu Canseek=%d", pos, vpos, Canseek);
886 /* Seek offset < current buffer */
887 if (pos < (vpos -TXBSIZE +1024)) {
888 BEofseen = 0;
889 if (Canseek > 0) {
890 vpos = pos & ~TXBMASK;
891 if (vpos >= pos)
892 vpos -= TXBSIZE;
893 if (fseek(fptr, vpos, 0))
894 return 1;
896 else if (Canseek == 0)
897 if (fseek(fptr, vpos = 0L, 0))
898 return 1;
899 else
900 return 1;
901 while (vpos <= pos) {
902 n = fread(Txb, 1, TXBSIZE, fptr);
903 vpos += n;
904 vfile("n=%d vpos=%ld", n, vpos);
905 if (n < TXBSIZE) {
906 BEofseen = 1;
907 break;
910 vfile("vpos=%ld", vpos);
911 return 0;
913 /* Seek offset > current buffer (crash recovery, etc.) */
914 if (pos > vpos) {
915 if (Canseek)
916 if (fseek(fptr, vpos = (pos & ~TXBMASK), 0))
917 return 1;
918 while (vpos <= pos) {
919 txbuf = Txb + (vpos & TXBMASK);
920 m = TXBSIZE - (vpos & TXBMASK);
921 n = fread(txbuf, 1, m, fptr);
922 vpos += n;
923 vfile("bo=%d n=%d vpos=%ld", txbuf-Txb, n, vpos);
924 if (m < n) {
925 BEofseen = 1;
926 break;
929 return 0;
931 /* Seek offset is within current buffer */
932 vfile("vpos=%ld", vpos);
933 return 0;
935 #define fseek fooseek
936 #endif
938 void vfile(const char *string, ...)
940 if (Verbose > 2) {
941 va_list args;
942 va_start(args, string);
943 vfprintf(stderr, string, args);
944 va_end(args);
945 fprintf(stderr, "\n");
950 void alrm(int sig)
952 longjmp(tohere, -1);
956 #ifndef vax11c
958 * readline(timeout) reads character(s) from file descriptor 0
959 * timeout is in tenths of seconds
961 int readline(int timeout)
963 register int c;
964 static char byt[1];
966 fflush(stdout);
967 if (setjmp(tohere)) {
968 zperr("TIMEOUT");
969 return TIMEOUT;
971 c = timeout/10;
972 if (c<2)
973 c=2;
974 if (Verbose>5) {
975 fprintf(stderr, "Timeout=%d Calling alarm(%d) ", timeout, c);
977 signal(SIGALRM, alrm); alarm(c);
978 c=read(iofd, byt, 1);
979 alarm(0);
980 if (Verbose>5)
981 fprintf(stderr, "ret %x\n", byt[0]);
982 if (c<1)
983 return TIMEOUT;
984 return (byt[0]&0377);
987 void flushmo()
989 fflush(stdout);
993 void purgeline()
995 #ifdef USG
996 ioctl(iofd, TCFLSH, 0);
997 #else
998 lseek(iofd, 0L, 2);
999 #endif
1001 #endif
1003 /* send cancel string to get the other end to shut up */
1004 void canit()
1006 static char canistr[] = {
1007 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
1010 #ifdef vax11c
1011 raw_wbuf(strlen(canistr), canistr);
1012 purgeline();
1013 #else
1014 printf("%s", canistr);
1015 fflush(stdout);
1016 #endif
1021 * Log an error
1023 /*VARARGS1*/
1024 void zperr(char *s, char *p, char *u)
1026 if (Verbose <= 0)
1027 return;
1028 fprintf(stderr, "\nRetry %d: ", errors);
1029 fprintf(stderr, s, p, u);
1030 fprintf(stderr, "\n");
1034 * substr(string, token) searches for token in string s
1035 * returns pointer to token within string if found, NULL otherwise
1037 char *
1038 substr(char *s, char *t)
1040 register char *ss,*tt;
1041 /* search for first char of token */
1042 for (ss=s; *s; s++)
1043 if (*s == *t)
1044 /* compare token with substring */
1045 for (ss=s,tt=t; ;) {
1046 if (*tt == 0)
1047 return s;
1048 if (*ss++ != *tt++)
1049 break;
1051 return (char *)NULL;
1054 char *babble[] = {
1055 #ifdef vax11c
1056 " Send file(s) with ZMODEM Protocol",
1057 "Usage: sz [-2+abdefkLlNnquvwYy] [-] file ...",
1058 " sz [-2Ceqv] -c COMMAND",
1059 " \\ Force next option letter to upper case",
1060 #else
1061 "Send file(s) with ZMODEM/YMODEM/XMODEM Protocol",
1062 " (Y) = Option applies to YMODEM only",
1063 " (Z) = Option applies to ZMODEM only",
1064 "Usage: sz [-2+abdefkLlNnquvwYy] [-] file ...",
1065 " sz [-2Ceqv] -c COMMAND",
1066 " sb [-2adfkquv] [-] file ...",
1067 " sx [-2akquv] [-] file",
1068 #endif
1069 #ifdef CSTOPB
1070 " 2 Use 2 stop bits",
1071 #endif
1072 " + Append to existing destination file (Z)",
1073 " a (ASCII) change NL to CR/LF",
1074 " b Binary file transfer override",
1075 " c send COMMAND (Z)",
1076 #ifndef vax11c
1077 " d Change '.' to '/' in pathnames (Y/Z)",
1078 #endif
1079 " e Escape all control characters (Z)",
1080 " f send Full pathname (Y/Z)",
1081 " i send COMMAND, ack Immediately (Z)",
1082 " k Send 1024 byte packets (Y)",
1083 " L N Limit subpacket length to N bytes (Z)",
1084 " l N Limit frame length to N bytes (l>=L) (Z)",
1085 " n send file if source newer (Z)",
1086 " N send file if source newer or longer (Z)",
1087 " o Use 16 bit CRC instead of 32 bit CRC (Z)",
1088 " p Protect existing destination file (Z)",
1089 " r Resume/Recover interrupted file transfer (Z)",
1090 " q Quiet (no progress reports)",
1091 #ifndef vax11c
1092 " u Unlink file after transmission",
1093 #endif
1094 " v Verbose - provide debugging information",
1095 " w N Window is N bytes (Z)",
1096 " Y Yes, overwrite existing file, skip if not present at rx (Z)",
1097 " y Yes, overwrite existing file (Z)",
1098 "- as pathname sends standard input as sPID.sz or environment ONAME",
1102 int usage()
1104 char **pp;
1106 for (pp=babble; **pp; ++pp)
1107 fprintf(stderr, "%s\n", *pp);
1108 fprintf(stderr, "%s for %s by Chuck Forsberg, Omen Technology INC\n",
1109 VERSION, OS);
1110 fprintf(stderr, "\t\t\042The High Reliability Software\042\n");
1111 cucheck();
1112 exit(SS_NORMAL);
1116 * Get the receiver's init parameters
1118 int getzrxinit()
1120 register int n;
1121 struct stat f;
1123 for (n=10; --n>=0; ) {
1125 switch (zgethdr(Rxhdr, 1)) {
1126 case ZCHALLENGE: /* Echo receiver's challenge numbr */
1127 stohdr(Rxpos);
1128 zshhdr(ZACK, Txhdr);
1129 continue;
1130 case ZCOMMAND: /* They didn't see out ZRQINIT */
1131 stohdr(0L);
1132 zshhdr(ZRQINIT, Txhdr);
1133 continue;
1134 case ZRINIT:
1135 Rxflags = 0377 & Rxhdr[ZF0];
1136 Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
1137 Zctlesc |= Rxflags & TESCCTL;
1138 Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
1139 if ( !(Rxflags & CANFDX))
1140 Txwindow = 0;
1141 vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen);
1142 if ( !Fromcu)
1143 signal(SIGINT, SIG_IGN);
1144 #ifdef MODE2OK
1145 mode(2); /* Set cbreak, XON/XOFF, etc. */
1146 #endif
1147 #ifndef READCHECK
1148 #ifndef USG
1149 /* Use 1024 byte frames if no sample/interrupt */
1150 if (Rxbuflen < 32 || Rxbuflen > 1024) {
1151 Rxbuflen = 1024;
1152 vfile("Rxbuflen=%d", Rxbuflen);
1154 #endif
1155 #endif
1156 /* Override to force shorter frame length */
1157 if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32))
1158 Rxbuflen = Tframlen;
1159 if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024))
1160 Rxbuflen = Tframlen;
1161 vfile("Rxbuflen=%d", Rxbuflen);
1163 #ifndef vax11c
1164 /* If using a pipe for testing set lower buf len */
1165 fstat(iofd, &f);
1166 if ((f.st_mode & S_IFMT) != S_IFCHR) {
1167 Rxbuflen = 1024;
1169 #endif
1170 #ifdef BADSEEK
1171 Canseek = 0;
1172 Txwindow = TXBSIZE - 1024;
1173 Txwspac = TXBSIZE/4;
1174 #endif
1176 * If input is not a regular file, force ACK's to
1177 * prevent running beyond the buffer limits
1179 if ( !Command) {
1180 fstat(fileno(in), &f);
1181 if ((f.st_mode & S_IFMT) != S_IFREG) {
1182 Canseek = -1;
1183 #ifdef TXBSIZE
1184 Txwindow = TXBSIZE - 1024;
1185 Txwspac = TXBSIZE/4;
1186 #else
1187 return ERROR;
1188 #endif
1191 /* Set initial subpacket length */
1192 if (blklen < 1024) { /* Command line override? */
1193 if (Baudrate > 300)
1194 blklen = 256;
1195 if (Baudrate > 1200)
1196 blklen = 512;
1197 if (Baudrate > 2400)
1198 blklen = 1024;
1200 if (Rxbuflen && blklen>Rxbuflen)
1201 blklen = Rxbuflen;
1202 if (blkopt && blklen > blkopt)
1203 blklen = blkopt;
1204 vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen);
1205 vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac);
1207 return (sendzsinit());
1208 case ZCAN:
1209 case TIMEOUT:
1210 return ERROR;
1211 case ZRQINIT:
1212 if (Rxhdr[ZF0] == ZCOMMAND)
1213 continue;
1214 default:
1215 zshhdr(ZNAK, Txhdr);
1216 continue;
1219 return ERROR;
1222 /* Send send-init information */
1223 int sendzsinit()
1225 register int c;
1227 if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL)))
1228 return OK;
1229 errors = 0;
1230 for (;;) {
1231 stohdr(0L);
1232 if (Zctlesc) {
1233 Txhdr[ZF0] |= TESCCTL; zshhdr(ZSINIT, Txhdr);
1235 else
1236 zsbhdr(ZSINIT, Txhdr);
1237 zsdata(Myattn, 1+strlen(Myattn), ZCRCW);
1238 c = zgethdr(Rxhdr, 1);
1239 switch (c) {
1240 case ZCAN:
1241 return ERROR;
1242 case ZACK:
1243 return OK;
1244 default:
1245 if (++errors > 19)
1246 return ERROR;
1247 continue;
1252 /* Send file name and related info */
1253 int zsendfile(char *buf, int blen)
1255 register int c;
1256 register UNSL long crc;
1258 for (;;) {
1259 Txhdr[ZF0] = Lzconv; /* file conversion request */
1260 Txhdr[ZF1] = Lzmanag; /* file management request */
1261 if (Lskipnocor)
1262 Txhdr[ZF1] |= ZMSKNOLOC;
1263 Txhdr[ZF2] = Lztrans; /* file transport request */
1264 Txhdr[ZF3] = 0;
1265 zsbhdr(ZFILE, Txhdr);
1266 zsdata(buf, blen, ZCRCW);
1267 again:
1268 c = zgethdr(Rxhdr, 1);
1269 switch (c) {
1270 case ZRINIT:
1271 while ((c = readline(50)) > 0)
1272 if (c == ZPAD) {
1273 goto again;
1275 /* **** FALL THRU TO **** */
1276 default:
1277 continue;
1278 case ZCAN:
1279 case TIMEOUT:
1280 case ZABORT:
1281 case ZFIN:
1282 return ERROR;
1283 case ZCRC:
1284 crc = 0xFFFFFFFFL;
1285 if (Canseek >= 0) {
1286 while (((c = getc(in)) != EOF) && --Rxpos)
1287 crc = UPDC32(c, crc);
1288 crc = ~crc;
1289 clearerr(in); /* Clear EOF */
1290 fseek(in, 0L, 0);
1292 stohdr(crc);
1293 zsbhdr(ZCRC, Txhdr);
1294 goto again;
1295 case ZSKIP:
1296 fclose(in); return c;
1297 case ZRPOS:
1299 * Suppress zcrcw request otherwise triggered by
1300 * lastyunc==bytcnt
1302 if (Rxpos && fseek(in, Rxpos, 0))
1303 return ERROR;
1304 Lastsync = (bytcnt = Txpos = Rxpos) -1;
1305 return zsendfdata();
1310 /* Send the data in the file */
1311 int zsendfdata()
1313 register int c, e, n;
1314 register int newcnt;
1315 register long tcount = 0;
1316 int junkcount; /* Counts garbage chars received by TX */
1317 static int tleft = 6; /* Counter for test mode */
1319 Lrxpos = 0;
1320 junkcount = 0;
1321 Beenhereb4 = FALSE;
1322 somemore:
1323 if (setjmp(intrjmp)) {
1324 waitack:
1325 junkcount = 0;
1326 c = getinsync(0);
1327 gotack:
1328 switch (c) {
1329 default:
1330 case ZCAN:
1331 fclose(in);
1332 return ERROR;
1333 case ZSKIP:
1334 fclose(in);
1335 return c;
1336 case ZACK:
1337 case ZRPOS:
1338 break;
1339 case ZRINIT:
1340 return OK;
1342 #ifdef READCHECK
1344 * If the reverse channel can be tested for data,
1345 * this logic may be used to detect error packets
1346 * sent by the receiver, in place of setjmp/longjmp
1347 * rdchk(fdes) returns non 0 if a character is available
1349 while (rdchk(iofd)) {
1350 #ifdef SV
1351 switch (checked)
1352 #else
1353 switch (readline(1))
1354 #endif
1356 case CAN:
1357 case ZPAD:
1358 c = getinsync(1);
1359 goto gotack;
1360 case XOFF: /* Wait a while for an XON */
1361 case XOFF|0200:
1362 readline(100);
1365 #endif
1368 if ( !Fromcu)
1369 signal(SIGINT, onintr);
1370 newcnt = Rxbuflen;
1371 Txwcnt = 0;
1372 stohdr(Txpos);
1373 zsbhdr(ZDATA, Txhdr);
1376 * Special testing mode. This should force receiver to Attn,ZRPOS
1377 * many times. Each time the signal should be caught, causing the
1378 * file to be started over from the beginning.
1380 if (Test) {
1381 if ( --tleft)
1382 while (tcount < 20000) {
1383 printf("%s", qbf); fflush(stdout);
1384 tcount += strlen(qbf);
1385 #ifdef READCHECK
1386 while (rdchk(iofd)) {
1387 #ifdef SV
1388 switch (checked)
1389 #else
1390 switch (readline(1))
1391 #endif
1393 case CAN:
1394 case ZPAD:
1395 #ifdef TCFLSH
1396 ioctl(iofd, TCFLSH, 1);
1397 #endif
1398 goto waitack;
1399 case XOFF: /* Wait for XON */
1400 case XOFF|0200:
1401 readline(100);
1404 #endif
1406 signal(SIGINT, SIG_IGN); canit();
1407 sleep(3); purgeline(); mode(0);
1408 printf("\nsz: Tcount = %ld\n", tcount);
1409 if (tleft) {
1410 printf("ERROR: Interrupts Not Caught\n");
1411 exit(1);
1413 exit(SS_NORMAL);
1416 do {
1417 n = zfilbuf();
1418 if (Eofseen)
1419 e = ZCRCE;
1420 else if (junkcount > 3)
1421 e = ZCRCW;
1422 else if (bytcnt == Lastsync)
1423 e = ZCRCW;
1424 else if (Rxbuflen && (newcnt -= n) <= 0)
1425 e = ZCRCW;
1426 else if (Txwindow && (Txwcnt += n) >= Txwspac) {
1427 Txwcnt = 0; e = ZCRCQ;
1429 else
1430 e = ZCRCG;
1431 if (Verbose>1)
1432 fprintf(stderr, "\r%7ld ZMODEM%s ",
1433 Txpos, Crc32t?" CRC-32":"");
1434 zsdata(txbuf, n, e);
1435 bytcnt = Txpos += n;
1436 if (e == ZCRCW)
1437 goto waitack;
1438 #ifdef READCHECK
1440 * If the reverse channel can be tested for data,
1441 * this logic may be used to detect error packets
1442 * sent by the receiver, in place of setjmp/longjmp
1443 * rdchk(fdes) returns non 0 if a character is available
1445 fflush(stdout);
1446 while (rdchk(iofd)) {
1447 #ifdef SV
1448 switch (checked)
1449 #else
1450 switch (readline(1))
1451 #endif
1453 case CAN:
1454 case ZPAD:
1455 c = getinsync(1);
1456 if (c == ZACK)
1457 break;
1458 #ifdef TCFLSH
1459 ioctl(iofd, TCFLSH, 1);
1460 #endif
1461 /* zcrce - dinna wanna starta ping-pong game */
1462 zsdata(txbuf, 0, ZCRCE);
1463 goto gotack;
1464 case XOFF: /* Wait a while for an XON */
1465 case XOFF|0200:
1466 readline(100);
1467 default:
1468 ++junkcount;
1471 #endif /* READCHECK */
1472 if (Txwindow) {
1473 while ((tcount = Txpos - Lrxpos) >= Txwindow) {
1474 vfile("%ld window >= %u", tcount, Txwindow);
1475 if (e != ZCRCQ)
1476 zsdata(txbuf, 0, e = ZCRCQ);
1477 c = getinsync(1);
1478 if (c != ZACK) {
1479 #ifdef TCFLSH
1480 ioctl(iofd, TCFLSH, 1);
1481 #endif
1482 zsdata(txbuf, 0, ZCRCE);
1483 goto gotack;
1486 vfile("window = %ld", tcount);
1488 } while (!Eofseen);
1489 if ( !Fromcu)
1490 signal(SIGINT, SIG_IGN);
1492 for (;;) {
1493 stohdr(Txpos);
1494 zsbhdr(ZEOF, Txhdr);
1495 switch (getinsync(0)) {
1496 case ZACK:
1497 continue;
1498 case ZRPOS:
1499 goto somemore;
1500 case ZRINIT:
1501 return OK;
1502 case ZSKIP:
1503 fclose(in);
1504 return c;
1505 default:
1506 fclose(in);
1507 return ERROR;
1513 * Respond to receiver's complaint, get back in sync with receiver
1515 int getinsync(int flag)
1517 register int c;
1519 for (;;) {
1520 if (Test) {
1521 printf("\r\n\n\n***** Signal Caught *****\r\n");
1522 Rxpos = 0; c = ZRPOS;
1523 } else
1524 c = zgethdr(Rxhdr, 0);
1525 switch (c) {
1526 case ZCAN:
1527 case ZABORT:
1528 case ZFIN:
1529 case TIMEOUT:
1530 return ERROR;
1531 case ZRPOS:
1532 /* ************************************* */
1533 /* If sending to a buffered modem, you */
1534 /* might send a break at this point to */
1535 /* dump the modem's buffer. */
1536 clearerr(in); /* In case file EOF seen */
1537 if (fseek(in, Rxpos, 0))
1538 return ERROR;
1539 Eofseen = 0;
1540 bytcnt = Lrxpos = Txpos = Rxpos;
1541 if (Lastsync == Rxpos) {
1542 if (++Beenhereb4 > 4)
1543 if (blklen > 32)
1544 blklen /= 2;
1546 Lastsync = Rxpos;
1547 return c;
1548 case ZACK:
1549 Lrxpos = Rxpos;
1550 if (flag || Txpos == Rxpos)
1551 return ZACK;
1552 continue;
1553 case ZRINIT:
1554 case ZSKIP:
1555 fclose(in);
1556 return c;
1557 case ERROR:
1558 default:
1559 zsbhdr(ZNAK, Txhdr);
1560 continue;
1566 /* Say "bibi" to the receiver, try to do it cleanly */
1567 void saybibi()
1569 for (;;) {
1570 stohdr(0L); /* CAF Was zsbhdr - minor change */
1571 zshhdr(ZFIN, Txhdr); /* to make debugging easier */
1572 switch (zgethdr(Rxhdr, 0)) {
1573 case ZFIN:
1574 sendline('O'); sendline('O'); flushmo();
1575 case ZCAN:
1576 case TIMEOUT:
1577 return;
1582 /* Local screen character display function */
1583 void bttyout(int c)
1585 if (Verbose)
1586 putc(c, stderr);
1589 /* Send command and related info */
1590 int zsendcmd(char *buf, int blen)
1592 register int c;
1593 long cmdnum;
1595 cmdnum = getpid();
1596 errors = 0;
1597 for (;;) {
1598 stohdr(cmdnum);
1599 Txhdr[ZF0] = Cmdack1;
1600 zsbhdr(ZCOMMAND, Txhdr);
1601 zsdata(buf, blen, ZCRCW);
1602 listen:
1603 Rxtimeout = 100; /* Ten second wait for resp. */
1604 c = zgethdr(Rxhdr, 1);
1606 switch (c) {
1607 case ZRINIT:
1608 goto listen; /* CAF 8-21-87 */
1609 case ERROR:
1610 case TIMEOUT:
1611 if (++errors > Cmdtries)
1612 return ERROR;
1613 continue;
1614 case ZCAN:
1615 case ZABORT:
1616 case ZFIN:
1617 case ZSKIP:
1618 case ZRPOS:
1619 return ERROR;
1620 default:
1621 if (++errors > 20)
1622 return ERROR;
1623 continue;
1624 case ZCOMPL:
1625 Exitcode = Rxpos;
1626 saybibi();
1627 return OK;
1628 case ZRQINIT:
1629 #ifdef vax11c /* YAMP :== Yet Another Missing Primitive */
1630 return ERROR;
1631 #else
1632 vfile("******** RZ *******");
1633 system("rz");
1634 vfile("******** SZ *******");
1635 goto listen;
1636 #endif
1642 * If called as sb use YMODEM protocol
1644 void chkinvok(char *s)
1646 #ifdef vax11c
1647 Progname = "sz";
1648 #else
1649 register char *p;
1651 p = s;
1652 while (*p == '-')
1653 s = ++p;
1654 while (*p)
1655 if (*p++ == '/')
1656 s = p;
1657 if (*s == 'v') {
1658 Verbose=1; ++s;
1660 Progname = s;
1661 if (s[0]=='s' && s[1]=='b') {
1662 Nozmodem = TRUE; blklen=1024;
1664 if (s[0]=='s' && s[1]=='x') {
1665 Modem2 = TRUE;
1667 #endif
1670 void countem(int argc, char **argv)
1672 register int c;
1673 struct stat f;
1675 for (Totalleft = 0, Filesleft = 0; --argc >=0; ++argv) {
1676 f.st_size = -1;
1677 if (Verbose>2) {
1678 fprintf(stderr, "\nCountem: %03d %s ", argc, *argv);
1679 fflush(stderr);
1681 if (access(*argv, 04) >= 0 && stat(*argv, &f) >= 0) {
1682 c = f.st_mode & S_IFMT;
1683 if (c != S_IFDIR && c != S_IFBLK) {
1684 ++Filesleft; Totalleft += f.st_size;
1687 if (Verbose>2)
1688 fprintf(stderr, " %lld", f.st_size);
1690 if (Verbose>2)
1691 fprintf(stderr, "\ncountem: Total %d %ld\n",
1692 Filesleft, Totalleft);
1695 void chartest(int m)
1697 register int n;
1699 mode(m);
1700 printf("\r\n\nCharacter Transparency Test Mode %d\r\n", m);
1701 printf("If Pro-YAM/ZCOMM is not displaying ^M hit ALT-V NOW.\r\n");
1702 printf("Hit Enter.\021"); fflush(stdout);
1703 readline(500);
1705 for (n = 0; n < 256; ++n) {
1706 if (!(n%8))
1707 printf("\r\n");
1708 printf("%02x ", n); fflush(stdout);
1709 sendline(n); flushmo();
1710 printf(" "); fflush(stdout);
1711 if (n == 127) {
1712 printf("Hit Enter.\021"); fflush(stdout);
1713 readline(500);
1714 printf("\r\n"); fflush(stdout);
1717 printf("\021\r\nEnter Characters, echo is in hex.\r\n");
1718 printf("Hit SPACE or pause 40 seconds for exit.\r\n");
1720 while (n != TIMEOUT && n != ' ') {
1721 n = readline(400);
1722 printf("%02x\r\n", n);
1723 fflush(stdout);
1725 printf("\r\nMode %d character transparency test ends.\r\n", m);
1726 fflush(stdout);
1729 /* End of sz.c */