📄 lrz.c
字号:
{ FILE *f=stdout; if (exitcode) { if (what) fprintf(stderr, "%s: %s\n",program_name,what); fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); exit(exitcode); } fprintf(f, _("%s version %s\n"), program_name, VERSION); fprintf(f,_("Usage: %s [options] [filename.if.xmodem]\n"), program_name); fputs(_("Receive files with ZMODEM/YMODEM/XMODEM protocol\n"),f); fputs(_( " (X) = option applies to XMODEM only\n" " (Y) = option applies to YMODEM only\n" " (Z) = option applies to ZMODEM only\n" ),f); fputs(_(" -+, --append append to existing files\n"" -a, --ascii ASCII transfer (change CR/LF to LF)\n"" -b, --binary binary transfer\n"" -B, --bufsize N buffer N bytes (N==auto: buffer whole file)\n"" -c, --with-crc Use 16 bit CRC (X)\n"" -C, --allow-remote-commands allow execution of remote commands (Z)\n"" -D, --null write all received data to /dev/null\n"" --delay-startup N sleep N seconds before doing anything\n"" -e, --escape Escape control characters (Z)\n"" -E, --rename rename any files already existing\n"" --errors N generate CRC error every N bytes (debugging)\n"" -h, --help Help, print this usage message\n"" -m, --min-bps N stop transmission if BPS below N\n"" -M, --min-bps-time N for at least N seconds (default: 120)\n"" -O, --disable-timeouts disable timeout code, wait forever for data\n"" --o-sync open output file(s) in synchronous write mode\n"" -p, --protect protect existing files\n"" -q, --quiet quiet, no progress reports\n"" -r, --resume try to resume interrupted file transfer (Z)\n"" -R, --restricted restricted, more secure mode\n"" -s, --stop-at {HH:MM|+N} stop transmission at HH:MM or in N seconds\n"" -S, --timesync request remote time (twice: set local time)\n"" --syslog[=off] turn syslog on or off, if possible\n"" -t, --timeout N set timeout to N tenths of a second\n"" -u, --keep-uppercase keep upper case filenames\n"" -U, --unrestrict disable restricted mode (if allowed to)\n"" -v, --verbose be verbose, provide debugging information\n"" -w, --windowsize N Window is N bytes (Z)\n"" -X --xmodem use XMODEM protocol\n"" -y, --overwrite Yes, clobber existing file if any\n"" --ymodem use YMODEM protocol\n"" -Z, --zmodem use ZMODEM protocol\n""\n""short options use the same arguments as the long ones\n" ),f); exit(exitcode);}/* * Let's receive something already. */static int wcreceive(int argc, char **argp){ int c; struct zm_fileinfo zi;#ifdef ENABLE_SYSLOG const char *shortname=NULL;;#endif zi.fname=NULL; zi.modtime=0; zi.mode=0; zi.bytes_total=0; zi.bytes_sent=0; zi.bytes_received=0; zi.bytes_skipped=0; zi.eof_seen=0; if (protocol!=ZM_XMODEM || argc==0) { Crcflg=1; if ( !Quiet) vstringf(_("%s waiting to receive."), program_name); if ((c=tryz())!=0) { if (c == ZCOMPL) return OK; if (c == ERROR) goto fubar; c = rzfiles(&zi);#ifdef ENABLE_SYSLOG shortname=NULL;#endif if (c) goto fubar; } else { for (;;) { if (Verbose > 1#ifdef ENABLE_SYSLOG || enable_syslog#endif ) timing(1,NULL);#ifdef ENABLE_SYSLOG shortname=NULL;#endif if (wcrxpn(&zi,secbuf)== ERROR) goto fubar; if (secbuf[0]==0) return OK; if (procheader(secbuf, &zi) == ERROR) goto fubar;#ifdef ENABLE_SYSLOG shortname=strrchr(zi.fname,'/'); if (shortname) shortname++; else shortname=zi.fname;#endif if (wcrx(&zi)==ERROR) goto fubar; 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); }#ifdef ENABLE_SYSLOG if (enable_syslog) lsyslog(LOG_INFO,"%s/%s: %ld Bytes, %ld BPS", shortname,protname(),zi.bytes_received, bps);#endif } } } } else { char dummy[128]; dummy[0]='\0'; /* pre-ANSI HPUX cc demands this */ dummy[1]='\0'; /* procheader uses name + 1 + strlen(name) */ zi.bytes_total = DEFBYTL; if (Verbose > 1#ifdef ENABLE_SYSLOG || enable_syslog#endif ) timing(1,NULL); procheader(dummy, &zi); if (Pathname) free(Pathname); errno=0; Pathname=malloc(PATH_MAX+1); if (!Pathname) error(1,0,_("out of memory")); strcpy(Pathname, *argp); checkpath(Pathname);#ifdef ENABLE_SYSLOG shortname=strrchr(*argp,'/'); if (shortname) shortname++; else shortname=*argp;#endif vchar('\n'); vstringf(_("%s: ready to receive %s"), program_name, Pathname); vstring("\r\n"); if ((fout=fopen(Pathname, "w")) == NULL) {#ifdef ENABLE_SYSLOG if (enable_syslog) lsyslog(LOG_ERR,"%s/%s: cannot open: %m", shortname,protname());#endif return ERROR; } if (wcrx(&zi)==ERROR) { goto fubar; } 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) { vstringf( _("\rBytes received: %7ld BPS:%-6ld \r\n"), (long) zi.bytes_received, bps); }#ifdef ENABLE_SYSLOG if (enable_syslog) lsyslog(LOG_INFO,"%s/%s: %ld Bytes, %ld BPS", shortname,protname(),zi.bytes_received, bps);#endif } } return OK;fubar:#ifdef ENABLE_SYSLOG if (enable_syslog) lsyslog(LOG_ERR,"%s/%s: got error", shortname ? shortname : "no.name", protname());#endif canit(STDOUT_FILENO); if (Topipe && fout) { pclose(fout); return ERROR; } if (fout) fclose(fout); if (Restricted && Pathname) { unlink(Pathname); vstringf(_("\r\n%s: %s removed.\r\n"), program_name, Pathname); } return ERROR;}/* * Fetch a pathname from the other end as a C ctyle ASCIZ string. * Length is indeterminate as long as less than Blklen * A null string represents no more files (YMODEM) */static int wcrxpn(struct zm_fileinfo *zi, char *rpn){ register int c; size_t Blklen=0; /* record length of received packets */#ifdef NFGVMIN READLINE_PF(1);#else purgeline(0);#endifet_tu: Firstsec=TRUE; zi->eof_seen=FALSE; sendline(Crcflg?WANTCRC:NAK); flushmo(); purgeline(0); /* Do read next time ... */ while ((c = wcgetsec(&Blklen, rpn, 100)) != 0) { if (c == WCEOT) { zperr( _("Pathname fetch returned EOT")); sendline(ACK); flushmo(); purgeline(0); /* Do read next time ... */ READLINE_PF(1); goto et_tu; } return ERROR; } sendline(ACK); flushmo(); return OK;}/* * Adapted from CMODEM13.C, written by * Jack M. Wierda and Roderick W. Hart */static int wcrx(struct zm_fileinfo *zi){ register int sectnum, sectcurr; register char sendchar; size_t Blklen; Firstsec=TRUE;sectnum=0; zi->eof_seen=FALSE; sendchar=Crcflg?WANTCRC:NAK; for (;;) { sendline(sendchar); /* send it now, we're ready! */ flushmo(); purgeline(0); /* Do read next time ... */ sectcurr=wcgetsec(&Blklen, secbuf, (unsigned int) ((sectnum&0177) ? 50 : 130)); report(sectcurr); if (sectcurr==((sectnum+1) &0377)) { sectnum++; /* if using xmodem we don't know how long a file is */ if (zi->bytes_total && R_BYTESLEFT(zi) < Blklen) Blklen=R_BYTESLEFT(zi); zi->bytes_received+=Blklen; if (putsec(zi, secbuf, Blklen)==ERROR) return ERROR; sendchar=ACK; } else if (sectcurr==(sectnum&0377)) { zperr( _("Received dup Sector")); sendchar=ACK; } else if (sectcurr==WCEOT) { if (closeit(zi)) return ERROR; sendline(ACK); flushmo(); purgeline(0); /* Do read next time ... */ return OK; } else if (sectcurr==ERROR) return ERROR; else { zperr( _("Sync Error")); return ERROR; } }}/* * Wcgetsec fetches a Ward Christensen type sector. * Returns sector number encountered or ERROR if valid sector not received, * or CAN CAN received * or WCEOT if eot sector * time is timeout for first char, set to 4 seconds thereafter ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK ************** * (Caller must do that when he is good and ready to get next sector) */static intwcgetsec(size_t *Blklen, char *rxbuf, unsigned int maxtime){ register int checksum, wcj, firstch; register unsigned short oldcrc; register char *p; int sectcurr; for (Lastrx=errors=0; errors<RETRYMAX; errors++) { if ((firstch=READLINE_PF(maxtime))==STX) { *Blklen=1024; goto get2; } if (firstch==SOH) { *Blklen=128;get2: sectcurr=READLINE_PF(1); if ((sectcurr+(oldcrc=READLINE_PF(1)))==0377) { oldcrc=checksum=0; for (p=rxbuf,wcj=*Blklen; --wcj>=0; ) { if ((firstch=READLINE_PF(1)) < 0) goto bilge; oldcrc=updcrc(firstch, oldcrc); checksum += (*p++ = firstch); } if ((firstch=READLINE_PF(1)) < 0) goto bilge; if (Crcflg) { oldcrc=updcrc(firstch, oldcrc); if ((firstch=READLINE_PF(1)) < 0) goto bilge; oldcrc=updcrc(firstch, oldcrc); if (oldcrc & 0xFFFF) zperr( _("CRC")); else { Firstsec=FALSE; return sectcurr; } } else if (((checksum-firstch)&0377)==0) { Firstsec=FALSE; return sectcurr; } else zperr( _("Checksum")); } else zperr(_("Sector number garbled")); } /* make sure eot really is eot and not just mixmash */#ifdef NFGVMIN else if (firstch==EOT && READLINE_PF(1)==TIMEOUT) return WCEOT;#else else if (firstch==EOT && READLINE_PF>0) return WCEOT;#endif else if (firstch==CAN) { if (Lastrx==CAN) { zperr( _("Sender Cancelled")); return ERROR; } else { Lastrx=CAN; continue; } } else if (firstch==TIMEOUT) { if (Firstsec) goto humbug;bilge: zperr( _("TIMEOUT")); } else zperr( _("Got 0%o sector header"), firstch);humbug: Lastrx=0; { int cnt=1000; while(cnt-- && READLINE_PF(1)!=TIMEOUT) ; } if (Firstsec) { sendline(Crcflg?WANTCRC:NAK); flushmo(); purgeline(0); /* Do read next time ... */ } else { maxtime=40; sendline(NAK); flushmo(); purgeline(0); /* Do read next time ... */ } } /* try to stop the bubble machine. */ canit(STDOUT_FILENO); return ERROR;}#define ZCRC_DIFFERS (ERROR+1)#define ZCRC_EQUAL (ERROR+2)/* * do ZCRC-Check for open file f. * check at most check_bytes bytes (crash recovery). if 0 -> whole file. * remote file size is remote_bytes. */static int do_crc_check(FILE *f, size_t remote_bytes, size_t check_bytes) { struct stat st; unsigned long crc; unsigned long rcrc; size_t n; int c; int t1=0,t2=0; if (-1==fstat(fileno(f),&st)) { DO_SYSLOG((LOG_ERR,"cannot fstat open file: %s",strerror(errno))); return ERROR; } if (check_bytes==0 && ((size_t) st.st_size)!=remote_bytes) return ZCRC_DIFFERS; /* shortcut */ crc=0xFFFFFFFFL; n=check_bytes; if (n==0) n=st.st_size; while (n-- && ((c = getc(f)) != EOF)) crc = UPDC32(c, crc); crc = ~crc; clearerr(f); /* Clear EOF */ fseek(f, 0L, 0); while (t1<3) { stohdr(check_bytes); zshhdr(ZCRC, Txhdr); while(t2<3) { size_t tmp; c = zgethdr(Rxhdr, 0, &tmp); rcrc=(unsigned long) tmp; switch (c) { default: /* ignore */ break; case ZFIN: return ERROR; case ZRINIT: return ERROR; case ZCAN: if (Verbose) vstringf(_("got ZCAN")); return ERROR; break; case ZCRC: if (crc!=rcrc) return ZCRC_DIFFERS; return ZCRC_EQUAL; break; } } } return ERROR;}/* * Process incoming file information header */static intprocheader(char *name, struct zm_fileinfo *zi){ const char *openmode; char *p; static char *name_static=NULL; char *nameend; if (name_static) free(name_static); if (junk_path) { p=strrchr(name,'/'); if (p) { p++; if (!*p) { /* alert - file name ended in with a / */ if (Verbose) vstringf(_("file name ends with a /, skipped: %s\n"),name); DO_SYSLOG((LOG_ERR,"file name ends with a /, skipped: %s", name)); return ERROR; } name=p; } } name_static=malloc(strlen(name)+1); if (!name_static) error(1,0,_("out of memory")); strcpy(name_static,name); zi->fname=name_static; if (Verbose>2) { vstringf(_("zmanag=%d, Lzmanag=%d\n"),zmanag,Lzmanag); vstringf(_("zconv=%d\n"),zconv); } /* set default parameters and overrides */ openmode = "w"; Thisbinary = (!Rxascii) || Rxbinary; if (Lzmanag) zmanag = Lzmanag; /* * Process ZMODEM remote file management requests */ if (!Rxbinary && zconv == ZCNL) /* Remote ASCII override */ Thisbinary = 0; if (zconv == ZCBIN) /* Remote Binary override */ Thisbinary = TRUE; if (Thisbinary && zconv == ZCBIN && try_resume) zconv=ZCRESUM; if (zmanag == ZF1_ZMAPND && zconv!=ZCRESUM) openmode = "a"; if (skip_if_not_found) openmode="r+";#ifdef ENABLE_TIMESYNC in_timesync=0; if (timesync_flag && 0==strcmp(name,"$time$.t")) in_timesync=1;#endif in_tcpsync=0; if (tcpsync_flag && 0==strcmp(name,"$tcp$.t")) in_tcpsync=1; zi->bytes_total = DEFBYTL; zi->mode = 0; zi->eof_seen = 0; zi->modtime = 0; nameend = name + 1 + strlen(name); if (*nameend) { /* file coming from Unix or DOS system */ long modtime; long bytes_total; int mode; sscanf(nameend, "%ld%lo%o", &bytes_total, &modtime, &mode); zi->modtime=modtime; zi->bytes_total=bytes_total; zi->mode=mode; if (zi->mode & UNIXFILE) ++Thisbinary;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -