📄 lrz.c
字号:
* 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) */wcgetsec(rxbuf, maxtime)char *rxbuf;int maxtime;{ register checksum, wcj, firstch; register unsigned short oldcrc; register char *p; int sectcurr; for (Lastrx=errors=0; errors<RETRYMAX; errors++) { if ((firstch=readline(maxtime))==STX) { Blklen=1024; goto get2; } if (firstch==SOH) { Blklen=128;get2: sectcurr=readline(1); if ((sectcurr+(oldcrc=readline(1)))==0377) { oldcrc=checksum=0; for (p=rxbuf,wcj=Blklen; --wcj>=0; ) { if ((firstch=readline(1)) < 0) goto bilge; oldcrc=updcrc(firstch, oldcrc); checksum += (*p++ = firstch); } if ((firstch=readline(1)) < 0) goto bilge; if (Crcflg) { oldcrc=updcrc(firstch, oldcrc); if ((firstch=readline(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(1)==TIMEOUT) return WCEOT;#else else if (firstch==EOT && Lleft==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; while(readline(1)!=TIMEOUT) ; if (Firstsec) { sendline(Crcflg?WANTCRC:NAK); Lleft=0; /* Do read next time ... */ } else { maxtime=40; sendline(NAK); Lleft=0; /* Do read next time ... */ } } /* try to stop the bubble machine. */ canit(); return ERROR;}/* * This version of readline is reasoably well suited for * reading many characters. * (except, currently, for the Regulus version!) * * timeout is in tenths of seconds */readline(timeout)int timeout;{ register n;#ifndef READLINE_PF static char *readline_ptr; /* pointer for removing chars from linbuf */#endif if (--Lleft >= 0) { if (Verbose > 8) { fprintf(stderr, "%02x ", *readline_ptr&0377); } return (*readline_ptr++ & 0377); } if (!no_timeout) { n = timeout/10; if (n < 2) n = 3; if (Verbose > 5) fprintf(stderr, "Calling read: alarm=%d Readnum=%d ", n, Readnum); signal(SIGALRM, alrm); alarm(n); } else if (Verbose > 5) fprintf(stderr, "Calling read: Readnum=%d ", Readnum); Lleft=read(iofd, readline_ptr=linbuf, Readnum); if (!no_timeout) alarm(0); if (Verbose > 5) { fprintf(stderr, "Read returned %d bytes\n", Lleft); } if (Lleft < 1) return TIMEOUT; --Lleft; if (Verbose > 8) { fprintf(stderr, "%02x ", *readline_ptr&0377); } return (*readline_ptr++ & 0377);}/* * Purge the modem input queue of all characters */purgeline(){ Lleft = 0;#ifdef TCFLSH ioctl(iofd, TCFLSH, 0);#else lseek(iofd, 0L, 2);#endif}/* * Process incoming file information header */procheader(name)char *name;{ register char *openmode, *p, **pp; int tabs, tab_num; /* 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; else if (zmanag == ZMAPND) openmode = "a"; if (Thisbinary && zconv == ZCBIN && try_resume) zconv=ZCRESUM;#ifdef ENABLE_TIMESYNC in_timesync=0; if (timesync_flag && 0==strcmp(name,"$time$.t")) in_timesync=1;#endif /* Check for existing file */ if (zconv != ZCRESUM && !Rxclob && (zmanag&ZMMASK) != ZMCLOB && (fout=fopen(name, "r"))) {#ifdef ENABLE_TIMESYNC if (!in_timesync)#endif fclose(fout); return ERROR; } Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L; p = name + 1 + strlen(name); if (*p) { /* file coming from Unix or DOS system */ sscanf(p, "%ld%lo%o", &Bytesleft, &Modtime, &Filemode); if (Filemode & UNIXFILE) ++Thisbinary; } else { /* File coming from CP/M system */ for (p=name; *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-Modtime; if (d<0) d=0; if ((Verbose && d>60) || Verbose > 1) fprintf(stderr, "TIMESYNC: here %ld, remote %ld, diff %d seconds\n", (long) t, (long) Modtime, (long) d);#ifdef HAVE_SETTIMEOFDAY if (timesync_flag > 1 && d > 10) { struct timeval tv; tv.tv_sec=Modtime; tv.tv_usec=0; if (settimeofday(&tv,NULL)) fprintf(stderr, "TIMESYNC: cannot set time: %s\n", strerror(errno)); }#endif return ERROR; /* skips file */ }#endif /* ENABLE_TIMESYNC */ if (!Zmodem && MakeLCPathname && !IsAnyLower(name) && !(Filemode&UNIXFILE)) uncaps(name); if (Topipe > 0) { sprintf(Pathname, "%s %s", Progname+2, name); if (Verbose) fprintf(stderr, "Topipe: %s %s\n", Pathname, Thisbinary?"BIN":"ASCII"); if ((fout=popen(Pathname, "w")) == NULL) return ERROR; } else { strcpy(Pathname, name); if (Verbose) fprintf(stderr, "\nReceiving: %s\n", name); timing(1); checkpath(name); if (Nflag) name = "/dev/null";#ifdef OMEN if (name[0] == '!' || name[0] == '|') { if ( !(fout = popen(name+1, "w"))) { return ERROR; } Topipe = -1; return(OK); }#endif if (Thisbinary && zconv==ZCRESUM) { struct stat st; fout = fopen(name, "r+"); if (fout && 0==fstat(fileno(fout),&st)) { /* retransfer whole blocks */ rxbytes = st.st_size & ~(1024); /* Bytesleft == filelength on remote */ if (rxbytes < Bytesleft) { if (fseek(fout, rxbytes, 0)) { fclose(fout); return ZFERR; } } goto buffer_it; } rxbytes=0; if (fout) fclose(fout); }#ifdef ENABLE_MKDIR fout = fopen(name, openmode); if ( !fout && Restricted < 2) if (make_dirs(name)) fout = fopen(name, openmode);#else fout = fopen(name, openmode);#endif if ( !fout) { int e=errno; fprintf(stderr, "lrz: cannot open %s: %s\n", name, strerror(e)); return ERROR; } }buffer_it: if (Topipe == 0) { static char *s=NULL; if (!s) { s=malloc(16384); if (!s) { fprintf(stderr,"lrz: out of memory\r\n"); exit(1); }#ifdef SETVBUF_REVERSED setvbuf(fout,_IOFBF,s,16384);#else setvbuf(fout,s,_IOFBF,16384);#endif } } 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. */make_dirs(pathname)register char *pathname;{ register char *p; /* Points into path */ int madeone = 0; /* Did we do anything yet? */ int save_errno = errno; /* Remember caller's errno */ char *strchr(); 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. */putsec(buf, n) char *buf; register n;{ register char *p; if (n == 0) return OK; if (Thisbinary) { if (fwrite(buf,n,1,fout)!=1) return ERROR; } else { if (Eofseen) return OK; for (p=buf; --n>=0; ++p ) { if ( *p == '\r') continue; if (*p == CPMEOF) { Eofseen=TRUE; return OK; } putc(*p ,fout); } } return OK;}/* * Send a character to modem. Small is beautiful. */sendline(c){ char d; d = c; if (Verbose>6) fprintf(stderr, "Sendline: %x\n", c); write(1, &d, 1);}flushmo() {}/* make string s lower case */uncaps(s)register char *s;{ for ( ; *s; ++s) if (isupper(*s)) *s = tolower(*s);}/* * IsAnyLower returns TRUE if string s has lower case letters. */IsAnyLower(s)register char *s;{ for ( ; *s; ++s) if (islower(*s)) return TRUE; return FALSE;}/* * Log an error *//*VARARGS1*/zperr(s,p,u)char *s, *p, *u;{ if (Verbose <= 0) return; fprintf(stderr, "Retry %d: ", errors); fprintf(stderr, s, p, u); fprintf(stderr, "\n");}/* send cancel string to get the other end to shut up */canit(){ static char canistr[] = { 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 }; printf(canistr); Lleft=0; /* Do read next time ... */ fflush(stdout);}report(sct)int sct;{ if (Verbose>1) fprintf(stderr,"Blocks received: %d\r",sct);}/* * 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 */chkinvok(s)char *s;{ register char *p; p = s; while (*p == '-') s = ++p; while (*p) if (*p++ == '/') s = p; if (*s == 'v') { Verbose=1; ++s; } Progname = s; if (*s == 'l') { /* lrz -> rz */ ++s; } if (s[0]=='r' && s[1]=='z') Batch = TRUE; if (s[0]=='r' && s[1]=='b') Batch = Nozmodem = TRUE; if (s[2] && s[0]=='r' && s[1]=='b') Topipe = 1; if (s[2] && s[0]=='r' && s[1]=='z') Topipe = 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -