📄 server.c
字号:
mode &= ~04000; gid = -1; if (gr == NULL || strcmp(group, gr->gr_name) != 0) { if ((*group == ':' && (getgrgid(gid = atoi(group + 1)) == NULL)) || ((gr = getgrnam(group)) == NULL)) { if (mode & 02000) { note("%s:%s: unknown group", host, group); mode &= ~02000; } } else gid = gr->gr_gid; } else gid = gr->gr_gid; if (userid && gid >= 0) { if (gr) for (i = 0; gr->gr_mem[i] != NULL; i++) if (!(strcmp(user, gr->gr_mem[i]))) goto ok; mode &= ~02000; gid = -1; }ok: if (fd != -1 && fchown(fd, uid, gid) < 0 || chown(file, uid, gid) < 0) note("%s: %s chown: %s", host, file, strerror(errno)); else if (mode & 07000 && (fd != -1 && fchmod(fd, mode) < 0 || chmod(file, mode) < 0)) note("%s: %s chmod: %s", host, file, strerror(errno)); return(0);}/* * Check for files on the machine being updated that are not on the master * machine and remove them. */static voidrmchk(opts) int opts;{ register char *cp, *s; struct stat stb; if (debug) printf("rmchk()\n"); /* * Tell the remote to clean the files from the last directory sent. */ (void) sprintf(buf, "C%o\n", opts & VERIFY); if (debug) printf("buf = %s", buf); (void) write(rem, buf, strlen(buf)); if (response() < 0) return; for (;;) { cp = s = buf; do { if (read(rem, cp, 1) != 1) lostconn(0); } while (*cp++ != '\n' && cp < &buf[BUFSIZ]); switch (*s++) { case 'Q': /* Query if file should be removed */ /* * Return the following codes to remove query. * N\n -- file exists - DON'T remove. * Y\n -- file doesn't exist - REMOVE. */ *--cp = '\0'; (void) sprintf(tp, "/%s", s); if (debug) printf("check %s\n", target); if (except(target)) (void) write(rem, "N\n", 2); else if (lstat(target, &stb) < 0) (void) write(rem, "Y\n", 2); else (void) write(rem, "N\n", 2); break; case '\0': *--cp = '\0'; if (*s != '\0') log(lfp, "%s\n", s); break; case 'E': *tp = '\0'; ack(); return; case '\1': case '\2': nerrs++; if (*s != '\n') { if (!iamremote) { fflush(stdout); (void) write(2, s, cp - s); } if (lfp != NULL) (void) fwrite(s, 1, cp - s, lfp); } if (buf[0] == '\2') lostconn(0); break; default: error("rmchk: unexpected response '%s'\n", buf); err(); } }}/* * Check the current directory (initialized by the 'T' command to server()) * for extraneous files and remove them. */static voidclean(cp) register char *cp;{ DIR *d; register struct direct *dp; struct stat stb; char *otp; int len, opts; opts = 0; while (*cp >= '0' && *cp <= '7') opts = (opts << 3) | (*cp++ - '0'); if (*cp != '\0') { error("clean: options not delimited\n"); return; } if ((d = opendir(target)) == NULL) { error("%s:%s: %s\n", host, target, strerror(errno)); return; } ack(); otp = tp; len = tp - target; while (dp = readdir(d)) { if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; if (len + 1 + strlen(dp->d_name) >= BUFSIZ - 1) { error("%s:%s/%s: Name too long\n", host, target, dp->d_name); continue; } tp = otp; *tp++ = '/'; cp = dp->d_name;; while (*tp++ = *cp++) ; tp--; if (lstat(target, &stb) < 0) { error("%s:%s: %s\n", host, target, strerror(errno)); continue; } (void) sprintf(buf, "Q%s\n", dp->d_name); (void) write(rem, buf, strlen(buf)); cp = buf; do { if (read(rem, cp, 1) != 1) cleanup(0); } while (*cp++ != '\n' && cp < &buf[BUFSIZ]); *--cp = '\0'; cp = buf; if (*cp != 'Y') continue; if (opts & VERIFY) { cp = buf; *cp++ = '\0'; (void) sprintf(cp, "need to remove: %s\n", target); (void) write(rem, buf, strlen(cp) + 1); } else removeit(&stb); } closedir(d); (void) write(rem, "E\n", 2); (void) response(); tp = otp; *tp = '\0';}/* * Remove a file or directory (recursively) and send back an acknowledge * or an error message. */static voidremoveit(stp) struct stat *stp;{ DIR *d; struct direct *dp; register char *cp; struct stat stb; char *otp; int len; switch (stp->st_mode & S_IFMT) { case S_IFREG: case S_IFLNK: if (unlink(target) < 0) goto bad; goto removed; case S_IFDIR: break; default: error("%s:%s: not a plain file\n", host, target); return; } if ((d = opendir(target)) == NULL) goto bad; otp = tp; len = tp - target; while (dp = readdir(d)) { if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; if (len + 1 + strlen(dp->d_name) >= BUFSIZ - 1) { error("%s:%s/%s: Name too long\n", host, target, dp->d_name); continue; } tp = otp; *tp++ = '/'; cp = dp->d_name;; while (*tp++ = *cp++) ; tp--; if (lstat(target, &stb) < 0) { error("%s:%s: %s\n", host, target, strerror(errno)); continue; } removeit(&stb); } closedir(d); tp = otp; *tp = '\0'; if (rmdir(target) < 0) {bad: error("%s:%s: %s\n", host, target, strerror(errno)); return; }removed: cp = buf; *cp++ = '\0'; (void) sprintf(cp, "removed %s\n", target); (void) write(rem, buf, strlen(cp) + 1);}/* * Execute a shell command to handle special cases. */static voiddospecial(cmd) char *cmd;{ int fd[2], status, pid, i; register char *cp, *s; char sbuf[BUFSIZ]; extern int userid, groupid; if (pipe(fd) < 0) { error("%s\n", strerror(errno)); return; } if ((pid = fork()) == 0) { /* * Return everything the shell commands print. */ (void) close(0); (void) close(1); (void) close(2); (void) open(_PATH_DEVNULL, O_RDONLY); (void) dup(fd[1]); (void) dup(fd[1]); (void) close(fd[0]); (void) close(fd[1]); setgid(groupid); setuid(userid); execl(_PATH_BSHELL, "sh", "-c", cmd, 0); _exit(127); } (void) close(fd[1]); s = sbuf; *s++ = '\0'; while ((i = read(fd[0], buf, sizeof(buf))) > 0) { cp = buf; do { *s++ = *cp++; if (cp[-1] != '\n') { if (s < &sbuf[sizeof(sbuf)-1]) continue; *s++ = '\n'; } /* * Throw away blank lines. */ if (s == &sbuf[2]) { s--; continue; } (void) write(rem, sbuf, s - sbuf); s = &sbuf[1]; } while (--i); } if (s > &sbuf[1]) { *s++ = '\n'; (void) write(rem, sbuf, s - sbuf); } while ((i = wait(&status)) != pid && i != -1) ; if (i == -1) status = -1; (void) close(fd[0]); if (status) error("shell returned %d\n", status); else ack();}#if __STDC__#include <stdarg.h>#else#include <varargs.h>#endifvoid#if __STDC__log(FILE *fp, const char *fmt, ...)#elselog(fp, fmt, va_alist) FILE *fp; char *fmt; va_dcl#endif{ va_list ap;#if __STDC__ va_start(ap, fmt);#else va_start(ap);#endif /* Print changes locally if not quiet mode */ if (!qflag) (void)vprintf(fmt, ap); /* Save changes (for mailing) if really updating files */ if (!(options & VERIFY) && fp != NULL) (void)vfprintf(fp, fmt, ap); va_end(ap);}void#if __STDC__error(const char *fmt, ...)#elseerror(fmt, va_alist) char *fmt; va_dcl#endif{ static FILE *fp; va_list ap;#if __STDC__ va_start(ap, fmt);#else va_start(ap);#endif ++nerrs; if (!fp && !(fp = fdopen(rem, "w"))) return; if (iamremote) { (void)fprintf(fp, "%crdist: ", 0x01); (void)vfprintf(fp, fmt, ap); fflush(fp); } else { fflush(stdout); (void)fprintf(stderr, "rdist: "); (void)vfprintf(stderr, fmt, ap); fflush(stderr); } if (lfp != NULL) { (void)fprintf(lfp, "rdist: "); (void)vfprintf(lfp, fmt, ap); fflush(lfp); } va_end(ap);}void#if __STDC__fatal(const char *fmt, ...)#elsefatal(fmt, va_alist) char *fmt; va_dcl#endif{ static FILE *fp; va_list ap;#if __STDC__ va_start(ap, fmt);#else va_start(ap);#endif ++nerrs; if (!fp && !(fp = fdopen(rem, "w"))) return; if (iamremote) { (void)fprintf(fp, "%crdist: ", 0x02); (void)vfprintf(fp, fmt, ap); fflush(fp); } else { fflush(stdout); (void)fprintf(stderr, "rdist: "); (void)vfprintf(stderr, fmt, ap); fflush(stderr); } if (lfp != NULL) { (void)fprintf(lfp, "rdist: "); (void)vfprintf(lfp, fmt, ap); fflush(lfp); } cleanup(0);}static intresponse(){ char *cp, *s; char resp[BUFSIZ]; if (debug) printf("response()\n"); cp = s = resp; do { if (read(rem, cp, 1) != 1) lostconn(0); } while (*cp++ != '\n' && cp < &resp[BUFSIZ]); switch (*s++) { case '\0': *--cp = '\0'; if (*s != '\0') { log(lfp, "%s\n", s); return(1); } return(0); case '\3': *--cp = '\0'; log(lfp, "Note: %s\n",s); return(response()); default: s--; /* fall into... */ case '\1': case '\2': nerrs++; if (*s != '\n') { if (!iamremote) { fflush(stdout); (void) write(2, s, cp - s); } if (lfp != NULL) (void) fwrite(s, 1, cp - s, lfp); } if (resp[0] == '\2') lostconn(0); return(-1); }}/* * Remove temporary files and do any cleanup operations before exiting. */voidcleanup(signo) int signo;{ (void) unlink(tempfile); exit(1);}static void#if __STDC__note(const char *fmt, ...)#elsenote(fmt, va_alist) char *fmt; va_dcl#endif{ static char buf[BUFSIZ]; va_list ap;#if __STDC__ va_start(ap, fmt);#else va_start(ap);#endif (void)vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); comment(buf);}static voidcomment(s) char *s;{ char c; c = '\3'; write(rem, &c, 1); write(rem, s, strlen(s)); c = '\n'; write(rem, &c, 1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -