source: trunk/minix/commands/zmodem/sz.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

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