⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lsz.c

📁 Linux下ztelnet 的rz、sz源码
💻 C
📖 第 1 页 / 共 4 页
字号:
			if (rxpos && fseek(input_f, (long) rxpos, 0)) {				int er=errno;				vfile("fseek failed: %s", strerror(er));				DO_SYSLOG((LOG_INFO, "%s/%s: fseek failed: %s",						   shortname, protname(), strerror(er)));				return ERROR;			}			if (rxpos)				zi->bytes_skipped=rxpos;			bytcnt = zi->bytes_sent = rxpos;			Lastsync = rxpos -1;	 		return zsendfdata(zi);		}	}}/* Send the data in the file */static intzsendfdata (struct zm_fileinfo *zi){	static int c;	int newcnt;	static int junkcount;				/* Counts garbage chars received by TX */	static size_t last_txpos = 0;	static long last_bps = 0;	static long not_printed = 0;	static long total_sent = 0;	static time_t low_bps=0;#ifdef HAVE_MMAP	if (use_mmap && !mm_addr)	{		struct stat st;		if (fstat (fileno (input_f), &st) == 0) {			mm_size = st.st_size;			mm_addr = mmap (0, mm_size, PROT_READ,							MAP_SHARED, fileno (input_f), 0);			if ((caddr_t) mm_addr == (caddr_t) - 1)				mm_addr = NULL;			else {				fclose (input_f);				input_f = NULL;			}		}	}#endif	if (play_with_sigint)		signal (SIGINT, onintr);	Lrxpos = 0;	junkcount = 0;	Beenhereb4 = 0;  somemore:	if (setjmp (intrjmp)) {	  if (play_with_sigint)		  signal (SIGINT, onintr);	  waitack:		junkcount = 0;		c = getinsync (zi, 0);	  gotack:		switch (c) {		default:			if (input_f)				fclose (input_f);			DO_SYSLOG((LOG_INFO, "%s/%s: got %d",					   shortname, protname(), c));			return ERROR;		case ZCAN:			if (input_f)				fclose (input_f);			DO_SYSLOG((LOG_INFO, "%s/%s: got ZCAN",					   shortname, protname(), c));			return ERROR;		case ZSKIP:			if (input_f)				fclose (input_f);			DO_SYSLOG((LOG_INFO, "%s/%s: got ZSKIP",					   shortname, protname(), c));			return c;		case ZACK:		case ZRPOS:			break;		case ZRINIT:			return OK;		}#ifdef READCHECK		/*		 * If the reverse channel can be tested for data,		 *  this logic may be used to detect error packets		 *  sent by the receiver, in place of setjmp/longjmp		 *  rdchk(fdes) returns non 0 if a character is available		 */		while (rdchk (io_mode_fd)) {#ifdef READCHECK_READS			switch (checked)#else			switch (READLINE_PF (1))#endif			{			case CAN:			case ZPAD:				c = getinsync (zi, 1);				goto gotack;			case XOFF:			/* Wait a while for an XON */			case XOFF | 0200:				READLINE_PF (100);			}		}#endif	}	newcnt = Rxbuflen;	Txwcnt = 0;	stohdr (zi->bytes_sent);	zsbhdr (ZDATA, Txhdr);	do {		size_t n;		int e;		unsigned old = blklen;		blklen = calc_blklen (total_sent);		total_sent += blklen + OVERHEAD;		if (Verbose > 2 && blklen != old)			vstringf (_("blklen now %d\n"), blklen);#ifdef HAVE_MMAP		if (mm_addr) {			if (zi->bytes_sent + blklen < mm_size)				n = blklen;			else {				n = mm_size - zi->bytes_sent;				zi->eof_seen = 1;			}		} else#endif			n = zfilbuf (zi);		if (zi->eof_seen) {			e = ZCRCE;			if (Verbose>3)				vstring("e=ZCRCE/eof seen");		} else if (junkcount > 3) {			e = ZCRCW;			if (Verbose>3)				vstring("e=ZCRCW/junkcount > 3");		} else if (bytcnt == Lastsync) {			e = ZCRCW;			if (Verbose>3)				vstringf("e=ZCRCW/bytcnt == Lastsync == %ld", 					(unsigned long) Lastsync);#if 0		/* what is this good for? Rxbuflen/newcnt normally are short - so after		 * a few KB ZCRCW will be used? (newcnt is never incremented)		 */		} else if (Rxbuflen && (newcnt -= n) <= 0) {			e = ZCRCW;			if (Verbose>3)				vstringf("e=ZCRCW/Rxbuflen(newcnt=%ld,n=%ld)", 					(unsigned long) newcnt,(unsigned long) n);#endif		} else if (Txwindow && (Txwcnt += n) >= Txwspac) {			Txwcnt = 0;			e = ZCRCQ;			if (Verbose>3)				vstring("e=ZCRCQ/Window");		} else {			e = ZCRCG;			if (Verbose>3)				vstring("e=ZCRCG");		}		if ((Verbose > 1 || min_bps || stop_time)			&& (not_printed > (min_bps ? 3 : 7) 				|| zi->bytes_sent > last_bps / 2 + last_txpos)) {			int minleft = 0;			int secleft = 0;			time_t now;			last_bps = (zi->bytes_sent / timing (0,&now));			if (last_bps > 0) {				minleft = (zi->bytes_total - zi->bytes_sent) / last_bps / 60;				secleft = ((zi->bytes_total - zi->bytes_sent) / last_bps) % 60;			}			if (min_bps) {				if (low_bps) {					if (last_bps<min_bps) {						if (now-low_bps>=min_bps_time) {							/* too bad */							if (Verbose) {								vstringf(_("zsendfdata: bps rate %ld below min %ld"),								  last_bps, min_bps);								vstring("\r\n");							}							DO_SYSLOG((LOG_INFO, "%s/%s: bps rate low: %ld <%ld",									   shortname, protname(), last_bps, min_bps));							return ERROR;						}					} else						low_bps=0;				} else if (last_bps < min_bps) {					low_bps=now;				}			}			if (stop_time && now>=stop_time) {				/* too bad */				if (Verbose) {					vstring(_("zsendfdata: reached stop time"));					vstring("\r\n");				}				DO_SYSLOG((LOG_INFO, "%s/%s: reached stop time",						   shortname, protname()));				return ERROR;			}			if (Verbose > 1) {				vchar ('\r');				vstringf (_("Bytes Sent:%7ld/%7ld   BPS:%-8ld ETA %02d:%02d  "),					 (long) zi->bytes_sent, (long) zi->bytes_total, 					last_bps, minleft, secleft);			}			last_txpos = zi->bytes_sent;		} else if (Verbose)			not_printed++;		ZSDATA (DATAADR, n, e);		bytcnt = zi->bytes_sent += n;		if (e == ZCRCW)			goto waitack;#ifdef READCHECK		/*		 * If the reverse channel can be tested for data,		 *  this logic may be used to detect error packets		 *  sent by the receiver, in place of setjmp/longjmp		 *  rdchk(fdes) returns non 0 if a character is available		 */		fflush (stdout);		while (rdchk (io_mode_fd)) {#ifdef READCHECK_READS			switch (checked)#else			switch (READLINE_PF (1))#endif			{			case CAN:			case ZPAD:				c = getinsync (zi, 1);				if (c == ZACK)					break;				/* zcrce - dinna wanna starta ping-pong game */				ZSDATA (txbuf, 0, ZCRCE);				goto gotack;			case XOFF:			/* Wait a while for an XON */			case XOFF | 0200:				READLINE_PF (100);			default:				++junkcount;			}		}#endif							/* READCHECK */		if (Txwindow) {			size_t tcount = 0;			while ((tcount = zi->bytes_sent - Lrxpos) >= Txwindow) {				vfile ("%ld (%ld,%ld) window >= %u", tcount, 					(long) zi->bytes_sent, (long) Lrxpos,					Txwindow);				if (e != ZCRCQ)					ZSDATA (txbuf, 0, e = ZCRCQ);				c = getinsync (zi, 1);				if (c != ZACK) {					ZSDATA (txbuf, 0, ZCRCE);					goto gotack;				}			}			vfile ("window = %ld", tcount);		}	} while (!zi->eof_seen);	if (play_with_sigint)		signal (SIGINT, SIG_IGN);	for (;;) {		stohdr (zi->bytes_sent);		zsbhdr (ZEOF, Txhdr);		switch (getinsync (zi, 0)) {		case ZACK:			continue;		case ZRPOS:			goto somemore;		case ZRINIT:			return OK;		case ZSKIP:			if (input_f)				fclose (input_f);			DO_SYSLOG((LOG_INFO, "%s/%s: got ZSKIP",					   shortname, protname()));			return c;		default:			if (input_f)				fclose (input_f);			DO_SYSLOG((LOG_INFO, "%s/%s: got %d",					   shortname, protname(), c));			return ERROR;		}	}}static intcalc_blklen(long total_sent){	static long total_bytes=0;	static int calcs_done=0;	static long last_error_count=0;	static int last_blklen=0;	static long last_bytes_per_error=0;	unsigned long best_bytes=0;	long best_size=0;	long this_bytes_per_error;	long d;	unsigned int i;	if (total_bytes==0)	{		/* called from countem */		total_bytes=total_sent;		return 0;	}	/* it's not good to calc blklen too early */	if (calcs_done++ < 5) {		if (error_count && start_blklen >1024)			return last_blklen=1024;		else 			last_blklen/=2;		return last_blklen=start_blklen;	}	if (!error_count) {		/* that's fine */		if (start_blklen==max_blklen)			return start_blklen;		this_bytes_per_error=LONG_MAX;		goto calcit;	}	if (error_count!=last_error_count) {		/* the last block was bad. shorten blocks until one block is		 * ok. this is because very often many errors come in an		 * short period */		if (error_count & 2)		{			last_blklen/=2;			if (last_blklen < 32)				last_blklen = 32;			else if (last_blklen > 512)				last_blklen=512;			if (Verbose > 3)				vstringf(_("calc_blklen: reduced to %d due to error\n"),					last_blklen);		}		last_error_count=error_count;		last_bytes_per_error=0; /* force recalc */		return last_blklen;	}	this_bytes_per_error=total_sent / error_count;		/* we do not get told about every error, because		 * there may be more than one error per failed block.		 * but one the other hand some errors are reported more		 * than once: If a modem buffers more than one block we		 * get at least two ZRPOS for the same position in case		 * *one* block has to be resent.		 * so don't do this:		 * this_bytes_per_error/=2;		 */	/* there has to be a margin */	if (this_bytes_per_error<100)		this_bytes_per_error=100;	/* be nice to the poor machine and do the complicated things not	 * too often	 */	if (last_bytes_per_error>this_bytes_per_error)		d=last_bytes_per_error-this_bytes_per_error;	else		d=this_bytes_per_error-last_bytes_per_error;	if (d<4)	{		if (Verbose > 3)		{			vstringf(_("calc_blklen: returned old value %d due to low bpe diff\n"),				last_blklen);			vstringf(_("calc_blklen: old %ld, new %ld, d %ld\n"),				last_bytes_per_error,this_bytes_per_error,d );		}		return last_blklen;	}	last_bytes_per_error=this_bytes_per_error;calcit:	if (Verbose > 3)		vstringf(_("calc_blklen: calc total_bytes=%ld, bpe=%ld, ec=%ld\n"),			total_bytes,this_bytes_per_error,(long) error_count);	for (i=32;i<=max_blklen;i*=2) {		long ok; /* some many ok blocks do we need */		long failed; /* and that's the number of blocks not transmitted ok */		unsigned long transmitted;		ok=total_bytes / i + 1;		failed=((long) i + OVERHEAD) * ok / this_bytes_per_error;		transmitted=total_bytes + ok * OVERHEAD  			+ failed * ((long) i+OVERHEAD+OVER_ERR);		if (Verbose > 4)			vstringf(_("calc_blklen: blklen %d, ok %ld, failed %ld -> %lu\n"),				i,ok,failed,transmitted);		if (transmitted < best_bytes || !best_bytes)		{			best_bytes=transmitted;			best_size=i;		}	}	if (best_size > 2*last_blklen)		best_size=2*last_blklen;	last_blklen=best_size;	if (Verbose > 3)		vstringf(_("calc_blklen: returned %d as best\n"),			last_blklen);	return last_blklen;}/* * Respond to receiver's complaint, get back in sync with receiver */static int getinsync(struct zm_fileinfo *zi, int flag){	int c;	size_t rxpos;	for (;;) {		c = zgethdr(Rxhdr, 0, &rxpos);		switch (c) {		case ZCAN:		case ZABORT:		case ZFIN:		case TIMEOUT:			return ERROR;		case ZRPOS:			/* ************************************* */			/*  If sending to a buffered modem, you  */			/*   might send a break at this point to */			/*   dump the modem's buffer.		 */			if (input_f)				clearerr(input_f);	/* In case file EOF seen */#ifdef HAVE_MMAP			if (!mm_addr)#endif			if (fseek(input_f, (long) rxpos, 0))				return ERROR;			zi->eof_seen = 0;			bytcnt = Lrxpos = zi->bytes_sent = rxpos;			if (Lastsync == rxpos) {				error_count++;			}			Lastsync = rxpos;			return c;		case ZACK:			Lrxpos = rxpos;			if (flag || zi->bytes_sent == rxpos)				return ZACK;			continue;		case ZRINIT:		case ZSKIP:			if (input_f)				fclose(input_f);#ifdef HAVE_MMAP			else if (mm_addr) {				munmap(mm_addr,mm_size);				mm_addr=NULL;			}#endif			return c;		case ERROR:		default:			error_count++;			zsbhdr(ZNAK, Txhdr);			continue;		}	}}/* Say "bibi" to the receiver, try to do it cleanly */static voidsaybibi(void){	for (;;) {		stohdr(0L);		/* CAF Was zsbhdr - minor change */		zshhdr(ZFIN, Txhdr);	/*  to make debugging easier */		switch (zgethdr(Rxhdr, 0,NULL)) {		case ZFIN:			sendline('O');			sendline('O');			flushmo();		case ZCAN:		case TIMEOUT:			return;		}	}}/* Send command and related info */static int zsendcmd(const char *buf, size_t blen){	int c;	pid_t cmdnum;	size_t rxpos;	cmdnum = getpid();	errors = 0;	for (;;) {		stohdr((size_t) cmdnum);		Txhdr[ZF0] = Cmdack1;		zsbhdr(ZCOMMAND, Txhdr);		ZSDATA(buf, blen, ZCRCW);listen:		Rxtimeout = 100;		/* Ten second wait for resp. */		c = zgethdr(Rxhdr, 1, &rxpos);		switch (c) {		case ZRINIT:			goto listen;	/* CAF 8-21-87 */		case ERROR:		case TIMEOUT:			if (++errors > Cmdtries)				return ERROR;			continue;		case ZCAN:		case ZABORT:		case ZFIN:		case ZSKIP:		case ZRPOS:			return ERROR;		default:			if (++errors > 20)				return ERROR;			continue;		case ZCOMPL:			Exitcode = rxpos;			saybibi();			return OK;		case ZRQINIT:			vfile("******** RZ *******");			system("rz");			vfile("******** SZ *******");			goto listen;		}	}}/* * If called as lsb use YMODEM protocol */static voidchkinvok (const char *s){	const char *p;	p = s;	while (*p == '-')		s = ++p;	while (*p)		if (*p++ == '/')			s = p;	if (*s == 'v') {		Verbose = 1;		++s;	}	program_name = s;	if (*s == 'l')		s++;					/* lsz -> sz */	protocol = ZM_ZMODEM;	if (s[0] == 's' && s[1] == 'x')		protocol = ZM_XMODEM;	if (s[0] == 's' && (s[1] == 'b' || s[1] == 'y')) {		protocol = ZM_YMODEM;	}}static voidcountem (int argc, char **argv){	struct stat f;	for (Totalleft = 0, Filesleft = 0; --argc >= 0; ++argv) {		f.st_size = -1;		if (Verbose > 2) {			vstringf ("\nCountem: %03d %s ", argc, *argv);		}		if (access (*argv, R_OK) >= 0 && stat (*argv, &f) >= 0) {#if defined(S_ISDIR)			if (!S_ISDIR(f.st_mode) && !S_ISBLK(f.st_mode)) {#else			int c;			c = f.st_mode & S_IFMT;			if (c != S_IFDIR && c != S_IFBLK) {#endif				++Filesleft;				Totalleft += f.st_size;			}		} else if (strcmp (*argv, "-") == 0) {			++Filesleft;			Totalleft += DEFBYTL;		}		if (Verbose > 2)			vstringf (" %ld", (long) f.st_size);	}	if (Verbose > 2)		vstringf (_("\ncountem: Total %d %ld\n"),				 Filesleft, Totalleft);	calc_blklen (Totalleft);}/* End of lsz.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -