?? rz.c
字號:
#define VERSION "3.48 01-27-98"#define PUBDIR "/usr/spool/uucppublic"/* * * rz.c By Chuck Forsberg * Copyright 1997 Omen Technology Inc All Rights Reserved * * 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. * * ********************************************************************* ********************************************************************* * * * This version implements numerous enhancements including ZMODEM * Run Length Encoding and variable length headers. These * features were not funded by the original Telenet development * contract. * * * This software may be freely used for educational (didactic * only) purposes. "Didactic" means it is used as a study item * in a course teaching the workings of computer protocols. * * This software may also be freely used to support file transfer * operations to or from duly licensed Omen Technology products. * This includes DSZ, GSZ, ZCOMM, Professional-YAM and PowerCom. * Institutions desiring to use rz/sz this way should add the * following to the sz compile line: -DCOMPL * Programs based on stolen or public domain ZMODEM materials are * not included. Use with other commercial or shareware programs * (Crosstalk, Procomm, etc.) REQUIRES REGISTRATION. * * * Any programs which incorporate part or all of this code must be * provided in source form with this notice intact except by * prior written permission from Omen Technology Incorporated. * This includes compiled executables of this program. * * The .doc files and the file "mailer.rz" must also be included. * * Use of this software for commercial or administrative purposes * except when exclusively limited to interfacing Omen Technology * products requires license payment of $20.00 US per user * (less in quantity, see mailer.rz). Use of this code by * inclusion, decompilation, reverse engineering or any other means * constitutes agreement to these conditions and acceptance of * liability to license the materials and payment of reasonable * legal costs necessary to enforce this license agreement. * * * Omen Technology Inc * Post Office Box 4681 * Portland OR 97208 * * This code is made available in the hope it will be useful, * BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY * DAMAGES OF ANY KIND. * * * -DMD may be added to compiler command line to compile in * Directory-creating routines from Public Domain TAR by John Gilmore * * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin */char *Copyrrz = "Copyright 1997 Omen Technology Inc All Rights Reserved";#define LOGFILE "/tmp/rzlog"#define LOGFILE2 "rzlog"#include <stdio.h>#include <signal.h>#include <ctype.h>#include <errno.h>extern int errno;#define OK 0#define FALSE 0#define TRUE 1#define ERROR (-1)/* * Max value for HOWMANY is 255. * A larger value reduces system overhead but may evoke kernel bugs. */#ifndef HOWMANY#define HOWMANY 96#endif/* 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 RCDO (-3)#define GCOUNT (-4)#define ERRORMAX 5#define RETRYMAX 5#define WCEOT (-10)#define PATHLEN 257 /* ready for 4.2 bsd ? */#define UNIXFILE 0xF000 /* The S_IFMT file mask bit for stat */int Zmodem=0; /* ZMODEM protocol requested */int Nozmodem = 0; /* If invoked as "rb" */unsigned Baudrate = 9600;#include "rbsb.c" /* most of the system dependent stuff here */#include "crctab.c"char endmsg[90] = {0}; /* Possible message to display on exit */char Zsendmask[33]; /* Additional control chars to mask */char *substr();FILE *fout;/* * Routine to calculate the free bytes on the current file system * ~0 means many free bytes (unknown) */long getfree(){ return(2147483647); /* many free bytes ... */}int Lastrx;long rxbytes;int Crcflg;int Firstsec;int Eofseen; /* indicates cpm eof (^Z) has been received */int errors;int Restricted=0; /* restricted; no /.. or ../ in filenames */#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 */int Filemode; /* Unix style mode for incoming file */long Totalleft;long Filesleft;char Pathname[PATHLEN];char *Progname; /* the name by which we were called */int Batch=0;int Thisbinary; /* current file is to be received in bin mode */int Rxbinary=FALSE; /* receive all files in bin mode */int Rxascii=FALSE; /* receive files in ascii (translate) mode */int Blklen; /* record length of received packets */#ifdef SEGMENTSint chinseg = 0; /* Number of characters received in this data seg */char secbuf[1+(SEGMENTS+1)*1024];#elsechar secbuf[1025];#endiftime_t timep[2];char Lzmanag; /* Local file management request */char Lzconv; /* Local ZMODEM file conversion request */char zconv; /* ZMODEM file conversion request */char zmanag; /* ZMODEM file management request */char ztrans; /* ZMODEM file transport request */int Zctlesc; /* Encode control characters */int Zrwindow = 1400; /* RX window size (controls garbage count) *//* * Log an error */voidzperr1(s,p,u)char *s, *p, *u;{ if (Verbose <= 0) return; fprintf(stderr, "Retry %d: ", errors); fprintf(stderr, s); fprintf(stderr, "\n");}voidzperr2(s,p,u)char *s, *p, *u;{ if (Verbose <= 0) return; fprintf(stderr, "Retry %d: ", errors); fprintf(stderr, s, p); fprintf(stderr, "\n");}voidzperr3(s,p,u)char *s, *p, *u;{ if (Verbose <= 0) return; fprintf(stderr, "Retry %d: ", errors); fprintf(stderr, s, p, u); fprintf(stderr, "\n");}#include "zm.c"#include "zmr.c"int tryzhdrtype=ZRINIT; /* Header type to send corresponding to Last rx close *//* called by signal interrupt or terminate to clean things up */voidbibi(n){ if (Zmodem) zmputs(Attn); canit(); mode(0); fprintf(stderr, "rz: caught signal %d; exiting", n); exit(3);}main(argc, argv)char *argv[];{ register char *cp; register npats; char *virgin, **patts; int exitcode = 0; Rxtimeout = 100; setbuf(stderr, NULL); if (((cp = getenv("RESTRICTED")) != 0) && *cp == '1') Restricted=TRUE; if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh"))) Restricted=TRUE; chkinvok(virgin=argv[0]); inittty(); npats = 0; while (--argc) { cp = *++argv; if (*cp == '-') { ++cp; while( *cp) { if (isdigit(*cp)) { ++cp; continue; } switch(*cp++) { case '\\': *cp = toupper(*cp); continue; case 'a': if (!Batch || Nozmodem) Rxascii=TRUE; else usage(); break; case 't': if (isdigit(*cp)) Rxtimeout = atoi(cp); else { if (--argc < 1) usage(); Rxtimeout = atoi(*++argv); } if (Rxtimeout<1 || Rxtimeout>1000) usage(); break; case 'w': if (isdigit(*cp)) Zrwindow = atoi(cp); else { if (--argc < 1) usage(); Zrwindow = atoi(*++argv); } break; case 'v': ++Verbose; break; case 'y': Lzmanag = ZMCLOB; break; default: usage(); } } } else if ( !npats && argc>0) { if (argv[0][0]) { npats=argc; patts=argv; } } } if (npats > 1) usage(); if (Batch && npats) usage(); if (Verbose) { if (freopen(LOGFILE, "a", stderr)==NULL) if (freopen(LOGFILE2, "a", stderr)==NULL) { fprintf(stderr, "Can't open log file!\n"); exit(2); } setbuf(stderr, NULL); fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname); } vfile("%s %s for %s tty=%s\n", Progname, VERSION, OS, Nametty); mode(1); if (signal(SIGINT, bibi) == SIG_IGN) { signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN); } else { signal(SIGINT, bibi); signal(SIGKILL, bibi); } signal(SIGTERM, bibi); if (wcreceive(npats, patts)==ERROR) { exitcode=1; canit(); } if (exitcode && !Zmodem) /* bellow again with all thy might. */ canit(); if (endmsg[0]) fprintf(stderr, " %s: %s\r\n", Progname, endmsg); fprintf(stderr, "%s %s finished.\r\n", Progname, VERSION); fflush(stderr);#ifndef REGISTERED /* Removing or disabling this code without registering is theft */ if (!Usevhdrs) { fprintf(stderr, "\n\n\n**** UNREGISTERED COPY *****\r\n"); fprintf(stderr, "Please read the License Agreement in rz.doc\r\n"); fflush(stderr); sleep(10); }#endif mode(0); if(exitcode) exit(1); exit(0); /* NOTREACHED */}usage(){ fprintf(stderr, "Receive Files and Commands with ZMODEM/YMODEM/XMODEM Protocol\n\n"); fprintf(stderr,"Usage: rz [-v] [-wN] [-tT] (ZMODEM)\n"); fprintf(stderr,"or rb [-avy] [-tT] (YMODEM)\n"); fprintf(stderr,"or rc [-avy] [-tT] file (XMODEM-CRC)\n"); fprintf(stderr,"or rx [-avy] [-tT] file (XMODEM)\n\n"); fprintf(stderr,"Supports the following incoming ZMODEM options given to the sending program:\n\ compression (-Z), binary (-b), ASCII CR/LF>NL (-a), newer(-n),\n\ newer+longer(-N), protect (-p), Crash Recovery (-r),\n\ clobber (-y), match+clobber (-Y), and append (-+).\n\n"); fprintf(stderr,"%s %s for %s by Chuck Forsberg, Omen Technology INC\n", Progname, VERSION, OS); fprintf(stderr, "\t\t\042The High Reliability Software\042\n\n"); fprintf(stderr,"Copyright (c) 1997 Omen Technology INC All Rights Reserved\n"); fprintf(stderr, "See rz.doc and README for option descriptions and licensing information.\n\n"); fprintf(stderr, "This program is designed to talk to terminal programs,\nnot to be called by one.\n");#ifndef REGISTERED fprintf(stderr, "\n\n\n **** UNREGISTERED COPY *****\r\n"); fprintf(stderr, "Please read the License Agreement in rz.doc\r\n");#endif exit(2);}/* * Let's receive something already. */char *rbmsg = "%s ready. Type \"%s file ...\" to your modem program\n\r";wcreceive(argc, argp)char **argp;{ register c; if (Batch || argc==0) { Crcflg=1; fprintf(stderr, rbmsg, Progname, Nozmodem?"sb":"sz"); if (c=tryz()) { if (c == ZCOMPL) return OK; if (c == ERROR) goto fubar; c = rzfiles(); if (c) } else { for (;;) { if (wcrxpn(secbuf)== ERROR) goto fubar; if (secbuf[0]==0) return OK; if (procheader(secbuf)) goto fubar; if (wcrx()==ERROR) goto fubar; } } } else { Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L; procheader(""); strcpy(Pathname, *argp); checkpath(Pathname); fprintf(stderr, "\nrz: ready to receive %s\r\n", Pathname); if ((fout=fopen(Pathname, "w")) == NULL) return ERROR; goto fubar; } return OK;fubar: canit(); Modtime = 1; 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; purgeline();et_tu: Firstsec=TRUE; Eofseen=FALSE; sendline(Crcflg?WANTCRC:NAK); flushmo(); Lleft=0; /* Do read next time ... */ switch (c = wcgetsec(rpn, 100)) { case WCEOT: zperr2( "Pathname fetch returned %d", c); sendline(ACK); flushmo(); Lleft=0; /* Do read next time ... */ readline(1); goto et_tu; case 0: sendline(ACK); flushmo(); return OK; default: return ERROR; }}/* * Adapted from CMODEM13.C, written by * Jack M. Wierda and Roderick W. Hart */wcrx(){ register int sectnum, sectcurr; register char sendchar; 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! */ flushmo(); Lleft=0; /* Do read next time ... */ sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130); 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)) { zperr1( "Received dup Sector"); sendchar=ACK; } else if (sectcurr==WCEOT) { if (closeit()) return ERROR; sendline(ACK); flushmo(); Lleft=0; /* Do read next time ... */ return OK; } else if (sectcurr==ERROR) return ERROR; else { zperr1( "Sync Error"); return ERROR; } } /* NOTREACHED */}/* * 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) zperr1( "CRC"); else { Firstsec=FALSE; return sectcurr; } } else if (((checksum-firstch)&0377)==0) { Firstsec=FALSE; return sectcurr; } else zperr1( "Checksum"); } else zperr1("Sector number garbled"); } /* make sure eot really is eot and not just mixmash */ else if (firstch==EOT && Lleft==0) return WCEOT; else if (firstch==CAN) { if (Lastrx==CAN) { zperr1( "Sender CANcelled"); return ERROR; } else { Lastrx=CAN; continue; } } else if (firstch==TIMEOUT) { if (Firstsec) goto humbug;bilge: zperr1( "TIMEOUT"); } else zperr1( "Got 0%o sector header", firstch);humbug: Lastrx=0; while(readline(1)!=TIMEOUT) ; if (Firstsec) { sendline(Crcflg?WANTCRC:NAK); flushmo(); Lleft=0; /* Do read next time ... */ } else { maxtime=40; sendline(NAK); flushmo(); Lleft=0; /* Do read next time ... */ } } /* try to stop the bubble machine. */ canit(); return ERROR;}/* * Process incoming file information header * Returns 0 for success, other codes for errors * or skip conditions. */procheader(name)char *name;{ register char *openmode, *p; static dummy; struct stat f; /* set default parameters and overrides */ openmode = "w"; Thisbinary = (!Rxascii) || Rxbinary; if (zconv == ZCBIN && Lzconv != ZCRESUM) Lzconv = zconv; /* Remote Binary override */ if (Lzconv) zconv = Lzconv; 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"; Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L; if (!name || !*name) return 0; p = name + 1 + strlen(name); if (*p) { /* file coming from Unix or DOS system */ sscanf(p, "%ld%lo%o%lo%d%ld%d%d", &Bytesleft, &Modtime, &Filemode, &dummy, &Filesleft, &Totalleft, &dummy, &dummy); if (Filemode & UNIXFILE) ++Thisbinary; if (Verbose) { fprintf(stderr, "Incoming: %s %ld %lo %o\n", name, Bytesleft, Modtime, Filemode); fprintf(stderr, "YMODEM header: %s\n", p); } } else { /* File coming from CP/M system */ for (p=name; *p; ++p) /* change / to _ */ if ( *p == '/') *p = '_'; if ( *--p == '.') /* zap trailing period */ *p = 0; } strcpy(Pathname, name); checkpath(name); if (*name && stat(name, &f)!= -1) { zmanag &= ZMMASK; if (zmanag==ZMPROT) goto skipfile; vfile("Current %s is %ld %lo", name, f.st_size, f.st_mtime); if (Thisbinary && zconv==ZCRESUM) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -