1 #define VERSION "2.03 05-17-88"
2 #define PUBDIR "/usr/spool/uucppublic"
4 /*% cc -compat -M2 -Ox -K -i -DMD -DOMEN % -o rz; size rz;
5 <-xtx-*> cc386 -Ox -DMD -DOMEN -DSEGMENTS=8 rz.c -o $B/rz; size $B/rz
7 * rz.c By Chuck Forsberg
9 * cc -O rz.c -o rz USG (3.0) Unix
10 * cc -O -DV7 rz.c -o rz Unix V7, BSD 2.8 - 4.3
12 * ln rz rb; ln rz rx For either system
14 * ln rz /usr/bin/rzrmail For remote mail. Make this the
15 * login shell. rzrmail then calls
16 * rmail(1) to deliver mail.
20 * define LNK$LIBRARY SYS$LIBRARY:VAXCRTL.OLB
24 * rz :== $disk:[username.subdir]rz.exe
27 * Unix is a trademark of Western Electric Company
29 * A program for Unix to receive files and commands from computers running
30 * Professional-YAM, PowerCom, YAM, IMP, or programs supporting XMODEM.
31 * rz uses Unix buffered input to reduce wasted CPU time.
33 * Iff the program is invoked by rzCOMMAND, output is piped to
34 * "COMMAND filename" (Unix only)
36 * Some systems (Venix, Coherent, Regulus) may not support tty raw mode
37 * read(2) the same way as Unix. ONEREAD must be defined to force one
38 * character reads for these systems. Added 7-01-84 CAF
40 * Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF
42 * BIX added 6-30-87 to support BIX(TM) upload protocol used by the
43 * Byte Information Exchange.
45 * NFGVMIN Updated 2-18-87 CAF for Xenix systems where c_cc[VMIN]
46 * doesn't work properly (even though it compiles without error!),
48 * SEGMENTS=n added 2-21-88 as a model for CP/M programs
49 * for CP/M-80 systems that cannot overlap modem and disk I/O.
51 * VMS flavor hacks begin with rz version 2.00
53 * -DMD may be added to compiler command line to compile in
54 * Directory-creating routines from Public Domain TAR by John Gilmore
56 * HOWMANY may be tuned for best performance
58 * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
61 #include <sys/types.h>
66 #define LOGFILE "rzlog.tmp"
70 #define SS_NORMAL SS$_NORMAL
74 #define LOGFILE "/tmp/rzlog"
97 int main(int argc
, char *argv
[]);
99 int wcreceive(int argc
, char **argp
);
100 int wcrxpn(char *rpn
);
102 int wcgetsec(char *rxbuf
, int maxtime
);
103 int readline(int timeout
);
104 void purgeline(void);
105 int procheader(char *name
);
106 int make_dirs(char *pathname
);
107 int makedir(char *dpath
, int dmode
);
108 int putsec(char *buf
, int n
);
109 void sendline(int c
);
111 void uncaps(char *s
);
112 int IsAnyLower(char *s
);
113 char *substr(char *s
, char *t
);
116 void report(int sct
);
117 void chkinvok(char *s
);
118 void checkpath(char *name
);
122 void zmputs(char *s
);
125 void bttyout(int c
);
127 void exec2(char *s
);
130 * Max value for HOWMANY is 255.
131 * A larger value reduces system overhead but may evoke kernel bugs.
132 * 133 corresponds to an XMODEM/CRC sector
138 /* Ward Christensen / CP/M parameters - Don't change these! */
140 #define CAN ('X'&037)
141 #define XOFF ('s'&037)
142 #define XON ('q'&037)
149 #define WANTCRC 0103 /* send C not NAK to get crc not checksum */
155 #define PATHLEN 257 /* ready for 4.2 bsd ? */
156 #define UNIXFILE 0xF000 /* The S_IFMT file mask bit for stat */
158 int Zmodem
=0; /* ZMODEM protocol requested */
159 int Nozmodem
= 0; /* If invoked as "rb" */
160 unsigned Baudrate
= 2400;
163 #include "vrzsz.c" /* most of the system dependent stuff here */
165 #include "rbsb.c" /* most of the system dependent stuff here */
173 * Routine to calculate the free bytes on the current file system
174 * ~0 means many free bytes (unknown)
178 return(~0L); /* many free bytes ... */
184 int Eofseen
; /* indicates cpm eof (^Z) has been received */
186 int Restricted
=0; /* restricted; no /.. or ../ in filenames */
188 /* Sorry, Regulus and some others don't work right in raw mode! */
189 int Readnum
= 1; /* Number of bytes to ask for in read() from modem */
191 int Readnum
= HOWMANY
; /* Number of bytes to ask for in read() from modem */
194 #define DEFBYTL 2000000000L /* default rx file size */
195 long Bytesleft
; /* number of bytes of incoming file left */
196 long Modtime
; /* Unix style mod time for incoming file */
197 int Filemode
; /* Unix style mode for incoming file */
198 char Pathname
[PATHLEN
];
199 char *Progname
; /* the name by which we were called */
203 int MakeLCPathname
=TRUE
; /* make received pathname lower case */
205 int Quiet
=0; /* overrides logic that would otherwise set verbose */
206 int Nflag
= 0; /* Don't really transfer files */
207 int Rxclob
=FALSE
; /* Clobber existing file */
208 int Rxbinary
=FALSE
; /* receive all files in bin mode */
209 int Rxascii
=FALSE
; /* receive files in ascii (translate) mode */
210 int Thisbinary
; /* current file is to be received in bin mode */
211 int Blklen
; /* record length of received packets */
214 int chinseg
= 0; /* Number of characters received in this data seg */
215 char secbuf
[1+(SEGMENTS
+1)*1024];
221 char linbuf
[HOWMANY
];
222 int Lleft
=0; /* number of characters in linbuf */
224 char Lzmanag
; /* Local file management request */
225 char zconv
; /* ZMODEM file conversion request */
226 char zmanag
; /* ZMODEM file management request */
227 char ztrans
; /* ZMODEM file transport request */
228 int Zctlesc
; /* Encode control characters */
229 int Zrwindow
= 1400; /* RX window size (controls garbage count) */
231 jmp_buf tohere
; /* For the interrupt on RX timeout */
233 #define xsendline(c) sendline(c)
236 int tryzhdrtype
=ZRINIT
; /* Header type to send corresponding to Last rx close */
244 /* called by signal interrupt or terminate to clean things up */
251 fprintf(stderr
, "rz: caught signal %d; exiting\n", n
);
262 char *virgin
, **patts
;
266 setbuf(stderr
, (char *)NULL
);
267 if ((cp
=getenv("SHELL")) && (substr(cp
, "rsh") || substr(cp
, "rksh")))
272 Progname
= virgin
= "rz";
274 chkinvok(virgin
=argv
[0]); /* if called as [-]rzCOMMAND set flag */
283 cp
[1] = toupper(cp
[1]); continue;
285 Lzmanag
= ZMAPND
; break;
289 Rxbinary
=TRUE
; break;
299 Lzmanag
= ZMPROT
; break;
301 Quiet
=TRUE
; Verbose
=0; break;
306 Rxtimeout
= atoi(*++argv
);
307 if (Rxtimeout
<10 || Rxtimeout
>1000)
314 Zrwindow
= atoi(*++argv
);
317 MakeLCPathname
=FALSE
; break;
327 else if ( !npats
&& argc
>0) {
339 if (freopen(LOGFILE
, "a", stderr
)==NULL
) {
340 printf("Can't open log file %s\n",LOGFILE
);
343 setbuf(stderr
, (char *)NULL
);
344 fprintf(stderr
, "argv[0]=%s Progname=%s\n", virgin
, Progname
);
346 if (Fromcu
&& !Quiet
) {
350 vfile("%s %s for %s\n", Progname
, VERSION
, OS
);
352 if (signal(SIGINT
, bibi
) == SIG_IGN
) {
353 signal(SIGINT
, SIG_IGN
); signal(SIGKILL
, SIG_IGN
);
356 signal(SIGINT
, bibi
); signal(SIGKILL
, bibi
);
358 signal(SIGTERM
, bibi
);
359 if (wcreceive(npats
, patts
)==ERROR
) {
364 vfile("exitcode = %d\n",exitcode
);
365 if (exitcode
&& !Zmodem
) /* bellow again with all thy might. */
369 if (Verbose
) putc('\n', stderr
);
370 exit(exitcode
? exitcode
:SS_NORMAL
);
378 fprintf(stderr
,"Usage: rz [-abeuvy]\n");
380 fprintf(stderr
,"Usage: rz [-abeuvy] (ZMODEM)\n");
381 fprintf(stderr
,"or rb [-abuvy] (YMODEM)\n");
382 fprintf(stderr
,"or rx [-abcv] file (XMODEM or XMODEM-1k)\n");
384 fprintf(stderr
," -a ASCII transfer (strip CR)\n");
385 fprintf(stderr
," -b Binary transfer for all files\n");
387 fprintf(stderr
," -c Use 16 bit CRC (XMODEM)\n");
389 fprintf(stderr
," -e Escape control characters (ZMODEM)\n");
390 fprintf(stderr
," -v Verbose more v's give more info\n");
391 fprintf(stderr
," -y Yes, clobber existing file if any\n");
392 fprintf(stderr
,"%s %s for %s by Chuck Forsberg, Omen Technology INC\n",
393 Progname
, VERSION
, OS
);
394 fprintf(stderr
, "\t\t\042The High Reliability Software\042\n");
398 * Debugging information output interface routine
401 void vfile(f
, a
, b
, c
)
402 register char *f
,*a
,*b
,*c
;
406 fprintf(stderr
, f
, a
, b
, c
);
407 fprintf(stderr
, "\n");
412 * Let's receive something already.
416 "%s ready. To begin transfer, type \"%s file ...\" to your modem program\r\n\n";
418 int wcreceive(argc
, argp
)
424 if (Batch
|| argc
==0) {
427 fprintf(stderr
, rbmsg
, Progname
, Nozmodem
?"sb":"sz");
438 if (wcrxpn(secbuf
)== ERROR
)
442 if (procheader(secbuf
) == ERROR
)
449 Bytesleft
= DEFBYTL
; Filemode
= 0; Modtime
= 0L;
451 procheader(""); strcpy(Pathname
, *argp
); checkpath(Pathname
);
452 fprintf(stderr
, "\nrz: ready to receive %s\r\n", Pathname
);
453 if ((fout
=fopen(Pathname
, "w")) == NULL
)
462 if (Topipe
&& fout
) {
463 pclose(fout
); return ERROR
;
471 fprintf(stderr
, "\r\nrz: %s removed.\r\n", Pathname
);
479 * Fetch a pathname from the other end as a C ctyle ASCIZ string.
480 * Length is indeterminate as long as less than Blklen
481 * A null string represents no more files (YMODEM)
484 char *rpn
; /* receive a pathname */
495 Firstsec
=TRUE
; Eofseen
=FALSE
;
496 sendline(Crcflg
?WANTCRC
:NAK
);
497 Lleft
=0; /* Do read next time ... */
498 while ((c
= wcgetsec(rpn
, 100)) != 0) {
500 zperr( "Pathname fetch returned %d", c
);
502 Lleft
=0; /* Do read next time ... */
513 * Adapted from CMODEM13.C, written by
514 * Jack M. Wierda and Roderick W. Hart
519 register int sectnum
, sectcurr
;
520 register char sendchar
;
521 int cblklen
; /* bytes to dump this block */
523 Firstsec
=TRUE
;sectnum
=0; Eofseen
=FALSE
;
524 sendchar
=Crcflg
?WANTCRC
:NAK
;
527 sendline(sendchar
); /* send it now, we're ready! */
528 Lleft
=0; /* Do read next time ... */
529 sectcurr
=wcgetsec(secbuf
, (sectnum
&0177)?50:130);
531 if (sectcurr
==((sectnum
+1) &0377)) {
533 cblklen
= Bytesleft
>Blklen
? Blklen
:Bytesleft
;
534 if (putsec(secbuf
, cblklen
)==ERROR
)
536 if ((Bytesleft
-=cblklen
) < 0)
540 else if (sectcurr
==(sectnum
&0377)) {
541 zperr( "Received dup Sector");
544 else if (sectcurr
==WCEOT
) {
548 Lleft
=0; /* Do read next time ... */
551 else if (sectcurr
==ERROR
)
554 zperr( "Sync Error");
561 * Wcgetsec fetches a Ward Christensen type sector.
562 * Returns sector number encountered or ERROR if valid sector not received,
563 * or CAN CAN received
564 * or WCEOT if eot sector
565 * time is timeout for first char, set to 4 seconds thereafter
566 ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
567 * (Caller must do that when he is good and ready to get next sector)
570 int wcgetsec(rxbuf
, maxtime
)
574 register checksum
, wcj
, firstch
;
575 register unsigned short oldcrc
;
579 for (Lastrx
=errors
=0; errors
<RETRYMAX
; errors
++) {
581 if ((firstch
=readline(maxtime
))==STX
) {
582 Blklen
=1024; goto get2
;
587 sectcurr
=readline(1);
588 if ((sectcurr
+(oldcrc
=readline(1)))==0377) {
590 for (p
=rxbuf
,wcj
=Blklen
; --wcj
>=0; ) {
591 if ((firstch
=readline(1)) < 0)
593 oldcrc
=updcrc(firstch
, oldcrc
);
594 checksum
+= (*p
++ = firstch
);
596 if ((firstch
=readline(1)) < 0)
599 oldcrc
=updcrc(firstch
, oldcrc
);
600 if ((firstch
=readline(1)) < 0)
602 oldcrc
=updcrc(firstch
, oldcrc
);
610 else if (((checksum
-firstch
)&0377)==0) {
618 zperr("Sector number garbled");
620 /* make sure eot really is eot and not just mixmash */
622 else if (firstch
==EOT
&& readline(1)==TIMEOUT
)
625 else if (firstch
==EOT
&& Lleft
==0)
628 else if (firstch
==CAN
) {
630 zperr( "Sender CANcelled");
637 else if (firstch
==TIMEOUT
) {
644 zperr( "Got 0%o sector header", firstch
);
648 while(readline(1)!=TIMEOUT
)
651 sendline(Crcflg
?WANTCRC
:NAK
);
652 Lleft
=0; /* Do read next time ... */
654 maxtime
=40; sendline(NAK
);
655 Lleft
=0; /* Do read next time ... */
658 /* try to stop the bubble machine. */
665 * This version of readline is reasoably well suited for
666 * reading many characters.
667 * (except, currently, for the Regulus version!)
669 * timeout is in tenths of seconds
671 int readline(timeout
)
675 static char *cdq
; /* pointer for removing chars from linbuf */
679 fprintf(stderr
, "%02x ", *cdq
&0377);
681 return (*cdq
++ & 0377);
687 fprintf(stderr
, "Calling read: alarm=%d Readnum=%d ",
689 if (setjmp(tohere
)) {
691 /* ioctl(iofd, TIOCFLUSH, 0); */
695 fprintf(stderr
, "Readline:TIMEOUT\n");
698 signal(SIGALRM
, alrm
); alarm(n
);
699 Lleft
=read(iofd
, cdq
=linbuf
, Readnum
);
702 fprintf(stderr
, "Read returned %d bytes\n", Lleft
);
708 fprintf(stderr
, "%02x ", *cdq
&0377);
710 return (*cdq
++ & 0377);
716 * Purge the modem input queue of all characters
722 ioctl(iofd
, TCFLSH
, 0);
731 * Process incoming file information header
736 register char *openmode
, *p
;
738 /* set default parameters and overrides */
740 Thisbinary
= (!Rxascii
) || Rxbinary
;
745 * Process ZMODEM remote file management requests
747 if (!Rxbinary
&& zconv
== ZCNL
) /* Remote ASCII override */
749 if (zconv
== ZCBIN
) /* Remote Binary override */
751 else if (zmanag
== ZMAPND
)
755 /* Check for existing file */
756 if (!Rxclob
&& (zmanag
&ZMMASK
) != ZMCLOB
&& (fout
=fopen(name
, "r"))) {
757 fclose(fout
); return ERROR
;
761 Bytesleft
= DEFBYTL
; Filemode
= 0; Modtime
= 0L;
763 p
= name
+ 1 + strlen(name
);
764 if (*p
) { /* file coming from Unix or DOS system */
765 sscanf(p
, "%ld%lo%o", &Bytesleft
, &Modtime
, &Filemode
);
767 if (Filemode
& UNIXFILE
)
771 fprintf(stderr
, "\nIncoming: %s %ld %lo %o\n",
772 name
, Bytesleft
, Modtime
, Filemode
);
777 if ((fout
=fopen("scratchpad", openmode
)) == NULL
)
782 else { /* File coming from CP/M system */
783 for (p
=name
; *p
; ++p
) /* change / to _ */
787 if ( *--p
== '.') /* zap trailing period */
792 if (!Zmodem
&& MakeLCPathname
&& !IsAnyLower(name
)
793 && !(Filemode
&UNIXFILE
))
797 sprintf(Pathname
, "%s %s", Progname
+2, name
);
799 fprintf(stderr
, "Topipe: %s %s\n",
800 Pathname
, Thisbinary
?"BIN":"ASCII");
802 if ((fout
=popen(Pathname
, "w")) == NULL
)
806 strcpy(Pathname
, name
);
808 fprintf(stderr
, "Receiving %s %s %s\n",
809 name
, Thisbinary
?"BIN":"ASCII", openmode
);
816 if (name
[0] == '!' || name
[0] == '|') {
817 if ( !(fout
= popen(name
+1, "w"))) {
820 Topipe
= -1; return(OK
);
825 fout
= fopen(name
, openmode
);
828 fout
= fopen(name
, openmode
);
830 fout
= fopen(name
, openmode
);
841 * Directory-creating routines from Public Domain TAR by John Gilmore
845 * After a file/link/symlink/dir creation has failed, see if
846 * it's because some required directory was not present, and if
847 * so, create all required dirs.
849 int make_dirs(pathname
)
850 register char *pathname
;
852 register char *p
; /* Points into path */
853 int madeone
= 0; /* Did we do anything yet? */
854 int save_errno
= errno
; /* Remember caller's errno */
858 return 0; /* Not our problem */
860 for (p
= strchr(pathname
, '/'); p
!= NULL
; p
= strchr(p
+1, '/')) {
861 /* Avoid mkdir of empty string, if leading or double '/' */
862 if (p
== pathname
|| p
[-1] == '/')
864 /* Avoid mkdir where last part of path is '.' */
865 if (p
[-1] == '.' && (p
== pathname
+1 || p
[-2] == '/'))
867 *p
= 0; /* Truncate the path there */
868 if ( !makedir(pathname
, 0777)) { /* Try to create it as a dir */
869 vfile("Made directory %s\n", pathname
);
870 madeone
++; /* Remember if we made one */
875 if (errno
== EEXIST
) /* Directory already exists */
878 * Some other error in the makedir. We return to the caller.
882 errno
= save_errno
; /* Restore caller's errno */
883 return madeone
; /* Tell them to retry if we made one */
887 #define TERM_SIGNAL(status) ((status) & 0x7F)
888 #define TERM_COREDUMP(status) (((status) & 0x80) != 0)
889 #define TERM_VALUE(status) ((status) >> 8)
891 * Make a directory. Compatible with the mkdir() system call on 4.2BSD.
893 int makedir(dpath
, dmode
)
900 if (stat(dpath
,&statbuf
) == 0) {
901 errno
= EEXIST
; /* Stat worked, so it already exists */
905 /* If stat fails for a reason other than non-existence, return error */
906 if (errno
!= ENOENT
) return -1;
908 switch (cpid
= fork()) {
910 case -1: /* Error in fork() */
911 return(-1); /* Errno is set already */
913 case 0: /* Child process */
915 * Cheap hack to set mode of new directory. Since this
916 * child process is going away anyway, we zap its umask.
917 * FIXME, this won't suffice to set SUID, SGID, etc. on this
918 * directory. Does anybody care?
920 status
= umask(0); /* Get current umask */
921 status
= umask(status
| (0777 & ~dmode
)); /* Set for mkdir */
922 execl("/bin/mkdir", "mkdir", dpath
, (char *)0);
923 _exit(-1); /* Can't exec /bin/mkdir */
925 default: /* Parent process */
926 while (cpid
!= wait(&status
)) ; /* Wait for kid to finish */
929 if (TERM_SIGNAL(status
) != 0 || TERM_VALUE(status
) != 0) {
930 errno
= EIO
; /* We don't know why, but */
931 return -1; /* /bin/mkdir failed */
940 * Putsec writes the n characters of buf to receive file fout.
941 * If not in binary mode, carriage returns, and all characters
942 * starting with CPMEOF are discarded.
953 for (p
=buf
; --n
>=0; )
959 for (p
=buf
; --n
>=0; ++p
) {
963 Eofseen
=TRUE
; return OK
;
973 * Send a character to modem. Small is beautiful.
982 fprintf(stderr
, "Sendline: %x\n", c
);
993 /* make string s lower case */
1002 * IsAnyLower returns TRUE if string s has lower case letters.
1014 * substr(string, token) searches for token in string s
1015 * returns pointer to token within string if found, NULL otherwise
1019 register char *s
,*t
;
1021 register char *ss
,*tt
;
1022 /* search for first char of token */
1025 /* compare token with substring */
1026 for (ss
=s
,tt
=t
; ;) {
1032 return (char *)NULL
;
1044 fprintf(stderr
, "Retry %d: ", errors
);
1045 fprintf(stderr
, s
, p
, u
);
1046 fprintf(stderr
, "\n");
1049 /* send cancel string to get the other end to shut up */
1052 static char canistr
[] = {
1053 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
1057 raw_wbuf(strlen(canistr
), canistr
);
1061 Lleft
=0; /* Do read next time ... */
1071 fprintf(stderr
,"%03d%c",sct
,sct
%10? ' ' : '\r');
1076 * If called as [-][dir/../]vrzCOMMAND set Verbose to 1
1077 * If called as [-][dir/../]rzCOMMAND set the pipe flag
1078 * If called as rb use YMODEM protocol
1095 if (s
[0]=='r' && s
[1]=='z')
1097 if (s
[0]=='r' && s
[1]=='b')
1098 Batch
= Nozmodem
= TRUE
;
1099 if (s
[2] && s
[0]=='r' && s
[1]=='b')
1101 if (s
[2] && s
[0]=='r' && s
[1]=='z')
1107 * Totalitarian Communist pathname processing
1109 void checkpath(name
)
1113 if (fopen(name
, "r") != NULL
) {
1115 fprintf(stderr
, "\r\nrz: %s exists\n", name
);
1118 /* restrict pathnames to current tree or uucppublic */
1119 if ( substr(name
, "../")
1120 || (name
[0]== '/' && strncmp(name
, PUBDIR
, strlen(PUBDIR
))) ) {
1122 fprintf(stderr
,"\r\nrz:\tSecurity Violation\r\n");
1129 * Initialize for Zmodem receive attempt, try to activate Zmodem sender
1130 * Handles ZSINIT frame
1131 * Return ZFILE if Zmodem filename received, -1 on error,
1132 * ZCOMPL if transaction finished, else 0
1137 register cmdzack1flg
;
1139 if (Nozmodem
) /* Check for "rb" program name */
1143 for (n
=Zmodem
?15:5; --n
>=0; ) {
1144 /* Set buffer length (0) and capability flags */
1146 stohdr(SEGMENTS
*1024L);
1151 Txhdr
[ZF0
] = CANFC32
|CANFDX
|CANOVIO
|CANBRK
;
1153 Txhdr
[ZF0
] = CANFC32
|CANFDX
|CANOVIO
;
1156 Txhdr
[ZF0
] |= TESCCTL
;
1157 zshhdr(tryzhdrtype
, Txhdr
);
1158 if (tryzhdrtype
== ZSKIP
) /* Don't skip too far */
1159 tryzhdrtype
= ZRINIT
; /* CAF 8-21-87 */
1161 switch (zgethdr(Rxhdr
, 0)) {
1170 zmanag
= Rxhdr
[ZF1
];
1171 ztrans
= Rxhdr
[ZF2
];
1172 tryzhdrtype
= ZRINIT
;
1173 c
= zrdata(secbuf
, 1024);
1177 zshhdr(ZNAK
, Txhdr
);
1180 Zctlesc
= TESCCTL
& Rxhdr
[ZF0
];
1181 if (zrdata(Attn
, ZATTNLEN
) == GOTCRCW
) {
1183 zshhdr(ZACK
, Txhdr
);
1186 zshhdr(ZNAK
, Txhdr
);
1190 zshhdr(ZACK
, Txhdr
);
1196 cmdzack1flg
= Rxhdr
[ZF0
];
1197 if (zrdata(secbuf
, 1024) == GOTCRCW
) {
1198 if (cmdzack1flg
& ZCACK1
)
1201 stohdr((long)sys2(secbuf
));
1202 purgeline(); /* dump impatient questions */
1204 zshhdr(ZCOMPL
, Txhdr
);
1206 while (++errors
<20 && zgethdr(Rxhdr
,1) != ZFIN
);
1208 if (cmdzack1flg
& ZCACK1
)
1212 zshhdr(ZNAK
, Txhdr
); goto again
;
1219 ackbibi(); return ZCOMPL
;
1228 * Receive 1 or more files with ZMODEM protocol
1235 switch (c
= rzfile()) {
1256 * Receive a file with ZMODEM protocol
1257 * Assumes file name frame is in secbuf
1265 if (procheader(secbuf
) == ERROR
) {
1266 return (tryzhdrtype
= ZSKIP
);
1269 n
= 20; rxbytes
= 0l;
1276 zshhdr(ZRPOS
, Txhdr
);
1278 switch (c
= zgethdr(Rxhdr
, 0)) {
1280 vfile("rzfile: zgethdr returned %d", c
);
1285 putsec(secbuf
, chinseg
);
1289 vfile("rzfile: zgethdr returned %d", c
);
1293 zrdata(secbuf
, 1024);
1297 putsec(secbuf
, chinseg
);
1300 if (rclhdr(Rxhdr
) != rxbytes
) {
1302 * Ignore eof if it's at wrong place - force
1303 * a timeout because the eof might have gone
1304 * out before we sent our zrpos.
1306 errors
= 0; goto nxthdr
;
1309 tryzhdrtype
= ZFERR
;
1310 vfile("rzfile: closeit returned <> 0");
1313 vfile("rzfile: normal EOF");
1315 case ERROR
: /* Too much garbage in header search error */
1317 putsec(secbuf
, chinseg
);
1321 vfile("rzfile: zgethdr returned %d", c
);
1328 putsec(secbuf
, chinseg
);
1332 vfile("rzfile: Sender SKIPPED file");
1335 if (rclhdr(Rxhdr
) != rxbytes
) {
1340 putsec(secbuf
, chinseg
);
1343 zmputs(Attn
); continue;
1347 fprintf(stderr
, "\r%7ld ZMODEM%s ",
1348 rxbytes
, Crc32
?" CRC-32":"");
1350 if (chinseg
>= (1024 * SEGMENTS
)) {
1351 putsec(secbuf
, chinseg
);
1354 switch (c
= zrdata(secbuf
+chinseg
, 1024))
1356 switch (c
= zrdata(secbuf
, 1024))
1361 putsec(secbuf
, chinseg
);
1364 vfile("rzfile: zgethdr returned %d", c
);
1366 case ERROR
: /* CRC error */
1368 putsec(secbuf
, chinseg
);
1372 vfile("rzfile: zgethdr returned %d", c
);
1379 putsec(secbuf
, chinseg
);
1383 vfile("rzfile: zgethdr returned %d", c
);
1391 putsec(secbuf
, chinseg
);
1394 putsec(secbuf
, Rxcount
);
1398 zshhdr(ZACK
, Txhdr
);
1406 putsec(secbuf
, Rxcount
);
1410 zshhdr(ZACK
, Txhdr
);
1417 putsec(secbuf
, Rxcount
);
1426 putsec(secbuf
, Rxcount
);
1436 * Send a string to the modem, processing for \336 (sleep 1 sec)
1437 * and \335 (break signal)
1449 sendbrk(); continue;
1457 * Close the receive dataset, return OK or ERROR
1471 if (fclose(fout
)==ERROR
) {
1472 fprintf(stderr
, "file close ERROR\n");
1477 timep
[0] = time(&q
);
1479 utime(Pathname
, (struct utimbuf
*) timep
);
1482 if ((Filemode
&S_IFMT
) == S_IFREG
)
1483 chmod(Pathname
, (07777 & Filemode
));
1488 * Ack a ZFIN packet, let byegones be byegones
1497 for (n
=3; --n
>=0; ) {
1499 zshhdr(ZFIN
, Txhdr
);
1500 switch (readline(100)) {
1502 readline(1); /* Discard 2nd 'O' */
1503 vfile("ackbibi complete");
1517 * Local console output simulation
1522 if (Verbose
|| Fromcu
)
1528 * Strip leading ! if present, do shell escape.
1538 * Strip leading ! if present, do exec.
1546 execl("/bin/sh", "sh", "-c", s
);