📄 rz.c
字号:
} vfile("Crash recovery at %ld", rxbytes); return 0; } else if ((zmanag==ZMNEW) || ((zmanag==ZMNEWL) && Bytesleft <= f.st_size) ) { if ((f.st_mtime+1) >= Modtime) goto skipfile; goto doopen; } switch (zmanag & ZMMASK) { case ZMCLOB: case ZMAPND: goto doopen; default: goto skipfile; } } else if (zmanag & ZMSKNOLOC) {skipfile: vfile("Skipping %s", name); return ZSKIP; }doopen: openit(name, openmode);#ifdef MD if ( !fout) if (make_dirs(name)) openit(name, openmode);#endif if ( !fout) return ZFERR; return 0;}openit(name, openmode)char *name, *openmode;{ fout = fopen(name, openmode);}#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 */ 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(2); /* 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;}/* * 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;}/* * If called as [-][dir/../]vrzCOMMAND set Verbose to 1 * 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[0]=='r' && s[1]=='z') Batch = TRUE; if (s[0]=='r' && s[1]=='c') Crcflg = TRUE; if (s[0]=='r' && s[1]=='b') Batch = Nozmodem = TRUE;}/* * Totalitarian Communist pathname processing */checkpath(name)char *name;{ if (Restricted) { if (fopen(name, "r") != NULL) { canit(); fprintf(stderr, "\r\nrz: %s exists\n", name); bibi(-1); } /* restrict pathnames to current tree or uucppublic */ if ( substr(name, "../") || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) { canit(); fprintf(stderr,"\r\nrz:\tSecurity Violation\r\n"); bibi(-1); } }}/* * Ack a ZFIN packet, let byegones be byegones */voidackbibi(){ register n; vfile("ackbibi:"); Readnum = 1; stohdr(0L); for (n=3; --n>=0; ) { purgeline(); zshhdr(4,ZFIN, Txhdr); switch (readline(100)) { case 'O': readline(1); /* Discard 2nd 'O' */ vfile("ackbibi complete"); return; case RCDO: return; case TIMEOUT: default: break; } }}/* * 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 */tryz(){ register c, n; register cmdzack1flg; if (Nozmodem) /* Check for "rb" program name */ return 0; for (n=15; --n>=0; ) { /* Set buffer length (0) and capability flags */#ifdef SEGMENTS stohdr(SEGMENTS*1024L);#else stohdr(0L);#endif#ifdef CANBREAK Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;#else Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;#endif if (Zctlesc) Txhdr[ZF0] |= TESCCTL; Txhdr[ZF0] |= CANRLE; Txhdr[ZF1] = CANVHDR; /* tryzhdrtype may == ZRINIT */ zshhdr(4,tryzhdrtype, Txhdr); if (tryzhdrtype == ZSKIP) /* Don't skip too far */ tryzhdrtype = ZRINIT; /* CAF 8-21-87 */again: switch (zgethdr(Rxhdr)) { case ZRQINIT: if (Rxhdr[ZF3] & 0x80) Usevhdrs = 1; /* we can var header */ continue; case ZEOF: continue; case TIMEOUT: continue; case ZFILE: zconv = Rxhdr[ZF0]; zmanag = Rxhdr[ZF1]; ztrans = Rxhdr[ZF2]; if (Rxhdr[ZF3] & ZCANVHDR) Usevhdrs = TRUE; tryzhdrtype = ZRINIT; c = zrdata(secbuf, 1024); if (c == GOTCRCW) return ZFILE; zshhdr(4,ZNAK, Txhdr); goto again; case ZSINIT: Zctlesc = TESCCTL & Rxhdr[ZF0]; if (zrdata(Attn, ZATTNLEN) == GOTCRCW) { stohdr(1L); zshhdr(4,ZACK, Txhdr); goto again; } zshhdr(4,ZNAK, Txhdr); goto again; case ZFREECNT: stohdr(getfree()); zshhdr(4,ZACK, Txhdr); goto again; case ZCOMMAND: cmdzack1flg = Rxhdr[ZF0]; if (zrdata(secbuf, 1024) == GOTCRCW) { if (cmdzack1flg & ZCACK1) stohdr(0L); else stohdr((long)sys2(secbuf)); purgeline(); /* dump impatient questions */ do { zshhdr(4,ZCOMPL, Txhdr); } while (++errors<20 && zgethdr(Rxhdr) != ZFIN); ackbibi(); if (cmdzack1flg & ZCACK1) exec2(secbuf); return ZCOMPL; } zshhdr(4,ZNAK, Txhdr); goto again; case ZCOMPL: goto again; default: continue; case ZFIN: ackbibi(); return ZCOMPL; case ZCAN: return ERROR; } } return 0;}/* * Receive 1 or more files with ZMODEM protocol */rzfiles(){ register c; for (;;) { switch (c = rzfile()) { case ZEOF: case ZSKIP: switch (tryz()) { case ZCOMPL: return OK; default: return ERROR; case ZFILE: break; } continue; default: return c; case ERROR: return ERROR; } }}/* * Receive a file with ZMODEM protocol * Assumes file name frame is in secbuf */rzfile(){ register c, n; Eofseen=FALSE; n = 20; rxbytes = 0l; if (c = procheader(secbuf)) { return (tryzhdrtype = c); } for (;;) {#ifdef SEGMENTS chinseg = 0;#endif stohdr(rxbytes); zshhdr(4,ZRPOS, Txhdr);nxthdr: switch (c = zgethdr(Rxhdr)) { default: vfile("rzfile: Wrong header %d", c); if ( --n < 0) { sprintf(endmsg, "rzfile: Wrong header %d", c); return ERROR; } continue; case ZCAN: sprintf(endmsg, "Sender CANcelled"); return ERROR; case ZNAK:#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif if ( --n < 0) { sprintf(endmsg, "rzfile: got ZNAK", c); return ERROR; } continue; case TIMEOUT:#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif if ( --n < 0) { sprintf(endmsg, "rzfile: TIMEOUT", c); return ERROR; } continue; case ZFILE: zrdata(secbuf, 1024); continue; case ZEOF:#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif if (rclhdr(Rxhdr) != rxbytes) { /* * 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()) { tryzhdrtype = ZFERR; vfile("rzfile: closeit returned <> 0"); sprintf(endmsg,"Error closing file"); 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) { sprintf(endmsg, "Persistent CRC or other ERROR"); return ERROR; } zmputs(Attn); continue; case ZSKIP:#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif Modtime = 1; closeit(); sprintf(endmsg, "Sender SKIPPED file"); return c; case ZDATA: if (rclhdr(Rxhdr) != rxbytes) { if ( --n < 0) { sprintf(endmsg,"Data has bad addr"); return ERROR; }#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif zmputs(Attn); continue; }moredata: if (Verbose>1) fprintf(stderr, "\r%7ld ZMODEM%s ", rxbytes, Crc32r?" CRC-32":"");#ifdef SEGMENTS if (chinseg >= (1024 * SEGMENTS)) { putsec(secbuf, chinseg); chinseg = 0; } switch (c = zrdata(secbuf+chinseg, 1024))#else switch (c = zrdata(secbuf, 1024))#endif { case ZCAN:#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif sprintf(endmsg, "Sender CANcelled"); return ERROR; case ERROR: /* CRC error */#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif if ( --n < 0) { sprintf(endmsg, "Persistent CRC or other ERROR"); return ERROR; } zmputs(Attn); continue; case TIMEOUT:#ifdef SEGMENTS putsec(secbuf, chinseg); chinseg = 0;#endif if ( --n < 0) { sprintf(endmsg, "TIMEOUT"); return ERROR; } continue; case GOTCRCW: n = 20;#ifdef SEGMENTS chinseg += Rxcount; putsec(secbuf, chinseg); chinseg = 0;#else putsec(secbuf, Rxcount);#endif rxbytes += Rxcount; stohdr(rxbytes); sendline(XON); zshhdr(4,ZACK, Txhdr); goto nxthdr; case GOTCRCQ: n = 20;#ifdef SEGMENTS chinseg += Rxcount;#else putsec(secbuf, Rxcount);#endif rxbytes += Rxcount; stohdr(rxbytes); zshhdr(4,ZACK, Txhdr); goto moredata; case GOTCRCG: n = 20;#ifdef SEGMENTS chinseg += Rxcount;#else putsec(secbuf, Rxcount);#endif rxbytes += Rxcount; goto moredata; case GOTCRCE: n = 20;#ifdef SEGMENTS chinseg += Rxcount;#else putsec(secbuf, Rxcount);#endif rxbytes += Rxcount; goto nxthdr; } } }}/* * Close the receive dataset, return OK or ERROR */closeit(){ time_t time(); if (fclose(fout)==ERROR) { fprintf(stderr, "file close ERROR\n"); return ERROR; } if (Modtime) { timep[0] = time(NULL); timep[1] = Modtime; utime(Pathname, timep); } if (#ifdef POSIX S_ISREG(Filemode)#else (Filemode&S_IFMT) == S_IFREG#endif ) chmod(Pathname, (unsigned short)(07777 & Filemode)); return OK;}/* * Strip leading ! if present, do shell escape. */sys2(s)register char *s;{ if (*s == '!') ++s; return system(s);}/* * Strip leading ! if present, do exec. */exec2(s)register char *s;{ if (*s == '!') ++s; mode(0); execl("/bin/sh", "sh", "-c", s);}/* End of rz.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -