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

📄 sz.c

📁 linux下的zmodem协议源代码实现
💻 C
📖 第 1 页 / 共 2 页
字号:
				goto gotnak;			if (firstch == CAN && Lastrx == CAN)				goto cancan;		}	}	logent("Retry Count Exceeded\n");	return ERROR;}/* fill buf with count chars padding with ^Z for CPM */filbuf(buf, count)register char *buf;{	register c, m;	if ( !Ascii) {		m = read(fileno(in), buf, count);		if (m <= 0)			return 0;		while (m < count)			buf[m++] = 032;		return count;	}	m=count;	if (Lfseen) {		*buf++ = 012; --m; Lfseen = 0;	}	while ((c=getc(in))!=EOF) {		if (c == 012) {			*buf++ = 015;			if (--m == 0) {				Lfseen = TRUE; break;			}		}		*buf++ =c;		if (--m == 0)			break;	}	if (m==count)		return 0;	else		while (--m>=0)			*buf++ = CPMEOF;	return count;}/* fill buf with count chars */zfilbuf(buf, count)register char *buf;{	register c, m;	m=count;	while ((c=getc(in))!=EOF) {		*buf++ =c;		if (--m == 0)			break;	}	return (count - m);}/* VARARGS1 */vfile(f, a, b, c)register char *f;{	if (Verbose > 1) {		fprintf(stderr, f, a, b, c);		fprintf(stderr, "\n");	}}alrm(){	longjmp(tohere, -1);}/* * readock(timeout, count) reads character(s) from file descriptor 0 *  (1 <= count <= 3) * it attempts to read count characters. If it gets more than one, * it is an error unless all are CAN * (otherwise, only normal response is ACK, CAN, or C) *  Only looks for one if Optiong, which signifies cbreak, not raw input * * timeout is in tenths of seconds */readock(timeout, count){	register int c;	static char byt[5];	if (Optiong)		count = 1;	/* Special hack for cbreak */	fflush(stdout);	if (setjmp(tohere)) {		logent("TIMEOUT\n");		return TIMEOUT;	}	c = timeout/10;	if (c<2)		c=2;	if (Verbose>3) {		fprintf(stderr, "Timeout=%d Calling alarm(%d) ", timeout, c);		byt[1] = 0;	}	signal(SIGALRM, alrm); alarm(c);#ifdef ONEREAD	c=read(iofd, byt, 1);		/* regulus raw read is unique */#else	c=read(iofd, byt, count);#endif	alarm(0);	if (Verbose>5)		fprintf(stderr, "ret cnt=%d %x %x\n", c, byt[0], byt[1]);	if (c<1)		return TIMEOUT;	if (c==1)		return (byt[0]&0377);	else		while (c)			if (byt[--c] != CAN)				return ERROR;	return CAN;}readline(n){	return (readock(n, 1));}purgeline(){#ifdef USG	ioctl(iofd, TCFLSH, 0);#else	lseek(iofd, 0L, 2);#endif}/* update CRC */unsignedupdcrc(c, crc)register c;register unsigned crc;{	register count;	for (count=8; --count>=0;) {		if (crc & 0x8000) {			crc <<= 1;			crc += (((c<<=1) & 0400)  !=  0);			crc ^= 0x1021;		}		else {			crc <<= 1;			crc += (((c<<=1) & 0400)  !=  0);		}	}	return crc;	}/* send cancel string to get the other end to shut up */canit(){	static char canistr[] = {	 ZPAD,ZPAD,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0	};	printf(canistr);	fflush(stdout);}/*VARARGS1*/logent(a, b, c)char *a, *b, *c;{	if(Verbose)		fprintf(stderr, a, b, c);}/* * return 1 iff stdout and stderr are different devices *  indicating this program operating with a modem on a *  different line */fromcu(){	struct stat a, b;	fstat(1, &a); fstat(2, &b);	return (a.st_rdev != b.st_rdev);}/* * substr(string, token) searches for token in string s * returns pointer to token within string if found, NULL otherwise */char *substr(s, t)register char *s,*t;{	register char *ss,*tt;	/* search for first char of token */	for (ss=s; *s; s++)		if (*s == *t)			/* compare token with substring */			for (ss=s,tt=t; ;) {				if (*tt == 0)					return s;				if (*ss++ != *tt++)					break;			}	return NULL;}usage(){	fprintf(stderr,"\nSend file(s) with ZMODEM/YMODEM/XMODEM Protocol\n");	fprintf(stderr,"%s for %s by Chuck Forsberg\n", VERSION, OS);	fprintf(stderr,"Usage:	sz [-1+adfknquvXy] [-] file ...\n");	fprintf(stderr,"	(Y) = Option applies to YMODEM only\n");	fprintf(stderr,"	(Z) = Option applies to ZMODEM only\n");	fprintf(stderr,"	sz [-1qv] -c COMMAND\n");	fprintf(stderr,"	1 Use stdout for modem input\n");	fprintf(stderr,"	+ Append to existing destination file (Z)\n");	fprintf(stderr,"	a (ASCII) change NL to CR/LF\n");	fprintf(stderr,"	c send COMMAND (Z)\n");	fprintf(stderr,"\tC N (set command retries to N default=%d) (Z)\n",	  Cmdtries);	fprintf(stderr,"	d Change '.' to '/' in pathnames (Y/Z)\n");	fprintf(stderr,"	f send Full pathname (Y/Z)\n");	fprintf(stderr,"	i send COMMAND, ack Immediately (Z)\n");	fprintf(stderr,"	k Send 1024 byte packets (Y)\n");	fprintf(stderr,"	n send file if Newer|different length (Z)\n");	fprintf(stderr,"	N send file if different length|CRC (Z)\n");	fprintf(stderr,"	r Resume interrupted file transfer (Z)\n");	fprintf(stderr,"	q Quiet (no progress reports)\n");	fprintf(stderr,"	u Unlink file after transmission\n");	fprintf(stderr,"	v Verbose - debugging information\n");	fprintf(stderr,"	X XMODEM protocol - no pathnames\n");	fprintf(stderr,"	y Yes, overwrite existing file (Z)\n");	fprintf(stderr,"- as pathname sends standard input as sPID.sz or environment ONAME\n");	exit(1);}/* * Get the receiver's init parameters */getzrxinit(){	register n;	struct stat f;	for (n=10; --n>=0; ) {				switch (zgethdr(Rxhdr, 1)) {		case ZCHALLENGE:	/* Echo receiver's challenge numbr */			stohdr(Rxpos);			zshhdr(ZACK, Txhdr);			continue;		case ZCOMMAND:		/* They didn't see out ZRQINIT */			stohdr(0L);			zshhdr(ZRQINIT, Txhdr);			continue;		case ZRINIT:			Rxflags = Rxhdr[ZF0];			Rxbuflen = Rxhdr[ZP0] + (Rxhdr[ZP1]<<8);			signal(SIGINT, SIG_IGN);			mode(2);	/* Set cbreak, XON/XOFF, etc. */			/* If using a pipe for testing set lower buf len */			fstat(iofd, &f);			if ((f.st_mode & S_IFMT) != S_IFCHR			  && (Rxbuflen == 0 || Rxbuflen > 4096))				Rxbuflen = 4096;			/*			 * If input is not a regular file, force ACK's each 1024			 *  (A smarter strategey could be used here ...)			 */			fstat(fileno(in), &f);			if (((f.st_mode & S_IFMT) != S_IFREG)			  && (Rxbuflen == 0 || Rxbuflen > 1024))				Rxbuflen = 1024;			return (sendzsinit());		case ZCAN:		case TIMEOUT:			return ERROR;		case ZRQINIT:			if (Rxhdr[ZF0] == ZCOMMAND)				continue;		default:			zshhdr(ZNAK, Txhdr);			continue;		}	}	return ERROR;}/* Send send-init information */sendzsinit(){	register c;	register errors;	errors = 0;	for (;;) {		stohdr(0L);		zsbhdr(ZSINIT, Txhdr);		zsbdata(Myattn, 1+strlen(Myattn), ZCRCW);		c = zgethdr(Rxhdr, 1);		switch (c) {		case ZCAN:			return ERROR;		case ZACK:			return OK;		default:			if (++errors > 9)				return ERROR;			continue;		}	}}/* Send file name and related info */zsendfile(buf, blen)char *buf;{	register c;	for (;;) {		Txhdr[ZF0] = Lzconv;	/* file conversion request */		Txhdr[ZF1] = Lzmanag;	/* file management request */		Txhdr[ZF2] = Lztrans;	/* file transport request */		Txhdr[ZF3] = 0;		zsbhdr(ZFILE, Txhdr);		zsbdata(buf, blen, ZCRCW);again:		c = zgethdr(Rxhdr, 1);		switch (c) {		case ZRINIT:			goto again;		case ZCAN:		case TIMEOUT:		case ZABORT:		case ZFIN:			return ERROR;		case ZSKIP:			fclose(in); return c;		case ZRPOS:			fseek(in, Rxpos, 0);			Txpos = Rxpos;			return zsendfdata();		case ERROR:		default:			continue;		}	}}/* Send the data in the file */zsendfdata(){	register c, e;	register newcnt;	register long tcount = 0;	static int tleft = 6;	/* Counter for test mode */	if (Baudrate > 300)		blklen = 256;	if (Baudrate > 2400)		blklen = KSIZE;	if (Rxbuflen && blklen>Rxbuflen)		blklen = Rxbuflen;somemore:	if (setjmp(intrjmp)) {waitack:		switch (c = getinsync()) {		default:		case ZCAN:			fclose(in);			return ERROR;		case ZSKIP:			fclose(in);			return c;		case ZACK:		case ZRPOS:			break;		}	}	signal(SIGINT, onintr);	newcnt = Rxbuflen;	stohdr(Txpos);	zsbhdr(ZDATA, Txhdr);	/*	 * Special testing mode.  This should force receiver to Attn,ZRPOS	 *  many times.  Each time the signal should be caught, causing the	 *  file to be started over from the beginning.	 */	if (Testattn) {		if ( --tleft)			while (tcount < 20000) {				printf(qbf); fflush(stdout);				tcount += strlen(qbf);			}		signal(SIGINT, SIG_IGN); canit();		sleep(3); purgeline(); mode(0);		printf("\nsz: Tcount = %ld\n", tcount);		if (tleft) {			printf("ERROR: Interrupts Not Caught\n");			exit(1);		}		exit(0);	}	do {		c = zfilbuf(txbuf, blklen);		if (c < blklen)			e = ZCRCE;		else if (Rxbuflen && (newcnt -= c) <= 0)			e = ZCRCW;		else			e = ZCRCG;		zsbdata(txbuf, c, e);		Txpos += c;		if (e == ZCRCW)			goto waitack;#ifdef NOTDEF_DOS		if ( !carrier()) {			return ERROR;		}		/*		 * 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		 *	miready() returns non 0 if a character is available		 */		while (miready()) {			if (readline(1) == ZPAD) {				zsbdata(U.ubuf, 0, ZCRCW);				goto somemore;			}		}#endif	} while (c == blklen);	signal(SIGINT, SIG_IGN);	for (;;) {		stohdr(Txpos);		zsbhdr(ZEOF, Txhdr);		switch (getinsync()) {		case ZRPOS:			goto somemore;		case ZRINIT:			fclose(in);			return OK;		case ZSKIP:			fclose(in);			return c;		default:			fclose(in);			return ERROR;		}	}}/* * Respond to receiver's complaint, get back in sync with receiver */getinsync(){	register c;	for (;;) {		if (Testattn) {			printf("\r\n\n\n***** Signal Caught *****\r\n");			Rxpos = 0; c = ZRPOS;		} else			c = zgethdr(Rxhdr, 0);		switch (c) {		case ZCAN:		case ZABORT:		case ZFIN:		case TIMEOUT:			return ERROR;		case ZRPOS:			clearerr(in);	/* In case file EOF seen */			fseek(in, Rxpos, 0);			Txpos = Rxpos;			return c;		case ZACK:			return c;		case ZRINIT:		case ZSKIP:			fclose(in);			return c;		case ERROR:		default:			zsbhdr(ZNAK, Txhdr);			continue;		}	}}/* Say "bibi" to the receiver, try to do it cleanly */saybibi(){	for (;;) {		stohdr(0L);		zsbhdr(ZFIN, Txhdr);		switch (zgethdr(Rxhdr, 0)) {		case ZFIN:			sendline('O'); sendline('O'); flushmo();		case ZCAN:		case TIMEOUT:			return;		}	}}/* Local screen character display function */bttyout(c){	if (Verbose)		putc(c, stderr);}/* Send command and related info */zsendcmd(buf, blen)char *buf;{	register c, errors;	long cmdnum;	cmdnum = getpid();	errors = 0;	for (;;) {		stohdr(cmdnum);		Txhdr[ZF0] = Cmdack1;		zsbhdr(ZCOMMAND, Txhdr);		zsbdata(buf, blen, ZCRCW);listen:		Rxtimeout = 100;		/* Ten second wait for resp. */		c = zgethdr(Rxhdr, 1);		switch (c) {		case ZRINIT:			continue;		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 > 10)				return ERROR;			continue;		case ZCOMPL:			Exitcode = Rxpos;			saybibi();			return OK;		case ZRQINIT:			vfile("******** RZ *******");			system("rz");			vfile("******** SZ *******");			goto listen;		}	}}

⌨️ 快捷键说明

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