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"
98 int main(int argc
, char *argv
[]);
100 int wcreceive(int argc
, char **argp
);
101 int wcrxpn(char *rpn
);
103 int wcgetsec(char *rxbuf
, int maxtime
);
104 int readline(int timeout
);
105 void purgeline(void);
106 int procheader(char *name
);
107 int make_dirs(char *pathname
);
108 int makedir(char *dpath
, int dmode
);
109 int putsec(char *buf
, int n
);
110 void sendline(int c
);
112 void uncaps(char *s
);
113 int IsAnyLower(char *s
);
114 char *substr(char *s
, char *t
);
117 void report(int sct
);
118 void chkinvok(char *s
);
119 void checkpath(char *name
);
123 void zmputs(char *s
);
126 void bttyout(int c
);
128 void exec2(char *s
);
130 * Debugging information output interface routine
132 void vfile(const char *s
, ...);
135 * Max value for HOWMANY is 255.
136 * A larger value reduces system overhead but may evoke kernel bugs.
137 * 133 corresponds to an XMODEM/CRC sector
143 /* Ward Christensen / CP/M parameters - Don't change these! */
145 #define CAN ('X'&037)
146 #define XOFF ('s'&037)
147 #define XON ('q'&037)
154 #define WANTCRC 0103 /* send C not NAK to get crc not checksum */
160 #define PATHLEN 257 /* ready for 4.2 bsd ? */
161 #define UNIXFILE 0xF000 /* The S_IFMT file mask bit for stat */
163 int Zmodem
=0; /* ZMODEM protocol requested */
164 int Nozmodem
= 0; /* If invoked as "rb" */
165 unsigned Baudrate
= 2400;
168 #include "vrzsz.c" /* most of the system dependent stuff here */
170 #include "rbsb.c" /* most of the system dependent stuff here */
178 * Routine to calculate the free bytes on the current file system
179 * ~0 means many free bytes (unknown)
183 return(~0L); /* many free bytes ... */
189 int Eofseen
; /* indicates cpm eof (^Z) has been received */
191 int Restricted
=0; /* restricted; no /.. or ../ in filenames */
193 /* Sorry, Regulus and some others don't work right in raw mode! */
194 int Readnum
= 1; /* Number of bytes to ask for in read() from modem */
196 int Readnum
= HOWMANY
; /* Number of bytes to ask for in read() from modem */
199 #define DEFBYTL 2000000000L /* default rx file size */
200 long Bytesleft
; /* number of bytes of incoming file left */
201 long Modtime
; /* Unix style mod time for incoming file */
202 int Filemode
; /* Unix style mode for incoming file */
203 char Pathname
[PATHLEN
];
204 char *Progname
; /* the name by which we were called */
208 int MakeLCPathname
=TRUE
; /* make received pathname lower case */
210 int Quiet
=0; /* overrides logic that would otherwise set verbose */
211 int Nflag
= 0; /* Don't really transfer files */
212 int Rxclob
=FALSE
; /* Clobber existing file */
213 int Rxbinary
=FALSE
; /* receive all files in bin mode */
214 int Rxascii
=FALSE
; /* receive files in ascii (translate) mode */
215 int Thisbinary
; /* current file is to be received in bin mode */
216 int Blklen
; /* record length of received packets */
219 int chinseg
= 0; /* Number of characters received in this data seg */
220 char secbuf
[1+(SEGMENTS
+1)*1024];
226 char linbuf
[HOWMANY
];
227 int Lleft
=0; /* number of characters in linbuf */
229 char Lzmanag
; /* Local file management request */
230 char zconv
; /* ZMODEM file conversion request */
231 char zmanag
; /* ZMODEM file management request */
232 char ztrans
; /* ZMODEM file transport request */
233 int Zctlesc
; /* Encode control characters */
234 int Zrwindow
= 1400; /* RX window size (controls garbage count) */
236 jmp_buf tohere
; /* For the interrupt on RX timeout */
238 #define xsendline(c) sendline(c)
241 int tryzhdrtype
=ZRINIT
; /* Header type to send corresponding to Last rx close */
249 /* called by signal interrupt or terminate to clean things up */
255 fprintf(stderr
, "rz: caught signal %d; exiting\n", n
);
260 int main(int argc
, char *argv
[])
264 char *virgin
, **patts
;
268 setbuf(stderr
, (char *)NULL
);
269 if ((cp
=getenv("SHELL")) && (substr(cp
, "rsh") || substr(cp
, "rksh")))
274 Progname
= virgin
= "rz";
276 chkinvok(virgin
=argv
[0]); /* if called as [-]rzCOMMAND set flag */
285 cp
[1] = toupper(cp
[1]); continue;
287 Lzmanag
= ZMAPND
; break;
291 Rxbinary
=TRUE
; break;
301 Lzmanag
= ZMPROT
; break;
303 Quiet
=TRUE
; Verbose
=0; break;
308 Rxtimeout
= atoi(*++argv
);
309 if (Rxtimeout
<10 || Rxtimeout
>1000)
316 Zrwindow
= atoi(*++argv
);
319 MakeLCPathname
=FALSE
; break;
329 else if ( !npats
&& argc
>0) {
341 if (freopen(LOGFILE
, "a", stderr
)==NULL
) {
342 printf("Can't open log file %s\n",LOGFILE
);
345 setbuf(stderr
, (char *)NULL
);
346 fprintf(stderr
, "argv[0]=%s Progname=%s\n", virgin
, Progname
);
348 if (Fromcu
&& !Quiet
) {
352 vfile("%s %s for %s\n", Progname
, VERSION
, OS
);
354 if (signal(SIGINT
, bibi
) == SIG_IGN
) {
355 signal(SIGINT
, SIG_IGN
); signal(SIGKILL
, SIG_IGN
);
358 signal(SIGINT
, bibi
); signal(SIGKILL
, bibi
);
360 signal(SIGTERM
, bibi
);
361 if (wcreceive(npats
, patts
)==ERROR
) {
366 vfile("exitcode = %d\n",exitcode
);
367 if (exitcode
&& !Zmodem
) /* bellow again with all thy might. */
371 if (Verbose
) putc('\n', stderr
);
372 exit(exitcode
? exitcode
:SS_NORMAL
);
380 fprintf(stderr
,"Usage: rz [-abeuvy]\n");
382 fprintf(stderr
,"Usage: rz [-abeuvy] (ZMODEM)\n");
383 fprintf(stderr
,"or rb [-abuvy] (YMODEM)\n");
384 fprintf(stderr
,"or rx [-abcv] file (XMODEM or XMODEM-1k)\n");
386 fprintf(stderr
," -a ASCII transfer (strip CR)\n");
387 fprintf(stderr
," -b Binary transfer for all files\n");
389 fprintf(stderr
," -c Use 16 bit CRC (XMODEM)\n");
391 fprintf(stderr
," -e Escape control characters (ZMODEM)\n");
392 fprintf(stderr
," -v Verbose more v's give more info\n");
393 fprintf(stderr
," -y Yes, clobber existing file if any\n");
394 fprintf(stderr
,"%s %s for %s by Chuck Forsberg, Omen Technology INC\n",
395 Progname
, VERSION
, OS
);
396 fprintf(stderr
, "\t\t\042The High Reliability Software\042\n");
400 void vfile(const char *string
, ...)
404 va_start(args
, string
);
405 vfprintf(stderr
, string
, args
);
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(int argc
, char **argp
)
422 if (Batch
|| argc
==0) {
425 fprintf(stderr
, rbmsg
, Progname
, Nozmodem
?"sb":"sz");
436 if (wcrxpn(secbuf
)== ERROR
)
440 if (procheader(secbuf
) == ERROR
)
447 Bytesleft
= DEFBYTL
; Filemode
= 0; Modtime
= 0L;
449 procheader(""); strcpy(Pathname
, *argp
); checkpath(Pathname
);
450 fprintf(stderr
, "\nrz: ready to receive %s\r\n", Pathname
);
451 if ((fout
=fopen(Pathname
, "w")) == NULL
)
460 if (Topipe
&& fout
) {
461 pclose(fout
); return ERROR
;
469 fprintf(stderr
, "\r\nrz: %s removed.\r\n", Pathname
);
477 * Fetch a pathname from the other end as a C ctyle ASCIZ string.
478 * Length is indeterminate as long as less than Blklen
479 * A null string represents no more files (YMODEM)
481 * Parameter rpn is for receiving a pathname
483 int wcrxpn(char *rpn
)
494 Firstsec
=TRUE
; Eofseen
=FALSE
;
495 sendline(Crcflg
?WANTCRC
:NAK
);
496 Lleft
=0; /* Do read next time ... */
497 while ((c
= wcgetsec(rpn
, 100)) != 0) {
499 zperr( "Pathname fetch returned %d", c
);
501 Lleft
=0; /* Do read next time ... */
512 * Adapted from CMODEM13.C, written by
513 * Jack M. Wierda and Roderick W. Hart
518 register int sectnum
, sectcurr
;
519 register char sendchar
;
520 int cblklen
; /* bytes to dump this block */
522 Firstsec
=TRUE
;sectnum
=0; Eofseen
=FALSE
;
523 sendchar
=Crcflg
?WANTCRC
:NAK
;
526 sendline(sendchar
); /* send it now, we're ready! */
527 Lleft
=0; /* Do read next time ... */
528 sectcurr
=wcgetsec(secbuf
, (sectnum
&0177)?50:130);
530 if (sectcurr
==((sectnum
+1) &0377)) {
532 cblklen
= Bytesleft
>Blklen
? Blklen
:Bytesleft
;
533 if (putsec(secbuf
, cblklen
)==ERROR
)
535 if ((Bytesleft
-=cblklen
) < 0)
539 else if (sectcurr
==(sectnum
&0377)) {
540 zperr( "Received dup Sector");
543 else if (sectcurr
==WCEOT
) {
547 Lleft
=0; /* Do read next time ... */
550 else if (sectcurr
==ERROR
)
553 zperr( "Sync Error");
560 * Wcgetsec fetches a Ward Christensen type sector.
561 * Returns sector number encountered or ERROR if valid sector not received,
562 * or CAN CAN received
563 * or WCEOT if eot sector
564 * time is timeout for first char, set to 4 seconds thereafter
565 ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
566 * (Caller must do that when he is good and ready to get next sector)
569 int wcgetsec(char *rxbuf
, int maxtime
)
571 register int checksum
, wcj
, firstch
;
572 register unsigned short oldcrc
;
576 for (Lastrx
=errors
=0; errors
<RETRYMAX
; errors
++) {
578 if ((firstch
=readline(maxtime
))==STX
) {
579 Blklen
=1024; goto get2
;
584 sectcurr
=readline(1);
585 if ((sectcurr
+(oldcrc
=readline(1)))==0377) {
587 for (p
=rxbuf
,wcj
=Blklen
; --wcj
>=0; ) {
588 if ((firstch
=readline(1)) < 0)
590 oldcrc
=updcrc(firstch
, oldcrc
);
591 checksum
+= (*p
++ = firstch
);
593 if ((firstch
=readline(1)) < 0)
596 oldcrc
=updcrc(firstch
, oldcrc
);
597 if ((firstch
=readline(1)) < 0)
599 oldcrc
=updcrc(firstch
, oldcrc
);
607 else if (((checksum
-firstch
)&0377)==0) {
615 zperr("Sector number garbled");
617 /* make sure eot really is eot and not just mixmash */
619 else if (firstch
==EOT
&& readline(1)==TIMEOUT
)
622 else if (firstch
==EOT
&& Lleft
==0)
625 else if (firstch
==CAN
) {
627 zperr( "Sender CANcelled");
634 else if (firstch
==TIMEOUT
) {
641 zperr( "Got 0%o sector header", firstch
);
645 while(readline(1)!=TIMEOUT
)
648 sendline(Crcflg
?WANTCRC
:NAK
);
649 Lleft
=0; /* Do read next time ... */
651 maxtime
=40; sendline(NAK
);
652 Lleft
=0; /* Do read next time ... */
655 /* try to stop the bubble machine. */
662 * This version of readline is reasoably well suited for
663 * reading many characters.
664 * (except, currently, for the Regulus version!)
666 * timeout is in tenths of seconds
668 int readline(int timeout
)
671 static char *cdq
; /* pointer for removing chars from linbuf */
675 fprintf(stderr
, "%02x ", *cdq
&0377);
677 return (*cdq
++ & 0377);
683 fprintf(stderr
, "Calling read: alarm=%d Readnum=%d ",
685 if (setjmp(tohere
)) {
687 /* ioctl(iofd, TIOCFLUSH, 0); */
691 fprintf(stderr
, "Readline:TIMEOUT\n");
694 signal(SIGALRM
, alrm
); alarm(n
);
695 Lleft
=read(iofd
, cdq
=linbuf
, Readnum
);
698 fprintf(stderr
, "Read returned %d bytes\n", Lleft
);
704 fprintf(stderr
, "%02x ", *cdq
&0377);
706 return (*cdq
++ & 0377);
712 * Purge the modem input queue of all characters
718 ioctl(iofd
, TCFLSH
, 0);
727 * Process incoming file information header
729 int procheader(char *name
)
731 register char *openmode
, *p
;
733 /* set default parameters and overrides */
735 Thisbinary
= (!Rxascii
) || Rxbinary
;
740 * Process ZMODEM remote file management requests
742 if (!Rxbinary
&& zconv
== ZCNL
) /* Remote ASCII override */
744 if (zconv
== ZCBIN
) /* Remote Binary override */
746 else if (zmanag
== ZMAPND
)
750 /* Check for existing file */
751 if (!Rxclob
&& (zmanag
&ZMMASK
) != ZMCLOB
&& (fout
=fopen(name
, "r"))) {
752 fclose(fout
); return ERROR
;
756 Bytesleft
= DEFBYTL
; Filemode
= 0; Modtime
= 0L;
758 p
= name
+ 1 + strlen(name
);
759 if (*p
) { /* file coming from Unix or DOS system */
760 sscanf(p
, "%ld%lo%o", &Bytesleft
, &Modtime
, &Filemode
);
762 if (Filemode
& UNIXFILE
)
766 fprintf(stderr
, "\nIncoming: %s %ld %lo %o\n",
767 name
, Bytesleft
, Modtime
, Filemode
);
772 if ((fout
=fopen("scratchpad", openmode
)) == NULL
)
777 else { /* File coming from CP/M system */
778 for (p
=name
; *p
; ++p
) /* change / to _ */
782 if ( *--p
== '.') /* zap trailing period */
787 if (!Zmodem
&& MakeLCPathname
&& !IsAnyLower(name
)
788 && !(Filemode
&UNIXFILE
))
792 sprintf(Pathname
, "%s %s", Progname
+2, name
);
794 fprintf(stderr
, "Topipe: %s %s\n",
795 Pathname
, Thisbinary
?"BIN":"ASCII");
797 if ((fout
=popen(Pathname
, "w")) == NULL
)
801 strcpy(Pathname
, name
);
803 fprintf(stderr
, "Receiving %s %s %s\n",
804 name
, Thisbinary
?"BIN":"ASCII", openmode
);
811 if (name
[0] == '!' || name
[0] == '|') {
812 if ( !(fout
= popen(name
+1, "w"))) {
815 Topipe
= -1; return(OK
);
820 fout
= fopen(name
, openmode
);
823 fout
= fopen(name
, openmode
);
825 fout
= fopen(name
, openmode
);
836 * Directory-creating routines from Public Domain TAR by John Gilmore
840 * After a file/link/symlink/dir creation has failed, see if
841 * it's because some required directory was not present, and if
842 * so, create all required dirs.
844 int make_dirs(char *pathname
)
846 register char *p
; /* Points into path */
847 int madeone
= 0; /* Did we do anything yet? */
848 int save_errno
= errno
; /* Remember caller's errno */
852 return 0; /* Not our problem */
854 for (p
= strchr(pathname
, '/'); p
!= NULL
; p
= strchr(p
+1, '/')) {
855 /* Avoid mkdir of empty string, if leading or double '/' */
856 if (p
== pathname
|| p
[-1] == '/')
858 /* Avoid mkdir where last part of path is '.' */
859 if (p
[-1] == '.' && (p
== pathname
+1 || p
[-2] == '/'))
861 *p
= 0; /* Truncate the path there */
862 if ( !makedir(pathname
, 0777)) { /* Try to create it as a dir */
863 vfile("Made directory %s\n", pathname
);
864 madeone
++; /* Remember if we made one */
869 if (errno
== EEXIST
) /* Directory already exists */
872 * Some other error in the makedir. We return to the caller.
876 errno
= save_errno
; /* Restore caller's errno */
877 return madeone
; /* Tell them to retry if we made one */
881 #define TERM_SIGNAL(status) ((status) & 0x7F)
882 #define TERM_COREDUMP(status) (((status) & 0x80) != 0)
883 #define TERM_VALUE(status) ((status) >> 8)
885 * Make a directory. Compatible with the mkdir() system call on 4.2BSD.
887 int makedir(char *dpath
, int dmode
)
892 if (stat(dpath
,&statbuf
) == 0) {
893 errno
= EEXIST
; /* Stat worked, so it already exists */
897 /* If stat fails for a reason other than non-existence, return error */
898 if (errno
!= ENOENT
) return -1;
900 switch (cpid
= fork()) {
902 case -1: /* Error in fork() */
903 return(-1); /* Errno is set already */
905 case 0: /* Child process */
907 * Cheap hack to set mode of new directory. Since this
908 * child process is going away anyway, we zap its umask.
909 * FIXME, this won't suffice to set SUID, SGID, etc. on this
910 * directory. Does anybody care?
912 status
= umask(0); /* Get current umask */
913 status
= umask(status
| (0777 & ~dmode
)); /* Set for mkdir */
914 execl("/bin/mkdir", "mkdir", dpath
, (char *)0);
915 _exit(-1); /* Can't exec /bin/mkdir */
917 default: /* Parent process */
918 while (cpid
!= wait(&status
)) ; /* Wait for kid to finish */
921 if (TERM_SIGNAL(status
) != 0 || TERM_VALUE(status
) != 0) {
922 errno
= EIO
; /* We don't know why, but */
923 return -1; /* /bin/mkdir failed */
932 * Putsec writes the n characters of buf to receive file fout.
933 * If not in binary mode, carriage returns, and all characters
934 * starting with CPMEOF are discarded.
936 int putsec(char *buf
, int n
)
943 for (p
=buf
; --n
>=0; )
949 for (p
=buf
; --n
>=0; ++p
) {
953 Eofseen
=TRUE
; return OK
;
963 * Send a character to modem. Small is beautiful.
971 fprintf(stderr
, "Sendline: %x\n", c
);
982 /* make string s lower case */
990 * IsAnyLower returns TRUE if string s has lower case letters.
992 int IsAnyLower(char *s
)
1001 * substr(string, token) searches for token in string s
1002 * returns pointer to token within string if found, NULL otherwise
1005 substr(char *s
, char *t
)
1007 register char *ss
,*tt
;
1008 /* search for first char of token */
1011 /* compare token with substring */
1012 for (ss
=s
,tt
=t
; ;) {
1018 return (char *)NULL
;
1025 void zperr(char *s
, char *p
, char *u
)
1029 fprintf(stderr
, "Retry %d: ", errors
);
1030 fprintf(stderr
, s
, p
, u
);
1031 fprintf(stderr
, "\n");
1034 /* send cancel string to get the other end to shut up */
1037 static char canistr
[] = {
1038 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
1042 raw_wbuf(strlen(canistr
), canistr
);
1045 printf("%s", canistr
);
1046 Lleft
=0; /* Do read next time ... */
1052 void report(int sct
)
1055 fprintf(stderr
,"%03d%c",sct
,sct
%10? ' ' : '\r');
1060 * If called as [-][dir/../]vrzCOMMAND set Verbose to 1
1061 * If called as [-][dir/../]rzCOMMAND set the pipe flag
1062 * If called as rb use YMODEM protocol
1064 void chkinvok(char *s
)
1078 if (s
[0]=='r' && s
[1]=='z')
1080 if (s
[0]=='r' && s
[1]=='b')
1081 Batch
= Nozmodem
= TRUE
;
1082 if (s
[2] && s
[0]=='r' && s
[1]=='b')
1084 if (s
[2] && s
[0]=='r' && s
[1]=='z')
1090 * Totalitarian Communist pathname processing
1092 void checkpath(char *name
)
1095 if (fopen(name
, "r") != NULL
) {
1097 fprintf(stderr
, "\r\nrz: %s exists\n", name
);
1100 /* restrict pathnames to current tree or uucppublic */
1101 if ( substr(name
, "../")
1102 || (name
[0]== '/' && strncmp(name
, PUBDIR
, strlen(PUBDIR
))) ) {
1104 fprintf(stderr
,"\r\nrz:\tSecurity Violation\r\n");
1111 * Initialize for Zmodem receive attempt, try to activate Zmodem sender
1112 * Handles ZSINIT frame
1113 * Return ZFILE if Zmodem filename received, -1 on error,
1114 * ZCOMPL if transaction finished, else 0
1119 register int cmdzack1flg
;
1121 if (Nozmodem
) /* Check for "rb" program name */
1125 for (n
=Zmodem
?15:5; --n
>=0; ) {
1126 /* Set buffer length (0) and capability flags */
1128 stohdr(SEGMENTS
*1024L);
1133 Txhdr
[ZF0
] = CANFC32
|CANFDX
|CANOVIO
|CANBRK
;
1135 Txhdr
[ZF0
] = CANFC32
|CANFDX
|CANOVIO
;
1138 Txhdr
[ZF0
] |= TESCCTL
;
1139 zshhdr(tryzhdrtype
, Txhdr
);
1140 if (tryzhdrtype
== ZSKIP
) /* Don't skip too far */
1141 tryzhdrtype
= ZRINIT
; /* CAF 8-21-87 */
1143 switch (zgethdr(Rxhdr
, 0)) {
1152 zmanag
= Rxhdr
[ZF1
];
1153 ztrans
= Rxhdr
[ZF2
];
1154 tryzhdrtype
= ZRINIT
;
1155 c
= zrdata(secbuf
, 1024);
1159 zshhdr(ZNAK
, Txhdr
);
1162 Zctlesc
= TESCCTL
& Rxhdr
[ZF0
];
1163 if (zrdata(Attn
, ZATTNLEN
) == GOTCRCW
) {
1165 zshhdr(ZACK
, Txhdr
);
1168 zshhdr(ZNAK
, Txhdr
);
1172 zshhdr(ZACK
, Txhdr
);
1178 cmdzack1flg
= Rxhdr
[ZF0
];
1179 if (zrdata(secbuf
, 1024) == GOTCRCW
) {
1180 if (cmdzack1flg
& ZCACK1
)
1183 stohdr((long)sys2(secbuf
));
1184 purgeline(); /* dump impatient questions */
1186 zshhdr(ZCOMPL
, Txhdr
);
1188 while (++errors
<20 && zgethdr(Rxhdr
,1) != ZFIN
);
1190 if (cmdzack1flg
& ZCACK1
)
1194 zshhdr(ZNAK
, Txhdr
); goto again
;
1201 ackbibi(); return ZCOMPL
;
1210 * Receive 1 or more files with ZMODEM protocol
1217 switch (c
= rzfile()) {
1238 * Receive a file with ZMODEM protocol
1239 * Assumes file name frame is in secbuf
1247 if (procheader(secbuf
) == ERROR
) {
1248 return (tryzhdrtype
= ZSKIP
);
1251 n
= 20; rxbytes
= 0l;
1258 zshhdr(ZRPOS
, Txhdr
);
1260 switch (c
= zgethdr(Rxhdr
, 0)) {
1262 vfile("rzfile: zgethdr returned %d", c
);
1267 putsec(secbuf
, chinseg
);
1271 vfile("rzfile: zgethdr returned %d", c
);
1275 zrdata(secbuf
, 1024);
1279 putsec(secbuf
, chinseg
);
1282 if (rclhdr(Rxhdr
) != rxbytes
) {
1284 * Ignore eof if it's at wrong place - force
1285 * a timeout because the eof might have gone
1286 * out before we sent our zrpos.
1288 errors
= 0; goto nxthdr
;
1291 tryzhdrtype
= ZFERR
;
1292 vfile("rzfile: closeit returned <> 0");
1295 vfile("rzfile: normal EOF");
1297 case ERROR
: /* Too much garbage in header search error */
1299 putsec(secbuf
, chinseg
);
1303 vfile("rzfile: zgethdr returned %d", c
);
1310 putsec(secbuf
, chinseg
);
1314 vfile("rzfile: Sender SKIPPED file");
1317 if (rclhdr(Rxhdr
) != rxbytes
) {
1322 putsec(secbuf
, chinseg
);
1325 zmputs(Attn
); continue;
1329 fprintf(stderr
, "\r%7ld ZMODEM%s ",
1330 rxbytes
, Crc32
?" CRC-32":"");
1332 if (chinseg
>= (1024 * SEGMENTS
)) {
1333 putsec(secbuf
, chinseg
);
1336 switch (c
= zrdata(secbuf
+chinseg
, 1024))
1338 switch (c
= zrdata(secbuf
, 1024))
1343 putsec(secbuf
, chinseg
);
1346 vfile("rzfile: zgethdr returned %d", c
);
1348 case ERROR
: /* CRC error */
1350 putsec(secbuf
, chinseg
);
1354 vfile("rzfile: zgethdr returned %d", c
);
1361 putsec(secbuf
, chinseg
);
1365 vfile("rzfile: zgethdr returned %d", c
);
1373 putsec(secbuf
, chinseg
);
1376 putsec(secbuf
, Rxcount
);
1380 zshhdr(ZACK
, Txhdr
);
1388 putsec(secbuf
, Rxcount
);
1392 zshhdr(ZACK
, Txhdr
);
1399 putsec(secbuf
, Rxcount
);
1408 putsec(secbuf
, Rxcount
);
1418 * Send a string to the modem, processing for \336 (sleep 1 sec)
1419 * and \335 (break signal)
1421 void zmputs(char *s
)
1430 sendbrk(); continue;
1438 * Close the receive dataset, return OK or ERROR
1452 if (fclose(fout
)==ERROR
) {
1453 fprintf(stderr
, "file close ERROR\n");
1458 timep
[0] = time(&q
);
1460 utime(Pathname
, (struct utimbuf
*) timep
);
1463 if ((Filemode
&S_IFMT
) == S_IFREG
)
1464 chmod(Pathname
, (07777 & Filemode
));
1469 * Ack a ZFIN packet, let byegones be byegones
1478 for (n
=3; --n
>=0; ) {
1480 zshhdr(ZFIN
, Txhdr
);
1481 switch (readline(100)) {
1483 readline(1); /* Discard 2nd 'O' */
1484 vfile("ackbibi complete");
1498 * Local console output simulation
1502 if (Verbose
|| Fromcu
)
1508 * Strip leading ! if present, do shell escape.
1517 * Strip leading ! if present, do exec.
1524 execl("/bin/sh", "sh", "-c", s
);