📄 lrz.c
字号:
} /* Check for existing file */ if (zconv != ZCRESUM && !Rxclob && (zmanag&ZF1_ZMMASK) != ZF1_ZMCLOB && (zmanag&ZF1_ZMMASK) != ZF1_ZMAPND#ifdef ENABLE_TIMESYNC && !in_timesync && !in_tcpsync#endif && (fout=fopen(name, "r"))) { struct stat sta; char *tmpname; char *ptr; int i; if (zmanag == ZF1_ZMNEW || zmanag==ZF1_ZMNEWL) { if (-1==fstat(fileno(fout),&sta)) {#ifdef ENABLE_SYSLOG int e=errno;#endif if (Verbose) vstringf(_("file exists, skipped: %s\n"),name); DO_SYSLOG((LOG_ERR,"cannot fstat open file %s: %s", name,strerror(e))); return ERROR; } if (zmanag == ZF1_ZMNEW) { if (sta.st_mtime > zi->modtime) { DO_SYSLOG((LOG_INFO,"skipping %s: newer file exists", name)); return ERROR; /* skips file */ } } else { /* newer-or-longer */ if (((size_t) sta.st_size) >= zi->bytes_total && sta.st_mtime > zi->modtime) { DO_SYSLOG((LOG_INFO,"skipping %s: longer+newer file exists", name)); return ERROR; /* skips file */ } } fclose(fout); } else if (zmanag==ZF1_ZMCRC) { int r=do_crc_check(fout,zi->bytes_total,0); if (r==ERROR) { fclose(fout); return ERROR; } if (r!=ZCRC_DIFFERS) { return ERROR; /* skips */ } fclose(fout); } else { size_t namelen; fclose(fout); if ((zmanag & ZF1_ZMMASK)!=ZF1_ZMCHNG) { if (Verbose) vstringf(_("file exists, skipped: %s\n"),name); return ERROR; } /* try to rename */ namelen=strlen(name); tmpname=alloca(namelen+5); memcpy(tmpname,name,namelen); ptr=tmpname+namelen; *ptr++='.'; i=0; do { sprintf(ptr,"%d",i++); } while (i<1000 && stat(tmpname,&sta)==0); if (i==1000) return ERROR; free(name_static); name_static=malloc(strlen(tmpname)+1); if (!name_static) error(1,0,_("out of memory")); strcpy(name_static,tmpname); zi->fname=name_static; } } if (!*nameend) { /* File coming from CP/M system */ for (p=name_static; *p; ++p) /* change / to _ */ if ( *p == '/') *p = '_'; if ( *--p == '.') /* zap trailing period */ *p = 0; }#ifdef ENABLE_TIMESYNC if (in_timesync) { long t=time(0); long d=t-zi->modtime; if (d<0) d=0; if ((Verbose && d>60) || Verbose > 1) vstringf(_("TIMESYNC: here %ld, remote %ld, diff %ld seconds\n"), (long) t, (long) zi->modtime, d);#ifdef HAVE_SETTIMEOFDAY if (timesync_flag > 1 && d > 10) { struct timeval tv; tv.tv_sec=zi->modtime; tv.tv_usec=0; if (settimeofday(&tv,NULL)) vstringf(_("TIMESYNC: cannot set time: %s\n"), strerror(errno)); }#endif return ERROR; /* skips file */ }#endif /* ENABLE_TIMESYNC */ if (in_tcpsync) { fout=tmpfile(); if (!fout) { error(1,errno,_("cannot tmpfile() for tcp protocol synchronization")); } zi->bytes_received=0; return OK; } if (!zmodem_requested && MakeLCPathname && !IsAnyLower(name_static) && !(zi->mode&UNIXFILE)) uncaps(name_static); if (Topipe > 0) { if (Pathname) free(Pathname); Pathname=malloc((PATH_MAX)*2); if (!Pathname) error(1,0,_("out of memory")); sprintf(Pathname, "%s %s", program_name+2, name_static); if (Verbose) { vstringf("%s: %s %s\n", _("Topipe"), Pathname, Thisbinary?"BIN":"ASCII"); } if ((fout=popen(Pathname, "w")) == NULL) return ERROR; } else { if (protocol==ZM_XMODEM) /* we don't have the filename yet */ return OK; /* dummy */ if (Pathname) free(Pathname); Pathname=malloc((PATH_MAX)*2); if (!Pathname) error(1,0,_("out of memory")); strcpy(Pathname, name_static); if (Verbose) { /* overwrite the "waiting to receive" line */ vstring("\r \r"); vstringf(_("Receiving: %s\n"), name_static); } checkpath(name_static); if (Nflag) { /* cast because we might not have a prototyp for strdup :-/ */ free(name_static); name_static=(char *) strdup("/dev/null"); if (!name_static) { fprintf(stderr,"%s: %s\n", program_name, _("out of memory")); exit(1); } }#ifdef OMEN /* looks like a security hole -- uwe */ if (name_static[0] == '!' || name_static[0] == '|') { if ( !(fout = popen(name_static+1, "w"))) { return ERROR; } Topipe = -1; return(OK); }#endif if (Thisbinary && zconv==ZCRESUM) { struct stat st; fout = fopen(name_static, "r+"); if (fout && 0==fstat(fileno(fout),&st)) { int can_resume=TRUE; if (zmanag==ZF1_ZMCRC) { int r=do_crc_check(fout,zi->bytes_total,st.st_size); if (r==ERROR) { fclose(fout); return ZFERR; } if (r==ZCRC_DIFFERS) { can_resume=FALSE; } } if ((unsigned long)st.st_size > zi->bytes_total) { can_resume=FALSE; } /* retransfer whole blocks */ zi->bytes_skipped = st.st_size & ~(1023); if (can_resume) { if (fseek(fout, (long) zi->bytes_skipped, SEEK_SET)) { fclose(fout); return ZFERR; } } else zi->bytes_skipped=0; /* resume impossible, file has changed */ goto buffer_it; } zi->bytes_skipped=0; if (fout) fclose(fout); } fout = fopen(name_static, openmode);#ifdef ENABLE_MKDIR if ( !fout && Restricted < 2) { if (make_dirs(name_static)) fout = fopen(name_static, openmode); }#endif if ( !fout) {#ifdef ENABLE_SYSLOG int e=errno;#endif zpfatal(_("cannot open %s"), name_static); DO_SYSLOG((LOG_ERR,"%s: cannot open: %s", protname(),strerror(e))); return ERROR; } }buffer_it: if (Topipe == 0) { static char *s=NULL; static size_t last_length=0;#if defined(F_GETFD) && defined(F_SETFD) && defined(O_SYNC) if (o_sync) { int oldflags; oldflags = fcntl (fileno(fout), F_GETFD, 0); if (oldflags>=0 && !(oldflags & O_SYNC)) { oldflags|=O_SYNC; fcntl (fileno(fout), F_SETFD, oldflags); /* errors don't matter */ } }#endif if (buffersize==-1 && s) { if (zi->bytes_total>last_length) { free(s); s=NULL; last_length=0; } } if (!s && buffersize) { last_length=32768; if (buffersize==-1) { if (zi->bytes_total>0) last_length=zi->bytes_total; } else last_length=buffersize; /* buffer `4096' bytes 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(fout,_IOFBF,s,last_length);#else setvbuf(fout,s,_IOFBF,last_length);#endif } } zi->bytes_received=zi->bytes_skipped; return OK;}#ifdef ENABLE_MKDIR/* * Directory-creating routines from Public Domain TAR by John Gilmore *//* * After a file/link/symlink/dir creation has failed, see if * it's because some required directory was not present, and if * so, create all required dirs. */static intmake_dirs(char *pathname){ register char *p; /* Points into path */ int madeone = 0; /* Did we do anything yet? */ int save_errno = errno; /* Remember caller's errno */ if (errno != ENOENT) return 0; /* Not our problem */ for (p = strchr(pathname, '/'); p != NULL; p = strchr(p+1, '/')) { /* Avoid mkdir of empty string, if leading or double '/' */ if (p == pathname || p[-1] == '/') continue; /* Avoid mkdir where last part of path is '.' */ if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/')) continue; *p = 0; /* Truncate the path there */ if ( !mkdir(pathname, 0777)) { /* Try to create it as a dir */ vfile("Made directory %s\n", pathname); madeone++; /* Remember if we made one */ *p = '/'; continue; } *p = '/'; if (errno == EEXIST) /* Directory already exists */ continue; /* * Some other error in the mkdir. We return to the caller. */ break; } errno = save_errno; /* Restore caller's errno */ return madeone; /* Tell them to retry if we made one */}#endif /* ENABLE_MKDIR *//* * Putsec writes the n characters of buf to receive file fout. * If not in binary mode, carriage returns, and all characters * starting with CPMEOF are discarded. */static int putsec(struct zm_fileinfo *zi, char *buf, size_t n){ register char *p; if (n == 0) return OK; if (Thisbinary) { if (fwrite(buf,n,1,fout)!=1) return ERROR; } else { if (zi->eof_seen) return OK; for (p=buf; n>0; ++p,n-- ) { if ( *p == '\r') continue; if (*p == CPMEOF) { zi->eof_seen=TRUE; return OK; } putc(*p ,fout); } } return OK;}/* make string s lower case */static voiduncaps(char *s){ for ( ; *s; ++s) if (isupper((unsigned char)(*s))) *s = tolower(*s);}/* * IsAnyLower returns TRUE if string s has lower case letters. */static int IsAnyLower(const char *s){ for ( ; *s; ++s) if (islower((unsigned char)(*s))) return TRUE; return FALSE;}static voidreport(int sct){ if (Verbose>1) { vstringf(_("Blocks received: %d"),sct); vchar('\r'); }}/* * If called as [-][dir/../]vrzCOMMAND set Verbose to 1 * If called as [-][dir/../]rzCOMMAND set the pipe flag * If called as rb use YMODEM protocol */static voidchkinvok(const char *s){ const char *p; p = s; while (*p == '-') s = ++p; while (*p) if (*p++ == '/') s = p; if (*s == 'v') { Verbose=1; ++s; } program_name = s; if (*s == 'l') s++; /* lrz -> rz */ protocol=ZM_ZMODEM; if (s[0]=='r' && s[1]=='x') protocol=ZM_XMODEM; if (s[0]=='r' && (s[1]=='b' || s[1]=='y')) protocol=ZM_YMODEM; if (s[2] && protocol!=ZM_XMODEM) Topipe = 1;}/* * Totalitarian Communist pathname processing */static void checkpath(const char *name){ if (Restricted) { const char *p; p=strrchr(name,'/'); if (p) p++; else p=name; /* don't overwrite any file in very restricted mode. * don't overwrite hidden files in restricted mode */ if ((Restricted==2 || *name=='.') && fopen(name, "r") != NULL) { canit(STDOUT_FILENO); vstring("\r\n"); vstringf(_("%s: %s exists\n"), program_name, name); bibi(-1); } /* restrict pathnames to current tree or uucppublic */ if ( strstr(name, "../")#ifdef PUBDIR || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR)))#endif ) { canit(STDOUT_FILENO); vstring("\r\n"); vstringf(_("%s:\tSecurity Violation"),program_name); vstring("\r\n"); bibi(-1); } if (Restricted > 1) { if (name[0]=='.' || strstr(name,"/.")) { canit(STDOUT_FILENO); vstring("\r\n"); vstringf(_("%s:\tSecurity Violation"),program_name); vstring("\r\n"); bibi(-1); } } }}/* * Initialize for Zmodem receive attempt, try to activate Zmodem sender * Handles ZSINIT frame * Return ZFILE if Zmodem filename received, -1 on error, * ZCOMPL if transaction finished, else 0 */static inttryz(void){ register int c, n; register int cmdzack1flg; int zrqinits_received=0; size_t bytes_in_block=0; if (protocol!=ZM_ZMODEM) /* Check for "rb" program name */ return 0; for (n=zmodem_requested?15:5; (--n + zrqinits_received) >=0 && zrqinits_received<10; ) { /* Set buffer length (0) and capability flags */#ifdef SEGMENTS stohdr(SEGMENTS*MAX_BLOCK);#else stohdr(0L);#endif#ifdef CANBREAK Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;#else Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;#endif#ifdef ENABLE_TIMESYNC if (timesync_flag) Txhdr[ZF1] |= ZF1_TIMESYNC;#endif if (Zctlesc) Txhdr[ZF0] |= TESCCTL; /* TESCCTL == ESCCTL */ zshhdr(tryzhdrtype, Txhdr); if (tcp_socket==-1 && *tcp_buf) { /* we need to switch to tcp mode */ tcp_socket=tcp_connect(tcp_buf); tcp_buf[0]=0; dup2(tcp_socket,0); dup2(tcp_socket,1); } if (tryzhdrtype == ZSKIP) /* Don't skip too far */ tryzhdrtype = ZRINIT; /* CAF 8-21-87 */again: switch (zgethdr(Rxhdr, 0, NULL)) { case ZRQINIT: /* getting one ZRQINIT is totally ok. Normally a ZFILE follows * (and might be in our buffer, so don't purge it). But if we * get more ZRQINITs than the sender has started up before us * and sent ZRQINITs while waiting. */ zrqinits_received++; continue; case ZEOF: continue; case TIMEOUT: continue; case ZFILE: zconv = Rxhdr[ZF0]; if (!zconv) /* resume with sz -r is impossible (at least with unix sz) * if this is not set */ zconv=ZCBIN; if (Rxhdr[ZF1] & ZF1_ZMSKNOLOC) { Rxhdr[ZF1] &= ~(ZF1_ZMSKNOLOC); skip_if_not_found=TRUE; } zmanag = Rxhdr[ZF1]; ztrans = Rxhdr[ZF2]; tryzhdrtype = ZRINIT; c = zrdata(secbuf, MAX_BLOCK,&bytes_in_block); io_mode(0,3); if (c == GOTCRCW) return ZFILE; zshhdr(ZNAK, Txhdr); goto again; case ZSINIT: /* this once was: * Zctlesc = TESCCTL & Rxhdr[ZF0]; * trouble: if rz get --escape flag: * - it sends TESCCTL to sz, * get a ZSINIT _without_ TESCCTL (yeah - sender didn't know), * overwrites Zctlesc flag ... * - sender receives TESCCTL and uses "|=..." * so: sz escapes, but rz doesn't unescape ... not good. */ Zctlesc |= TESCCTL & Rxhdr[ZF0]; if (zrdata(Attn, ZATTNLEN,&bytes_in_block) == GOTCRCW) { stohdr(1L); zshhdr(ZACK, Txhdr); goto again; } zshhdr(ZNAK, Txhdr); goto again; case ZFREECNT: stohdr(getfree()); zshhdr(ZACK, Txhdr); goto again; case ZCOMMAND: cmdzack1flg = Rxhdr[ZF0]; if (zrdata(secbuf, MAX_BLOCK,&bytes_in_block) == GOTCRCW) { if (Verbose) { vstringf("%s: %s\n", program_name, _("remote command execution requested")); vstringf("%s: %s\n", program_name, secbuf); } if (!allow_remote_commands) { if (Verbose) vstringf("%s: %s\n", program_name, _("not executed")); zshhdr(ZCOMPL, Txhdr); DO_SYSLOG((LOG_INFO,"rexec denied: %s",secbuf)); return ZCOMPL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -