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

📄 sz.c

📁 linux下的zmodem协议源代码实现
💻 C
📖 第 1 页 / 共 2 页
字号:
#define VERSION "sz 1.03 05-18-86"#define PUBDIR "/usr/spool/uucppublic"/*% cc -O -K sz.c -o sz; size sz * sz.c By Chuck Forsberg * *	cc -O sz.c -o sz		USG (SYS III/V) Unix * 	cc -O -DV7  sz.c -o sz		Unix Version 7, 2.8 - 4.3 BSD * *  ******* Some systems (Venix, Coherent, Regulus) do not ******* *  ******* support tty raw mode read(2) identically to    ******* *  ******* Unix. ONEREAD must be defined to force one     ******* *  ******* character reads for these systems.		   ******* * * A program for Unix to send files and commands to computers running *  Professional-YAM, PowerCom, YAM, IMP, or programs supporting XMODEM. * *  Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM. * *  USG UNIX (3.0) ioctl conventions courtesy Jeff Martin *//* * Attention string to be executed by receiver to interrupt streaming data *  when an error is detected.  A pause (0336) may be needed before the *  ^C (03) or after it. */char Myattn[] = { 03, 0336, 0 };unsigned updcrc();char *substr(), *getenv();#define LOGFILE "/tmp/szlog"#define zperr vfile#include <stdio.h>#include <signal.h>#include <setjmp.h>#include <ctype.h>#define PATHLEN 256#define OK 0#define FALSE 0#define TRUE 1#define ERROR (-1)#define HOWMANY 2int Zmodem=0;		/* ZMODEM protocol requested */unsigned Baudrate;#include "rbsb.c"	/* most of the system dependent stuff here */FILE *in;/* 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 WANTG 0107	/* Send G not NAK to get nonstop batch xmsn */#define TIMEOUT (-2)#define RETRYMAX 10#define SECSIZ 128	/* cp/m's Magic Number record size */#define KSIZE 1024char Lastrx;char Crcflg;int Wcsmask=0377;int Verbose=0;int Modem=0;		/* MODEM - don't send pathnames */int Restricted=0;	/* restricted; no /.. or ../ in filenames */int Quiet=0;		/* overrides logic that would otherwise set verbose */int Ascii=0;		/* Add CR's for brain damaged programs */int Fullname=0;		/* transmit full pathname */int Unlinkafter=0;	/* Unlink file after it is sent */int Dottoslash=0;	/* Change foo.bar.baz to foo/bar/baz */int firstsec;int errcnt=0;		/* number of files unreadable */int blklen=SECSIZ;		/* length of transmitted records */int Optiong;		/* Let it rip no wait for sector ACK's */int Noeofseen;int Totsecs;		/* total number of sectors this file */char txbuf[KSIZE];int Filcnt=0;		/* count of number of files opened */int Lfseen=0;unsigned Rxbuflen = 16384;	/* Receiver's max buffer length */int Rxflags = 0;char Lzconv;	/* Local ZMODEM file conversion request */char Lzmanag;	/* Local ZMODEM file management request */char Lztrans;char zconv;		/* ZMODEM file conversion request */char zmanag;		/* ZMODEM file management request */char ztrans;		/* ZMODEM file transport request */int Command;		/* Send a command, then exit. */char *Cmdstr;		/* Pointer to the command string */int Cmdtries = 11;int Cmdack1;		/* Rx ACKs command, then do it */int Exitcode;int Testattn;		/* Force receiver to send Attn, etc with qbf. */char *qbf="The quick brown fox jumped over the lazy dog's back 1234567890\r\n";jmp_buf tohere;		/* For the interrupt on RX timeout */jmp_buf intrjmp;	/* For the interrupt on RX CAN *//* called by signal interrupt or terminate to clean things up */bibi(n){	canit(); fflush(stdout); mode(0);	fprintf(stderr, "sz: caught signal %d; exiting\n", n);	if (n == SIGQUIT)		abort();	exit(128+n);}/* Called when Zmodem gets an interrupt (^X) */onintr(){	signal(SIGINT, SIG_IGN);	longjmp(intrjmp, -1);}#define sendline(c) putchar(c & Wcsmask)#define xsendline(c) putchar(c)flushmo(){	fflush(stdout);}#include "zm.c"main(argc, argv)char *argv[];{	register char *cp;	register npats;	int agcnt; char **agcv;	char **patts;	static char xXbuf[BUFSIZ];	if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rsh")))		Restricted=TRUE;	Rxtimeout = 600;	npats=0;	if (argc<2)		usage();	setbuf(stdout, xXbuf);			while (--argc) {		cp = *++argv;		if (*cp++ == '-' && *cp) {			while ( *cp) {				switch(*cp++) {				case '+':					Lzmanag = ZMAPND; break;				case '1':					iofd = 1; break;				case '7':					Wcsmask=0177; break;				case 'a':					Lzconv = ZCNL;					Ascii = TRUE; break;				case 'b':					Lzconv = ZCBIN; break;				case 'C':					if (--argc < 1) {						usage();					}					Cmdtries = atoi(*++argv);					break;				case 'i':					Cmdack1 = ZCACK1;					/* **** FALL THROUGH TO **** */				case 'c':					if (--argc != 1) {						usage();					}					Command = TRUE;					Cmdstr = *++argv;					break;				case 'd':					++Dottoslash;					/* **** FALL THROUGH TO **** */				case 'f':					Fullname=TRUE; break;				case 'k':					blklen=KSIZE; break;				case 'N':					Lzmanag = ZMCRC;  break;				case 'n':					Lzmanag = ZMNEW;  break;				case 'r':					Lzconv = ZCRESUM;				case 'q':					Quiet=TRUE; Verbose=0; break;				case 'T':					Testattn = TRUE; break;				case 'u':					++Unlinkafter; break;				case 'v':					++Verbose; break;				case 'X':					++Modem; break;				case 'y':					Lzmanag = ZMCLOB; break;				default:					usage();				}			}		}		else if ( !npats && argc>0) {			if (argv[0][0]) {				npats=argc;				patts=argv;				if ( !strcmp(*patts, "-"))					iofd = 1;			}		}	}	if (npats < 1 && !Command) 		usage();	if (Verbose) {		if (freopen(LOGFILE, "a", stderr)==NULL) {			printf("Can't open log file %s\n",LOGFILE);			exit(0200);		}		setbuf(stderr, NULL);	}	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);		signal(SIGQUIT, bibi);	}	if ( !Modem) {		if (!Command) {			printf("rz\r");  fflush(stdout);		}		if (!Command && !Quiet && Verbose != 1) {			fprintf(stderr, "sz: %d file%s requested:\r\n",			 npats, npats>1?"s":"");			for ( agcnt=npats, agcv=patts; --agcnt>=0; ) {				fprintf(stderr, "%s ", *agcv++);			}			fprintf(stderr, "\r\n");			printf("\r\n\bSending in Batch Mode\r\n");		}		stohdr(0L);		if (Command)			Txhdr[ZF0] = ZCOMMAND;		zshhdr(ZRQINIT, Txhdr);	}	fflush(stdout);	if (Command) {		if (getzrxinit()) {			Exitcode=0200; canit();		}		else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {			Exitcode=0200; canit();		}	} else if (wcsend(npats, patts)==ERROR) {		Exitcode=0200;		canit();	}	fflush(stdout);	mode(0);	exit((errcnt != 0) | Exitcode);	/*NOTREACHED*/}wcsend(argc, argp)char *argp[];{	register n;	Crcflg=FALSE;	firstsec=TRUE;	for (n=0; n<argc; ++n) {		Totsecs = 0;		if (wcs(argp[n])==ERROR)			return ERROR;	}	Totsecs = 0;	if (Filcnt==0) {	/* bitch if we couldn't open ANY files */		fprintf(stderr,"\r\nCan't open any requested files.\r\n");		return ERROR;	}	if (Zmodem)		saybibi();	else		wctxpn("");	return OK;}wcs(oname)char *oname;{	register c;	register char *p;	struct stat f;	char name[PATHLEN];	strcpy(name, oname);	if (Restricted) {		/* restrict pathnames to current tree or uucppublic */		if ( substr(name, "../")		 || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {			canit();			fprintf(stderr,"\r\nsz:\tSecurity Violation\r\n");			return ERROR;		}	}	if ( !strcmp(oname, "-")) {		if ((p = getenv("ONAME")) && *p)			strcpy(name, p);		else			sprintf(name, "s%d.sz", getpid());		in = stdin;	}	else if ((in=fopen(oname, "r"))==NULL) {		++errcnt;		return OK;	/* pass over it, there may be others */	}	++Noeofseen;	/* Check for directory or block special files */	fstat(fileno(in), &f);	c = f.st_mode & S_IFMT;	if (c == S_IFDIR || c == S_IFBLK) {		fclose(in);		return OK;	}	++Filcnt;	switch (wctxpn(name)) {	case ERROR:		return ERROR;	case ZSKIP:		return OK;	}	if (!Zmodem && wctx()==ERROR)		return ERROR;	if (Unlinkafter)		unlink(oname);	return 0;}/* * generate and transmit pathname block consisting of *  pathname (null terminated), *  file length, mode time and file mode in octal *  as provided by the Unix fstat call. *  N.B.: modifies the passed name, may extend it! */wctxpn(name)char *name;{	register char *p, *q;	char name2[PATHLEN];	struct stat f;	if (Modem) {		if ((in!=stdin) && *name && fstat(fileno(in), &f)!= -1) {			fprintf(stderr, "Sending %s, %ld blocks: ",			  name, f.st_size>>7);		}		fprintf(stderr, "Give your local XMODEM receive command now.\r\n");		return OK;	}	logent("\r\nAwaiting pathname nak for %s\r\n", *name?name:"<END>");	if ( !Zmodem)		if (getnak())			return ERROR;	q = (char *) 0;	if (Dottoslash) {		/* change . to . */		for (p=name; *p; ++p) {			if (*p == '/')				q = p;			else if (*p == '.')				*(q=p) = '/';		}		if (q && strlen(++q) > 8) {	/* If name>8 chars */			q += 8;			/*   make it .ext */			strcpy(name2, q);	/* save excess of name */			*q = '.';			strcpy(++q, name2);	/* add it back */		}	}	for (p=name, q=txbuf ; *p; )		if ((*q++ = *p++) == '/' && !Fullname)			q = txbuf;	*q++ = 0;	p=q;	while (q < (txbuf + KSIZE))		*q++ = 0;	if (!Ascii && (in!=stdin) && *name && fstat(fileno(in), &f)!= -1)		sprintf(p, "%lu %lo %o", f.st_size, f.st_mtime, f.st_mode);	/* force 1k blocks if name won't fit in 128 byte block */	if (txbuf[125])		blklen=KSIZE;	else {		/* A little goodie for IMP/KMD */		if (Zmodem)			blklen = SECSIZ;		txbuf[127] = f.st_size >>7;		txbuf[126] = f.st_size >>15;	}	if (Zmodem)		return zsendfile(txbuf, 1+strlen(p)+(p-txbuf));	if (wcputsec(txbuf, 0, SECSIZ)==ERROR)		return ERROR;	return OK;}getnak(){	register firstch;	Lastrx = 0;	for (;;) {		switch (firstch = readock(800,1)) {		case ZPAD:			if (getzrxinit())				return ERROR;			Ascii = 0;			return FALSE;		case TIMEOUT:			logent("Timeout on pathname\n");			return TRUE;		case WANTG:			mode(2);	/* Set cbreak, XON/XOFF, etc. */			Optiong = TRUE;			blklen=KSIZE;		case WANTCRC:			Crcflg = TRUE;		case NAK:			return FALSE;		case CAN:			if (Lastrx == CAN)				return TRUE;		default:			break;		}		Lastrx = firstch;	}}wctx(){	register int sectnum, attempts, firstch;	firstsec=TRUE;	while ((firstch=readock(400, 2))!=NAK && firstch != WANTCRC	  && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN)		;	if (firstch==CAN) {		logent("Receiver CANcelled\n");		return ERROR;	}	if (firstch==WANTCRC)		Crcflg=TRUE;	if (firstch==WANTG)		Crcflg=TRUE;	sectnum=1;	while (filbuf(txbuf, blklen)) {		if (wcputsec(txbuf, sectnum, blklen)==ERROR) {			return ERROR;		} else			sectnum++;	}	if (Verbose>1)		fprintf(stderr, " Closing ");	fclose(in);	attempts=0;	do {		logent(" EOT ");		purgeline();		sendline(EOT);		fflush(stdout);		++attempts;	}		while ((firstch=(readock(100, 1)) != ACK) && attempts < RETRYMAX);	if (attempts == RETRYMAX) {		logent("No ACK on EOT\n");		return ERROR;	}	else		return OK;}wcputsec(buf, sectnum, cseclen)char *buf;int sectnum;int cseclen;	/* data length of this sector to send */{	register checksum, wcj;	register char *cp;	unsigned oldcrc;	int firstch;	int attempts;	firstch=0;	/* part of logic to detect CAN CAN */	if (Verbose>1)		fprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs/8 );	for (attempts=0; attempts <= RETRYMAX; attempts++) {		Lastrx= firstch;		sendline(cseclen==KSIZE?STX:SOH);		sendline(sectnum);		sendline(-sectnum -1);		oldcrc=checksum=0;		for (wcj=cseclen,cp=buf; --wcj>=0; ) {			sendline(*cp);			oldcrc=updcrc(*cp, oldcrc);			checksum += *cp++;		}		if (Crcflg) {			oldcrc=updcrc(0,updcrc(0,oldcrc));			sendline((int)oldcrc>>8);			sendline((int)oldcrc);		}		else			sendline(checksum);		if (Optiong) {			firstsec = FALSE; return OK;		}		firstch = readock(400, (Noeofseen&&sectnum) ? 2:1);gotnak:		switch (firstch) {		case CAN:			if(Lastrx == CAN) {cancan:				logent("Cancelled\n");  return ERROR;			}			break;		case TIMEOUT:			logent("Timeout on sector ACK\n"); continue;		case WANTCRC:			if (firstsec)				Crcflg = TRUE;		case NAK:			logent("NAK on sector\n"); continue;		case ACK: 			firstsec=FALSE;			Totsecs += (cseclen>>7);			return OK;		case ERROR:			logent("Got burst for sector ACK\n"); break;		default:			logent("Got %02x for sector ACK\n", firstch); break;		}		for (;;) {			Lastrx = firstch;			if ((firstch = readock(400, 2)) == TIMEOUT)				break;			if (firstch == NAK || firstch == WANTCRC)

⌨️ 快捷键说明

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