Annotation of embedaddon/lrzsz/src/lsz.c, revision 1.1.1.1
1.1 misho 1: /*
2: lsz - send 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: #include "zglobal.h"
25:
26: /* char *getenv(); */
27:
28: #define SS_NORMAL 0
29: #include <stdio.h>
30: #include <stdlib.h>
31: #include <signal.h>
32: #include <setjmp.h>
33: #include <ctype.h>
34: #include <errno.h>
35: #include <getopt.h>
36:
37: #ifndef R_OK
38: # define R_OK 4
39: #endif
40:
41: #if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP)
42: # include <sys/mman.h>
43: size_t mm_size;
44: void *mm_addr=NULL;
45: #else
46: # undef HAVE_MMAP
47: #endif
48: #include "timing.h"
49: #include "long-options.h"
50: #include "xstrtoul.h"
51: #include "error.h"
52:
53: #ifndef STRICT_PROTOTYPES
54: extern time_t time();
55: extern char *strerror();
56: extern char *strstr();
57: #endif
58:
59: #ifndef HAVE_ERRNO_DECLARATION
60: extern int errno;
61: #endif
62:
63: unsigned Baudrate=2400; /* Default, should be set by first mode() call */
64: unsigned Txwindow; /* Control the size of the transmitted window */
65: unsigned Txwspac; /* Spacing between zcrcq requests */
66: unsigned Txwcnt; /* Counter used to space ack requests */
67: size_t Lrxpos; /* Receiver's last reported offset */
68: int errors;
69: enum zm_type_enum protocol;
70: int under_rsh=FALSE;
71: extern int turbo_escape;
72: static int no_unixmode;
73:
74: int Canseek=1; /* 1: can; 0: only rewind, -1: neither */
75:
76: static int zsendfile __P ((struct zm_fileinfo *zi, const char *buf, size_t blen));
77: static int getnak __P ((void));
78: static int wctxpn __P ((struct zm_fileinfo *));
79: static int wcs __P ((const char *oname, const char *remotename));
80: static size_t zfilbuf __P ((struct zm_fileinfo *zi));
81: static size_t filbuf __P ((char *buf, size_t count));
82: static int getzrxinit __P ((void));
83: static int calc_blklen __P ((long total_sent));
84: static int sendzsinit __P ((void));
85: static int wctx __P ((struct zm_fileinfo *));
86: static int zsendfdata __P ((struct zm_fileinfo *));
87: static int getinsync __P ((struct zm_fileinfo *, int flag));
88: static void countem __P ((int argc, char **argv));
89: static void chkinvok __P ((const char *s));
90: static void usage __P ((int exitcode, const char *what));
91: static int zsendcmd __P ((const char *buf, size_t blen));
92: static void saybibi __P ((void));
93: static int wcsend __P ((int argc, char *argp[]));
94: static int wcputsec __P ((char *buf, int sectnum, size_t cseclen));
95: static void usage1 __P ((int exitcode));
96:
97: #ifdef ENABLE_SYSLOG
98: #define DO_SYSLOG(message) do { \
99: if (enable_syslog) { \
100: const char *shortname; \
101: if (!zi->fname) \
102: shortname="no.name"; \
103: else { \
104: shortname=strrchr(zi->fname,'/'); \
105: if (!shortname) \
106: shortname=zi->fname; \
107: else \
108: shortname++; \
109: } \
110: lsyslog message ; \
111: } \
112: } while(0)
113: #else
114: #define DO_SYSLOG(message) do { } while(0)
115: #endif
116:
117: #define ZSDATA(x,y,z) \
118: do { if (Crc32t) {zsda32(x,y,z); } else {zsdata(x,y,z);}} while(0)
119: #ifdef HAVE_MMAP
120: #define DATAADR (mm_addr ? ((char *)mm_addr)+zi->bytes_sent : txbuf)
121: #else
122: #define DATAADR (txbuf)
123: #endif
124:
125: int Filesleft;
126: long Totalleft;
127: size_t buffersize=16384;
128: #ifdef HAVE_MMAP
129: int use_mmap=1;
130: #endif
131:
132: /*
133: * Attention string to be executed by receiver to interrupt streaming data
134: * when an error is detected. A pause (0336) may be needed before the
135: * ^C (03) or after it.
136: */
137: #ifdef READCHECK
138: char Myattn[] = { 0 };
139: #else
140: char Myattn[] = { 03, 0336, 0 };
141: #endif
142:
143: FILE *input_f;
144:
145: #define MAX_BLOCK 8192
146: char txbuf[MAX_BLOCK];
147:
148: long vpos = 0; /* Number of bytes read from file */
149:
150: char Lastrx;
151: char Crcflg;
152: int Verbose=0;
153: int Restricted=0; /* restricted; no /.. or ../ in filenames */
154: int Quiet=0; /* overrides logic that would otherwise set verbose */
155: int Ascii=0; /* Add CR's for brain damaged programs */
156: int Fullname=0; /* transmit full pathname */
157: int Unlinkafter=0; /* Unlink file after it is sent */
158: int Dottoslash=0; /* Change foo.bar.baz to foo/bar/baz */
159: int firstsec;
160: int errcnt=0; /* number of files unreadable */
161: size_t blklen=128; /* length of transmitted records */
162: int Optiong; /* Let it rip no wait for sector ACK's */
163: int Totsecs; /* total number of sectors this file */
164: int Filcnt=0; /* count of number of files opened */
165: int Lfseen=0;
166: unsigned Rxbuflen = 16384; /* Receiver's max buffer length */
167: unsigned Tframlen = 0; /* Override for tx frame length */
168: unsigned blkopt=0; /* Override value for zmodem blklen */
169: int Rxflags = 0;
170: int Rxflags2 = 0;
171: size_t bytcnt;
172: int Wantfcs32 = TRUE; /* want to send 32 bit FCS */
173: char Lzconv; /* Local ZMODEM file conversion request */
174: char Lzmanag; /* Local ZMODEM file management request */
175: int Lskipnocor;
176: char Lztrans;
177: char zconv; /* ZMODEM file conversion request */
178: char zmanag; /* ZMODEM file management request */
179: char ztrans; /* ZMODEM file transport request */
180: int command_mode; /* Send a command, then exit. */
181: int Cmdtries = 11;
182: int Cmdack1; /* Rx ACKs command, then do it */
183: int Exitcode;
184: int enable_timesync=0;
185: size_t Lastsync; /* Last offset to which we got a ZRPOS */
186: int Beenhereb4; /* How many times we've been ZRPOS'd same place */
187:
188: int no_timeout=FALSE;
189: size_t max_blklen=1024;
190: size_t start_blklen=0;
191: int zmodem_requested;
192: time_t stop_time=0;
193: int tcp_flag=0;
194: char *tcp_server_address=0;
195: int tcp_socket=-1;
196:
197: int error_count;
198: #define OVERHEAD 18
199: #define OVER_ERR 20
200:
201: #define MK_STRING(x) #x
202:
203: #ifdef ENABLE_SYSLOG
204: # if defined(ENABLE_SYSLOG_FORCE) || defined(ENABLE_SYSLOG_DEFAULT)
205: int enable_syslog=TRUE;
206: # else
207: int enable_syslog=FALSE;
208: # endif
209: #endif
210:
211: jmp_buf intrjmp; /* For the interrupt on RX CAN */
212:
213: static long min_bps;
214: static long min_bps_time;
215:
216: static int io_mode_fd=0;
217: static int zrqinits_sent=0;
218: static int play_with_sigint=0;
219:
220: /* called by signal interrupt or terminate to clean things up */
221: RETSIGTYPE
222: bibi (int n)
223: {
224: canit(STDOUT_FILENO);
225: fflush (stdout);
226: io_mode (io_mode_fd,0);
227: if (n == 99)
228: error (0, 0, _ ("io_mode(,2) in rbsb.c not implemented\n"));
229: else
230: error (0, 0, _ ("caught signal %d; exiting"), n);
231: if (n == SIGQUIT)
232: abort ();
233: exit (128 + n);
234: }
235:
236: /* Called when ZMODEM gets an interrupt (^C) */
237: static RETSIGTYPE
238: onintr(int n LRZSZ_ATTRIB_UNUSED)
239: {
240: signal(SIGINT, SIG_IGN);
241: longjmp(intrjmp, -1);
242: }
243:
244: int Zctlesc; /* Encode control characters */
245: const char *program_name = "sz";
246: int Zrwindow = 1400; /* RX window size (controls garbage count) */
247:
248: static struct option const long_options[] =
249: {
250: {"append", no_argument, NULL, '+'},
251: {"twostop", no_argument, NULL, '2'},
252: {"try-8k", no_argument, NULL, '8'},
253: {"start-8k", no_argument, NULL, '9'},
254: {"try-4k", no_argument, NULL, '4'},
255: {"start-4k", no_argument, NULL, '5'},
256: {"ascii", no_argument, NULL, 'a'},
257: {"binary", no_argument, NULL, 'b'},
258: {"bufsize", required_argument, NULL, 'B'},
259: {"cmdtries", required_argument, NULL, 'C'},
260: {"command", required_argument, NULL, 'c'},
261: {"immediate-command", required_argument, NULL, 'i'},
262: {"dot-to-slash", no_argument, NULL, 'd'},
263: {"full-path", no_argument, NULL, 'f'},
264: {"escape", no_argument, NULL, 'e'},
265: {"rename", no_argument, NULL, 'E'},
266: {"help", no_argument, NULL, 'h'},
267: {"crc-check", no_argument, NULL, 'H'},
268: {"1024", no_argument, NULL, 'k'},
269: {"1k", no_argument, NULL, 'k'},
270: {"packetlen", required_argument, NULL, 'L'},
271: {"framelen", required_argument, NULL, 'l'},
272: {"min-bps", required_argument, NULL, 'm'},
273: {"min-bps-time", required_argument, NULL, 'M'},
274: {"newer", no_argument, NULL, 'n'},
275: {"newer-or-longer", no_argument, NULL, 'N'},
276: {"16-bit-crc", no_argument, NULL, 'o'},
277: {"disable-timeouts", no_argument, NULL, 'O'},
278: {"disable-timeout", no_argument, NULL, 'O'}, /* i can't get it right */
279: {"protect", no_argument, NULL, 'p'},
280: {"resume", no_argument, NULL, 'r'},
281: {"restricted", no_argument, NULL, 'R'},
282: {"quiet", no_argument, NULL, 'q'},
283: {"stop-at", required_argument, NULL, 's'},
284: {"syslog", optional_argument, NULL , 2},
285: {"timesync", no_argument, NULL, 'S'},
286: {"timeout", required_argument, NULL, 't'},
287: {"turbo", no_argument, NULL, 'T'},
288: {"unlink", no_argument, NULL, 'u'},
289: {"unrestrict", no_argument, NULL, 'U'},
290: {"verbose", no_argument, NULL, 'v'},
291: {"windowsize", required_argument, NULL, 'w'},
292: {"xmodem", no_argument, NULL, 'X'},
293: {"ymodem", no_argument, NULL, 1},
294: {"zmodem", no_argument, NULL, 'Z'},
295: {"overwrite", no_argument, NULL, 'y'},
296: {"overwrite-or-skip", no_argument, NULL, 'Y'},
297:
298: {"delay-startup", required_argument, NULL, 4},
299: {"tcp", no_argument, NULL, 5},
300: {"tcp-server", no_argument, NULL, 6},
301: {"tcp-client", required_argument, NULL, 7},
302: {"no-unixmode", no_argument, NULL, 8},
303: {NULL, 0, NULL, 0}
304: };
305:
306: static void
307: show_version(void)
308: {
309: printf ("%s (%s) %s\n", program_name, PACKAGE, VERSION);
310: }
311:
312:
313: int
314: main(int argc, char **argv)
315: {
316: char *cp;
317: int npats;
318: int dm;
319: int i;
320: int stdin_files;
321: char **patts;
322: int c;
323: const char *Cmdstr=NULL; /* Pointer to the command string */
324: unsigned int startup_delay=0;
325:
326: if (((cp = getenv("ZNULLS")) != NULL) && *cp)
327: Znulls = atoi(cp);
328: if (((cp=getenv("SHELL"))!=NULL) && (strstr(cp, "rsh") || strstr(cp, "rksh")
329: || strstr(cp, "rbash") || strstr(cp,"rshell")))
330: {
331: under_rsh=TRUE;
332: Restricted=1;
333: }
334: if ((cp=getenv("ZMODEM_RESTRICTED"))!=NULL)
335: Restricted=1;
336: from_cu();
337: chkinvok(argv[0]);
338:
339: #ifdef ENABLE_SYSLOG
340: openlog(program_name,LOG_PID,ENABLE_SYSLOG);
341: #endif
342:
343: setlocale (LC_ALL, "");
344: bindtextdomain (PACKAGE, LOCALEDIR);
345: textdomain (PACKAGE);
346:
347: parse_long_options (argc, argv, show_version, usage1);
348:
349: Rxtimeout = 600;
350:
351: while ((c = getopt_long (argc, argv,
352: "2+48abB:C:c:dfeEghHi:kL:l:m:M:NnOopRrqsSt:TUuvw:XYy",
353: long_options, (int *) 0))!=EOF)
354: {
355: unsigned long int tmp;
356: char *tmpptr;
357: enum strtol_error s_err;
358:
359: switch (c)
360: {
361: case 0:
362: break;
363: case '+': Lzmanag = ZF1_ZMAPND; break;
364: case '2': Twostop = TRUE; break;
365: case '8':
366: if (max_blklen==8192)
367: start_blklen=8192;
368: else
369: max_blklen=8192;
370: break;
371: case '9': /* this is a longopt .. */
372: start_blklen=8192;
373: max_blklen=8192;
374: break;
375: case '4':
376: if (max_blklen==4096)
377: start_blklen=4096;
378: else
379: max_blklen=4096;
380: break;
381: case '5': /* this is a longopt .. */
382: start_blklen=4096;
383: max_blklen=4096;
384: break;
385: case 'a': Lzconv = ZCNL; Ascii = TRUE; break;
386: case 'b': Lzconv = ZCBIN; break;
387: case 'B':
388: if (0==strcmp(optarg,"auto"))
389: buffersize= (size_t) -1;
390: else
391: buffersize=strtol(optarg,NULL,10);
392: #ifdef HAVE_MMAP
393: use_mmap=0;
394: #endif
395: break;
396: case 'C':
397: s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
398: Cmdtries = tmp;
399: if (s_err != LONGINT_OK)
400: STRTOL_FATAL_ERROR (optarg, _("command tries"), s_err);
401: break;
402: case 'i':
403: Cmdack1 = ZCACK1;
404: /* **** FALL THROUGH TO **** */
405: case 'c':
406: command_mode = TRUE;
407: Cmdstr = optarg;
408: break;
409: case 'd':
410: ++Dottoslash;
411: /* **** FALL THROUGH TO **** */
412: case 'f': Fullname=TRUE; break;
413: case 'e': Zctlesc = 1; break;
414: case 'E': Lzmanag = ZF1_ZMCHNG; break;
415: case 'h': usage(0,NULL); break;
416: case 'H': Lzmanag = ZF1_ZMCRC; break;
417: case 'k': start_blklen=1024; break;
418: case 'L':
419: s_err = xstrtoul (optarg, NULL, 0, &tmp, "ck");
420: blkopt = tmp;
421: if (s_err != LONGINT_OK)
422: STRTOL_FATAL_ERROR (optarg, _("packetlength"), s_err);
423: if (blkopt<24 || blkopt>MAX_BLOCK)
424: {
425: char meld[256];
426: sprintf(meld,
427: _("packetlength out of range 24..%ld"),
428: (long) MAX_BLOCK);
429: usage(2,meld);
430: }
431: break;
432: case 'l':
433: s_err = xstrtoul (optarg, NULL, 0, &tmp, "ck");
434: Tframlen = tmp;
435: if (s_err != LONGINT_OK)
436: STRTOL_FATAL_ERROR (optarg, _("framelength"), s_err);
437: if (Tframlen<32 || Tframlen>MAX_BLOCK)
438: {
439: char meld[256];
440: sprintf(meld,
441: _("framelength out of range 32..%ld"),
442: (long) MAX_BLOCK);
443: usage(2,meld);
444: }
445: break;
446: case 'm':
447: s_err = xstrtoul (optarg, &tmpptr, 0, &tmp, "km");
448: min_bps = tmp;
449: if (s_err != LONGINT_OK)
450: STRTOL_FATAL_ERROR (optarg, _("min_bps"), s_err);
451: if (min_bps<0)
452: usage(2,_("min_bps must be >= 0"));
453: break;
454: case 'M':
455: s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
456: min_bps_time = tmp;
457: if (s_err != LONGINT_OK)
458: STRTOL_FATAL_ERROR (optarg, _("min_bps_time"), s_err);
459: if (min_bps_time<=1)
460: usage(2,_("min_bps_time must be > 1"));
461: break;
462: case 'N': Lzmanag = ZF1_ZMNEWL; break;
463: case 'n': Lzmanag = ZF1_ZMNEW; break;
464: case 'o': Wantfcs32 = FALSE; break;
465: case 'O': no_timeout = TRUE; break;
466: case 'p': Lzmanag = ZF1_ZMPROT; break;
467: case 'r':
468: if (Lzconv == ZCRESUM)
469: Lzmanag = ZF1_ZMCRC;
470: else
471: Lzconv = ZCRESUM;
472: break;
473: case 'R': Restricted = TRUE; break;
474: case 'q': Quiet=TRUE; Verbose=0; break;
475: case 's':
476: if (isdigit((unsigned char) (*optarg))) {
477: struct tm *tm;
478: time_t t;
479: int hh,mm;
480: char *nex;
481:
482: hh = strtoul (optarg, &nex, 10);
483: if (hh>23)
484: usage(2,_("hour to large (0..23)"));
485: if (*nex!=':')
486: usage(2, _("unparsable stop time\n"));
487: nex++;
488: mm = strtoul (optarg, &nex, 10);
489: if (mm>59)
490: usage(2,_("minute to large (0..59)"));
491:
492: t=time(NULL);
493: tm=localtime(&t);
494: tm->tm_hour=hh;
495: tm->tm_min=hh;
496: stop_time=mktime(tm);
497: if (stop_time<t)
498: stop_time+=86400L; /* one day more */
499: if (stop_time - t <10)
500: usage(2,_("stop time to small"));
501: } else {
502: s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
503: stop_time = tmp + time(0);
504: if (s_err != LONGINT_OK)
505: STRTOL_FATAL_ERROR (optarg, _("stop-at"), s_err);
506: if (tmp<10)
507: usage(2,_("stop time to small"));
508: }
509: break;
510: case 'S': enable_timesync=1; break;
511: case 'T': turbo_escape=1; break;
512: case 't':
513: s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
514: Rxtimeout = tmp;
515: if (s_err != LONGINT_OK)
516: STRTOL_FATAL_ERROR (optarg, _("timeout"), s_err);
517: if (Rxtimeout<10 || Rxtimeout>1000)
518: usage(2,_("timeout out of range 10..1000"));
519: break;
520: case 'u': ++Unlinkafter; break;
521: case 'U':
522: if (!under_rsh)
523: Restricted=0;
524: else
525: error(1,0,
526: _("security violation: can't do that under restricted shell\n"));
527: break;
528: case 'v': ++Verbose; break;
529: case 'w':
530: s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
531: Txwindow = tmp;
532: if (s_err != LONGINT_OK)
533: STRTOL_FATAL_ERROR (optarg, _("window size"), s_err);
534: if (Txwindow < 256)
535: Txwindow = 256;
536: Txwindow = (Txwindow/64) * 64;
537: Txwspac = Txwindow/4;
538: if (blkopt > Txwspac
539: || (!blkopt && Txwspac < MAX_BLOCK))
540: blkopt = Txwspac;
541: break;
542: case 'X': protocol=ZM_XMODEM; break;
543: case 1: protocol=ZM_YMODEM; break;
544: case 'Z': protocol=ZM_ZMODEM; break;
545: case 'Y':
546: Lskipnocor = TRUE;
547: /* **** FALLL THROUGH TO **** */
548: case 'y':
549: Lzmanag = ZF1_ZMCLOB; break;
550: case 2:
551: #ifdef ENABLE_SYSLOG
552: # ifndef ENABLE_SYSLOG_FORCE
553: if (optarg && (!strcmp(optarg,"off") || !strcmp(optarg,"no")))
554: {
555: if (under_rsh)
556: error(0,0, _("cannot turnoff syslog"));
557: else
558: enable_syslog=FALSE;
559: }
560: else
561: enable_syslog=TRUE;
562: # else
563: error(0,0, _("cannot turnoff syslog"));
564: # endif
565: #endif
566: break;
567: case 4:
568: s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL);
569: startup_delay = tmp;
570: if (s_err != LONGINT_OK)
571: STRTOL_FATAL_ERROR (optarg, _("startup delay"), s_err);
572: break;
573: case 5:
574: tcp_flag=1;
575: break;
576: case 6:
577: tcp_flag=2;
578: break;
579: case 7:
580: tcp_flag=3;
581: tcp_server_address=(char *)strdup(optarg);
582: if (!tcp_server_address) {
583: error(1,0,_("out of memory"));
584: }
585: break;
586: case 8: no_unixmode=1; break;
587: default:
588: usage (2,NULL);
589: break;
590: }
591: }
592:
593: if (getuid()!=geteuid()) {
594: error(1,0,
595: _("this program was never intended to be used setuid\n"));
596: }
597: zsendline_init();
598:
599: if (start_blklen==0) {
600: if (protocol == ZM_ZMODEM) {
601: start_blklen=1024;
602: if (Tframlen) {
603: start_blklen=max_blklen=Tframlen;
604: }
605: }
606: else
607: start_blklen=128;
608: }
609:
610: if (argc<2)
611: usage(2,_("need at least one file to send"));
612:
613: if (startup_delay)
614: sleep(startup_delay);
615:
616: #ifdef HAVE_SIGINTERRUPT
617: /* we want interrupted system calls to fail and not to be restarted. */
618: siginterrupt(SIGALRM,1);
619: #endif
620:
621:
622: npats = argc - optind;
623: patts=&argv[optind];
624:
625: if (npats < 1 && !command_mode)
626: usage(2,_("need at least one file to send"));
627: if (command_mode && Restricted) {
628: printf(_("Can't send command in restricted mode\n"));
629: exit(1);
630: }
631:
632: if (Fromcu && !Quiet) {
633: if (Verbose == 0)
634: Verbose = 2;
635: }
636: vfile("%s %s\n", program_name, VERSION);
637:
638: if (tcp_flag==2) {
639: char buf[256];
640: #ifdef MAXHOSTNAMELEN
641: char hn[MAXHOSTNAMELEN];
642: #else
643: char hn[256];
644: #endif
645: char *p,*q;
646: int d;
647:
648: /* tell receiver to receive via tcp */
649: d=tcp_server(buf);
650: p=strchr(buf+1,'<');
651: p++;
652: q=strchr(p,'>');
653: *q=0;
654: if (gethostname(hn,sizeof(hn))==-1) {
655: error(1,0, _("hostname too long\n"));
656: }
657: fprintf(stdout,"connect with lrz --tcp-client \"%s:%s\"\n",hn,p);
658: fflush(stdout);
659: /* ok, now that this file is sent we can switch to tcp */
660:
661: tcp_socket=tcp_accept(d);
662: dup2(tcp_socket,0);
663: dup2(tcp_socket,1);
664: }
665: if (tcp_flag==3) {
666: char buf[256];
667: char *p;
668: p=strchr(tcp_server_address,':');
669: if (!p)
670: error(1,0, _("illegal server address\n"));
671: *p++=0;
672: sprintf(buf,"[%s] <%s>\n",tcp_server_address,p);
673:
674: fprintf(stdout,"connecting to %s\n",buf);
675: fflush(stdout);
676:
677: /* we need to switch to tcp mode */
678: tcp_socket=tcp_connect(buf);
679: dup2(tcp_socket,0);
680: dup2(tcp_socket,1);
681: }
682:
683:
684: {
685: /* we write max_blocklen (data) + 18 (ZModem protocol overhead)
686: * + escape overhead (about 4 %), so buffer has to be
687: * somewhat larger than max_blklen
688: */
689: char *s=malloc(max_blklen+1024);
690: if (!s)
691: {
692: zperr(_("out of memory"));
693: exit(1);
694: }
695: #ifdef SETVBUF_REVERSED
696: setvbuf(stdout,_IOFBF,s,max_blklen+1024);
697: #else
698: setvbuf(stdout,s,_IOFBF,max_blklen+1024);
699: #endif
700: }
701: blklen=start_blklen;
702:
703: for (i=optind,stdin_files=0;i<argc;i++) {
704: if (0==strcmp(argv[i],"-"))
705: stdin_files++;
706: }
707:
708: if (stdin_files>1) {
709: usage(1,_("can read only one file from stdin"));
710: } else if (stdin_files==1) {
711: io_mode_fd=1;
712: }
713: io_mode(io_mode_fd,1);
714: readline_setup(io_mode_fd, 128, 256);
715:
716: if (signal(SIGINT, bibi) == SIG_IGN)
717: signal(SIGINT, SIG_IGN);
718: else {
719: signal(SIGINT, bibi);
720: play_with_sigint=1;
721: }
722: signal(SIGTERM, bibi);
723: signal(SIGPIPE, bibi);
724: signal(SIGHUP, bibi);
725:
726: if ( protocol!=ZM_XMODEM) {
727: if (protocol==ZM_ZMODEM) {
728: printf("rz\r");
729: fflush(stdout);
730: }
731: countem(npats, patts);
732: if (protocol == ZM_ZMODEM) {
733: /* throw away any input already received. This doesn't harm
734: * as we invite the receiver to send it's data again, and
735: * might be useful if the receiver has already died or
736: * if there is dirt left if the line
737: */
738: #ifdef HAVE_SELECT
739: struct timeval t;
740: unsigned char throwaway;
741: fd_set f;
742: #endif
743:
744: purgeline(io_mode_fd);
745:
746: #ifdef HAVE_SELECT
747: t.tv_sec = 0;
748: t.tv_usec = 0;
749:
750: FD_ZERO(&f);
751: FD_SET(io_mode_fd,&f);
752:
753: while (select(1,&f,NULL,NULL,&t)) {
754: if (0==read(io_mode_fd,&throwaway,1)) /* EOF ... */
755: break;
756: }
757: #endif
758:
759: purgeline(io_mode_fd);
760: stohdr(0L);
761: if (command_mode)
762: Txhdr[ZF0] = ZCOMMAND;
763: zshhdr(ZRQINIT, Txhdr);
764: zrqinits_sent++;
765: #if defined(ENABLE_TIMESYNC)
766: if (Rxflags2 != ZF1_TIMESYNC)
767: /* disable timesync if there are any flags we don't know.
768: * dsz/gsz seems to use some other flags! */
769: enable_timesync=FALSE;
770: if (Rxflags2 & ZF1_TIMESYNC && enable_timesync) {
771: Totalleft+=6; /* TIMESYNC never needs more */
772: Filesleft++;
773: }
774: #endif
775: if (tcp_flag==1) {
776: Totalleft+=256; /* tcp never needs more */
777: Filesleft++;
778: }
779: }
780: }
781: fflush(stdout);
782:
783: if (Cmdstr) {
784: if (getzrxinit()) {
785: Exitcode=0200; canit(STDOUT_FILENO);
786: }
787: else if (zsendcmd(Cmdstr, strlen(Cmdstr)+1)) {
788: Exitcode=0200; canit(STDOUT_FILENO);
789: }
790: } else if (wcsend(npats, patts)==ERROR) {
791: Exitcode=0200;
792: canit(STDOUT_FILENO);
793: }
794: fflush(stdout);
795: io_mode(io_mode_fd,0);
796: if (Exitcode)
797: dm=Exitcode;
798: else if (errcnt)
799: dm=1;
800: else
801: dm=0;
802: if (Verbose)
803: {
804: fputs("\r\n",stderr);
805: if (dm)
806: fputs(_("Transfer incomplete\n"),stderr);
807: else
808: fputs(_("Transfer complete\n"),stderr);
809: }
810: exit(dm);
811: /*NOTREACHED*/
812: }
813:
814: static int
815: send_pseudo(const char *name, const char *data)
816: {
817: char *tmp;
818: const char *p;
819: int ret=0; /* ok */
820: size_t plen;
821: int fd;
822: int lfd;
823:
824: p = getenv ("TMPDIR");
825: if (!p)
826: p = getenv ("TMP");
827: if (!p)
828: p = "/tmp";
829: tmp=malloc(PATH_MAX+1);
830: if (!tmp)
831: error(1,0,_("out of memory"));
832:
833: plen=strlen(p);
834: memcpy(tmp,p,plen);
835: tmp[plen++]='/';
836:
837: lfd=0;
838: do {
839: if (lfd++==10) {
840: free(tmp);
841: vstringf (_ ("send_pseudo %s: cannot open tmpfile %s: %s"),
842: name, tmp, strerror (errno));
843: vstring ("\r\n");
844: return 1;
845: }
846: sprintf(tmp+plen,"%s.%lu.%d",name,(unsigned long) getpid(),lfd);
847: fd=open(tmp,O_WRONLY|O_CREAT|O_EXCL,0700);
848: /* is O_EXCL guaranted to not follow symlinks?
849: * I don`t know ... so be careful
850: */
851: if (fd!=-1) {
852: struct stat st;
853: if (0!=lstat(tmp,&st)) {
854: vstringf (_ ("send_pseudo %s: cannot lstat tmpfile %s: %s"),
855: name, tmp, strerror (errno));
856: vstring ("\r\n");
857: unlink(tmp);
858: close(fd);
859: fd=-1;
860: } else {
861: if (S_ISLNK(st.st_mode)) {
862: vstringf (_ ("send_pseudo %s: avoiding symlink trap"),name);
863: vstring ("\r\n");
864: unlink(tmp);
865: close(fd);
866: fd=-1;
867: }
868: }
869: }
870: } while (fd==-1);
871: if (write(fd,data,strlen(data))!=(signed long) strlen(data)
872: || close(fd)!=0) {
873: vstringf (_ ("send_pseudo %s: cannot write to tmpfile %s: %s"),
874: name, tmp, strerror (errno));
875: vstring ("\r\n");
876: free(tmp);
877: return 1;
878: }
879:
880: if (wcs (tmp,name) == ERROR) {
881: if (Verbose)
882: vstringf (_ ("send_pseudo %s: failed"),name);
883: else {
884: if (Verbose)
885: vstringf (_ ("send_pseudo %s: ok"),name);
886: Filcnt--;
887: }
888: vstring ("\r\n");
889: ret=1;
890: }
891: unlink (tmp);
892: free(tmp);
893: return ret;
894: }
895:
896: static int
897: wcsend (int argc, char *argp[])
898: {
899: int n;
900:
901: Crcflg = FALSE;
902: firstsec = TRUE;
903: bytcnt = (size_t) -1;
904:
905: if (tcp_flag==1) {
906: char buf[256];
907: int d;
908:
909: /* tell receiver to receive via tcp */
910: d=tcp_server(buf);
911: if (send_pseudo("/$tcp$.t",buf)) {
912: error(1,0,_("tcp protocol init failed\n"));
913: }
914: /* ok, now that this file is sent we can switch to tcp */
915:
916: tcp_socket=tcp_accept(d);
917: dup2(tcp_socket,0);
918: dup2(tcp_socket,1);
919: }
920:
921: for (n = 0; n < argc; ++n) {
922: Totsecs = 0;
923: if (wcs (argp[n],NULL) == ERROR)
924: return ERROR;
925: }
926: #if defined(ENABLE_TIMESYNC)
927: if (Rxflags2 & ZF1_TIMESYNC && enable_timesync) {
928: /* implement Peter Mandrellas extension */
929: char buf[60];
930: time_t t = time (NULL);
931: struct tm *tm = localtime (&t); /* sets timezone */
932: strftime (buf, sizeof (buf) - 1, "%H:%M:%S", tm);
933: if (Verbose) {
934: vstring ("\r\n");
935: vstringf (_("Answering TIMESYNC at %s"),buf);
936: }
937: #if defined(HAVE_TIMEZONE_VAR)
938: sprintf(buf+strlen(buf),"%ld\r\n", timezone / 60);
939: if (Verbose)
940: vstringf (" (%s %ld)\r\n", _ ("timezone"), timezone / 60);
941: #else
942: if (Verbose)
943: vstringf (" (%s)\r\n", _ ("timezone unknown"));
944: #endif
945: send_pseudo("/$time$.t",buf);
946: }
947: #endif
948: Totsecs = 0;
949: if (Filcnt == 0) { /* bitch if we couldn't open ANY files */
950: #if 0
951: /* i *really* do not like this */
952: if (protocol != ZM_XMODEM) {
953: const char *Cmdstr; /* Pointer to the command string */
954: command_mode = TRUE;
955: Cmdstr = "echo \"lsz: Can't open any requested files\"";
956: if (getnak ()) {
957: Exitcode = 0200;
958: canit(STDOUT_FILENO);
959: }
960: if (!zmodem_requested)
961: canit(STDOUT_FILENO);
962: else if (zsendcmd (Cmdstr, 1 + strlen (Cmdstr))) {
963: Exitcode = 0200;
964: canit(STDOUT_FILENO);
965: }
966: Exitcode = 1;
967: return OK;
968: }
969: #endif
970: canit(STDOUT_FILENO);
971: vstring ("\r\n");
972: vstringf (_ ("Can't open any requested files."));
973: vstring ("\r\n");
974: return ERROR;
975: }
976: if (zmodem_requested)
977: saybibi ();
978: else if (protocol != ZM_XMODEM) {
979: struct zm_fileinfo zi;
980: char *pa;
981: pa=alloca(PATH_MAX+1);
982: *pa='\0';
983: zi.fname = pa;
984: zi.modtime = 0;
985: zi.mode = 0;
986: zi.bytes_total = 0;
987: zi.bytes_sent = 0;
988: zi.bytes_received = 0;
989: zi.bytes_skipped = 0;
990: wctxpn (&zi);
991: }
992: return OK;
993: }
994:
995: static int
996: wcs(const char *oname, const char *remotename)
997: {
998: #if !defined(S_ISDIR)
999: int c;
1000: #endif
1001: struct stat f;
1002: char *name;
1003: struct zm_fileinfo zi;
1004: #ifdef HAVE_MMAP
1005: int dont_mmap_this=0;
1006: #endif
1007: #ifdef ENABLE_SYSLOG
1008: const char *shortname;
1009: shortname=strrchr(oname,'/');
1010: if (shortname)
1011: shortname++;
1012: else
1013: shortname=oname;
1014: #endif
1015:
1016:
1017: if (Restricted) {
1018: /* restrict pathnames to current tree or uucppublic */
1019: if ( strstr(oname, "../")
1020: #ifdef PUBDIR
1021: || (oname[0]== '/' && strncmp(oname, MK_STRING(PUBDIR),
1022: strlen(MK_STRING(PUBDIR))))
1023: #endif
1024: ) {
1025: canit(STDOUT_FILENO);
1026: vchar('\r');
1027: error(1,0,
1028: _("security violation: not allowed to upload from %s"),oname);
1029: }
1030: }
1031:
1032: if (0==strcmp(oname,"-")) {
1033: char *p=getenv("ONAME");
1034: name=alloca(PATH_MAX+1);
1035: if (p) {
1036: strcpy(name, p);
1037: } else {
1038: sprintf(name, "s%lu.lsz", (unsigned long) getpid());
1039: }
1040: input_f=stdin;
1041: #ifdef HAVE_MMAP
1042: dont_mmap_this=1;
1043: #endif
1044: } else if ((input_f=fopen(oname, "r"))==NULL) {
1045: int e=errno;
1046: error(0,e, _("cannot open %s"),oname);
1047: ++errcnt;
1048: return OK; /* pass over it, there may be others */
1049: } else {
1050: name=alloca(PATH_MAX+1);
1051: strcpy(name, oname);
1052: }
1053: #ifdef HAVE_MMAP
1054: if (!use_mmap || dont_mmap_this)
1055: #endif
1056: {
1057: static char *s=NULL;
1058: static size_t last_length=0;
1059: struct stat st;
1060: if (fstat(fileno(input_f),&st)==-1)
1061: st.st_size=1024*1024;
1062: if (buffersize==(size_t) -1 && s) {
1063: if ((size_t) st.st_size > last_length) {
1064: free(s);
1065: s=NULL;
1066: last_length=0;
1067: }
1068: }
1069: if (!s && buffersize) {
1070: last_length=16384;
1071: if (buffersize==(size_t) -1) {
1072: if (st.st_size>0)
1073: last_length=st.st_size;
1074: } else
1075: last_length=buffersize;
1076: /* buffer whole pages */
1077: last_length=(last_length+4095)&0xfffff000;
1078: s=malloc(last_length);
1079: if (!s) {
1080: zpfatal(_("out of memory"));
1081: exit(1);
1082: }
1083: }
1084: if (s) {
1085: #ifdef SETVBUF_REVERSED
1086: setvbuf(input_f,_IOFBF,s,last_length);
1087: #else
1088: setvbuf(input_f,s,_IOFBF,last_length);
1089: #endif
1090: }
1091: }
1092: vpos = 0;
1093: /* Check for directory or block special files */
1094: fstat(fileno(input_f), &f);
1095: #if defined(S_ISDIR)
1096: if (S_ISDIR(f.st_mode) || S_ISBLK(f.st_mode)) {
1097: #else
1098: c = f.st_mode & S_IFMT;
1099: if (c == S_IFDIR || c == S_IFBLK) {
1100: #endif
1101: error(0,0, _("is not a file: %s"),name);
1102: fclose(input_f);
1103: return OK;
1104: }
1105:
1106: if (remotename) {
1107: /* disqualify const */
1108: union {
1109: const char *c;
1110: char *s;
1111: } cheat;
1112: cheat.c=remotename;
1113: zi.fname=cheat.s;
1114: } else
1115: zi.fname=name;
1116: zi.modtime=f.st_mtime;
1117: zi.mode=f.st_mode;
1118: #if defined(S_ISFIFO)
1119: zi.bytes_total= (S_ISFIFO(f.st_mode)) ? DEFBYTL : f.st_size;
1120: #else
1121: zi.bytes_total= c == S_IFIFO ? DEFBYTL : f.st_size;
1122: #endif
1123: zi.bytes_sent=0;
1124: zi.bytes_received=0;
1125: zi.bytes_skipped=0;
1126: zi.eof_seen=0;
1127: timing(1,NULL);
1128:
1129: ++Filcnt;
1130: switch (wctxpn(&zi)) {
1131: case ERROR:
1132: #ifdef ENABLE_SYSLOG
1133: if (enable_syslog)
1134: lsyslog(LOG_INFO, _("%s/%s: error occured"),protname(),shortname);
1135: #endif
1136: return ERROR;
1137: case ZSKIP:
1138: error(0,0, _("skipped: %s"),name);
1139: #ifdef ENABLE_SYSLOG
1140: if (enable_syslog)
1141: lsyslog(LOG_INFO, _("%s/%s: skipped"),protname(),shortname);
1142: #endif
1143: return OK;
1144: }
1145: if (!zmodem_requested && wctx(&zi)==ERROR)
1146: {
1147: #ifdef ENABLE_SYSLOG
1148: if (enable_syslog)
1149: lsyslog(LOG_INFO, _("%s/%s: error occured"),protname(),shortname);
1150: #endif
1151: return ERROR;
1152: }
1153: if (Unlinkafter)
1154: unlink(oname);
1155:
1156: if (Verbose > 1
1157: #ifdef ENABLE_SYSLOG
1158: || enable_syslog
1159: #endif
1160: ) {
1161: long bps;
1162: double d=timing(0,NULL);
1163: if (d==0) /* can happen if timing() uses time() */
1164: d=0.5;
1165: bps=zi.bytes_sent/d;
1166: vchar('\r');
1167: if (Verbose > 1)
1168: vstringf(_("Bytes Sent:%7ld BPS:%-8ld \n"),
1169: (long) zi.bytes_sent,bps);
1170: #ifdef ENABLE_SYSLOG
1171: if (enable_syslog)
1172: lsyslog(LOG_INFO, "%s/%s: %ld Bytes, %ld BPS",shortname,
1173: protname(), (long) zi.bytes_sent,bps);
1174: #endif
1175: }
1176: return 0;
1177: }
1178:
1179: /*
1180: * generate and transmit pathname block consisting of
1181: * pathname (null terminated),
1182: * file length, mode time and file mode in octal
1183: * as provided by the Unix fstat call.
1184: * N.B.: modifies the passed name, may extend it!
1185: */
1186: static int
1187: wctxpn(struct zm_fileinfo *zi)
1188: {
1189: register char *p, *q;
1190: char *name2;
1191: struct stat f;
1192:
1193: name2=alloca(PATH_MAX+1);
1194: f.st_size = 0;
1195:
1196: if (protocol==ZM_XMODEM) {
1197: if (Verbose && *zi->fname && fstat(fileno(input_f), &f)!= -1) {
1198: vstringf(_("Sending %s, %ld blocks: "),
1199: zi->fname, (long) (f.st_size>>7));
1200: }
1201: vstringf(_("Give your local XMODEM receive command now."));
1202: vstring("\r\n");
1203: return OK;
1204: }
1205: if (!zmodem_requested)
1206: if (getnak()) {
1207: vfile("getnak failed");
1208: DO_SYSLOG((LOG_INFO, "%s/%s: getnak failed",
1209: shortname,protname()));
1210: return ERROR;
1211: }
1212:
1213: q = (char *) 0;
1214: if (Dottoslash) { /* change . to . */
1215: for (p=zi->fname; *p; ++p) {
1216: if (*p == '/')
1217: q = p;
1218: else if (*p == '.')
1219: *(q=p) = '/';
1220: }
1221: if (q && strlen(++q) > 8) { /* If name>8 chars */
1222: q += 8; /* make it .ext */
1223: strcpy(name2, q); /* save excess of name */
1224: *q = '.';
1225: strcpy(++q, name2); /* add it back */
1226: }
1227: }
1228:
1229: for (p=zi->fname, q=txbuf ; *p; )
1230: if ((*q++ = *p++) == '/' && !Fullname)
1231: q = txbuf;
1232: *q++ = 0;
1233: p=q;
1234: while (q < (txbuf + MAX_BLOCK))
1235: *q++ = 0;
1236: /* note that we may lose some information here in case mode_t is wider than an
1237: * int. But i believe sending %lo instead of %o _could_ break compatability
1238: */
1239: if (!Ascii && (input_f!=stdin) && *zi->fname && fstat(fileno(input_f), &f)!= -1)
1240: sprintf(p, "%lu %lo %o 0 %d %ld", (long) f.st_size, f.st_mtime,
1241: (unsigned int)((no_unixmode) ? 0 : f.st_mode),
1242: Filesleft, Totalleft);
1243: if (Verbose)
1244: vstringf(_("Sending: %s\n"),txbuf);
1245: Totalleft -= f.st_size;
1246: if (--Filesleft <= 0)
1247: Totalleft = 0;
1248: if (Totalleft < 0)
1249: Totalleft = 0;
1250:
1251: /* force 1k blocks if name won't fit in 128 byte block */
1252: if (txbuf[125])
1253: blklen=1024;
1254: else { /* A little goodie for IMP/KMD */
1255: txbuf[127] = (f.st_size + 127) >>7;
1256: txbuf[126] = (f.st_size + 127) >>15;
1257: }
1258: if (zmodem_requested)
1259: return zsendfile(zi,txbuf, 1+strlen(p)+(p-txbuf));
1260: if (wcputsec(txbuf, 0, 128)==ERROR) {
1261: vfile("wcputsec failed");
1262: DO_SYSLOG((LOG_INFO, "%s/%s: wcputsec failed",
1263: shortname,protname()));
1264: return ERROR;
1265: }
1266: return OK;
1267: }
1268:
1269: static int
1270: getnak(void)
1271: {
1272: int firstch;
1273: int tries=0;
1274:
1275: Lastrx = 0;
1276: for (;;) {
1277: tries++;
1278: switch (firstch = READLINE_PF(100)) {
1279: case ZPAD:
1280: if (getzrxinit())
1281: return ERROR;
1282: Ascii = 0; /* Receiver does the conversion */
1283: return FALSE;
1284: case TIMEOUT:
1285: /* 30 seconds are enough */
1286: if (tries==3) {
1287: zperr(_("Timeout on pathname"));
1288: return TRUE;
1289: }
1290: /* don't send a second ZRQINIT _directly_ after the
1291: * first one. Never send more then 4 ZRQINIT, because
1292: * omen rz stops if it saw 5 of them */
1293: if ((zrqinits_sent>1 || tries>1) && zrqinits_sent<4) {
1294: /* if we already sent a ZRQINIT we are using zmodem
1295: * protocol and may send further ZRQINITs
1296: */
1297: stohdr(0L);
1298: zshhdr(ZRQINIT, Txhdr);
1299: zrqinits_sent++;
1300: }
1301: continue;
1302: case WANTG:
1303: io_mode(io_mode_fd,2); /* Set cbreak, XON/XOFF, etc. */
1304: Optiong = TRUE;
1305: blklen=1024;
1306: case WANTCRC:
1307: Crcflg = TRUE;
1308: case NAK:
1309: return FALSE;
1310: case CAN:
1311: if ((firstch = READLINE_PF(20)) == CAN && Lastrx == CAN)
1312: return TRUE;
1313: default:
1314: break;
1315: }
1316: Lastrx = firstch;
1317: }
1318: }
1319:
1320:
1321: static int
1322: wctx(struct zm_fileinfo *zi)
1323: {
1324: register size_t thisblklen;
1325: register int sectnum, attempts, firstch;
1326:
1327: firstsec=TRUE; thisblklen = blklen;
1328: vfile("wctx:file length=%ld", (long) zi->bytes_total);
1329:
1330: while ((firstch=READLINE_PF(Rxtimeout))!=NAK && firstch != WANTCRC
1331: && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN)
1332: ;
1333: if (firstch==CAN) {
1334: zperr(_("Receiver Cancelled"));
1335: return ERROR;
1336: }
1337: if (firstch==WANTCRC)
1338: Crcflg=TRUE;
1339: if (firstch==WANTG)
1340: Crcflg=TRUE;
1341: sectnum=0;
1342: for (;;) {
1343: if (zi->bytes_total <= (zi->bytes_sent + 896L))
1344: thisblklen = 128;
1345: if ( !filbuf(txbuf, thisblklen))
1346: break;
1347: if (wcputsec(txbuf, ++sectnum, thisblklen)==ERROR)
1348: return ERROR;
1349: zi->bytes_sent += thisblklen;
1350: }
1351: fclose(input_f);
1352: attempts=0;
1353: do {
1354: purgeline(io_mode_fd);
1355: sendline(EOT);
1356: flushmo();
1357: ++attempts;
1358: } while ((firstch=(READLINE_PF(Rxtimeout)) != ACK) && attempts < RETRYMAX);
1359: if (attempts == RETRYMAX) {
1360: zperr(_("No ACK on EOT"));
1361: return ERROR;
1362: }
1363: else
1364: return OK;
1365: }
1366:
1367: static int
1368: wcputsec(char *buf, int sectnum, size_t cseclen)
1369: {
1370: int checksum, wcj;
1371: char *cp;
1372: unsigned oldcrc;
1373: int firstch;
1374: int attempts;
1375:
1376: firstch=0; /* part of logic to detect CAN CAN */
1377:
1378: if (Verbose>1) {
1379: vchar('\r');
1380: if (protocol==ZM_XMODEM) {
1381: vstringf(_("Xmodem sectors/kbytes sent: %3d/%2dk"), Totsecs, Totsecs/8 );
1382: } else {
1383: vstringf(_("Ymodem sectors/kbytes sent: %3d/%2dk"), Totsecs, Totsecs/8 );
1384: }
1385: }
1386: for (attempts=0; attempts <= RETRYMAX; attempts++) {
1387: Lastrx= firstch;
1388: sendline(cseclen==1024?STX:SOH);
1389: sendline(sectnum);
1390: sendline(-sectnum -1);
1391: oldcrc=checksum=0;
1392: for (wcj=cseclen,cp=buf; --wcj>=0; ) {
1393: sendline(*cp);
1394: oldcrc=updcrc((0377& *cp), oldcrc);
1395: checksum += *cp++;
1396: }
1397: if (Crcflg) {
1398: oldcrc=updcrc(0,updcrc(0,oldcrc));
1399: sendline((int)oldcrc>>8);
1400: sendline((int)oldcrc);
1401: }
1402: else
1403: sendline(checksum);
1404:
1405: flushmo();
1406: if (Optiong) {
1407: firstsec = FALSE; return OK;
1408: }
1409: firstch = READLINE_PF(Rxtimeout);
1410: gotnak:
1411: switch (firstch) {
1412: case CAN:
1413: if(Lastrx == CAN) {
1414: cancan:
1415: zperr(_("Cancelled")); return ERROR;
1416: }
1417: break;
1418: case TIMEOUT:
1419: zperr(_("Timeout on sector ACK")); continue;
1420: case WANTCRC:
1421: if (firstsec)
1422: Crcflg = TRUE;
1423: case NAK:
1424: zperr(_("NAK on sector")); continue;
1425: case ACK:
1426: firstsec=FALSE;
1427: Totsecs += (cseclen>>7);
1428: return OK;
1429: case ERROR:
1430: zperr(_("Got burst for sector ACK")); break;
1431: default:
1432: zperr(_("Got %02x for sector ACK"), firstch); break;
1433: }
1434: for (;;) {
1435: Lastrx = firstch;
1436: if ((firstch = READLINE_PF(Rxtimeout)) == TIMEOUT)
1437: break;
1438: if (firstch == NAK || firstch == WANTCRC)
1439: goto gotnak;
1440: if (firstch == CAN && Lastrx == CAN)
1441: goto cancan;
1442: }
1443: }
1444: zperr(_("Retry Count Exceeded"));
1445: return ERROR;
1446: }
1447:
1448: /* fill buf with count chars padding with ^Z for CPM */
1449: static size_t
1450: filbuf(char *buf, size_t count)
1451: {
1452: int c;
1453: size_t m;
1454:
1455: if ( !Ascii) {
1456: m = read(fileno(input_f), buf, count);
1457: if (m <= 0)
1458: return 0;
1459: while (m < count)
1460: buf[m++] = 032;
1461: return count;
1462: }
1463: m=count;
1464: if (Lfseen) {
1465: *buf++ = 012; --m; Lfseen = 0;
1466: }
1467: while ((c=getc(input_f))!=EOF) {
1468: if (c == 012) {
1469: *buf++ = 015;
1470: if (--m == 0) {
1471: Lfseen = TRUE; break;
1472: }
1473: }
1474: *buf++ =c;
1475: if (--m == 0)
1476: break;
1477: }
1478: if (m==count)
1479: return 0;
1480: else
1481: while (m--!=0)
1482: *buf++ = CPMEOF;
1483: return count;
1484: }
1485:
1486: /* Fill buffer with blklen chars */
1487: static size_t
1488: zfilbuf (struct zm_fileinfo *zi)
1489: {
1490: size_t n;
1491:
1492: n = fread (txbuf, 1, blklen, input_f);
1493: if (n < blklen)
1494: zi->eof_seen = 1;
1495: else {
1496: /* save one empty paket in case file ends ob blklen boundary */
1497: int c = getc(input_f);
1498:
1499: if (c != EOF || !feof(input_f))
1500: ungetc(c, input_f);
1501: else
1502: zi->eof_seen = 1;
1503: }
1504: return n;
1505: }
1506:
1507: static void
1508: usage1 (int exitcode)
1509: {
1510: usage (exitcode, NULL);
1511: }
1512:
1513: static void
1514: usage(int exitcode, const char *what)
1515: {
1516: FILE *f=stdout;
1517:
1518: if (exitcode)
1519: {
1520: if (what)
1521: fprintf(stderr, "%s: %s\n",program_name,what);
1522: fprintf (stderr, _("Try `%s --help' for more information.\n"),
1523: program_name);
1524: exit(exitcode);
1525: }
1526:
1527: fprintf(f, _("%s version %s\n"), program_name,
1528: VERSION);
1529:
1530: fprintf(f,_("Usage: %s [options] file ...\n"),
1531: program_name);
1532: fprintf(f,_(" or: %s [options] -{c|i} COMMAND\n"),program_name);
1533: fputs(_("Send file(s) with ZMODEM/YMODEM/XMODEM protocol\n"),f);
1534: fputs(_(
1535: " (X) = option applies to XMODEM only\n"
1536: " (Y) = option applies to YMODEM only\n"
1537: " (Z) = option applies to ZMODEM only\n"
1538: ),f);
1539: /* splitted into two halves for really bad compilers */
1540: fputs(_(
1541: " -+, --append append to existing destination file (Z)\n"
1542: " -2, --twostop use 2 stop bits\n"
1543: " -4, --try-4k go up to 4K blocksize\n"
1544: " --start-4k start with 4K blocksize (doesn't try 8)\n"
1545: " -8, --try-8k go up to 8K blocksize\n"
1546: " --start-8k start with 8K blocksize\n"
1547: " -a, --ascii ASCII transfer (change CR/LF to LF)\n"
1548: " -b, --binary binary transfer\n"
1549: " -B, --bufsize N buffer N bytes (N==auto: buffer whole file)\n"
1550: " -c, --command COMMAND execute remote command COMMAND (Z)\n"
1551: " -C, --command-tries N try N times to execute a command (Z)\n"
1552: " -d, --dot-to-slash change '.' to '/' in pathnames (Y/Z)\n"
1553: " --delay-startup N sleep N seconds before doing anything\n"
1554: " -e, --escape escape all control characters (Z)\n"
1555: " -E, --rename force receiver to rename files it already has\n"
1556: " -f, --full-path send full pathname (Y/Z)\n"
1557: " -i, --immediate-command CMD send remote CMD, return immediately (Z)\n"
1558: " -h, --help print this usage message\n"
1559: " -k, --1k send 1024 byte packets (X)\n"
1560: " -L, --packetlen N limit subpacket length to N bytes (Z)\n"
1561: " -l, --framelen N limit frame length to N bytes (l>=L) (Z)\n"
1562: " -m, --min-bps N stop transmission if BPS below N\n"
1563: " -M, --min-bps-time N for at least N seconds (default: 120)\n"
1564: ),f);
1565: fputs(_(
1566: " -n, --newer send file if source newer (Z)\n"
1567: " -N, --newer-or-longer send file if source newer or longer (Z)\n"
1568: " -o, --16-bit-crc use 16 bit CRC instead of 32 bit CRC (Z)\n"
1569: " -O, --disable-timeouts disable timeout code, wait forever\n"
1570: " -p, --protect protect existing destination file (Z)\n"
1571: " -r, --resume resume interrupted file transfer (Z)\n"
1572: " -R, --restricted restricted, more secure mode\n"
1573: " -q, --quiet quiet (no progress reports)\n"
1574: " -s, --stop-at {HH:MM|+N} stop transmission at HH:MM or in N seconds\n"
1575: " --tcp build a TCP connection to transmit files\n"
1576: " --tcp-server open socket, wait for connection\n"
1577: " -u, --unlink unlink file after transmission\n"
1578: " -U, --unrestrict turn off restricted mode (if allowed to)\n"
1579: " -v, --verbose be verbose, provide debugging information\n"
1580: " -w, --windowsize N Window is N bytes (Z)\n"
1581: " -X, --xmodem use XMODEM protocol\n"
1582: " -y, --overwrite overwrite existing files\n"
1583: " -Y, --overwrite-or-skip overwrite existing files, else skip\n"
1584: " --ymodem use YMODEM protocol\n"
1585: " -Z, --zmodem use ZMODEM protocol\n"
1586: "\n"
1587: "short options use the same arguments as the long ones\n"
1588: ),f);
1589: exit(exitcode);
1590: }
1591:
1592: /*
1593: * Get the receiver's init parameters
1594: */
1595: static int
1596: getzrxinit(void)
1597: {
1598: static int dont_send_zrqinit=1;
1599: int old_timeout=Rxtimeout;
1600: int n;
1601: struct stat f;
1602: size_t rxpos;
1603: int timeouts=0;
1604:
1605: Rxtimeout=100; /* 10 seconds */
1606: /* XXX purgeline(io_mode_fd); this makes _real_ trouble. why? -- uwe */
1607:
1608: for (n=10; --n>=0; ) {
1609: /* we might need to send another zrqinit in case the first is
1610: * lost. But *not* if getting here for the first time - in
1611: * this case we might just get a ZRINIT for our first ZRQINIT.
1612: * Never send more then 4 ZRQINIT, because
1613: * omen rz stops if it saw 5 of them.
1614: */
1615: if (zrqinits_sent<4 && n!=10 && !dont_send_zrqinit) {
1616: zrqinits_sent++;
1617: stohdr(0L);
1618: zshhdr(ZRQINIT, Txhdr);
1619: }
1620: dont_send_zrqinit=0;
1621:
1622: switch (zgethdr(Rxhdr, 1,&rxpos)) {
1623: case ZCHALLENGE: /* Echo receiver's challenge numbr */
1624: stohdr(rxpos);
1625: zshhdr(ZACK, Txhdr);
1626: continue;
1627: case ZCOMMAND: /* They didn't see our ZRQINIT */
1628: /* ??? Since when does a receiver send ZCOMMAND? -- uwe */
1629: continue;
1630: case ZRINIT:
1631: Rxflags = 0377 & Rxhdr[ZF0];
1632: Rxflags2 = 0377 & Rxhdr[ZF1];
1633: Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
1634: {
1635: int old=Zctlesc;
1636: Zctlesc |= Rxflags & TESCCTL;
1637: /* update table - was initialised to not escape */
1638: if (Zctlesc && !old)
1639: zsendline_init();
1640: }
1641: Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
1642: if ( !(Rxflags & CANFDX))
1643: Txwindow = 0;
1644: vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen);
1645: if ( play_with_sigint)
1646: signal(SIGINT, SIG_IGN);
1647: io_mode(io_mode_fd,2); /* Set cbreak, XON/XOFF, etc. */
1648: #ifndef READCHECK
1649: /* Use MAX_BLOCK byte frames if no sample/interrupt */
1650: if (Rxbuflen < 32 || Rxbuflen > MAX_BLOCK) {
1651: Rxbuflen = MAX_BLOCK;
1652: vfile("Rxbuflen=%d", Rxbuflen);
1653: }
1654: #endif
1655: /* Override to force shorter frame length */
1656: if (Tframlen && Rxbuflen > Tframlen)
1657: Rxbuflen = Tframlen;
1658: if ( !Rxbuflen)
1659: Rxbuflen = 1024;
1660: vfile("Rxbuflen=%d", Rxbuflen);
1661:
1662: /* If using a pipe for testing set lower buf len */
1663: fstat(0, &f);
1664: #if defined(S_ISCHR)
1665: if (! (S_ISCHR(f.st_mode))) {
1666: #else
1667: if ((f.st_mode & S_IFMT) != S_IFCHR) {
1668: #endif
1669: Rxbuflen = MAX_BLOCK;
1670: }
1671: /*
1672: * If input is not a regular file, force ACK's to
1673: * prevent running beyond the buffer limits
1674: */
1675: if ( !command_mode) {
1676: fstat(fileno(input_f), &f);
1677: #if defined(S_ISREG)
1678: if (!(S_ISREG(f.st_mode))) {
1679: #else
1680: if ((f.st_mode & S_IFMT) != S_IFREG) {
1681: #endif
1682: Canseek = -1;
1683: /* return ERROR; */
1684: }
1685: }
1686: /* Set initial subpacket length */
1687: if (blklen < 1024) { /* Command line override? */
1688: if (Baudrate > 300)
1689: blklen = 256;
1690: if (Baudrate > 1200)
1691: blklen = 512;
1692: if (Baudrate > 2400)
1693: blklen = 1024;
1694: }
1695: if (Rxbuflen && blklen>Rxbuflen)
1696: blklen = Rxbuflen;
1697: if (blkopt && blklen > blkopt)
1698: blklen = blkopt;
1699: vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen);
1700: vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac);
1701: Rxtimeout=old_timeout;
1702: return (sendzsinit());
1703: case ZCAN:
1704: case TIMEOUT:
1705: if (timeouts++==0)
1706: continue; /* force one other ZRQINIT to be sent */
1707: return ERROR;
1708: case ZRQINIT:
1709: if (Rxhdr[ZF0] == ZCOMMAND)
1710: continue;
1711: default:
1712: zshhdr(ZNAK, Txhdr);
1713: continue;
1714: }
1715: }
1716: return ERROR;
1717: }
1718:
1719: /* Send send-init information */
1720: static int
1721: sendzsinit(void)
1722: {
1723: int c;
1724:
1725: if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL)))
1726: return OK;
1727: errors = 0;
1728: for (;;) {
1729: stohdr(0L);
1730: if (Zctlesc) {
1731: Txhdr[ZF0] |= TESCCTL; zshhdr(ZSINIT, Txhdr);
1732: }
1733: else
1734: zsbhdr(ZSINIT, Txhdr);
1735: ZSDATA(Myattn, 1+strlen(Myattn), ZCRCW);
1736: c = zgethdr(Rxhdr, 1,NULL);
1737: switch (c) {
1738: case ZCAN:
1739: return ERROR;
1740: case ZACK:
1741: return OK;
1742: default:
1743: if (++errors > 19)
1744: return ERROR;
1745: continue;
1746: }
1747: }
1748: }
1749:
1750: /* Send file name and related info */
1751: static int
1752: zsendfile(struct zm_fileinfo *zi, const char *buf, size_t blen)
1753: {
1754: int c;
1755: unsigned long crc;
1756: size_t rxpos;
1757:
1758: /* we are going to send a ZFILE. There cannot be much useful
1759: * stuff in the line right now (*except* ZCAN?).
1760: */
1761: #if 0
1762: purgeline(io_mode_fd); /* might possibly fix stefan glasers problems */
1763: #endif
1764:
1765: for (;;) {
1766: Txhdr[ZF0] = Lzconv; /* file conversion request */
1767: Txhdr[ZF1] = Lzmanag; /* file management request */
1768: if (Lskipnocor)
1769: Txhdr[ZF1] |= ZF1_ZMSKNOLOC;
1770: Txhdr[ZF2] = Lztrans; /* file transport request */
1771: Txhdr[ZF3] = 0;
1772: zsbhdr(ZFILE, Txhdr);
1773: ZSDATA(buf, blen, ZCRCW);
1774: again:
1775: c = zgethdr(Rxhdr, 1, &rxpos);
1776: switch (c) {
1777: case ZRINIT:
1778: while ((c = READLINE_PF(50)) > 0)
1779: if (c == ZPAD) {
1780: goto again;
1781: }
1782: /* **** FALL THRU TO **** */
1783: default:
1784: continue;
1785: case ZRQINIT: /* remote site is sender! */
1786: if (Verbose)
1787: vstringf(_("got ZRQINIT"));
1788: DO_SYSLOG((LOG_INFO, "%s/%s: got ZRQINIT - sz talks to sz",
1789: shortname,protname()));
1790: return ERROR;
1791: case ZCAN:
1792: if (Verbose)
1793: vstringf(_("got ZCAN"));
1794: DO_SYSLOG((LOG_INFO, "%s/%s: got ZCAN - receiver canceled",
1795: shortname,protname()));
1796: return ERROR;
1797: case TIMEOUT:
1798: DO_SYSLOG((LOG_INFO, "%s/%s: got TIMEOUT",
1799: shortname,protname()));
1800: return ERROR;
1801: case ZABORT:
1802: DO_SYSLOG((LOG_INFO, "%s/%s: got ZABORT",
1803: shortname,protname()));
1804: return ERROR;
1805: case ZFIN:
1806: DO_SYSLOG((LOG_INFO, "%s/%s: got ZFIN",
1807: shortname,protname()));
1808: return ERROR;
1809: case ZCRC:
1810: crc = 0xFFFFFFFFL;
1811: #ifdef HAVE_MMAP
1812: if (use_mmap && !mm_addr)
1813: {
1814: struct stat st;
1815: if (fstat (fileno (input_f), &st) == 0) {
1816: mm_size = st.st_size;
1817: mm_addr = mmap (0, mm_size, PROT_READ,
1818: MAP_SHARED, fileno (input_f), 0);
1819: if ((caddr_t) mm_addr == (caddr_t) - 1)
1820: mm_addr = NULL;
1821: else {
1822: fclose (input_f);
1823: input_f = NULL;
1824: }
1825: }
1826: }
1827: if (mm_addr) {
1828: size_t i;
1829: size_t count;
1830: char *p=mm_addr;
1831: count=(rxpos < mm_size && rxpos > 0)? rxpos: mm_size;
1832: for (i=0;i<count;i++,p++) {
1833: crc = UPDC32(*p, crc);
1834: }
1835: crc = ~crc;
1836: } else
1837: #endif
1838: if (Canseek >= 0) {
1839: if (rxpos==0) {
1840: struct stat st;
1841: if (0==fstat(fileno(input_f),&st)) {
1842: rxpos=st.st_size;
1843: } else
1844: rxpos=-1;
1845: }
1846: while (rxpos-- && ((c = getc(input_f)) != EOF))
1847: crc = UPDC32(c, crc);
1848: crc = ~crc;
1849: clearerr(input_f); /* Clear EOF */
1850: fseek(input_f, 0L, 0);
1851: }
1852: stohdr(crc);
1853: zsbhdr(ZCRC, Txhdr);
1854: goto again;
1855: case ZSKIP:
1856: if (input_f)
1857: fclose(input_f);
1858: #ifdef HAVE_MMAP
1859: else if (mm_addr) {
1860: munmap(mm_addr,mm_size);
1861: mm_addr=NULL;
1862: }
1863: #endif
1864:
1865: vfile("receiver skipped");
1866: DO_SYSLOG((LOG_INFO, "%s/%s: receiver skipped",
1867: shortname, protname()));
1868: return c;
1869: case ZRPOS:
1870: /*
1871: * Suppress zcrcw request otherwise triggered by
1872: * lastsync==bytcnt
1873: */
1874: #ifdef HAVE_MMAP
1875: if (!mm_addr)
1876: #endif
1877: if (rxpos && fseek(input_f, (long) rxpos, 0)) {
1878: int er=errno;
1879: vfile("fseek failed: %s", strerror(er));
1880: DO_SYSLOG((LOG_INFO, "%s/%s: fseek failed: %s",
1881: shortname, protname(), strerror(er)));
1882: return ERROR;
1883: }
1884: if (rxpos)
1885: zi->bytes_skipped=rxpos;
1886: bytcnt = zi->bytes_sent = rxpos;
1887: Lastsync = rxpos -1;
1888: return zsendfdata(zi);
1889: }
1890: }
1891: }
1892:
1893: /* Send the data in the file */
1894: static int
1895: zsendfdata (struct zm_fileinfo *zi)
1896: {
1897: static int c;
1898: int newcnt;
1899: static int junkcount; /* Counts garbage chars received by TX */
1900: static size_t last_txpos = 0;
1901: static long last_bps = 0;
1902: static long not_printed = 0;
1903: static long total_sent = 0;
1904: static time_t low_bps=0;
1905:
1906: #ifdef HAVE_MMAP
1907: if (use_mmap && !mm_addr)
1908: {
1909: struct stat st;
1910: if (fstat (fileno (input_f), &st) == 0) {
1911: mm_size = st.st_size;
1912: mm_addr = mmap (0, mm_size, PROT_READ,
1913: MAP_SHARED, fileno (input_f), 0);
1914: if ((caddr_t) mm_addr == (caddr_t) - 1)
1915: mm_addr = NULL;
1916: else {
1917: fclose (input_f);
1918: input_f = NULL;
1919: }
1920: }
1921: }
1922: #endif
1923:
1924: if (play_with_sigint)
1925: signal (SIGINT, onintr);
1926:
1927: Lrxpos = 0;
1928: junkcount = 0;
1929: Beenhereb4 = 0;
1930: somemore:
1931: if (setjmp (intrjmp)) {
1932: if (play_with_sigint)
1933: signal (SIGINT, onintr);
1934: waitack:
1935: junkcount = 0;
1936: c = getinsync (zi, 0);
1937: gotack:
1938: switch (c) {
1939: default:
1940: if (input_f)
1941: fclose (input_f);
1942: DO_SYSLOG((LOG_INFO, "%s/%s: got %d",
1943: shortname, protname(), c));
1944: return ERROR;
1945: case ZCAN:
1946: if (input_f)
1947: fclose (input_f);
1948: DO_SYSLOG((LOG_INFO, "%s/%s: got ZCAN",
1949: shortname, protname(), c));
1950: return ERROR;
1951: case ZSKIP:
1952: if (input_f)
1953: fclose (input_f);
1954: DO_SYSLOG((LOG_INFO, "%s/%s: got ZSKIP",
1955: shortname, protname(), c));
1956: return c;
1957: case ZACK:
1958: case ZRPOS:
1959: break;
1960: case ZRINIT:
1961: return OK;
1962: }
1963: #ifdef READCHECK
1964: /*
1965: * If the reverse channel can be tested for data,
1966: * this logic may be used to detect error packets
1967: * sent by the receiver, in place of setjmp/longjmp
1968: * rdchk(fdes) returns non 0 if a character is available
1969: */
1970: while (rdchk (io_mode_fd)) {
1971: #ifdef READCHECK_READS
1972: switch (checked)
1973: #else
1974: switch (READLINE_PF (1))
1975: #endif
1976: {
1977: case CAN:
1978: case ZPAD:
1979: c = getinsync (zi, 1);
1980: goto gotack;
1981: case XOFF: /* Wait a while for an XON */
1982: case XOFF | 0200:
1983: READLINE_PF (100);
1984: }
1985: }
1986: #endif
1987: }
1988:
1989: newcnt = Rxbuflen;
1990: Txwcnt = 0;
1991: stohdr (zi->bytes_sent);
1992: zsbhdr (ZDATA, Txhdr);
1993:
1994: do {
1995: size_t n;
1996: int e;
1997: unsigned old = blklen;
1998: blklen = calc_blklen (total_sent);
1999: total_sent += blklen + OVERHEAD;
2000: if (Verbose > 2 && blklen != old)
2001: vstringf (_("blklen now %d\n"), blklen);
2002: #ifdef HAVE_MMAP
2003: if (mm_addr) {
2004: if (zi->bytes_sent + blklen < mm_size)
2005: n = blklen;
2006: else {
2007: n = mm_size - zi->bytes_sent;
2008: zi->eof_seen = 1;
2009: }
2010: } else
2011: #endif
2012: n = zfilbuf (zi);
2013: if (zi->eof_seen) {
2014: e = ZCRCE;
2015: if (Verbose>3)
2016: vstring("e=ZCRCE/eof seen");
2017: } else if (junkcount > 3) {
2018: e = ZCRCW;
2019: if (Verbose>3)
2020: vstring("e=ZCRCW/junkcount > 3");
2021: } else if (bytcnt == Lastsync) {
2022: e = ZCRCW;
2023: if (Verbose>3)
2024: vstringf("e=ZCRCW/bytcnt == Lastsync == %ld",
2025: (unsigned long) Lastsync);
2026: #if 0
2027: /* what is this good for? Rxbuflen/newcnt normally are short - so after
2028: * a few KB ZCRCW will be used? (newcnt is never incremented)
2029: */
2030: } else if (Rxbuflen && (newcnt -= n) <= 0) {
2031: e = ZCRCW;
2032: if (Verbose>3)
2033: vstringf("e=ZCRCW/Rxbuflen(newcnt=%ld,n=%ld)",
2034: (unsigned long) newcnt,(unsigned long) n);
2035: #endif
2036: } else if (Txwindow && (Txwcnt += n) >= Txwspac) {
2037: Txwcnt = 0;
2038: e = ZCRCQ;
2039: if (Verbose>3)
2040: vstring("e=ZCRCQ/Window");
2041: } else {
2042: e = ZCRCG;
2043: if (Verbose>3)
2044: vstring("e=ZCRCG");
2045: }
2046: if ((Verbose > 1 || min_bps || stop_time)
2047: && (not_printed > (min_bps ? 3 : 7)
2048: || zi->bytes_sent > last_bps / 2 + last_txpos)) {
2049: int minleft = 0;
2050: int secleft = 0;
2051: time_t now;
2052: last_bps = (zi->bytes_sent / timing (0,&now));
2053: if (last_bps > 0) {
2054: minleft = (zi->bytes_total - zi->bytes_sent) / last_bps / 60;
2055: secleft = ((zi->bytes_total - zi->bytes_sent) / last_bps) % 60;
2056: }
2057: if (min_bps) {
2058: if (low_bps) {
2059: if (last_bps<min_bps) {
2060: if (now-low_bps>=min_bps_time) {
2061: /* too bad */
2062: if (Verbose) {
2063: vstringf(_("zsendfdata: bps rate %ld below min %ld"),
2064: last_bps, min_bps);
2065: vstring("\r\n");
2066: }
2067: DO_SYSLOG((LOG_INFO, "%s/%s: bps rate low: %ld <%ld",
2068: shortname, protname(), last_bps, min_bps));
2069: return ERROR;
2070: }
2071: } else
2072: low_bps=0;
2073: } else if (last_bps < min_bps) {
2074: low_bps=now;
2075: }
2076: }
2077: if (stop_time && now>=stop_time) {
2078: /* too bad */
2079: if (Verbose) {
2080: vstring(_("zsendfdata: reached stop time"));
2081: vstring("\r\n");
2082: }
2083: DO_SYSLOG((LOG_INFO, "%s/%s: reached stop time",
2084: shortname, protname()));
2085: return ERROR;
2086: }
2087:
2088: if (Verbose > 1) {
2089: vchar ('\r');
2090: vstringf (_("Bytes Sent:%7ld/%7ld BPS:%-8ld ETA %02d:%02d "),
2091: (long) zi->bytes_sent, (long) zi->bytes_total,
2092: last_bps, minleft, secleft);
2093: }
2094: last_txpos = zi->bytes_sent;
2095: } else if (Verbose)
2096: not_printed++;
2097: ZSDATA (DATAADR, n, e);
2098: bytcnt = zi->bytes_sent += n;
2099: if (e == ZCRCW)
2100: goto waitack;
2101: #ifdef READCHECK
2102: /*
2103: * If the reverse channel can be tested for data,
2104: * this logic may be used to detect error packets
2105: * sent by the receiver, in place of setjmp/longjmp
2106: * rdchk(fdes) returns non 0 if a character is available
2107: */
2108: fflush (stdout);
2109: while (rdchk (io_mode_fd)) {
2110: #ifdef READCHECK_READS
2111: switch (checked)
2112: #else
2113: switch (READLINE_PF (1))
2114: #endif
2115: {
2116: case CAN:
2117: case ZPAD:
2118: c = getinsync (zi, 1);
2119: if (c == ZACK)
2120: break;
2121: /* zcrce - dinna wanna starta ping-pong game */
2122: ZSDATA (txbuf, 0, ZCRCE);
2123: goto gotack;
2124: case XOFF: /* Wait a while for an XON */
2125: case XOFF | 0200:
2126: READLINE_PF (100);
2127: default:
2128: ++junkcount;
2129: }
2130: }
2131: #endif /* READCHECK */
2132: if (Txwindow) {
2133: size_t tcount = 0;
2134: while ((tcount = zi->bytes_sent - Lrxpos) >= Txwindow) {
2135: vfile ("%ld (%ld,%ld) window >= %u", tcount,
2136: (long) zi->bytes_sent, (long) Lrxpos,
2137: Txwindow);
2138: if (e != ZCRCQ)
2139: ZSDATA (txbuf, 0, e = ZCRCQ);
2140: c = getinsync (zi, 1);
2141: if (c != ZACK) {
2142: ZSDATA (txbuf, 0, ZCRCE);
2143: goto gotack;
2144: }
2145: }
2146: vfile ("window = %ld", tcount);
2147: }
2148: } while (!zi->eof_seen);
2149:
2150:
2151: if (play_with_sigint)
2152: signal (SIGINT, SIG_IGN);
2153:
2154: for (;;) {
2155: stohdr (zi->bytes_sent);
2156: zsbhdr (ZEOF, Txhdr);
2157: switch (getinsync (zi, 0)) {
2158: case ZACK:
2159: continue;
2160: case ZRPOS:
2161: goto somemore;
2162: case ZRINIT:
2163: return OK;
2164: case ZSKIP:
2165: if (input_f)
2166: fclose (input_f);
2167: DO_SYSLOG((LOG_INFO, "%s/%s: got ZSKIP",
2168: shortname, protname()));
2169: return c;
2170: default:
2171: if (input_f)
2172: fclose (input_f);
2173: DO_SYSLOG((LOG_INFO, "%s/%s: got %d",
2174: shortname, protname(), c));
2175: return ERROR;
2176: }
2177: }
2178: }
2179:
2180: static int
2181: calc_blklen(long total_sent)
2182: {
2183: static long total_bytes=0;
2184: static int calcs_done=0;
2185: static long last_error_count=0;
2186: static int last_blklen=0;
2187: static long last_bytes_per_error=0;
2188: unsigned long best_bytes=0;
2189: long best_size=0;
2190: long this_bytes_per_error;
2191: long d;
2192: unsigned int i;
2193: if (total_bytes==0)
2194: {
2195: /* called from countem */
2196: total_bytes=total_sent;
2197: return 0;
2198: }
2199:
2200: /* it's not good to calc blklen too early */
2201: if (calcs_done++ < 5) {
2202: if (error_count && start_blklen >1024)
2203: return last_blklen=1024;
2204: else
2205: last_blklen/=2;
2206: return last_blklen=start_blklen;
2207: }
2208:
2209: if (!error_count) {
2210: /* that's fine */
2211: if (start_blklen==max_blklen)
2212: return start_blklen;
2213: this_bytes_per_error=LONG_MAX;
2214: goto calcit;
2215: }
2216:
2217: if (error_count!=last_error_count) {
2218: /* the last block was bad. shorten blocks until one block is
2219: * ok. this is because very often many errors come in an
2220: * short period */
2221: if (error_count & 2)
2222: {
2223: last_blklen/=2;
2224: if (last_blklen < 32)
2225: last_blklen = 32;
2226: else if (last_blklen > 512)
2227: last_blklen=512;
2228: if (Verbose > 3)
2229: vstringf(_("calc_blklen: reduced to %d due to error\n"),
2230: last_blklen);
2231: }
2232: last_error_count=error_count;
2233: last_bytes_per_error=0; /* force recalc */
2234: return last_blklen;
2235: }
2236:
2237: this_bytes_per_error=total_sent / error_count;
2238: /* we do not get told about every error, because
2239: * there may be more than one error per failed block.
2240: * but one the other hand some errors are reported more
2241: * than once: If a modem buffers more than one block we
2242: * get at least two ZRPOS for the same position in case
2243: * *one* block has to be resent.
2244: * so don't do this:
2245: * this_bytes_per_error/=2;
2246: */
2247: /* there has to be a margin */
2248: if (this_bytes_per_error<100)
2249: this_bytes_per_error=100;
2250:
2251: /* be nice to the poor machine and do the complicated things not
2252: * too often
2253: */
2254: if (last_bytes_per_error>this_bytes_per_error)
2255: d=last_bytes_per_error-this_bytes_per_error;
2256: else
2257: d=this_bytes_per_error-last_bytes_per_error;
2258: if (d<4)
2259: {
2260: if (Verbose > 3)
2261: {
2262: vstringf(_("calc_blklen: returned old value %d due to low bpe diff\n"),
2263: last_blklen);
2264: vstringf(_("calc_blklen: old %ld, new %ld, d %ld\n"),
2265: last_bytes_per_error,this_bytes_per_error,d );
2266: }
2267: return last_blklen;
2268: }
2269: last_bytes_per_error=this_bytes_per_error;
2270:
2271: calcit:
2272: if (Verbose > 3)
2273: vstringf(_("calc_blklen: calc total_bytes=%ld, bpe=%ld, ec=%ld\n"),
2274: total_bytes,this_bytes_per_error,(long) error_count);
2275: for (i=32;i<=max_blklen;i*=2) {
2276: long ok; /* some many ok blocks do we need */
2277: long failed; /* and that's the number of blocks not transmitted ok */
2278: unsigned long transmitted;
2279: ok=total_bytes / i + 1;
2280: failed=((long) i + OVERHEAD) * ok / this_bytes_per_error;
2281: transmitted=total_bytes + ok * OVERHEAD
2282: + failed * ((long) i+OVERHEAD+OVER_ERR);
2283: if (Verbose > 4)
2284: vstringf(_("calc_blklen: blklen %d, ok %ld, failed %ld -> %lu\n"),
2285: i,ok,failed,transmitted);
2286: if (transmitted < best_bytes || !best_bytes)
2287: {
2288: best_bytes=transmitted;
2289: best_size=i;
2290: }
2291: }
2292: if (best_size > 2*last_blklen)
2293: best_size=2*last_blklen;
2294: last_blklen=best_size;
2295: if (Verbose > 3)
2296: vstringf(_("calc_blklen: returned %d as best\n"),
2297: last_blklen);
2298: return last_blklen;
2299: }
2300:
2301: /*
2302: * Respond to receiver's complaint, get back in sync with receiver
2303: */
2304: static int
2305: getinsync(struct zm_fileinfo *zi, int flag)
2306: {
2307: int c;
2308: size_t rxpos;
2309:
2310: for (;;) {
2311: c = zgethdr(Rxhdr, 0, &rxpos);
2312: switch (c) {
2313: case ZCAN:
2314: case ZABORT:
2315: case ZFIN:
2316: case TIMEOUT:
2317: return ERROR;
2318: case ZRPOS:
2319: /* ************************************* */
2320: /* If sending to a buffered modem, you */
2321: /* might send a break at this point to */
2322: /* dump the modem's buffer. */
2323: if (input_f)
2324: clearerr(input_f); /* In case file EOF seen */
2325: #ifdef HAVE_MMAP
2326: if (!mm_addr)
2327: #endif
2328: if (fseek(input_f, (long) rxpos, 0))
2329: return ERROR;
2330: zi->eof_seen = 0;
2331: bytcnt = Lrxpos = zi->bytes_sent = rxpos;
2332: if (Lastsync == rxpos) {
2333: error_count++;
2334: }
2335: Lastsync = rxpos;
2336: return c;
2337: case ZACK:
2338: Lrxpos = rxpos;
2339: if (flag || zi->bytes_sent == rxpos)
2340: return ZACK;
2341: continue;
2342: case ZRINIT:
2343: case ZSKIP:
2344: if (input_f)
2345: fclose(input_f);
2346: #ifdef HAVE_MMAP
2347: else if (mm_addr) {
2348: munmap(mm_addr,mm_size);
2349: mm_addr=NULL;
2350: }
2351: #endif
2352: return c;
2353: case ERROR:
2354: default:
2355: error_count++;
2356: zsbhdr(ZNAK, Txhdr);
2357: continue;
2358: }
2359: }
2360: }
2361:
2362:
2363: /* Say "bibi" to the receiver, try to do it cleanly */
2364: static void
2365: saybibi(void)
2366: {
2367: for (;;) {
2368: stohdr(0L); /* CAF Was zsbhdr - minor change */
2369: zshhdr(ZFIN, Txhdr); /* to make debugging easier */
2370: switch (zgethdr(Rxhdr, 0,NULL)) {
2371: case ZFIN:
2372: sendline('O');
2373: sendline('O');
2374: flushmo();
2375: case ZCAN:
2376: case TIMEOUT:
2377: return;
2378: }
2379: }
2380: }
2381:
2382: /* Send command and related info */
2383: static int
2384: zsendcmd(const char *buf, size_t blen)
2385: {
2386: int c;
2387: pid_t cmdnum;
2388: size_t rxpos;
2389:
2390: cmdnum = getpid();
2391: errors = 0;
2392: for (;;) {
2393: stohdr((size_t) cmdnum);
2394: Txhdr[ZF0] = Cmdack1;
2395: zsbhdr(ZCOMMAND, Txhdr);
2396: ZSDATA(buf, blen, ZCRCW);
2397: listen:
2398: Rxtimeout = 100; /* Ten second wait for resp. */
2399: c = zgethdr(Rxhdr, 1, &rxpos);
2400:
2401: switch (c) {
2402: case ZRINIT:
2403: goto listen; /* CAF 8-21-87 */
2404: case ERROR:
2405: case TIMEOUT:
2406: if (++errors > Cmdtries)
2407: return ERROR;
2408: continue;
2409: case ZCAN:
2410: case ZABORT:
2411: case ZFIN:
2412: case ZSKIP:
2413: case ZRPOS:
2414: return ERROR;
2415: default:
2416: if (++errors > 20)
2417: return ERROR;
2418: continue;
2419: case ZCOMPL:
2420: Exitcode = rxpos;
2421: saybibi();
2422: return OK;
2423: case ZRQINIT:
2424: vfile("******** RZ *******");
2425: system("rz");
2426: vfile("******** SZ *******");
2427: goto listen;
2428: }
2429: }
2430: }
2431:
2432: /*
2433: * If called as lsb use YMODEM protocol
2434: */
2435: static void
2436: chkinvok (const char *s)
2437: {
2438: const char *p;
2439:
2440: p = s;
2441: while (*p == '-')
2442: s = ++p;
2443: while (*p)
2444: if (*p++ == '/')
2445: s = p;
2446: if (*s == 'v') {
2447: Verbose = 1;
2448: ++s;
2449: }
2450: program_name = s;
2451: if (*s == 'l')
2452: s++; /* lsz -> sz */
2453: protocol = ZM_ZMODEM;
2454: if (s[0] == 's' && s[1] == 'x')
2455: protocol = ZM_XMODEM;
2456: if (s[0] == 's' && (s[1] == 'b' || s[1] == 'y')) {
2457: protocol = ZM_YMODEM;
2458: }
2459: }
2460:
2461: static void
2462: countem (int argc, char **argv)
2463: {
2464: struct stat f;
2465:
2466: for (Totalleft = 0, Filesleft = 0; --argc >= 0; ++argv) {
2467: f.st_size = -1;
2468: if (Verbose > 2) {
2469: vstringf ("\nCountem: %03d %s ", argc, *argv);
2470: }
2471: if (access (*argv, R_OK) >= 0 && stat (*argv, &f) >= 0) {
2472: #if defined(S_ISDIR)
2473: if (!S_ISDIR(f.st_mode) && !S_ISBLK(f.st_mode)) {
2474: #else
2475: int c;
2476: c = f.st_mode & S_IFMT;
2477: if (c != S_IFDIR && c != S_IFBLK) {
2478: #endif
2479: ++Filesleft;
2480: Totalleft += f.st_size;
2481: }
2482: } else if (strcmp (*argv, "-") == 0) {
2483: ++Filesleft;
2484: Totalleft += DEFBYTL;
2485: }
2486: if (Verbose > 2)
2487: vstringf (" %ld", (long) f.st_size);
2488: }
2489: if (Verbose > 2)
2490: vstringf (_("\ncountem: Total %d %ld\n"),
2491: Filesleft, Totalleft);
2492: calc_blklen (Totalleft);
2493: }
2494:
2495: /* End of lsz.c */
2496:
2497:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>