📄 lsz.c
字号:
/* lsz.c cosmetic modifications by Matt Porter * from the Public Domain version of sz.c by Chuck Forsberg, * Omen Technology INC * * A program for Linux to send files and commands to computers running * zmodem, ymodem, or xmodem protocols. * */#include "config.h"#if STDC_HEADERS# include <string.h>#else# ifdef HAVE_STRINGS_H# include <strings.h># endif# ifndef HAVE_STRCHR# define strchr index# define strrchr rindex# endifchar *strchr (), *strrchr ();# ifndef HAVE_MEMCPY# define memcpy(d, s, n) bcopy ((s), (d), (n))# define memmove(d, s, n) bcopy ((s), (d), (n))# endif#endif#define NEW_ERRORchar *getenv();#define SS_NORMAL 0#define LOGFILE "/var/log/szlog"#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <setjmp.h>#include <ctype.h>#include <errno.h>#ifdef HAVE_LIMITS_H# include <limits.h>#else # define PATH_MAX 1024#endif#if defined(ENABLE_TIMESYNC)# ifdef TM_IN_SYS_TIME# ifdef TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h># else# ifdef HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif# endif# else# include <time.h># endif#endif#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP)# include <sys/mman.h>size_t mm_size;void *mm_addr=NULL;#else# undef HAVE_MMAP#endif#include "timing.h"extern int errno;#define sendline(c) putchar(c & 0377)#define xsendline(c) putchar(c)#define PATHLEN 256#define OK 0#define FALSE 0#define TRUE 1#define ERROR (-1)/* 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 10#define HOWMANY 2int Zmodem=0; /* ZMODEM protocol requested by receiver */unsigned Baudrate=2400; /* Default, should be set by first mode() call */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;int Canseek=1; /* 1: can; 0: only rewind, -1: neither */#include "rbsb.c" /* most of the system dependent stuff here */#include "crctab.c"static int wctx(off_t flen);int Filesleft;long Totalleft,Filesize;/* * 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 };#elsechar Myattn[] = { 03, 0336, 0 };#endifFILE *in;#define MAX_BLOCK 8192char txbuf[MAX_BLOCK];long vpos = 0; /* Number of bytes read from file */char Lastrx;char Crcflg;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 Eofseen; /* EOF seen on input set by zfilbuf */int Totsecs; /* total number of sectors this file */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;int Rxflags2 = 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 enable_timesync=0;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 Lastsync; /* Last offset to which we got a ZRPOS */int Beenhereb4; /* How many times we've been ZRPOS'd same place */int no_timeout=FALSE;int max_blklen=1024;int start_blklen=1024;#ifdef NEW_ERRORint error_count;#define OVERHEAD 18#define OVER_ERR 20#endif#define MK_STRING(x) MK_STRING2(x)#define MK_STRING2(x) #xjmp_buf intrjmp; /* For the interrupt on RX CAN *//* called by signal interrupt or terminate to clean things up */RETSIGTYPEbibi(int 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) */RETSIGTYPEonintr(){ signal(SIGINT, SIG_IGN); longjmp(intrjmp, -1);}int Zctlesc; /* Encode control characters */int Nozmodem = 0; /* If invoked as "sb" */char *Progname = "sz";int Zrwindow = 1400; /* RX window size (controls garbage count) */#define READLINE_PF(x) readline(x)#include "zm.c"int main(int argc, char **argv){ register char *cp; register npats; int dm; int under_rsh=FALSE; char **patts; if ((cp = getenv("ZNULLS")) && *cp) Znulls = atoi(cp); if ((cp=getenv("SHELL")) && (strstr(cp, "rsh") || strstr(cp, "rksh") || strstr(cp, "rbash"))) { under_rsh=TRUE; Restricted=1; } if ((cp=getenv("ZMODEM_RESTRICTED"))!=NULL) Restricted=1; from_cu(); chkinvok(argv[0]); Rxtimeout = 600; npats=0; if (argc<2) usage(); while (--argc) { cp = *++argv; if (*cp++ == '-' && *cp) { while ( *cp) { switch(*cp++) { case '\\': *cp = toupper(*cp); continue; case '+': Lzmanag = ZMAPND; break;#ifdef CSTOPB case '2': Twostop = TRUE; break;#endif case '8': if (max_blklen==8192) start_blklen=8192; else max_blklen=8192; 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 'h': usage(); break; case 'k': start_blklen=1024; break; case 'L': if (--argc < 1) { usage(); } blkopt = atoi(*++argv); if (blkopt<24 || blkopt>MAX_BLOCK) usage(); break; case 'l': if (--argc < 1) { usage(); } Tframlen = atoi(*++argv); if (Tframlen<32 || Tframlen>MAX_BLOCK) usage(); break; case 'N': Lzmanag = ZMNEWL; break; case 'n': Lzmanag = ZMNEW; break; case 'o': Wantfcs32 = FALSE; break; case 'O': no_timeout = TRUE; break; case 'p': Lzmanag = ZMPROT; break; case 'r': Lzconv = ZCRESUM; break; case 'R': Restricted = TRUE; break; case 'q': Quiet=TRUE; Verbose=0; break; case 'S': enable_timesync=1; 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 'U': if (!under_rsh) Restricted=0; else {fprintf(stderr,"security violation: running under restricted shell\n",stderr); exit(1); } 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 < MAX_BLOCK)) 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 (Command && Restricted) { printf("Can't send command in restricted mode\n"); exit(1); } if (Verbose) {#if 0 if (freopen(LOGFILE, "a", stderr)==NULL) { printf("Can't open log file %s\n",LOGFILE); exit(0200); }#endif setbuf(stderr, NULL); } if (Fromcu && !Quiet) { if (Verbose == 0) Verbose = 2; } vfile("%s %s for %s\n", Progname, VERSION, OS); { /* we write max_blocklen (data) + 18 (ZModem protocol overhead) * + escape overhead (about 4 %), so buffer has to be * somewhat larger than max_blklen */ char *s=malloc(max_blklen+1024); if (!s) { fprintf(stderr,"lsz: out of memory\n"); exit(1); }#ifdef SETVBUF_REVERSED setvbuf(stdout,_IOFBF,s,max_blklen+1024);#else setvbuf(stdout,s,_IOFBF,max_blklen+1024);#endif } blklen=start_blklen; mode(1);#ifndef linux 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);#endif if ( !Modem2) { if (!Nozmodem) { printf("rz\r"); fflush(stdout); } countem(npats, patts); if (!Nozmodem) { stohdr(0L); if (Command) Txhdr[ZF0] = ZCOMMAND; zshhdr(ZRQINIT, Txhdr);#if defined(ENABLE_TIMESYNC) if (Rxflags2 != ZF1_TIMESYNC) /* disable timesync if there are any flags we don't know. * dsz/gsz seems to use some other flags! */ enable_timesync=FALSE; if (Rxflags2 & ZF1_TIMESYNC && enable_timesync) { Totalleft+=6; /* TIMESYNC never needs more */ Filesleft++; }#endif } } 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); } exit(SS_NORMAL); /*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; }#if defined(ENABLE_TIMESYNC) if (Rxflags2 & ZF1_TIMESYNC && enable_timesync) { /* implement Peter Mandrellas extension */ /* yes, this *has* a minor race condition */ char tmp[PATH_MAX]; const char *p; FILE *f; if (Verbose) fprintf(stderr, "\r\nAnswering TIMESYNC"); p=getenv("TMPDIR"); if (!p) p=getenv("TMP"); if (!p) p="/tmp"; strcpy(tmp,p); strcat(tmp,"/$time$.t"); f=fopen(tmp,"w"); if (f) { char buf[30]; time_t t=time(NULL); struct tm *tm=localtime(&t); /* sets timezone */#ifdef HAVE_STRFTIME strftime(buf,sizeof(buf)-1,"%H:%M:%S",tm); if (Verbose) fprintf(stderr, " at %s",buf);#endif#if defined(HAVE_TIMEZONE_VAR) fprintf(f,"%ld\r\n",timezone / 60); if (Verbose) fprintf(stderr, " (tz %ld)\r\n",timezone/60);#else if (Verbose) fprintf(stderr, " (tz unknown)\r\n");#endif fclose(f); if (wcs(tmp)==ERROR) if (Verbose) fprintf(stderr, "\r\nTIMESYNC: failed\n"); else { if (Verbose) fprintf(stderr, "\r\nTIMESYNC: ok\n"); Filcnt--; } unlink(tmp); } else { if (!Verbose) fprintf(stderr, "\r\nAnswering TIMESYNC\n"); else fprintf(stderr, "\r\n"); fprintf(stderr, " cannot open tmpfile %s: %s\r\n",tmp, strerror(errno)); } }#endif Totsecs = 0; if (Filcnt==0) { /* bitch if we couldn't open ANY files */ if ( !Modem2) { Command = TRUE; Cmdstr = "echo \"lsz: 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 ( strstr(name, "../")#ifdef PUBDIR || (name[0]== '/' && strncmp(name, MK_STRING(PUBDIR), strlen(MK_STRING(PUBDIR))))#endif ) { canit(); fprintf(stderr,"\r\nlsz:\tSecurity Violation\r\n"); return ERROR; } } if ( !strcmp(oname, "-")) { if ((p = getenv("ONAME")) && *p) strcpy(name, p); else sprintf(name, "s%d.lsz", getpid()); in = stdin; } else if ((in=fopen(oname, "r"))==NULL) { ++errcnt; return OK; /* pass over it, there may be others */ } { static char *s=NULL; if (!s) { s=malloc(16384); if (!s) { fprintf(stderr,"lsz: out of memory\n"); exit(1); } }#ifdef SETVBUF_REVERSED setvbuf(in,_IOFBF,s,16384);#else setvbuf(in,s,_IOFBF,16384);#endif } timing(1); Eofseen = 0; vpos = 0; /* Check for directory or block special files */ fstat(fileno(in), &f); c = f.st_mode & S_IFMT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -