xref: /OK3568_Linux_fs/u-boot/common/lrz.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2   lrz - receive files with x/y/zmodem
3   Copyright (C) until 1988 Chuck Forsberg (Omen Technology INC)
4   Copyright (C) 1994 Matt Porter, Michael D. Black
5   Copyright (C) 1996, 1997 Uwe Ohse
6 
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2, or (at your option)
10   any later version.
11 
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16 
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20   02111-1307, USA.
21 
22   originally written by Chuck Forsberg
23 */
24 
25 #include "zglobal.h"
26 
27 #define SS_NORMAL 0
28 #include <stdio.h>
29 #include <stdlib.h>
30 //#include <signal.h>
31 //#include <ctype.h>
32 #include <errno.h>
33 //#include <getopt.h>
34 
35 #ifdef HAVE_UTIME_H
36 #include <utime.h>
37 #endif
38 
39 //#include "timing.h"
40 //#include "long-options.h"
41 //#include "error.h"
42 //#include "xstrtol.h"
43 
44 #ifndef STRICT_PROTOTYPES
45 //extern time_t time();
46 //extern char *strerror();
47 //extern char *strstr();
48 #endif
49 
50 #ifndef HAVE_ERRNO_DECLARATION
51 extern int errno;
52 #endif
53 
54 #define MAX_BLOCK 8192
55 
56 /*
57  * Max value for HOWMANY is 255 if NFGVMIN is not defined.
58  *   A larger value reduces system overhead but may evoke kernel bugs.
59  *   133 corresponds to an XMODEM/CRC sector
60  */
61 #ifndef HOWMANY
62 #ifdef NFGVMIN
63 #define HOWMANY MAX_BLOCK
64 #else
65 #define HOWMANY 255
66 #endif
67 #endif
68 
69 unsigned Baudrate = 2400;
70 
71 //FILE *fout;
72 
73 
74 int Lastrx;
75 int Crcflg;
76 int Firstsec;
77 int errors;
78 int Restricted=1;	/* restricted; no /.. or ../ in filenames */
79 int Readnum = HOWMANY;	/* Number of bytes to ask for in read() from modem */
80 int skip_if_not_found;
81 
82 char *Pathname;
83 const char *program_name="rz";		/* the name by which we were called */
84 
85 int Topipe=0;
86 int MakeLCPathname=TRUE;	/* make received pathname lower case */
87 int Verbose=0;
88 int Quiet=0;		/* overrides logic that would otherwise set verbose */
89 int Nflag = 0;		/* Don't really transfer files */
90 int Rxclob=TRUE;;	/* Clobber existing file */
91 int Rxbinary=FALSE;	/* receive all files in bin mode */
92 int Rxascii=FALSE;	/* receive files in ascii (translate) mode */
93 int Thisbinary;		/* current file is to be received in bin mode */
94 int try_resume=FALSE;
95 int allow_remote_commands=FALSE;
96 int junk_path=FALSE;
97 int no_timeout=FALSE;
98 enum zm_type_enum protocol=ZM_ZMODEM;
99 int	under_rsh=FALSE;
100 int zmodem_requested=FALSE;
101 
102 #ifdef SEGMENTS
103 int chinseg = 0;	/* Number of characters received in this data seg */
104 char secbuf[1+(SEGMENTS+1)*MAX_BLOCK];
105 #else
106 char secbuf[MAX_BLOCK + 1];
107 #endif
108 
109 #ifdef ENABLE_TIMESYNC
110 int timesync_flag=0;
111 int in_timesync=0;
112 #endif
113 int in_tcpsync=0;
114 int tcpsync_flag=1;
115 int tcp_socket=-1;
116 int tcp_flag=0;
117 char *tcp_server_address=NULL;
118 
119 char tcp_buf[256]="";
120 #if defined(F_GETFD) && defined(F_SETFD) && defined(O_SYNC)
121 static int o_sync = 0;
122 #endif
123 static int rzfiles __P ((struct zm_fileinfo *));
124 static int tryz __P ((void));
125 static void checkpath __P ((const char *name));
126 //static void chkinvok __P ((const char *s));
127 static void report __P ((int sct));
128 static void uncaps __P ((char *s));
129 static int IsAnyLower __P ((const char *s));
130 static int putsec __P ((struct zm_fileinfo *zi, char *buf, size_t n));
131 //static int make_dirs __P ((char *pathname));
132 static int procheader __P ((char *name, struct zm_fileinfo *));
133 static int wcgetsec __P ((size_t *Blklen, char *rxbuf, unsigned int maxtime));
134 static int wcrx __P ((struct zm_fileinfo *));
135 static int wcrxpn __P ((struct zm_fileinfo *, char *rpn));
136 static int wcreceive __P ((int argc, char **argp));
137 static int rzfile __P ((struct zm_fileinfo *));
138 static void usage __P ((int exitcode, const char *what));
139 //static void usage1 __P ((int exitcode));
140 static void exec2 __P ((const char *s));
141 static int closeit __P ((struct zm_fileinfo *));
142 static void ackbibi __P ((void));
143 static int sys2 __P ((const char *s));
144 static void zmputs __P ((const char *s));
145 static size_t getfree __P ((void));
146 
147 static long buffersize=1024*128;
148 static unsigned long min_bps=0;
149 static long min_bps_time=120;
150 
151 extern int CYGACC_COMM_IF_GETC_TIMEOUT (char chan, char *c);
152 extern void CYGACC_COMM_IF_PUTC (char x, char y);
153 extern int CYGACC_COMM_IF_GETC_TIMEOUT (char chan, char *c);
154 
155 char Lzmanag;		/* Local file management request */
156 char zconv;		/* ZMODEM file conversion request */
157 char zmanag;		/* ZMODEM file management request */
158 char ztrans;		/* ZMODEM file transport request */
159 int Zctlesc;		/* Encode control characters */
160 int Zrwindow = 1400;	/* RX window size (controls garbage count) */
161 
162 int tryzhdrtype=ZRINIT;	/* Header type to send corresponding to Last rx close */
163 time_t stop_time;
164 void *zmodem_addr;
165 unsigned int zmodem_offset;
166 
167 #ifdef ENABLE_SYSLOG
168 #  if defined(ENABLE_SYSLOG_FORCE) || defined(ENABLE_SYSLOG_DEFAULT)
169 int enable_syslog=TRUE;
170 #  else
171 int enable_syslog=FALSE;
172 #  endif
173 #define DO_SYSLOG_FNAME(message) do { \
174 	if (enable_syslog) { \
175 		const char *shortname; \
176 		if (!zi->fname) \
177 			shortname="no.name"; \
178 		else { \
179 			shortname=strrchr(zi->fname,'/'); \
180 			if (!shortname) \
181 				shortname=zi->fname; \
182 			else \
183 				shortname++; \
184 		} \
185         lsyslog message ; \
186 	} \
187 } while(0)
188 #define DO_SYSLOG(message) do { \
189 	if (enable_syslog) { \
190         lsyslog message ; \
191 	} \
192 } while(0)
193 #else
194 #define DO_SYSLOG_FNAME(message) do { } while(0)
195 #define DO_SYSLOG(message) do { } while(0)
196 #endif
197 #ifdef __STDC__
198 #  define WAYTOGO
199 #  include <stdarg.h>
200 #  define VA_START(args, lastarg) va_start(args, lastarg)
201 #else
202 #  include <varargs.h>
203 #  define VA_START(args, lastarg) va_start(args)
204 #endif
205 #define error(x,y,z,a)
206 /*********************************************************/
207 /****************  PORTING FUNTIONS **********************/
208 /*********************************************************/
209 
210 // Send one character
sendline(int c)211 void sendline(int c)
212 {
213 	CYGACC_COMM_IF_PUTC(0, c);
214 }
215 //read data with timeout
216 //ret value: how many bytes read, 0=timeout, <0=error
217 //read data is store at buf
read_data(int tout_in_100ms,char * buf,int size)218 int read_data(int tout_in_100ms, char *buf, int size)
219 {
220 	extern int xyzModem_CHAR_TIMEOUT;
221 	char c;
222 	int wait_msec = tout_in_100ms * 100;
223 	int ret;
224 
225 	while(1) {
226 		ret = CYGACC_COMM_IF_GETC_TIMEOUT(0, &c);
227 		if(ret != 0) {
228 			buf[0] = c;
229 			return 1;
230 		}
231 		if(wait_msec > xyzModem_CHAR_TIMEOUT)
232 			wait_msec -= xyzModem_CHAR_TIMEOUT;
233 		else
234 			wait_msec = 0;
235 		if(wait_msec == 0)
236 			return 0;
237 	}
238 
239 
240 }
241 //send data in a buffer
send_data(int fd,char * buf,int size)242 void send_data(int fd, char *buf, int size)
243 {
244 	int i;
245 	for(i=0;i<size;i++)
246 		CYGACC_COMM_IF_PUTC(0, buf[i]);
247 
248 }
249 //flush tx data
flushmo(void)250 void flushmo(void)
251 {
252 	//flush tx
253 }
254 //return seconds elapsed between reset=1 & reset=0. float allowed
timing(int reset,time_t * nowp)255 ulong timing (int reset, time_t *nowp)
256 {
257 	static unsigned long start;
258 	if(reset) {
259 		start = get_timer(0);
260 		return 0;
261 	}
262 	else {
263 		return get_timer(start)/ 1000;
264 	}
265 
266 }
267 /***************************************************/
268 /************** END PORTING FUNCTIONS **************/
269 /***************************************************/
xsendline(int c)270 void xsendline(int c)
271 {
272 	sendline(c);
273 }
printable(int c)274 int printable(int c)
275 {
276 	if((c>=' ') && (c <= '~'))
277 		return c;
278 	return '?';
279 }
280 
281 void
282 #ifdef WAYTOGO
zperr(const char * fmt,...)283 zperr(const char *fmt, ...)
284 #else
285 zperr(fmt, va_alist)
286 	const char *fmt;
287 	va_dcl
288 #endif
289 {
290 #if 0
291     va_list ap;
292 
293 	if (Verbose<=0)
294 		return;
295 	fprintf(stderr,_("Retry %d: "),errors);
296     VA_START(ap, fmt);
297     vfprintf(stderr,fmt, ap);
298     va_end(ap);
299     putc('\n',stderr);
300 #endif
301 }
302 
303 void
304 #ifdef WAYTOGO
zpfatal(const char * fmt,...)305 zpfatal(const char *fmt, ...)
306 #else
307 zpfatal(fmt, va_alist)
308 	const char *fmt;
309 	va_dcl
310 #endif
311 {
312 #if 0
313     va_list ap;
314     int err=errno;
315 
316 	if (Verbose<=0)
317 		return;
318 	fprintf(stderr,"%s: ",program_name);
319     VA_START(ap, fmt);
320     vfprintf(stderr,fmt, ap);
321     va_end(ap);
322 	fprintf(stderr,": %s\n",strerror(err));
323 #endif
324 }
325 
326 void
327 #ifdef WAYTOGO
vfile(const char * format,...)328 vfile(const char *format, ...)
329 #else
330 vfile(format, va_alist)
331 	const char *format;
332 	va_dcl
333 #endif
334 {
335 #if 0
336     va_list ap;
337 
338 	if (Verbose < 3)
339 		return;
340     VA_START(ap, format);
341     vfprintf(stderr,format, ap);
342     va_end(ap);
343     putc('\n',stderr);
344 #endif
345 }
346 
347 #ifndef vstringf
348 /* if using gcc this function is not needed */
349 void
350 #ifdef WAYTOGO
vstringf(const char * format,...)351 vstringf(const char *format, ...)
352 #else
353 vstringf(format, va_alist)
354 	const char *format;
355 	va_dcl
356 #endif
357 {
358     va_list ap;
359 
360     VA_START(ap, format);
361     vfprintf(stderr,format, ap);
362     va_end(ap);
363 }
364 #endif
365 long cr3tab[] = { /* CRC polynomial 0xedb88320 */
366 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
367 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
368 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
369 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
370 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
371 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
372 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
373 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
374 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
375 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
376 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
377 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
378 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
379 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
380 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
381 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
382 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
383 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
384 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
385 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
386 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
387 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
388 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
389 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
390 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
391 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
392 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
393 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
394 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
395 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
396 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
397 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
398 };
399 unsigned short crctab[256] = {
400     0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
401     0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
402     0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
403     0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
404     0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
405     0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
406     0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
407     0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
408     0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
409     0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
410     0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
411     0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
412     0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
413     0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
414     0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
415     0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
416     0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
417     0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
418     0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
419     0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
420     0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
421     0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
422     0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
423     0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
424     0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
425     0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
426     0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
427     0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
428     0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
429     0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
430     0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
431     0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
432 };
433 
434 void
canit(int fd)435 canit (int fd)
436 {
437 	static char canistr[] =
438 	{
439 		24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0
440 	};
441 	purgeline(fd);
442 	//write(fd,canistr,strlen(canistr));
443 	send_data(fd, canistr, strlen(canistr));
444 	if (fd==0) {
445 		//write(1,canistr,strlen(canistr));
446 		send_data(1,canistr,strlen(canistr));
447 	}
448 }
449 
450 const char *
protname(void)451 protname(void)
452 {
453 	const char *prot_name;
454 	switch(protocol) {
455 	case ZM_XMODEM:
456 		prot_name="XMODEM";
457 		break;
458 	case ZM_YMODEM:
459 		prot_name="YMODEM";
460 		break;
461 	default:
462 		prot_name="ZMODEM";
463 		break;
464 	}
465 	return prot_name;
466 }
467 
468 /* called by signal interrupt or terminate to clean things up */
469 RETSIGTYPE
bibi(int n)470 bibi(int n)
471 {
472 	if (zmodem_requested)
473 		zmputs(Attn);
474 	canit(0);
475 	io_mode(0,0);
476 	//error(128+n,0,_("caught signal %d; exiting"), n);
477 }
478 
479 #if 0
480 static struct option const long_options[] =
481 {
482 	{"append", no_argument, NULL, '+'},
483 	{"ascii", no_argument, NULL, 'a'},
484 	{"binary", no_argument, NULL, 'b'},
485 	{"bufsize", required_argument, NULL, 'B'},
486 	{"allow-commands", no_argument, NULL, 'C'},
487 	{"allow-remote-commands", no_argument, NULL, 'C'},
488 	{"escape", no_argument, NULL, 'e'},
489 	{"rename", no_argument, NULL, 'E'},
490 	{"help", no_argument, NULL, 'h'},
491 	{"crc-check", no_argument, NULL, 'H'},
492 	{"junk-path", no_argument, NULL, 'j'},
493 	{"errors", required_argument, NULL, 3},
494 	{"disable-timeouts", no_argument, NULL, 'O'},
495 	{"disable-timeout", no_argument, NULL, 'O'}, /* i can't get it right */
496 	{"min-bps", required_argument, NULL, 'm'},
497 	{"min-bps-time", required_argument, NULL, 'M'},
498 	{"newer", no_argument, NULL, 'n'},
499 	{"newer-or-longer", no_argument, NULL, 'N'},
500 	{"protect", no_argument, NULL, 'p'},
501 	{"resume", no_argument, NULL, 'r'},
502 	{"restricted", no_argument, NULL, 'R'},
503 	{"quiet", no_argument, NULL, 'q'},
504 	{"stop-at", required_argument, NULL, 's'},
505 	{"timesync", no_argument, NULL, 'S'},
506 	{"timeout", required_argument, NULL, 't'},
507 	{"keep-uppercase", no_argument, NULL, 'u'},
508 	{"unrestrict", no_argument, NULL, 'U'},
509 	{"verbose", no_argument, NULL, 'v'},
510 	{"windowsize", required_argument, NULL, 'w'},
511 	{"with-crc", no_argument, NULL, 'c'},
512 	{"xmodem", no_argument, NULL, 'X'},
513 	{"ymodem", no_argument, NULL, 1},
514 	{"zmodem", no_argument, NULL, 'Z'},
515 	{"overwrite", no_argument, NULL, 'y'},
516 	{"null", no_argument, NULL, 'D'},
517 	{"syslog", optional_argument, NULL , 2},
518 	{"delay-startup", required_argument, NULL, 4},
519 	{"o-sync", no_argument, NULL, 5},
520 	{"o_sync", no_argument, NULL, 5},
521 	{"tcp-server", no_argument, NULL, 6},
522 	{"tcp-client", required_argument, NULL, 7},
523 	{NULL,0,NULL,0}
524 };
525 #endif
526 
527 void
show_version(void)528 show_version(void)
529 {
530 	printf ("%s (%s) %s\n", program_name, PACKAGE, VERSION);
531 }
532 
533 int
534 //main(int argc, char *argv[])
zmodem_rx(unsigned long addr,int * rxsize)535 zmodem_rx(unsigned long addr, int *rxsize)
536 {
537 	__maybe_unused register char *cp;
538 	//register int npats;
539 	//char **patts=NULL; /* keep compiler quiet */
540 	int exitcode=0;
541 	__maybe_unused int c;
542 	__maybe_unused unsigned int startup_delay=0;
543 	__maybe_unused int argc = 1;
544 	__maybe_unused char *argv[] = { "rz" };
545 	zmodem_addr = (void *)addr;
546 	zmodem_offset = 0;
547 
548 	Rxtimeout = 100;
549 #if 0
550 	setbuf(stderr, NULL);
551 	if ((cp=getenv("SHELL")) && (strstr(cp, "rsh") || strstr(cp, "rksh")
552 		|| strstr(cp,"rbash") || strstr(cp, "rshell")))
553 		under_rsh=TRUE;
554 	if ((cp=getenv("ZMODEM_RESTRICTED"))!=NULL)
555 		Restricted=2;
556 #endif
557 
558 	/* make temporary and unfinished files */
559 	//umask(0077);
560 
561 	//from_cu();
562 	//chkinvok(argv[0]);	/* if called as [-]rzCOMMAND set flag */
563 
564 #ifdef ENABLE_SYSLOG
565 	openlog(program_name,LOG_PID,ENABLE_SYSLOG);
566 #endif
567 
568 	//setlocale (LC_ALL, "");
569 	//bindtextdomain (PACKAGE, LOCALEDIR);
570 	//textdomain (PACKAGE);
571 
572 #if 0
573     parse_long_options (argc, argv, show_version, usage1);
574 
575 	while ((c = getopt_long (argc, argv,
576 		"a+bB:cCDeEhm:M:OprRqs:St:uUvw:XZy",
577 		long_options, (int *) 0)) != EOF)
578 	{
579 		unsigned long int tmp;
580 		char *tmpptr;
581 		enum strtol_error s_err;
582 
583 		switch (c)
584 		{
585 		case 0:
586 			break;
587 		case '+': Lzmanag = ZF1_ZMAPND; break;
588 		case 'a': Rxascii=TRUE;  break;
589 		case 'b': Rxbinary=TRUE; break;
590 		case 'B':
591 			if (strcmp(optarg,"auto")==0)
592 				buffersize=-1;
593 			else
594 				buffersize=strtol(optarg,NULL,10);
595 			break;
596 		case 'c': Crcflg=TRUE; break;
597 		case 'C': allow_remote_commands=TRUE; break;
598 		case 'D': Nflag = TRUE; break;
599 		case 'E': Lzmanag = ZF1_ZMCHNG; break;
600 		case 'e': Zctlesc = 1; break;
601 		case 'h': usage(0,NULL); break;
602 		case 'H': Lzmanag= ZF1_ZMCRC; break;
603 		case 'j': junk_path=TRUE; break;
604 		case 'm':
605 			s_err = xstrtoul (optarg, &tmpptr, 0, &tmp, "km");
606 			min_bps = tmp;
607 			if (s_err != LONGINT_OK)
608 				STRTOL_FATAL_ERROR (optarg, _("min_bps"), s_err);
609 			break;
610 		case 'M':
611 			s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
612 			min_bps_time = tmp;
613 			if (s_err != LONGINT_OK)
614 				STRTOL_FATAL_ERROR (optarg, _("min_bps_time"), s_err);
615 			if (min_bps_time<=1)
616 				usage(2,_("min_bps_time must be > 1"));
617 			break;
618 		case 'N': Lzmanag = ZF1_ZMNEWL;  break;
619 		case 'n': Lzmanag = ZF1_ZMNEW;  break;
620 		case 'O': no_timeout=TRUE; break;
621 		case 'p': Lzmanag = ZF1_ZMPROT;  break;
622 		case 'q': Quiet=TRUE; Verbose=0; break;
623 		case 's':
624 			if (isdigit((unsigned char) (*optarg))) {
625 				struct tm *tm;
626 				time_t t;
627 				int hh,mm;
628 				char *nex;
629 
630 				hh = strtoul (optarg, &nex, 10);
631 				if (hh>23)
632 					usage(2,_("hour to large (0..23)"));
633 				if (*nex!=':')
634 					usage(2, _("unparsable stop time\n"));
635 				nex++;
636                 mm = strtoul (optarg, &nex, 10);
637 				if (mm>59)
638 					usage(2,_("minute to large (0..59)"));
639 
640 				t=time(NULL);
641 				tm=localtime(&t);
642 				tm->tm_hour=hh;
643 				tm->tm_min=hh;
644 				stop_time=mktime(tm);
645 				if (stop_time<t)
646 					stop_time+=86400L; /* one day more */
647 				if (stop_time - t <10)
648 					usage(2,_("stop time to small"));
649 			} else {
650 				s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
651 				stop_time = tmp + time(0);
652 				if (s_err != LONGINT_OK)
653 					STRTOL_FATAL_ERROR (optarg, _("stop-at"), s_err);
654 				if (tmp<10)
655 					usage(2,_("stop time to small"));
656 			}
657 			break;
658 
659 
660 		case 'r':
661 			if (try_resume)
662 				Lzmanag= ZF1_ZMCRC;
663 			else
664 				try_resume=TRUE;
665 			break;
666 		case 'R': Restricted++;  break;
667 		case 'S':
668 #ifdef ENABLE_TIMESYNC
669 			timesync_flag++;
670 			if (timesync_flag==2) {
671 #ifdef HAVE_SETTIMEOFDAY
672 				//error(0,0,_("don't have settimeofday, will not set time\n"));
673 #endif
674 				//if (getuid()!=0)
675 				//	error(0,0,
676 				//_("not running as root (this is good!), can not set time\n"));
677 			}
678 #endif
679 			break;
680 		case 't':
681 			s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
682 			Rxtimeout = tmp;
683 			if (s_err != LONGINT_OK)
684 				STRTOL_FATAL_ERROR (optarg, _("timeout"), s_err);
685 			if (Rxtimeout<10 || Rxtimeout>1000)
686 				usage(2,_("timeout out of range 10..1000"));
687 			break;
688 		case 'w':
689 			s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
690 			Zrwindow = tmp;
691 			if (s_err != LONGINT_OK)
692 				STRTOL_FATAL_ERROR (optarg, _("window size"), s_err);
693 			break;
694 		case 'u':
695 			MakeLCPathname=FALSE; break;
696 		case 'U':
697 			if (!under_rsh)
698 				Restricted=0;
699 			else  {
700 				DO_SYSLOG((LOG_INFO,"--unrestrict option used under restricted shell"));
701 				//error(1,0,
702 	//_("security violation: can't do that under restricted shell\n"));
703 			}
704 			break;
705 		case 'v':
706 			++Verbose; break;
707 		case 'X': protocol=ZM_XMODEM; break;
708 		case 1:   protocol=ZM_YMODEM; break;
709 		case 'Z': protocol=ZM_ZMODEM; break;
710 		case 'y':
711 			Rxclob=TRUE; break;
712 		case 2:
713 #ifdef ENABLE_SYSLOG
714 #  ifndef ENABLE_SYSLOG_FORCE
715 			if (optarg && (!strcmp(optarg,"off") || !strcmp(optarg,"no"))) {
716 				if (under_rsh)
717 					;//error(0,0, _("cannot turnoff syslog"));
718 				else
719 					enable_syslog=FALSE;
720 			}
721 			else
722 				enable_syslog=TRUE;
723 #  else
724 			//error(0,0, _("cannot turnoff syslog"));
725 #  endif
726 #endif
727 		case 3:
728 			s_err = xstrtoul (optarg, NULL, 0, &tmp, "km");
729 			bytes_per_error = tmp;
730 			if (s_err != LONGINT_OK)
731 				STRTOL_FATAL_ERROR (optarg, _("bytes_per_error"), s_err);
732 			if (bytes_per_error<100)
733 				usage(2,_("bytes-per-error should be >100"));
734 			break;
735         case 4:
736 			s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
737 			startup_delay = tmp;
738 			if (s_err != LONGINT_OK)
739 				STRTOL_FATAL_ERROR (optarg, _("startup delay"), s_err);
740 			break;
741 		case 5:
742 #if defined(F_GETFD) && defined(F_SETFD) && defined(O_SYNC)
743 			o_sync=1;
744 #else
745 			//error(0,0, _("O_SYNC not supported by the kernel"));
746 #endif
747 			break;
748 		case 6:
749 			tcp_flag=2;
750 			break;
751 		case 7:
752 			tcp_flag=3;
753 			tcp_server_address=(char *)strdup(optarg);
754 			if (!tcp_server_address)
755 				;//error(1,0,_("out of memory"));
756 			break;
757 		default:
758 			usage(2,NULL);
759 		}
760 
761 	}
762 #endif
763 
764 #if 0
765 	if (getuid()!=geteuid()) {
766 		error(1,0,
767 		_("this program was never intended to be used setuid\n"));
768 	}
769 #endif
770 	/* initialize zsendline tab */
771 	zsendline_init();
772 #ifdef HAVE_SIGINTERRUPT
773 	siginterrupt(SIGALRM,1);
774 #endif
775 	//if (startup_delay)
776 	//	sleep(startup_delay);
777 
778 	//npats = argc - optind;
779 	//patts=&argv[optind];
780 
781 #if 0
782 	if (npats > 1)
783 		usage(2,_("garbage on commandline"));
784 	if (protocol!=ZM_XMODEM && npats)
785 		usage(2, _("garbage on commandline"));
786 	if (Restricted && allow_remote_commands) {
787 		allow_remote_commands=FALSE;
788 	}
789 #endif
790 	allow_remote_commands=FALSE;
791 	if (Fromcu && !Quiet) {
792 		if (Verbose == 0)
793 			Verbose = 2;
794 	}
795 
796 	vfile("%s %s\n", program_name, VERSION);
797 
798 #if 0
799 	if (tcp_flag==2) {
800 		char buf[256];
801 #ifdef MAXHOSTNAMELEN
802 		char hn[MAXHOSTNAMELEN];
803 #else
804 		char hn[256];
805 #endif
806 		char *p,*q;
807 		int d;
808 
809 		/* tell receiver to receive via tcp */
810 		d=tcp_server(buf);
811 		p=strchr(buf+1,'<');
812 		p++;
813 		q=strchr(p,'>');
814 		*q=0;
815 		if (gethostname(hn,sizeof(hn))==-1) {
816 			error(1,0, _("hostname too long\n"));
817 		}
818 		fprintf(stdout,"connect with lrz --tcp-client \"%s:%s\"\n",hn,p);
819 		fflush(stdout);
820 		/* ok, now that this file is sent we can switch to tcp */
821 
822 		tcp_socket=tcp_accept(d);
823 		dup2(tcp_socket,0);
824 		dup2(tcp_socket,1);
825 	}
826 	if (tcp_flag==3) {
827 		char buf[256];
828 		char *p;
829 		p=strchr(tcp_server_address,':');
830 		if (!p)
831 			error(1,0, _("illegal server address\n"));
832 		*p++=0;
833 		sprintf(buf,"[%s] <%s>\n",tcp_server_address,p);
834 
835 		fprintf(stdout,"connecting to %s\n",buf);
836 		fflush(stdout);
837 
838 		/* we need to switch to tcp mode */
839 		tcp_socket=tcp_connect(buf);
840 		dup2(tcp_socket,0);
841 		dup2(tcp_socket,1);
842 	}
843 #endif
844 
845 	io_mode(0,1);
846 	readline_setup(0, HOWMANY, MAX_BLOCK*2);
847 	//if (signal(SIGINT, bibi) == SIG_IGN)
848 	//	signal(SIGINT, SIG_IGN);
849 	//else
850 	//	signal(SIGINT, bibi);
851 	//signal(SIGTERM, bibi);
852 	//signal(SIGPIPE, bibi);
853 	xil_printf("Starto wait rx data\n\r");
854 
855 	if (wcreceive(0, NULL)==ERROR) {
856 		exitcode=0200;
857 		canit(0);
858 	}
859 	xil_printf("Receive done\n\r");
860 	io_mode(0,0);
861 	if (exitcode && !zmodem_requested)	/* bellow again with all thy might. */
862 		canit(0);
863 	if (Verbose)
864 	{
865 		fputs(stderr, "\r\n");
866 		if (exitcode)
867 			fputs(stderr, "Transfer incomplete\n");
868 		else
869 			fputs(stderr, "Transfer complete\n");
870 	}
871 	*rxsize = zmodem_offset;
872 	return exitcode;
873 }
874 
875 void
usage1(int exitcode)876 usage1(int exitcode)
877 {
878 	usage(exitcode,NULL);
879 }
880 
881 static void
usage(int exitcode,const char * what)882 usage(int exitcode, const char *what)
883 {
884 	printf("TBD\n");
885 	return;
886 }
887 
888 /*
889  * Let's receive something already.
890  */
891 
892 static int
wcreceive(int argc,char ** argp)893 wcreceive(int argc, char **argp)
894 {
895 	int c;
896 	struct zm_fileinfo zi;
897 #ifdef ENABLE_SYSLOG
898 	const char *shortname=NULL;;
899 #endif
900 	zi.fname=NULL;
901 	zi.modtime=0;
902 	zi.mode=0;
903 	zi.bytes_total=0;
904 	zi.bytes_sent=0;
905 	zi.bytes_received=0;
906 	zi.bytes_skipped=0;
907 	zi.eof_seen=0;
908 
909 	if (protocol!=ZM_XMODEM || argc==0) {
910 		Crcflg=1;
911 		if ( !Quiet)
912 			vstringf(_("%s waiting to receive."), program_name);
913 		if ((c=tryz())!=0) {
914 			//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
915 			if (c == ZCOMPL) {
916 				//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
917 				return OK;
918 			}
919 			if (c == ERROR) {
920 				xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
921 				goto fubar;
922 			}
923 			c = rzfiles(&zi);
924 
925 #ifdef ENABLE_SYSLOG
926 			shortname=NULL;
927 #endif
928 			if (c) {
929 				//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
930 				goto fubar;
931 			}
932 		} else {
933 			for (;;) {
934 				if (Verbose > 1
935 #ifdef ENABLE_SYSLOG
936 					|| enable_syslog
937 #endif
938 				)
939 					timing(1,NULL);
940 #ifdef ENABLE_SYSLOG
941 				shortname=NULL;
942 #endif
943 				if (wcrxpn(&zi,secbuf)== ERROR) {
944 					xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
945 					goto fubar;
946 				}
947 				if (secbuf[0]==0) {
948 					//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
949 					return OK;
950 				}
951 				if (procheader(secbuf, &zi) == ERROR) {
952 					xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
953 					goto fubar;
954 				}
955 #ifdef ENABLE_SYSLOG
956 				shortname=strrchr(zi.fname,'/');
957 				if (shortname)
958 					shortname++;
959 				else
960 					shortname=zi.fname;
961 #endif
962 				if (wcrx(&zi)==ERROR) {
963 					xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
964 					goto fubar;
965 				}
966 
967 				if (Verbose > 1
968 #ifdef ENABLE_SYSLOG
969 					|| enable_syslog
970 #endif
971 				) {
972 					ulong d;
973 					long bps;
974 					d=timing(0,NULL);
975 					if (d==0)
976 						d=0.5; /* can happen if timing uses time() */
977 					bps=(zi.bytes_received-zi.bytes_skipped)/d;
978 
979 					if (Verbose>1) {
980 						vstringf(
981 							_("\rBytes received: %7ld/%7ld   BPS:%-6ld                \r\n"),
982 							(long) zi.bytes_received, (long) zi.bytes_total, bps);
983 					}
984 #ifdef ENABLE_SYSLOG
985 					if (enable_syslog)
986 						lsyslog(LOG_INFO,"%s/%s: %ld Bytes, %ld BPS",
987 							shortname,protname(),zi.bytes_received, bps);
988 #endif
989 				}
990 			}
991 		}
992 	} else {
993 		printf("Only support ZModem\n");
994 #if 0
995 		char dummy[128];
996 		dummy[0]='\0'; /* pre-ANSI HPUX cc demands this */
997 		dummy[1]='\0'; /* procheader uses name + 1 + strlen(name) */
998 		zi.bytes_total = DEFBYTL;
999 
1000 		if (Verbose > 1
1001 #ifdef ENABLE_SYSLOG
1002 			|| enable_syslog
1003 #endif
1004 			)
1005 			timing(1,NULL);
1006 		procheader(dummy, &zi);
1007 
1008 		if (Pathname)
1009 			free(Pathname);
1010 		errno=0;
1011 		Pathname=malloc(PATH_MAX+1);
1012 		//if (!Pathname)
1013 		//	error(1,0,_("out of memory"));
1014 
1015 		strcpy(Pathname, *argp);
1016 		checkpath(Pathname);
1017 #ifdef ENABLE_SYSLOG
1018 		shortname=strrchr(*argp,'/');
1019 		if (shortname)
1020 			shortname++;
1021 		else
1022 			shortname=*argp;
1023 #endif
1024 		vchar('\n');
1025 		vstringf(_("%s: ready to receive %s"), program_name, Pathname);
1026 		vstring("\r\n");
1027 
1028 		//if ((fout=fopen(Pathname, "w")) == NULL) {
1029 		if (0) {
1030 #ifdef ENABLE_SYSLOG
1031 			if (enable_syslog)
1032 				lsyslog(LOG_ERR,"%s/%s: cannot open: %m",
1033 					shortname,protname());
1034 #endif
1035 			return ERROR;
1036 		}
1037 		if (wcrx(&zi)==ERROR) {
1038 			goto fubar;
1039 		}
1040 		if (Verbose > 1
1041 #ifdef ENABLE_SYSLOG
1042 			|| enable_syslog
1043 #endif
1044 	 		) {
1045 			ulong d;
1046 			long bps;
1047 			d=timing(0,NULL);
1048 			if (d==0)
1049 				d=0.5; /* can happen if timing uses time() */
1050 			bps=(zi.bytes_received-zi.bytes_skipped)/d;
1051 			if (Verbose) {
1052 				vstringf(
1053 					_("\rBytes received: %7ld   BPS:%-6ld                \r\n"),
1054 					(long) zi.bytes_received, bps);
1055 			}
1056 #ifdef ENABLE_SYSLOG
1057 			if (enable_syslog)
1058 				lsyslog(LOG_INFO,"%s/%s: %ld Bytes, %ld BPS",
1059 					shortname,protname(),zi.bytes_received, bps);
1060 #endif
1061 		}
1062 #endif
1063 	}
1064 	return OK;
1065 fubar:
1066 #ifdef ENABLE_SYSLOG
1067 	if (enable_syslog)
1068 		lsyslog(LOG_ERR,"%s/%s: got error",
1069 			shortname ? shortname : "no.name", protname());
1070 #endif
1071 	canit(0);
1072 #if 0
1073 	if (Topipe && fout) {
1074 		pclose(fout);  return ERROR;
1075 	}
1076 	if (fout)
1077 		fclose(fout);
1078 #endif
1079 
1080 	if (Restricted && Pathname) {
1081 		//unlink(Pathname);
1082 		vstringf(_("\r\n%s: %s removed.\r\n"), program_name, Pathname);
1083 	}
1084 	return ERROR;
1085 }
1086 
1087 
1088 /*
1089  * Fetch a pathname from the other end as a C ctyle ASCIZ string.
1090  * Length is indeterminate as long as less than Blklen
1091  * A null string represents no more files (YMODEM)
1092  */
1093 static int
wcrxpn(struct zm_fileinfo * zi,char * rpn)1094 wcrxpn(struct zm_fileinfo *zi, char *rpn)
1095 {
1096 	register int c;
1097 	size_t Blklen=0;		/* record length of received packets */
1098 
1099 #ifdef NFGVMIN
1100 	READLINE_PF(1);
1101 #else
1102 	purgeline(0);
1103 #endif
1104 
1105 et_tu:
1106 	Firstsec=TRUE;
1107 	zi->eof_seen=FALSE;
1108 	sendline(Crcflg?WANTCRC:NAK);
1109 	flushmo();
1110 	purgeline(0); /* Do read next time ... */
1111 	while ((c = wcgetsec(&Blklen, rpn, 100)) != 0) {
1112 		if (c == WCEOT) {
1113 			xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
1114 			zperr( _("Pathname fetch returned EOT"));
1115 			sendline(ACK);
1116 			flushmo();
1117 			purgeline(0);	/* Do read next time ... */
1118 			READLINE_PF(1);
1119 			goto et_tu;
1120 		}
1121 		return ERROR;
1122 	}
1123 	sendline(ACK);
1124 	flushmo();
1125 	return OK;
1126 }
1127 
1128 /*
1129  * Adapted from CMODEM13.C, written by
1130  * Jack M. Wierda and Roderick W. Hart
1131  */
1132 static int
wcrx(struct zm_fileinfo * zi)1133 wcrx(struct zm_fileinfo *zi)
1134 {
1135 	register int sectnum, sectcurr;
1136 	register char sendchar;
1137 	size_t Blklen;
1138 
1139 	Firstsec=TRUE;sectnum=0;
1140 	zi->eof_seen=FALSE;
1141 	sendchar=Crcflg?WANTCRC:NAK;
1142 
1143 	for (;;) {
1144 		sendline(sendchar);	/* send it now, we're ready! */
1145 		flushmo();
1146 		purgeline(0);	/* Do read next time ... */
1147 		sectcurr=wcgetsec(&Blklen, secbuf,
1148 			(unsigned int) ((sectnum&0177) ? 50 : 130));
1149 		report(sectcurr);
1150 		if (sectcurr==((sectnum+1) &0377)) {
1151 			sectnum++;
1152 			/* if using xmodem we don't know how long a file is */
1153 			if (zi->bytes_total && R_BYTESLEFT(zi) < Blklen)
1154 				Blklen=R_BYTESLEFT(zi);
1155 			zi->bytes_received+=Blklen;
1156 			if (putsec(zi, secbuf, Blklen)==ERROR) {
1157 				return ERROR;
1158 			}
1159 			sendchar=ACK;
1160 		}
1161 		else if (sectcurr==(sectnum&0377)) {
1162 			zperr( _("Received dup Sector"));
1163 			sendchar=ACK;
1164 		}
1165 		else if (sectcurr==WCEOT) {
1166 			if (closeit(zi)) {
1167 				return ERROR;
1168 			}
1169 			sendline(ACK);
1170 			flushmo();
1171 			purgeline(0);	/* Do read next time ... */
1172 			return OK;
1173 		}
1174 		else if (sectcurr==ERROR) {
1175 			return ERROR;
1176 		}
1177 		else {
1178 			zperr( _("Sync Error"));
1179 			return ERROR;
1180 		}
1181 	}
1182 }
1183 
1184 /*
1185  * Wcgetsec fetches a Ward Christensen type sector.
1186  * Returns sector number encountered or ERROR if valid sector not received,
1187  * or CAN CAN received
1188  * or WCEOT if eot sector
1189  * time is timeout for first char, set to 4 seconds thereafter
1190  ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
1191  *    (Caller must do that when he is good and ready to get next sector)
1192  */
1193 static int
wcgetsec(size_t * Blklen,char * rxbuf,unsigned int maxtime)1194 wcgetsec(size_t *Blklen, char *rxbuf, unsigned int maxtime)
1195 {
1196 	register int checksum, wcj, firstch;
1197 	register unsigned short oldcrc;
1198 	register char *p;
1199 	int sectcurr;
1200 
1201 	for (Lastrx=errors=0; errors<RETRYMAX; errors++) {
1202 
1203 		if ((firstch=READLINE_PF(maxtime))==STX) {
1204 			*Blklen=1024; goto get2;
1205 		}
1206 		if (firstch==SOH) {
1207 			*Blklen=128;
1208 get2:
1209 			sectcurr=READLINE_PF(1);
1210 			if ((sectcurr+(oldcrc=READLINE_PF(1)))==0377) {
1211 				oldcrc=checksum=0;
1212 				for (p=rxbuf,wcj=*Blklen; --wcj>=0; ) {
1213 					if ((firstch=READLINE_PF(1)) < 0)
1214 						goto bilge;
1215 					oldcrc=updcrc(firstch, oldcrc);
1216 					checksum += (*p++ = firstch);
1217 				}
1218 				if ((firstch=READLINE_PF(1)) < 0)
1219 					goto bilge;
1220 				if (Crcflg) {
1221 					oldcrc=updcrc(firstch, oldcrc);
1222 					if ((firstch=READLINE_PF(1)) < 0)
1223 						goto bilge;
1224 					oldcrc=updcrc(firstch, oldcrc);
1225 					if (oldcrc & 0xFFFF)
1226 						zperr( _("CRC"));
1227 					else {
1228 						Firstsec=FALSE;
1229 						return sectcurr;
1230 					}
1231 				}
1232 				else if (((checksum-firstch)&0377)==0) {
1233 					Firstsec=FALSE;
1234 					return sectcurr;
1235 				}
1236 				else
1237 					zperr( _("Checksum"));
1238 			}
1239 			else
1240 				zperr(_("Sector number garbled"));
1241 		}
1242 		/* make sure eot really is eot and not just mixmash */
1243 #if 1
1244 		else if (firstch==EOT && READLINE_PF(1)==TIMEOUT)
1245 			return WCEOT;
1246 #else
1247 		else if (firstch==EOT && READLINE_PF>0)
1248 			return WCEOT;
1249 #endif
1250 		else if (firstch==CAN) {
1251 			if (Lastrx==CAN) {
1252 				zperr( _("Sender Cancelled"));
1253 				return ERROR;
1254 			} else {
1255 				Lastrx=CAN;
1256 				continue;
1257 			}
1258 		}
1259 		else if (firstch==TIMEOUT) {
1260 			if (Firstsec)
1261 				goto humbug;
1262 bilge:
1263 			zperr( _("TIMEOUT"));
1264 		}
1265 		else
1266 			zperr( _("Got 0%o sector header"), firstch);
1267 
1268 humbug:
1269 		Lastrx=0;
1270 		{
1271 			int cnt=1000;
1272 			while(cnt-- && READLINE_PF(1)!=TIMEOUT)
1273 				;
1274 		}
1275 		if (Firstsec) {
1276 			sendline(Crcflg?WANTCRC:NAK);
1277 			flushmo();
1278 			purgeline(0);	/* Do read next time ... */
1279 		} else {
1280 			maxtime=40;
1281 			sendline(NAK);
1282 			flushmo();
1283 			purgeline(0);	/* Do read next time ... */
1284 		}
1285 	}
1286 	/* try to stop the bubble machine. */
1287 	canit(0);
1288 	return ERROR;
1289 }
1290 
1291 #define ZCRC_DIFFERS (ERROR+1)
1292 #define ZCRC_EQUAL (ERROR+2)
1293 /*
1294  * do ZCRC-Check for open file f.
1295  * check at most check_bytes bytes (crash recovery). if 0 -> whole file.
1296  * remote file size is remote_bytes.
1297  */
zmodem_buf_getc(int c)1298 int zmodem_buf_getc(int c)
1299 {
1300 	return *(unsigned char *)(zmodem_addr+c);
1301 }
1302 static int
do_crc_check(void * f,size_t remote_bytes,size_t check_bytes)1303 do_crc_check(void *f, size_t remote_bytes, size_t check_bytes)
1304 {
1305 	//struct stat st;
1306 	unsigned long crc;
1307 	unsigned long rcrc;
1308 	size_t n;
1309 	int c;
1310 	int t1=0,t2=0;
1311 	int i;
1312 #if 0
1313 	if (-1==fstat(fileno(f),&st)) {
1314 		DO_SYSLOG((LOG_ERR,"cannot fstat open file: %s",strerror(errno)));
1315 		return ERROR;
1316 	}
1317 #endif
1318 	//if (check_bytes==0 && ((size_t) st.st_size)!=remote_bytes)
1319 	//	return ZCRC_DIFFERS; /* shortcut */
1320 
1321 	crc=0xFFFFFFFFL;
1322 	n=check_bytes;
1323 	if (n==0)
1324 		n=zmodem_offset;
1325 	//while (n-- && ((c = getc(f)) != EOF))
1326 	for(i=0;i<zmodem_offset;i++) {
1327 		c = zmodem_buf_getc(i);
1328 		crc = UPDC32(c, crc);
1329 	}
1330 	crc = ~crc;
1331 	//clearerr(f);  /* Clear EOF */
1332 	//fseek(f, 0L, 0);
1333 
1334 	while (t1<3) {
1335 		stohdr(check_bytes);
1336 		zshhdr(ZCRC, Txhdr);
1337 		while(t2<3) {
1338 			size_t tmp;
1339 			c = zgethdr(Rxhdr, 0, &tmp);
1340 			rcrc=(unsigned long) tmp;
1341 			switch (c) {
1342 			default: /* ignore */
1343 				break;
1344 			case ZFIN:
1345 				return ERROR;
1346 			case ZRINIT:
1347 				return ERROR;
1348 			case ZCAN:
1349 				if (Verbose)
1350 					vstringf(_("got ZCAN"));
1351 				return ERROR;
1352 				break;
1353 			case ZCRC:
1354 				if (crc!=rcrc)
1355 					return ZCRC_DIFFERS;
1356 				return ZCRC_EQUAL;
1357 				break;
1358 			}
1359 		}
1360 	}
1361 	return ERROR;
1362 }
1363 
1364 /*
1365  * Process incoming file information header
1366  */
1367 static int
procheader(char * name,struct zm_fileinfo * zi)1368 procheader(char *name, struct zm_fileinfo *zi)
1369 {
1370 	__maybe_unused const char *openmode;
1371 	char *p;
1372 	static char *name_static=NULL;
1373 	char *nameend;
1374 
1375 	if (name_static)
1376 		free(name_static);
1377 	if (junk_path) {
1378 		p=strrchr(name,'/');
1379 		if (p) {
1380 			p++;
1381 			if (!*p) {
1382 				/* alert - file name ended in with a / */
1383 				if (Verbose)
1384 					vstringf(_("file name ends with a /, skipped: %s\n"),name);
1385 				DO_SYSLOG((LOG_ERR,"file name ends with a /, skipped: %s", name));
1386 				return ERROR;
1387 			}
1388 			name=p;
1389 		}
1390 	}
1391 	name_static=malloc(strlen(name)+1);
1392 	//if (!name_static)
1393 	//	error(1,0,_("out of memory"));
1394 	strcpy(name_static,name);
1395 	zi->fname=name_static;
1396 
1397 	if (Verbose>2) {
1398 		vstringf(_("zmanag=%d, Lzmanag=%d\n"),zmanag,Lzmanag);
1399 		vstringf(_("zconv=%d\n"),zconv);
1400 	}
1401 
1402 	/* set default parameters and overrides */
1403 	openmode = "w";
1404 	Thisbinary = (!Rxascii) || Rxbinary;
1405 	if (Lzmanag)
1406 		zmanag = Lzmanag;
1407 
1408 	/*
1409 	 *  Process ZMODEM remote file management requests
1410 	 */
1411 	if (!Rxbinary && zconv == ZCNL)	/* Remote ASCII override */
1412 		Thisbinary = 0;
1413 	if (zconv == ZCBIN)	/* Remote Binary override */
1414 		Thisbinary = TRUE;
1415 	if (Thisbinary && zconv == ZCBIN && try_resume)
1416 		zconv=ZCRESUM;
1417 	if (zmanag == ZF1_ZMAPND && zconv!=ZCRESUM)
1418 		openmode = "a";
1419 	if (skip_if_not_found)
1420 		openmode="r+";
1421 
1422 #ifdef ENABLE_TIMESYNC
1423 	in_timesync=0;
1424 	if (timesync_flag && 0==strcmp(name,"$time$.t"))
1425 		in_timesync=1;
1426 #endif
1427 	in_tcpsync=0;
1428 	if (tcpsync_flag && 0==strcmp(name,"$tcp$.t"))
1429 		in_tcpsync=1;
1430 
1431 	zi->bytes_total = DEFBYTL;
1432 	zi->mode = 0;
1433 	zi->eof_seen = 0;
1434 	zi->modtime = 0;
1435 
1436 	nameend = name + 1 + strlen(name);
1437 #if 0
1438 	if (*nameend) {	/* file coming from Unix or DOS system */
1439 		long modtime;
1440 		long bytes_total;
1441 		int mode;
1442 		sscanf(nameend, "%ld%lo%o", &bytes_total, &modtime, &mode);
1443 		zi->modtime=modtime;
1444 		zi->bytes_total=bytes_total;
1445 		zi->mode=mode;
1446 		if (zi->mode & UNIXFILE)
1447 			++Thisbinary;
1448 	}
1449 #endif
1450 
1451 	/* Check for existing file */
1452 	if (zconv != ZCRESUM && !Rxclob && (zmanag&ZF1_ZMMASK) != ZF1_ZMCLOB
1453 		&& (zmanag&ZF1_ZMMASK) != ZF1_ZMAPND
1454 #ifdef ENABLE_TIMESYNC
1455 	    && !in_timesync
1456 	    && !in_tcpsync
1457 #endif
1458 		//&& (fout=fopen(name, "r"))) {
1459 		){
1460 		//struct stat sta;
1461 		char *tmpname;
1462 		char *ptr;
1463 		int i  __maybe_unused;
1464 		if (zmanag == ZF1_ZMNEW || zmanag==ZF1_ZMNEWL) {
1465 #if 0
1466 			if (-1==fstat(fileno(fout),&sta)) {
1467 #ifdef ENABLE_SYSLOG
1468 				int e=errno;
1469 #endif
1470 				if (Verbose)
1471 					vstringf(_("file exists, skipped: %s\n"),name);
1472 				DO_SYSLOG((LOG_ERR,"cannot fstat open file %s: %s",
1473 					name,strerror(e)));
1474 				return ERROR;
1475 			}
1476 #endif
1477 			if (zmanag == ZF1_ZMNEW) {
1478 #if 0
1479 				if (sta.st_mtime > zi->modtime) {
1480 					DO_SYSLOG((LOG_INFO,"skipping %s: newer file exists", name));
1481 					return ERROR; /* skips file */
1482 				}
1483 #endif
1484 			} else {
1485 				/* newer-or-longer */
1486 #if 0
1487 				if (((size_t) sta.st_size) >= zi->bytes_total
1488 					&& sta.st_mtime > zi->modtime) {
1489 					DO_SYSLOG((LOG_INFO,"skipping %s: longer+newer file exists", name));
1490 					return ERROR; /* skips file */
1491 				}
1492 #endif
1493 			}
1494 			//fclose(fout);
1495 		} else if (zmanag==ZF1_ZMCRC) {
1496 			int r=do_crc_check(NULL,zi->bytes_total,0);
1497 			if (r==ERROR) {
1498 				//fclose(fout);
1499 				return ERROR;
1500 			}
1501 			if (r!=ZCRC_DIFFERS) {
1502 				return ERROR; /* skips */
1503 			}
1504 			//fclose(fout);
1505 		} else {
1506 			size_t namelen;
1507 			//fclose(fout);
1508 			if ((zmanag & ZF1_ZMMASK)!=ZF1_ZMCHNG) {
1509 				if (Verbose)
1510 					vstringf(_("file exists, skipped: %s\n"),name);
1511 				return ERROR;
1512 			}
1513 			/* try to rename */
1514 			namelen=strlen(name);
1515 			tmpname=alloca(namelen+5);
1516 			memcpy(tmpname,name,namelen);
1517 			ptr=tmpname+namelen;
1518 			*ptr++='.';
1519 			i=0;
1520 			printf("Not going to happend\n");
1521 #if 0
1522 			do {
1523 				sprintf(ptr,"%d",i++);
1524 			} while (i<1000 && stat(tmpname,&sta)==0);
1525 			if (i==1000)
1526 				return ERROR;
1527 			free(name_static);
1528 			name_static=malloc(strlen(tmpname)+1);
1529 			//if (!name_static)
1530 			//	error(1,0,_("out of memory"));
1531 			strcpy(name_static,tmpname);
1532 			zi->fname=name_static;
1533 #endif
1534 		}
1535 	}
1536 
1537 	if (!*nameend) {		/* File coming from CP/M system */
1538 		for (p=name_static; *p; ++p)		/* change / to _ */
1539 			if ( *p == '/')
1540 				*p = '_';
1541 
1542 		if ( *--p == '.')		/* zap trailing period */
1543 			*p = 0;
1544 	}
1545 
1546 #ifdef ENABLE_TIMESYNC
1547 	if (in_timesync)
1548 	{
1549 		long t=time(0);
1550 		long d=t-zi->modtime;
1551 		if (d<0)
1552 			d=0;
1553 		if ((Verbose && d>60) || Verbose > 1)
1554 			vstringf(_("TIMESYNC: here %ld, remote %ld, diff %ld seconds\n"),
1555 			(long) t, (long) zi->modtime, d);
1556 #ifdef HAVE_SETTIMEOFDAY
1557 		if (timesync_flag > 1 && d > 10)
1558 		{
1559 			struct timeval tv;
1560 			tv.tv_sec=zi->modtime;
1561 			tv.tv_usec=0;
1562 			//if (settimeofday(&tv,NULL))
1563 			//	vstringf(_("TIMESYNC: cannot set time: %s\n"),
1564 			//		strerror(errno));
1565 		}
1566 #endif
1567 		return ERROR; /* skips file */
1568 	}
1569 #endif /* ENABLE_TIMESYNC */
1570 #if 0
1571 	if (in_tcpsync) {
1572 		fout=tmpfile();
1573 		if (!fout) {
1574 			error(1,errno,_("cannot tmpfile() for tcp protocol synchronization"));
1575 		}
1576 		zi->bytes_received=0;
1577 		return OK;
1578 	}
1579 #endif
1580 
1581 
1582 	if (!zmodem_requested && MakeLCPathname && !IsAnyLower(name_static)
1583 	  && !(zi->mode&UNIXFILE))
1584 		uncaps(name_static);
1585 	if (Topipe > 0) {
1586 #if 0
1587 		if (Pathname)
1588 			free(Pathname);
1589 		Pathname=malloc((PATH_MAX)*2);
1590 		if (!Pathname)
1591 			error(1,0,_("out of memory"));
1592 		sprintf(Pathname, "%s %s", program_name+2, name_static);
1593 		if (Verbose) {
1594 			vstringf("%s: %s %s\n",
1595 				_("Topipe"),
1596 				Pathname, Thisbinary?"BIN":"ASCII");
1597 		}
1598 
1599 		if ((fout=popen(Pathname, "w")) == NULL)
1600 			return ERROR;
1601 #endif
1602 	} else {
1603 		if (protocol==ZM_XMODEM)
1604 			/* we don't have the filename yet */
1605 			return OK; /* dummy */
1606 		if (Pathname)
1607 			free(Pathname);
1608 		Pathname=malloc((PATH_MAX)*2);
1609 		//if (!Pathname)
1610 		//	error(1,0,_("out of memory"));
1611 		strcpy(Pathname, name_static);
1612 		if (Verbose) {
1613 			/* overwrite the "waiting to receive" line */
1614 			vstring("\r                                                                     \r");
1615 			vstringf(_("Receiving: %s\n"), name_static);
1616 		}
1617 		checkpath(name_static);
1618 		if (Nflag)
1619 		{
1620 			/* cast because we might not have a prototyp for strdup :-/ */
1621 			free(name_static);
1622 			name_static=(char *) strdup("/dev/null");
1623 			if (!name_static)
1624 			{
1625 				fprintf(stderr,"%s: %s\n", program_name, _("out of memory"));
1626 				return -1;
1627 			}
1628 		}
1629 #ifdef OMEN
1630 #if 0
1631 asdfadsf
1632 		/* looks like a security hole -- uwe */
1633 		if (name_static[0] == '!' || name_static[0] == '|') {
1634 			if ( !(fout = popen(name_static+1, "w"))) {
1635 				return ERROR;
1636 			}
1637 			Topipe = -1;  return(OK);
1638 		}
1639 #endif
1640 #endif
1641 		if (Thisbinary && zconv==ZCRESUM) {
1642 			//struct stat st;
1643 			//fout = fopen(name_static, "r+");
1644 			//if (fout && 0==fstat(fileno(fout),&st))
1645 			if(1)
1646 			{
1647 				printf("This should not happened\n");
1648 				int can_resume=FALSE;
1649 				if (zmanag==ZF1_ZMCRC) {
1650 					int r=do_crc_check(NULL,zi->bytes_total,0);
1651 					if (r==ERROR) {
1652 						//fclose(fout);
1653 						return ZFERR;
1654 					}
1655 					if (r==ZCRC_DIFFERS) {
1656 						can_resume=FALSE;
1657 					}
1658 				}
1659 				//if ((unsigned long)st.st_size > zi->bytes_total) {
1660 				{
1661 					can_resume=FALSE;
1662 				}
1663 				/* retransfer whole blocks */
1664 				zi->bytes_skipped = 0 & ~(1023);
1665 				if (can_resume) {
1666 #if 0
1667 					if (fseek(fout, (long) zi->bytes_skipped, SEEK_SET)) {
1668 						fclose(fout);
1669 						return ZFERR;
1670 					}
1671 #endif
1672 				}
1673 				else
1674 					zi->bytes_skipped=0; /* resume impossible, file has changed */
1675 				goto buffer_it;
1676 			}
1677 			zi->bytes_skipped=0;
1678 #if  0
1679 			if (fout)
1680 				fclose(fout);
1681 #endif
1682 		}
1683 #if 0
1684 		fout = fopen(name_static, openmode);
1685 #ifdef ENABLE_MKDIR
1686 		if ( !fout && Restricted < 2) {
1687 			if (make_dirs(name_static))
1688 				fout = fopen(name_static, openmode);
1689 		}
1690 #endif
1691 		if ( !fout)
1692 		{
1693 #ifdef ENABLE_SYSLOG
1694 			int e=errno;
1695 #endif
1696 			zpfatal(_("cannot open %s"), name_static);
1697 			DO_SYSLOG((LOG_ERR,"%s: cannot open: %s",
1698 				protname(),strerror(e)));
1699 			return ERROR;
1700 		}
1701 #endif
1702 	}
1703 buffer_it:
1704 	if (Topipe == 0) {
1705 		static char *s=NULL;
1706 		static size_t last_length=0;
1707 #if defined(F_GETFD) && defined(F_SETFD) && defined(O_SYNC)
1708 #if 0
1709 		if (o_sync) {
1710 			int oldflags;
1711 			oldflags = fcntl (fileno(fout), F_GETFD, 0);
1712 			if (oldflags>=0 && !(oldflags & O_SYNC)) {
1713 				oldflags|=O_SYNC;
1714 				fcntl (fileno(fout), F_SETFD, oldflags); /* errors don't matter */
1715 			}
1716 		}
1717 #endif
1718 #endif
1719 
1720 		if (buffersize==-1 && s) {
1721 			if (zi->bytes_total>last_length) {
1722 				free(s);
1723 				s=NULL;
1724 				last_length=0;
1725 			}
1726 		}
1727 		if (!s && buffersize) {
1728 			last_length=32768;
1729 			if (buffersize==-1) {
1730 				if (zi->bytes_total>0)
1731 					last_length=zi->bytes_total;
1732 			} else
1733 				last_length=buffersize;
1734 			/* buffer `4096' bytes pages */
1735 			last_length=(last_length+4095)&0xfffff000;
1736 			s=malloc(last_length);
1737 			if (!s) {
1738 				zpfatal(_("out of memory"));
1739 				return 1;
1740 			}
1741 		}
1742 		if (s) {
1743 #if 0
1744 #ifdef SETVBUF_REVERSED
1745 			setvbuf(fout,_IOFBF,s,last_length);
1746 #else
1747 			setvbuf(fout,s,_IOFBF,last_length);
1748 #endif
1749 #endif
1750 		}
1751 	}
1752 	zi->bytes_received=zi->bytes_skipped;
1753 
1754 	return OK;
1755 }
1756 
1757 #ifdef ENABLE_MKDIR
1758 /*
1759  *  Directory-creating routines from Public Domain TAR by John Gilmore
1760  */
1761 
1762 /*
1763  * After a file/link/symlink/dir creation has failed, see if
1764  * it's because some required directory was not present, and if
1765  * so, create all required dirs.
1766  */
1767 int
make_dirs(char * pathname)1768 make_dirs(char *pathname)
1769 {
1770 	register char *p;		/* Points into path */
1771 	int madeone = 0;		/* Did we do anything yet? */
1772 	int save_errno = errno;		/* Remember caller's errno */
1773 
1774 	if (errno != ENOENT)
1775 		return 0;		/* Not our problem */
1776 
1777 	for (p = strchr(pathname, '/'); p != NULL; p = strchr(p+1, '/')) {
1778 		/* Avoid mkdir of empty string, if leading or ulong '/' */
1779 		if (p == pathname || p[-1] == '/')
1780 			continue;
1781 		/* Avoid mkdir where last part of path is '.' */
1782 		if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
1783 			continue;
1784 		*p = 0;				/* Truncate the path there */
1785 		if ( !mkdir(pathname, 0777)) {	/* Try to create it as a dir */
1786 			vfile("Made directory %s\n", pathname);
1787 			madeone++;		/* Remember if we made one */
1788 			*p = '/';
1789 			continue;
1790 		}
1791 		*p = '/';
1792 		if (errno == EEXIST)		/* Directory already exists */
1793 			continue;
1794 		/*
1795 		 * Some other error in the mkdir.  We return to the caller.
1796 		 */
1797 		break;
1798 	}
1799 	errno = save_errno;		/* Restore caller's errno */
1800 	return madeone;			/* Tell them to retry if we made one */
1801 }
1802 
1803 #endif /* ENABLE_MKDIR */
1804 
1805 /*
1806  * Putsec writes the n characters of buf to receive file fout.
1807  *  If not in binary mode, carriage returns, and all characters
1808  *  starting with CPMEOF are discarded.
1809  */
putsec(struct zm_fileinfo * zi,char * buf,size_t n)1810 static int putsec(struct zm_fileinfo *zi, char *buf, size_t n)
1811 {
1812 	memcpy(zmodem_addr + zmodem_offset, buf, n);
1813 	zmodem_offset += n;
1814 	return 0;
1815 }
1816 #if 0
1817 static int
1818 putsec(struct zm_fileinfo *zi, char *buf, size_t n)
1819 {
1820 	register char *p;
1821 
1822 	if (n == 0)
1823 		return OK;
1824 	if (Thisbinary) {
1825 		if (fwrite(buf,n,1,fout)!=1)
1826 			return ERROR;
1827 	}
1828 	else {
1829 		if (zi->eof_seen)
1830 			return OK;
1831 		for (p=buf; n>0; ++p,n-- ) {
1832 			if ( *p == '\r')
1833 				continue;
1834 			if (*p == CPMEOF) {
1835 				zi->eof_seen=TRUE;
1836 				return OK;
1837 			}
1838 			putc(*p ,fout);
1839 		}
1840 	}
1841 	return OK;
1842 }
1843 #endif
1844 
islower(int c)1845 int islower(int c)
1846 {
1847 	if((c >='a') && (c<='z'))
1848 		return 1;
1849 	return 0;
1850 }
isupper(int c)1851 int isupper(int c)
1852 {
1853 	if((c >='A') && (c<='Z'))
1854 		return 1;
1855 	return 0;
1856 }
tolower(int c)1857 int tolower(int c)
1858 {
1859 	if((c >='A') && (c<='Z'))
1860 		return c+32;
1861 	return c;
1862 }
1863 /* make string s lower case */
1864 static void
uncaps(char * s)1865 uncaps(char *s)
1866 {
1867 	for ( ; *s; ++s)
1868 		if (isupper((unsigned char)(*s)))
1869 			*s = tolower(*s);
1870 }
1871 /*
1872  * IsAnyLower returns TRUE if string s has lower case letters.
1873  */
1874 static int
IsAnyLower(const char * s)1875 IsAnyLower(const char *s)
1876 {
1877 	for ( ; *s; ++s)
1878 		if (islower((unsigned char)(*s)))
1879 			return TRUE;
1880 	return FALSE;
1881 }
1882 
1883 static void
report(int sct)1884 report(int sct)
1885 {
1886 	if (Verbose>1)
1887 	{
1888 		vstringf(_("Blocks received: %d"),sct);
1889 		//vchar('\r');
1890 	}
1891 }
1892 
1893 /*
1894  * If called as [-][dir/../]vrzCOMMAND set Verbose to 1
1895  * If called as [-][dir/../]rzCOMMAND set the pipe flag
1896  * If called as rb use YMODEM protocol
1897  */
1898 void
chkinvok(const char * s)1899 chkinvok(const char *s)
1900 {
1901 	const char *p;
1902 
1903 	p = s;
1904 	while (*p == '-')
1905 		s = ++p;
1906 	while (*p)
1907 		if (*p++ == '/')
1908 			s = p;
1909 	if (*s == 'v') {
1910 		Verbose=1; ++s;
1911 	}
1912 	program_name = s;
1913 	if (*s == 'l')
1914 		s++; /* lrz -> rz */
1915 	protocol=ZM_ZMODEM;
1916 	if (s[0]=='r' && s[1]=='x')
1917 		protocol=ZM_XMODEM;
1918 	if (s[0]=='r' && (s[1]=='b' || s[1]=='y'))
1919 		protocol=ZM_YMODEM;
1920 	//if (s[2] && protocol!=ZM_XMODEM)
1921 	//	Topipe = 1;
1922 }
1923 
1924 /*
1925  * Totalitarian Communist pathname processing
1926  */
1927 static void
checkpath(const char * name)1928 checkpath(const char *name)
1929 {
1930 	if (Restricted) {
1931 		const char *p;
1932 		p=strrchr(name,'/');
1933 		if (p)
1934 			p++;
1935 		else
1936 			p=name;
1937 		/* don't overwrite any file in very restricted mode.
1938 		 * don't overwrite hidden files in restricted mode */
1939 #if 0
1940 		if ((Restricted==2 || *name=='.') && fopen(name, "r") != NULL) {
1941 			canit(0);
1942 			vstring("\r\n");
1943 			vstringf(_("%s: %s exists\n"),
1944 				program_name, name);
1945 			bibi(-1);
1946 		}
1947 #endif
1948 		/* restrict pathnames to current tree or uucppublic */
1949 		if ( strstr(name, "../")
1950 #ifdef PUBDIR
1951 		 || (name[0]== '/' && strncmp(name, PUBDIR,
1952 		 	strlen(PUBDIR)))
1953 #endif
1954 		) {
1955 			canit(0);
1956 			vstring("\r\n");
1957 			vstringf(_("%s:\tSecurity Violation"),program_name);
1958 			vstring("\r\n");
1959 			bibi(-1);
1960 		}
1961 		if (Restricted > 1) {
1962 			if (name[0]=='.' || strstr(name,"/.")) {
1963 				canit(0);
1964 				vstring("\r\n");
1965 				vstringf(_("%s:\tSecurity Violation"),program_name);
1966 				vstring("\r\n");
1967 				bibi(-1);
1968 			}
1969 		}
1970 	}
1971 }
1972 
1973 /*
1974  * Initialize for Zmodem receive attempt, try to activate Zmodem sender
1975  *  Handles ZSINIT frame
1976  *  Return ZFILE if Zmodem filename received, -1 on error,
1977  *   ZCOMPL if transaction finished,  else 0
1978  */
1979 static int
tryz(void)1980 tryz(void)
1981 {
1982 	register int c, n;
1983 	register int cmdzack1flg;
1984 	int zrqinits_received=0;
1985 	size_t bytes_in_block=0;
1986 
1987 	if (protocol!=ZM_ZMODEM)		/* Check for "rb" program name */
1988 		return 0;
1989 
1990 	for (n=zmodem_requested?15:5;
1991 		 (--n + zrqinits_received) >=0 && zrqinits_received<10; ) {
1992 		/* Set buffer length (0) and capability flags */
1993 #ifdef SEGMENTS
1994 		stohdr(SEGMENTS*MAX_BLOCK);
1995 #else
1996 		stohdr(0L);
1997 #endif
1998 #ifdef CANBREAK
1999 		Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
2000 #else
2001 		Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
2002 #endif
2003 #ifdef ENABLE_TIMESYNC
2004 		if (timesync_flag)
2005 			Txhdr[ZF1] |= ZF1_TIMESYNC;
2006 #endif
2007 		if (Zctlesc)
2008 			Txhdr[ZF0] |= TESCCTL; /* TESCCTL == ESCCTL */
2009 		zshhdr(tryzhdrtype, Txhdr);
2010 
2011 #if 0
2012 		if (tcp_socket==-1 && *tcp_buf) {
2013 			/* we need to switch to tcp mode */
2014 			tcp_socket=tcp_connect(tcp_buf);
2015 			tcp_buf[0]=0;
2016 			dup2(tcp_socket,0);
2017 			dup2(tcp_socket,1);
2018 		}
2019 #endif
2020 		if (tryzhdrtype == ZSKIP)	/* Don't skip too far */
2021 			tryzhdrtype = ZRINIT;	/* CAF 8-21-87 */
2022 again:
2023 		switch (zgethdr(Rxhdr, 0, NULL)) {
2024 		case ZRQINIT:
2025 			/* getting one ZRQINIT is totally ok. Normally a ZFILE follows
2026 			 * (and might be in our buffer, so don't purge it). But if we
2027 			 * get more ZRQINITs than the sender has started up before us
2028 			 * and sent ZRQINITs while waiting.
2029 			 */
2030 			zrqinits_received++;
2031 			continue;
2032 
2033 		case ZEOF:
2034 			continue;
2035 		case TIMEOUT:
2036 			continue;
2037 		case ZFILE:
2038 			zconv = Rxhdr[ZF0];
2039 			if (!zconv)
2040 				/* resume with sz -r is impossible (at least with unix sz)
2041 				 * if this is not set */
2042 				zconv=ZCBIN;
2043 			if (Rxhdr[ZF1] & ZF1_ZMSKNOLOC) {
2044 				Rxhdr[ZF1] &= ~(ZF1_ZMSKNOLOC);
2045 				skip_if_not_found=TRUE;
2046 			}
2047 			zmanag = Rxhdr[ZF1];
2048 			ztrans = Rxhdr[ZF2];
2049 			tryzhdrtype = ZRINIT;
2050 			c = zrdata(secbuf, MAX_BLOCK,&bytes_in_block);
2051 			io_mode(0,3);
2052 			if (c == GOTCRCW)
2053 				return ZFILE;
2054 			zshhdr(ZNAK, Txhdr);
2055 			goto again;
2056 		case ZSINIT:
2057 			/* this once was:
2058 			 * Zctlesc = TESCCTL & Rxhdr[ZF0];
2059 			 * trouble: if rz get --escape flag:
2060 			 * - it sends TESCCTL to sz,
2061 			 *   get a ZSINIT _without_ TESCCTL (yeah - sender didn't know),
2062 			 *   overwrites Zctlesc flag ...
2063 			 * - sender receives TESCCTL and uses "|=..."
2064 			 * so: sz escapes, but rz doesn't unescape ... not good.
2065 			 */
2066 			Zctlesc |= TESCCTL & Rxhdr[ZF0];
2067 			if (zrdata(Attn, ZATTNLEN,&bytes_in_block) == GOTCRCW) {
2068 				stohdr(1L);
2069 				zshhdr(ZACK, Txhdr);
2070 				goto again;
2071 			}
2072 			zshhdr(ZNAK, Txhdr);
2073 			goto again;
2074 		case ZFREECNT:
2075 			stohdr(getfree());
2076 			zshhdr(ZACK, Txhdr);
2077 			goto again;
2078 		case ZCOMMAND:
2079 			cmdzack1flg = Rxhdr[ZF0];
2080 			if (zrdata(secbuf, MAX_BLOCK,&bytes_in_block) == GOTCRCW) {
2081 				if (Verbose)
2082 				{
2083 					vstringf("%s: %s\n", program_name,
2084 						_("remote command execution requested"));
2085 					vstringf("%s: %s\n", program_name, secbuf);
2086 				}
2087 				if (!allow_remote_commands)
2088 				{
2089 					if (Verbose)
2090 						vstringf("%s: %s\n", program_name,
2091 							_("not executed"));
2092 					zshhdr(ZCOMPL, Txhdr);
2093 					DO_SYSLOG((LOG_INFO,"rexec denied: %s",secbuf));
2094 					return ZCOMPL;
2095 				}
2096 				DO_SYSLOG((LOG_INFO,"rexec allowed: %s",secbuf));
2097 				if (cmdzack1flg & ZCACK1)
2098 					stohdr(0L);
2099 				else
2100 					stohdr((size_t)sys2(secbuf));
2101 				purgeline(0);	/* dump impatient questions */
2102 				do {
2103 					zshhdr(ZCOMPL, Txhdr);
2104 				}
2105 				while (++errors<20 && zgethdr(Rxhdr,1, NULL) != ZFIN);
2106 				ackbibi();
2107 				if (cmdzack1flg & ZCACK1)
2108 					exec2(secbuf);
2109 				return ZCOMPL;
2110 			}
2111 			zshhdr(ZNAK, Txhdr);
2112 			goto again;
2113 		case ZCOMPL:
2114 			goto again;
2115 		default:
2116 			continue;
2117 		case ZFIN:
2118 			ackbibi();
2119 			return ZCOMPL;
2120 		case ZRINIT:
2121 			if (Verbose)
2122 				vstringf(_("got ZRINIT"));
2123 			return ERROR;
2124 		case ZCAN:
2125 			if (Verbose)
2126 				vstringf(_("got ZCAN"));
2127 			return ERROR;
2128 		}
2129 	}
2130 	return 0;
2131 }
2132 
2133 
2134 /*
2135  * Receive 1 or more files with ZMODEM protocol
2136  */
2137 static int
rzfiles(struct zm_fileinfo * zi)2138 rzfiles(struct zm_fileinfo *zi)
2139 {
2140 	register int c;
2141 
2142 	//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2143 	for (;;) {
2144 		timing(1,NULL);
2145 		c = rzfile(zi);
2146 		//xil_printf("%s(): L%d debug, c=%d\n\r", __func__, __LINE__, c);
2147 		switch (c) {
2148 		case ZEOF:
2149 			xil_printf("%s(): receive %s (%d bytes)complete\n\r", __func__, zi->fname, (u32)zi->bytes_total);
2150 			if (Verbose > 1
2151 #ifdef ENABLE_SYSLOG
2152 				|| enable_syslog
2153 #endif
2154 	 		) {
2155 				ulong d;
2156 				long bps;
2157 				d=timing(0,NULL);
2158 				if (d==0)
2159 					d=0.5; /* can happen if timing uses time() */
2160 				bps=(zi->bytes_received-zi->bytes_skipped)/d;
2161 				if (Verbose > 1) {
2162 					vstringf(
2163 						_("\rBytes received: %7ld/%7ld   BPS:%-6ld                \r\n"),
2164 						(long) zi->bytes_received, (long) zi->bytes_total, bps);
2165 				}
2166 				DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: %ld Bytes, %ld BPS",shortname,
2167 						   protname(), (long) zi->bytes_total,bps));
2168 			}
2169 			/* FALL THROUGH */
2170 		case ZSKIP:
2171 			if (c==ZSKIP)
2172 			{
2173 				if (Verbose)
2174 					vstringf(_("Skipped"));
2175 				DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: skipped",shortname,protname()));
2176 			}
2177 			switch (tryz()) {
2178 			case ZCOMPL:
2179 				return OK;
2180 			default:
2181 				return ERROR;
2182 			case ZFILE:
2183 				break;
2184 			}
2185 			continue;
2186 		default:
2187 			return c;
2188 		case ERROR:
2189 			DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error",shortname,protname()));
2190 			return ERROR;
2191 		}
2192 	}
2193 }
2194 
2195 /* "OOSB" means Out Of Sync Block. I once thought that if sz sents
2196  * blocks a,b,c,d, of which a is ok, b fails, we might want to save
2197  * c and d. But, alas, i never saw c and d.
2198  */
2199 #define SAVE_OOSB
2200 #ifdef SAVE_OOSB
2201 typedef struct oosb_t {
2202 	size_t pos;
2203 	size_t len;
2204 	char *data;
2205 	struct oosb_t *next;
2206 } oosb_t;
2207 struct oosb_t *anker=NULL;
2208 #endif
2209 
2210 /*
2211  * Receive a file with ZMODEM protocol
2212  *  Assumes file name frame is in secbuf
2213  */
2214 static int
rzfile(struct zm_fileinfo * zi)2215 rzfile(struct zm_fileinfo *zi)
2216 {
2217 	register int c, n;
2218 	long last_rxbytes=0;
2219 	unsigned long last_bps=0;
2220 	long not_printed=0;
2221 	time_t low_bps=0;
2222 	size_t bytes_in_block=0;
2223 
2224 	zi->eof_seen=FALSE;
2225 
2226 	n = 20;
2227 
2228 	if (procheader(secbuf,zi) == ERROR) {
2229 		xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2230 		DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: procheader error",
2231 				   shortname,protname()));
2232 		return (tryzhdrtype = ZSKIP);
2233 	}
2234 
2235 	for (;;) {
2236 #ifdef SEGMENTS
2237 		chinseg = 0;
2238 #endif
2239 		stohdr(zi->bytes_received);
2240 		zshhdr(ZRPOS, Txhdr);
2241 		goto skip_oosb;
2242 nxthdr:
2243 #ifdef SAVE_OOSB
2244 		if (anker) {
2245 			oosb_t *akt,*last,*next;
2246 			for (akt=anker,last=NULL;akt;last= akt ? akt : last ,akt=next) {
2247 				if (akt->pos==zi->bytes_received) {
2248 					putsec(zi, akt->data, akt->len);
2249 					zi->bytes_received += akt->len;
2250 					vfile("using saved out-of-sync-paket %lx, len %ld",
2251 						  akt->pos,akt->len);
2252 					//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2253 					goto nxthdr;
2254 				}
2255 				next=akt->next;
2256 				if (akt->pos<zi->bytes_received) {
2257 					vfile("removing unneeded saved out-of-sync-paket %lx, len %ld",
2258 						  akt->pos,akt->len);
2259 					if (last)
2260 						last->next=akt->next;
2261 					else
2262 						anker=akt->next;
2263 					free(akt->data);
2264 					free(akt);
2265 					akt=NULL;
2266 				}
2267 			}
2268 		}
2269 #endif
2270 	skip_oosb:
2271 		c = zgethdr(Rxhdr, 0, NULL);
2272 		switch (c) {
2273 		default:
2274 			xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2275 			DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: zgethdr returned %d",shortname,
2276 					   protname(),c));
2277 			vfile("rzfile: zgethdr returned %d", c);
2278 			return ERROR;
2279 		case ZNAK:
2280 		case TIMEOUT:
2281 			xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2282 #ifdef SEGMENTS
2283 			putsec(secbuf, chinseg);
2284 			chinseg = 0;
2285 #endif
2286 			if ( --n < 0) {
2287 				DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: zgethdr returned %s",shortname,
2288 					   protname(),c == ZNAK ? "ZNAK" : "TIMEOUT"));
2289 				vfile("rzfile: zgethdr returned %d", c);
2290 				return ERROR;
2291 			}
2292 		case ZFILE:
2293 			//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2294 			zrdata(secbuf, MAX_BLOCK,&bytes_in_block);
2295 			continue;
2296 		case ZEOF:
2297 			//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2298 #ifdef SEGMENTS
2299 			putsec(secbuf, chinseg);
2300 			chinseg = 0;
2301 #endif
2302 			if (rclhdr(Rxhdr) != (long) zi->bytes_received) {
2303 				/*
2304 				 * Ignore eof if it's at wrong place - force
2305 				 *  a timeout because the eof might have gone
2306 				 *  out before we sent our zrpos.
2307 				 */
2308 				errors = 0;  goto nxthdr;
2309 			}
2310 			if (closeit(zi)) {
2311 				tryzhdrtype = ZFERR;
2312 				DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: closeit return <>0",
2313 						   shortname, protname()));
2314 				vfile("rzfile: closeit returned <> 0");
2315 				return ERROR;
2316 			}
2317 			vfile("rzfile: normal EOF");
2318 			return c;
2319 		case ERROR:	/* Too much garbage in header search error */
2320 			xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2321 #ifdef SEGMENTS
2322 			putsec(secbuf, chinseg);
2323 			chinseg = 0;
2324 #endif
2325 			if ( --n < 0) {
2326 				DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: zgethdr returned %d",
2327 						   shortname, protname(),c));
2328 				vfile("rzfile: zgethdr returned %d", c);
2329 				return ERROR;
2330 			}
2331 			zmputs(Attn);
2332 			continue;
2333 		case ZSKIP:
2334 			//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2335 #ifdef SEGMENTS
2336 			putsec(secbuf, chinseg);
2337 			chinseg = 0;
2338 #endif
2339 			closeit(zi);
2340 			DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: sender skipped",
2341 					   shortname, protname()));
2342 			vfile("rzfile: Sender SKIPPED file");
2343 			return c;
2344 		case ZDATA:
2345 			//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2346 			if (rclhdr(Rxhdr) != (long) zi->bytes_received) {
2347 #if defined(SAVE_OOSB)
2348 				oosb_t *neu;
2349 				size_t pos=rclhdr(Rxhdr);
2350 #endif
2351 				if ( --n < 0) {
2352 					vfile("rzfile: out of sync");
2353 					DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: out of sync",
2354 					   shortname, protname()));
2355 					return ERROR;
2356 				}
2357 #if defined(SAVE_OOSB)
2358 				switch (c = zrdata(secbuf, MAX_BLOCK,&bytes_in_block))
2359 				{
2360 				case GOTCRCW:
2361 				case GOTCRCG:
2362 				case GOTCRCE:
2363 				case GOTCRCQ:
2364 					if (pos>zi->bytes_received) {
2365 						neu=malloc(sizeof(oosb_t));
2366 						if (neu)
2367 							neu->data=malloc(bytes_in_block);
2368 						if (neu && neu->data) {
2369 #ifdef ENABLE_SYSLOG
2370 /* call syslog to tell me if this happens */
2371 							lsyslog(LOG_ERR,
2372 								   "saving out-of-sync-block %lx, len %lu",
2373 								   pos, (unsigned long) bytes_in_block);
2374 #endif
2375 							vfile("saving out-of-sync-block %lx, len %lu",pos,
2376 								  (unsigned long) bytes_in_block);
2377 							memcpy(neu->data,secbuf,bytes_in_block);
2378 							neu->pos=pos;
2379 							neu->len=bytes_in_block;
2380 							neu->next=anker;
2381 							anker=neu;
2382 						}
2383 						else if (neu)
2384 							free(neu);
2385 					}
2386 				}
2387 #endif
2388 #ifdef SEGMENTS
2389 				putsec(secbuf, chinseg);
2390 				chinseg = 0;
2391 #endif
2392 				zmputs(Attn);  continue;
2393 			}
2394 moredata:
2395 			//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2396 			if ((Verbose>1 || min_bps || stop_time)
2397 				&& (not_printed > (min_bps ? 3 : 7)
2398 					|| zi->bytes_received > last_bps / 2 + last_rxbytes)) {
2399 				int minleft =  0;
2400 				int secleft =  0;
2401 				time_t now;
2402 				ulong d;
2403 				//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2404 				d=timing(0,&now);
2405 				if (d==0)
2406 					d=0.5; /* timing() might use time() */
2407 				last_bps=zi->bytes_received/d;
2408 				if (last_bps > 0) {
2409 					minleft =  (R_BYTESLEFT(zi))/last_bps/60;
2410 					secleft =  ((R_BYTESLEFT(zi))/last_bps)%60;
2411 				}
2412 				if (min_bps) {
2413 					if (low_bps) {
2414 						if (last_bps<min_bps) {
2415 							if (now-low_bps>=min_bps_time) {
2416 								/* too bad */
2417 								vfile(_("rzfile: bps rate %ld below min %ld"),
2418 									  last_bps, min_bps);
2419 								DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: bps rate low: %ld < %ld",
2420 										   shortname, protname(), last_bps, min_bps));
2421 								xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2422 								return ERROR;
2423 							}
2424 						}
2425 						else
2426 							low_bps=0;
2427 					} else if (last_bps<min_bps) {
2428 						low_bps=now;
2429 					}
2430 				}
2431 				if (stop_time && now>=stop_time) {
2432 					/* too bad */
2433 					vfile(_("rzfile: reached stop time"));
2434 					DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: reached stop time",
2435 							   shortname, protname()));
2436 					xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2437 					return ERROR;
2438 				}
2439 
2440 				if (Verbose > 1) {
2441 					vstringf(_("\rBytes received: %7ld/%7ld   BPS:%-6ld ETA %02d:%02d  "),
2442 						(long) zi->bytes_received, (long) zi->bytes_total,
2443 						last_bps, minleft, secleft);
2444 					last_rxbytes=zi->bytes_received;
2445 					not_printed=0;
2446 				}
2447 			} else if (Verbose)
2448 				not_printed++;
2449 #ifdef SEGMENTS
2450 			if (chinseg >= (MAX_BLOCK * SEGMENTS)) {
2451 				putsec(secbuf, chinseg);
2452 				chinseg = 0;
2453 			}
2454 			switch (c = zrdata(secbuf+chinseg, MAX_BLOCK,&bytes_in_block))
2455 #else
2456 			switch (c = zrdata(secbuf, MAX_BLOCK,&bytes_in_block))
2457 #endif
2458 			{
2459 			case ZCAN:
2460 				xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2461 #ifdef SEGMENTS
2462 				putsec(secbuf, chinseg);
2463 				chinseg = 0;
2464 #endif
2465 				vfile("rzfile: zrdata returned %d", c);
2466 				DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: zrdata returned ZCAN",
2467 						   shortname, protname()));
2468 				return ERROR;
2469 			case ERROR:	/* CRC error */
2470 				xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2471 #ifdef SEGMENTS
2472 				putsec(secbuf, chinseg);
2473 				chinseg = 0;
2474 #endif
2475 				if ( --n < 0) {
2476 					vfile("rzfile: zgethdr returned %d", c);
2477 					DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: zrdata returned ERROR",
2478 							   shortname, protname()));
2479 					return ERROR;
2480 				}
2481 				zmputs(Attn);
2482 				continue;
2483 			case TIMEOUT:
2484 				xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2485 #ifdef SEGMENTS
2486 				putsec(secbuf, chinseg);
2487 				chinseg = 0;
2488 #endif
2489 				if ( --n < 0) {
2490 					DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: zrdata returned TIMEOUT",
2491 							   shortname, protname()));
2492 					vfile("rzfile: zgethdr returned %d", c);
2493 					return ERROR;
2494 				}
2495 				continue;
2496 			case GOTCRCW:
2497 				//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2498 				n = 20;
2499 #ifdef SEGMENTS
2500 				chinseg += bytes_in_block;
2501 				putsec(zi, secbuf, chinseg);
2502 				chinseg = 0;
2503 #else
2504 				putsec(zi, secbuf, bytes_in_block);
2505 #endif
2506 				zi->bytes_received += bytes_in_block;
2507 				stohdr(zi->bytes_received);
2508 				zshhdr(ZACK | 0x80, Txhdr);
2509 				goto nxthdr;
2510 			case GOTCRCQ:
2511 				//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2512 				n = 20;
2513 #ifdef SEGMENTS
2514 				chinseg += bytes_in_block;
2515 #else
2516 				putsec(zi, secbuf, bytes_in_block);
2517 #endif
2518 				zi->bytes_received += bytes_in_block;
2519 				stohdr(zi->bytes_received);
2520 				zshhdr(ZACK, Txhdr);
2521 				goto moredata;
2522 			case GOTCRCG:
2523 				//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2524 				n = 20;
2525 #ifdef SEGMENTS
2526 				chinseg += bytes_in_block;
2527 #else
2528 				putsec(zi, secbuf, bytes_in_block);
2529 #endif
2530 				zi->bytes_received += bytes_in_block;
2531 				goto moredata;
2532 			case GOTCRCE:
2533 				//xil_printf("%s(): L%d debug\n\r", __func__, __LINE__);
2534 				n = 20;
2535 #ifdef SEGMENTS
2536 				chinseg += bytes_in_block;
2537 #else
2538 				putsec(zi, secbuf, bytes_in_block);
2539 #endif
2540 				zi->bytes_received += bytes_in_block;
2541 				goto nxthdr;
2542 			}
2543 		}
2544 	}
2545 }
2546 
2547 /*
2548  * Send a string to the modem, processing for \336 (sleep 1 sec)
2549  *   and \335 (break signal)
2550  */
2551 static void
zmputs(const char * s)2552 zmputs(const char *s)
2553 {
2554 	__maybe_unused const char *p;
2555 
2556 	xil_printf("%s(): L%d zmputs not implmenment yet\n\r", __func__, __LINE__);
2557 #if 0
2558 	while (s && *s)
2559 	{
2560 		p=strpbrk(s,"\335\336");
2561 		if (!p)
2562 		{
2563 			write(1,s,strlen(s));
2564 			return;
2565 		}
2566 		if (p!=s)
2567 		{
2568 			write(1,s,(size_t) (p-s));
2569 			s=p;
2570 		}
2571 		if (*p=='\336')
2572 			sleep(1);
2573 		else
2574 			sendbrk(0);
2575 		p++;
2576 	}
2577 #endif
2578 }
2579 
2580 /*
2581  * Close the receive dataset, return OK or ERROR
2582  */
2583 #if 0
2584 int print_filename(FILE *f)
2585 {
2586 static	char buf[1024];
2587 	char fnmbuf[1024];
2588 	sprintf(fnmbuf, "/proc/self/fd/%d", fileno(f));
2589 	ssize_t nr;
2590 	if(0>(nr=readlink(fnmbuf, buf, sizeof(buf)))) return -1;
2591 	else buf[nr] = 0;
2592 	return buf;
2593 }
2594 #endif
2595 static int
closeit(struct zm_fileinfo * zi)2596 closeit(struct zm_fileinfo *zi)
2597 {
2598 	int ret;
2599 	if (Topipe) {
2600 #if 0
2601 		if (pclose(fout)) {
2602 			return ERROR;
2603 		}
2604 #endif
2605 		return OK;
2606 	}
2607 #if 0
2608 	if (in_tcpsync) {
2609 		rewind(fout);
2610 		if (!fgets(tcp_buf,sizeof(tcp_buf),fout)) {
2611 			error(1,errno,_("fgets for tcp protocol synchronization failed: "));
2612 		}
2613 		fclose(fout);
2614 		return OK;
2615 	}
2616 #endif
2617 	//ret=fclose(fout);
2618 	ret = 0;
2619 	if (ret) {
2620 		zpfatal(_("file close error"));
2621 		/* this may be any sort of error, including random data corruption */
2622 
2623 		//unlink(Pathname);
2624 		return ERROR;
2625 	}
2626 	if (zi->modtime) {
2627 #ifdef HAVE_STRUCT_UTIMBUF
2628 		struct utimbuf timep;
2629 		timep.actime = time(NULL);
2630 		timep.modtime = zi->modtime;
2631 		//utime(Pathname, &timep);
2632 #else
2633 		__maybe_unused time_t timep[2];
2634 		//timep[0] = time(NULL);
2635 		//timep[1] = zi->modtime;
2636 		//utime(Pathname, timep);
2637 #endif
2638 	}
2639 #ifdef S_ISREG
2640 	if (S_ISREG(zi->mode)) {
2641 #else
2642 	//if ((zi->mode&S_IFMT) == S_IFREG) {
2643 	if(1) {
2644 #endif
2645 		/* we must not make this program executable if running
2646 		 * under rsh, because the user might have uploaded an
2647 		 * unrestricted shell.
2648 		 */
2649 #if 0
2650 		if (under_rsh)
2651 			chmod(Pathname, (00666 & zi->mode));
2652 		else
2653 			chmod(Pathname, (07777 & zi->mode));
2654 #endif
2655 	}
2656 	//chmod(Pathname, 00777);
2657 	return OK;
2658 }
2659 
2660 /*
2661  * Ack a ZFIN packet, let byegones be byegones
2662  */
2663 static void
2664 ackbibi(void)
2665 {
2666 	int n;
2667 
2668 	vfile("ackbibi:");
2669 	Readnum = 1;
2670 	stohdr(0L);
2671 	for (n=3; --n>=0; ) {
2672 		purgeline(0);
2673 		zshhdr(ZFIN, Txhdr);
2674 		switch (READLINE_PF(100)) {
2675 		case 'O':
2676 			READLINE_PF(1);	/* Discard 2nd 'O' */
2677 			vfile("ackbibi complete");
2678 			return;
2679 		case RCDO:
2680 			return;
2681 		case TIMEOUT:
2682 		default:
2683 			break;
2684 		}
2685 	}
2686 }
2687 
2688 /*
2689  * Strip leading ! if present, do shell escape.
2690  */
2691 static int
2692 sys2(const char *s)
2693 {
2694 	if (*s == '!')
2695 		++s;
2696 	return 0;
2697 	//return system(s);
2698 }
2699 
2700 /*
2701  * Strip leading ! if present, do exec.
2702  */
2703 static void
2704 exec2(const char *s)
2705 {
2706 #if 0
2707 	if (*s == '!')
2708 		++s;
2709 	io_mode(0,0);
2710 	execl("/bin/sh", "sh", "-c", s);
2711 	zpfatal("execl");
2712 	exit(1);
2713 #endif
2714 }
2715 
2716 /*
2717  * Routine to calculate the free bytes on the current file system
2718  *  ~0 means many free bytes (unknown)
2719  */
2720 static size_t
2721 getfree(void)
2722 {
2723 	return((size_t) (~0L));	/* many free bytes ... */
2724 }
2725