📄 lrz.c
字号:
} DO_SYSLOG((LOG_INFO,"rexec allowed: %s",secbuf)); if (cmdzack1flg & ZCACK1) stohdr(0L); else stohdr((size_t)sys2(secbuf)); purgeline(0); /* dump impatient questions */ do { zshhdr(ZCOMPL, Txhdr); } while (++errors<20 && zgethdr(Rxhdr,1, NULL) != ZFIN); ackbibi(); if (cmdzack1flg & ZCACK1) exec2(secbuf); return ZCOMPL; } zshhdr(ZNAK, Txhdr); goto again; case ZCOMPL: goto again; default: continue; case ZFIN: ackbibi(); return ZCOMPL; case ZRINIT: if (Verbose) vstringf(_("got ZRINIT")); return ERROR; case ZCAN: if (Verbose) vstringf(_("got ZCAN")); return ERROR; } } return 0;}/* * Receive 1 or more files with ZMODEM protocol */static intrzfiles(struct zm_fileinfo *zi){ register int c; for (;;) { timing(1,NULL); c = rzfile(zi); switch (c) { case ZEOF: if (Verbose > 1#ifdef ENABLE_SYSLOG || enable_syslog#endif ) { double d; long bps; d=timing(0,NULL); if (d==0) d=0.5; /* can happen if timing uses time() */ bps=(zi->bytes_received-zi->bytes_skipped)/d; if (Verbose > 1) { vstringf( _("\rBytes received: %7ld/%7ld BPS:%-6ld \r\n"), (long) zi->bytes_received, (long) zi->bytes_total, bps); } DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: %ld Bytes, %ld BPS",shortname, protname(), (long) zi->bytes_total,bps)); } /* FALL THROUGH */ case ZSKIP: if (c==ZSKIP) { if (Verbose) vstringf(_("Skipped")); DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: skipped",shortname,protname())); } switch (tryz()) { case ZCOMPL: return OK; default: return ERROR; case ZFILE: break; } continue; default: return c; case ERROR: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error",shortname,protname())); return ERROR; } }}/* "OOSB" means Out Of Sync Block. I once thought that if sz sents * blocks a,b,c,d, of which a is ok, b fails, we might want to save * c and d. But, alas, i never saw c and d. */#define SAVE_OOSB#ifdef SAVE_OOSBtypedef struct oosb_t { size_t pos; size_t len; char *data; struct oosb_t *next;} oosb_t;struct oosb_t *anker=NULL;#endif/* * Receive a file with ZMODEM protocol * Assumes file name frame is in secbuf */static intrzfile(struct zm_fileinfo *zi){ register int c, n; long last_rxbytes=0; unsigned long last_bps=0; long not_printed=0; time_t low_bps=0; size_t bytes_in_block=0; zi->eof_seen=FALSE; n = 20; if (procheader(secbuf,zi) == ERROR) { DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: procheader error", shortname,protname())); return (tryzhdrtype = ZSKIP); } for (;;) {#ifdef SEGMENTS chinseg = 0;#endif stohdr(zi->bytes_received); zshhdr(ZRPOS, Txhdr); goto skip_oosb;nxthdr:#ifdef SAVE_OOSB if (anker) { oosb_t *akt,*last,*next; for (akt=anker,last=NULL;akt;last= akt ? akt : last ,akt=next) { if (akt->pos==zi->bytes_received) { putsec(zi, akt->data, akt->len); zi->bytes_received += akt->len; vfile("using saved out-of-sync-paket %lx, len %ld", akt->pos,akt->len); goto nxthdr; } next=akt->next; if (akt->pos<zi->bytes_received) { vfile("removing unneeded saved out-of-sync-paket %lx, len %ld", akt->pos,akt->len); if (last) last->next=akt->next; else anker=akt->next; free(akt->data); free(akt); akt=NULL; } } }#endif skip_oosb: c = zgethdr(Rxhdr, 0, NULL); switch (c) { default: DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: zgethdr returned %d",shortname, protname(),c)); vfile("rzfile: zgethdr returned %d", c); return ERROR; case ZNAK: case TIMEOUT:#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif if ( --n < 0) { DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: zgethdr returned %s",shortname, protname(),c == ZNAK ? "ZNAK" : "TIMEOUT")); vfile("rzfile: zgethdr returned %d", c); return ERROR; } case ZFILE: zrdata(secbuf, MAX_BLOCK,&bytes_in_block); continue; case ZEOF:#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif if (rclhdr(Rxhdr) != (long) zi->bytes_received) { /* * Ignore eof if it's at wrong place - force * a timeout because the eof might have gone * out before we sent our zrpos. */ errors = 0; goto nxthdr; } if (closeit(zi)) { tryzhdrtype = ZFERR; DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: closeit return <>0", shortname, protname())); vfile("rzfile: closeit returned <> 0"); return ERROR; } vfile("rzfile: normal EOF"); return c; case ERROR: /* Too much garbage in header search error */#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif if ( --n < 0) { DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: zgethdr returned %d", shortname, protname(),c)); vfile("rzfile: zgethdr returned %d", c); return ERROR; } zmputs(Attn); continue; case ZSKIP:#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif closeit(zi); DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: sender skipped", shortname, protname())); vfile("rzfile: Sender SKIPPED file"); return c; case ZDATA: if (rclhdr(Rxhdr) != (long) zi->bytes_received) {#if defined(SAVE_OOSB) oosb_t *neu; size_t pos=rclhdr(Rxhdr);#endif if ( --n < 0) { vfile("rzfile: out of sync"); DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: error: out of sync", shortname, protname())); return ERROR; }#if defined(SAVE_OOSB) switch (c = zrdata(secbuf, MAX_BLOCK,&bytes_in_block)) { case GOTCRCW: case GOTCRCG: case GOTCRCE: case GOTCRCQ: if (pos>zi->bytes_received) { neu=malloc(sizeof(oosb_t)); if (neu) neu->data=malloc(bytes_in_block); if (neu && neu->data) {#ifdef ENABLE_SYSLOG/* call syslog to tell me if this happens */ lsyslog(LOG_ERR, "saving out-of-sync-block %lx, len %lu", pos, (unsigned long) bytes_in_block);#endif vfile("saving out-of-sync-block %lx, len %lu",pos, (unsigned long) bytes_in_block); memcpy(neu->data,secbuf,bytes_in_block); neu->pos=pos; neu->len=bytes_in_block; neu->next=anker; anker=neu; } else if (neu) free(neu); } }#endif#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif zmputs(Attn); continue; }moredata: if ((Verbose>1 || min_bps || stop_time) && (not_printed > (min_bps ? 3 : 7) || zi->bytes_received > last_bps / 2 + last_rxbytes)) { int minleft = 0; int secleft = 0; time_t now; double d; d=timing(0,&now); if (d==0) d=0.5; /* timing() might use time() */ last_bps=zi->bytes_received/d; if (last_bps > 0) { minleft = (R_BYTESLEFT(zi))/last_bps/60; secleft = ((R_BYTESLEFT(zi))/last_bps)%60; } if (min_bps) { if (low_bps) { if (last_bps<min_bps) { if (now-low_bps>=min_bps_time) { /* too bad */ vfile(_("rzfile: bps rate %ld below min %ld"), last_bps, min_bps); DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: bps rate low: %ld < %ld", shortname, protname(), last_bps, min_bps)); return ERROR; } } else low_bps=0; } else if (last_bps<min_bps) { low_bps=now; } } if (stop_time && now>=stop_time) { /* too bad */ vfile(_("rzfile: reached stop time")); DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: reached stop time", shortname, protname())); return ERROR; } if (Verbose > 1) { vstringf(_("\rBytes received: %7ld/%7ld BPS:%-6ld ETA %02d:%02d "), (long) zi->bytes_received, (long) zi->bytes_total, last_bps, minleft, secleft); last_rxbytes=zi->bytes_received; not_printed=0; } } else if (Verbose) not_printed++;#ifdef SEGMENTS if (chinseg >= (MAX_BLOCK * SEGMENTS)) { putsec(secbuf, chinseg); chinseg = 0; } switch (c = zrdata(secbuf+chinseg, MAX_BLOCK,&bytes_in_block))#else switch (c = zrdata(secbuf, MAX_BLOCK,&bytes_in_block))#endif { case ZCAN:#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif vfile("rzfile: zrdata returned %d", c); DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: zrdata returned ZCAN", shortname, protname())); return ERROR; case ERROR: /* CRC error */#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif if ( --n < 0) { vfile("rzfile: zgethdr returned %d", c); DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: zrdata returned ERROR", shortname, protname())); return ERROR; } zmputs(Attn); continue; case TIMEOUT:#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif if ( --n < 0) { DO_SYSLOG_FNAME((LOG_INFO, "%s/%s: zrdata returned TIMEOUT", shortname, protname())); vfile("rzfile: zgethdr returned %d", c); return ERROR; } continue; case GOTCRCW: n = 20;#ifdef SEGMENTS chinseg += bytes_in_block; putsec(zi, secbuf, chinseg); chinseg = 0;#else putsec(zi, secbuf, bytes_in_block);#endif zi->bytes_received += bytes_in_block; stohdr(zi->bytes_received); zshhdr(ZACK | 0x80, Txhdr); goto nxthdr; case GOTCRCQ: n = 20;#ifdef SEGMENTS chinseg += bytes_in_block;#else putsec(zi, secbuf, bytes_in_block);#endif zi->bytes_received += bytes_in_block; stohdr(zi->bytes_received); zshhdr(ZACK, Txhdr); goto moredata; case GOTCRCG: n = 20;#ifdef SEGMENTS chinseg += bytes_in_block;#else putsec(zi, secbuf, bytes_in_block);#endif zi->bytes_received += bytes_in_block; goto moredata; case GOTCRCE: n = 20;#ifdef SEGMENTS chinseg += bytes_in_block;#else putsec(zi, secbuf, bytes_in_block);#endif zi->bytes_received += bytes_in_block; goto nxthdr; } } }}/* * Send a string to the modem, processing for \336 (sleep 1 sec) * and \335 (break signal) */static voidzmputs(const char *s){ const char *p; while (s && *s) { p=strpbrk(s,"\335\336"); if (!p) { write(1,s,strlen(s)); return; } if (p!=s) { write(1,s,(size_t) (p-s)); s=p; } if (*p=='\336') sleep(1); else sendbrk(0); p++; }}/* * Close the receive dataset, return OK or ERROR */static intcloseit(struct zm_fileinfo *zi){ int ret; if (Topipe) { if (pclose(fout)) { return ERROR; } return OK; } if (in_tcpsync) { rewind(fout); if (!fgets(tcp_buf,sizeof(tcp_buf),fout)) { error(1,errno,_("fgets for tcp protocol synchronization failed: ")); } fclose(fout); return OK; } ret=fclose(fout); if (ret) { zpfatal(_("file close error")); /* this may be any sort of error, including random data corruption */ unlink(Pathname); return ERROR; } if (zi->modtime) {#ifdef HAVE_STRUCT_UTIMBUF struct utimbuf timep; timep.actime = time(NULL); timep.modtime = zi->modtime; utime(Pathname, &timep);#else time_t timep[2]; timep[0] = time(NULL); timep[1] = zi->modtime; utime(Pathname, timep);#endif }#ifdef S_ISREG if (S_ISREG(zi->mode)) {#else if ((zi->mode&S_IFMT) == S_IFREG) {#endif /* we must not make this program executable if running * under rsh, because the user might have uploaded an * unrestricted shell. */ if (under_rsh) chmod(Pathname, (00666 & zi->mode)); else chmod(Pathname, (07777 & zi->mode)); } return OK;}/* * Ack a ZFIN packet, let byegones be byegones */static voidackbibi(void){ int n; vfile("ackbibi:"); Readnum = 1; stohdr(0L); for (n=3; --n>=0; ) { purgeline(0); zshhdr(ZFIN, Txhdr); switch (READLINE_PF(100)) { case 'O': READLINE_PF(1); /* Discard 2nd 'O' */ vfile("ackbibi complete"); return; case RCDO: return; case TIMEOUT: default: break; } }}/* * Strip leading ! if present, do shell escape. */static intsys2(const char *s){ if (*s == '!') ++s; return system(s);}/* * Strip leading ! if present, do exec. */static void exec2(const char *s){ if (*s == '!') ++s; io_mode(0,0); execl("/bin/sh", "sh", "-c", s); zpfatal("execl"); exit(1);}/* * Routine to calculate the free bytes on the current file system * ~0 means many free bytes (unknown) */static size_t getfree(void){ return((size_t) (~0L)); /* many free bytes ... */}/* End of lrz.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -