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

📄 rz.c

📁 ZMODEM协议的实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	for (;;) {		sendline(sendchar);	/* send it now, we're ready! */		Lleft=0;	/* Do read next time ... */		sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130);		report(sectcurr);		if (sectcurr==(sectnum+1 &0377)) {			sectnum++;			cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;			if (putsec(secbuf, cblklen)==ERROR)				return ERROR;			if ((Bytesleft-=cblklen) < 0)				Bytesleft = 0;			sendchar=ACK;		}		else if (sectcurr==(sectnum&0377)) {			zperr( "Received dup Sector");			sendchar=ACK;		}		else if (sectcurr==WCEOT) {			if (closeit())				return ERROR;			sendline(ACK);			Lleft=0;	/* Do read next time ... */			return OK;		}		else if (sectcurr==ERROR)			return ERROR;		else {			zperr( "Sync Error");			return ERROR;		}	}}/* * Wcgetsec fetches a Ward Christensen type sector. * Returns sector number encountered or ERROR if valid sector not received, * or CAN CAN received * or WCEOT if eot sector * time is timeout for first char, set to 4 seconds thereafter ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK ************** *    (Caller must do that when he is good and ready to get next sector) */wcgetsec(rxbuf, maxtime)char *rxbuf;int maxtime;{	register checksum, wcj, firstch;	register unsigned short oldcrc;	register char *p;	int sectcurr;	for (Lastrx=errors=0; errors<RETRYMAX; errors++) {		if ((firstch=readline(maxtime))==STX) {			Blklen=1024; goto get2;		}		if (firstch==SOH) {			Blklen=128;get2:			sectcurr=readline(1);			if ((sectcurr+(oldcrc=readline(1)))==0377) {				oldcrc=checksum=0;				for (p=rxbuf,wcj=Blklen; --wcj>=0; ) {					if ((firstch=readline(1)) < 0)						goto bilge;					oldcrc=updcrc(firstch, oldcrc);					checksum += (*p++ = firstch);				}				if ((firstch=readline(1)) < 0)					goto bilge;				if (Crcflg) {					oldcrc=updcrc(firstch, oldcrc);					if ((firstch=readline(1)) < 0)						goto bilge;					oldcrc=updcrc(firstch, oldcrc);					if (oldcrc & 0xFFFF)						zperr( "CRC");					else {						Firstsec=FALSE;						return sectcurr;					}				}				else if (((checksum-firstch)&0377)==0) {					Firstsec=FALSE;					return sectcurr;				}				else					zperr( "Checksum");			}			else				zperr("Sector number garbled");		}		/* make sure eot really is eot and not just mixmash */#ifdef NFGVMIN		else if (firstch==EOT && readline(1)==TIMEOUT)			return WCEOT;#else		else if (firstch==EOT && Lleft==0)			return WCEOT;#endif		else if (firstch==CAN) {			if (Lastrx==CAN) {				zperr( "Sender CANcelled");				return ERROR;			} else {				Lastrx=CAN;				continue;			}		}		else if (firstch==TIMEOUT) {			if (Firstsec)				goto humbug;bilge:			zperr( "TIMEOUT");		}		else			zperr( "Got 0%o sector header", firstch);humbug:		Lastrx=0;		while(readline(1)!=TIMEOUT)			;		if (Firstsec) {			sendline(Crcflg?WANTCRC:NAK);			Lleft=0;	/* Do read next time ... */		} else {			maxtime=40; sendline(NAK);			Lleft=0;	/* Do read next time ... */		}	}	/* try to stop the bubble machine. */	canit();	return ERROR;}#ifndef vax11c/* * This version of readline is reasoably well suited for * reading many characters. *  (except, currently, for the Regulus version!) * * timeout is in tenths of seconds */readline(timeout)int timeout;{	register n;	static char *cdq;	/* pointer for removing chars from linbuf */	if (--Lleft >= 0) {		if (Verbose > 8) {			fprintf(stderr, "%02x ", *cdq&0377);		}		return (*cdq++ & 0377);	}	n = timeout/10;	if (n < 2)		n = 3;	if (Verbose > 5)		fprintf(stderr, "Calling read: alarm=%d  Readnum=%d ",		  n, Readnum);	if (setjmp(tohere)) {#ifdef TIOCFLUSH/*		ioctl(0, TIOCFLUSH, 0); */#endif		Lleft = 0;		if (Verbose>1)			fprintf(stderr, "Readline:TIMEOUT\n");		return TIMEOUT;	}	signal(SIGALRM, alrm); alarm(n);	Lleft=read(0, cdq=linbuf, Readnum);	alarm(0);	if (Verbose > 5) {		fprintf(stderr, "Read returned %d bytes\n", Lleft);	}	if (Lleft < 1)		return TIMEOUT;	--Lleft;	if (Verbose > 8) {		fprintf(stderr, "%02x ", *cdq&0377);	}	return (*cdq++ & 0377);}/* * Purge the modem input queue of all characters */purgeline(){	Lleft = 0;#ifdef USG	ioctl(0, TCFLSH, 0);#else	lseek(0, 0L, 2);#endif}#endif/* * Process incoming file information header */procheader(name)char *name;{	register char *openmode, *p, **pp;	/* set default parameters and overrides */	openmode = "w";	Thisbinary = (!Rxascii) || Rxbinary;	if (Lzmanag)		zmanag = Lzmanag;	/*	 *  Process ZMODEM remote file management requests	 */	if (!Rxbinary && zconv == ZCNL)	/* Remote ASCII override */		Thisbinary = 0;	if (zconv == ZCBIN)	/* Remote Binary override */		Thisbinary = TRUE;	else if (zmanag == ZMAPND)		openmode = "a";#ifndef BIX	/* Check for existing file */	if (!Rxclob && (zmanag&ZMMASK) != ZMCLOB && (fout=fopen(name, "r"))) {		fclose(fout);  return ERROR;	}#endif	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);#ifndef vax11c		if (Filemode & UNIXFILE)			++Thisbinary;#endif		if (Verbose) {			fprintf(stderr,  "Incoming: %s %ld %lo %o\n",			  name, Bytesleft, Modtime, Filemode);		}	}#ifdef BIX	if ((fout=fopen("scratchpad", openmode)) == NULL)		return ERROR;	return OK;#else	else {		/* File coming from CP/M system */		for (p=name; *p; ++p)		/* change / to _ */			if ( *p == '/')				*p = '_';		if ( *--p == '.')		/* zap trailing period */			*p = 0;	}#ifndef vax11c	if (!Zmodem && MakeLCPathname && !IsAnyLower(name)	  && !(Filemode&UNIXFILE))		uncaps(name);#endif	if (Topipe > 0) {		sprintf(Pathname, "%s %s", Progname+2, name);		if (Verbose)			fprintf(stderr,  "Topipe: %s %s\n",			  Pathname, Thisbinary?"BIN":"ASCII");#ifndef vax11c		if ((fout=popen(Pathname, "w")) == NULL)			return ERROR;#endif	} 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";#ifndef vax11c		if (name[0] == '!' || name[0] == '|') {			if ( !(fout = popen(name+1, "w"))) {				return ERROR;			}			Topipe = -1;  return(OK);		}#endif#ifdef MD		fout = fopen(name, openmode);		if ( !fout)			if (make_dirs(name))				fout = fopen(name, openmode);#else		fout = fopen(name, openmode);#endif		if ( !fout)			return ERROR;	}	return OK;#endif /* BIX */}#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 */	char *strchr();	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(-1);		/* 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;}#ifndef vax11c/* *  Send a character to modem.  Small is beautiful. */sendline(c){	char d;	d = c;	if (Verbose>6)		fprintf(stderr, "Sendline: %x\n", c);	write(1, &d, 1);}flushmo() {}#endif/* 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;}/* * 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*/zperr(s,p,u)char *s, *p, *u;{	if (Verbose <= 0)

⌨️ 快捷键说明

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