File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lrzsz / src / lrz.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Thu Oct 24 15:49:50 2019 UTC (4 years, 11 months ago) by misho
Branches: lrzsz, MAIN
CVS tags: v0_12_20p5, HEAD
lrzsz ver 0.12.20

    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>