📄 lsz.c
字号:
/* lsz - send files with x/y/zmodem Copyright (C) until 1988 Chuck Forsberg (Omen Technology INC) Copyright (C) 1994 Matt Porter, Michael D. Black Copyright (C) 1996, 1997 Uwe Ohse This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. originally written by Chuck Forsberg*/#include "zglobal.h"/* char *getenv(); */#define SS_NORMAL 0#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <setjmp.h>#include <ctype.h>#include <errno.h>#include <getopt.h>#ifndef R_OK# define R_OK 4#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"#include "long-options.h"#include "xstrtoul.h"#include "error.h"#ifndef STRICT_PROTOTYPESextern time_t time();extern char *strerror();extern char *strstr();#endif#ifndef HAVE_ERRNO_DECLARATIONextern int errno;#endifunsigned 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 */size_t Lrxpos; /* Receiver's last reported offset */int errors;enum zm_type_enum protocol;int under_rsh=FALSE;extern int turbo_escape;static int no_unixmode;int Canseek=1; /* 1: can; 0: only rewind, -1: neither */static int zsendfile __P ((struct zm_fileinfo *zi, const char *buf, size_t blen));static int getnak __P ((void));static int wctxpn __P ((struct zm_fileinfo *));static int wcs __P ((const char *oname, const char *remotename));static size_t zfilbuf __P ((struct zm_fileinfo *zi));static size_t filbuf __P ((char *buf, size_t count));static int getzrxinit __P ((void));static int calc_blklen __P ((long total_sent));static int sendzsinit __P ((void));static int wctx __P ((struct zm_fileinfo *));static int zsendfdata __P ((struct zm_fileinfo *));static int getinsync __P ((struct zm_fileinfo *, int flag));static void countem __P ((int argc, char **argv));static void chkinvok __P ((const char *s));static void usage __P ((int exitcode, const char *what));static int zsendcmd __P ((const char *buf, size_t blen));static void saybibi __P ((void));static int wcsend __P ((int argc, char *argp[]));static int wcputsec __P ((char *buf, int sectnum, size_t cseclen));static void usage1 __P ((int exitcode));#ifdef ENABLE_SYSLOG#define DO_SYSLOG(message) do { \ if (enable_syslog) { \ const char *shortname; \ if (!zi->fname) \ shortname="no.name"; \ else { \ shortname=strrchr(zi->fname,'/'); \ if (!shortname) \ shortname=zi->fname; \ else \ shortname++; \ } \ lsyslog message ; \ } \ } while(0)#else#define DO_SYSLOG(message) do { } while(0)#endif#define ZSDATA(x,y,z) \ do { if (Crc32t) {zsda32(x,y,z); } else {zsdata(x,y,z);}} while(0)#ifdef HAVE_MMAP#define DATAADR (mm_addr ? ((char *)mm_addr)+zi->bytes_sent : txbuf)#else#define DATAADR (txbuf)#endifint Filesleft;long Totalleft;size_t buffersize=16384;#ifdef HAVE_MMAPint use_mmap=1;#endif/* * 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 *input_f;#define MAX_BLOCK 8192char txbuf[MAX_BLOCK];long vpos = 0; /* Number of bytes read from file */char Lastrx;char Crcflg;int Verbose=0;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 */size_t blklen=128; /* length of transmitted records */int Optiong; /* Let it rip no wait for sector ACK's */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 */unsigned Tframlen = 0; /* Override for tx frame length */unsigned blkopt=0; /* Override value for zmodem blklen */int Rxflags = 0;int Rxflags2 = 0;size_t 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_mode; /* Send a command, then exit. */int Cmdtries = 11;int Cmdack1; /* Rx ACKs command, then do it */int Exitcode;int enable_timesync=0;size_t 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;size_t max_blklen=1024;size_t start_blklen=0;int zmodem_requested;time_t stop_time=0;int tcp_flag=0;char *tcp_server_address=0;int tcp_socket=-1;int error_count;#define OVERHEAD 18#define OVER_ERR 20#define MK_STRING(x) #x#ifdef ENABLE_SYSLOG# if defined(ENABLE_SYSLOG_FORCE) || defined(ENABLE_SYSLOG_DEFAULT)int enable_syslog=TRUE;# elseint enable_syslog=FALSE;# endif#endifjmp_buf intrjmp; /* For the interrupt on RX CAN */static long min_bps;static long min_bps_time;static int io_mode_fd=0;static int zrqinits_sent=0;static int play_with_sigint=0;/* called by signal interrupt or terminate to clean things up */RETSIGTYPEbibi (int n){ canit(STDOUT_FILENO); fflush (stdout); io_mode (io_mode_fd,0); if (n == 99) error (0, 0, _ ("io_mode(,2) in rbsb.c not implemented\n")); else error (0, 0, _ ("caught signal %d; exiting"), n); if (n == SIGQUIT) abort (); exit (128 + n);}/* Called when ZMODEM gets an interrupt (^C) */static RETSIGTYPEonintr(int n LRZSZ_ATTRIB_UNUSED){ signal(SIGINT, SIG_IGN); longjmp(intrjmp, -1);}int Zctlesc; /* Encode control characters */const char *program_name = "sz";int Zrwindow = 1400; /* RX window size (controls garbage count) */static struct option const long_options[] ={ {"append", no_argument, NULL, '+'}, {"twostop", no_argument, NULL, '2'}, {"try-8k", no_argument, NULL, '8'}, {"start-8k", no_argument, NULL, '9'}, {"try-4k", no_argument, NULL, '4'}, {"start-4k", no_argument, NULL, '5'}, {"ascii", no_argument, NULL, 'a'}, {"binary", no_argument, NULL, 'b'}, {"bufsize", required_argument, NULL, 'B'}, {"cmdtries", required_argument, NULL, 'C'}, {"command", required_argument, NULL, 'c'}, {"immediate-command", required_argument, NULL, 'i'}, {"dot-to-slash", no_argument, NULL, 'd'}, {"full-path", no_argument, NULL, 'f'}, {"escape", no_argument, NULL, 'e'}, {"rename", no_argument, NULL, 'E'}, {"help", no_argument, NULL, 'h'}, {"crc-check", no_argument, NULL, 'H'}, {"1024", no_argument, NULL, 'k'}, {"1k", no_argument, NULL, 'k'}, {"packetlen", required_argument, NULL, 'L'}, {"framelen", required_argument, NULL, 'l'}, {"min-bps", required_argument, NULL, 'm'}, {"min-bps-time", required_argument, NULL, 'M'}, {"newer", no_argument, NULL, 'n'}, {"newer-or-longer", no_argument, NULL, 'N'}, {"16-bit-crc", no_argument, NULL, 'o'}, {"disable-timeouts", no_argument, NULL, 'O'}, {"disable-timeout", no_argument, NULL, 'O'}, /* i can't get it right */ {"protect", no_argument, NULL, 'p'}, {"resume", no_argument, NULL, 'r'}, {"restricted", no_argument, NULL, 'R'}, {"quiet", no_argument, NULL, 'q'}, {"stop-at", required_argument, NULL, 's'}, {"syslog", optional_argument, NULL , 2}, {"timesync", no_argument, NULL, 'S'}, {"timeout", required_argument, NULL, 't'}, {"turbo", no_argument, NULL, 'T'}, {"unlink", no_argument, NULL, 'u'}, {"unrestrict", no_argument, NULL, 'U'}, {"verbose", no_argument, NULL, 'v'}, {"windowsize", required_argument, NULL, 'w'}, {"xmodem", no_argument, NULL, 'X'}, {"ymodem", no_argument, NULL, 1}, {"zmodem", no_argument, NULL, 'Z'}, {"overwrite", no_argument, NULL, 'y'}, {"overwrite-or-skip", no_argument, NULL, 'Y'}, {"delay-startup", required_argument, NULL, 4}, {"tcp", no_argument, NULL, 5}, {"tcp-server", no_argument, NULL, 6}, {"tcp-client", required_argument, NULL, 7}, {"no-unixmode", no_argument, NULL, 8}, {NULL, 0, NULL, 0}};static voidshow_version(void){ printf ("%s (%s) %s\n", program_name, PACKAGE, VERSION);}int main(int argc, char **argv){ char *cp; int npats; int dm; int i; int stdin_files; char **patts; int c; const char *Cmdstr=NULL; /* Pointer to the command string */ unsigned int startup_delay=0; if (((cp = getenv("ZNULLS")) != NULL) && *cp) Znulls = atoi(cp); if (((cp=getenv("SHELL"))!=NULL) && (strstr(cp, "rsh") || strstr(cp, "rksh") || strstr(cp, "rbash") || strstr(cp,"rshell"))) { under_rsh=TRUE; Restricted=1; } if ((cp=getenv("ZMODEM_RESTRICTED"))!=NULL) Restricted=1; from_cu(); chkinvok(argv[0]);#ifdef ENABLE_SYSLOG openlog(program_name,LOG_PID,ENABLE_SYSLOG);#endif setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); parse_long_options (argc, argv, show_version, usage1); Rxtimeout = 600; while ((c = getopt_long (argc, argv, "2+48abB:C:c:dfeEghHi:kL:l:m:M:NnOopRrqsSt:TUuvw:XYy", long_options, (int *) 0))!=EOF) { unsigned long int tmp; char *tmpptr; enum strtol_error s_err; switch (c) { case 0: break; case '+': Lzmanag = ZF1_ZMAPND; break; case '2': Twostop = TRUE; break; case '8': if (max_blklen==8192) start_blklen=8192; else max_blklen=8192; break; case '9': /* this is a longopt .. */ start_blklen=8192; max_blklen=8192; break; case '4': if (max_blklen==4096) start_blklen=4096; else max_blklen=4096; break; case '5': /* this is a longopt .. */ start_blklen=4096; max_blklen=4096; break; case 'a': Lzconv = ZCNL; Ascii = TRUE; break; case 'b': Lzconv = ZCBIN; break; case 'B': if (0==strcmp(optarg,"auto")) buffersize= (size_t) -1; else buffersize=strtol(optarg,NULL,10);#ifdef HAVE_MMAP use_mmap=0;#endif break; case 'C': s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL); Cmdtries = tmp; if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("command tries"), s_err); break; case 'i': Cmdack1 = ZCACK1; /* **** FALL THROUGH TO **** */ case 'c': command_mode = TRUE; Cmdstr = optarg; break; case 'd': ++Dottoslash; /* **** FALL THROUGH TO **** */ case 'f': Fullname=TRUE; break; case 'e': Zctlesc = 1; break; case 'E': Lzmanag = ZF1_ZMCHNG; break; case 'h': usage(0,NULL); break; case 'H': Lzmanag = ZF1_ZMCRC; break; case 'k': start_blklen=1024; break; case 'L': s_err = xstrtoul (optarg, NULL, 0, &tmp, "ck"); blkopt = tmp; if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("packetlength"), s_err); if (blkopt<24 || blkopt>MAX_BLOCK) { char meld[256]; sprintf(meld, _("packetlength out of range 24..%ld"), (long) MAX_BLOCK); usage(2,meld); } break; case 'l': s_err = xstrtoul (optarg, NULL, 0, &tmp, "ck"); Tframlen = tmp; if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("framelength"), s_err); if (Tframlen<32 || Tframlen>MAX_BLOCK) { char meld[256]; sprintf(meld, _("framelength out of range 32..%ld"), (long) MAX_BLOCK); usage(2,meld); } break; case 'm': s_err = xstrtoul (optarg, &tmpptr, 0, &tmp, "km"); min_bps = tmp; if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("min_bps"), s_err); if (min_bps<0) usage(2,_("min_bps must be >= 0")); break; case 'M': s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL); min_bps_time = tmp; if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("min_bps_time"), s_err); if (min_bps_time<=1) usage(2,_("min_bps_time must be > 1")); break; case 'N': Lzmanag = ZF1_ZMNEWL; break; case 'n': Lzmanag = ZF1_ZMNEW; break; case 'o': Wantfcs32 = FALSE; break; case 'O': no_timeout = TRUE; break; case 'p': Lzmanag = ZF1_ZMPROT; break; case 'r': if (Lzconv == ZCRESUM) Lzmanag = ZF1_ZMCRC; else Lzconv = ZCRESUM; break; case 'R': Restricted = TRUE; break; case 'q': Quiet=TRUE; Verbose=0; break; case 's': if (isdigit((unsigned char) (*optarg))) { struct tm *tm; time_t t; int hh,mm; char *nex; hh = strtoul (optarg, &nex, 10); if (hh>23) usage(2,_("hour to large (0..23)")); if (*nex!=':') usage(2, _("unparsable stop time\n")); nex++; mm = strtoul (optarg, &nex, 10); if (mm>59) usage(2,_("minute to large (0..59)")); t=time(NULL); tm=localtime(&t); tm->tm_hour=hh; tm->tm_min=hh; stop_time=mktime(tm); if (stop_time<t) stop_time+=86400L; /* one day more */ if (stop_time - t <10) usage(2,_("stop time to small")); } else { s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL); stop_time = tmp + time(0); if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("stop-at"), s_err); if (tmp<10) usage(2,_("stop time to small")); } break; case 'S': enable_timesync=1; break; case 'T': turbo_escape=1; break; case 't': s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL); Rxtimeout = tmp; if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("timeout"), s_err); if (Rxtimeout<10 || Rxtimeout>1000) usage(2,_("timeout out of range 10..1000")); break; case 'u': ++Unlinkafter; break; case 'U': if (!under_rsh) Restricted=0; else error(1,0, _("security violation: can't do that under restricted shell\n")); break; case 'v': ++Verbose; break; case 'w': s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL); Txwindow = tmp; if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("window size"), s_err); if (Txwindow < 256) Txwindow = 256; Txwindow = (Txwindow/64) * 64; Txwspac = Txwindow/4; if (blkopt > Txwspac || (!blkopt && Txwspac < MAX_BLOCK)) blkopt = Txwspac; break; case 'X': protocol=ZM_XMODEM; break; case 1: protocol=ZM_YMODEM; break; case 'Z': protocol=ZM_ZMODEM; break; case 'Y': Lskipnocor = TRUE; /* **** FALLL THROUGH TO **** */ case 'y': Lzmanag = ZF1_ZMCLOB; break; case 2:#ifdef ENABLE_SYSLOG# ifndef ENABLE_SYSLOG_FORCE if (optarg && (!strcmp(optarg,"off") || !strcmp(optarg,"no"))) { if (under_rsh) error(0,0, _("cannot turnoff syslog")); else enable_syslog=FALSE; } else enable_syslog=TRUE;# else error(0,0, _("cannot turnoff syslog"));# endif#endif break; case 4: s_err = xstrtoul (optarg, NULL, 0, &tmp, NULL); startup_delay = tmp; if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("startup delay"), s_err); break; case 5: tcp_flag=1; break; case 6: tcp_flag=2; break; case 7: tcp_flag=3; tcp_server_address=(char *)strdup(optarg); if (!tcp_server_address) { error(1,0,_("out of memory")); } break; case 8: no_unixmode=1; break; default: usage (2,NULL); break; } } if (getuid()!=geteuid()) { error(1,0, _("this program was never intended to be used setuid\n")); } zsendline_init(); if (start_blklen==0) { if (protocol == ZM_ZMODEM) { start_blklen=1024; if (Tframlen) { start_blklen=max_blklen=Tframlen; } } else start_blklen=128; } if (argc<2) usage(2,_("need at least one file to send")); if (startup_delay) sleep(startup_delay);#ifdef HAVE_SIGINTERRUPT /* we want interrupted system calls to fail and not to be restarted. */ siginterrupt(SIGALRM,1);#endif npats = argc - optind; patts=&argv[optind]; if (npats < 1 && !command_mode)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -