Annotation of embedaddon/lrzsz/src/lsz.c, revision 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>