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