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

📄 rz.c

📁 linux下的zmodem协议源代码实现
💻 C
📖 第 1 页 / 共 2 页
字号:
#define VERSION "1.03 05-18-86"#define PUBDIR "/usr/spool/uucppublic"/*% cc -DNFGVMIN -K -O % -o rz; size rz * * rz.c By Chuck Forsberg * *	cc -O rz.c -o rz		USG (3.0) Unix * 	cc -O -DV7  rz.c -o rz		Unix V7, BSD 2.8 - 4.3 * *	ln rz rb			For either system * *	ln rz /usr/bin/rbrmail		For remote mail.  Make this the *					login shell. rbrmail then calls *					rmail(1) to deliver mail. * *  Unix is a trademark of Western Electric Company * * A program for Unix to receive files and commands from computers running *  Professional-YAM, PowerCom, YAM, IMP, or programs supporting XMODEM. *  rz uses Unix buffered input to reduce wasted CPU time. * * Iff the program is invoked by rzCOMMAND, output is piped to  * "COMMAND filename" * *  Some systems (Venix, Coherent, Regulus) may not support tty raw mode *  read(2) the same way as Unix. ONEREAD must be defined to force one *  character reads for these systems. Added 7-01-84 CAF * *  Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF  * *  NFGVMIN Added 1-13-85 CAF for PC-AT Xenix systems where c_cc[VMIN] *  doesn't seem to work (even though it compiles without error!). * *  USG UNIX (3.0) ioctl conventions courtesy  Jeff Martin */#define LOGFILE "/tmp/rzlog"#define zperr vfile#include <stdio.h>#include <signal.h>#include <setjmp.h>#include <ctype.h>FILE *popen();#define OK 0#define FALSE 0#define TRUE 1#define ERROR (-1)#define HOWMANY 133int Zmodem=0;		/* ZMODEM protocol requested */int Nozmodem = 0;	/* If invoked as "rb" */unsigned Baudrate;#include "rbsb.c"	/* most of the system dependent stuff here */char *substr();FILE *fout;/* * Routine to calculate the free bytes on the current file system *  ~0 means many free bytes (unknown) */long getfree(){	return(~0L);	/* many free bytes ... */}char *Extensions[] = {".A",".ARC",".CCC",".CL",".CMD",".COM",".CRL",".DAT",".DIR",".EXE",".O",".OBJ",".OVL",".PAG",".REL",".SAV",".SUB",".SWP",".SYS",".TAR",".UTL",".a",".arc",".com",".dat",".o",".obj",".ovl",".sys",".tar",""};/* Ward Christensen / CP/M parameters - Don't change these! */#define ENQ 005#define CAN ('X'&037)#define XOFF ('s'&037)#define XON ('q'&037)#define SOH 1#define STX 2#define EOT 4#define ACK 6#define NAK 025#define CPMEOF 032#define WANTCRC 0103	/* send C not NAK to get crc not checksum */#define TIMEOUT (-2)#define ERRORMAX 5#define RETRYMAX 5#define WCEOT (-10)#define SECSIZ 128	/* cp/m's Magic Number record size */#define PATHLEN 257	/* ready for 4.2 bsd ? */#define KSIZE 1024	/* record size with k option */#define UNIXFILE 0x8000	/* happens to the the S_IFREG file mask bit for stat */int Lastrx;int Crcflg;int Firstsec;int Eofseen;		/* indicates cpm eof (^Z) has been received */int errors;int Restricted=0;	/* restricted; no /.. or ../ in filenames */int Badclose = 0;	/* Error on last close */#ifdef ONEREAD/* Sorry, Regulus and some others don't work right in raw mode! */int Readnum = 1;	/* Number of bytes to ask for in read() from modem */#elseint Readnum = KSIZE;	/* Number of bytes to ask for in read() from modem */#endif#define DEFBYTL 2000000000L	/* default rx file size */long Bytesleft;		/* number of bytes of incoming file left */long Modtime;		/* Unix style mod time for incoming file */short Filemode;		/* Unix style mode for incoming file */char Pathname[PATHLEN];char *Progname;		/* the name by which we were called */int Batch=0;int Wcsmask=0377;int Topipe=0;int MakeLCPathname=TRUE;	/* make received pathname lower case */int Verbose=0;int Quiet=0;		/* overrides logic that would otherwise set verbose */int Nflag = 0;		/* Don't really transfer files */int Rxbinary=FALSE;	/* receive all files in bin mode */int Thisbinary;		/* current file is to be received in bin mode */int Blklen;		/* record length of received packets */char secbuf[KSIZE];char linbuf[KSIZE];int Lleft=0;		/* number of characters in linbuf */time_t timep[2];char zconv;		/* ZMODEM file conversion request */char zmanag;		/* ZMODEM file management request */char ztrans;		/* ZMODEM file transport request */jmp_buf tohere;		/* For the interrupt on RX timeout */unsigned short updcrc();#include "zm.c"alrm(){	longjmp(tohere, -1);}/* called by signal interrupt or terminate to clean things up */bibi(n){	if (Zmodem)		zmputs(Attn);	canit(); mode(0);	fprintf(stderr, "sb: caught signal %d; exiting", n);	exit(128+n);}main(argc, argv)char *argv[];{	register char *cp;	register npats;	char *virgin, **patts;	char *getenv();	int exitcode;	setbuf(stderr, NULL);	if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rsh")))		Restricted=TRUE;	chkinvok(virgin=argv[0]);	/* if called as [-]rzCOMMAND set flag */	npats = 0;	while (--argc) {		cp = *++argv;		if (*cp == '-') {			while( *++cp) {				switch(*cp) {				case '1':					iofd = 1; break;				case '7':					Wcsmask = 0177;				case 'b':					Rxbinary=TRUE; break;				case 'k':				case 'c':					Crcflg=TRUE; break;				case 'D':					Nflag = TRUE; break;				case 'q':					Quiet=TRUE; Verbose=0; break;				case 'u':					MakeLCPathname=FALSE; break;				case 'v':					++Verbose; break;				default:					usage();				}			}		}		else if ( !npats && argc>0) {			if (argv[0][0]) {				npats=argc;				patts=argv;			}		}	}	if (npats > 1)		usage();	if (Verbose) {		if (freopen(LOGFILE, "a", stderr)==NULL) {			printf("Can't open log file %s\n",LOGFILE);			exit(0200);		}		setbuf(stderr, NULL);		fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);	}	if (fromcu() && !Quiet) {		if (Verbose == 0)			Verbose = 2;	}	mode(1);	if (signal(SIGINT, bibi) == SIG_IGN) {		signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);	}	else {		signal(SIGINT, bibi); signal(SIGKILL, bibi);	}	if (wcreceive(npats, patts)==ERROR) {		exitcode=0200;		canit();	}	mode(0);	if (exitcode && !Zmodem)	/* bellow again with all thy might. */		canit();	exit(exitcode);}usage(){	fprintf(stderr,"%s %s for %s by Chuck Forsberg\n",	  Progname, VERSION, OS);	fprintf(stderr,"Usage:	rz [-1buv]		(ZMODEM Batch)\n");	fprintf(stderr,"or	rb [-1buv]		(YMODEM Batch)\n");	fprintf(stderr,"or	rz [-1bcv] file		(XMODEM)\n");	fprintf(stderr,"	  -1 For cu(1): Use fd 1 for input\n");	fprintf(stderr,"	  -b Binary transfer for all files\n");	fprintf(stderr,"	  -u Allow all UPPER CASE names\n");	fprintf(stderr,"	  -v Verbose more v's give more info\n");	fprintf(stderr,"	  -c Use 16 bit CRC	(XMODEM)\n");	exit(1);}/* *  Debugging information output interface routine *//* VARARGS1 */vfile(f, a, b, c)register char *f;{	if (Verbose > 1) {		fprintf(stderr, f, a, b, c);		fprintf(stderr, "\n");	}}/* * Let's receive something already. */wcreceive(argc, argp)char **argp;{	register c;	if (Batch || argc==0) {		Crcflg=(Wcsmask==0377);		if ( !Quiet)			fprintf(stderr, "rz: ready ");		if (c=tryz()) {			if (c == ZCOMPL)				return OK;			if (c == ERROR)				goto fubar;			c = rzfiles();			if (c)				goto fubar;		} else {			for (;;) {				if (wcrxpn(secbuf)== ERROR)					goto fubar;				if (secbuf[0]==0)					return OK;				if (procheader(secbuf) == ERROR)					goto fubar;				if (wcrx()==ERROR)					goto fubar;			}		}	} else {		Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;		strcpy(Pathname, *argp);		checkpath(Pathname);		fprintf(stderr, "\nrz: ready to receive %s ", Pathname);		if ((fout=fopen(Pathname, "w")) == NULL)			return ERROR;		if (wcrx()==ERROR)			goto fubar;	}	return OK;fubar:	canit();	if (Topipe && fout) {		pclose(fout);  return ERROR;	}	if (fout)		fclose(fout);	if (Restricted) {		unlink(Pathname);		fprintf(stderr, "\r\nrz: %s removed.\r\n", Pathname);	}	return ERROR;}/* * Fetch a pathname from the other end as a C ctyle ASCIZ string. * Length is indeterminate as long as less than Blklen * A null string represents no more files (YMODEM) */wcrxpn(rpn)char *rpn;	/* receive a pathname */{	register c;#ifdef NFGVMIN	readline(1);#else	purgeline();#endifet_tu:	Firstsec=TRUE;  Eofseen=FALSE;	sendline(Crcflg?WANTCRC:NAK);	Lleft=0;	/* Do read next time ... */	while ((c = wcgetsec(rpn, 100)) != 0) {		log( "Pathname fetch returned %d\n", c);		if (c == WCEOT) {			sendline(ACK);			Lleft=0;	/* Do read next time ... */			readline(1);			goto et_tu;		}		return ERROR;	}	sendline(ACK);	return OK;}/* * Adapted from CMODEM13.C, written by * Jack M. Wierda and Roderick W. Hart */wcrx(){	register int sectnum, sectcurr;	register char sendchar;	register char *p;	int cblklen;			/* bytes to dump this block */	Firstsec=TRUE;sectnum=0; Eofseen=FALSE;	sendchar=Crcflg?WANTCRC:NAK;	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 &Wcsmask)) {			if (sectnum==0 && !Thisbinary) {				p=secbuf;  sectcurr=Blklen;				if (*p == 032)	/* A hack for .arc files */					goto binbin;				for (; *p != 032 && --sectcurr>=0; ++p)					if (*p < 07 || (*p & 0200)) {binbin:						Thisbinary++;						if (Verbose)							fprintf(stderr, "Changed to BIN\n");						break;					}			}			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&Wcsmask)) {			log( "Received dup Sector\n");			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 {			log( "Sync Error\n");			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=KSIZE; goto get2;		}		if (firstch==SOH) {			Blklen=SECSIZ;get2:			sectcurr=readline(1);			if ((sectcurr+(oldcrc=readline(1)))==Wcsmask) {				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)						log("CRC=0%o\n", oldcrc);					else {						Firstsec=FALSE;						return sectcurr;					}				}				else if (((checksum-firstch)&Wcsmask)==0) {					Firstsec=FALSE;					return sectcurr;				}				else					log( "Checksum Error\n");			}			else				log("Sector number garbled 0%o 0%o\n",				 sectcurr, oldcrc);		}		/* 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) {				log( "Sender CANcelled\n");				return ERROR;			} else {				Lastrx=CAN;				continue;			}		}		else if (firstch==TIMEOUT) {			if (Firstsec)				goto humbug;bilge:			log( "Timeout\n");		}		else			log( "Got 0%o sector header\n", 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;}/* * 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++ & Wcsmask);	}	n = timeout/10;	if (n < 2)		n = 3;	if (Verbose > 3)		fprintf(stderr, "Calling read: n=%d ", n);	if (setjmp(tohere)) {#ifdef TIOCFLUSH/*		ioctl(iofd, TIOCFLUSH, 0); */#endif		Lleft = 0;		if (Verbose>1)			fprintf(stderr, "Readline:TIMEOUT\n");		return TIMEOUT;	}	signal(SIGALRM, alrm); alarm(n);	Lleft=read(iofd, cdq=linbuf, Readnum);	alarm(0);	if (Verbose > 3) {		fprintf(stderr, "Read returned %d bytes\n", Lleft);	}	if (Lleft < 1)		return TIMEOUT;	--Lleft;	if (Verbose > 8) {		fprintf(stderr, "%02x ", *cdq&0377);	}	return (*cdq++ & Wcsmask);}/* * Purge the modem input queue of all characters */purgeline(){	Lleft = 0;#ifdef USG	ioctl(iofd, TCFLSH, 0);#else

⌨️ 快捷键说明

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