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

📄 rz.c

📁 支持ZModem协议的串口通讯程序
💻 C
📖 第 1 页 / 共 2 页
字号:
			}			vfile("Crash recovery at %ld", rxbytes);			return 0;		}		else if ((zmanag==ZMNEW) ||		  ((zmanag==ZMNEWL) && Bytesleft <= f.st_size) ) {			if ((f.st_mtime+1) >= Modtime)				goto skipfile;			goto doopen;		}		switch (zmanag & ZMMASK) {		case ZMCLOB:		case ZMAPND:			goto doopen;		default:			goto skipfile;		}	} else if (zmanag & ZMSKNOLOC) {skipfile:		vfile("Skipping %s", name);		return ZSKIP;	}doopen:	openit(name, openmode);#ifdef MD	if ( !fout)		if (make_dirs(name))			openit(name, openmode);#endif	if ( !fout)		return ZFERR;	return 0;}openit(name, openmode)char *name, *openmode;{	fout = fopen(name, openmode);}#ifdef MD/* *  Directory-creating routines from Public Domain TAR by John Gilmore *//* * After a file/link/symlink/dir creation has failed, see if * it's because some required directory was not present, and if * so, create all required dirs. */make_dirs(pathname)register char *pathname;{	register char *p;		/* Points into path */	int madeone = 0;		/* Did we do anything yet? */	int save_errno = errno;		/* Remember caller's errno */	if (errno != ENOENT)		return 0;		/* Not our problem */	for (p = strchr(pathname, '/'); p != NULL; p = strchr(p+1, '/')) {		/* Avoid mkdir of empty string, if leading or double '/' */		if (p == pathname || p[-1] == '/')			continue;		/* Avoid mkdir where last part of path is '.' */		if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))			continue;		*p = 0;				/* Truncate the path there */		if ( !mkdir(pathname, 0777)) {	/* Try to create it as a dir */			vfile("Made directory %s\n", pathname);			madeone++;		/* Remember if we made one */			*p = '/';			continue;		}		*p = '/';		if (errno == EEXIST)		/* Directory already exists */			continue;		/*		 * Some other error in the mkdir.  We return to the caller.		 */		break;	}	errno = save_errno;		/* Restore caller's errno */	return madeone;			/* Tell them to retry if we made one */}#if (MD != 2)#define	TERM_SIGNAL(status)	((status) & 0x7F)#define TERM_COREDUMP(status)	(((status) & 0x80) != 0)#define TERM_VALUE(status)	((status) >> 8)/* * Make a directory.  Compatible with the mkdir() system call on 4.2BSD. */mkdir(dpath, dmode)char *dpath;int dmode;{	int cpid, status;	struct stat statbuf;	if (stat(dpath,&statbuf) == 0) {		errno = EEXIST;		/* Stat worked, so it already exists */		return -1;	}	/* If stat fails for a reason other than non-existence, return error */	if (errno != ENOENT) return -1; 	switch (cpid = fork()) {	case -1:			/* Error in fork() */		return(-1);		/* Errno is set already */	case 0:				/* Child process */		/*		 * Cheap hack to set mode of new directory.  Since this		 * child process is going away anyway, we zap its umask.		 * FIXME, this won't suffice to set SUID, SGID, etc. on this		 * directory.  Does anybody care?		 */		status = umask(0);	/* Get current umask */		status = umask(status | (0777 & ~dmode)); /* Set for mkdir */		execl("/bin/mkdir", "mkdir", dpath, (char *)0);		_exit(2);		/* Can't exec /bin/mkdir */		default:			/* Parent process */		while (cpid != wait(&status)) ;	/* Wait for kid to finish */	}	if (TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0) {		errno = EIO;		/* We don't know why, but */		return -1;		/* /bin/mkdir failed */	}	return 0;}#endif /* MD != 2 */#endif /* MD *//* * 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 (n == 0)		return OK;	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;}/* * 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;}/* * If called as [-][dir/../]vrzCOMMAND set Verbose to 1 * 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]=='z')		Batch = TRUE;	if (s[0]=='r' && s[1]=='c')		Crcflg = TRUE;	if (s[0]=='r' && s[1]=='b')		Batch = Nozmodem = 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(-1);		}		/* 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(-1);		}	}}/* * Ack a ZFIN packet, let byegones be byegones */voidackbibi(){	register n;	vfile("ackbibi:");	Readnum = 1;	stohdr(0L);	for (n=3; --n>=0; ) {		purgeline();		zshhdr(4,ZFIN, Txhdr);		switch (readline(100)) {		case 'O':			readline(1);	/* Discard 2nd 'O' */			vfile("ackbibi complete");			return;		case RCDO:			return;		case TIMEOUT:		default:			break;		}	}}/* * 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;	for (n=15; --n>=0; ) {		/* Set buffer length (0) and capability flags */#ifdef SEGMENTS		stohdr(SEGMENTS*1024L);#else		stohdr(0L);#endif#ifdef CANBREAK		Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;#else		Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;#endif		if (Zctlesc)			Txhdr[ZF0] |= TESCCTL;		Txhdr[ZF0] |= CANRLE;		Txhdr[ZF1] = CANVHDR;		/* tryzhdrtype may == ZRINIT */		zshhdr(4,tryzhdrtype, Txhdr);		if (tryzhdrtype == ZSKIP)	/* Don't skip too far */			tryzhdrtype = ZRINIT;	/* CAF 8-21-87 */again:		switch (zgethdr(Rxhdr)) {		case ZRQINIT:			if (Rxhdr[ZF3] & 0x80)				Usevhdrs = 1;	/* we can var header */			continue;		case ZEOF:			continue;		case TIMEOUT:			continue;		case ZFILE:			zconv = Rxhdr[ZF0];			zmanag = Rxhdr[ZF1];			ztrans = Rxhdr[ZF2];			if (Rxhdr[ZF3] & ZCANVHDR)				Usevhdrs = TRUE;			tryzhdrtype = ZRINIT;			c = zrdata(secbuf, 1024);			if (c == GOTCRCW)				return ZFILE;			zshhdr(4,ZNAK, Txhdr);			goto again;		case ZSINIT:			Zctlesc = TESCCTL & Rxhdr[ZF0];			if (zrdata(Attn, ZATTNLEN) == GOTCRCW) {				stohdr(1L);				zshhdr(4,ZACK, Txhdr);				goto again;			}			zshhdr(4,ZNAK, Txhdr);			goto again;		case ZFREECNT:			stohdr(getfree());			zshhdr(4,ZACK, Txhdr);			goto again;		case ZCOMMAND:			cmdzack1flg = Rxhdr[ZF0];			if (zrdata(secbuf, 1024) == GOTCRCW) {				if (cmdzack1flg & ZCACK1)					stohdr(0L);				else					stohdr((long)sys2(secbuf));				purgeline();	/* dump impatient questions */				do {					zshhdr(4,ZCOMPL, Txhdr);				}				while (++errors<20 && zgethdr(Rxhdr) != ZFIN);				ackbibi();				if (cmdzack1flg & ZCACK1)					exec2(secbuf);				return ZCOMPL;			}			zshhdr(4,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;	Eofseen=FALSE;	n = 20; rxbytes = 0l;	if (c = procheader(secbuf)) {		return (tryzhdrtype = c);	}	for (;;) {#ifdef SEGMENTS		chinseg = 0;#endif		stohdr(rxbytes);		zshhdr(4,ZRPOS, Txhdr);nxthdr:		switch (c = zgethdr(Rxhdr)) {		default:			vfile("rzfile: Wrong header %d", c);			if ( --n < 0) {				sprintf(endmsg, "rzfile: Wrong header %d", c);				return ERROR;			}			continue;		case ZCAN:			sprintf(endmsg, "Sender CANcelled");			return ERROR;		case ZNAK:#ifdef SEGMENTS			putsec(secbuf, chinseg);			chinseg = 0;#endif			if ( --n < 0) {				sprintf(endmsg, "rzfile: got ZNAK", c);				return ERROR;			}			continue;		case TIMEOUT:#ifdef SEGMENTS			putsec(secbuf, chinseg);			chinseg = 0;#endif			if ( --n < 0) {				sprintf(endmsg, "rzfile: TIMEOUT", c);				return ERROR;			}			continue;		case ZFILE:			zrdata(secbuf, 1024);			continue;		case ZEOF:#ifdef SEGMENTS			putsec(secbuf, chinseg);			chinseg = 0;#endif			if (rclhdr(Rxhdr) != rxbytes) {				/*				 * Ignore eof if it's at wrong place - force				 *  a timeout because the eof might have gone				 *  out before we sent our zrpos.				 */				errors = 0;  goto nxthdr;			}			if (closeit()) {				tryzhdrtype = ZFERR;				vfile("rzfile: closeit returned <> 0");				sprintf(endmsg,"Error closing file");				return ERROR;			}			vfile("rzfile: normal EOF");			return c;		case ERROR:	/* Too much garbage in header search error */#ifdef SEGMENTS			putsec(secbuf, chinseg);			chinseg = 0;#endif			if ( --n < 0) {				sprintf(endmsg, "Persistent CRC or other ERROR");				return ERROR;			}			zmputs(Attn);			continue;		case ZSKIP:#ifdef SEGMENTS			putsec(secbuf, chinseg);			chinseg = 0;#endif			Modtime = 1;			closeit();			sprintf(endmsg, "Sender SKIPPED file");			return c;		case ZDATA:			if (rclhdr(Rxhdr) != rxbytes) {				if ( --n < 0) {					sprintf(endmsg,"Data has bad addr");					return ERROR;				}#ifdef SEGMENTS				putsec(secbuf, chinseg);				chinseg = 0;#endif				zmputs(Attn);  continue;			}moredata:			if (Verbose>1)				fprintf(stderr, "\r%7ld ZMODEM%s    ",				  rxbytes, Crc32r?" CRC-32":"");#ifdef SEGMENTS			if (chinseg >= (1024 * SEGMENTS)) {				putsec(secbuf, chinseg);				chinseg = 0;			}			switch (c = zrdata(secbuf+chinseg, 1024))#else			switch (c = zrdata(secbuf, 1024))#endif			{			case ZCAN:#ifdef SEGMENTS				putsec(secbuf, chinseg);				chinseg = 0;#endif				sprintf(endmsg, "Sender CANcelled");				return ERROR;			case ERROR:	/* CRC error */#ifdef SEGMENTS				putsec(secbuf, chinseg);				chinseg = 0;#endif				if ( --n < 0) {					sprintf(endmsg, "Persistent CRC or other ERROR");					return ERROR;				}				zmputs(Attn);				continue;			case TIMEOUT:#ifdef SEGMENTS				putsec(secbuf, chinseg);				chinseg = 0;#endif				if ( --n < 0) {					sprintf(endmsg, "TIMEOUT");					return ERROR;				}				continue;			case GOTCRCW:				n = 20;#ifdef SEGMENTS				chinseg += Rxcount;				putsec(secbuf, chinseg);				chinseg = 0;#else				putsec(secbuf, Rxcount);#endif				rxbytes += Rxcount;				stohdr(rxbytes);				sendline(XON);				zshhdr(4,ZACK, Txhdr);				goto nxthdr;			case GOTCRCQ:				n = 20;#ifdef SEGMENTS				chinseg += Rxcount;#else				putsec(secbuf, Rxcount);#endif				rxbytes += Rxcount;				stohdr(rxbytes);				zshhdr(4,ZACK, Txhdr);				goto moredata;			case GOTCRCG:				n = 20;#ifdef SEGMENTS				chinseg += Rxcount;#else				putsec(secbuf, Rxcount);#endif				rxbytes += Rxcount;				goto moredata;			case GOTCRCE:				n = 20;#ifdef SEGMENTS				chinseg += Rxcount;#else				putsec(secbuf, Rxcount);#endif				rxbytes += Rxcount;				goto nxthdr;			}		}	}}/* * Close the receive dataset, return OK or ERROR */closeit(){	time_t time();	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 (#ifdef POSIX	S_ISREG(Filemode)#else	(Filemode&S_IFMT) == S_IFREG#endif	)		chmod(Pathname, (unsigned short)(07777 & Filemode));	return OK;}/* * 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);}/* End of rz.c */

⌨️ 快捷键说明

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