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

📄 rz.c

📁 linux下的zmodem协议源代码实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	lseek(iofd, 0L, 2);#endif}/* * Update CRC CRC-16 used by XMODEM/CRC, YMODEM, and ZMODEM. *  Note: Final result must be masked with 0xFFFF before testing *  More efficient table driven routines exist. */unsigned shortupdcrc(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;	}/* * Process incoming file information header */procheader(name)char *name;{	register char *openmode, *p, **pp;	/* set default parameters */	openmode = "w"; Thisbinary=Rxbinary;	/*	 *  Process ZMODEM remote file management requests	 */	if (zconv == ZCNL)	/* Remote ASCII override */		Thisbinary = 0;	if (zconv == ZCBIN)	/* Remote Binary override */		++Thisbinary;	else if (zmanag == ZMAPND)		openmode = "a";	Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;	p = name + 1 + strlen(name);	if (*p) {	/* file coming from Unix or DOS system */		sscanf(p, "%ld%lo%o", &Bytesleft, &Modtime, &Filemode);		if (Filemode & UNIXFILE)			++Thisbinary;		if (Verbose) {			fprintf(stderr,  "Incoming: %s %ld %lo %o\n",			  name, Bytesleft, Modtime, Filemode);		}	}	else {		/* File coming from CP/M system */		for (p=name; *p; ++p)		/* change / to _ */			if ( *p == '/')				*p = '_';		if ( *--p == '.')		/* zap trailing period */			*p = 0;	}	/* scan for extensions that signify a binary file */	if (p=substr(name, "."))		for (pp=Extensions; **pp; ++pp)			if (strcmp(p, *pp)==0) {				Thisbinary=TRUE; break;			}	/* scan for files which should be appended */	if ( !Thisbinary	  && (substr(name, ".TXT")	  || substr(name, ".txt")	  || substr(name, ".MSG")))		openmode = "a";	if (MakeLCPathname && !IsAnyLower(name))		uncaps(name);	if (Topipe) {		sprintf(Pathname, "%s %s", Progname+2, name);		if (Verbose)			fprintf(stderr,  "Topipe: %s %s\n",			  Pathname, Thisbinary?"BIN":"ASCII");		if ((fout=popen(Pathname, "w")) == NULL)			return ERROR;	} else {		strcpy(Pathname, name);		if (Verbose) {			fprintf(stderr,  "Receiving %s %s %s\n",			  name, Thisbinary?"BIN":"ASCII", openmode);		}		checkpath(name);		if (Nflag)			name = "/dev/null";		if ((fout=fopen(name, openmode)) == NULL)			return ERROR;	}	return OK;}/* Make string s lower case */uncaps(s)register char *s;{	for ( ; *s; ++s)		if (isupper(*s))			*s = tolower(*s);}/* * IsAnyLower returns TRUE if string s has lower case letters. */IsAnyLower(s)register char *s;{	for ( ; *s; ++s)		if (islower(*s))			return TRUE;	return FALSE;}/* * Putsec writes the n characters of buf to receive file fout. *  If not in binary mode, carriage returns, and all characters *  starting with CPMEOF are discarded. */putsec(buf, n)char *buf;register n;{	register char *p;	if (Thisbinary) {		for (p=buf; --n>=0; )			putc( *p++, fout);	}	else {		if (Eofseen)			return OK;		for (p=buf; --n>=0; ++p ) {			if ( *p == '\r')				continue;			if (*p == CPMEOF) {				Eofseen=TRUE; return OK;			}			putc(*p ,fout);		}	}	return OK;}/* *  Send a character to modem.  Small is beautiful. */sendline(c){	char d;	d = c;	if (Verbose>4)		fprintf(stderr, "Sendline: %x\n", c);	write(1, &d, 1);}xsendline(c){	sendline(c);}flushmo() {}/* * 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;}/* * Log an error *//*VARARGS1*/log(s,p,u)char *s, *p, *u;{	if (!Verbose)		return;	fprintf(stderr, "error %d: ", errors);	fprintf(stderr, s, p, u);}/* 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);	Lleft=0;	/* Do read next time ... */	fflush(stdout);}/* * 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);}report(sct)int sct;{	if (Verbose>1)		fprintf(stderr,"%03d%c",sct,sct%10? ' ' : '\r');}/* * If called as [-][dir/../]vrzCOMMAND set Verbose to 1 * If called as [-][dir/../]rzCOMMAND set the pipe flag * If called as rb use YMODEM protocol */chkinvok(s)char *s;{	register char *p;	p = s;	while (*p == '-')		s = ++p;	while (*p)		if (*p++ == '/')			s = p;	if (*s == 'v') {		Verbose=1; ++s;	}	Progname = s;	if (s[0]=='r' && s[1]=='b')		Nozmodem = TRUE;	if (s[2] && s[0]=='r' && s[1]=='b')		Topipe=TRUE;	if (s[2] && s[0]=='r' && s[1]=='z')		Topipe=TRUE;}/* * Totalitarian Communist pathname processing */checkpath(name)char *name;{	if (Restricted) {		if (fopen(name, "r") != NULL) {			canit();			fprintf(stderr, "\r\nrz: %s exists\n", name);			bibi();		}		/* restrict pathnames to current tree or uucppublic */		if ( substr(name, "../")		 || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {			canit();			fprintf(stderr,"\r\nrz:\tSecurity Violation\r\n");			bibi();		}	}}/* * Initialize for Zmodem receive attempt, try to activate Zmodem sender *  Handles ZSINIT frame *  Return ZFILE if Zmodem filename received, -1 on error, *   ZCOMPL if transaction finished,  else 0 */tryz(){	register c, n;	register cmdzack1flg;	if (Nozmodem)		/* Check for "rb" program name */		return 0;	Rxtimeout = 100;	for (n=5; --n>=0; ) {		/* Set buffer length (0) and capability flags */		stohdr(0L);		Txhdr[ZF0] = CANFDX|CANOVIO|CANBRK;		zshhdr(Badclose?ZFERR:ZRINIT, Txhdr);again:		switch (zgethdr(Rxhdr, 0)) {		case ZRQINIT:			continue;		case ZEOF:			continue;		case TIMEOUT:			continue;		case ZFILE:			zconv = Rxhdr[ZF0];			zmanag = Rxhdr[ZF1];			ztrans = Rxhdr[ZF2];			Badclose = FALSE;			if (zrbdata(secbuf, KSIZE) == GOTCRCW)				return ZFILE;			zshhdr(ZNAK, Txhdr);		case ZSINIT:			if (zrbdata(Attn, ZATTNLEN) == GOTCRCW) {				zshhdr(ZACK, Txhdr);				goto again;			}			zshhdr(ZNAK, Txhdr);			continue;		case ZFREECNT:			stohdr(getfree());			zshhdr(ZACK, Txhdr);			goto again;		case ZCOMMAND:			cmdzack1flg = Rxhdr[ZF0];			if (zrbdata(secbuf, KSIZE) == GOTCRCW) {				if (cmdzack1flg & ZCACK1)					stohdr(0L);				else					stohdr((long)sys2(secbuf));				purgeline();	/* dump impatient questions */				do {					zshhdr(ZCOMPL, Txhdr);				}				while (++errors<10 && zgethdr(Rxhdr,1) != ZFIN);				ackbibi();				if (cmdzack1flg & ZCACK1)					exec2(secbuf);				return ZCOMPL;			}			zshhdr(ZNAK, Txhdr); goto again;		case ZCOMPL:			goto again;		default:			continue;		case ZFIN:			ackbibi(); return ZCOMPL;		case ZCAN:			return ERROR;		}	}	return 0;}/* * Receive 1 or more files with ZMODEM protocol */rzfiles(){	register c;	for (;;) {		switch (c = rzfile()) {		case ZEOF:		case ZSKIP:			switch (tryz()) {			case ZCOMPL:				return OK;			default:				return ERROR;			case ZFILE:				break;			}			continue;		default:			return c;		case ERROR:			return ERROR;		}	}}/* * Receive a file with ZMODEM protocol *  Assumes file name frame is in secbuf */rzfile(){	register c, n;	long rxbytes;	Eofseen=FALSE;	if (procheader(secbuf) == ERROR) {		zshhdr(ZSKIP, Txhdr);		return ZSKIP;	}	n = 10; rxbytes = 0l;	for (;;) {		stohdr(rxbytes);		zshhdr(ZRPOS, Txhdr);nxthdr:		switch (c = zgethdr(Rxhdr, 0)) {		default:			vfile("rzfile: zgethdr returned %d", c);			return ERROR;		case ZNAK:		case TIMEOUT:			if ( --n < 0) {				vfile("rzfile: zgethdr returned %d", c);				return ERROR;			}		case ZFILE:			continue;		case ZEOF:			if (rclhdr(Rxhdr) != rxbytes) {				continue;			}			if (closeit()) {				Badclose = TRUE;				vfile("rzfile: closeit returned <> 0");				return ERROR;			}			vfile("rzfile: normal EOF");			return c;		case ERROR:	/* Too much garbage in header search error */			if ( --n < 0) {				vfile("rzfile: zgethdr returned %d", c);				return ERROR;			}			zmputs(Attn);			continue;		case ZDATA:			n = 10;			if (rclhdr(Rxhdr) != rxbytes) {				zmputs(Attn);				continue;			}moredata:			switch (c = zrbdata(secbuf, KSIZE)) {			case ZCAN:				vfile("rzfile: zgethdr returned %d", c);				return ERROR;			case ERROR:	/* CRC error */				if ( --n < 0) {					vfile("rzfile: zgethdr returned %d", c);					return ERROR;				}				zmputs(Attn);				continue;			case TIMEOUT:				if ( --n < 0) {					vfile("rzfile: zgethdr returned %d", c);					return ERROR;				}				continue;			case GOTCRCW:				putsec(secbuf, Rxcount);				rxbytes += Rxcount;				stohdr(rxbytes);				zshhdr(ZACK, Txhdr);				goto nxthdr;			case GOTCRCQ:				putsec(secbuf, Rxcount);				rxbytes += Rxcount;				stohdr(rxbytes);				zshhdr(ZACK, Txhdr);				goto moredata;			case GOTCRCG:				putsec(secbuf, Rxcount);				rxbytes += Rxcount;				goto moredata;			case GOTCRCE:				putsec(secbuf, Rxcount);				rxbytes += Rxcount;				goto nxthdr;			}		}	}}/* * Send a string to the modem, processing for \336 (sleep 1 sec) *   and \335 (break signal) */zmputs(s)char *s;{	register c;	while (*s) {		switch (c = *s++) {		case '\336':			sleep(1); continue;		case '\335':			sendbrk(); continue;		default:			sendline(c);		}	}}/* * Close the receive dataset, return OK or ERROR */closeit(){	if (Topipe) {		if (pclose(fout)) {			return ERROR;		}		return OK;	}	if (fclose(fout)==ERROR) {		fprintf(stderr, "file close ERROR\n");		return ERROR;	}	if (Modtime) {		timep[0] = time(NULL);		timep[1] = Modtime;		utime(Pathname, timep);	}	if (Filemode)		chmod(Pathname, (07777 & Filemode));	return OK;}/* * Ack a ZFIN packet, let byegones be byegones */ackbibi(){	register n;	vfile("ackbibi:");	Readnum = 1;	stohdr(0L);	for (n=4; --n>=0; ) {		zshhdr(ZFIN, Txhdr);		for (;;) {			switch (readline(100)) {			case 'O':				readline(1);	/* Discard 2nd 'O' */				/* ***** FALL THRU TO ***** */			case TIMEOUT:				vfile("ackbibi complete");				return;			default:				break;			}		}	}}/* * Local console output simulation */bttyout(c){	if (Verbose || fromcu)		putc(c, stderr);}/* * Strip leading ! if present, do shell escape.  */sys2(s)register char *s;{	if (*s == '!')		++s;	return system(s);}/* * Strip leading ! if present, do exec. */exec2(s)register char *s;{	if (*s == '!')		++s;	mode(0);	execl("/bin/sh", "sh", "-c", s);}

⌨️ 快捷键说明

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