📄 rcp.c
字号:
char buf[BUFSIZ]; for (x = 0; x < argc; x++) { name = argv[x]; if ((f = open(name, 0)) < 0) { error("rcp: %s: %s\n", name, strerror(errno)); continue; } if (fstat(f, &stb) < 0) goto notreg; switch (stb.st_mode&S_IFMT) { case S_IFREG: break; case S_IFDIR: if (iamrecursive) { (void) close(f); rsource(name, &stb); continue; } /* fall into ... */ default:notreg: (void) close(f); error("rcp: %s: not a plain file\n", name); continue; } last = strrchr(name, '/'); if (last == 0) last = name; else last++; if (pflag) { /* * Make it compatible with possible future * versions expecting microseconds. */ (void) sprintf(buf, "T%ld 0 %ld 0\n", stb.st_mtime, stb.st_atime); (void) write(rem, buf, strlen(buf)); if (response() < 0) { (void) close(f); continue; } } (void) sprintf(buf, "C%04o %ld %s\n", stb.st_mode&07777, stb.st_size, last); (void) write(rem, buf, strlen(buf)); if (response() < 0) { (void) close(f); continue; } if ((bp = allocbuf(&buffer, f, BUFSIZ)) == 0) { (void) close(f); continue; } sizerr = 0; for (i = 0; i < stb.st_size; i += bp->cnt) { amt = bp->cnt; if (i + amt > stb.st_size) amt = stb.st_size - i; if (sizerr == 0 && read(f, bp->buf, amt) != amt) sizerr = 1; (void) write(rem, bp->buf, amt); } (void) close(f); if (sizerr == 0) ga(); else error("rcp: %s: file changed size\n", name); (void) response(); }}voidrsource(name, statp) char *name; struct stat *statp;{ DIR *d = opendir(name); char *last; struct dirent *dp; char buf[BUFSIZ]; char *bufv[1]; if (d == 0) { error("rcp: %s: %s\n", name, strerror(errno)); return; } last = strrchr(name, '/'); if (last == 0) last = name; else last++; if (pflag) { (void) sprintf(buf, "T%ld 0 %ld 0\n", statp->st_mtime, statp->st_atime); (void) write(rem, buf, strlen(buf)); if (response() < 0) { closedir(d); return; } } (void) sprintf(buf, "D%04o %d %s\n", statp->st_mode&07777, 0, last); (void) write(rem, buf, strlen(buf)); if (response() < 0) { closedir(d); return; } while (dp = readdir(d)) { if (dp->d_ino == 0) continue; if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; if (strlen(name) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) { error("%s/%s: Name too long.\n", name, dp->d_name); continue; } (void) sprintf(buf, "%s/%s", name, dp->d_name); bufv[0] = buf; source(1, bufv); } closedir(d); (void) write(rem, "E\n", 2); (void) response();}intresponse(){ char resp, c, rbuf[BUFSIZ], *cp = rbuf; if (read(rem, &resp, 1) != 1) lostconn(0); switch (resp) { case 0: /* ok */ return (0); default: *cp++ = resp; /* fall into... */ case 1: /* error, followed by err msg */ case 2: /* fatal error, "" */ do { if (read(rem, &c, 1) != 1) lostconn(0); *cp++ = c; } while (cp < &rbuf[BUFSIZ] && c != '\n'); if (iamremote == 0) (void) write(2, rbuf, cp - rbuf); errs++; if (resp == 1) return (-1); exit(1); } /*NOTREACHED*/}voidlostconn(sig)int sig;{ if (iamremote == 0) fprintf(stderr, "rcp: lost connection\n"); exit(1);}voidsink(argc, argv) int argc; char **argv;{ off_t i, j, size; char *targ, *whopp, *cp; int of, mode, wrerr, exists, first, count, amt; struct buffer *bp; static struct buffer buffer; struct stat stb; int targisdir = 0; int mask = umask(0); char *myargv[1]; char cmdbuf[BUFSIZ], nambuf[BUFSIZ]; int setimes = 0; struct utimbuf utimbuf;#define atime utimbuf.actime#define mtime utimbuf.modtime time_t dummy;#define SCREWUP(str) { whopp = str; goto screwup; }#ifdef NOT_DEF seteuid(pwd->pw_uid);#endif if (!pflag) (void) umask(mask); if (argc != 1) { error("rcp: ambiguous target\n"); exit(1); } targ = *argv; if (targetshouldbedirectory) verifydir(targ); ga(); if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR) targisdir = 1; for (first = 1; ; first = 0) { cp = cmdbuf; if (read(rem, cp, 1) <= 0) return; if (*cp++ == '\n') SCREWUP("unexpected '\\n'"); do { if (read(rem, cp, 1) != 1) SCREWUP("lost connection"); } while (*cp++ != '\n'); *cp = 0; if (cmdbuf[0] == '\01' || cmdbuf[0] == '\02') { if (iamremote == 0) (void) write(2, cmdbuf+1, strlen(cmdbuf+1)); if (cmdbuf[0] == '\02') exit(1); errs++; continue; } *--cp = 0; cp = cmdbuf; if (*cp == 'E') { ga(); return; }#define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0'); if (*cp == 'T') { setimes++; cp++; getnum(mtime); if (*cp++ != ' ') SCREWUP("mtime.sec not delimited"); getnum(dummy); if (*cp++ != ' ') SCREWUP("mtime.usec not delimited"); getnum(atime); if (*cp++ != ' ') SCREWUP("atime.sec not delimited"); getnum(dummy); if (*cp++ != '\0') SCREWUP("atime.usec not delimited"); ga(); continue; } if (*cp != 'C' && *cp != 'D') { /* * Check for the case "rcp remote:foo\* local:bar". * In this case, the line "No match." can be returned * by the shell before the rcp command on the remote is * executed so the ^Aerror_message convention isn't * followed. */ if (first) { error("%s\n", cp); exit(1); } SCREWUP("expected control record"); } cp++; mode = 0; for (; cp < cmdbuf+5; cp++) { if (*cp < '0' || *cp > '7') SCREWUP("bad mode"); mode = (mode << 3) | (*cp - '0'); } if (*cp++ != ' ') SCREWUP("mode not delimited"); size = 0; while (isdigit(*cp)) size = size * 10 + (*cp++ - '0'); if (*cp++ != ' ') SCREWUP("size not delimited"); if (targisdir) (void) sprintf(nambuf, "%s%s%s", targ, *targ ? "/" : "", cp); else (void) strcpy(nambuf, targ); exists = stat(nambuf, &stb) == 0; if (cmdbuf[0] == 'D') { if (exists) { if ((stb.st_mode&S_IFMT) != S_IFDIR) { errno = ENOTDIR; goto bad; } if (pflag) (void) chmod(nambuf, mode); } else if (mkdir(nambuf, mode) < 0) goto bad; myargv[0] = nambuf; sink(1, myargv); if (setimes) { setimes = 0; if (utime(nambuf, &utimbuf) < 0) error("rcp: can't set times on %s: %s\n", nambuf, strerror(errno)); } continue; } if ((of = creat(nambuf, mode)) < 0) { bad: error("rcp: %s: %s\n", nambuf, strerror(errno)); continue; } if (exists && pflag) (void) chmod(nambuf, mode); ga(); if ((bp = allocbuf(&buffer, of, BUFSIZ)) == 0) { (void) close(of); continue; } cp = bp->buf; count = 0; wrerr = 0; for (i = 0; i < size; i += BUFSIZ) { amt = BUFSIZ; if (i + amt > size) amt = size - i; count += amt; do { j = read(rem, cp, amt); if (j <= 0) exit(1); amt -= j; cp += j; } while (amt > 0); if (count == bp->cnt) { if (wrerr == 0 && write(of, bp->buf, count) != count) wrerr++; count = 0; cp = bp->buf; } } if (count != 0 && wrerr == 0 && write(of, bp->buf, count) != count) wrerr++; (void) close(of); (void) response(); if (setimes) { setimes = 0; if (utime(nambuf, &utimbuf) < 0) error("rcp: can't set times on %s: %s\n", nambuf, strerror(errno)); } if (wrerr) error("rcp: %s: %s\n", nambuf, strerror(errno)); else ga(); }screwup: error("rcp: protocol screwup: %s\n", whopp); exit(1);}struct buffer *allocbuf(bp, fd, blksize) struct buffer *bp; int fd, blksize;{ struct stat stb; int size; if (fstat(fd, &stb) < 0) { error("rcp: fstat: %s\n", strerror(errno)); return ((struct buffer *)0); } size= 0;#if NOT_DEF size = roundup(stb.st_blksize, blksize);#endif if (size == 0) size = blksize; if (bp->cnt < size) { if (bp->buf != 0) free(bp->buf); bp->buf = (char *)malloc((unsigned) size); if (bp->buf == 0) { error("rcp: malloc: out of memory\n"); return ((struct buffer *)0); } } bp->cnt = size; return (bp);}/*VARARGS1*/#if __STDC__voiderror (char *fmt, ...)#elseerror(fmt)char *fmt;#endif{ char buf[BUFSIZ], *cp = buf; va_list ap; va_start(ap, fmt); errs++; *cp++ = 1; (void) vsprintf(cp, fmt, ap); va_end(ap); (void) write(rem, buf, strlen(buf)); if (iamremote == 0) (void) write(2, buf+1, strlen(buf+1));}voidusage(){ fprintf(stderr, "Usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn d2\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -