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
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>
64 #define TXBSIZE 32768 /* Must be power of two, < MAXINT */
67 #define LOGFILE "szlog.tmp"
73 #define SS_NORMAL SS$_NORMAL
74 #define xsendline(c) sendline(c)
81 #define LOGFILE "/tmp/szlog"
83 #define sendline(c) putchar((c) & 0377)
84 #define xsendline(c) putchar(c)
105 /* Ward Christensen / CP/M parameters - Don't change these! */
107 #define CAN ('X'&037)
108 #define XOFF ('s'&037)
109 #define XON ('q'&037)
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 */
124 int Zmodem
=0; /* ZMODEM protocol requested by receiver */
125 unsigned Baudrate
=2400; /* Default, should be set by first mode() call */
126 unsigned Txwindow
; /* Control the size of the transmitted window */
127 unsigned Txwspac
; /* Spacing between zcrcq requests */
128 unsigned Txwcnt
; /* Counter used to space ack requests */
129 long Lrxpos
; /* Receiver's last reported offset */
133 #include "vrzsz.c" /* most of the system dependent stuff here */
135 #include "rbsb.c" /* most of the system dependent stuff here */
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.
148 char Myattn
[] = { 0 };
151 char Myattn
[] = { 03, 0336, 0 };
153 char Myattn
[] = { 0 };
160 int Canseek
= 0; /* 1: Can seek 0: only rewind -1: neither (pipe) */
162 #define TXBSIZE 16384 /* Must be power of two, < MAXINT */
165 int Canseek
= 1; /* 1: Can seek 0: only rewind -1: neither (pipe) */
169 #define TXBMASK (TXBSIZE-1)
170 char Txb
[TXBSIZE
]; /* Circular buffer for file reads */
171 char *txbuf
= Txb
; /* Pointer to current file segment */
175 long vpos
= 0; /* Number of bytes read from file */
180 int Modem2
=0; /* XMODEM Protocol - don't send pathnames */
181 int Restricted
=0; /* restricted; no /.. or ../ in filenames */
182 int Quiet
=0; /* overrides logic that would otherwise set verbose */
183 int Ascii
=0; /* Add CR's for brain damaged programs */
184 int Fullname
=0; /* transmit full pathname */
185 int Unlinkafter
=0; /* Unlink file after it is sent */
186 int Dottoslash
=0; /* Change foo.bar.baz to foo/bar/baz */
188 int errcnt
=0; /* number of files unreadable */
189 int blklen
=128; /* length of transmitted records */
190 int Optiong
; /* Let it rip no wait for sector ACK's */
191 int Eofseen
; /* EOF seen on input set by zfilbuf */
192 int BEofseen
; /* EOF seen on input set by fooseek */
193 int Totsecs
; /* total number of sectors this file */
194 int Filcnt
=0; /* count of number of files opened */
196 unsigned Rxbuflen
= 16384; /* Receiver's max buffer length */
197 int Tframlen
= 0; /* Override for tx frame length */
198 int blkopt
=0; /* Override value for zmodem blklen */
201 int Wantfcs32
= TRUE
; /* want to send 32 bit FCS */
202 char Lzconv
; /* Local ZMODEM file conversion request */
203 char Lzmanag
; /* Local ZMODEM file management request */
206 char zconv
; /* ZMODEM file conversion request */
207 char zmanag
; /* ZMODEM file management request */
208 char ztrans
; /* ZMODEM file transport request */
209 int Command
; /* Send a command, then exit. */
210 char *Cmdstr
; /* Pointer to the command string */
212 int Cmdack1
; /* Rx ACKs command, then do it */
214 int Test
; /* 1= Force receiver to send Attn, etc with qbf. */
215 /* 2= Character transparency test */
216 char *qbf
="The quick brown fox jumped over the lazy dog's back 1234567890\r\n";
217 long Lastsync
; /* Last offset to which we got a ZRPOS */
218 int Beenhereb4
; /* How many times we've been ZRPOS'd same place */
220 jmp_buf tohere
; /* For the interrupt on RX timeout */
221 jmp_buf intrjmp
; /* For the interrupt on RX CAN */
223 void onintr(int sig
);
224 int main(int argc
, char *argv
[]);
225 int wcsend(int argc
, char *argp
[]);
226 int wcs(char *oname
);
227 int wctxpn(char *name
);
229 int wctx(long flen
);
230 int wcputsec(char *buf
, int sectnum
, int cseclen
);
231 int filbuf(char *buf
, int count
);
233 int fooseek(FILE *fptr
, long pos
, int whence
);
235 int readline(int timeout
);
237 void purgeline(void);
240 char *substr(char *s
, char *t
);
242 int getzrxinit(void);
243 int sendzsinit(void);
244 int zsendfile(char *buf
, int blen
);
245 int zsendfdata(void);
246 int getinsync(int flag
);
248 void bttyout(int c
);
249 int zsendcmd(char *buf
, int blen
);
250 void chkinvok(char *s
);
251 void countem(int argc
, char **argv
);
252 void chartest(int m
);
254 /* called by signal interrupt or terminate to clean things up */
258 canit(); fflush(stdout
); mode(0);
259 fprintf(stderr
, "sz: caught signal %d; exiting\n", n
);
263 fprintf(stderr
, "mode(2) in rbsb.c not implemented!!\n");
267 /* Called when ZMODEM gets an interrupt (^X) */
271 signal(SIGINT
, SIG_IGN
);
272 longjmp(intrjmp
, -1);
275 int Zctlesc
; /* Encode control characters */
276 int Nozmodem
= 0; /* If invoked as "sb" */
277 char *Progname
= "sz";
278 int Zrwindow
= 1400; /* RX window size (controls garbage count) */
290 static char xXbuf
[BUFSIZ
];
292 if ((cp
= getenv("ZNULLS")) && *cp
)
294 if ((cp
=getenv("SHELL")) && (substr(cp
, "rsh") || substr(cp
, "rksh")))
303 setbuf(stdout
, xXbuf
);
306 if (*cp
++ == '-' && *cp
) {
310 *cp
= toupper(*cp
); continue;
312 Lzmanag
= ZMAPND
; break;
315 Twostop
= TRUE
; break;
321 Lzconv
= ZCBIN
; break;
326 Cmdtries
= atoi(*++argv
);
330 /* **** FALL THROUGH TO **** */
340 /* **** FALL THROUGH TO **** */
342 Fullname
=TRUE
; break;
351 blkopt
= atoi(*++argv
);
352 if (blkopt
<24 || blkopt
>1024)
359 Tframlen
= atoi(*++argv
);
360 if (Tframlen
<32 || Tframlen
>1024)
364 Lzmanag
= ZMNEWL
; break;
366 Lzmanag
= ZMNEW
; break;
368 Wantfcs32
= FALSE
; break;
370 Lzmanag
= ZMPROT
; break;
374 Quiet
=TRUE
; Verbose
=0; break;
379 Rxtimeout
= atoi(*++argv
);
380 if (Rxtimeout
<10 || Rxtimeout
>1000)
385 chartest(1); chartest(2);
391 ++Unlinkafter
; break;
399 Txwindow
= atoi(*++argv
);
402 Txwindow
= (Txwindow
/64) * 64;
403 Txwspac
= Txwindow
/4;
405 || (!blkopt
&& Txwspac
< 1024))
412 /* **** FALLL THROUGH TO **** */
414 Lzmanag
= ZMCLOB
; break;
420 else if ( !npats
&& argc
>0) {
425 if ( !strcmp(*patts
, "-"))
431 if (npats
< 1 && !Command
&& !Test
)
434 if (freopen(LOGFILE
, "a", stderr
)==NULL
) {
435 printf("Can't open log file %s\n",LOGFILE
);
438 setbuf(stderr
, (char *)NULL
);
440 if (Fromcu
&& !Quiet
) {
444 vfile("%s %s for %s\n", Progname
, VERSION
, OS
);
448 if (signal(SIGINT
, bibi
) == SIG_IGN
) {
449 signal(SIGINT
, SIG_IGN
); signal(SIGKILL
, SIG_IGN
);
451 signal(SIGINT
, bibi
); signal(SIGKILL
, bibi
);
454 signal(SIGQUIT
, SIG_IGN
);
455 signal(SIGTERM
, bibi
);
459 printf("rz\r"); fflush(stdout
);
461 countem(npats
, patts
);
465 Txhdr
[ZF0
] = ZCOMMAND
;
466 zshhdr(ZRQINIT
, Txhdr
);
473 Exitcode
=0200; canit();
475 else if (zsendcmd(Cmdstr
, 1+strlen(Cmdstr
))) {
476 Exitcode
=0200; canit();
478 } else if (wcsend(npats
, patts
)==ERROR
) {
484 dm
= ((errcnt
!= 0) | Exitcode
);
493 int wcsend(argc
, argp
)
502 for (n
=0; n
<argc
; ++n
) {
504 if (wcs(argp
[n
])==ERROR
)
508 if (Filcnt
==0) { /* bitch if we couldn't open ANY files */
511 Cmdstr
= "echo \"sz: Can't open any requested files\"";
513 Exitcode
=0200; canit();
517 else if (zsendcmd(Cmdstr
, 1+strlen(Cmdstr
))) {
518 Exitcode
=0200; canit();
520 Exitcode
= 1; return OK
;
523 fprintf(stderr
,"\r\nCan't open any requested files.\r\n");
544 /* restrict pathnames to current tree or uucppublic */
545 if ( substr(name
, "../")
546 || (name
[0]== '/' && strncmp(name
, PUBDIR
, strlen(PUBDIR
))) ) {
548 fprintf(stderr
,"\r\nsz:\tSecurity Violation\r\n");
553 if ( !strcmp(oname
, "-")) {
554 if ((p
= getenv("ONAME")) && *p
)
557 sprintf(name
, "s%d.sz", getpid());
560 else if ((in
=fopen(oname
, "r"))==NULL
) {
562 return OK
; /* pass over it, there may be others */
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
) {
574 switch (wctxpn(name
)) {
580 if (!Zmodem
&& wctx(f
.st_size
)==ERROR
)
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!
599 register char *p
, *q
;
604 if ((in
!=stdin
) && *name
&& fstat(fileno(in
), &f
)!= -1) {
605 fprintf(stderr
, "Sending %s, %ld blocks: ",
608 fprintf(stderr
, "Give your local XMODEM receive command now.\r\n");
611 zperr("Awaiting pathname nak for %s", *name
?name
:"<END>");
617 if (Dottoslash
) { /* change . to . */
618 for (p
=name
; *p
; ++p
) {
624 if (q
&& strlen(++q
) > 8) { /* If name>8 chars */
625 q
+= 8; /* make it .ext */
626 strcpy(name2
, q
); /* save excess of name */
628 strcpy(++q
, name2
); /* add it back */
632 for (p
=name
, q
=txbuf
; *p
; )
633 if ((*q
++ = *p
++) == '/' && !Fullname
)
637 while (q
< (txbuf
+ 1024))
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)
648 /* force 1k blocks if name won't fit in 128 byte block */
651 else { /* A little goodie for IMP/KMD */
652 txbuf
[127] = (f
.st_size
+ 127) >>7;
653 txbuf
[126] = (f
.st_size
+ 127) >>15;
656 return zsendfile(txbuf
, 1+strlen(p
)+(p
-txbuf
));
657 if (wcputsec(txbuf
, 0, 128)==ERROR
)
668 switch (firstch
= readline(800)) {
672 Ascii
= 0; /* Receiver does the conversion */
675 zperr("Timeout on pathname");
679 mode(2); /* Set cbreak, XON/XOFF, etc. */
688 if ((firstch
= readline(20)) == CAN
&& Lastrx
== CAN
)
701 register int thisblklen
;
702 register int sectnum
, attempts
, firstch
;
705 charssent
= 0; firstsec
=TRUE
; thisblklen
= blklen
;
706 vfile("wctx:file length=%ld", flen
);
708 while ((firstch
=readline(Rxtimeout
))!=NAK
&& firstch
!= WANTCRC
709 && firstch
!= WANTG
&& firstch
!=TIMEOUT
&& firstch
!=CAN
)
712 zperr("Receiver CANcelled");
715 if (firstch
==WANTCRC
)
721 if (flen
<= (charssent
+ 896L))
723 if ( !filbuf(txbuf
, thisblklen
))
725 if (wcputsec(txbuf
, ++sectnum
, thisblklen
)==ERROR
)
727 charssent
+= thisblklen
;
737 while ((firstch
=(readline(Rxtimeout
)) != ACK
) && attempts
< RETRYMAX
);
738 if (attempts
== RETRYMAX
) {
739 zperr("No ACK on EOT");
746 int wcputsec(buf
, sectnum
, cseclen
)
749 int cseclen
; /* data length of this sector to send */
751 register checksum
, wcj
;
757 firstch
=0; /* part of logic to detect CAN CAN */
760 fprintf(stderr
, "Sector %3d %2dk\n", Totsecs
, Totsecs
/8 );
762 fprintf(stderr
, "\rSector %3d %2dk ", Totsecs
, Totsecs
/8 );
763 for (attempts
=0; attempts
<= RETRYMAX
; attempts
++) {
765 sendline(cseclen
==1024?STX
:SOH
);
767 sendline(-sectnum
-1);
769 for (wcj
=cseclen
,cp
=buf
; --wcj
>=0; ) {
771 oldcrc
=updcrc((0377& *cp
), oldcrc
);
775 oldcrc
=updcrc(0,updcrc(0,oldcrc
));
776 sendline((int)oldcrc
>>8);
777 sendline((int)oldcrc
);
783 firstsec
= FALSE
; return OK
;
785 firstch
= readline(Rxtimeout
);
791 zperr("Cancelled"); return ERROR
;
795 zperr("Timeout on sector ACK"); continue;
800 zperr("NAK on sector"); continue;
803 Totsecs
+= (cseclen
>>7);
806 zperr("Got burst for sector ACK"); break;
808 zperr("Got %02x for sector ACK", firstch
); break;
812 if ((firstch
= readline(Rxtimeout
)) == TIMEOUT
)
814 if (firstch
== NAK
|| firstch
== WANTCRC
)
816 if (firstch
== CAN
&& Lastrx
== CAN
)
820 zperr("Retry Count Exceeded");
824 /* fill buf with count chars padding with ^Z for CPM */
825 int filbuf(buf
, count
)
832 m
= read(fileno(in
), buf
, count
);
841 *buf
++ = 012; --m
; Lfseen
= 0;
843 while ((c
=getc(in
))!=EOF
) {
847 Lfseen
= TRUE
; break;
862 /* Fill buffer with blklen chars */
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
);
877 if (vpos
>= (bytcnt
+blklen
))
879 /* May be a short block if crash recovery etc. */
881 return (vpos
- bytcnt
);
883 n
= fread(txbuf
, 1, blklen
, in
);
891 int fooseek(fptr
, pos
, whence
)
897 vfile("fooseek: pos =%lu vpos=%lu Canseek=%d", pos
, vpos
, Canseek
);
898 /* Seek offset < current buffer */
899 if (pos
< (vpos
-TXBSIZE
+1024)) {
902 vpos
= pos
& ~TXBMASK
;
905 if (fseek(fptr
, vpos
, 0))
908 else if (Canseek
== 0)
909 if (fseek(fptr
, vpos
= 0L, 0))
913 while (vpos
<= pos
) {
914 n
= fread(Txb
, 1, TXBSIZE
, fptr
);
916 vfile("n=%d vpos=%ld", n
, vpos
);
922 vfile("vpos=%ld", vpos
);
925 /* Seek offset > current buffer (crash recovery, etc.) */
928 if (fseek(fptr
, vpos
= (pos
& ~TXBMASK
), 0))
930 while (vpos
<= pos
) {
931 txbuf
= Txb
+ (vpos
& TXBMASK
);
932 m
= TXBSIZE
- (vpos
& TXBMASK
);
933 n
= fread(txbuf
, 1, m
, fptr
);
935 vfile("bo=%d n=%d vpos=%ld", txbuf
-Txb
, n
, vpos
);
943 /* Seek offset is within current buffer */
944 vfile("vpos=%ld", vpos
);
947 #define fseek fooseek
952 void vfile(f
, a
, b
, c
)
953 register char *f
,*a
,*b
,*c
;
956 fprintf(stderr
, f
, a
, b
, c
);
957 fprintf(stderr
, "\n");
971 * readline(timeout) reads character(s) from file descriptor 0
972 * timeout is in tenths of seconds
974 int readline(timeout
)
981 if (setjmp(tohere
)) {
989 fprintf(stderr
, "Timeout=%d Calling alarm(%d) ", timeout
, c
);
991 signal(SIGALRM
, alrm
); alarm(c
);
992 c
=read(iofd
, byt
, 1);
995 fprintf(stderr
, "ret %x\n", byt
[0]);
998 return (byt
[0]&0377);
1010 ioctl(iofd
, TCFLSH
, 0);
1017 /* send cancel string to get the other end to shut up */
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
1025 raw_wbuf(strlen(canistr
), canistr
);
1043 fprintf(stderr
, "\nRetry %d: ", errors
);
1044 fprintf(stderr
, s
, p
, u
);
1045 fprintf(stderr
, "\n");
1049 * substr(string, token) searches for token in string s
1050 * returns pointer to token within string if found, NULL otherwise
1054 register char *s
,*t
;
1056 register char *ss
,*tt
;
1057 /* search for first char of token */
1060 /* compare token with substring */
1061 for (ss
=s
,tt
=t
; ;) {
1067 return (char *)NULL
;
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",
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",
1086 " 2 Use 2 stop bits",
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)",
1093 " d Change '.' to '/' in pathnames (Y/Z)",
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)",
1108 " u Unlink file after transmission",
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",
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",
1126 fprintf(stderr
, "\t\t\042The High Reliability Software\042\n");
1132 * Get the receiver's init parameters
1139 for (n
=10; --n
>=0; ) {
1141 switch (zgethdr(Rxhdr
, 1)) {
1142 case ZCHALLENGE
: /* Echo receiver's challenge numbr */
1144 zshhdr(ZACK
, Txhdr
);
1146 case ZCOMMAND
: /* They didn't see out ZRQINIT */
1148 zshhdr(ZRQINIT
, Txhdr
);
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
))
1157 vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen
, Tframlen
);
1159 signal(SIGINT
, SIG_IGN
);
1161 mode(2); /* Set cbreak, XON/XOFF, etc. */
1165 /* Use 1024 byte frames if no sample/interrupt */
1166 if (Rxbuflen
< 32 || Rxbuflen
> 1024) {
1168 vfile("Rxbuflen=%d", Rxbuflen
);
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
);
1180 /* If using a pipe for testing set lower buf len */
1182 if ((f
.st_mode
& S_IFMT
) != S_IFCHR
) {
1188 Txwindow
= TXBSIZE
- 1024;
1189 Txwspac
= TXBSIZE
/4;
1192 * If input is not a regular file, force ACK's to
1193 * prevent running beyond the buffer limits
1196 fstat(fileno(in
), &f
);
1197 if ((f
.st_mode
& S_IFMT
) != S_IFREG
) {
1200 Txwindow
= TXBSIZE
- 1024;
1201 Txwspac
= TXBSIZE
/4;
1207 /* Set initial subpacket length */
1208 if (blklen
< 1024) { /* Command line override? */
1211 if (Baudrate
> 1200)
1213 if (Baudrate
> 2400)
1216 if (Rxbuflen
&& blklen
>Rxbuflen
)
1218 if (blkopt
&& blklen
> blkopt
)
1220 vfile("Rxbuflen=%d blklen=%d", Rxbuflen
, blklen
);
1221 vfile("Txwindow = %u Txwspac = %d", Txwindow
, Txwspac
);
1223 return (sendzsinit());
1228 if (Rxhdr
[ZF0
] == ZCOMMAND
)
1231 zshhdr(ZNAK
, Txhdr
);
1238 /* Send send-init information */
1243 if (Myattn
[0] == '\0' && (!Zctlesc
|| (Rxflags
& TESCCTL
)))
1249 Txhdr
[ZF0
] |= TESCCTL
; zshhdr(ZSINIT
, Txhdr
);
1252 zsbhdr(ZSINIT
, Txhdr
);
1253 zsdata(Myattn
, 1+strlen(Myattn
), ZCRCW
);
1254 c
= zgethdr(Rxhdr
, 1);
1268 /* Send file name and related info */
1269 int zsendfile(buf
, blen
)
1274 register UNSL
long crc
;
1277 Txhdr
[ZF0
] = Lzconv
; /* file conversion request */
1278 Txhdr
[ZF1
] = Lzmanag
; /* file management request */
1280 Txhdr
[ZF1
] |= ZMSKNOLOC
;
1281 Txhdr
[ZF2
] = Lztrans
; /* file transport request */
1283 zsbhdr(ZFILE
, Txhdr
);
1284 zsdata(buf
, blen
, ZCRCW
);
1286 c
= zgethdr(Rxhdr
, 1);
1289 while ((c
= readline(50)) > 0)
1293 /* **** FALL THRU TO **** */
1304 while (((c
= getc(in
)) != EOF
) && --Rxpos
)
1305 crc
= UPDC32(c
, crc
);
1307 clearerr(in
); /* Clear EOF */
1311 zsbhdr(ZCRC
, Txhdr
);
1314 fclose(in
); return c
;
1317 * Suppress zcrcw request otherwise triggered by
1320 if (Rxpos
&& fseek(in
, Rxpos
, 0))
1322 Lastsync
= (bytcnt
= Txpos
= Rxpos
) -1;
1323 return zsendfdata();
1328 /* Send the data in the file */
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 */
1341 if (setjmp(intrjmp
)) {
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
1367 while (rdchk(iofd
)) {
1371 switch (readline(1))
1378 case XOFF
: /* Wait a while for an XON */
1387 signal(SIGINT
, onintr
);
1391 zsbhdr(ZDATA
, Txhdr
);
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.
1400 while (tcount
< 20000) {
1401 printf(qbf
); fflush(stdout
);
1402 tcount
+= strlen(qbf
);
1404 while (rdchk(iofd
)) {
1408 switch (readline(1))
1414 ioctl(iofd
, TCFLSH
, 1);
1417 case XOFF
: /* Wait for XON */
1424 signal(SIGINT
, SIG_IGN
); canit();
1425 sleep(3); purgeline(); mode(0);
1426 printf("\nsz: Tcount = %ld\n", tcount
);
1428 printf("ERROR: Interrupts Not Caught\n");
1438 else if (junkcount
> 3)
1440 else if (bytcnt
== Lastsync
)
1442 else if (Rxbuflen
&& (newcnt
-= n
) <= 0)
1444 else if (Txwindow
&& (Txwcnt
+= n
) >= Txwspac
) {
1445 Txwcnt
= 0; e
= ZCRCQ
;
1450 fprintf(stderr
, "\r%7ld ZMODEM%s ",
1451 Txpos
, Crc32t
?" CRC-32":"");
1452 zsdata(txbuf
, n
, e
);
1453 bytcnt
= Txpos
+= n
;
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
1464 while (rdchk(iofd
)) {
1468 switch (readline(1))
1477 ioctl(iofd
, TCFLSH
, 1);
1479 /* zcrce - dinna wanna starta ping-pong game */
1480 zsdata(txbuf
, 0, ZCRCE
);
1482 case XOFF
: /* Wait a while for an XON */
1489 #endif /* READCHECK */
1491 while ((tcount
= Txpos
- Lrxpos
) >= Txwindow
) {
1492 vfile("%ld window >= %u", tcount
, Txwindow
);
1494 zsdata(txbuf
, 0, e
= ZCRCQ
);
1498 ioctl(iofd
, TCFLSH
, 1);
1500 zsdata(txbuf
, 0, ZCRCE
);
1504 vfile("window = %ld", tcount
);
1508 signal(SIGINT
, SIG_IGN
);
1512 zsbhdr(ZEOF
, Txhdr
);
1513 switch (getinsync(0)) {
1531 * Respond to receiver's complaint, get back in sync with receiver
1540 printf("\r\n\n\n***** Signal Caught *****\r\n");
1541 Rxpos
= 0; c
= ZRPOS
;
1543 c
= zgethdr(Rxhdr
, 0);
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))
1559 bytcnt
= Lrxpos
= Txpos
= Rxpos
;
1560 if (Lastsync
== Rxpos
) {
1561 if (++Beenhereb4
> 4)
1569 if (flag
|| Txpos
== Rxpos
)
1578 zsbhdr(ZNAK
, Txhdr
);
1585 /* Say "bibi" to the receiver, try to do it cleanly */
1589 stohdr(0L); /* CAF Was zsbhdr - minor change */
1590 zshhdr(ZFIN
, Txhdr
); /* to make debugging easier */
1591 switch (zgethdr(Rxhdr
, 0)) {
1593 sendline('O'); sendline('O'); flushmo();
1601 /* Local screen character display function */
1609 /* Send command and related info */
1610 int zsendcmd(buf
, blen
)
1621 Txhdr
[ZF0
] = Cmdack1
;
1622 zsbhdr(ZCOMMAND
, Txhdr
);
1623 zsdata(buf
, blen
, ZCRCW
);
1625 Rxtimeout
= 100; /* Ten second wait for resp. */
1626 c
= zgethdr(Rxhdr
, 1);
1630 goto listen
; /* CAF 8-21-87 */
1633 if (++errors
> Cmdtries
)
1651 #ifdef vax11c /* YAMP :== Yet Another Missing Primitive */
1654 vfile("******** RZ *******");
1656 vfile("******** SZ *******");
1664 * If called as sb use YMODEM protocol
1684 if (s
[0]=='s' && s
[1]=='b') {
1685 Nozmodem
= TRUE
; blklen
=1024;
1687 if (s
[0]=='s' && s
[1]=='x') {
1693 void countem(argc
, argv
)
1695 register char **argv
;
1700 for (Totalleft
= 0, Filesleft
= 0; --argc
>=0; ++argv
) {
1703 fprintf(stderr
, "\nCountem: %03d %s ", argc
, *argv
);
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
;
1713 fprintf(stderr
, " %ld", f
.st_size
);
1716 fprintf(stderr
, "\ncountem: Total %d %ld\n",
1717 Filesleft
, Totalleft
);
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
);
1731 for (n
= 0; n
< 256; ++n
) {
1734 printf("%02x ", n
); fflush(stdout
);
1735 sendline(n
); flushmo();
1736 printf(" "); fflush(stdout
);
1738 printf("Hit Enter.\021"); fflush(stdout
);
1740 printf("\r\n"); fflush(stdout
);
1743 printf("\021\r\nEnter Characters, echo is in hex.\r\n");
1744 printf("Hit SPACE or pause 40 seconds for exit.\r\n");
1746 while (n
!= TIMEOUT
&& n
!= ' ') {
1748 printf("%02x\r\n", n
);
1751 printf("\r\nMode %d character transparency test ends.\r\n", m
);