📄 sz.c
字号:
#define VERSION "sz 1.44 03-03-88"#define PUBDIR "/usr/spool/uucppublic"/*% cc -M0 -Ox -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz; size sz * * sz.c By Chuck Forsberg * * cc -O sz.c -o sz USG (SYS III/V) Unix * cc -O -DSV sz.c -o sz Sys V Release 2 with non-blocking input * Define to allow reverse channel checking * cc -O -DV7 sz.c -o sz Unix Version 7, 2.8 - 4.3 BSD * * cc -O -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz Xenix * * ln sz sb **** All versions **** * ln sz sx **** All versions **** * * * ******* 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 Y/XMODEM. * * Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM. * * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin * * 1.34 implements tx backchannel garbage count and ZCRCW after ZRPOS * in accordance with the 7-31-87 ZMODEM Protocol Description */char *substr(), *getenv();#define LOGFILE "/tmp/szlog"#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 by receiver */unsigned Baudrate;unsigned Txwindow; /* Control the size of the transmitted window */unsigned Txwspac; /* Spacing between zcrcq requests */unsigned Txwcnt; /* Counter used to space ack requests */long Lrxpos; /* Receiver's last reported offset */int errors;#include "rbsb.c" /* most of the system dependent stuff here */int Filesleft;long Totalleft;/* * 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. */#ifdef READCHECKchar Myattn[] = { 0 };#else#ifdef USGchar Myattn[] = { 03, 0336, 0 };#elsechar Myattn[] = { 0 };#endif#endifFILE *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 RCDO (-3)#define RETRYMAX 10char Lastrx;char Crcflg;int Wcsmask=0377;int Verbose=0;int Modem2=0; /* XMODEM Protocol - 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=128; /* 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[1024];int Filcnt=0; /* count of number of files opened */int Lfseen=0;unsigned Rxbuflen = 16384; /* Receiver's max buffer length */int Tframlen = 0; /* Override for tx frame length */int blkopt=0; /* Override value for zmodem blklen */int Rxflags = 0;long bytcnt;int Wantfcs32 = TRUE; /* want to send 32 bit FCS */char Lzconv; /* Local ZMODEM file conversion request */char Lzmanag; /* Local ZMODEM file management request */int Lskipnocor;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 Test; /* 1= Force receiver to send Attn, etc with qbf. */ /* 2= Character transparency test */char *qbf="The quick brown fox jumped over the lazy dog's back 1234567890\r\n";long Lastread; /* Beginning offset of last buffer read */int Lastn; /* Count of last buffer read or -1 */int Dontread; /* Don't read the buffer, it's still there */long Lastsync; /* Last offset to which we got a ZRPOS */int Beenhereb4; /* How many times we've been ZRPOS'd same place */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(); if (n == 99) fprintf(stderr, "mode(2) in rbsb.c not implemented!!\n"); cucheck(); 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);}int Zctlesc; /* Encode control characters */int Nozmodem = 0; /* If invoked as "sb" */char *Progname = "sz";int Zrwindow = 1400; /* RX window size (controls garbage count) */#include "zm.c"main(argc, argv)char *argv[];{ register char *cp; register npats; int dm; char **patts; static char xXbuf[BUFSIZ]; if ((cp = getenv("ZNULLS")) && *cp) Znulls = atoi(cp); if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh"))) Restricted=TRUE; from_cu(); chkinvok(argv[0]); 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;#ifdef CSTOPB case '2': Twostop = TRUE; break;#endif 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 'e': Zctlesc = 1; break; case 'k': blklen=1024; break; case 'L': if (--argc < 1) { usage(); } blkopt = atoi(*++argv); if (blkopt<24 || blkopt>1024) usage(); break; case 'l': if (--argc < 1) { usage(); } Tframlen = atoi(*++argv); if (Tframlen<32 || Tframlen>1024) usage(); break; case 'N': Lzmanag = ZMNEWL; break; case 'n': Lzmanag = ZMNEW; break; case 'o': Wantfcs32 = FALSE; break; case 'p': Lzmanag = ZMPROT; break; case 'r': Lzconv = ZCRESUM; case 'q': Quiet=TRUE; Verbose=0; break; case 't': if (--argc < 1) { usage(); } Rxtimeout = atoi(*++argv); if (Rxtimeout<10 || Rxtimeout>1000) usage(); break; case 'T': if (++Test > 1) { chartest(1); chartest(2); mode(0); exit(0); } break; case 'u': ++Unlinkafter; break; case 'v': ++Verbose; break; case 'w': if (--argc < 1) { usage(); } Txwindow = atoi(*++argv); if (Txwindow < 256) Txwindow = 256; Txwindow = (Txwindow/64) * 64; Txwspac = Txwindow/4; if (blkopt > Txwspac || (!blkopt && Txwspac < 1024)) blkopt = Txwspac; break; case 'X': ++Modem2; break; case 'Y': Lskipnocor = TRUE; /* **** FALLL THROUGH TO **** */ 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 && !Test) 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); } if ( !Fromcu) signal(SIGQUIT, SIG_IGN); signal(SIGTERM, bibi); if ( !Modem2) { if (!Nozmodem) { printf("rz\r"); fflush(stdout); } countem(npats, patts); if (!Command && !Quiet && Verbose != 1) { dm = Filesleft + (Totalleft*11L) / (Baudrate * 6L); fprintf(stderr, "%s: %d file%s %ld bytes %u.%u minutes\r\n", Progname, Filesleft, Filesleft>1?"s":"", Totalleft, dm/10, dm%10); } if (!Nozmodem) { 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); dm = ((errcnt != 0) | Exitcode); if (dm) cucheck(); exit(dm); /*NOTREACHED*/}wcsend(argc, argp)char *argp[];{ register n; Crcflg=FALSE; firstsec=TRUE; bytcnt = -1; 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 */ if ( !Modem2) { Command = TRUE; Cmdstr = "echo \"sz: Can't open any requested files\""; if (getnak()) { Exitcode=0200; canit(); } if (!Zmodem) canit(); else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) { Exitcode=0200; canit(); } Exitcode = 1; return OK; } canit(); fprintf(stderr,"\r\nCan't open any requested files.\r\n"); return ERROR; } if (Zmodem) saybibi(); else if ( !Modem2) 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; Lastread = 0; Lastn = -1; Dontread = FALSE; /* 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(f.st_size)==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 (Modem2) { 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; } zperr("Awaiting pathname nak for %s", *name?name:"<END>"); if ( !Zmodem) if (getnak()) return ERROR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -