📄 lsz.c
字号:
usage(2,_("need at least one file to send")); if (command_mode && Restricted) { printf(_("Can't send command in restricted mode\n")); exit(1); } if (Fromcu && !Quiet) { if (Verbose == 0) Verbose = 2; } vfile("%s %s\n", program_name, VERSION); if (tcp_flag==2) { char buf[256];#ifdef MAXHOSTNAMELEN char hn[MAXHOSTNAMELEN];#else char hn[256];#endif char *p,*q; int d; /* tell receiver to receive via tcp */ d=tcp_server(buf); p=strchr(buf+1,'<'); p++; q=strchr(p,'>'); *q=0; if (gethostname(hn,sizeof(hn))==-1) { error(1,0, _("hostname too long\n")); } fprintf(stdout,"connect with lrz --tcp-client \"%s:%s\"\n",hn,p); fflush(stdout); /* ok, now that this file is sent we can switch to tcp */ tcp_socket=tcp_accept(d); dup2(tcp_socket,0); dup2(tcp_socket,1); } if (tcp_flag==3) { char buf[256]; char *p; p=strchr(tcp_server_address,':'); if (!p) error(1,0, _("illegal server address\n")); *p++=0; sprintf(buf,"[%s] <%s>\n",tcp_server_address,p); fprintf(stdout,"connecting to %s\n",buf); fflush(stdout); /* we need to switch to tcp mode */ tcp_socket=tcp_connect(buf); dup2(tcp_socket,0); dup2(tcp_socket,1); } { /* 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) { zperr(_("out of memory")); exit(1); }#ifdef SETVBUF_REVERSED setvbuf(stdout,_IOFBF,s,max_blklen+1024);#else setvbuf(stdout,s,_IOFBF,max_blklen+1024);#endif } blklen=start_blklen; for (i=optind,stdin_files=0;i<argc;i++) { if (0==strcmp(argv[i],"-")) stdin_files++; } if (stdin_files>1) { usage(1,_("can read only one file from stdin")); } else if (stdin_files==1) { io_mode_fd=1; } io_mode(io_mode_fd,1); readline_setup(io_mode_fd, 128, 256); if (signal(SIGINT, bibi) == SIG_IGN) signal(SIGINT, SIG_IGN); else { signal(SIGINT, bibi); play_with_sigint=1; } signal(SIGTERM, bibi); signal(SIGPIPE, bibi); signal(SIGHUP, bibi); if ( protocol!=ZM_XMODEM) { if (protocol==ZM_ZMODEM) { printf("rz\r"); fflush(stdout); } countem(npats, patts); if (protocol == ZM_ZMODEM) { /* throw away any input already received. This doesn't harm * as we invite the receiver to send it's data again, and * might be useful if the receiver has already died or * if there is dirt left if the line */#ifdef HAVE_SELECT struct timeval t; unsigned char throwaway; fd_set f;#endif purgeline(io_mode_fd); #ifdef HAVE_SELECT t.tv_sec = 0; t.tv_usec = 0; FD_ZERO(&f); FD_SET(io_mode_fd,&f); while (select(1,&f,NULL,NULL,&t)) { if (0==read(io_mode_fd,&throwaway,1)) /* EOF ... */ break; }#endif purgeline(io_mode_fd); stohdr(0L); if (command_mode) Txhdr[ZF0] = ZCOMMAND; zshhdr(ZRQINIT, Txhdr); zrqinits_sent++;#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 if (tcp_flag==1) { Totalleft+=256; /* tcp never needs more */ Filesleft++; } } } fflush(stdout); if (Cmdstr) { if (getzrxinit()) { Exitcode=0200; canit(STDOUT_FILENO); } else if (zsendcmd(Cmdstr, strlen(Cmdstr)+1)) { Exitcode=0200; canit(STDOUT_FILENO); } } else if (wcsend(npats, patts)==ERROR) { Exitcode=0200; canit(STDOUT_FILENO); } fflush(stdout); io_mode(io_mode_fd,0); if (Exitcode) dm=Exitcode; else if (errcnt) dm=1; else dm=0; if (Verbose) { fputs("\r\n",stderr); if (dm) fputs(_("Transfer incomplete\n"),stderr); else fputs(_("Transfer complete\n"),stderr); } exit(dm); /*NOTREACHED*/}static int send_pseudo(const char *name, const char *data){ char *tmp; const char *p; int ret=0; /* ok */ size_t plen; int fd; int lfd; p = getenv ("TMPDIR"); if (!p) p = getenv ("TMP"); if (!p) p = "/tmp"; tmp=malloc(PATH_MAX+1); if (!tmp) error(1,0,_("out of memory")); plen=strlen(p); memcpy(tmp,p,plen); tmp[plen++]='/'; lfd=0; do { if (lfd++==10) { free(tmp); vstringf (_ ("send_pseudo %s: cannot open tmpfile %s: %s"), name, tmp, strerror (errno)); vstring ("\r\n"); return 1; } sprintf(tmp+plen,"%s.%lu.%d",name,(unsigned long) getpid(),lfd); fd=open(tmp,O_WRONLY|O_CREAT|O_EXCL,0700); /* is O_EXCL guaranted to not follow symlinks? * I don`t know ... so be careful */ if (fd!=-1) { struct stat st; if (0!=lstat(tmp,&st)) { vstringf (_ ("send_pseudo %s: cannot lstat tmpfile %s: %s"), name, tmp, strerror (errno)); vstring ("\r\n"); unlink(tmp); close(fd); fd=-1; } else { if (S_ISLNK(st.st_mode)) { vstringf (_ ("send_pseudo %s: avoiding symlink trap"),name); vstring ("\r\n"); unlink(tmp); close(fd); fd=-1; } } } } while (fd==-1); if (write(fd,data,strlen(data))!=(signed long) strlen(data) || close(fd)!=0) { vstringf (_ ("send_pseudo %s: cannot write to tmpfile %s: %s"), name, tmp, strerror (errno)); vstring ("\r\n"); free(tmp); return 1; } if (wcs (tmp,name) == ERROR) { if (Verbose) vstringf (_ ("send_pseudo %s: failed"),name); else { if (Verbose) vstringf (_ ("send_pseudo %s: ok"),name); Filcnt--; } vstring ("\r\n"); ret=1; } unlink (tmp); free(tmp); return ret;}static intwcsend (int argc, char *argp[]){ int n; Crcflg = FALSE; firstsec = TRUE; bytcnt = (size_t) -1; if (tcp_flag==1) { char buf[256]; int d; /* tell receiver to receive via tcp */ d=tcp_server(buf); if (send_pseudo("/$tcp$.t",buf)) { error(1,0,_("tcp protocol init failed\n")); } /* ok, now that this file is sent we can switch to tcp */ tcp_socket=tcp_accept(d); dup2(tcp_socket,0); dup2(tcp_socket,1); } for (n = 0; n < argc; ++n) { Totsecs = 0; if (wcs (argp[n],NULL) == ERROR) return ERROR; }#if defined(ENABLE_TIMESYNC) if (Rxflags2 & ZF1_TIMESYNC && enable_timesync) { /* implement Peter Mandrellas extension */ char buf[60]; time_t t = time (NULL); struct tm *tm = localtime (&t); /* sets timezone */ strftime (buf, sizeof (buf) - 1, "%H:%M:%S", tm); if (Verbose) { vstring ("\r\n"); vstringf (_("Answering TIMESYNC at %s"),buf); }#if defined(HAVE_TIMEZONE_VAR) sprintf(buf+strlen(buf),"%ld\r\n", timezone / 60); if (Verbose) vstringf (" (%s %ld)\r\n", _ ("timezone"), timezone / 60);#else if (Verbose) vstringf (" (%s)\r\n", _ ("timezone unknown"));#endif send_pseudo("/$time$.t",buf); }#endif Totsecs = 0; if (Filcnt == 0) { /* bitch if we couldn't open ANY files */#if 0 /* i *really* do not like this */ if (protocol != ZM_XMODEM) { const char *Cmdstr; /* Pointer to the command string */ command_mode = TRUE; Cmdstr = "echo \"lsz: Can't open any requested files\""; if (getnak ()) { Exitcode = 0200; canit(STDOUT_FILENO); } if (!zmodem_requested) canit(STDOUT_FILENO); else if (zsendcmd (Cmdstr, 1 + strlen (Cmdstr))) { Exitcode = 0200; canit(STDOUT_FILENO); } Exitcode = 1; return OK; }#endif canit(STDOUT_FILENO); vstring ("\r\n"); vstringf (_ ("Can't open any requested files.")); vstring ("\r\n"); return ERROR; } if (zmodem_requested) saybibi (); else if (protocol != ZM_XMODEM) { struct zm_fileinfo zi; char *pa; pa=alloca(PATH_MAX+1); *pa='\0'; zi.fname = pa; zi.modtime = 0; zi.mode = 0; zi.bytes_total = 0; zi.bytes_sent = 0; zi.bytes_received = 0; zi.bytes_skipped = 0; wctxpn (&zi); } return OK;}static intwcs(const char *oname, const char *remotename){#if !defined(S_ISDIR) int c;#endif struct stat f; char *name; struct zm_fileinfo zi;#ifdef HAVE_MMAP int dont_mmap_this=0;#endif#ifdef ENABLE_SYSLOG const char *shortname; shortname=strrchr(oname,'/'); if (shortname) shortname++; else shortname=oname;#endif if (Restricted) { /* restrict pathnames to current tree or uucppublic */ if ( strstr(oname, "../")#ifdef PUBDIR || (oname[0]== '/' && strncmp(oname, MK_STRING(PUBDIR), strlen(MK_STRING(PUBDIR))))#endif ) { canit(STDOUT_FILENO); vchar('\r'); error(1,0, _("security violation: not allowed to upload from %s"),oname); } } if (0==strcmp(oname,"-")) { char *p=getenv("ONAME"); name=alloca(PATH_MAX+1); if (p) { strcpy(name, p); } else { sprintf(name, "s%lu.lsz", (unsigned long) getpid()); } input_f=stdin;#ifdef HAVE_MMAP dont_mmap_this=1;#endif } else if ((input_f=fopen(oname, "r"))==NULL) { int e=errno; error(0,e, _("cannot open %s"),oname); ++errcnt; return OK; /* pass over it, there may be others */ } else { name=alloca(PATH_MAX+1); strcpy(name, oname); }#ifdef HAVE_MMAP if (!use_mmap || dont_mmap_this)#endif { static char *s=NULL; static size_t last_length=0; struct stat st; if (fstat(fileno(input_f),&st)==-1) st.st_size=1024*1024; if (buffersize==(size_t) -1 && s) { if ((size_t) st.st_size > last_length) { free(s); s=NULL; last_length=0; } } if (!s && buffersize) { last_length=16384; if (buffersize==(size_t) -1) { if (st.st_size>0) last_length=st.st_size; } else last_length=buffersize; /* buffer whole pages */ last_length=(last_length+4095)&0xfffff000; s=malloc(last_length); if (!s) { zpfatal(_("out of memory")); exit(1); } } if (s) {#ifdef SETVBUF_REVERSED setvbuf(input_f,_IOFBF,s,last_length);#else setvbuf(input_f,s,_IOFBF,last_length);#endif } } vpos = 0; /* Check for directory or block special files */ fstat(fileno(input_f), &f);#if defined(S_ISDIR) if (S_ISDIR(f.st_mode) || S_ISBLK(f.st_mode)) {#else c = f.st_mode & S_IFMT; if (c == S_IFDIR || c == S_IFBLK) {#endif error(0,0, _("is not a file: %s"),name); fclose(input_f); return OK; } if (remotename) { /* disqualify const */ union { const char *c; char *s; } cheat; cheat.c=remotename; zi.fname=cheat.s; } else zi.fname=name; zi.modtime=f.st_mtime; zi.mode=f.st_mode;#if defined(S_ISFIFO) zi.bytes_total= (S_ISFIFO(f.st_mode)) ? DEFBYTL : f.st_size;#else zi.bytes_total= c == S_IFIFO ? DEFBYTL : f.st_size;#endif zi.bytes_sent=0; zi.bytes_received=0; zi.bytes_skipped=0; zi.eof_seen=0; timing(1,NULL); ++Filcnt; switch (wctxpn(&zi)) { case ERROR:#ifdef ENABLE_SYSLOG if (enable_syslog) lsyslog(LOG_INFO, _("%s/%s: error occured"),protname(),shortname);#endif return ERROR; case ZSKIP: error(0,0, _("skipped: %s"),name);#ifdef ENABLE_SYSLOG if (enable_syslog) lsyslog(LOG_INFO, _("%s/%s: skipped"),protname(),shortname);#endif return OK; } if (!zmodem_requested && wctx(&zi)==ERROR) {#ifdef ENABLE_SYSLOG if (enable_syslog) lsyslog(LOG_INFO, _("%s/%s: error occured"),protname(),shortname);#endif return ERROR; } if (Unlinkafter) unlink(oname); if (Verbose > 1#ifdef ENABLE_SYSLOG || enable_syslog#endif ) { long bps; double d=timing(0,NULL); if (d==0) /* can happen if timing() uses time() */ d=0.5; bps=zi.bytes_sent/d; vchar('\r'); if (Verbose > 1) vstringf(_("Bytes Sent:%7ld BPS:%-8ld \n"), (long) zi.bytes_sent,bps);#ifdef ENABLE_SYSLOG if (enable_syslog) lsyslog(LOG_INFO, "%s/%s: %ld Bytes, %ld BPS",shortname, protname(), (long) zi.bytes_sent,bps);#endif } 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! */static intwctxpn(struct zm_fileinfo *zi){ register char *p, *q; char *name2; struct stat f; name2=alloca(PATH_MAX+1); if (protocol==ZM_XMODEM) { if (Verbose && *zi->fname && fstat(fileno(input_f), &f)!= -1) { vstringf(_("Sending %s, %ld blocks: "), zi->fname, (long) (f.st_size>>7)); } vstringf(_("Give your local XMODEM receive command now.")); vstring("\r\n"); return OK; } if (!zmodem_requested) if (getnak()) { vfile("getnak failed"); DO_SYSLOG((LOG_INFO, "%s/%s: getnak failed", shortname,protname())); return ERROR; } q = (char *) 0; if (Dottoslash) { /* change . to . */ for (p=zi->fname; *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=zi->fname, q=txbuf ; *p; ) if ((*q++ = *p++) == '/' && !Fullname) q = txbuf; *q++ = 0; p=q; while (q < (txbuf + MAX_BLOCK)) *q++ = 0; /* note that we may lose some information here in case mode_t is wider than an * int. But i believe sending %lo instead of %o _could_ break compatability */ if (!Ascii && (input_f!=stdin) && *zi->fname && fstat(fileno(input_f), &f)!= -1) sprintf(p, "%lu %lo %o 0 %d %ld", (long) f.st_size, f.st_mtime, (unsigned int)((no_unixmode) ? 0 : f.st_mode), Filesleft, Totalleft); if (Verbose) vstringf(_("Sending: %s\n"),txbuf); Totalleft -= f.st_size; if (--Filesleft <= 0) Totalleft = 0; if (Totalleft < 0) Totalleft = 0; /* force 1k blocks if name won't fit in 128 byte block */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -