1433d6423SLionel Sambuc #define VERSION "2.03 05-17-88"
2433d6423SLionel Sambuc #define PUBDIR "/usr/spool/uucppublic"
3433d6423SLionel Sambuc
4433d6423SLionel Sambuc /*% cc -compat -M2 -Ox -K -i -DMD -DOMEN % -o rz; size rz;
5433d6423SLionel Sambuc <-xtx-*> cc386 -Ox -DMD -DOMEN -DSEGMENTS=8 rz.c -o $B/rz; size $B/rz
6433d6423SLionel Sambuc *
7433d6423SLionel Sambuc * rz.c By Chuck Forsberg
8433d6423SLionel Sambuc *
9433d6423SLionel Sambuc * cc -O rz.c -o rz USG (3.0) Unix
10433d6423SLionel Sambuc * cc -O -DV7 rz.c -o rz Unix V7, BSD 2.8 - 4.3
11433d6423SLionel Sambuc *
12433d6423SLionel Sambuc * ln rz rb; ln rz rx For either system
13433d6423SLionel Sambuc *
14433d6423SLionel Sambuc * ln rz /usr/bin/rzrmail For remote mail. Make this the
15433d6423SLionel Sambuc * login shell. rzrmail then calls
16433d6423SLionel Sambuc * rmail(1) to deliver mail.
17433d6423SLionel Sambuc *
18433d6423SLionel Sambuc * To compile on VMS:
19433d6423SLionel Sambuc *
20433d6423SLionel Sambuc * define LNK$LIBRARY SYS$LIBRARY:VAXCRTL.OLB
21433d6423SLionel Sambuc * cc rz.c
22433d6423SLionel Sambuc * cc vvmodem.c
23433d6423SLionel Sambuc * link rz,vvmodem
24433d6423SLionel Sambuc * rz :== $disk:[username.subdir]rz.exe
25433d6423SLionel Sambuc *
26433d6423SLionel Sambuc *
27433d6423SLionel Sambuc * Unix is a trademark of Western Electric Company
28433d6423SLionel Sambuc *
29433d6423SLionel Sambuc * A program for Unix to receive files and commands from computers running
30433d6423SLionel Sambuc * Professional-YAM, PowerCom, YAM, IMP, or programs supporting XMODEM.
31433d6423SLionel Sambuc * rz uses Unix buffered input to reduce wasted CPU time.
32433d6423SLionel Sambuc *
33433d6423SLionel Sambuc * Iff the program is invoked by rzCOMMAND, output is piped to
34433d6423SLionel Sambuc * "COMMAND filename" (Unix only)
35433d6423SLionel Sambuc *
36433d6423SLionel Sambuc * Some systems (Venix, Coherent, Regulus) may not support tty raw mode
37433d6423SLionel Sambuc * read(2) the same way as Unix. ONEREAD must be defined to force one
38433d6423SLionel Sambuc * character reads for these systems. Added 7-01-84 CAF
39433d6423SLionel Sambuc *
40433d6423SLionel Sambuc * Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF
41433d6423SLionel Sambuc *
42433d6423SLionel Sambuc * BIX added 6-30-87 to support BIX(TM) upload protocol used by the
43433d6423SLionel Sambuc * Byte Information Exchange.
44433d6423SLionel Sambuc *
45433d6423SLionel Sambuc * NFGVMIN Updated 2-18-87 CAF for Xenix systems where c_cc[VMIN]
46433d6423SLionel Sambuc * doesn't work properly (even though it compiles without error!),
47433d6423SLionel Sambuc *
48433d6423SLionel Sambuc * SEGMENTS=n added 2-21-88 as a model for CP/M programs
49433d6423SLionel Sambuc * for CP/M-80 systems that cannot overlap modem and disk I/O.
50433d6423SLionel Sambuc *
51433d6423SLionel Sambuc * VMS flavor hacks begin with rz version 2.00
52433d6423SLionel Sambuc *
53433d6423SLionel Sambuc * -DMD may be added to compiler command line to compile in
54433d6423SLionel Sambuc * Directory-creating routines from Public Domain TAR by John Gilmore
55433d6423SLionel Sambuc *
56433d6423SLionel Sambuc * HOWMANY may be tuned for best performance
57433d6423SLionel Sambuc *
58433d6423SLionel Sambuc * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
59433d6423SLionel Sambuc */
60433d6423SLionel Sambuc
61433d6423SLionel Sambuc #include <sys/types.h>
62433d6423SLionel Sambuc
63433d6423SLionel Sambuc #ifdef vax11c
64433d6423SLionel Sambuc #include <types.h>
65433d6423SLionel Sambuc #include <stat.h>
66433d6423SLionel Sambuc #define LOGFILE "rzlog.tmp"
67433d6423SLionel Sambuc #define OS "VMS"
68433d6423SLionel Sambuc #define BUFREAD
69433d6423SLionel Sambuc extern int errno;
70433d6423SLionel Sambuc #define SS_NORMAL SS$_NORMAL
71433d6423SLionel Sambuc #else
72433d6423SLionel Sambuc /* Not vax11c */
73433d6423SLionel Sambuc #define SS_NORMAL 0
74433d6423SLionel Sambuc #define LOGFILE "/tmp/rzlog"
75433d6423SLionel Sambuc #endif
76433d6423SLionel Sambuc
77433d6423SLionel Sambuc #include <time.h>
78433d6423SLionel Sambuc #include <ctype.h>
79433d6423SLionel Sambuc #include <errno.h>
80433d6423SLionel Sambuc #include <signal.h>
81433d6423SLionel Sambuc #include <setjmp.h>
82433d6423SLionel Sambuc #include <string.h>
83433d6423SLionel Sambuc #include <stdlib.h>
84433d6423SLionel Sambuc #include <unistd.h>
85433d6423SLionel Sambuc #include <utime.h>
86433d6423SLionel Sambuc #include <stdio.h>
87433d6423SLionel Sambuc #include <stdarg.h>
88433d6423SLionel Sambuc
89433d6423SLionel Sambuc #define OK 0
90433d6423SLionel Sambuc #define FALSE 0
91433d6423SLionel Sambuc #define TRUE 1
92433d6423SLionel Sambuc #undef ERROR
93433d6423SLionel Sambuc #define ERROR (-1)
94433d6423SLionel Sambuc
95433d6423SLionel Sambuc
96433d6423SLionel Sambuc long getfree(void);
97433d6423SLionel Sambuc void alrm(int sig );
98433d6423SLionel Sambuc int main(int argc , char *argv []);
99433d6423SLionel Sambuc int usage(void);
100433d6423SLionel Sambuc int wcreceive(int argc , char **argp );
101433d6423SLionel Sambuc int wcrxpn(char *rpn );
102433d6423SLionel Sambuc int wcrx(void);
103433d6423SLionel Sambuc int wcgetsec(char *rxbuf , int maxtime );
104433d6423SLionel Sambuc int readline(int timeout );
105433d6423SLionel Sambuc void purgeline(void);
106433d6423SLionel Sambuc int procheader(char *name );
107433d6423SLionel Sambuc int make_dirs(char *pathname );
108433d6423SLionel Sambuc int makedir(char *dpath , int dmode );
109433d6423SLionel Sambuc int putsec(char *buf , int n );
110433d6423SLionel Sambuc void sendline(int c );
111433d6423SLionel Sambuc void flushmo(void);
112433d6423SLionel Sambuc void uncaps(char *s );
113433d6423SLionel Sambuc int IsAnyLower(char *s );
114433d6423SLionel Sambuc char *substr(char *s , char *t );
115433d6423SLionel Sambuc void zperr();
116433d6423SLionel Sambuc void canit(void);
117433d6423SLionel Sambuc void report(int sct );
118433d6423SLionel Sambuc void chkinvok(char *s );
119433d6423SLionel Sambuc void checkpath(char *name );
120433d6423SLionel Sambuc int tryz(void);
121433d6423SLionel Sambuc int rzfiles(void);
122433d6423SLionel Sambuc int rzfile(void);
123433d6423SLionel Sambuc void zmputs(char *s );
124433d6423SLionel Sambuc int closeit(void);
125433d6423SLionel Sambuc void ackbibi(void);
126433d6423SLionel Sambuc void bttyout(int c );
127433d6423SLionel Sambuc int sys2(char *s );
128433d6423SLionel Sambuc void exec2(char *s );
129433d6423SLionel Sambuc /*
130433d6423SLionel Sambuc * Debugging information output interface routine
131433d6423SLionel Sambuc */
132433d6423SLionel Sambuc void vfile(const char *s, ...);
133433d6423SLionel Sambuc
134433d6423SLionel Sambuc /*
135433d6423SLionel Sambuc * Max value for HOWMANY is 255.
136433d6423SLionel Sambuc * A larger value reduces system overhead but may evoke kernel bugs.
137433d6423SLionel Sambuc * 133 corresponds to an XMODEM/CRC sector
138433d6423SLionel Sambuc */
139433d6423SLionel Sambuc #ifndef HOWMANY
140433d6423SLionel Sambuc #define HOWMANY 133
141433d6423SLionel Sambuc #endif
142433d6423SLionel Sambuc
143433d6423SLionel Sambuc /* Ward Christensen / CP/M parameters - Don't change these! */
144433d6423SLionel Sambuc #define ENQ 005
145433d6423SLionel Sambuc #define CAN ('X'&037)
146433d6423SLionel Sambuc #define XOFF ('s'&037)
147433d6423SLionel Sambuc #define XON ('q'&037)
148433d6423SLionel Sambuc #define SOH 1
149433d6423SLionel Sambuc #define STX 2
150433d6423SLionel Sambuc #define EOT 4
151433d6423SLionel Sambuc #define ACK 6
152433d6423SLionel Sambuc #define NAK 025
153433d6423SLionel Sambuc #define CPMEOF 032
154433d6423SLionel Sambuc #define WANTCRC 0103 /* send C not NAK to get crc not checksum */
155433d6423SLionel Sambuc #define TIMEOUT (-2)
156433d6423SLionel Sambuc #define RCDO (-3)
157433d6423SLionel Sambuc #define ERRORMAX 5
158433d6423SLionel Sambuc #define RETRYMAX 5
159433d6423SLionel Sambuc #define WCEOT (-10)
160433d6423SLionel Sambuc #define PATHLEN 257 /* ready for 4.2 bsd ? */
161433d6423SLionel Sambuc #define UNIXFILE 0xF000 /* The S_IFMT file mask bit for stat */
162433d6423SLionel Sambuc
163433d6423SLionel Sambuc int Zmodem=0; /* ZMODEM protocol requested */
164433d6423SLionel Sambuc int Nozmodem = 0; /* If invoked as "rb" */
165433d6423SLionel Sambuc unsigned Baudrate = 2400;
166433d6423SLionel Sambuc
167433d6423SLionel Sambuc #ifdef vax11c
168433d6423SLionel Sambuc #include "vrzsz.c" /* most of the system dependent stuff here */
169433d6423SLionel Sambuc #else
170433d6423SLionel Sambuc #include "rbsb.c" /* most of the system dependent stuff here */
171433d6423SLionel Sambuc #endif
172433d6423SLionel Sambuc
173433d6423SLionel Sambuc #include "crctab.c"
174433d6423SLionel Sambuc
175433d6423SLionel Sambuc FILE *fout;
176433d6423SLionel Sambuc
177433d6423SLionel Sambuc /*
178433d6423SLionel Sambuc * Routine to calculate the free bytes on the current file system
179433d6423SLionel Sambuc * ~0 means many free bytes (unknown)
180433d6423SLionel Sambuc */
getfree()181433d6423SLionel Sambuc long getfree()
182433d6423SLionel Sambuc {
183433d6423SLionel Sambuc return(~0L); /* many free bytes ... */
184433d6423SLionel Sambuc }
185433d6423SLionel Sambuc
186433d6423SLionel Sambuc int Lastrx;
187433d6423SLionel Sambuc int Crcflg;
188433d6423SLionel Sambuc int Firstsec;
189433d6423SLionel Sambuc int Eofseen; /* indicates cpm eof (^Z) has been received */
190433d6423SLionel Sambuc int errors;
191433d6423SLionel Sambuc int Restricted=0; /* restricted; no /.. or ../ in filenames */
192433d6423SLionel Sambuc #ifdef ONEREAD
193433d6423SLionel Sambuc /* Sorry, Regulus and some others don't work right in raw mode! */
194433d6423SLionel Sambuc int Readnum = 1; /* Number of bytes to ask for in read() from modem */
195433d6423SLionel Sambuc #else
196433d6423SLionel Sambuc int Readnum = HOWMANY; /* Number of bytes to ask for in read() from modem */
197433d6423SLionel Sambuc #endif
198433d6423SLionel Sambuc
199433d6423SLionel Sambuc #define DEFBYTL 2000000000L /* default rx file size */
200433d6423SLionel Sambuc long Bytesleft; /* number of bytes of incoming file left */
201433d6423SLionel Sambuc long Modtime; /* Unix style mod time for incoming file */
202433d6423SLionel Sambuc int Filemode; /* Unix style mode for incoming file */
203433d6423SLionel Sambuc char Pathname[PATHLEN];
204433d6423SLionel Sambuc char *Progname; /* the name by which we were called */
205433d6423SLionel Sambuc
206433d6423SLionel Sambuc int Batch=0;
207433d6423SLionel Sambuc int Topipe=0;
208433d6423SLionel Sambuc int MakeLCPathname=TRUE; /* make received pathname lower case */
209433d6423SLionel Sambuc int Verbose=0;
210433d6423SLionel Sambuc int Quiet=0; /* overrides logic that would otherwise set verbose */
211433d6423SLionel Sambuc int Nflag = 0; /* Don't really transfer files */
212433d6423SLionel Sambuc int Rxclob=FALSE; /* Clobber existing file */
213433d6423SLionel Sambuc int Rxbinary=FALSE; /* receive all files in bin mode */
214433d6423SLionel Sambuc int Rxascii=FALSE; /* receive files in ascii (translate) mode */
215433d6423SLionel Sambuc int Thisbinary; /* current file is to be received in bin mode */
216433d6423SLionel Sambuc int Blklen; /* record length of received packets */
217433d6423SLionel Sambuc
218433d6423SLionel Sambuc #ifdef SEGMENTS
219433d6423SLionel Sambuc int chinseg = 0; /* Number of characters received in this data seg */
220433d6423SLionel Sambuc char secbuf[1+(SEGMENTS+1)*1024];
221433d6423SLionel Sambuc #else
222433d6423SLionel Sambuc char secbuf[1025];
223433d6423SLionel Sambuc #endif
224433d6423SLionel Sambuc
225433d6423SLionel Sambuc
226433d6423SLionel Sambuc char linbuf[HOWMANY];
227433d6423SLionel Sambuc int Lleft=0; /* number of characters in linbuf */
228433d6423SLionel Sambuc time_t timep[2];
229433d6423SLionel Sambuc char Lzmanag; /* Local file management request */
230433d6423SLionel Sambuc char zconv; /* ZMODEM file conversion request */
231433d6423SLionel Sambuc char zmanag; /* ZMODEM file management request */
232433d6423SLionel Sambuc char ztrans; /* ZMODEM file transport request */
233433d6423SLionel Sambuc int Zctlesc; /* Encode control characters */
234433d6423SLionel Sambuc int Zrwindow = 1400; /* RX window size (controls garbage count) */
235433d6423SLionel Sambuc
236433d6423SLionel Sambuc jmp_buf tohere; /* For the interrupt on RX timeout */
237433d6423SLionel Sambuc
238433d6423SLionel Sambuc #define xsendline(c) sendline(c)
239433d6423SLionel Sambuc #include "zm.c"
240433d6423SLionel Sambuc
241433d6423SLionel Sambuc int tryzhdrtype=ZRINIT; /* Header type to send corresponding to Last rx close */
242433d6423SLionel Sambuc
alrm(sig)243433d6423SLionel Sambuc void alrm(sig)
244433d6423SLionel Sambuc int sig;
245433d6423SLionel Sambuc {
246433d6423SLionel Sambuc longjmp(tohere, -1);
247433d6423SLionel Sambuc }
248433d6423SLionel Sambuc
249433d6423SLionel Sambuc /* called by signal interrupt or terminate to clean things up */
bibi(int n)250433d6423SLionel Sambuc void bibi(int n)
251433d6423SLionel Sambuc {
252433d6423SLionel Sambuc if (Zmodem)
253433d6423SLionel Sambuc zmputs(Attn);
254433d6423SLionel Sambuc canit(); mode(0);
255433d6423SLionel Sambuc fprintf(stderr, "rz: caught signal %d; exiting\n", n);
256433d6423SLionel Sambuc cucheck();
257433d6423SLionel Sambuc exit(128+n);
258433d6423SLionel Sambuc }
259433d6423SLionel Sambuc
main(int argc,char * argv[])260433d6423SLionel Sambuc int main(int argc, char *argv[])
261433d6423SLionel Sambuc {
262433d6423SLionel Sambuc register char *cp;
263433d6423SLionel Sambuc register int npats;
264433d6423SLionel Sambuc char *virgin, **patts;
265433d6423SLionel Sambuc int exitcode = 0;
266433d6423SLionel Sambuc
267433d6423SLionel Sambuc Rxtimeout = 100;
268433d6423SLionel Sambuc setbuf(stderr, (char *)NULL);
269433d6423SLionel Sambuc if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
270433d6423SLionel Sambuc Restricted=TRUE;
271433d6423SLionel Sambuc
272433d6423SLionel Sambuc from_cu();
273433d6423SLionel Sambuc #ifdef vax11c
274433d6423SLionel Sambuc Progname = virgin = "rz";
275433d6423SLionel Sambuc #else
276433d6423SLionel Sambuc chkinvok(virgin=argv[0]); /* if called as [-]rzCOMMAND set flag */
277433d6423SLionel Sambuc #endif
278433d6423SLionel Sambuc npats = 0;
279433d6423SLionel Sambuc while (--argc) {
280433d6423SLionel Sambuc cp = *++argv;
281433d6423SLionel Sambuc if (*cp == '-') {
282433d6423SLionel Sambuc while( *++cp) {
283433d6423SLionel Sambuc switch(*cp) {
284433d6423SLionel Sambuc case '\\':
285433d6423SLionel Sambuc cp[1] = toupper(cp[1]); continue;
286433d6423SLionel Sambuc case '+':
287433d6423SLionel Sambuc Lzmanag = ZMAPND; break;
288433d6423SLionel Sambuc case 'a':
289433d6423SLionel Sambuc Rxascii=TRUE; break;
290433d6423SLionel Sambuc case 'b':
291433d6423SLionel Sambuc Rxbinary=TRUE; break;
292433d6423SLionel Sambuc case 'c':
293433d6423SLionel Sambuc Crcflg=TRUE; break;
294433d6423SLionel Sambuc #ifndef vax11c
295433d6423SLionel Sambuc case 'D':
296433d6423SLionel Sambuc Nflag = TRUE; break;
297433d6423SLionel Sambuc #endif
298433d6423SLionel Sambuc case 'e':
299433d6423SLionel Sambuc Zctlesc = 1; break;
300433d6423SLionel Sambuc case 'p':
301433d6423SLionel Sambuc Lzmanag = ZMPROT; break;
302433d6423SLionel Sambuc case 'q':
303433d6423SLionel Sambuc Quiet=TRUE; Verbose=0; break;
304433d6423SLionel Sambuc case 't':
305433d6423SLionel Sambuc if (--argc < 1) {
306433d6423SLionel Sambuc usage();
307433d6423SLionel Sambuc }
308433d6423SLionel Sambuc Rxtimeout = atoi(*++argv);
309433d6423SLionel Sambuc if (Rxtimeout<10 || Rxtimeout>1000)
310433d6423SLionel Sambuc usage();
311433d6423SLionel Sambuc break;
312433d6423SLionel Sambuc case 'w':
313433d6423SLionel Sambuc if (--argc < 1) {
314433d6423SLionel Sambuc usage();
315433d6423SLionel Sambuc }
316433d6423SLionel Sambuc Zrwindow = atoi(*++argv);
317433d6423SLionel Sambuc break;
318433d6423SLionel Sambuc case 'u':
319433d6423SLionel Sambuc MakeLCPathname=FALSE; break;
320433d6423SLionel Sambuc case 'v':
321433d6423SLionel Sambuc ++Verbose; break;
322433d6423SLionel Sambuc case 'y':
323433d6423SLionel Sambuc Rxclob=TRUE; break;
324433d6423SLionel Sambuc default:
325433d6423SLionel Sambuc usage();
326433d6423SLionel Sambuc }
327433d6423SLionel Sambuc }
328433d6423SLionel Sambuc }
329433d6423SLionel Sambuc else if ( !npats && argc>0) {
330433d6423SLionel Sambuc if (argv[0][0]) {
331433d6423SLionel Sambuc npats=argc;
332433d6423SLionel Sambuc patts=argv;
333433d6423SLionel Sambuc }
334433d6423SLionel Sambuc }
335433d6423SLionel Sambuc }
336433d6423SLionel Sambuc if (npats > 1)
337433d6423SLionel Sambuc usage();
338433d6423SLionel Sambuc if (Batch && npats)
339433d6423SLionel Sambuc usage();
340433d6423SLionel Sambuc if (Verbose) {
341433d6423SLionel Sambuc if (freopen(LOGFILE, "a", stderr)==NULL) {
342433d6423SLionel Sambuc printf("Can't open log file %s\n",LOGFILE);
343433d6423SLionel Sambuc exit(0200);
344433d6423SLionel Sambuc }
345433d6423SLionel Sambuc setbuf(stderr, (char *)NULL);
346433d6423SLionel Sambuc fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);
347433d6423SLionel Sambuc }
348433d6423SLionel Sambuc if (Fromcu && !Quiet) {
349433d6423SLionel Sambuc if (Verbose == 0)
350433d6423SLionel Sambuc Verbose = 2;
351433d6423SLionel Sambuc }
352433d6423SLionel Sambuc vfile("%s %s for %s\n", Progname, VERSION, OS);
353433d6423SLionel Sambuc mode(1);
354433d6423SLionel Sambuc if (signal(SIGINT, bibi) == SIG_IGN) {
355433d6423SLionel Sambuc signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
356433d6423SLionel Sambuc }
357433d6423SLionel Sambuc else {
358433d6423SLionel Sambuc signal(SIGINT, bibi); signal(SIGKILL, bibi);
359433d6423SLionel Sambuc }
360433d6423SLionel Sambuc signal(SIGTERM, bibi);
361433d6423SLionel Sambuc if (wcreceive(npats, patts)==ERROR) {
362433d6423SLionel Sambuc exitcode=0200;
363433d6423SLionel Sambuc canit();
364433d6423SLionel Sambuc }
365433d6423SLionel Sambuc mode(0);
366433d6423SLionel Sambuc vfile("exitcode = %d\n",exitcode);
367433d6423SLionel Sambuc if (exitcode && !Zmodem) /* bellow again with all thy might. */
368433d6423SLionel Sambuc canit();
369433d6423SLionel Sambuc if (exitcode)
370433d6423SLionel Sambuc cucheck();
371433d6423SLionel Sambuc if (Verbose) putc('\n', stderr);
372433d6423SLionel Sambuc exit(exitcode ? exitcode:SS_NORMAL);
373433d6423SLionel Sambuc }
374433d6423SLionel Sambuc
375433d6423SLionel Sambuc
usage()376433d6423SLionel Sambuc int usage()
377433d6423SLionel Sambuc {
378433d6423SLionel Sambuc cucheck();
379433d6423SLionel Sambuc #ifdef vax11c
380433d6423SLionel Sambuc fprintf(stderr,"Usage: rz [-abeuvy]\n");
381433d6423SLionel Sambuc #else
382433d6423SLionel Sambuc fprintf(stderr,"Usage: rz [-abeuvy] (ZMODEM)\n");
383433d6423SLionel Sambuc fprintf(stderr,"or rb [-abuvy] (YMODEM)\n");
384433d6423SLionel Sambuc fprintf(stderr,"or rx [-abcv] file (XMODEM or XMODEM-1k)\n");
385433d6423SLionel Sambuc #endif
386433d6423SLionel Sambuc fprintf(stderr," -a ASCII transfer (strip CR)\n");
387433d6423SLionel Sambuc fprintf(stderr," -b Binary transfer for all files\n");
388433d6423SLionel Sambuc #ifndef vax11c
389433d6423SLionel Sambuc fprintf(stderr," -c Use 16 bit CRC (XMODEM)\n");
390433d6423SLionel Sambuc #endif
391433d6423SLionel Sambuc fprintf(stderr," -e Escape control characters (ZMODEM)\n");
392433d6423SLionel Sambuc fprintf(stderr," -v Verbose more v's give more info\n");
393433d6423SLionel Sambuc fprintf(stderr," -y Yes, clobber existing file if any\n");
394433d6423SLionel Sambuc fprintf(stderr,"%s %s for %s by Chuck Forsberg, Omen Technology INC\n",
395433d6423SLionel Sambuc Progname, VERSION, OS);
396433d6423SLionel Sambuc fprintf(stderr, "\t\t\042The High Reliability Software\042\n");
397433d6423SLionel Sambuc exit(SS_NORMAL);
398433d6423SLionel Sambuc }
399433d6423SLionel Sambuc
vfile(const char * string,...)400433d6423SLionel Sambuc void vfile(const char *string, ...)
401433d6423SLionel Sambuc {
402433d6423SLionel Sambuc if (Verbose > 2) {
403433d6423SLionel Sambuc va_list args;
404433d6423SLionel Sambuc va_start(args, string);
405433d6423SLionel Sambuc vfprintf(stderr, string, args);
406433d6423SLionel Sambuc va_end(args);
407433d6423SLionel Sambuc fprintf(stderr, "\n");
408433d6423SLionel Sambuc }
409433d6423SLionel Sambuc }
410433d6423SLionel Sambuc
411433d6423SLionel Sambuc /*
412433d6423SLionel Sambuc * Let's receive something already.
413433d6423SLionel Sambuc */
414433d6423SLionel Sambuc
415433d6423SLionel Sambuc char *rbmsg =
416433d6423SLionel Sambuc "%s ready. To begin transfer, type \"%s file ...\" to your modem program\r\n\n";
417433d6423SLionel Sambuc
wcreceive(int argc,char ** argp)418433d6423SLionel Sambuc int wcreceive(int argc, char **argp)
419433d6423SLionel Sambuc {
420433d6423SLionel Sambuc register int c;
421433d6423SLionel Sambuc
422433d6423SLionel Sambuc if (Batch || argc==0) {
423433d6423SLionel Sambuc Crcflg=1;
424433d6423SLionel Sambuc if ( !Quiet)
425433d6423SLionel Sambuc fprintf(stderr, rbmsg, Progname, Nozmodem?"sb":"sz");
426433d6423SLionel Sambuc if ((c=tryz())) {
427433d6423SLionel Sambuc if (c == ZCOMPL)
428433d6423SLionel Sambuc return OK;
429433d6423SLionel Sambuc if (c == ERROR)
430433d6423SLionel Sambuc goto fubar;
431433d6423SLionel Sambuc c = rzfiles();
432433d6423SLionel Sambuc if (c)
433433d6423SLionel Sambuc goto fubar;
434433d6423SLionel Sambuc } else {
435433d6423SLionel Sambuc for (;;) {
436433d6423SLionel Sambuc if (wcrxpn(secbuf)== ERROR)
437433d6423SLionel Sambuc goto fubar;
438433d6423SLionel Sambuc if (secbuf[0]==0)
439433d6423SLionel Sambuc return OK;
440433d6423SLionel Sambuc if (procheader(secbuf) == ERROR)
441433d6423SLionel Sambuc goto fubar;
442433d6423SLionel Sambuc if (wcrx()==ERROR)
443433d6423SLionel Sambuc goto fubar;
444433d6423SLionel Sambuc }
445433d6423SLionel Sambuc }
446433d6423SLionel Sambuc } else {
447433d6423SLionel Sambuc Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
448433d6423SLionel Sambuc
449433d6423SLionel Sambuc procheader(""); strcpy(Pathname, *argp); checkpath(Pathname);
450433d6423SLionel Sambuc fprintf(stderr, "\nrz: ready to receive %s\r\n", Pathname);
451433d6423SLionel Sambuc if ((fout=fopen(Pathname, "w")) == NULL)
452433d6423SLionel Sambuc return ERROR;
453433d6423SLionel Sambuc if (wcrx()==ERROR)
454433d6423SLionel Sambuc goto fubar;
455433d6423SLionel Sambuc }
456433d6423SLionel Sambuc return OK;
457433d6423SLionel Sambuc fubar:
458433d6423SLionel Sambuc canit();
459433d6423SLionel Sambuc #ifndef vax11c
460433d6423SLionel Sambuc if (Topipe && fout) {
461433d6423SLionel Sambuc pclose(fout); return ERROR;
462433d6423SLionel Sambuc }
463433d6423SLionel Sambuc #endif
464433d6423SLionel Sambuc if (fout)
465433d6423SLionel Sambuc fclose(fout);
466433d6423SLionel Sambuc #ifndef vax11c
467433d6423SLionel Sambuc if (Restricted) {
468433d6423SLionel Sambuc unlink(Pathname);
469433d6423SLionel Sambuc fprintf(stderr, "\r\nrz: %s removed.\r\n", Pathname);
470433d6423SLionel Sambuc }
471433d6423SLionel Sambuc #endif
472433d6423SLionel Sambuc return ERROR;
473433d6423SLionel Sambuc }
474433d6423SLionel Sambuc
475433d6423SLionel Sambuc
476433d6423SLionel Sambuc /*
477433d6423SLionel Sambuc * Fetch a pathname from the other end as a C ctyle ASCIZ string.
478433d6423SLionel Sambuc * Length is indeterminate as long as less than Blklen
479433d6423SLionel Sambuc * A null string represents no more files (YMODEM)
480433d6423SLionel Sambuc *
481433d6423SLionel Sambuc * Parameter rpn is for receiving a pathname
482433d6423SLionel Sambuc */
wcrxpn(char * rpn)483433d6423SLionel Sambuc int wcrxpn(char *rpn)
484433d6423SLionel Sambuc {
485433d6423SLionel Sambuc register int c;
486433d6423SLionel Sambuc
487433d6423SLionel Sambuc #ifdef NFGVMIN
488433d6423SLionel Sambuc readline(1);
489433d6423SLionel Sambuc #else
490433d6423SLionel Sambuc purgeline();
491433d6423SLionel Sambuc #endif
492433d6423SLionel Sambuc
493433d6423SLionel Sambuc et_tu:
494433d6423SLionel Sambuc Firstsec=TRUE; Eofseen=FALSE;
495433d6423SLionel Sambuc sendline(Crcflg?WANTCRC:NAK);
496433d6423SLionel Sambuc Lleft=0; /* Do read next time ... */
497433d6423SLionel Sambuc while ((c = wcgetsec(rpn, 100)) != 0) {
498433d6423SLionel Sambuc if (c == WCEOT) {
499433d6423SLionel Sambuc zperr( "Pathname fetch returned %d", c);
500433d6423SLionel Sambuc sendline(ACK);
501433d6423SLionel Sambuc Lleft=0; /* Do read next time ... */
502433d6423SLionel Sambuc readline(1);
503433d6423SLionel Sambuc goto et_tu;
504433d6423SLionel Sambuc }
505433d6423SLionel Sambuc return ERROR;
506433d6423SLionel Sambuc }
507433d6423SLionel Sambuc sendline(ACK);
508433d6423SLionel Sambuc return OK;
509433d6423SLionel Sambuc }
510433d6423SLionel Sambuc
511433d6423SLionel Sambuc /*
512433d6423SLionel Sambuc * Adapted from CMODEM13.C, written by
513433d6423SLionel Sambuc * Jack M. Wierda and Roderick W. Hart
514433d6423SLionel Sambuc */
515433d6423SLionel Sambuc
wcrx()516433d6423SLionel Sambuc int wcrx()
517433d6423SLionel Sambuc {
518433d6423SLionel Sambuc register int sectnum, sectcurr;
519433d6423SLionel Sambuc register char sendchar;
520433d6423SLionel Sambuc int cblklen; /* bytes to dump this block */
521433d6423SLionel Sambuc
522433d6423SLionel Sambuc Firstsec=TRUE;sectnum=0; Eofseen=FALSE;
523433d6423SLionel Sambuc sendchar=Crcflg?WANTCRC:NAK;
524433d6423SLionel Sambuc
525433d6423SLionel Sambuc for (;;) {
526433d6423SLionel Sambuc sendline(sendchar); /* send it now, we're ready! */
527433d6423SLionel Sambuc Lleft=0; /* Do read next time ... */
528433d6423SLionel Sambuc sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130);
529433d6423SLionel Sambuc report(sectcurr);
530433d6423SLionel Sambuc if (sectcurr==((sectnum+1) &0377)) {
531433d6423SLionel Sambuc sectnum++;
532433d6423SLionel Sambuc cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;
533433d6423SLionel Sambuc if (putsec(secbuf, cblklen)==ERROR)
534433d6423SLionel Sambuc return ERROR;
535433d6423SLionel Sambuc if ((Bytesleft-=cblklen) < 0)
536433d6423SLionel Sambuc Bytesleft = 0;
537433d6423SLionel Sambuc sendchar=ACK;
538433d6423SLionel Sambuc }
539433d6423SLionel Sambuc else if (sectcurr==(sectnum&0377)) {
540433d6423SLionel Sambuc zperr( "Received dup Sector");
541433d6423SLionel Sambuc sendchar=ACK;
542433d6423SLionel Sambuc }
543433d6423SLionel Sambuc else if (sectcurr==WCEOT) {
544433d6423SLionel Sambuc if (closeit())
545433d6423SLionel Sambuc return ERROR;
546433d6423SLionel Sambuc sendline(ACK);
547433d6423SLionel Sambuc Lleft=0; /* Do read next time ... */
548433d6423SLionel Sambuc return OK;
549433d6423SLionel Sambuc }
550433d6423SLionel Sambuc else if (sectcurr==ERROR)
551433d6423SLionel Sambuc return ERROR;
552433d6423SLionel Sambuc else {
553433d6423SLionel Sambuc zperr( "Sync Error");
554433d6423SLionel Sambuc return ERROR;
555433d6423SLionel Sambuc }
556433d6423SLionel Sambuc }
557433d6423SLionel Sambuc }
558433d6423SLionel Sambuc
559433d6423SLionel Sambuc /*
560433d6423SLionel Sambuc * Wcgetsec fetches a Ward Christensen type sector.
561433d6423SLionel Sambuc * Returns sector number encountered or ERROR if valid sector not received,
562433d6423SLionel Sambuc * or CAN CAN received
563433d6423SLionel Sambuc * or WCEOT if eot sector
564433d6423SLionel Sambuc * time is timeout for first char, set to 4 seconds thereafter
565433d6423SLionel Sambuc ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
566433d6423SLionel Sambuc * (Caller must do that when he is good and ready to get next sector)
567433d6423SLionel Sambuc */
568433d6423SLionel Sambuc
wcgetsec(char * rxbuf,int maxtime)569433d6423SLionel Sambuc int wcgetsec(char *rxbuf, int maxtime)
570433d6423SLionel Sambuc {
571433d6423SLionel Sambuc register int checksum, wcj, firstch;
572433d6423SLionel Sambuc register unsigned short oldcrc;
573433d6423SLionel Sambuc register char *p;
574433d6423SLionel Sambuc int sectcurr;
575433d6423SLionel Sambuc
576433d6423SLionel Sambuc for (Lastrx=errors=0; errors<RETRYMAX; errors++) {
577433d6423SLionel Sambuc
578433d6423SLionel Sambuc if ((firstch=readline(maxtime))==STX) {
579433d6423SLionel Sambuc Blklen=1024; goto get2;
580433d6423SLionel Sambuc }
581433d6423SLionel Sambuc if (firstch==SOH) {
582433d6423SLionel Sambuc Blklen=128;
583433d6423SLionel Sambuc get2:
584433d6423SLionel Sambuc sectcurr=readline(1);
585433d6423SLionel Sambuc if ((sectcurr+(oldcrc=readline(1)))==0377) {
586433d6423SLionel Sambuc oldcrc=checksum=0;
587433d6423SLionel Sambuc for (p=rxbuf,wcj=Blklen; --wcj>=0; ) {
588433d6423SLionel Sambuc if ((firstch=readline(1)) < 0)
589433d6423SLionel Sambuc goto bilge;
590433d6423SLionel Sambuc oldcrc=updcrc(firstch, oldcrc);
591433d6423SLionel Sambuc checksum += (*p++ = firstch);
592433d6423SLionel Sambuc }
593433d6423SLionel Sambuc if ((firstch=readline(1)) < 0)
594433d6423SLionel Sambuc goto bilge;
595433d6423SLionel Sambuc if (Crcflg) {
596433d6423SLionel Sambuc oldcrc=updcrc(firstch, oldcrc);
597433d6423SLionel Sambuc if ((firstch=readline(1)) < 0)
598433d6423SLionel Sambuc goto bilge;
599433d6423SLionel Sambuc oldcrc=updcrc(firstch, oldcrc);
600433d6423SLionel Sambuc if (oldcrc & 0xFFFF)
601433d6423SLionel Sambuc zperr( "CRC");
602433d6423SLionel Sambuc else {
603433d6423SLionel Sambuc Firstsec=FALSE;
604433d6423SLionel Sambuc return sectcurr;
605433d6423SLionel Sambuc }
606433d6423SLionel Sambuc }
607433d6423SLionel Sambuc else if (((checksum-firstch)&0377)==0) {
608433d6423SLionel Sambuc Firstsec=FALSE;
609433d6423SLionel Sambuc return sectcurr;
610433d6423SLionel Sambuc }
611433d6423SLionel Sambuc else
612433d6423SLionel Sambuc zperr( "Checksum");
613433d6423SLionel Sambuc }
614433d6423SLionel Sambuc else
615433d6423SLionel Sambuc zperr("Sector number garbled");
616433d6423SLionel Sambuc }
617433d6423SLionel Sambuc /* make sure eot really is eot and not just mixmash */
618433d6423SLionel Sambuc #ifdef NFGVMIN
619433d6423SLionel Sambuc else if (firstch==EOT && readline(1)==TIMEOUT)
620433d6423SLionel Sambuc return WCEOT;
621433d6423SLionel Sambuc #else
622433d6423SLionel Sambuc else if (firstch==EOT && Lleft==0)
623433d6423SLionel Sambuc return WCEOT;
624433d6423SLionel Sambuc #endif
625433d6423SLionel Sambuc else if (firstch==CAN) {
626433d6423SLionel Sambuc if (Lastrx==CAN) {
627433d6423SLionel Sambuc zperr( "Sender CANcelled");
628433d6423SLionel Sambuc return ERROR;
629433d6423SLionel Sambuc } else {
630433d6423SLionel Sambuc Lastrx=CAN;
631433d6423SLionel Sambuc continue;
632433d6423SLionel Sambuc }
633433d6423SLionel Sambuc }
634433d6423SLionel Sambuc else if (firstch==TIMEOUT) {
635433d6423SLionel Sambuc if (Firstsec)
636433d6423SLionel Sambuc goto humbug;
637433d6423SLionel Sambuc bilge:
638433d6423SLionel Sambuc zperr( "TIMEOUT");
639433d6423SLionel Sambuc }
640433d6423SLionel Sambuc else
641433d6423SLionel Sambuc zperr( "Got 0%o sector header", firstch);
642433d6423SLionel Sambuc
643433d6423SLionel Sambuc humbug:
644433d6423SLionel Sambuc Lastrx=0;
645433d6423SLionel Sambuc while(readline(1)!=TIMEOUT)
646433d6423SLionel Sambuc ;
647433d6423SLionel Sambuc if (Firstsec) {
648433d6423SLionel Sambuc sendline(Crcflg?WANTCRC:NAK);
649433d6423SLionel Sambuc Lleft=0; /* Do read next time ... */
650433d6423SLionel Sambuc } else {
651433d6423SLionel Sambuc maxtime=40; sendline(NAK);
652433d6423SLionel Sambuc Lleft=0; /* Do read next time ... */
653433d6423SLionel Sambuc }
654433d6423SLionel Sambuc }
655433d6423SLionel Sambuc /* try to stop the bubble machine. */
656433d6423SLionel Sambuc canit();
657433d6423SLionel Sambuc return ERROR;
658433d6423SLionel Sambuc }
659433d6423SLionel Sambuc
660433d6423SLionel Sambuc #ifndef vax11c
661433d6423SLionel Sambuc /*
662433d6423SLionel Sambuc * This version of readline is reasoably well suited for
663433d6423SLionel Sambuc * reading many characters.
664433d6423SLionel Sambuc * (except, currently, for the Regulus version!)
665433d6423SLionel Sambuc *
666433d6423SLionel Sambuc * timeout is in tenths of seconds
667433d6423SLionel Sambuc */
readline(int timeout)668433d6423SLionel Sambuc int readline(int timeout)
669433d6423SLionel Sambuc {
670433d6423SLionel Sambuc register int n;
671433d6423SLionel Sambuc static char *cdq; /* pointer for removing chars from linbuf */
672433d6423SLionel Sambuc
673433d6423SLionel Sambuc if (--Lleft >= 0) {
674433d6423SLionel Sambuc if (Verbose > 8) {
675433d6423SLionel Sambuc fprintf(stderr, "%02x ", *cdq&0377);
676433d6423SLionel Sambuc }
677433d6423SLionel Sambuc return (*cdq++ & 0377);
678433d6423SLionel Sambuc }
679433d6423SLionel Sambuc n = timeout/10;
680433d6423SLionel Sambuc if (n < 2)
681433d6423SLionel Sambuc n = 3;
682433d6423SLionel Sambuc if (Verbose > 5)
683433d6423SLionel Sambuc fprintf(stderr, "Calling read: alarm=%d Readnum=%d ",
684433d6423SLionel Sambuc n, Readnum);
685433d6423SLionel Sambuc if (setjmp(tohere)) {
686433d6423SLionel Sambuc #ifdef TIOCFLUSH
687433d6423SLionel Sambuc /* ioctl(iofd, TIOCFLUSH, 0); */
688433d6423SLionel Sambuc #endif
689433d6423SLionel Sambuc Lleft = 0;
690433d6423SLionel Sambuc if (Verbose>1)
691433d6423SLionel Sambuc fprintf(stderr, "Readline:TIMEOUT\n");
692433d6423SLionel Sambuc return TIMEOUT;
693433d6423SLionel Sambuc }
694433d6423SLionel Sambuc signal(SIGALRM, alrm); alarm(n);
695433d6423SLionel Sambuc Lleft=read(iofd, cdq=linbuf, Readnum);
696433d6423SLionel Sambuc alarm(0);
697433d6423SLionel Sambuc if (Verbose > 5) {
698433d6423SLionel Sambuc fprintf(stderr, "Read returned %d bytes\n", Lleft);
699433d6423SLionel Sambuc }
700433d6423SLionel Sambuc if (Lleft < 1)
701433d6423SLionel Sambuc return TIMEOUT;
702433d6423SLionel Sambuc --Lleft;
703433d6423SLionel Sambuc if (Verbose > 8) {
704433d6423SLionel Sambuc fprintf(stderr, "%02x ", *cdq&0377);
705433d6423SLionel Sambuc }
706433d6423SLionel Sambuc return (*cdq++ & 0377);
707433d6423SLionel Sambuc }
708433d6423SLionel Sambuc
709433d6423SLionel Sambuc
710433d6423SLionel Sambuc
711433d6423SLionel Sambuc /*
712433d6423SLionel Sambuc * Purge the modem input queue of all characters
713433d6423SLionel Sambuc */
purgeline()714433d6423SLionel Sambuc void purgeline()
715433d6423SLionel Sambuc {
716433d6423SLionel Sambuc Lleft = 0;
717433d6423SLionel Sambuc #ifdef USG
718433d6423SLionel Sambuc ioctl(iofd, TCFLSH, 0);
719433d6423SLionel Sambuc #else
720433d6423SLionel Sambuc lseek(iofd, 0L, 2);
721433d6423SLionel Sambuc #endif
722433d6423SLionel Sambuc }
723433d6423SLionel Sambuc #endif
724433d6423SLionel Sambuc
725433d6423SLionel Sambuc
726433d6423SLionel Sambuc /*
727433d6423SLionel Sambuc * Process incoming file information header
728433d6423SLionel Sambuc */
procheader(char * name)729433d6423SLionel Sambuc int procheader(char *name)
730433d6423SLionel Sambuc {
731433d6423SLionel Sambuc register char *openmode, *p;
732433d6423SLionel Sambuc
733433d6423SLionel Sambuc /* set default parameters and overrides */
734433d6423SLionel Sambuc openmode = "w";
735433d6423SLionel Sambuc Thisbinary = (!Rxascii) || Rxbinary;
736433d6423SLionel Sambuc if (Lzmanag)
737433d6423SLionel Sambuc zmanag = Lzmanag;
738433d6423SLionel Sambuc
739433d6423SLionel Sambuc /*
740433d6423SLionel Sambuc * Process ZMODEM remote file management requests
741433d6423SLionel Sambuc */
742433d6423SLionel Sambuc if (!Rxbinary && zconv == ZCNL) /* Remote ASCII override */
743433d6423SLionel Sambuc Thisbinary = 0;
744433d6423SLionel Sambuc if (zconv == ZCBIN) /* Remote Binary override */
745433d6423SLionel Sambuc Thisbinary = TRUE;
746433d6423SLionel Sambuc else if (zmanag == ZMAPND)
747433d6423SLionel Sambuc openmode = "a";
748433d6423SLionel Sambuc
749433d6423SLionel Sambuc #ifndef BIX
750433d6423SLionel Sambuc /* Check for existing file */
751433d6423SLionel Sambuc if (!Rxclob && (zmanag&ZMMASK) != ZMCLOB && (fout=fopen(name, "r"))) {
752433d6423SLionel Sambuc fclose(fout); return ERROR;
753433d6423SLionel Sambuc }
754433d6423SLionel Sambuc #endif
755433d6423SLionel Sambuc
756433d6423SLionel Sambuc Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
757433d6423SLionel Sambuc
758433d6423SLionel Sambuc p = name + 1 + strlen(name);
759433d6423SLionel Sambuc if (*p) { /* file coming from Unix or DOS system */
760433d6423SLionel Sambuc sscanf(p, "%ld%lo%o", &Bytesleft, &Modtime, &Filemode);
761433d6423SLionel Sambuc #ifndef vax11c
762433d6423SLionel Sambuc if (Filemode & UNIXFILE)
763433d6423SLionel Sambuc ++Thisbinary;
764433d6423SLionel Sambuc #endif
765433d6423SLionel Sambuc if (Verbose) {
766433d6423SLionel Sambuc fprintf(stderr, "\nIncoming: %s %ld %lo %o\n",
767433d6423SLionel Sambuc name, Bytesleft, Modtime, Filemode);
768433d6423SLionel Sambuc }
769433d6423SLionel Sambuc }
770433d6423SLionel Sambuc
771433d6423SLionel Sambuc #ifdef BIX
772433d6423SLionel Sambuc if ((fout=fopen("scratchpad", openmode)) == NULL)
773433d6423SLionel Sambuc return ERROR;
774433d6423SLionel Sambuc return OK;
775433d6423SLionel Sambuc #else
776433d6423SLionel Sambuc
777433d6423SLionel Sambuc else { /* File coming from CP/M system */
778433d6423SLionel Sambuc for (p=name; *p; ++p) /* change / to _ */
779433d6423SLionel Sambuc if ( *p == '/')
780433d6423SLionel Sambuc *p = '_';
781433d6423SLionel Sambuc
782433d6423SLionel Sambuc if ( *--p == '.') /* zap trailing period */
783433d6423SLionel Sambuc *p = 0;
784433d6423SLionel Sambuc }
785433d6423SLionel Sambuc
786433d6423SLionel Sambuc #ifndef vax11c
787433d6423SLionel Sambuc if (!Zmodem && MakeLCPathname && !IsAnyLower(name)
788433d6423SLionel Sambuc && !(Filemode&UNIXFILE))
789433d6423SLionel Sambuc uncaps(name);
790433d6423SLionel Sambuc #endif
791433d6423SLionel Sambuc if (Topipe > 0) {
792433d6423SLionel Sambuc sprintf(Pathname, "%s %s", Progname+2, name);
793433d6423SLionel Sambuc if (Verbose)
794433d6423SLionel Sambuc fprintf(stderr, "Topipe: %s %s\n",
795433d6423SLionel Sambuc Pathname, Thisbinary?"BIN":"ASCII");
796433d6423SLionel Sambuc #ifndef vax11c
797433d6423SLionel Sambuc if ((fout=popen(Pathname, "w")) == NULL)
798433d6423SLionel Sambuc return ERROR;
799433d6423SLionel Sambuc #endif
800433d6423SLionel Sambuc } else {
801433d6423SLionel Sambuc strcpy(Pathname, name);
802433d6423SLionel Sambuc if (Verbose) {
803433d6423SLionel Sambuc fprintf(stderr, "Receiving %s %s %s\n",
804433d6423SLionel Sambuc name, Thisbinary?"BIN":"ASCII", openmode);
805433d6423SLionel Sambuc }
806433d6423SLionel Sambuc checkpath(name);
807433d6423SLionel Sambuc if (Nflag)
808433d6423SLionel Sambuc name = "/dev/null";
809433d6423SLionel Sambuc #ifndef vax11c
810433d6423SLionel Sambuc #ifdef OMEN
811433d6423SLionel Sambuc if (name[0] == '!' || name[0] == '|') {
812433d6423SLionel Sambuc if ( !(fout = popen(name+1, "w"))) {
813433d6423SLionel Sambuc return ERROR;
814433d6423SLionel Sambuc }
815433d6423SLionel Sambuc Topipe = -1; return(OK);
816433d6423SLionel Sambuc }
817433d6423SLionel Sambuc #endif
818433d6423SLionel Sambuc #endif
819433d6423SLionel Sambuc #ifdef MD
820433d6423SLionel Sambuc fout = fopen(name, openmode);
821433d6423SLionel Sambuc if ( !fout)
822433d6423SLionel Sambuc if (make_dirs(name))
823433d6423SLionel Sambuc fout = fopen(name, openmode);
824433d6423SLionel Sambuc #else
825433d6423SLionel Sambuc fout = fopen(name, openmode);
826433d6423SLionel Sambuc #endif
827433d6423SLionel Sambuc if ( !fout)
828433d6423SLionel Sambuc return ERROR;
829433d6423SLionel Sambuc }
830433d6423SLionel Sambuc return OK;
831433d6423SLionel Sambuc #endif /* BIX */
832433d6423SLionel Sambuc }
833433d6423SLionel Sambuc
834433d6423SLionel Sambuc #ifdef MD
835433d6423SLionel Sambuc /*
836433d6423SLionel Sambuc * Directory-creating routines from Public Domain TAR by John Gilmore
837433d6423SLionel Sambuc */
838433d6423SLionel Sambuc
839433d6423SLionel Sambuc /*
840433d6423SLionel Sambuc * After a file/link/symlink/dir creation has failed, see if
841433d6423SLionel Sambuc * it's because some required directory was not present, and if
842433d6423SLionel Sambuc * so, create all required dirs.
843433d6423SLionel Sambuc */
make_dirs(char * pathname)844433d6423SLionel Sambuc int make_dirs(char *pathname)
845433d6423SLionel Sambuc {
846433d6423SLionel Sambuc register char *p; /* Points into path */
847433d6423SLionel Sambuc int madeone = 0; /* Did we do anything yet? */
848433d6423SLionel Sambuc int save_errno = errno; /* Remember caller's errno */
849433d6423SLionel Sambuc char *strchr();
850433d6423SLionel Sambuc
851433d6423SLionel Sambuc if (errno != ENOENT)
852433d6423SLionel Sambuc return 0; /* Not our problem */
853433d6423SLionel Sambuc
854433d6423SLionel Sambuc for (p = strchr(pathname, '/'); p != NULL; p = strchr(p+1, '/')) {
855433d6423SLionel Sambuc /* Avoid mkdir of empty string, if leading or double '/' */
856433d6423SLionel Sambuc if (p == pathname || p[-1] == '/')
857433d6423SLionel Sambuc continue;
858433d6423SLionel Sambuc /* Avoid mkdir where last part of path is '.' */
859433d6423SLionel Sambuc if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
860433d6423SLionel Sambuc continue;
861433d6423SLionel Sambuc *p = 0; /* Truncate the path there */
862433d6423SLionel Sambuc if ( !makedir(pathname, 0777)) { /* Try to create it as a dir */
863433d6423SLionel Sambuc vfile("Made directory %s\n", pathname);
864433d6423SLionel Sambuc madeone++; /* Remember if we made one */
865433d6423SLionel Sambuc *p = '/';
866433d6423SLionel Sambuc continue;
867433d6423SLionel Sambuc }
868433d6423SLionel Sambuc *p = '/';
869433d6423SLionel Sambuc if (errno == EEXIST) /* Directory already exists */
870433d6423SLionel Sambuc continue;
871433d6423SLionel Sambuc /*
872433d6423SLionel Sambuc * Some other error in the makedir. We return to the caller.
873433d6423SLionel Sambuc */
874433d6423SLionel Sambuc break;
875433d6423SLionel Sambuc }
876433d6423SLionel Sambuc errno = save_errno; /* Restore caller's errno */
877433d6423SLionel Sambuc return madeone; /* Tell them to retry if we made one */
878433d6423SLionel Sambuc }
879433d6423SLionel Sambuc
880433d6423SLionel Sambuc #if (MD != 2)
881433d6423SLionel Sambuc #define TERM_SIGNAL(status) ((status) & 0x7F)
882433d6423SLionel Sambuc #define TERM_COREDUMP(status) (((status) & 0x80) != 0)
883433d6423SLionel Sambuc #define TERM_VALUE(status) ((status) >> 8)
884433d6423SLionel Sambuc /*
885433d6423SLionel Sambuc * Make a directory. Compatible with the mkdir() system call on 4.2BSD.
886433d6423SLionel Sambuc */
makedir(char * dpath,int dmode)887433d6423SLionel Sambuc int makedir(char *dpath, int dmode)
888433d6423SLionel Sambuc {
889433d6423SLionel Sambuc int cpid, status;
890433d6423SLionel Sambuc struct stat statbuf;
891433d6423SLionel Sambuc
892433d6423SLionel Sambuc if (stat(dpath,&statbuf) == 0) {
893433d6423SLionel Sambuc errno = EEXIST; /* Stat worked, so it already exists */
894433d6423SLionel Sambuc return -1;
895433d6423SLionel Sambuc }
896433d6423SLionel Sambuc
897433d6423SLionel Sambuc /* If stat fails for a reason other than non-existence, return error */
898433d6423SLionel Sambuc if (errno != ENOENT) return -1;
899433d6423SLionel Sambuc
900433d6423SLionel Sambuc switch (cpid = fork()) {
901433d6423SLionel Sambuc
902433d6423SLionel Sambuc case -1: /* Error in fork() */
903433d6423SLionel Sambuc return(-1); /* Errno is set already */
904433d6423SLionel Sambuc
905433d6423SLionel Sambuc case 0: /* Child process */
906433d6423SLionel Sambuc /*
907433d6423SLionel Sambuc * Cheap hack to set mode of new directory. Since this
908433d6423SLionel Sambuc * child process is going away anyway, we zap its umask.
909433d6423SLionel Sambuc * FIXME, this won't suffice to set SUID, SGID, etc. on this
910433d6423SLionel Sambuc * directory. Does anybody care?
911433d6423SLionel Sambuc */
912433d6423SLionel Sambuc status = umask(0); /* Get current umask */
913433d6423SLionel Sambuc status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
914433d6423SLionel Sambuc execl("/bin/mkdir", "mkdir", dpath, (char *)0);
915433d6423SLionel Sambuc _exit(-1); /* Can't exec /bin/mkdir */
916433d6423SLionel Sambuc
917433d6423SLionel Sambuc default: /* Parent process */
918433d6423SLionel Sambuc while (cpid != wait(&status)) ; /* Wait for kid to finish */
919433d6423SLionel Sambuc }
920433d6423SLionel Sambuc
921433d6423SLionel Sambuc if (TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0) {
922433d6423SLionel Sambuc errno = EIO; /* We don't know why, but */
923433d6423SLionel Sambuc return -1; /* /bin/mkdir failed */
924433d6423SLionel Sambuc }
925433d6423SLionel Sambuc
926433d6423SLionel Sambuc return 0;
927433d6423SLionel Sambuc }
928433d6423SLionel Sambuc #endif /* MD != 2 */
929433d6423SLionel Sambuc #endif /* MD */
930433d6423SLionel Sambuc
931433d6423SLionel Sambuc /*
932433d6423SLionel Sambuc * Putsec writes the n characters of buf to receive file fout.
933433d6423SLionel Sambuc * If not in binary mode, carriage returns, and all characters
934433d6423SLionel Sambuc * starting with CPMEOF are discarded.
935433d6423SLionel Sambuc */
putsec(char * buf,int n)936433d6423SLionel Sambuc int putsec(char *buf, int n)
937433d6423SLionel Sambuc {
938433d6423SLionel Sambuc register char *p;
939433d6423SLionel Sambuc
940433d6423SLionel Sambuc if (n == 0)
941433d6423SLionel Sambuc return OK;
942433d6423SLionel Sambuc if (Thisbinary) {
943433d6423SLionel Sambuc for (p=buf; --n>=0; )
944433d6423SLionel Sambuc putc( *p++, fout);
945433d6423SLionel Sambuc }
946433d6423SLionel Sambuc else {
947433d6423SLionel Sambuc if (Eofseen)
948433d6423SLionel Sambuc return OK;
949433d6423SLionel Sambuc for (p=buf; --n>=0; ++p ) {
950433d6423SLionel Sambuc if ( *p == '\r')
951433d6423SLionel Sambuc continue;
952433d6423SLionel Sambuc if (*p == CPMEOF) {
953433d6423SLionel Sambuc Eofseen=TRUE; return OK;
954433d6423SLionel Sambuc }
955433d6423SLionel Sambuc putc(*p ,fout);
956433d6423SLionel Sambuc }
957433d6423SLionel Sambuc }
958433d6423SLionel Sambuc return OK;
959433d6423SLionel Sambuc }
960433d6423SLionel Sambuc
961433d6423SLionel Sambuc #ifndef vax11c
962433d6423SLionel Sambuc /*
963433d6423SLionel Sambuc * Send a character to modem. Small is beautiful.
964433d6423SLionel Sambuc */
sendline(int c)965433d6423SLionel Sambuc void sendline(int c)
966433d6423SLionel Sambuc {
967433d6423SLionel Sambuc char d;
968433d6423SLionel Sambuc
969433d6423SLionel Sambuc d = c;
970433d6423SLionel Sambuc if (Verbose>6)
971433d6423SLionel Sambuc fprintf(stderr, "Sendline: %x\n", c);
972433d6423SLionel Sambuc write(1, &d, 1);
973433d6423SLionel Sambuc }
974433d6423SLionel Sambuc
flushmo()975433d6423SLionel Sambuc void flushmo() {}
976433d6423SLionel Sambuc #endif
977433d6423SLionel Sambuc
978433d6423SLionel Sambuc
979433d6423SLionel Sambuc
980433d6423SLionel Sambuc
981433d6423SLionel Sambuc
982433d6423SLionel Sambuc /* make string s lower case */
uncaps(char * s)983433d6423SLionel Sambuc void uncaps(char *s)
984433d6423SLionel Sambuc {
985433d6423SLionel Sambuc for ( ; *s; ++s)
986433d6423SLionel Sambuc if (isupper(*s))
987433d6423SLionel Sambuc *s = tolower(*s);
988433d6423SLionel Sambuc }
989433d6423SLionel Sambuc /*
990433d6423SLionel Sambuc * IsAnyLower returns TRUE if string s has lower case letters.
991433d6423SLionel Sambuc */
IsAnyLower(char * s)992433d6423SLionel Sambuc int IsAnyLower(char *s)
993433d6423SLionel Sambuc {
994433d6423SLionel Sambuc for ( ; *s; ++s)
995433d6423SLionel Sambuc if (islower(*s))
996433d6423SLionel Sambuc return TRUE;
997433d6423SLionel Sambuc return FALSE;
998433d6423SLionel Sambuc }
999433d6423SLionel Sambuc
1000433d6423SLionel Sambuc /*
1001433d6423SLionel Sambuc * substr(string, token) searches for token in string s
1002433d6423SLionel Sambuc * returns pointer to token within string if found, NULL otherwise
1003433d6423SLionel Sambuc */
1004433d6423SLionel Sambuc char *
substr(char * s,char * t)1005433d6423SLionel Sambuc substr(char *s, char *t)
1006433d6423SLionel Sambuc {
1007433d6423SLionel Sambuc register char *ss,*tt;
1008433d6423SLionel Sambuc /* search for first char of token */
1009433d6423SLionel Sambuc for (ss=s; *s; s++)
1010433d6423SLionel Sambuc if (*s == *t)
1011433d6423SLionel Sambuc /* compare token with substring */
1012433d6423SLionel Sambuc for (ss=s,tt=t; ;) {
1013433d6423SLionel Sambuc if (*tt == 0)
1014433d6423SLionel Sambuc return s;
1015433d6423SLionel Sambuc if (*ss++ != *tt++)
1016433d6423SLionel Sambuc break;
1017433d6423SLionel Sambuc }
1018433d6423SLionel Sambuc return (char *)NULL;
1019433d6423SLionel Sambuc }
1020433d6423SLionel Sambuc
1021433d6423SLionel Sambuc /*
1022433d6423SLionel Sambuc * Log an error
1023433d6423SLionel Sambuc */
1024433d6423SLionel Sambuc /*VARARGS1*/
zperr(char * s,char * p,char * u)1025433d6423SLionel Sambuc void zperr(char *s, char *p, char *u)
1026433d6423SLionel Sambuc {
1027433d6423SLionel Sambuc if (Verbose <= 0)
1028433d6423SLionel Sambuc return;
1029433d6423SLionel Sambuc fprintf(stderr, "Retry %d: ", errors);
1030433d6423SLionel Sambuc fprintf(stderr, s, p, u);
1031433d6423SLionel Sambuc fprintf(stderr, "\n");
1032433d6423SLionel Sambuc }
1033433d6423SLionel Sambuc
1034433d6423SLionel Sambuc /* send cancel string to get the other end to shut up */
canit()1035433d6423SLionel Sambuc void canit()
1036433d6423SLionel Sambuc {
1037433d6423SLionel Sambuc static char canistr[] = {
1038433d6423SLionel Sambuc 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
1039433d6423SLionel Sambuc };
1040433d6423SLionel Sambuc
1041433d6423SLionel Sambuc #ifdef vax11c
1042433d6423SLionel Sambuc raw_wbuf(strlen(canistr), canistr);
1043433d6423SLionel Sambuc purgeline();
1044433d6423SLionel Sambuc #else
1045*d0055759SDavid van Moolenbroek printf("%s", canistr);
1046433d6423SLionel Sambuc Lleft=0; /* Do read next time ... */
1047433d6423SLionel Sambuc fflush(stdout);
1048433d6423SLionel Sambuc #endif
1049433d6423SLionel Sambuc }
1050433d6423SLionel Sambuc
1051433d6423SLionel Sambuc
report(int sct)1052433d6423SLionel Sambuc void report(int sct)
1053433d6423SLionel Sambuc {
1054433d6423SLionel Sambuc if (Verbose>1)
1055433d6423SLionel Sambuc fprintf(stderr,"%03d%c",sct,sct%10? ' ' : '\r');
1056433d6423SLionel Sambuc }
1057433d6423SLionel Sambuc
1058433d6423SLionel Sambuc #ifndef vax11c
1059433d6423SLionel Sambuc /*
1060433d6423SLionel Sambuc * If called as [-][dir/../]vrzCOMMAND set Verbose to 1
1061433d6423SLionel Sambuc * If called as [-][dir/../]rzCOMMAND set the pipe flag
1062433d6423SLionel Sambuc * If called as rb use YMODEM protocol
1063433d6423SLionel Sambuc */
chkinvok(char * s)1064433d6423SLionel Sambuc void chkinvok(char *s)
1065433d6423SLionel Sambuc {
1066433d6423SLionel Sambuc register char *p;
1067433d6423SLionel Sambuc
1068433d6423SLionel Sambuc p = s;
1069433d6423SLionel Sambuc while (*p == '-')
1070433d6423SLionel Sambuc s = ++p;
1071433d6423SLionel Sambuc while (*p)
1072433d6423SLionel Sambuc if (*p++ == '/')
1073433d6423SLionel Sambuc s = p;
1074433d6423SLionel Sambuc if (*s == 'v') {
1075433d6423SLionel Sambuc Verbose=1; ++s;
1076433d6423SLionel Sambuc }
1077433d6423SLionel Sambuc Progname = s;
1078433d6423SLionel Sambuc if (s[0]=='r' && s[1]=='z')
1079433d6423SLionel Sambuc Batch = TRUE;
1080433d6423SLionel Sambuc if (s[0]=='r' && s[1]=='b')
1081433d6423SLionel Sambuc Batch = Nozmodem = TRUE;
1082433d6423SLionel Sambuc if (s[2] && s[0]=='r' && s[1]=='b')
1083433d6423SLionel Sambuc Topipe = 1;
1084433d6423SLionel Sambuc if (s[2] && s[0]=='r' && s[1]=='z')
1085433d6423SLionel Sambuc Topipe = 1;
1086433d6423SLionel Sambuc }
1087433d6423SLionel Sambuc #endif
1088433d6423SLionel Sambuc
1089433d6423SLionel Sambuc /*
1090433d6423SLionel Sambuc * Totalitarian Communist pathname processing
1091433d6423SLionel Sambuc */
checkpath(char * name)1092433d6423SLionel Sambuc void checkpath(char *name)
1093433d6423SLionel Sambuc {
1094433d6423SLionel Sambuc if (Restricted) {
1095433d6423SLionel Sambuc if (fopen(name, "r") != NULL) {
1096433d6423SLionel Sambuc canit();
1097433d6423SLionel Sambuc fprintf(stderr, "\r\nrz: %s exists\n", name);
1098433d6423SLionel Sambuc bibi(-1);
1099433d6423SLionel Sambuc }
1100433d6423SLionel Sambuc /* restrict pathnames to current tree or uucppublic */
1101433d6423SLionel Sambuc if ( substr(name, "../")
1102433d6423SLionel Sambuc || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
1103433d6423SLionel Sambuc canit();
1104433d6423SLionel Sambuc fprintf(stderr,"\r\nrz:\tSecurity Violation\r\n");
1105433d6423SLionel Sambuc bibi(-1);
1106433d6423SLionel Sambuc }
1107433d6423SLionel Sambuc }
1108433d6423SLionel Sambuc }
1109433d6423SLionel Sambuc
1110433d6423SLionel Sambuc /*
1111433d6423SLionel Sambuc * Initialize for Zmodem receive attempt, try to activate Zmodem sender
1112433d6423SLionel Sambuc * Handles ZSINIT frame
1113433d6423SLionel Sambuc * Return ZFILE if Zmodem filename received, -1 on error,
1114433d6423SLionel Sambuc * ZCOMPL if transaction finished, else 0
1115433d6423SLionel Sambuc */
tryz()1116433d6423SLionel Sambuc int tryz()
1117433d6423SLionel Sambuc {
1118433d6423SLionel Sambuc register int c, n;
1119433d6423SLionel Sambuc register int cmdzack1flg;
1120433d6423SLionel Sambuc
1121433d6423SLionel Sambuc if (Nozmodem) /* Check for "rb" program name */
1122433d6423SLionel Sambuc return 0;
1123433d6423SLionel Sambuc
1124433d6423SLionel Sambuc
1125433d6423SLionel Sambuc for (n=Zmodem?15:5; --n>=0; ) {
1126433d6423SLionel Sambuc /* Set buffer length (0) and capability flags */
1127433d6423SLionel Sambuc #ifdef SEGMENTS
1128433d6423SLionel Sambuc stohdr(SEGMENTS*1024L);
1129433d6423SLionel Sambuc #else
1130433d6423SLionel Sambuc stohdr(0L);
1131433d6423SLionel Sambuc #endif
1132433d6423SLionel Sambuc #ifdef CANBREAK
1133433d6423SLionel Sambuc Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
1134433d6423SLionel Sambuc #else
1135433d6423SLionel Sambuc Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
1136433d6423SLionel Sambuc #endif
1137433d6423SLionel Sambuc if (Zctlesc)
1138433d6423SLionel Sambuc Txhdr[ZF0] |= TESCCTL;
1139433d6423SLionel Sambuc zshhdr(tryzhdrtype, Txhdr);
1140433d6423SLionel Sambuc if (tryzhdrtype == ZSKIP) /* Don't skip too far */
1141433d6423SLionel Sambuc tryzhdrtype = ZRINIT; /* CAF 8-21-87 */
1142433d6423SLionel Sambuc again:
1143433d6423SLionel Sambuc switch (zgethdr(Rxhdr, 0)) {
1144433d6423SLionel Sambuc case ZRQINIT:
1145433d6423SLionel Sambuc continue;
1146433d6423SLionel Sambuc case ZEOF:
1147433d6423SLionel Sambuc continue;
1148433d6423SLionel Sambuc case TIMEOUT:
1149433d6423SLionel Sambuc continue;
1150433d6423SLionel Sambuc case ZFILE:
1151433d6423SLionel Sambuc zconv = Rxhdr[ZF0];
1152433d6423SLionel Sambuc zmanag = Rxhdr[ZF1];
1153433d6423SLionel Sambuc ztrans = Rxhdr[ZF2];
1154433d6423SLionel Sambuc tryzhdrtype = ZRINIT;
1155433d6423SLionel Sambuc c = zrdata(secbuf, 1024);
1156433d6423SLionel Sambuc mode(3);
1157433d6423SLionel Sambuc if (c == GOTCRCW)
1158433d6423SLionel Sambuc return ZFILE;
1159433d6423SLionel Sambuc zshhdr(ZNAK, Txhdr);
1160433d6423SLionel Sambuc goto again;
1161433d6423SLionel Sambuc case ZSINIT:
1162433d6423SLionel Sambuc Zctlesc = TESCCTL & Rxhdr[ZF0];
1163433d6423SLionel Sambuc if (zrdata(Attn, ZATTNLEN) == GOTCRCW) {
1164433d6423SLionel Sambuc stohdr(1L);
1165433d6423SLionel Sambuc zshhdr(ZACK, Txhdr);
1166433d6423SLionel Sambuc goto again;
1167433d6423SLionel Sambuc }
1168433d6423SLionel Sambuc zshhdr(ZNAK, Txhdr);
1169433d6423SLionel Sambuc goto again;
1170433d6423SLionel Sambuc case ZFREECNT:
1171433d6423SLionel Sambuc stohdr(getfree());
1172433d6423SLionel Sambuc zshhdr(ZACK, Txhdr);
1173433d6423SLionel Sambuc goto again;
1174433d6423SLionel Sambuc case ZCOMMAND:
1175433d6423SLionel Sambuc #ifdef vax11c
1176433d6423SLionel Sambuc return ERROR;
1177433d6423SLionel Sambuc #else
1178433d6423SLionel Sambuc cmdzack1flg = Rxhdr[ZF0];
1179433d6423SLionel Sambuc if (zrdata(secbuf, 1024) == GOTCRCW) {
1180433d6423SLionel Sambuc if (cmdzack1flg & ZCACK1)
1181433d6423SLionel Sambuc stohdr(0L);
1182433d6423SLionel Sambuc else
1183433d6423SLionel Sambuc stohdr((long)sys2(secbuf));
1184433d6423SLionel Sambuc purgeline(); /* dump impatient questions */
1185433d6423SLionel Sambuc do {
1186433d6423SLionel Sambuc zshhdr(ZCOMPL, Txhdr);
1187433d6423SLionel Sambuc }
1188433d6423SLionel Sambuc while (++errors<20 && zgethdr(Rxhdr,1) != ZFIN);
1189433d6423SLionel Sambuc ackbibi();
1190433d6423SLionel Sambuc if (cmdzack1flg & ZCACK1)
1191433d6423SLionel Sambuc exec2(secbuf);
1192433d6423SLionel Sambuc return ZCOMPL;
1193433d6423SLionel Sambuc }
1194433d6423SLionel Sambuc zshhdr(ZNAK, Txhdr); goto again;
1195433d6423SLionel Sambuc #endif
1196433d6423SLionel Sambuc case ZCOMPL:
1197433d6423SLionel Sambuc goto again;
1198433d6423SLionel Sambuc default:
1199433d6423SLionel Sambuc continue;
1200433d6423SLionel Sambuc case ZFIN:
1201433d6423SLionel Sambuc ackbibi(); return ZCOMPL;
1202433d6423SLionel Sambuc case ZCAN:
1203433d6423SLionel Sambuc return ERROR;
1204433d6423SLionel Sambuc }
1205433d6423SLionel Sambuc }
1206433d6423SLionel Sambuc return 0;
1207433d6423SLionel Sambuc }
1208433d6423SLionel Sambuc
1209433d6423SLionel Sambuc /*
1210433d6423SLionel Sambuc * Receive 1 or more files with ZMODEM protocol
1211433d6423SLionel Sambuc */
rzfiles()1212433d6423SLionel Sambuc int rzfiles()
1213433d6423SLionel Sambuc {
1214433d6423SLionel Sambuc register int c;
1215433d6423SLionel Sambuc
1216433d6423SLionel Sambuc for (;;) {
1217433d6423SLionel Sambuc switch (c = rzfile()) {
1218433d6423SLionel Sambuc case ZEOF:
1219433d6423SLionel Sambuc case ZSKIP:
1220433d6423SLionel Sambuc switch (tryz()) {
1221433d6423SLionel Sambuc case ZCOMPL:
1222433d6423SLionel Sambuc return OK;
1223433d6423SLionel Sambuc default:
1224433d6423SLionel Sambuc return ERROR;
1225433d6423SLionel Sambuc case ZFILE:
1226433d6423SLionel Sambuc break;
1227433d6423SLionel Sambuc }
1228433d6423SLionel Sambuc continue;
1229433d6423SLionel Sambuc default:
1230433d6423SLionel Sambuc return c;
1231433d6423SLionel Sambuc case ERROR:
1232433d6423SLionel Sambuc return ERROR;
1233433d6423SLionel Sambuc }
1234433d6423SLionel Sambuc }
1235433d6423SLionel Sambuc }
1236433d6423SLionel Sambuc
1237433d6423SLionel Sambuc /*
1238433d6423SLionel Sambuc * Receive a file with ZMODEM protocol
1239433d6423SLionel Sambuc * Assumes file name frame is in secbuf
1240433d6423SLionel Sambuc */
rzfile()1241433d6423SLionel Sambuc int rzfile()
1242433d6423SLionel Sambuc {
1243433d6423SLionel Sambuc register int c, n;
1244433d6423SLionel Sambuc long rxbytes;
1245433d6423SLionel Sambuc
1246433d6423SLionel Sambuc Eofseen=FALSE;
1247433d6423SLionel Sambuc if (procheader(secbuf) == ERROR) {
1248433d6423SLionel Sambuc return (tryzhdrtype = ZSKIP);
1249433d6423SLionel Sambuc }
1250433d6423SLionel Sambuc
1251433d6423SLionel Sambuc n = 20; rxbytes = 0l;
1252433d6423SLionel Sambuc
1253433d6423SLionel Sambuc for (;;) {
1254433d6423SLionel Sambuc #ifdef SEGMENTS
1255433d6423SLionel Sambuc chinseg = 0;
1256433d6423SLionel Sambuc #endif
1257433d6423SLionel Sambuc stohdr(rxbytes);
1258433d6423SLionel Sambuc zshhdr(ZRPOS, Txhdr);
1259433d6423SLionel Sambuc nxthdr:
1260433d6423SLionel Sambuc switch (c = zgethdr(Rxhdr, 0)) {
1261433d6423SLionel Sambuc default:
1262433d6423SLionel Sambuc vfile("rzfile: zgethdr returned %d", c);
1263433d6423SLionel Sambuc return ERROR;
1264433d6423SLionel Sambuc case ZNAK:
1265433d6423SLionel Sambuc case TIMEOUT:
1266433d6423SLionel Sambuc #ifdef SEGMENTS
1267433d6423SLionel Sambuc putsec(secbuf, chinseg);
1268433d6423SLionel Sambuc chinseg = 0;
1269433d6423SLionel Sambuc #endif
1270433d6423SLionel Sambuc if ( --n < 0) {
1271433d6423SLionel Sambuc vfile("rzfile: zgethdr returned %d", c);
1272433d6423SLionel Sambuc return ERROR;
1273433d6423SLionel Sambuc }
1274433d6423SLionel Sambuc case ZFILE:
1275433d6423SLionel Sambuc zrdata(secbuf, 1024);
1276433d6423SLionel Sambuc continue;
1277433d6423SLionel Sambuc case ZEOF:
1278433d6423SLionel Sambuc #ifdef SEGMENTS
1279433d6423SLionel Sambuc putsec(secbuf, chinseg);
1280433d6423SLionel Sambuc chinseg = 0;
1281433d6423SLionel Sambuc #endif
1282433d6423SLionel Sambuc if (rclhdr(Rxhdr) != rxbytes) {
1283433d6423SLionel Sambuc /*
1284433d6423SLionel Sambuc * Ignore eof if it's at wrong place - force
1285433d6423SLionel Sambuc * a timeout because the eof might have gone
1286433d6423SLionel Sambuc * out before we sent our zrpos.
1287433d6423SLionel Sambuc */
1288433d6423SLionel Sambuc errors = 0; goto nxthdr;
1289433d6423SLionel Sambuc }
1290433d6423SLionel Sambuc if (closeit()) {
1291433d6423SLionel Sambuc tryzhdrtype = ZFERR;
1292433d6423SLionel Sambuc vfile("rzfile: closeit returned <> 0");
1293433d6423SLionel Sambuc return ERROR;
1294433d6423SLionel Sambuc }
1295433d6423SLionel Sambuc vfile("rzfile: normal EOF");
1296433d6423SLionel Sambuc return c;
1297433d6423SLionel Sambuc case ERROR: /* Too much garbage in header search error */
1298433d6423SLionel Sambuc #ifdef SEGMENTS
1299433d6423SLionel Sambuc putsec(secbuf, chinseg);
1300433d6423SLionel Sambuc chinseg = 0;
1301433d6423SLionel Sambuc #endif
1302433d6423SLionel Sambuc if ( --n < 0) {
1303433d6423SLionel Sambuc vfile("rzfile: zgethdr returned %d", c);
1304433d6423SLionel Sambuc return ERROR;
1305433d6423SLionel Sambuc }
1306433d6423SLionel Sambuc zmputs(Attn);
1307433d6423SLionel Sambuc continue;
1308433d6423SLionel Sambuc case ZSKIP:
1309433d6423SLionel Sambuc #ifdef SEGMENTS
1310433d6423SLionel Sambuc putsec(secbuf, chinseg);
1311433d6423SLionel Sambuc chinseg = 0;
1312433d6423SLionel Sambuc #endif
1313433d6423SLionel Sambuc closeit();
1314433d6423SLionel Sambuc vfile("rzfile: Sender SKIPPED file");
1315433d6423SLionel Sambuc return c;
1316433d6423SLionel Sambuc case ZDATA:
1317433d6423SLionel Sambuc if (rclhdr(Rxhdr) != rxbytes) {
1318433d6423SLionel Sambuc if ( --n < 0) {
1319433d6423SLionel Sambuc return ERROR;
1320433d6423SLionel Sambuc }
1321433d6423SLionel Sambuc #ifdef SEGMENTS
1322433d6423SLionel Sambuc putsec(secbuf, chinseg);
1323433d6423SLionel Sambuc chinseg = 0;
1324433d6423SLionel Sambuc #endif
1325433d6423SLionel Sambuc zmputs(Attn); continue;
1326433d6423SLionel Sambuc }
1327433d6423SLionel Sambuc moredata:
1328433d6423SLionel Sambuc if (Verbose>1)
1329433d6423SLionel Sambuc fprintf(stderr, "\r%7ld ZMODEM%s ",
1330433d6423SLionel Sambuc rxbytes, Crc32?" CRC-32":"");
1331433d6423SLionel Sambuc #ifdef SEGMENTS
1332433d6423SLionel Sambuc if (chinseg >= (1024 * SEGMENTS)) {
1333433d6423SLionel Sambuc putsec(secbuf, chinseg);
1334433d6423SLionel Sambuc chinseg = 0;
1335433d6423SLionel Sambuc }
1336433d6423SLionel Sambuc switch (c = zrdata(secbuf+chinseg, 1024))
1337433d6423SLionel Sambuc #else
1338433d6423SLionel Sambuc switch (c = zrdata(secbuf, 1024))
1339433d6423SLionel Sambuc #endif
1340433d6423SLionel Sambuc {
1341433d6423SLionel Sambuc case ZCAN:
1342433d6423SLionel Sambuc #ifdef SEGMENTS
1343433d6423SLionel Sambuc putsec(secbuf, chinseg);
1344433d6423SLionel Sambuc chinseg = 0;
1345433d6423SLionel Sambuc #endif
1346433d6423SLionel Sambuc vfile("rzfile: zgethdr returned %d", c);
1347433d6423SLionel Sambuc return ERROR;
1348433d6423SLionel Sambuc case ERROR: /* CRC error */
1349433d6423SLionel Sambuc #ifdef SEGMENTS
1350433d6423SLionel Sambuc putsec(secbuf, chinseg);
1351433d6423SLionel Sambuc chinseg = 0;
1352433d6423SLionel Sambuc #endif
1353433d6423SLionel Sambuc if ( --n < 0) {
1354433d6423SLionel Sambuc vfile("rzfile: zgethdr returned %d", c);
1355433d6423SLionel Sambuc return ERROR;
1356433d6423SLionel Sambuc }
1357433d6423SLionel Sambuc zmputs(Attn);
1358433d6423SLionel Sambuc continue;
1359433d6423SLionel Sambuc case TIMEOUT:
1360433d6423SLionel Sambuc #ifdef SEGMENTS
1361433d6423SLionel Sambuc putsec(secbuf, chinseg);
1362433d6423SLionel Sambuc chinseg = 0;
1363433d6423SLionel Sambuc #endif
1364433d6423SLionel Sambuc if ( --n < 0) {
1365433d6423SLionel Sambuc vfile("rzfile: zgethdr returned %d", c);
1366433d6423SLionel Sambuc return ERROR;
1367433d6423SLionel Sambuc }
1368433d6423SLionel Sambuc continue;
1369433d6423SLionel Sambuc case GOTCRCW:
1370433d6423SLionel Sambuc n = 20;
1371433d6423SLionel Sambuc #ifdef SEGMENTS
1372433d6423SLionel Sambuc chinseg += Rxcount;
1373433d6423SLionel Sambuc putsec(secbuf, chinseg);
1374433d6423SLionel Sambuc chinseg = 0;
1375433d6423SLionel Sambuc #else
1376433d6423SLionel Sambuc putsec(secbuf, Rxcount);
1377433d6423SLionel Sambuc #endif
1378433d6423SLionel Sambuc rxbytes += Rxcount;
1379433d6423SLionel Sambuc stohdr(rxbytes);
1380433d6423SLionel Sambuc zshhdr(ZACK, Txhdr);
1381433d6423SLionel Sambuc sendline(XON);
1382433d6423SLionel Sambuc goto nxthdr;
1383433d6423SLionel Sambuc case GOTCRCQ:
1384433d6423SLionel Sambuc n = 20;
1385433d6423SLionel Sambuc #ifdef SEGMENTS
1386433d6423SLionel Sambuc chinseg += Rxcount;
1387433d6423SLionel Sambuc #else
1388433d6423SLionel Sambuc putsec(secbuf, Rxcount);
1389433d6423SLionel Sambuc #endif
1390433d6423SLionel Sambuc rxbytes += Rxcount;
1391433d6423SLionel Sambuc stohdr(rxbytes);
1392433d6423SLionel Sambuc zshhdr(ZACK, Txhdr);
1393433d6423SLionel Sambuc goto moredata;
1394433d6423SLionel Sambuc case GOTCRCG:
1395433d6423SLionel Sambuc n = 20;
1396433d6423SLionel Sambuc #ifdef SEGMENTS
1397433d6423SLionel Sambuc chinseg += Rxcount;
1398433d6423SLionel Sambuc #else
1399433d6423SLionel Sambuc putsec(secbuf, Rxcount);
1400433d6423SLionel Sambuc #endif
1401433d6423SLionel Sambuc rxbytes += Rxcount;
1402433d6423SLionel Sambuc goto moredata;
1403433d6423SLionel Sambuc case GOTCRCE:
1404433d6423SLionel Sambuc n = 20;
1405433d6423SLionel Sambuc #ifdef SEGMENTS
1406433d6423SLionel Sambuc chinseg += Rxcount;
1407433d6423SLionel Sambuc #else
1408433d6423SLionel Sambuc putsec(secbuf, Rxcount);
1409433d6423SLionel Sambuc #endif
1410433d6423SLionel Sambuc rxbytes += Rxcount;
1411433d6423SLionel Sambuc goto nxthdr;
1412433d6423SLionel Sambuc }
1413433d6423SLionel Sambuc }
1414433d6423SLionel Sambuc }
1415433d6423SLionel Sambuc }
1416433d6423SLionel Sambuc
1417433d6423SLionel Sambuc /*
1418433d6423SLionel Sambuc * Send a string to the modem, processing for \336 (sleep 1 sec)
1419433d6423SLionel Sambuc * and \335 (break signal)
1420433d6423SLionel Sambuc */
zmputs(char * s)1421433d6423SLionel Sambuc void zmputs(char *s)
1422433d6423SLionel Sambuc {
1423433d6423SLionel Sambuc register int c;
1424433d6423SLionel Sambuc
1425433d6423SLionel Sambuc while (*s) {
1426433d6423SLionel Sambuc switch (c = *s++) {
1427433d6423SLionel Sambuc case '\336':
1428433d6423SLionel Sambuc sleep(1); continue;
1429433d6423SLionel Sambuc case '\335':
1430433d6423SLionel Sambuc sendbrk(); continue;
1431433d6423SLionel Sambuc default:
1432433d6423SLionel Sambuc sendline(c);
1433433d6423SLionel Sambuc }
1434433d6423SLionel Sambuc }
1435433d6423SLionel Sambuc }
1436433d6423SLionel Sambuc
1437433d6423SLionel Sambuc /*
1438433d6423SLionel Sambuc * Close the receive dataset, return OK or ERROR
1439433d6423SLionel Sambuc */
closeit()1440433d6423SLionel Sambuc int closeit()
1441433d6423SLionel Sambuc {
1442433d6423SLionel Sambuc time_t q;
1443433d6423SLionel Sambuc
1444433d6423SLionel Sambuc #ifndef vax11c
1445433d6423SLionel Sambuc if (Topipe) {
1446433d6423SLionel Sambuc if (pclose(fout)) {
1447433d6423SLionel Sambuc return ERROR;
1448433d6423SLionel Sambuc }
1449433d6423SLionel Sambuc return OK;
1450433d6423SLionel Sambuc }
1451433d6423SLionel Sambuc #endif
1452433d6423SLionel Sambuc if (fclose(fout)==ERROR) {
1453433d6423SLionel Sambuc fprintf(stderr, "file close ERROR\n");
1454433d6423SLionel Sambuc return ERROR;
1455433d6423SLionel Sambuc }
1456433d6423SLionel Sambuc #ifndef vax11c
1457433d6423SLionel Sambuc if (Modtime) {
1458433d6423SLionel Sambuc timep[0] = time(&q);
1459433d6423SLionel Sambuc timep[1] = Modtime;
1460433d6423SLionel Sambuc utime(Pathname, (struct utimbuf *) timep);
1461433d6423SLionel Sambuc }
1462433d6423SLionel Sambuc #endif
1463433d6423SLionel Sambuc if ((Filemode&S_IFMT) == S_IFREG)
1464433d6423SLionel Sambuc chmod(Pathname, (07777 & Filemode));
1465433d6423SLionel Sambuc return OK;
1466433d6423SLionel Sambuc }
1467433d6423SLionel Sambuc
1468433d6423SLionel Sambuc /*
1469433d6423SLionel Sambuc * Ack a ZFIN packet, let byegones be byegones
1470433d6423SLionel Sambuc */
ackbibi()1471433d6423SLionel Sambuc void ackbibi()
1472433d6423SLionel Sambuc {
1473433d6423SLionel Sambuc register int n;
1474433d6423SLionel Sambuc
1475433d6423SLionel Sambuc vfile("ackbibi:");
1476433d6423SLionel Sambuc Readnum = 1;
1477433d6423SLionel Sambuc stohdr(0L);
1478433d6423SLionel Sambuc for (n=3; --n>=0; ) {
1479433d6423SLionel Sambuc purgeline();
1480433d6423SLionel Sambuc zshhdr(ZFIN, Txhdr);
1481433d6423SLionel Sambuc switch (readline(100)) {
1482433d6423SLionel Sambuc case 'O':
1483433d6423SLionel Sambuc readline(1); /* Discard 2nd 'O' */
1484433d6423SLionel Sambuc vfile("ackbibi complete");
1485433d6423SLionel Sambuc return;
1486433d6423SLionel Sambuc case RCDO:
1487433d6423SLionel Sambuc return;
1488433d6423SLionel Sambuc case TIMEOUT:
1489433d6423SLionel Sambuc default:
1490433d6423SLionel Sambuc break;
1491433d6423SLionel Sambuc }
1492433d6423SLionel Sambuc }
1493433d6423SLionel Sambuc }
1494433d6423SLionel Sambuc
1495433d6423SLionel Sambuc
1496433d6423SLionel Sambuc
1497433d6423SLionel Sambuc /*
1498433d6423SLionel Sambuc * Local console output simulation
1499433d6423SLionel Sambuc */
bttyout(int c)1500433d6423SLionel Sambuc void bttyout(int c)
1501433d6423SLionel Sambuc {
1502433d6423SLionel Sambuc if (Verbose || Fromcu)
1503433d6423SLionel Sambuc putc(c, stderr);
1504433d6423SLionel Sambuc }
1505433d6423SLionel Sambuc
1506433d6423SLionel Sambuc #ifndef vax11c
1507433d6423SLionel Sambuc /*
1508433d6423SLionel Sambuc * Strip leading ! if present, do shell escape.
1509433d6423SLionel Sambuc */
sys2(char * s)1510433d6423SLionel Sambuc int sys2(char *s)
1511433d6423SLionel Sambuc {
1512433d6423SLionel Sambuc if (*s == '!')
1513433d6423SLionel Sambuc ++s;
1514433d6423SLionel Sambuc return system(s);
1515433d6423SLionel Sambuc }
1516433d6423SLionel Sambuc /*
1517433d6423SLionel Sambuc * Strip leading ! if present, do exec.
1518433d6423SLionel Sambuc */
exec2(char * s)1519433d6423SLionel Sambuc void exec2(char *s)
1520433d6423SLionel Sambuc {
1521433d6423SLionel Sambuc if (*s == '!')
1522433d6423SLionel Sambuc ++s;
1523433d6423SLionel Sambuc mode(0);
1524433d6423SLionel Sambuc execl("/bin/sh", "sh", "-c", s);
1525433d6423SLionel Sambuc }
1526433d6423SLionel Sambuc #endif
1527433d6423SLionel Sambuc /* End of rz.c */
1528