📄 rz.c
字号:
for (;;) { sendline(sendchar); /* send it now, we're ready! */ Lleft=0; /* Do read next time ... */ sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130); report(sectcurr); if (sectcurr==(sectnum+1 &0377)) { sectnum++; cblklen = Bytesleft>Blklen ? Blklen:Bytesleft; if (putsec(secbuf, cblklen)==ERROR) return ERROR; if ((Bytesleft-=cblklen) < 0) Bytesleft = 0; sendchar=ACK; } else if (sectcurr==(sectnum&0377)) { zperr( "Received dup Sector"); sendchar=ACK; } else if (sectcurr==WCEOT) { if (closeit()) return ERROR; sendline(ACK); Lleft=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) */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;}#ifndef vax11c/* * 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; static char *cdq; /* pointer for removing chars from linbuf */ if (--Lleft >= 0) { if (Verbose > 8) { fprintf(stderr, "%02x ", *cdq&0377); } return (*cdq++ & 0377); } n = timeout/10; if (n < 2) n = 3; if (Verbose > 5) fprintf(stderr, "Calling read: alarm=%d Readnum=%d ", n, Readnum); if (setjmp(tohere)) {#ifdef TIOCFLUSH/* ioctl(0, TIOCFLUSH, 0); */#endif Lleft = 0; if (Verbose>1) fprintf(stderr, "Readline:TIMEOUT\n"); return TIMEOUT; } signal(SIGALRM, alrm); alarm(n); Lleft=read(0, cdq=linbuf, Readnum); 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 ", *cdq&0377); } return (*cdq++ & 0377);}/* * Purge the modem input queue of all characters */purgeline(){ Lleft = 0;#ifdef USG ioctl(0, TCFLSH, 0);#else lseek(0, 0L, 2);#endif}#endif/* * Process incoming file information header */procheader(name)char *name;{ register char *openmode, *p, **pp; /* 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";#ifndef BIX /* Check for existing file */ if (!Rxclob && (zmanag&ZMMASK) != ZMCLOB && (fout=fopen(name, "r"))) { fclose(fout); return ERROR; }#endif 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);#ifndef vax11c if (Filemode & UNIXFILE) ++Thisbinary;#endif if (Verbose) { fprintf(stderr, "Incoming: %s %ld %lo %o\n", name, Bytesleft, Modtime, Filemode); } }#ifdef BIX if ((fout=fopen("scratchpad", openmode)) == NULL) return ERROR; return OK;#else else { /* File coming from CP/M system */ for (p=name; *p; ++p) /* change / to _ */ if ( *p == '/') *p = '_'; if ( *--p == '.') /* zap trailing period */ *p = 0; }#ifndef vax11c if (!Zmodem && MakeLCPathname && !IsAnyLower(name) && !(Filemode&UNIXFILE)) uncaps(name);#endif if (Topipe > 0) { sprintf(Pathname, "%s %s", Progname+2, name); if (Verbose) fprintf(stderr, "Topipe: %s %s\n", Pathname, Thisbinary?"BIN":"ASCII");#ifndef vax11c if ((fout=popen(Pathname, "w")) == NULL) return ERROR;#endif } else { strcpy(Pathname, name); if (Verbose) { fprintf(stderr, "Receiving %s %s %s\n", name, Thisbinary?"BIN":"ASCII", openmode); } checkpath(name); if (Nflag) name = "/dev/null";#ifndef vax11c if (name[0] == '!' || name[0] == '|') { if ( !(fout = popen(name+1, "w"))) { return ERROR; } Topipe = -1; return(OK); }#endif#ifdef MD fout = fopen(name, openmode); if ( !fout) if (make_dirs(name)) fout = fopen(name, openmode);#else fout = fopen(name, openmode);#endif if ( !fout) return ERROR; } return OK;#endif /* BIX */}#ifdef MD/* * 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 */}#if (MD != 2)#define TERM_SIGNAL(status) ((status) & 0x7F)#define TERM_COREDUMP(status) (((status) & 0x80) != 0)#define TERM_VALUE(status) ((status) >> 8)/* * Make a directory. Compatible with the mkdir() system call on 4.2BSD. */mkdir(dpath, dmode)char *dpath;int dmode;{ int cpid, status; struct stat statbuf; if (stat(dpath,&statbuf) == 0) { errno = EEXIST; /* Stat worked, so it already exists */ return -1; } /* If stat fails for a reason other than non-existence, return error */ if (errno != ENOENT) return -1; switch (cpid = fork()) { case -1: /* Error in fork() */ return(-1); /* Errno is set already */ case 0: /* Child process */ /* * Cheap hack to set mode of new directory. Since this * child process is going away anyway, we zap its umask. * FIXME, this won't suffice to set SUID, SGID, etc. on this * directory. Does anybody care? */ status = umask(0); /* Get current umask */ status = umask(status | (0777 & ~dmode)); /* Set for mkdir */ execl("/bin/mkdir", "mkdir", dpath, (char *)0); _exit(-1); /* Can't exec /bin/mkdir */ default: /* Parent process */ while (cpid != wait(&status)) ; /* Wait for kid to finish */ } if (TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0) { errno = EIO; /* We don't know why, but */ return -1; /* /bin/mkdir failed */ } return 0;}#endif /* MD != 2 */#endif /* MD *//* * 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) { for (p=buf; --n>=0; ) putc( *p++, fout); } 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;}#ifndef vax11c/* * 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() {}#endif/* 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;}/* * substr(string, token) searches for token in string s * returns pointer to token within string if found, NULL otherwise */char *substr(s, t)register char *s,*t;{ register char *ss,*tt; /* search for first char of token */ for (ss=s; *s; s++) if (*s == *t) /* compare token with substring */ for (ss=s,tt=t; ;) { if (*tt == 0) return s; if (*ss++ != *tt++) break; } return NULL;}/* * Log an error *//*VARARGS1*/zperr(s,p,u)char *s, *p, *u;{ if (Verbose <= 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -