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