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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>