From 3024eb6fe4c672bc135bbbcab2ff37b956ff6571 Mon Sep 17 00:00:00 2001 From: Ralph Campbell Date: Tue, 11 Oct 1983 00:17:36 -0800 Subject: [PATCH] stable version that works. SCCS-vsn: usr.bin/rdist/defs.h 4.3 SCCS-vsn: usr.bin/rdist/Makefile 4.3 SCCS-vsn: usr.bin/rdist/docmd.c 4.3 SCCS-vsn: usr.bin/rdist/expand.c 4.3 SCCS-vsn: usr.bin/rdist/gram.y 4.3 SCCS-vsn: usr.bin/rdist/main.c 4.3 SCCS-vsn: usr.bin/rdist/server.c 4.3 SCCS-vsn: usr.bin/rdist/lookup.c 4.3 --- usr/src/usr.bin/rdist/Makefile | 2 +- usr/src/usr.bin/rdist/defs.h | 20 ++- usr/src/usr.bin/rdist/docmd.c | 60 ++++--- usr/src/usr.bin/rdist/expand.c | 90 ++++++---- usr/src/usr.bin/rdist/gram.y | 59 ++++--- usr/src/usr.bin/rdist/lookup.c | 18 +- usr/src/usr.bin/rdist/main.c | 4 +- usr/src/usr.bin/rdist/server.c | 314 +++++++++++++++++++-------------- 8 files changed, 327 insertions(+), 240 deletions(-) diff --git a/usr/src/usr.bin/rdist/Makefile b/usr/src/usr.bin/rdist/Makefile index b90520133a..4b3b522d9f 100644 --- a/usr/src/usr.bin/rdist/Makefile +++ b/usr/src/usr.bin/rdist/Makefile @@ -1,4 +1,4 @@ -# Makefile 4.1 83/09/07 +# Makefile 4.3 83/10/10 DESTDIR= SRCS = docmd.c expand.c gram.y lookup.c main.c server.c diff --git a/usr/src/usr.bin/rdist/defs.h b/usr/src/usr.bin/rdist/defs.h index 342835ca78..d2f5181176 100644 --- a/usr/src/usr.bin/rdist/defs.h +++ b/usr/src/usr.bin/rdist/defs.h @@ -1,4 +1,4 @@ -/* defs.h 4.2 83/09/27 */ +/* defs.h 4.3 83/10/10 */ #include #include @@ -12,7 +12,7 @@ #include #include -#define MAILCMD "/usr/lib/sendmail -i -t" +#define MAILCMD "/usr/lib/sendmail -oi -t" /* defines for yacc */ #define EQUAL 1 @@ -22,10 +22,9 @@ #define DCOLON 5 #define NAME 6 #define INSTALL 7 -#define VERIFY 8 -#define NOTIFY 9 -#define EXCEPT 10 - +#define NOTIFY 8 +#define EXCEPT 9 +#define OPTION 10 #define VAR 11 /* lexical definitions */ @@ -39,11 +38,17 @@ #define GAVSIZ NCARGS / 6 #define NSTAMPS 15 + /* option flags */ +#define VERIFY 1 +#define WHOLE 2 +#define YOUNGER 4 +#define STRIP 8 #define ALLOC(x) (struct x *) malloc(sizeof(struct x)) struct block { - int b_type; + short b_type; + short b_options; char *b_name; struct block *b_next; struct block *b_args; @@ -71,5 +76,6 @@ extern char *sys_errlist[]; struct block *lookup(); struct block *makeblock(); struct block *expand(); +char *malloc(); char *rindex(); char *index(); diff --git a/usr/src/usr.bin/rdist/docmd.c b/usr/src/usr.bin/rdist/docmd.c index d4c0615f88..a10ea3ca3c 100644 --- a/usr/src/usr.bin/rdist/docmd.c +++ b/usr/src/usr.bin/rdist/docmd.c @@ -1,5 +1,5 @@ #ifndef lint -static char *sccsid = "@(#)docmd.c 4.2 (Berkeley) 83/09/27"; +static char *sccsid = "@(#)docmd.c 4.3 (Berkeley) 83/10/10"; #endif #include "defs.h" @@ -13,7 +13,7 @@ dohcmds(files, hosts, cmds) struct block *files, *hosts, *cmds; { register struct block *h, *f, *c; - register char *cp, **cpp; + register char **cpp; int n, ddir; if (debug) @@ -53,10 +53,7 @@ dohcmds(files, hosts, cmds) n = 0; for (c = cmds; c != NULL; c = c->b_next) if (c->b_type == INSTALL) { - install(f->b_name, c->b_name, ddir, 0); - n++; - } else if (c->b_type == VERIFY) { - install(f->b_name, c->b_name, ddir, 1); + install(f->b_name, c->b_name, ddir, c->b_options); n++; } if (n == 0) @@ -112,23 +109,25 @@ makeconn(rhost) return(1); } -extern char target[], *tp; - /* * Update the file(s) if they are different. * destdir = 1 if destination should be a directory * (i.e., more than one source is being copied to the same destination). */ -install(src, dest, destdir, verify) +install(src, dest, destdir, options) char *src, *dest; - int destdir, verify; + int destdir, options; { + register char *cp; + if (exclude(src)) return; - if (nflag) { - printf("%s %s %s\n", verify ? "verify" : "install", src, dest); - return; + if (nflag || debug) { + printf("%s%s %s %s\n", options & VERIFY ? "verify" : "install", + options & WHOLE ? " -w" : "", src, dest); + if (nflag) + return; } /* * Pass the destination file/directory name to remote. @@ -137,8 +136,10 @@ install(src, dest, destdir, verify) if (debug) printf("buf = %s", buf); (void) write(rem, buf, strlen(buf)); - tp = NULL; - sendf(src, verify); + + if (!destdir && (options & WHOLE)) + options |= STRIP; + sendf(src, NULL, options); } struct tstamp { @@ -148,6 +149,8 @@ struct tstamp { int nstamps; +extern char target[], *tp; + /* * Process commands for comparing files to time stamp files. */ @@ -159,7 +162,6 @@ dofcmds(files, stamps, cmds) register char **cpp; struct stat stb; extern char *tmpinc; - int n; if (debug) printf("dofcmds()\n"); @@ -204,11 +206,11 @@ dofcmds(files, stamps, cmds) cmptime(b->b_name); } if (!nflag && !vflag) - for (t = ts; t < &ts[n]; t++) + for (t = ts; t < &ts[nstamps]; t++) if (t->tfp != NULL) (void) fclose(t->tfp); *tmpinc = 'A'; - while (n--) { + while (nstamps--) { for (b = cmds; b != NULL; b = b->b_next) if (b->b_type == NOTIFY) notify(tmpfile, NULL, b->b_args); @@ -308,8 +310,8 @@ rcmptime(st) /* * Notify the list of people the changes that were made. */ -notify(file, host, to) - char *file, *host; +notify(file, rhost, to) + char *file, *rhost; register struct block *to; { register int fd, len; @@ -320,8 +322,8 @@ notify(file, host, to) return; if (!qflag) { printf("notify "); - if (host) - printf("@%s ", host); + if (rhost) + printf("@%s ", rhost); prnames(to); } if (nflag) @@ -344,22 +346,26 @@ notify(file, host, to) * Create a pipe to mailling program. */ pf = popen(MAILCMD, "w"); - if (pf == NULL) - fatal("notify: \"%s\" failed\n", MAILCMD); + if (pf == NULL) { + error("notify: \"%s\" failed\n", MAILCMD); + (void) close(fd); + return; + } /* * Output the proper header information. */ fprintf(pf, "From: rdist (Remote distribution program)\n"); fprintf(pf, "To:"); while (to != NULL) { - if (!any('@', to->b_name)) - fprintf(pf, " %s@%s", to->b_name, host); + if (!any('@', to->b_name) && host != NULL) + fprintf(pf, " %s@%s", to->b_name, rhost); else fprintf(pf, " %s", to->b_name); to = to->b_next; } putc('\n', pf); - fprintf(pf, "Subject: files updated by rdist\n"); + fprintf(pf, "Subject: files updated by rdist from %s to %s\n", + host, rhost); putc('\n', pf); while ((len = read(fd, buf, BUFSIZ)) > 0) diff --git a/usr/src/usr.bin/rdist/expand.c b/usr/src/usr.bin/rdist/expand.c index a5e42a3c66..62e4044386 100644 --- a/usr/src/usr.bin/rdist/expand.c +++ b/usr/src/usr.bin/rdist/expand.c @@ -1,5 +1,5 @@ #ifndef lint -static char *sccsid = "@(#)expand.c 4.2 (Berkeley) 83/09/27"; +static char *sccsid = "@(#)expand.c 4.3 (Berkeley) 83/10/10"; #endif #include "defs.h" @@ -17,6 +17,7 @@ char *entp; char **sortbase; char *index(); +struct block *copy(); /* * Take a list of names and expand any macros, etc. @@ -27,17 +28,22 @@ expand(list, noshexp) int noshexp; { register struct block *prev, *bp, *tp; - register char *cp, *s; + register char *cp; register int n; - char *var, *tail; + char *tail; int c; char pathbuf[BUFSIZ]; char *argvbuf[GAVSIZ]; + if (debug) { + printf("expand(%x, %d)\nlist = ", list, noshexp); + prnames(list); + } + for (prev = NULL, bp = list; bp != NULL; prev = bp, bp = bp->b_next) { again: cp = index(bp->b_name, '$'); - if (cp == NULL || cp != bp->b_name && cp[-1] == '\\') + if (cp == NULL) continue; *cp++ = '\0'; if (*cp == '\0') @@ -55,24 +61,26 @@ expand(list, noshexp) *tail = '\0'; } tp = lookup(cp, NULL, 0); + if (c != '\0') + *tail = c; if ((tp = tp->b_args) != NULL) { - struct block *first = tp; - + struct block *first = bp; + + for (bp = prev; tp != NULL; tp = tp->b_next) { + if (bp == NULL) + list = bp = copy(tp, first->b_name, tail); + else { + bp->b_next = copy(tp, first->b_name, tail); + bp = bp->b_next; + } + } + bp->b_next = first->b_next; + free(first->b_name); + free(first); if (prev == NULL) - list = tp; + bp = list; else - prev->b_next = tp; - if (c) - *tail = c; - makestr(tp, bp->b_name, tail); - while (tp->b_next != NULL) { - tp = tp->b_next; - makestr(tp, bp->b_name, tail); - } - tp->b_next = bp->b_next; - free(bp->b_name); - free(bp); - bp = first; + bp = prev->b_next; goto again; } else { if (prev == NULL) @@ -92,6 +100,11 @@ expand(list, noshexp) if (noshexp) return(list); + if (debug) { + printf("shexpand "); + prnames(list); + } + path = pathp = pathbuf; *pathp = '\0'; lastpathp = &path[sizeof pathbuf - 2]; @@ -126,24 +139,28 @@ expand(list, noshexp) } /* - * Concat head, bp->b_name, and tail + * Return a new NAME block named "head, bp->b_name, tail" */ -makestr(bp, head, tail) +struct block * +copy(bp, head, tail) struct block *bp; char *head, *tail; { register int n; register char *cp; + register struct block *np; - if (!*head && !*tail) - return; + np = ALLOC(block); + if (np == NULL) + fatal("ran out of memory\n"); + np->b_type = NAME; + np->b_next = bp->b_args = NULL; n = strlen(bp->b_name) + strlen(head) + strlen(tail) + 1; - cp = (char *) malloc(n); + np->b_name = cp = malloc(n); if (cp == NULL) fatal("ran out of memory"); sprintf(cp, "%s%s%s", head, bp->b_name, tail); - free(bp->b_name); - bp->b_name = cp; + return(np); } /* @@ -153,7 +170,6 @@ makestr(bp, head, tail) expsh(s) register char *s; { - register int i; register int oargc = argc; if (!strcmp(s, "{") || !strcmp(s, "{}")) { @@ -232,7 +248,6 @@ matchdir(pattern) struct stat stb; register struct direct *dp; DIR *dirp; - register int cnt; dirp = opendir(path); if (dirp == NULL) { @@ -499,13 +514,13 @@ Cat(s1, s2) register char *s1, *s2; { int len = strlen(s1) + strlen(s2) + 1; - register char *s, *ep; + register char *s; nleft -= len; if (nleft <= 0 || ++argc >= GAVSIZ) fatal("Arguments too long\n"); argv[argc] = 0; - argv[argc - 1] = s = (char *) malloc(len); + argv[argc - 1] = s = malloc(len); if (s == NULL) fatal("ran out of memory\n"); while (*s++ = *s1++ & TRIM) @@ -527,8 +542,10 @@ addpath(c) /* * Expand file names beginning with `~' into the - * user's home directory path name. + * user's home directory path name. Return a pointer in buf to the + * part corresponding to `file'. */ +char * exptilde(buf, file) char buf[]; register char *file; @@ -539,7 +556,7 @@ exptilde(buf, file) if (*file != '~') { strcpy(buf, file); - return; + return(buf); } file++; if (*file == '\0' || *file == '/') { @@ -554,10 +571,10 @@ exptilde(buf, file) s3 = NULL; pw = getpwnam(file); if (pw == NULL) { - fatal("unknown user %s\n", file); + error("unknown user %s\n", file); if (s3 != NULL) *s3 = '/'; - return; + return(NULL); } if (s3 != NULL) *s3 = '/'; @@ -565,9 +582,10 @@ exptilde(buf, file) } for (s1 = buf; *s1++ = *s2++; ) ; - if (s3 == NULL) - return; s1--; + if (s3 == NULL) + return(s1); while (*s1++ = *s3++) ; + return(s1 - 1); } diff --git a/usr/src/usr.bin/rdist/gram.y b/usr/src/usr.bin/rdist/gram.y index 34a7c08d00..d9aa63f92d 100644 --- a/usr/src/usr.bin/rdist/gram.y +++ b/usr/src/usr.bin/rdist/gram.y @@ -1,6 +1,6 @@ %{ #ifndef lint -static char *sccsid = "@(#)gram.y 4.2 (Berkeley) 83/09/27"; +static char *sccsid = "@(#)gram.y 4.3 (Berkeley) 83/10/10"; #endif #include "defs.h" @@ -17,16 +17,17 @@ struct block *lastc; %term DCOLON 5 %term NAME 6 %term INSTALL 7 -%term VERIFY 8 -%term NOTIFY 9 -%term EXCEPT 10 +%term NOTIFY 8 +%term EXCEPT 9 +%term OPTION 10 -%union - { +%union { struct block *blk; - } + int intval; +} -%type NAME, INSTALL, VERIFY, NOTIFY, EXCEPT, namelist, names, cmdlist, cmd +%type NAME, INSTALL, NOTIFY, EXCEPT, namelist, names, cmdlist, cmd +%type OPTION, options %% @@ -83,20 +84,16 @@ cmdlist: /* VOID */ { } ; -cmd: INSTALL NAME = { +cmd: INSTALL options NAME = { register struct block *b; - inst_name: - b = expand($2, 0); + $1->b_options = $2; + b = expand($3, 0); if (b == NULL || b->b_next != NULL) fatal("exactly one name allowed\n"); $1->b_name = b->b_name; - free($2); $$ = $1; } - | VERIFY NAME = { - goto inst_name; - } | NOTIFY namelist = { $1->b_args = expand($2, 1); $$ = $1; @@ -106,6 +103,13 @@ cmd: INSTALL NAME = { $$ = $1; } ; +options: /* VOID */ = { + $$ = 0; + } + | options OPTION = { + $$ |= $2; + } + ; %% @@ -117,8 +121,7 @@ yylex() static char yytext[INMAX]; register int c; register char *cp1, *cp2; - register struct block *bp; - static char quotechars[] = "[]{}*?"; + static char quotechars[] = "[]{}*?$"; again: switch (c = getc(fin)) { @@ -158,9 +161,6 @@ again: ungetc(c, fin); c = ':'; } - /* - * Start of a name. - */ cp1 = yytext; cp2 = &yytext[INMAX - 1]; for (;;) { @@ -185,17 +185,30 @@ again: } } *cp1 = '\0'; + if (yytext[0] == '-' && yytext[2] == '\0') { + switch (yytext[1]) { + case 'v': + yylval.intval = VERIFY; + return(OPTION); + + case 'w': + yylval.intval = WHOLE; + return(OPTION); + + case 'y': + yylval.intval = YOUNGER; + return(OPTION); + } + } if (!strcmp(yytext, "install")) c = INSTALL; - else if (!strcmp(yytext, "verify")) - c = VERIFY; else if (!strcmp(yytext, "notify")) c = NOTIFY; else if (!strcmp(yytext, "except")) c = EXCEPT; else c = NAME; - yylval.blk = bp = makeblock(c, yytext); + yylval.blk = makeblock(c, yytext); return(c); } diff --git a/usr/src/usr.bin/rdist/lookup.c b/usr/src/usr.bin/rdist/lookup.c index 6a5836c19b..4fbba69a93 100644 --- a/usr/src/usr.bin/rdist/lookup.c +++ b/usr/src/usr.bin/rdist/lookup.c @@ -1,5 +1,5 @@ #ifndef lint -static char *sccsid = "@(#)lookup.c 4.2 (Berkeley) 83/09/27"; +static char *sccsid = "@(#)lookup.c 4.3 (Berkeley) 83/10/10"; #endif #include "defs.h" @@ -17,9 +17,12 @@ define(name) printf("define(%s)\n", name); cp = index(name, '='); - if (cp == NULL || cp[1] == '\0') + if (cp == NULL) value = NULL; - else if (cp[1] != '(') { + else if (cp[1] == '\0') { + *cp++ = '\0'; + value = NULL; + } else if (cp[1] != '(') { *cp++ = '\0'; value = makeblock(NAME, cp); } else { @@ -99,13 +102,6 @@ lookup(name, value, insert) value->b_args = f; } else if (value->b_type == VAR) fatal("%s redefined\n", name); - while (f = value->b_next) { - value->b_next = f->b_next; - free(f->b_name); - free(f); - } - free(value->b_name); - free(value); } return(b); } @@ -135,7 +131,7 @@ makeblock(type, name) bp->b_type = type; bp->b_next = bp->b_args = NULL; if (type == NAME || type == VAR) { - bp->b_name = cp = (char *) malloc(strlen(name) + 1); + bp->b_name = cp = malloc(strlen(name) + 1); if (cp == NULL) fatal("ran out of memory\n"); while (*cp++ = *name++) diff --git a/usr/src/usr.bin/rdist/main.c b/usr/src/usr.bin/rdist/main.c index 6399478f29..e4bdf15e38 100644 --- a/usr/src/usr.bin/rdist/main.c +++ b/usr/src/usr.bin/rdist/main.c @@ -1,5 +1,5 @@ #ifndef lint -static char *sccsid = "@(#)main.c 4.2 (Berkeley) 83/09/27"; +static char *sccsid = "@(#)main.c 4.3 (Berkeley) 83/10/10"; #endif #include "defs.h" @@ -147,7 +147,7 @@ doupdate(nargs, args) char *args[]; { struct block *bp, *files, *hosts, *cmds, *prev; - int i, firsttime = 1; + int i; char *pos, dest[BUFSIZ]; if (nargs < 2) diff --git a/usr/src/usr.bin/rdist/server.c b/usr/src/usr.bin/rdist/server.c index efb827e5c3..2de64e70c7 100644 --- a/usr/src/usr.bin/rdist/server.c +++ b/usr/src/usr.bin/rdist/server.c @@ -1,5 +1,5 @@ #ifndef lint -static char *sccsid = "@(#)server.c 4.2 (Berkeley) 83/09/27"; +static char *sccsid = "@(#)server.c 4.3 (Berkeley) 83/10/10"; #endif #include "defs.h" @@ -10,12 +10,16 @@ char buf[BUFSIZ]; /* general purpose buffer */ char target[BUFSIZ]; /* target/source directory name */ char *tp; /* pointer to end of target name */ int catname; /* cat name to target name */ +char *stp[32]; /* stack of saved tp's for directories */ +int sumask; /* saved umask for creating files */ static struct passwd *p = NULL; static struct group *g = NULL; extern FILE *lfp; /* log file for mailing changes */ +extern char *exptilde(); + /* * Server routine to read requests and process them. * Commands are: @@ -28,10 +32,9 @@ server() char cmdbuf[BUFSIZ]; register char *cp; register struct block *bp, *last = NULL; - register int n; static struct block cmdblk = { EXCEPT }; - (void) umask(0); + sumask = umask(0); ga(); for (;;) { @@ -57,7 +60,7 @@ server() fatal("ran out of memory\n"); bp->b_type = NAME; bp->b_next = bp->b_args = NULL; - bp->b_name = cp = (char *) malloc(strlen(cp) + 1); + bp->b_name = cp = malloc(strlen(cp) + 1); if (cp == NULL) fatal("ran out of memory\n"); strcpy(cp, &cmdbuf[1]); @@ -77,20 +80,18 @@ server() case 't': /* init target file/directory name */ catname = 0; dotarget: - exptilde(target, cp); + (void) exptilde(target, cp); tp = target; while (*tp) tp++; continue; case 'S': /* Send. Transfer file if out of date. */ - tp = NULL; - sendf(cp, 0); + sendf(cp, NULL, 0); continue; case 'V': /* Verify. See if file is out of date. */ - tp = NULL; - sendf(cp, 1); + sendf(cp, NULL, VERIFY); continue; case 'R': /* Receive. Transfer file. */ @@ -107,22 +108,21 @@ server() error("too many 'E's\n"); continue; } - cp = rindex(target, '/'); - if (cp == NULL) - tp = NULL; - else { - *cp = '\0'; - tp = cp; - } + tp = stp[catname]; + *tp = '\0'; ga(); continue; - case 'Q': /* Query. Does file exist? */ - query(cp); + case 'Q': /* Query. Does directory exist? */ + query(cp, 1); + continue; + + case 'q': /* query. Does file exist? */ + query(cp, 0); continue; case 'L': /* Log. save message in log file */ - query(cp); + log(lfp, cp); continue; case '\1': @@ -143,40 +143,57 @@ server() /* * Transfer the file or directory 'name'. */ -sendf(name, verify) - char *name; - int verify; +sendf(lname, rname, options) + char *lname, *rname; + int options; { - register char *last; + register char *cp; struct stat stb; int sizerr, f, u; off_t i; if (debug) - printf("sendf(%s, %d)\n", name, verify); + printf("sendf(%s, %s, %x)\n", lname, + rname != NULL ? rname : "NULL", options); - if (exclude(name)) + if (exclude(lname)) return; /* - * first time sendf() is called? + * First time sendf() is called? */ - if (tp == NULL) { - exptilde(target, name); - tp = name = target; + if (rname == NULL) { + rname = exptilde(target, lname); + if (rname == NULL) + return; + tp = lname = target; while (*tp) tp++; + /* + * If we are renaming a directory and we want to preserve + * the directory heirarchy (-w), we must strip off the first + * directory name and preserve the rest. + */ + if (options & STRIP) { + options &= ~STRIP; + rname = index(rname, '/'); + if (rname == NULL) + rname = tp; + else + rname++; + } else if (!(options & WHOLE)) { + rname = rindex(lname, '/'); + if (rname == NULL) + rname = lname; + else + rname++; + } } - if (access(name, 4) < 0 || stat(name, &stb) < 0) { - error("%s: %s\n", name, sys_errlist[errno]); + if (access(lname, 4) < 0 || stat(lname, &stb) < 0) { + error("%s: %s\n", lname, sys_errlist[errno]); return; } - last = rindex(name, '/'); - if (last == NULL) - last = name; - else - last++; - if ((u = update(last, &stb)) == 0) + if ((u = update(lname, rname, options, &stb)) == 0) return; if (p == NULL || p->pw_uid != stb.st_uid) @@ -195,25 +212,25 @@ sendf(name, verify) break; case S_IFDIR: - rsendf(name, verify, &stb, p->pw_name, g->gr_name); + rsendf(lname, rname, options, &stb, p->pw_name, g->gr_name); return; default: - error("%s: not a plain file\n", name); + error("%s: not a plain file\n", lname); return; } - log(lfp, "%s: %s\n", u == 2 ? "updating" : "installing", name); + log(lfp, "%s: %s\n", u == 2 ? "updating" : "installing", lname); - if (verify || vflag) + if ((options & VERIFY) || vflag) return; - if ((f = open(name, 0)) < 0) { - error("%s: %s\n", name, sys_errlist[errno]); + if ((f = open(lname, 0)) < 0) { + error("%s: %s\n", lname, sys_errlist[errno]); return; } (void) sprintf(buf, "R%04o %D %D %s %s %s\n", stb.st_mode & 07777, - stb.st_size, stb.st_mtime, p->pw_name, g->gr_name, last); + stb.st_size, stb.st_mtime, p->pw_name, g->gr_name, rname); if (debug) printf("buf = %s", buf); (void) write(rem, buf, strlen(buf)); @@ -232,39 +249,33 @@ sendf(name, verify) } (void) close(f); if (sizerr) - error("%s: file changed size\n", name); + error("%s: file changed size\n", lname); else ga(); (void) response(); } -rsendf(name, verify, st, owner, group) - char *name; - int verify; +rsendf(lname, rname, options, st, owner, group) + char *lname, *rname; + int options; struct stat *st; char *owner, *group; { DIR *d; struct direct *dp; - register char *last; - char *otp; + char *otp, *cp; int len; if (debug) - printf("rsendf(%s, %d, %x, %s, %s)\n", name, verify, st, - owner, group); + printf("rsendf(%s, %s, %x, %x, %s, %s)\n", lname, rname, + options, st, owner, group); - if ((d = opendir(name)) == NULL) { - error("%s: %s\n", name, sys_errlist[errno]); + if ((d = opendir(lname)) == NULL) { + error("%s: %s\n", lname, sys_errlist[errno]); return; } - last = rindex(name, '/'); - if (last == NULL) - last = name; - else - last++; (void) sprintf(buf, "D%04o 0 0 %s %s %s\n", st->st_mode & 07777, - owner, group, last); + owner, group, rname); if (debug) printf("buf = %s", buf); (void) write(rem, buf, strlen(buf)); @@ -278,16 +289,16 @@ rsendf(name, verify, st, owner, group) if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; if (len + 1 + strlen(dp->d_name) >= BUFSIZ - 1) { - error("%s/%s: Name too long\n", name, dp->d_name); + error("%s/%s: Name too long\n", target, dp->d_name); continue; } tp = otp; *tp++ = '/'; - last = dp->d_name; - while (*tp++ = *last++) + cp = dp->d_name; + while (*tp++ = *cp++) ; tp--; - sendf(target, verify); + sendf(target, dp->d_name, options); } closedir(d); (void) write(rem, "E\n", 2); @@ -300,8 +311,9 @@ rsendf(name, verify, st, owner, group) * Check to see if file needs to be updated on the remote machine. * Returns 0 if no update, 1 if remote doesn't exist, and 2 if out of date. */ -update(name, st) - char *name; +update(lname, rname, options, st) + char *lname, *rname; + int options; struct stat *st; { register char *cp; @@ -309,12 +321,13 @@ update(name, st) register time_t mtime; if (debug) - printf("update(%s, %x)\n", name, st); + printf("update(%s, %s, %x, %x)\n", lname, rname, options, st); /* * Check to see if the file exists on the remote machine. */ - (void) sprintf(buf, "Q%s\n", name); + (void) sprintf(buf, "%c%s\n", + (st->st_mode & S_IFMT) == S_IFDIR ? 'Q' : 'q', rname); if (debug) printf("buf = %s", buf); (void) write(rem, buf, strlen(buf)); @@ -323,12 +336,8 @@ update(name, st) if (read(rem, cp, 1) != 1) lostconn(); } while (*cp++ != '\n' && cp < &buf[BUFSIZ]); - *--cp = '\0'; - cp = buf; - if (debug) - printf("resp = %s\n", cp); - switch (*cp++) { + switch (buf[0]) { case 'Y': break; @@ -337,26 +346,24 @@ update(name, st) case '\1': errs++; - if (*cp != '\0') { + if (cp > &buf[2]) { if (!iamremote) { fflush(stdout); - (void) write(2, cp, strlen(cp)); + (void) write(2, cp, cp - buf); } if (lfp != NULL) - (void) fwrite(cp, 1, strlen(cp), lfp); + (void) fwrite(cp, 1, cp - buf, lfp); } return(0); default: - error("unexpected response '%c' to query\n", *--cp); + error("unexpected response '%c' to query\n", buf[0]); return(0); } - if (*cp == '\0') { - if ((st->st_mode & S_IFMT) == S_IFDIR) - return(2); - return(1); - } + cp = &buf[1]; + if (*cp == '\n') + return(2); size = 0; while (isdigit(*cp)) @@ -368,15 +375,21 @@ update(name, st) mtime = 0; while (isdigit(*cp)) mtime = mtime * 10 + (*cp++ - '0'); - if (*cp != '\0') { + if (*cp != '\n') { error("mtime not delimited\n"); return(0); } /* * File needs to be updated? */ - if (st->st_mtime == mtime && st->st_size == size || - yflag && st->st_mtime < mtime) + if (yflag || (options & YOUNGER)) { + if (st->st_mtime == mtime) + return(0); + if (st->st_mtime < mtime) { + log(lfp, "Warning: %s older than remote copy\n", lname); + return(0); + } + } else if (st->st_mtime == mtime && st->st_size == size) return(0); return(2); } @@ -388,13 +401,15 @@ update(name, st) * Y\n - exists and its a directory * ^Aerror message\n */ -query(name) +query(name, isdir) char *name; { struct stat stb; if (catname) (void) sprintf(tp, "/%s", name); + +again: if (stat(target, &stb) < 0) { (void) write(rem, "N\n", 2); *tp = '\0'; @@ -408,6 +423,14 @@ query(name) break; case S_IFDIR: + /* + * If file -> directory, need to cat name to target and stat. + */ + if (!isdir && !catname) { + isdir = 1; + (void) sprintf(tp, "/%s", name); + goto again; + } (void) write(rem, "Y\n", 2); break; @@ -423,7 +446,7 @@ recvf(cmd, isdir) int isdir; { register char *cp; - int f, mode, wrerr, exists, olderrno; + int f, mode, wrerr, olderrno; off_t i, size; time_t mtime; struct stat stb; @@ -477,6 +500,11 @@ recvf(cmd, isdir) new[0] = '\0'; if (isdir) { + if (catname >= sizeof(stp)) { + error("%s: too many directory levels\n", target); + return; + } + stp[catname] = tp; if (catname++) { *tp++ = '/'; while (*tp++ = *cp++) @@ -493,23 +521,8 @@ recvf(cmd, isdir) goto bad; } } else { - /* - * Check parent directory for write permission. - */ - cp = rindex(target, '/'); - if (cp == NULL) - dir = "."; - else if (cp == target) { - dir = "/"; - cp = NULL; - } else { - dir = target; - *cp = '\0'; - } - if (access(dir, 2) < 0) - goto bad2; - if (cp != NULL) - *cp = '/'; + if (chkparent(target) < 0) + goto bad; if (mkdir(target, mode) < 0) goto bad; if (chog(target, owner, group, mode) < 0) @@ -537,9 +550,8 @@ recvf(cmd, isdir) return; } } - /* - * Check parent directory for write permission. - */ + if (chkparent(target) < 0) + goto bad; cp = rindex(target, '/'); if (cp == NULL) dir = "."; @@ -550,13 +562,6 @@ recvf(cmd, isdir) dir = target; *cp = '\0'; } - if (access(dir, 2) < 0) { -bad2: - error("%s: %s\n", dir, sys_errlist[errno]); - if (cp != NULL) - *cp = '/'; - return; - } (void) sprintf(new, "%s/%s", dir, tmpname); if (cp != NULL) *cp = '/'; @@ -572,8 +577,8 @@ bad2: wrerr = 0; for (i = 0; i < size; i += BUFSIZ) { int amt = BUFSIZ; - char *cp = buf; + cp = buf; if (i + amt > size) amt = size - i; do { @@ -630,6 +635,53 @@ bad: ga(); } +/* + * Check parent directory for write permission and create if it doesn't + * exist. + */ +chkparent(name) + char *name; +{ + register char *cp, *dir; + extern int userid, groupid; + + cp = rindex(name, '/'); + if (cp == NULL) + dir = "."; + else if (cp == name) { + dir = "/"; + cp = NULL; + } else { + dir = name; + *cp = '\0'; + } + if (access(dir, 2) == 0) { + if (cp != NULL) + *cp = '/'; + return(0); + } + if (errno == ENOENT) { + if (rindex(dir, '/') != NULL && chkparent(dir) < 0) + goto bad; + if (!strcmp(dir, ".") || !strcmp(dir, "/")) + goto bad; + if (mkdir(dir, 0777 & ~sumask) < 0) + goto bad; + if (chown(dir, userid, groupid) < 0) { + (void) unlink(dir); + goto bad; + } + if (cp != NULL) + *cp = '/'; + return(0); + } + +bad: + if (cp != NULL) + *cp = '/'; + return(-1); +} + /* * Change owner and group of file. */ @@ -680,7 +732,7 @@ ok: return(0); } -/*VARARGS*/ +/*VARARGS2*/ log(fp, fmt, a1, a2, a3) FILE *fp; char *fmt; @@ -695,7 +747,7 @@ log(fp, fmt, a1, a2, a3) fprintf(fp, fmt, a1, a2, a3); } -/*VARARGS*/ +/*VARARGS1*/ error(fmt, a1, a2, a3) char *fmt; int a1, a2, a3; @@ -704,17 +756,15 @@ error(fmt, a1, a2, a3) strcpy(buf, "\1rdist: "); (void) sprintf(buf+8, fmt, a1, a2, a3); (void) write(rem, buf, strlen(buf)); - if (buf[1] != '\0') { - if (!iamremote) { - fflush(stdout); - (void) write(2, buf+1, strlen(buf+1)); - } - if (lfp != NULL) - (void) fwrite(buf+1, 1, strlen(buf+1), lfp); + if (!iamremote) { + fflush(stdout); + (void) write(2, buf+1, strlen(buf+1)); } + if (lfp != NULL) + (void) fwrite(buf+1, 1, strlen(buf+1), lfp); } -/*VARARGS*/ +/*VARARGS1*/ fatal(fmt, a1, a2,a3) char *fmt; int a1, a2, a3; @@ -723,20 +773,18 @@ fatal(fmt, a1, a2,a3) strcpy(buf, "\2rdist: "); (void) sprintf(buf+8, fmt, a1, a2, a3); (void) write(rem, buf, strlen(buf)); - if (buf[1] != '\0') { - if (!iamremote) { - fflush(stdout); - (void) write(2, buf+1, strlen(buf+1)); - } - if (lfp != NULL) - (void) fwrite(buf+1, 1, strlen(buf+1), lfp); + if (!iamremote) { + fflush(stdout); + (void) write(2, buf+1, strlen(buf+1)); } + if (lfp != NULL) + (void) fwrite(buf+1, 1, strlen(buf+1), lfp); cleanup(); } response() { - char resp, c, *cp = buf; + char resp, *cp = buf; if (debug) printf("response()\n"); -- 2.20.1