Annotation of embedaddon/lrzsz/src/lrz.c, revision 1.1.1.1
1.1 misho 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 "xstrtoul.h"
42: #include "error.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; /* 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=FALSE; /* 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;
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=32768;
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:
161: #ifdef ENABLE_SYSLOG
162: # if defined(ENABLE_SYSLOG_FORCE) || defined(ENABLE_SYSLOG_DEFAULT)
163: int enable_syslog=TRUE;
164: # else
165: int enable_syslog=FALSE;
166: # endif
167: #define DO_SYSLOG_FNAME(message) do { \
168: if (enable_syslog) { \
169: const char *shortname; \
170: if (!zi->fname) \
171: shortname="no.name"; \
172: else { \
173: shortname=strrchr(zi->fname,'/'); \
174: if (!shortname) \
175: shortname=zi->fname; \
176: else \
177: shortname++; \
178: } \
179: lsyslog message ; \
180: } \
181: } while(0)
182: #define DO_SYSLOG(message) do { \
183: if (enable_syslog) { \
184: lsyslog message ; \
185: } \
186: } while(0)
187: #else
188: #define DO_SYSLOG_FNAME(message) do { } while(0)
189: #define DO_SYSLOG(message) do { } while(0)
190: #endif
191:
192:
193: /* called by signal interrupt or terminate to clean things up */
194: RETSIGTYPE
195: bibi(int n)
196: {
197: if (zmodem_requested)
198: zmputs(Attn);
199: canit(STDOUT_FILENO);
200: io_mode(0,0);
201: error(128+n,0,_("caught signal %d; exiting"), n);
202: }
203:
204: static struct option const long_options[] =
205: {
206: {"append", no_argument, NULL, '+'},
207: {"ascii", no_argument, NULL, 'a'},
208: {"binary", no_argument, NULL, 'b'},
209: {"bufsize", required_argument, NULL, 'B'},
210: {"allow-commands", no_argument, NULL, 'C'},
211: {"allow-remote-commands", no_argument, NULL, 'C'},
212: {"escape", no_argument, NULL, 'e'},
213: {"rename", no_argument, NULL, 'E'},
214: {"help", no_argument, NULL, 'h'},
215: {"crc-check", no_argument, NULL, 'H'},
216: {"junk-path", no_argument, NULL, 'j'},
217: {"errors", required_argument, NULL, 3},
218: {"disable-timeouts", no_argument, NULL, 'O'},
219: {"disable-timeout", no_argument, NULL, 'O'}, /* i can't get it right */
220: {"min-bps", required_argument, NULL, 'm'},
221: {"min-bps-time", required_argument, NULL, 'M'},
222: {"newer", no_argument, NULL, 'n'},
223: {"newer-or-longer", no_argument, NULL, 'N'},
224: {"protect", no_argument, NULL, 'p'},
225: {"resume", no_argument, NULL, 'r'},
226: {"restricted", no_argument, NULL, 'R'},
227: {"quiet", no_argument, NULL, 'q'},
228: {"stop-at", required_argument, NULL, 's'},
229: {"timesync", no_argument, NULL, 'S'},
230: {"timeout", required_argument, NULL, 't'},
231: {"keep-uppercase", no_argument, NULL, 'u'},
232: {"unrestrict", no_argument, NULL, 'U'},
233: {"verbose", no_argument, NULL, 'v'},
234: {"windowsize", required_argument, NULL, 'w'},
235: {"with-crc", no_argument, NULL, 'c'},
236: {"xmodem", no_argument, NULL, 'X'},
237: {"ymodem", no_argument, NULL, 1},
238: {"zmodem", no_argument, NULL, 'Z'},
239: {"overwrite", no_argument, NULL, 'y'},
240: {"null", no_argument, NULL, 'D'},
241: {"syslog", optional_argument, NULL , 2},
242: {"delay-startup", required_argument, NULL, 4},
243: {"o-sync", no_argument, NULL, 5},
244: {"o_sync", no_argument, NULL, 5},
245: {"tcp-server", no_argument, NULL, 6},
246: {"tcp-client", required_argument, NULL, 7},
247: {NULL,0,NULL,0}
248: };
249:
250: static void
251: show_version(void)
252: {
253: printf ("%s (%s) %s\n", program_name, PACKAGE, VERSION);
254: }
255:
256: int
257: main(int argc, char *argv[])
258: {
259: register char *cp;
260: register int npats;
261: char **patts=NULL; /* keep compiler quiet */
262: int exitcode=0;
263: int c;
264: unsigned int startup_delay=0;
265:
266: Rxtimeout = 100;
267: setbuf(stderr, NULL);
268: if ((cp=getenv("SHELL")) && (strstr(cp, "rsh") || strstr(cp, "rksh")
269: || strstr(cp,"rbash") || strstr(cp, "rshell")))
270: under_rsh=TRUE;
271: if ((cp=getenv("ZMODEM_RESTRICTED"))!=NULL)
272: Restricted=2;
273:
274: /* make temporary and unfinished files */
275: umask(0077);
276:
277: from_cu();
278: chkinvok(argv[0]); /* if called as [-]rzCOMMAND set flag */
279:
280: #ifdef ENABLE_SYSLOG
281: openlog(program_name,LOG_PID,ENABLE_SYSLOG);
282: #endif
283:
284: setlocale (LC_ALL, "");
285: bindtextdomain (PACKAGE, LOCALEDIR);
286: textdomain (PACKAGE);
287:
288: parse_long_options (argc, argv, show_version, usage1);
289:
290: while ((c = getopt_long (argc, argv,
291: "a+bB:cCDeEhm:M:OprRqs:St:uUvw:XZy",
292: long_options, (int *) 0)) != EOF)
293: {
294: unsigned long int tmp;
295: char *tmpptr;
296: enum strtol_error s_err;
297:
298: switch (c)
299: {
300: case 0:
301: break;
302: case '+': Lzmanag = ZF1_ZMAPND; break;
303: case 'a': Rxascii=TRUE; break;
304: case 'b': Rxbinary=TRUE; break;
305: case 'B':
306: if (strcmp(optarg,"auto")==0)
307: buffersize=-1;
308: else
309: buffersize=strtol(optarg,NULL,10);
310: break;
311: case 'c': Crcflg=TRUE; break;
312: case 'C': allow_remote_commands=TRUE; break;
313: case 'D': Nflag = TRUE; break;
314: case 'E': Lzmanag = ZF1_ZMCHNG; break;
315: case 'e': Zctlesc = 1; break;
316: case 'h': usage(0,NULL); break;
317: case 'H': Lzmanag= ZF1_ZMCRC; break;
318: case 'j': junk_path=TRUE; break;
319: case 'm':
320: s_err = xstrtoul (optarg, &tmpptr, 0, &tmp, "km");
321: min_bps = tmp;
322: if (s_err != LONGINT_OK)
323: STRTOL_FATAL_ERROR (optarg, _("min_bps"), s_err);
324: break;
325: case 'M':
326: s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
327: min_bps_time = tmp;
328: if (s_err != LONGINT_OK)
329: STRTOL_FATAL_ERROR (optarg, _("min_bps_time"), s_err);
330: if (min_bps_time<=1)
331: usage(2,_("min_bps_time must be > 1"));
332: break;
333: case 'N': Lzmanag = ZF1_ZMNEWL; break;
334: case 'n': Lzmanag = ZF1_ZMNEW; break;
335: case 'O': no_timeout=TRUE; break;
336: case 'p': Lzmanag = ZF1_ZMPROT; break;
337: case 'q': Quiet=TRUE; Verbose=0; break;
338: case 's':
339: if (isdigit((unsigned char) (*optarg))) {
340: struct tm *tm;
341: time_t t;
342: int hh,mm;
343: char *nex;
344:
345: hh = strtoul (optarg, &nex, 10);
346: if (hh>23)
347: usage(2,_("hour to large (0..23)"));
348: if (*nex!=':')
349: usage(2, _("unparsable stop time\n"));
350: nex++;
351: mm = strtoul (optarg, &nex, 10);
352: if (mm>59)
353: usage(2,_("minute to large (0..59)"));
354:
355: t=time(NULL);
356: tm=localtime(&t);
357: tm->tm_hour=hh;
358: tm->tm_min=hh;
359: stop_time=mktime(tm);
360: if (stop_time<t)
361: stop_time+=86400L; /* one day more */
362: if (stop_time - t <10)
363: usage(2,_("stop time to small"));
364: } else {
365: s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
366: stop_time = tmp + time(0);
367: if (s_err != LONGINT_OK)
368: STRTOL_FATAL_ERROR (optarg, _("stop-at"), s_err);
369: if (tmp<10)
370: usage(2,_("stop time to small"));
371: }
372: break;
373:
374:
375: case 'r':
376: if (try_resume)
377: Lzmanag= ZF1_ZMCRC;
378: else
379: try_resume=TRUE;
380: break;
381: case 'R': Restricted++; break;
382: case 'S':
383: #ifdef ENABLE_TIMESYNC
384: timesync_flag++;
385: if (timesync_flag==2) {
386: #ifdef HAVE_SETTIMEOFDAY
387: error(0,0,_("don't have settimeofday, will not set time\n"));
388: #endif
389: if (getuid()!=0)
390: error(0,0,
391: _("not running as root (this is good!), can not set time\n"));
392: }
393: #endif
394: break;
395: case 't':
396: s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
397: Rxtimeout = tmp;
398: if (s_err != LONGINT_OK)
399: STRTOL_FATAL_ERROR (optarg, _("timeout"), s_err);
400: if (Rxtimeout<10 || Rxtimeout>1000)
401: usage(2,_("timeout out of range 10..1000"));
402: break;
403: case 'w':
404: s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
405: Zrwindow = tmp;
406: if (s_err != LONGINT_OK)
407: STRTOL_FATAL_ERROR (optarg, _("window size"), s_err);
408: break;
409: case 'u':
410: MakeLCPathname=FALSE; break;
411: case 'U':
412: if (!under_rsh)
413: Restricted=0;
414: else {
415: DO_SYSLOG((LOG_INFO,"--unrestrict option used under restricted shell"));
416: error(1,0,
417: _("security violation: can't do that under restricted shell\n"));
418: }
419: break;
420: case 'v':
421: ++Verbose; break;
422: case 'X': protocol=ZM_XMODEM; break;
423: case 1: protocol=ZM_YMODEM; break;
424: case 'Z': protocol=ZM_ZMODEM; break;
425: case 'y':
426: Rxclob=TRUE; break;
427: case 2:
428: #ifdef ENABLE_SYSLOG
429: # ifndef ENABLE_SYSLOG_FORCE
430: if (optarg && (!strcmp(optarg,"off") || !strcmp(optarg,"no"))) {
431: if (under_rsh)
432: error(0,0, _("cannot turnoff syslog"));
433: else
434: enable_syslog=FALSE;
435: }
436: else
437: enable_syslog=TRUE;
438: # else
439: error(0,0, _("cannot turnoff syslog"));
440: # endif
441: #endif
442: case 3:
443: s_err = xstrtoul (optarg, NULL, 0, &tmp, "km");
444: bytes_per_error = tmp;
445: if (s_err != LONGINT_OK)
446: STRTOL_FATAL_ERROR (optarg, _("bytes_per_error"), s_err);
447: if (bytes_per_error<100)
448: usage(2,_("bytes-per-error should be >100"));
449: break;
450: case 4:
451: s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
452: startup_delay = tmp;
453: if (s_err != LONGINT_OK)
454: STRTOL_FATAL_ERROR (optarg, _("startup delay"), s_err);
455: break;
456: case 5:
457: #if defined(F_GETFD) && defined(F_SETFD) && defined(O_SYNC)
458: o_sync=1;
459: #else
460: error(0,0, _("O_SYNC not supported by the kernel"));
461: #endif
462: break;
463: case 6:
464: tcp_flag=2;
465: break;
466: case 7:
467: tcp_flag=3;
468: tcp_server_address=(char *)strdup(optarg);
469: if (!tcp_server_address)
470: error(1,0,_("out of memory"));
471: break;
472: default:
473: usage(2,NULL);
474: }
475:
476: }
477:
478: if (getuid()!=geteuid()) {
479: error(1,0,
480: _("this program was never intended to be used setuid\n"));
481: }
482: /* initialize zsendline tab */
483: zsendline_init();
484: #ifdef HAVE_SIGINTERRUPT
485: siginterrupt(SIGALRM,1);
486: #endif
487: if (startup_delay)
488: sleep(startup_delay);
489:
490: npats = argc - optind;
491: patts=&argv[optind];
492:
493: if (npats > 1)
494: usage(2,_("garbage on commandline"));
495: if (protocol!=ZM_XMODEM && npats)
496: usage(2, _("garbage on commandline"));
497: if (protocol==ZM_XMODEM && !npats)
498: usage(2, _("need a file name to receive"));
499: if (Restricted && allow_remote_commands) {
500: allow_remote_commands=FALSE;
501: }
502: if (Fromcu && !Quiet) {
503: if (Verbose == 0)
504: Verbose = 2;
505: }
506:
507: vfile("%s %s\n", program_name, VERSION);
508:
509: if (tcp_flag==2) {
510: char buf[256];
511: #ifdef MAXHOSTNAMELEN
512: char hn[MAXHOSTNAMELEN];
513: #else
514: char hn[256];
515: #endif
516: char *p,*q;
517: int d;
518:
519: /* tell receiver to receive via tcp */
520: d=tcp_server(buf);
521: p=strchr(buf+1,'<');
522: p++;
523: q=strchr(p,'>');
524: *q=0;
525: if (gethostname(hn,sizeof(hn))==-1) {
526: error(1,0, _("hostname too long\n"));
527: }
528: fprintf(stdout,"connect with lrz --tcp-client \"%s:%s\"\n",hn,p);
529: fflush(stdout);
530: /* ok, now that this file is sent we can switch to tcp */
531:
532: tcp_socket=tcp_accept(d);
533: dup2(tcp_socket,0);
534: dup2(tcp_socket,1);
535: }
536: if (tcp_flag==3) {
537: char buf[256];
538: char *p;
539: p=strchr(tcp_server_address,':');
540: if (!p)
541: error(1,0, _("illegal server address\n"));
542: *p++=0;
543: sprintf(buf,"[%s] <%s>\n",tcp_server_address,p);
544:
545: fprintf(stdout,"connecting to %s\n",buf);
546: fflush(stdout);
547:
548: /* we need to switch to tcp mode */
549: tcp_socket=tcp_connect(buf);
550: dup2(tcp_socket,0);
551: dup2(tcp_socket,1);
552: }
553:
554: io_mode(0,1);
555: readline_setup(0, HOWMANY, MAX_BLOCK*2);
556: if (signal(SIGINT, bibi) == SIG_IGN)
557: signal(SIGINT, SIG_IGN);
558: else
559: signal(SIGINT, bibi);
560: signal(SIGTERM, bibi);
561: signal(SIGPIPE, bibi);
562: if (wcreceive(npats, patts)==ERROR) {
563: exitcode=0200;
564: canit(STDOUT_FILENO);
565: }
566: io_mode(0,0);
567: if (exitcode && !zmodem_requested) /* bellow again with all thy might. */
568: canit(STDOUT_FILENO);
569: if (Verbose)
570: {
571: fputs("\r\n",stderr);
572: if (exitcode)
573: fputs(_("Transfer incomplete\n"),stderr);
574: else
575: fputs(_("Transfer complete\n"),stderr);
576: }
577: exit(exitcode);
578: }
579:
580: static void
581: usage1(int exitcode)
582: {
583: usage(exitcode,NULL);
584: }
585:
586: static void
587: usage(int exitcode, const char *what)
588: {
589: FILE *f=stdout;
590:
591: if (exitcode)
592: {
593: if (what)
594: fprintf(stderr, "%s: %s\n",program_name,what);
595: fprintf (stderr, _("Try `%s --help' for more information.\n"),
596: program_name);
597: exit(exitcode);
598: }
599:
600: fprintf(f, _("%s version %s\n"), program_name,
601: VERSION);
602:
603: fprintf(f,_("Usage: %s [options] [filename.if.xmodem]\n"), program_name);
604: fputs(_("Receive files with ZMODEM/YMODEM/XMODEM protocol\n"),f);
605: fputs(_(
606: " (X) = option applies to XMODEM only\n"
607: " (Y) = option applies to YMODEM only\n"
608: " (Z) = option applies to ZMODEM only\n"
609: ),f);
610: fputs(_(
611: " -+, --append append to existing files\n"
612: " -a, --ascii ASCII transfer (change CR/LF to LF)\n"
613: " -b, --binary binary transfer\n"
614: " -B, --bufsize N buffer N bytes (N==auto: buffer whole file)\n"
615: " -c, --with-crc Use 16 bit CRC (X)\n"
616: " -C, --allow-remote-commands allow execution of remote commands (Z)\n"
617: " -D, --null write all received data to /dev/null\n"
618: " --delay-startup N sleep N seconds before doing anything\n"
619: " -e, --escape Escape control characters (Z)\n"
620: " -E, --rename rename any files already existing\n"
621: " --errors N generate CRC error every N bytes (debugging)\n"
622: " -h, --help Help, print this usage message\n"
623: " -m, --min-bps N stop transmission if BPS below N\n"
624: " -M, --min-bps-time N for at least N seconds (default: 120)\n"
625: " -O, --disable-timeouts disable timeout code, wait forever for data\n"
626: " --o-sync open output file(s) in synchronous write mode\n"
627: " -p, --protect protect existing files\n"
628: " -q, --quiet quiet, no progress reports\n"
629: " -r, --resume try to resume interrupted file transfer (Z)\n"
630: " -R, --restricted restricted, more secure mode\n"
631: " -s, --stop-at {HH:MM|+N} stop transmission at HH:MM or in N seconds\n"
632: " -S, --timesync request remote time (twice: set local time)\n"
633: " --syslog[=off] turn syslog on or off, if possible\n"
634: " -t, --timeout N set timeout to N tenths of a second\n"
635: " -u, --keep-uppercase keep upper case filenames\n"
636: " -U, --unrestrict disable restricted mode (if allowed to)\n"
637: " -v, --verbose be verbose, provide debugging information\n"
638: " -w, --windowsize N Window is N bytes (Z)\n"
639: " -X --xmodem use XMODEM protocol\n"
640: " -y, --overwrite Yes, clobber existing file if any\n"
641: " --ymodem use YMODEM protocol\n"
642: " -Z, --zmodem use ZMODEM protocol\n"
643: "\n"
644: "short options use the same arguments as the long ones\n"
645: ),f);
646: exit(exitcode);
647: }
648:
649: /*
650: * Let's receive something already.
651: */
652:
653: static int
654: wcreceive(int argc, char **argp)
655: {
656: int c;
657: struct zm_fileinfo zi;
658: #ifdef ENABLE_SYSLOG
659: const char *shortname=NULL;;
660: #endif
661: zi.fname=NULL;
662: zi.modtime=0;
663: zi.mode=0;
664: zi.bytes_total=0;
665: zi.bytes_sent=0;
666: zi.bytes_received=0;
667: zi.bytes_skipped=0;
668: zi.eof_seen=0;
669:
670: if (protocol!=ZM_XMODEM || argc==0) {
671: Crcflg=1;
672: if ( !Quiet)
673: vstringf(_("%s waiting to receive."), program_name);
674: if ((c=tryz())!=0) {
675: if (c == ZCOMPL)
676: return OK;
677: if (c == ERROR)
678: goto fubar;
679: c = rzfiles(&zi);
680:
681: #ifdef ENABLE_SYSLOG
682: shortname=NULL;
683: #endif
684: if (c)
685: goto fubar;
686: } else {
687: for (;;) {
688: if (Verbose > 1
689: #ifdef ENABLE_SYSLOG
690: || enable_syslog
691: #endif
692: )
693: timing(1,NULL);
694: #ifdef ENABLE_SYSLOG
695: shortname=NULL;
696: #endif
697: if (wcrxpn(&zi,secbuf)== ERROR)
698: goto fubar;
699: if (secbuf[0]==0)
700: return OK;
701: if (procheader(secbuf, &zi) == ERROR)
702: goto fubar;
703: #ifdef ENABLE_SYSLOG
704: shortname=strrchr(zi.fname,'/');
705: if (shortname)
706: shortname++;
707: else
708: shortname=zi.fname;
709: #endif
710: if (wcrx(&zi)==ERROR)
711: goto fubar;
712:
713: if (Verbose > 1
714: #ifdef ENABLE_SYSLOG
715: || enable_syslog
716: #endif
717: ) {
718: double d;
719: long bps;
720: d=timing(0,NULL);
721: if (d==0)
722: d=0.5; /* can happen if timing uses time() */
723: bps=(zi.bytes_received-zi.bytes_skipped)/d;
724:
725: if (Verbose>1) {
726: vstringf(
727: _("\rBytes received: %7ld/%7ld BPS:%-6ld \r\n"),
728: (long) zi.bytes_received, (long) zi.bytes_total, bps);
729: }
730: #ifdef ENABLE_SYSLOG
731: if (enable_syslog)
732: lsyslog(LOG_INFO,"%s/%s: %ld Bytes, %ld BPS",
733: shortname,protname(),zi.bytes_received, bps);
734: #endif
735: }
736: }
737: }
738: } else {
739: char dummy[128];
740: dummy[0]='\0'; /* pre-ANSI HPUX cc demands this */
741: dummy[1]='\0'; /* procheader uses name + 1 + strlen(name) */
742: zi.bytes_total = DEFBYTL;
743:
744: if (Verbose > 1
745: #ifdef ENABLE_SYSLOG
746: || enable_syslog
747: #endif
748: )
749: timing(1,NULL);
750: procheader(dummy, &zi);
751:
752: if (Pathname)
753: free(Pathname);
754: errno=0;
755: Pathname=malloc(PATH_MAX+1);
756: if (!Pathname)
757: error(1,0,_("out of memory"));
758:
759: strcpy(Pathname, *argp);
760: checkpath(Pathname);
761: #ifdef ENABLE_SYSLOG
762: shortname=strrchr(*argp,'/');
763: if (shortname)
764: shortname++;
765: else
766: shortname=*argp;
767: #endif
768: vchar('\n');
769: vstringf(_("%s: ready to receive %s"), program_name, Pathname);
770: vstring("\r\n");
771:
772: if ((fout=fopen(Pathname, "w")) == NULL) {
773: #ifdef ENABLE_SYSLOG
774: if (enable_syslog)
775: lsyslog(LOG_ERR,"%s/%s: cannot open: %m",
776: shortname,protname());
777: #endif
778: return ERROR;
779: }
780: if (wcrx(&zi)==ERROR) {
781: goto fubar;
782: }
783: if (Verbose > 1
784: #ifdef ENABLE_SYSLOG
785: || enable_syslog
786: #endif
787: ) {
788: double d;
789: long bps;
790: d=timing(0,NULL);
791: if (d==0)
792: d=0.5; /* can happen if timing uses time() */
793: bps=(zi.bytes_received-zi.bytes_skipped)/d;
794: if (Verbose) {
795: vstringf(
796: _("\rBytes received: %7ld BPS:%-6ld \r\n"),
797: (long) zi.bytes_received, bps);
798: }
799: #ifdef ENABLE_SYSLOG
800: if (enable_syslog)
801: lsyslog(LOG_INFO,"%s/%s: %ld Bytes, %ld BPS",
802: shortname,protname(),zi.bytes_received, bps);
803: #endif
804: }
805: }
806: return OK;
807: fubar:
808: #ifdef ENABLE_SYSLOG
809: if (enable_syslog)
810: lsyslog(LOG_ERR,"%s/%s: got error",
811: shortname ? shortname : "no.name", protname());
812: #endif
813: canit(STDOUT_FILENO);
814: if (Topipe && fout) {
815: pclose(fout); return ERROR;
816: }
817: if (fout)
818: fclose(fout);
819:
820: if (Restricted && Pathname) {
821: unlink(Pathname);
822: vstringf(_("\r\n%s: %s removed.\r\n"), program_name, Pathname);
823: }
824: return ERROR;
825: }
826:
827:
828: /*
829: * Fetch a pathname from the other end as a C ctyle ASCIZ string.
830: * Length is indeterminate as long as less than Blklen
831: * A null string represents no more files (YMODEM)
832: */
833: static int
834: wcrxpn(struct zm_fileinfo *zi, char *rpn)
835: {
836: register int c;
837: size_t Blklen=0; /* record length of received packets */
838:
839: #ifdef NFGVMIN
840: READLINE_PF(1);
841: #else
842: purgeline(0);
843: #endif
844:
845: et_tu:
846: Firstsec=TRUE;
847: zi->eof_seen=FALSE;
848: sendline(Crcflg?WANTCRC:NAK);
849: flushmo();
850: purgeline(0); /* Do read next time ... */
851: while ((c = wcgetsec(&Blklen, rpn, 100)) != 0) {
852: if (c == WCEOT) {
853: zperr( _("Pathname fetch returned EOT"));
854: sendline(ACK);
855: flushmo();
856: purgeline(0); /* Do read next time ... */
857: READLINE_PF(1);
858: goto et_tu;
859: }
860: return ERROR;
861: }
862: sendline(ACK);
863: flushmo();
864: return OK;
865: }
866:
867: /*
868: * Adapted from CMODEM13.C, written by
869: * Jack M. Wierda and Roderick W. Hart
870: */
871: static int
872: wcrx(struct zm_fileinfo *zi)
873: {
874: register int sectnum, sectcurr;
875: register char sendchar;
876: size_t Blklen;
877:
878: Firstsec=TRUE;sectnum=0;
879: zi->eof_seen=FALSE;
880: sendchar=Crcflg?WANTCRC:NAK;
881:
882: for (;;) {
883: sendline(sendchar); /* send it now, we're ready! */
884: flushmo();
885: purgeline(0); /* Do read next time ... */
886: sectcurr=wcgetsec(&Blklen, secbuf,
887: (unsigned int) ((sectnum&0177) ? 50 : 130));
888: report(sectcurr);
889: if (sectcurr==((sectnum+1) &0377)) {
890: sectnum++;
891: /* if using xmodem we don't know how long a file is */
892: if (zi->bytes_total && R_BYTESLEFT(zi) < Blklen)
893: Blklen=R_BYTESLEFT(zi);
894: zi->bytes_received+=Blklen;
895: if (putsec(zi, secbuf, Blklen)==ERROR)
896: return ERROR;
897: sendchar=ACK;
898: }
899: else if (sectcurr==(sectnum&0377)) {
900: zperr( _("Received dup Sector"));
901: sendchar=ACK;
902: }
903: else if (sectcurr==WCEOT) {
904: if (closeit(zi))
905: return ERROR;
906: sendline(ACK);
907: flushmo();
908: purgeline(0); /* Do read next time ... */
909: return OK;
910: }
911: else if (sectcurr==ERROR)
912: return ERROR;
913: else {
914: zperr( _("Sync Error"));
915: return ERROR;
916: }
917: }
918: }
919:
920: /*
921: * Wcgetsec fetches a Ward Christensen type sector.
922: * Returns sector number encountered or ERROR if valid sector not received,
923: * or CAN CAN received
924: * or WCEOT if eot sector
925: * time is timeout for first char, set to 4 seconds thereafter
926: ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
927: * (Caller must do that when he is good and ready to get next sector)
928: */
929: static int
930: wcgetsec(size_t *Blklen, char *rxbuf, unsigned int maxtime)
931: {
932: register int checksum, wcj, firstch;
933: register unsigned short oldcrc;
934: register char *p;
935: int sectcurr;
936:
937: for (Lastrx=errors=0; errors<RETRYMAX; errors++) {
938:
939: if ((firstch=READLINE_PF(maxtime))==STX) {
940: *Blklen=1024; goto get2;
941: }
942: if (firstch==SOH) {
943: *Blklen=128;
944: get2:
945: sectcurr=READLINE_PF(1);
946: if ((sectcurr+(oldcrc=READLINE_PF(1)))==0377) {
947: oldcrc=checksum=0;
948: for (p=rxbuf,wcj=*Blklen; --wcj>=0; ) {
949: if ((firstch=READLINE_PF(1)) < 0)
950: goto bilge;
951: oldcrc=updcrc(firstch, oldcrc);
952: checksum += (*p++ = firstch);
953: }
954: if ((firstch=READLINE_PF(1)) < 0)
955: goto bilge;
956: if (Crcflg) {
957: oldcrc=updcrc(firstch, oldcrc);
958: if ((firstch=READLINE_PF(1)) < 0)
959: goto bilge;
960: oldcrc=updcrc(firstch, oldcrc);
961: if (oldcrc & 0xFFFF)
962: zperr( _("CRC"));
963: else {
964: Firstsec=FALSE;
965: return sectcurr;
966: }
967: }
968: else if (((checksum-firstch)&0377)==0) {
969: Firstsec=FALSE;
970: return sectcurr;
971: }
972: else
973: zperr( _("Checksum"));
974: }
975: else
976: zperr(_("Sector number garbled"));
977: }
978: /* make sure eot really is eot and not just mixmash */
979: #ifdef NFGVMIN
980: else if (firstch==EOT && READLINE_PF(1)==TIMEOUT)
981: return WCEOT;
982: #else
983: else if (firstch==EOT && READLINE_PF>0)
984: return WCEOT;
985: #endif
986: else if (firstch==CAN) {
987: if (Lastrx==CAN) {
988: zperr( _("Sender Cancelled"));
989: return ERROR;
990: } else {
991: Lastrx=CAN;
992: continue;
993: }
994: }
995: else if (firstch==TIMEOUT) {
996: if (Firstsec)
997: goto humbug;
998: bilge:
999: zperr( _("TIMEOUT"));
1000: }
1001: else
1002: zperr( _("Got 0%o sector header"), firstch);
1003:
1004: humbug:
1005: Lastrx=0;
1006: {
1007: int cnt=1000;
1008: while(cnt-- && READLINE_PF(1)!=TIMEOUT)
1009: ;
1010: }
1011: if (Firstsec) {
1012: sendline(Crcflg?WANTCRC:NAK);
1013: flushmo();
1014: purgeline(0); /* Do read next time ... */
1015: } else {
1016: maxtime=40;
1017: sendline(NAK);
1018: flushmo();
1019: purgeline(0); /* Do read next time ... */
1020: }
1021: }
1022: /* try to stop the bubble machine. */
1023: canit(STDOUT_FILENO);
1024: return ERROR;
1025: }
1026:
1027: #define ZCRC_DIFFERS (ERROR+1)
1028: #define ZCRC_EQUAL (ERROR+2)
1029: /*
1030: * do ZCRC-Check for open file f.
1031: * check at most check_bytes bytes (crash recovery). if 0 -> whole file.
1032: * remote file size is remote_bytes.
1033: */
1034: static int
1035: do_crc_check(FILE *f, size_t remote_bytes, size_t check_bytes)
1036: {
1037: struct stat st;
1038: unsigned long crc;
1039: unsigned long rcrc;
1040: size_t n;
1041: int c;
1042: int t1=0,t2=0;
1043: if (-1==fstat(fileno(f),&st)) {
1044: DO_SYSLOG((LOG_ERR,"cannot fstat open file: %s",strerror(errno)));
1045: return ERROR;
1046: }
1047: if (check_bytes==0 && ((size_t) st.st_size)!=remote_bytes)
1048: return ZCRC_DIFFERS; /* shortcut */
1049:
1050: crc=0xFFFFFFFFL;
1051: n=check_bytes;
1052: if (n==0)
1053: n=st.st_size;
1054: while (n-- && ((c = getc(f)) != EOF))
1055: crc = UPDC32(c, crc);
1056: crc = ~crc;
1057: clearerr(f); /* Clear EOF */
1058: fseek(f, 0L, 0);
1059:
1060: while (t1<3) {
1061: stohdr(check_bytes);
1062: zshhdr(ZCRC, Txhdr);
1063: while(t2<3) {
1064: size_t tmp;
1065: c = zgethdr(Rxhdr, 0, &tmp);
1066: rcrc=(unsigned long) tmp;
1067: switch (c) {
1068: default: /* ignore */
1069: break;
1070: case ZFIN:
1071: return ERROR;
1072: case ZRINIT:
1073: return ERROR;
1074: case ZCAN:
1075: if (Verbose)
1076: vstringf(_("got ZCAN"));
1077: return ERROR;
1078: break;
1079: case ZCRC:
1080: if (crc!=rcrc)
1081: return ZCRC_DIFFERS;
1082: return ZCRC_EQUAL;
1083: break;
1084: }
1085: }
1086: }
1087: return ERROR;
1088: }
1089:
1090: /*
1091: * Process incoming file information header
1092: */
1093: static int
1094: procheader(char *name, struct zm_fileinfo *zi)
1095: {
1096: const char *openmode;
1097: char *p;
1098: static char *name_static=NULL;
1099: char *nameend;
1100:
1101: if (name_static)
1102: free(name_static);
1103: if (junk_path) {
1104: p=strrchr(name,'/');
1105: if (p) {
1106: p++;
1107: if (!*p) {
1108: /* alert - file name ended in with a / */
1109: if (Verbose)
1110: vstringf(_("file name ends with a /, skipped: %s\n"),name);
1111: DO_SYSLOG((LOG_ERR,"file name ends with a /, skipped: %s", name));
1112: return ERROR;
1113: }
1114: name=p;
1115: }
1116: }
1117: name_static=malloc(strlen(name)+1);
1118: if (!name_static)
1119: error(1,0,_("out of memory"));
1120: strcpy(name_static,name);
1121: zi->fname=name_static;
1122:
1123: if (Verbose>2) {
1124: vstringf(_("zmanag=%d, Lzmanag=%d\n"),zmanag,Lzmanag);
1125: vstringf(_("zconv=%d\n"),zconv);
1126: }
1127:
1128: /* set default parameters and overrides */
1129: openmode = "w";
1130: Thisbinary = (!Rxascii) || Rxbinary;
1131: if (Lzmanag)
1132: zmanag = Lzmanag;
1133:
1134: /*
1135: * Process ZMODEM remote file management requests
1136: */
1137: if (!Rxbinary && zconv == ZCNL) /* Remote ASCII override */
1138: Thisbinary = 0;
1139: if (zconv == ZCBIN) /* Remote Binary override */
1140: Thisbinary = TRUE;
1141: if (Thisbinary && zconv == ZCBIN && try_resume)
1142: zconv=ZCRESUM;
1143: if (zmanag == ZF1_ZMAPND && zconv!=ZCRESUM)
1144: openmode = "a";
1145: if (skip_if_not_found)
1146: openmode="r+";
1147:
1148: #ifdef ENABLE_TIMESYNC
1149: in_timesync=0;
1150: if (timesync_flag && 0==strcmp(name,"$time$.t"))
1151: in_timesync=1;
1152: #endif
1153: in_tcpsync=0;
1154: if (tcpsync_flag && 0==strcmp(name,"$tcp$.t"))
1155: in_tcpsync=1;
1156:
1157: zi->bytes_total = DEFBYTL;
1158: zi->mode = 0;
1159: zi->eof_seen = 0;
1160: zi->modtime = 0;
1161:
1162: nameend = name + 1 + strlen(name);
1163: if (*nameend) { /* file coming from Unix or DOS system */
1164: long modtime=0;
1165: long bytes_total=DEFBYTL;
1166: int mode=0;
1167: sscanf(nameend, "%ld%lo%o", &bytes_total, &modtime, &mode);
1168: zi->modtime=modtime;
1169: zi->bytes_total=bytes_total;
1170: zi->mode=mode;
1171: if (zi->mode & UNIXFILE)
1172: ++Thisbinary;
1173: }
1174:
1175: /* Check for existing file */
1176: if (zconv != ZCRESUM && !Rxclob && (zmanag&ZF1_ZMMASK) != ZF1_ZMCLOB
1177: && (zmanag&ZF1_ZMMASK) != ZF1_ZMAPND
1178: #ifdef ENABLE_TIMESYNC
1179: && !in_timesync
1180: && !in_tcpsync
1181: #endif
1182: && (fout=fopen(name, "r"))) {
1183: struct stat sta;
1184: char *tmpname;
1185: char *ptr;
1186: int i;
1187: if (zmanag == ZF1_ZMNEW || zmanag==ZF1_ZMNEWL) {
1188: if (-1==fstat(fileno(fout),&sta)) {
1189: #ifdef ENABLE_SYSLOG
1190: int e=errno;
1191: #endif
1192: if (Verbose)
1193: vstringf(_("file exists, skipped: %s\n"),name);
1194: DO_SYSLOG((LOG_ERR,"cannot fstat open file %s: %s",
1195: name,strerror(e)));
1196: return ERROR;
1197: }
1198: if (zmanag == ZF1_ZMNEW) {
1199: if (sta.st_mtime > zi->modtime) {
1200: DO_SYSLOG((LOG_INFO,"skipping %s: newer file exists", name));
1201: return ERROR; /* skips file */
1202: }
1203: } else {
1204: /* newer-or-longer */
1205: if (((size_t) sta.st_size) >= zi->bytes_total
1206: && sta.st_mtime > zi->modtime) {
1207: DO_SYSLOG((LOG_INFO,"skipping %s: longer+newer file exists", name));
1208: return ERROR; /* skips file */
1209: }
1210: }
1211: fclose(fout);
1212: } else if (zmanag==ZF1_ZMCRC) {
1213: int r=do_crc_check(fout,zi->bytes_total,0);
1214: if (r==ERROR) {
1215: fclose(fout);
1216: return ERROR;
1217: }
1218: if (r!=ZCRC_DIFFERS) {
1219: return ERROR; /* skips */
1220: }
1221: fclose(fout);
1222: } else {
1223: size_t namelen;
1224: fclose(fout);
1225: if ((zmanag & ZF1_ZMMASK)!=ZF1_ZMCHNG) {
1226: if (Verbose)
1227: vstringf(_("file exists, skipped: %s\n"),name);
1228: return ERROR;
1229: }
1230: /* try to rename */
1231: namelen=strlen(name);
1232: tmpname=alloca(namelen+5);
1233: memcpy(tmpname,name,namelen);
1234: ptr=tmpname+namelen;
1235: *ptr++='.';
1236: i=0;
1237: do {
1238: sprintf(ptr,"%d",i++);
1239: } while (i<1000 && stat(tmpname,&sta)==0);
1240: if (i==1000)
1241: return ERROR;
1242: free(name_static);
1243: name_static=malloc(strlen(tmpname)+1);
1244: if (!name_static)
1245: error(1,0,_("out of memory"));
1246: strcpy(name_static,tmpname);
1247: zi->fname=name_static;
1248: }
1249: }
1250:
1251: if (!*nameend) { /* File coming from CP/M system */
1252: for (p=name_static; *p; ++p) /* change / to _ */
1253: if ( *p == '/')
1254: *p = '_';
1255:
1256: if ( *--p == '.') /* zap trailing period */
1257: *p = 0;
1258: }
1259:
1260: #ifdef ENABLE_TIMESYNC
1261: if (in_timesync)
1262: {
1263: long t=time(0);
1264: long d=t-zi->modtime;
1265: if (d<0)
1266: d=0;
1267: if ((Verbose && d>60) || Verbose > 1)
1268: vstringf(_("TIMESYNC: here %ld, remote %ld, diff %ld seconds\n"),
1269: (long) t, (long) zi->modtime, d);
1270: #ifdef HAVE_SETTIMEOFDAY
1271: if (timesync_flag > 1 && d > 10)
1272: {
1273: struct timeval tv;
1274: tv.tv_sec=zi->modtime;
1275: tv.tv_usec=0;
1276: if (settimeofday(&tv,NULL))
1277: vstringf(_("TIMESYNC: cannot set time: %s\n"),
1278: strerror(errno));
1279: }
1280: #endif
1281: return ERROR; /* skips file */
1282: }
1283: #endif /* ENABLE_TIMESYNC */
1284: if (in_tcpsync) {
1285: fout=tmpfile();
1286: if (!fout) {
1287: error(1,errno,_("cannot tmpfile() for tcp protocol synchronization"));
1288: }
1289: zi->bytes_received=0;
1290: return OK;
1291: }
1292:
1293:
1294: if (!zmodem_requested && MakeLCPathname && !IsAnyLower(name_static)
1295: && !(zi->mode&UNIXFILE))
1296: uncaps(name_static);
1297: if (Topipe > 0) {
1298: if (Pathname)
1299: free(Pathname);
1300: Pathname=malloc((PATH_MAX)*2);
1301: if (!Pathname)
1302: error(1,0,_("out of memory"));
1303: sprintf(Pathname, "%s %s", program_name+2, name_static);
1304: if (Verbose) {
1305: vstringf("%s: %s %s\n",
1306: _("Topipe"),
1307: Pathname, Thisbinary?"BIN":"ASCII");
1308: }
1309: if ((fout=popen(Pathname, "w")) == NULL)
1310: return ERROR;
1311: } else {
1312: if (protocol==ZM_XMODEM)
1313: /* we don't have the filename yet */
1314: return OK; /* dummy */
1315: if (Pathname)
1316: free(Pathname);
1317: Pathname=malloc((PATH_MAX)*2);
1318: if (!Pathname)
1319: error(1,0,_("out of memory"));
1320: strcpy(Pathname, name_static);
1321: if (Verbose) {
1322: /* overwrite the "waiting to receive" line */
1323: vstring("\r \r");
1324: vstringf(_("Receiving: %s\n"), name_static);
1325: }
1326: checkpath(name_static);
1327: if (Nflag)
1328: {
1329: /* cast because we might not have a prototyp for strdup :-/ */
1330: free(name_static);
1331: name_static=(char *) strdup("/dev/null");
1332: if (!name_static)
1333: {
1334: fprintf(stderr,"%s: %s\n", program_name, _("out of memory"));
1335: exit(1);
1336: }
1337: }
1338: #ifdef OMEN
1339: /* looks like a security hole -- uwe */
1340: if (name_static[0] == '!' || name_static[0] == '|') {
1341: if ( !(fout = popen(name_static+1, "w"))) {
1342: return ERROR;
1343: }
1344: Topipe = -1; return(OK);
1345: }
1346: #endif
1347: if (Thisbinary && zconv==ZCRESUM) {
1348: struct stat st;
1349: fout = fopen(name_static, "r+");
1350: if (fout && 0==fstat(fileno(fout),&st))
1351: {
1352: int can_resume=TRUE;
1353: if (zmanag==ZF1_ZMCRC) {
1354: int r=do_crc_check(fout,zi->bytes_total,st.st_size);
1355: if (r==ERROR) {
1356: fclose(fout);
1357: return ZFERR;
1358: }
1359: if (r==ZCRC_DIFFERS) {
1360: can_resume=FALSE;
1361: }
1362: }
1363: if ((unsigned long)st.st_size > zi->bytes_total) {
1364: can_resume=FALSE;
1365: }
1366: /* retransfer whole blocks */
1367: zi->bytes_skipped = st.st_size & ~(1023);
1368: if (can_resume) {
1369: if (fseek(fout, (long) zi->bytes_skipped, SEEK_SET)) {
1370: fclose(fout);
1371: return ZFERR;
1372: }
1373: }
1374: else
1375: zi->bytes_skipped=0; /* resume impossible, file has changed */
1376: goto buffer_it;
1377: }
1378: zi->bytes_skipped=0;
1379: if (fout)
1380: fclose(fout);
1381: }
1382: fout = fopen(name_static, openmode);
1383: #ifdef ENABLE_MKDIR
1384: if ( !fout && Restricted < 2) {
1385: if (make_dirs(name_static))
1386: fout = fopen(name_static, openmode);
1387: }
1388: #endif
1389: if ( !fout)
1390: {
1391: #ifdef ENABLE_SYSLOG
1392: int e=errno;
1393: #endif
1394: zpfatal(_("cannot open %s"), name_static);
1395: DO_SYSLOG((LOG_ERR,"%s: cannot open: %s",
1396: protname(),strerror(e)));
1397: return ERROR;
1398: }
1399: }
1400: buffer_it:
1401: if (Topipe == 0) {
1402: static char *s=NULL;
1403: static size_t last_length=0;
1404: #if defined(F_GETFD) && defined(F_SETFD) && defined(O_SYNC)
1405: if (o_sync) {
1406: int oldflags;
1407: oldflags = fcntl (fileno(fout), F_GETFD, 0);
1408: if (oldflags>=0 && !(oldflags & O_SYNC)) {
1409: oldflags|=O_SYNC;
1410: fcntl (fileno(fout), F_SETFD, oldflags); /* errors don't matter */
1411: }
1412: }
1413: #endif
1414:
1415: if (buffersize==-1 && s) {
1416: if (zi->bytes_total>last_length) {
1417: free(s);
1418: s=NULL;
1419: last_length=0;
1420: }
1421: }
1422: if (!s && buffersize) {
1423: last_length=32768;
1424: if (buffersize==-1) {
1425: if (zi->bytes_total>0)
1426: last_length=zi->bytes_total;
1427: } else
1428: last_length=buffersize;
1429: /* buffer `4096' bytes pages */
1430: last_length=(last_length+4095)&0xfffff000;
1431: s=malloc(last_length);
1432: if (!s) {
1433: zpfatal(_("out of memory"));
1434: exit(1);
1435: }
1436: }
1437: if (s) {
1438: #ifdef SETVBUF_REVERSED
1439: setvbuf(fout,_IOFBF,s,last_length);
1440: #else
1441: setvbuf(fout,s,_IOFBF,last_length);
1442: #endif
1443: }
1444: }
1445: zi->bytes_received=zi->bytes_skipped;
1446:
1447: return OK;
1448: }
1449:
1450: #ifdef ENABLE_MKDIR
1451: /*
1452: * Directory-creating routines from Public Domain TAR by John Gilmore
1453: */
1454:
1455: /*
1456: * After a file/link/symlink/dir creation has failed, see if
1457: * it's because some required directory was not present, and if
1458: * so, create all required dirs.
1459: */
1460: static int
1461: make_dirs(char *pathname)
1462: {
1463: register char *p; /* Points into path */
1464: int madeone = 0; /* Did we do anything yet? */
1465: int save_errno = errno; /* Remember caller's errno */
1466:
1467: if (errno != ENOENT)
1468: return 0; /* Not our problem */
1469:
1470: for (p = strchr(pathname, '/'); p != NULL; p = strchr(p+1, '/')) {
1471: /* Avoid mkdir of empty string, if leading or double '/' */
1472: if (p == pathname || p[-1] == '/')
1473: continue;
1474: /* Avoid mkdir where last part of path is '.' */
1475: if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
1476: continue;
1477: *p = 0; /* Truncate the path there */
1478: if ( !mkdir(pathname, 0777)) { /* Try to create it as a dir */
1479: vfile("Made directory %s\n", pathname);
1480: madeone++; /* Remember if we made one */
1481: *p = '/';
1482: continue;
1483: }
1484: *p = '/';
1485: if (errno == EEXIST) /* Directory already exists */
1486: continue;
1487: /*
1488: * Some other error in the mkdir. We return to the caller.
1489: */
1490: break;
1491: }
1492: errno = save_errno; /* Restore caller's errno */
1493: return madeone; /* Tell them to retry if we made one */
1494: }
1495:
1496: #endif /* ENABLE_MKDIR */
1497:
1498: /*
1499: * Putsec writes the n characters of buf to receive file fout.
1500: * If not in binary mode, carriage returns, and all characters
1501: * starting with CPMEOF are discarded.
1502: */
1503: static int
1504: putsec(struct zm_fileinfo *zi, char *buf, size_t n)
1505: {
1506: register char *p;
1507:
1508: if (n == 0)
1509: return OK;
1510: if (Thisbinary) {
1511: if (fwrite(buf,n,1,fout)!=1)
1512: return ERROR;
1513: }
1514: else {
1515: if (zi->eof_seen)
1516: return OK;
1517: for (p=buf; n>0; ++p,n-- ) {
1518: if ( *p == '\r')
1519: continue;
1520: if (*p == CPMEOF) {
1521: zi->eof_seen=TRUE;
1522: return OK;
1523: }
1524: putc(*p ,fout);
1525: }
1526: }
1527: return OK;
1528: }
1529:
1530: /* make string s lower case */
1531: static void
1532: uncaps(char *s)
1533: {
1534: for ( ; *s; ++s)
1535: if (isupper((unsigned char)(*s)))
1536: *s = tolower(*s);
1537: }
1538: /*
1539: * IsAnyLower returns TRUE if string s has lower case letters.
1540: */
1541: static int
1542: IsAnyLower(const char *s)
1543: {
1544: for ( ; *s; ++s)
1545: if (islower((unsigned char)(*s)))
1546: return TRUE;
1547: return FALSE;
1548: }
1549:
1550: static void
1551: report(int sct)
1552: {
1553: if (Verbose>1)
1554: {
1555: vstringf(_("Blocks received: %d"),sct);
1556: vchar('\r');
1557: }
1558: }
1559:
1560: /*
1561: * If called as [-][dir/../]vrzCOMMAND set Verbose to 1
1562: * If called as [-][dir/../]rzCOMMAND set the pipe flag
1563: * If called as rb use YMODEM protocol
1564: */
1565: static void
1566: chkinvok(const char *s)
1567: {
1568: const char *p;
1569:
1570: p = s;
1571: while (*p == '-')
1572: s = ++p;
1573: while (*p)
1574: if (*p++ == '/')
1575: s = p;
1576: if (*s == 'v') {
1577: Verbose=1; ++s;
1578: }
1579: program_name = s;
1580: if (*s == 'l')
1581: s++; /* lrz -> rz */
1582: protocol=ZM_ZMODEM;
1583: if (s[0]=='r' && s[1]=='x')
1584: protocol=ZM_XMODEM;
1585: if (s[0]=='r' && (s[1]=='b' || s[1]=='y'))
1586: protocol=ZM_YMODEM;
1587: if (s[2] && protocol!=ZM_XMODEM)
1588: Topipe = 1;
1589: }
1590:
1591: /*
1592: * Totalitarian Communist pathname processing
1593: */
1594: static void
1595: checkpath(const char *name)
1596: {
1597: if (Restricted) {
1598: const char *p;
1599: p=strrchr(name,'/');
1600: if (p)
1601: p++;
1602: else
1603: p=name;
1604: /* don't overwrite any file in very restricted mode.
1605: * don't overwrite hidden files in restricted mode */
1606: if ((Restricted==2 || *name=='.') && fopen(name, "r") != NULL) {
1607: canit(STDOUT_FILENO);
1608: vstring("\r\n");
1609: vstringf(_("%s: %s exists\n"),
1610: program_name, name);
1611: bibi(-1);
1612: }
1613: /* restrict pathnames to current tree or uucppublic */
1614: if ( strstr(name, "../")
1615: #ifdef PUBDIR
1616: || (name[0]== '/' && strncmp(name, PUBDIR,
1617: strlen(PUBDIR)))
1618: #endif
1619: ) {
1620: canit(STDOUT_FILENO);
1621: vstring("\r\n");
1622: vstringf(_("%s:\tSecurity Violation"),program_name);
1623: vstring("\r\n");
1624: bibi(-1);
1625: }
1626: if (Restricted > 1) {
1627: if (name[0]=='.' || strstr(name,"/.")) {
1628: canit(STDOUT_FILENO);
1629: vstring("\r\n");
1630: vstringf(_("%s:\tSecurity Violation"),program_name);
1631: vstring("\r\n");
1632: bibi(-1);
1633: }
1634: }
1635: }
1636: }
1637:
1638: /*
1639: * Initialize for Zmodem receive attempt, try to activate Zmodem sender
1640: * Handles ZSINIT frame
1641: * Return ZFILE if Zmodem filename received, -1 on error,
1642: * ZCOMPL if transaction finished, else 0
1643: */
1644: static int
1645: tryz(void)
1646: {
1647: register int c, n;
1648: register int cmdzack1flg;
1649: int zrqinits_received=0;
1650: size_t bytes_in_block=0;
1651:
1652: if (protocol!=ZM_ZMODEM) /* Check for "rb" program name */
1653: return 0;
1654:
1655: for (n=zmodem_requested?15:5;
1656: (--n + zrqinits_received) >=0 && zrqinits_received<10; ) {
1657: /* Set buffer length (0) and capability flags */
1658: #ifdef SEGMENTS
1659: stohdr(SEGMENTS*MAX_BLOCK);
1660: #else
1661: stohdr(0L);
1662: #endif
1663: #ifdef CANBREAK
1664: Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
1665: #else
1666: Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
1667: #endif
1668: #ifdef ENABLE_TIMESYNC
1669: if (timesync_flag)
1670: Txhdr[ZF1] |= ZF1_TIMESYNC;
1671: #endif
1672: if (Zctlesc)
1673: Txhdr[ZF0] |= TESCCTL; /* TESCCTL == ESCCTL */
1674: zshhdr(tryzhdrtype, Txhdr);
1675:
1676: if (tcp_socket==-1 && *tcp_buf) {
1677: /* we need to switch to tcp mode */
1678: tcp_socket=tcp_connect(tcp_buf);
1679: tcp_buf[0]=0;
1680: dup2(tcp_socket,0);
1681: dup2(tcp_socket,1);
1682: }
1683: if (tryzhdrtype == ZSKIP) /* Don't skip too far */
1684: tryzhdrtype = ZRINIT; /* CAF 8-21-87 */
1685: again:
1686: switch (zgethdr(Rxhdr, 0, NULL)) {
1687: case ZRQINIT:
1688: /* getting one ZRQINIT is totally ok. Normally a ZFILE follows
1689: * (and might be in our buffer, so don't purge it). But if we
1690: * get more ZRQINITs than the sender has started up before us
1691: * and sent ZRQINITs while waiting.
1692: */
1693: zrqinits_received++;
1694: continue;
1695:
1696: case ZEOF:
1697: continue;
1698: case TIMEOUT:
1699: continue;
1700: case ZFILE:
1701: zconv = Rxhdr[ZF0];
1702: if (!zconv)
1703: /* resume with sz -r is impossible (at least with unix sz)
1704: * if this is not set */
1705: zconv=ZCBIN;
1706: if (Rxhdr[ZF1] & ZF1_ZMSKNOLOC) {
1707: Rxhdr[ZF1] &= ~(ZF1_ZMSKNOLOC);
1708: skip_if_not_found=TRUE;
1709: }
1710: zmanag = Rxhdr[ZF1];
1711: ztrans = Rxhdr[ZF2];
1712: tryzhdrtype = ZRINIT;
1713: c = zrdata(secbuf, MAX_BLOCK,&bytes_in_block);
1714: io_mode(0,3);
1715: if (c == GOTCRCW)
1716: return ZFILE;
1717: zshhdr(ZNAK, Txhdr);
1718: goto again;
1719: case ZSINIT:
1720: /* this once was:
1721: * Zctlesc = TESCCTL & Rxhdr[ZF0];
1722: * trouble: if rz get --escape flag:
1723: * - it sends TESCCTL to sz,
1724: * get a ZSINIT _without_ TESCCTL (yeah - sender didn't know),
1725: * overwrites Zctlesc flag ...
1726: * - sender receives TESCCTL and uses "|=..."
1727: * so: sz escapes, but rz doesn't unescape ... not good.
1728: */
1729: Zctlesc |= TESCCTL & Rxhdr[ZF0];
1730: if (zrdata(Attn, ZATTNLEN,&bytes_in_block) == GOTCRCW) {
1731: stohdr(1L);
1732: zshhdr(ZACK, Txhdr);
1733: goto again;
1734: }
1735: zshhdr(ZNAK, Txhdr);
1736: goto again;
1737: case ZFREECNT:
1738: stohdr(getfree());
1739: zshhdr(ZACK, Txhdr);
1740: goto again;
1741: case ZCOMMAND:
1742: cmdzack1flg = Rxhdr[ZF0];
1743: if (zrdata(secbuf, MAX_BLOCK,&bytes_in_block) == GOTCRCW) {
1744: if (Verbose)
1745: {
1746: vstringf("%s: %s\n", program_name,
1747: _("remote command execution requested"));
1748: vstringf("%s: %s\n", program_name, secbuf);
1749: }
1750: if (!allow_remote_commands)
1751: {
1752: if (Verbose)
1753: vstringf("%s: %s\n", program_name,
1754: _("not executed"));
1755: zshhdr(ZCOMPL, Txhdr);
1756: DO_SYSLOG((LOG_INFO,"rexec denied: %s",secbuf));
1757: return ZCOMPL;
1758: }
1759: DO_SYSLOG((LOG_INFO,"rexec allowed: %s",secbuf));
1760: if (cmdzack1flg & ZCACK1)
1761: stohdr(0L);
1762: else
1763: stohdr((size_t)sys2(secbuf));
1764: purgeline(0); /* dump impatient questions */
1765: do {
1766: zshhdr(ZCOMPL, Txhdr);
1767: }
1768: while (++errors<20 && zgethdr(Rxhdr,1, NULL) != ZFIN);
1769: ackbibi();
1770: if (cmdzack1flg & ZCACK1)
1771: exec2(secbuf);
1772: return ZCOMPL;
1773: }
1774: zshhdr(ZNAK, Txhdr);
1775: goto again;
1776: case ZCOMPL:
1777: goto again;
1778: default:
1779: continue;
1780: case ZFIN:
1781: ackbibi();
1782: return ZCOMPL;
1783: case ZRINIT:
1784: if (Verbose)
1785: vstringf(_("got ZRINIT"));
1786: return ERROR;
1787: case ZCAN:
1788: if (Verbose)
1789: vstringf(_("got ZCAN"));
1790: return ERROR;
1791: }
1792: }
1793: return 0;
1794: }
1795:
1796:
1797: /*
1798: * Receive 1 or more files with ZMODEM protocol
1799: */
1800: static int
1801: rzfiles(struct zm_fileinfo *zi)
1802: {
1803: register int c;
1804:
1805: for (;;) {
1806: timing(1,NULL);
1807: c = rzfile(zi);
1808: switch (c) {
1809: case ZEOF:
1810: if (Verbose > 1
1811: #ifdef ENABLE_SYSLOG
1812: || enable_syslog
1813: #endif
1814: ) {
1815: double d;
1816: long bps;
1817: d=timing(0,NULL);
1818: if (d==0)
1819: d=0.5; /* can happen if timing uses time() */
1820: bps=(zi->bytes_received-zi->bytes_skipped)/d;
1821: if (Verbose > 1) {
1822: vstringf(
1823: _("\rBytes received: %7ld/%7ld BPS:%-6ld \r\n"),
1824: (long) zi->bytes_received, (long) zi->bytes_total, bps);
1825: }
1826: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: %ld Bytes, %ld BPS",shortname,
1827: protname(), (long) zi->bytes_total,bps));
1828: }
1829: /* FALL THROUGH */
1830: case ZSKIP:
1831: if (c==ZSKIP)
1832: {
1833: if (Verbose)
1834: vstringf(_("Skipped"));
1835: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: skipped",shortname,protname()));
1836: }
1837: switch (tryz()) {
1838: case ZCOMPL:
1839: return OK;
1840: default:
1841: return ERROR;
1842: case ZFILE:
1843: break;
1844: }
1845: continue;
1846: default:
1847: return c;
1848: case ERROR:
1849: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error",shortname,protname()));
1850: return ERROR;
1851: }
1852: }
1853: }
1854:
1855: /* "OOSB" means Out Of Sync Block. I once thought that if sz sents
1856: * blocks a,b,c,d, of which a is ok, b fails, we might want to save
1857: * c and d. But, alas, i never saw c and d.
1858: */
1859: #define SAVE_OOSB
1860: #ifdef SAVE_OOSB
1861: typedef struct oosb_t {
1862: size_t pos;
1863: size_t len;
1864: char *data;
1865: struct oosb_t *next;
1866: } oosb_t;
1867: struct oosb_t *anker=NULL;
1868: #endif
1869:
1870: /*
1871: * Receive a file with ZMODEM protocol
1872: * Assumes file name frame is in secbuf
1873: */
1874: static int
1875: rzfile(struct zm_fileinfo *zi)
1876: {
1877: register int c, n;
1878: long last_rxbytes=0;
1879: unsigned long last_bps=0;
1880: long not_printed=0;
1881: time_t low_bps=0;
1882: size_t bytes_in_block=0;
1883:
1884: zi->eof_seen=FALSE;
1885:
1886: n = 20;
1887:
1888: if (procheader(secbuf,zi) == ERROR) {
1889: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: procheader error",
1890: shortname,protname()));
1891: return (tryzhdrtype = ZSKIP);
1892: }
1893:
1894: for (;;) {
1895: #ifdef SEGMENTS
1896: chinseg = 0;
1897: #endif
1898: stohdr(zi->bytes_received);
1899: zshhdr(ZRPOS, Txhdr);
1900: goto skip_oosb;
1901: nxthdr:
1902: #ifdef SAVE_OOSB
1903: if (anker) {
1904: oosb_t *akt,*last,*next;
1905: for (akt=anker,last=NULL;akt;last= akt ? akt : last ,akt=next) {
1906: if (akt->pos==zi->bytes_received) {
1907: putsec(zi, akt->data, akt->len);
1908: zi->bytes_received += akt->len;
1909: vfile("using saved out-of-sync-paket %lx, len %ld",
1910: akt->pos,akt->len);
1911: goto nxthdr;
1912: }
1913: next=akt->next;
1914: if (akt->pos<zi->bytes_received) {
1915: vfile("removing unneeded saved out-of-sync-paket %lx, len %ld",
1916: akt->pos,akt->len);
1917: if (last)
1918: last->next=akt->next;
1919: else
1920: anker=akt->next;
1921: free(akt->data);
1922: free(akt);
1923: akt=NULL;
1924: }
1925: }
1926: }
1927: #endif
1928: skip_oosb:
1929: c = zgethdr(Rxhdr, 0, NULL);
1930: switch (c) {
1931: default:
1932: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: zgethdr returned %d",shortname,
1933: protname(),c));
1934: vfile("rzfile: zgethdr returned %d", c);
1935: return ERROR;
1936: case ZNAK:
1937: case TIMEOUT:
1938: #ifdef SEGMENTS
1939: putsec(secbuf, chinseg);
1940: chinseg = 0;
1941: #endif
1942: if ( --n < 0) {
1943: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: zgethdr returned %s",shortname,
1944: protname(),c == ZNAK ? "ZNAK" : "TIMEOUT"));
1945: vfile("rzfile: zgethdr returned %d", c);
1946: return ERROR;
1947: }
1948: case ZFILE:
1949: zrdata(secbuf, MAX_BLOCK,&bytes_in_block);
1950: continue;
1951: case ZEOF:
1952: #ifdef SEGMENTS
1953: putsec(secbuf, chinseg);
1954: chinseg = 0;
1955: #endif
1956: if (rclhdr(Rxhdr) != (long) zi->bytes_received) {
1957: /*
1958: * Ignore eof if it's at wrong place - force
1959: * a timeout because the eof might have gone
1960: * out before we sent our zrpos.
1961: */
1962: errors = 0; goto nxthdr;
1963: }
1964: if (closeit(zi)) {
1965: tryzhdrtype = ZFERR;
1966: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: closeit return <>0",
1967: shortname, protname()));
1968: vfile("rzfile: closeit returned <> 0");
1969: return ERROR;
1970: }
1971: vfile("rzfile: normal EOF");
1972: return c;
1973: case ERROR: /* Too much garbage in header search error */
1974: #ifdef SEGMENTS
1975: putsec(secbuf, chinseg);
1976: chinseg = 0;
1977: #endif
1978: if ( --n < 0) {
1979: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: zgethdr returned %d",
1980: shortname, protname(),c));
1981: vfile("rzfile: zgethdr returned %d", c);
1982: return ERROR;
1983: }
1984: zmputs(Attn);
1985: continue;
1986: case ZSKIP:
1987: #ifdef SEGMENTS
1988: putsec(secbuf, chinseg);
1989: chinseg = 0;
1990: #endif
1991: closeit(zi);
1992: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: sender skipped",
1993: shortname, protname()));
1994: vfile("rzfile: Sender SKIPPED file");
1995: return c;
1996: case ZDATA:
1997: if (rclhdr(Rxhdr) != (long) zi->bytes_received) {
1998: #if defined(SAVE_OOSB)
1999: oosb_t *neu;
2000: size_t pos=rclhdr(Rxhdr);
2001: #endif
2002: if ( --n < 0) {
2003: vfile("rzfile: out of sync");
2004: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: out of sync",
2005: shortname, protname()));
2006: return ERROR;
2007: }
2008: #if defined(SAVE_OOSB)
2009: switch (c = zrdata(secbuf, MAX_BLOCK,&bytes_in_block))
2010: {
2011: case GOTCRCW:
2012: case GOTCRCG:
2013: case GOTCRCE:
2014: case GOTCRCQ:
2015: if (pos>zi->bytes_received) {
2016: neu=malloc(sizeof(oosb_t));
2017: if (neu)
2018: neu->data=malloc(bytes_in_block);
2019: if (neu && neu->data) {
2020: #ifdef ENABLE_SYSLOG
2021: /* call syslog to tell me if this happens */
2022: lsyslog(LOG_ERR,
2023: "saving out-of-sync-block %lx, len %lu",
2024: pos, (unsigned long) bytes_in_block);
2025: #endif
2026: vfile("saving out-of-sync-block %lx, len %lu",pos,
2027: (unsigned long) bytes_in_block);
2028: memcpy(neu->data,secbuf,bytes_in_block);
2029: neu->pos=pos;
2030: neu->len=bytes_in_block;
2031: neu->next=anker;
2032: anker=neu;
2033: }
2034: else if (neu)
2035: free(neu);
2036: }
2037: }
2038: #endif
2039: #ifdef SEGMENTS
2040: putsec(secbuf, chinseg);
2041: chinseg = 0;
2042: #endif
2043: zmputs(Attn); continue;
2044: }
2045: moredata:
2046: if ((Verbose>1 || min_bps || stop_time)
2047: && (not_printed > (min_bps ? 3 : 7)
2048: || zi->bytes_received > last_bps / 2 + last_rxbytes)) {
2049: int minleft = 0;
2050: int secleft = 0;
2051: time_t now;
2052: double d;
2053: d=timing(0,&now);
2054: if (d==0)
2055: d=0.5; /* timing() might use time() */
2056: last_bps=zi->bytes_received/d;
2057: if (last_bps > 0) {
2058: minleft = (R_BYTESLEFT(zi))/last_bps/60;
2059: secleft = ((R_BYTESLEFT(zi))/last_bps)%60;
2060: }
2061: if (min_bps) {
2062: if (low_bps) {
2063: if (last_bps<min_bps) {
2064: if (now-low_bps>=min_bps_time) {
2065: /* too bad */
2066: vfile(_("rzfile: bps rate %ld below min %ld"),
2067: last_bps, min_bps);
2068: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: bps rate low: %ld < %ld",
2069: shortname, protname(), last_bps, min_bps));
2070: return ERROR;
2071: }
2072: }
2073: else
2074: low_bps=0;
2075: } else if (last_bps<min_bps) {
2076: low_bps=now;
2077: }
2078: }
2079: if (stop_time && now>=stop_time) {
2080: /* too bad */
2081: vfile(_("rzfile: reached stop time"));
2082: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: reached stop time",
2083: shortname, protname()));
2084: return ERROR;
2085: }
2086:
2087: if (Verbose > 1) {
2088: vstringf(_("\rBytes received: %7ld/%7ld BPS:%-6ld ETA %02d:%02d "),
2089: (long) zi->bytes_received, (long) zi->bytes_total,
2090: last_bps, minleft, secleft);
2091: last_rxbytes=zi->bytes_received;
2092: not_printed=0;
2093: }
2094: } else if (Verbose)
2095: not_printed++;
2096: #ifdef SEGMENTS
2097: if (chinseg >= (MAX_BLOCK * SEGMENTS)) {
2098: putsec(secbuf, chinseg);
2099: chinseg = 0;
2100: }
2101: switch (c = zrdata(secbuf+chinseg, MAX_BLOCK,&bytes_in_block))
2102: #else
2103: switch (c = zrdata(secbuf, MAX_BLOCK,&bytes_in_block))
2104: #endif
2105: {
2106: case ZCAN:
2107: #ifdef SEGMENTS
2108: putsec(secbuf, chinseg);
2109: chinseg = 0;
2110: #endif
2111: vfile("rzfile: zrdata returned %d", c);
2112: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: zrdata returned ZCAN",
2113: shortname, protname()));
2114: return ERROR;
2115: case ERROR: /* CRC error */
2116: #ifdef SEGMENTS
2117: putsec(secbuf, chinseg);
2118: chinseg = 0;
2119: #endif
2120: if ( --n < 0) {
2121: vfile("rzfile: zgethdr returned %d", c);
2122: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: zrdata returned ERROR",
2123: shortname, protname()));
2124: return ERROR;
2125: }
2126: zmputs(Attn);
2127: continue;
2128: case TIMEOUT:
2129: #ifdef SEGMENTS
2130: putsec(secbuf, chinseg);
2131: chinseg = 0;
2132: #endif
2133: if ( --n < 0) {
2134: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: zrdata returned TIMEOUT",
2135: shortname, protname()));
2136: vfile("rzfile: zgethdr returned %d", c);
2137: return ERROR;
2138: }
2139: continue;
2140: case GOTCRCW:
2141: n = 20;
2142: #ifdef SEGMENTS
2143: chinseg += bytes_in_block;
2144: putsec(zi, secbuf, chinseg);
2145: chinseg = 0;
2146: #else
2147: putsec(zi, secbuf, bytes_in_block);
2148: #endif
2149: zi->bytes_received += bytes_in_block;
2150: stohdr(zi->bytes_received);
2151: zshhdr(ZACK | 0x80, Txhdr);
2152: goto nxthdr;
2153: case GOTCRCQ:
2154: n = 20;
2155: #ifdef SEGMENTS
2156: chinseg += bytes_in_block;
2157: #else
2158: putsec(zi, secbuf, bytes_in_block);
2159: #endif
2160: zi->bytes_received += bytes_in_block;
2161: stohdr(zi->bytes_received);
2162: zshhdr(ZACK, Txhdr);
2163: goto moredata;
2164: case GOTCRCG:
2165: n = 20;
2166: #ifdef SEGMENTS
2167: chinseg += bytes_in_block;
2168: #else
2169: putsec(zi, secbuf, bytes_in_block);
2170: #endif
2171: zi->bytes_received += bytes_in_block;
2172: goto moredata;
2173: case GOTCRCE:
2174: n = 20;
2175: #ifdef SEGMENTS
2176: chinseg += bytes_in_block;
2177: #else
2178: putsec(zi, secbuf, bytes_in_block);
2179: #endif
2180: zi->bytes_received += bytes_in_block;
2181: goto nxthdr;
2182: }
2183: }
2184: }
2185: }
2186:
2187: /*
2188: * Send a string to the modem, processing for \336 (sleep 1 sec)
2189: * and \335 (break signal)
2190: */
2191: static void
2192: zmputs(const char *s)
2193: {
2194: const char *p;
2195:
2196: while (s && *s)
2197: {
2198: p=strpbrk(s,"\335\336");
2199: if (!p)
2200: {
2201: write(1,s,strlen(s));
2202: return;
2203: }
2204: if (p!=s)
2205: {
2206: write(1,s,(size_t) (p-s));
2207: s=p;
2208: }
2209: if (*p=='\336')
2210: sleep(1);
2211: else
2212: sendbrk(0);
2213: p++;
2214: }
2215: }
2216:
2217: /*
2218: * Close the receive dataset, return OK or ERROR
2219: */
2220: static int
2221: closeit(struct zm_fileinfo *zi)
2222: {
2223: int ret;
2224: if (Topipe) {
2225: if (pclose(fout)) {
2226: return ERROR;
2227: }
2228: return OK;
2229: }
2230: if (in_tcpsync) {
2231: rewind(fout);
2232: if (!fgets(tcp_buf,sizeof(tcp_buf),fout)) {
2233: error(1,errno,_("fgets for tcp protocol synchronization failed: "));
2234: }
2235: fclose(fout);
2236: return OK;
2237: }
2238: ret=fclose(fout);
2239: if (ret) {
2240: zpfatal(_("file close error"));
2241: /* this may be any sort of error, including random data corruption */
2242:
2243: unlink(Pathname);
2244: return ERROR;
2245: }
2246: if (zi->modtime) {
2247: #ifdef HAVE_STRUCT_UTIMBUF
2248: struct utimbuf timep;
2249: timep.actime = time(NULL);
2250: timep.modtime = zi->modtime;
2251: utime(Pathname, &timep);
2252: #else
2253: time_t timep[2];
2254: timep[0] = time(NULL);
2255: timep[1] = zi->modtime;
2256: utime(Pathname, timep);
2257: #endif
2258: }
2259: #ifdef S_ISREG
2260: if (S_ISREG(zi->mode)) {
2261: #else
2262: if ((zi->mode&S_IFMT) == S_IFREG) {
2263: #endif
2264: /* we must not make this program executable if running
2265: * under rsh, because the user might have uploaded an
2266: * unrestricted shell.
2267: */
2268: if (under_rsh)
2269: chmod(Pathname, (00666 & zi->mode));
2270: else
2271: chmod(Pathname, (07777 & zi->mode));
2272: }
2273: return OK;
2274: }
2275:
2276: /*
2277: * Ack a ZFIN packet, let byegones be byegones
2278: */
2279: static void
2280: ackbibi(void)
2281: {
2282: int n;
2283:
2284: vfile("ackbibi:");
2285: Readnum = 1;
2286: stohdr(0L);
2287: for (n=3; --n>=0; ) {
2288: purgeline(0);
2289: zshhdr(ZFIN, Txhdr);
2290: switch (READLINE_PF(100)) {
2291: case 'O':
2292: READLINE_PF(1); /* Discard 2nd 'O' */
2293: vfile("ackbibi complete");
2294: return;
2295: case RCDO:
2296: return;
2297: case TIMEOUT:
2298: default:
2299: break;
2300: }
2301: }
2302: }
2303:
2304: /*
2305: * Strip leading ! if present, do shell escape.
2306: */
2307: static int
2308: sys2(const char *s)
2309: {
2310: if (*s == '!')
2311: ++s;
2312: return system(s);
2313: }
2314:
2315: /*
2316: * Strip leading ! if present, do exec.
2317: */
2318: static void
2319: exec2(const char *s)
2320: {
2321: if (*s == '!')
2322: ++s;
2323: io_mode(0,0);
2324: execl("/bin/sh", "sh", "-c", s);
2325: zpfatal("execl");
2326: exit(1);
2327: }
2328:
2329: /*
2330: * Routine to calculate the free bytes on the current file system
2331: * ~0 means many free bytes (unknown)
2332: */
2333: static size_t
2334: getfree(void)
2335: {
2336: return((size_t) (~0L)); /* many free bytes ... */
2337: }
2338:
2339: /* End of lrz.c */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>