diff options
author | obrien <obrien@FreeBSD.org> | 2000-12-07 19:24:55 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 2000-12-07 19:24:55 +0000 |
commit | 172e75f19374ae58caa1a5459a3f8a1d3a36f5de (patch) | |
tree | d09d274b31adb401922100b5a49ef6f97fab5171 /usr.bin/rdist | |
parent | d2fca12323f8e184b45b47597f9ce026d4831358 (diff) | |
download | FreeBSD-src-172e75f19374ae58caa1a5459a3f8a1d3a36f5de.zip FreeBSD-src-172e75f19374ae58caa1a5459a3f8a1d3a36f5de.tar.gz |
Retire this ancient version of rdist.
Diffstat (limited to 'usr.bin/rdist')
-rw-r--r-- | usr.bin/rdist/Makefile | 16 | ||||
-rw-r--r-- | usr.bin/rdist/cron.entry | 1 | ||||
-rw-r--r-- | usr.bin/rdist/defs.h | 191 | ||||
-rw-r--r-- | usr.bin/rdist/docmd.c | 700 | ||||
-rw-r--r-- | usr.bin/rdist/expand.c | 677 | ||||
-rw-r--r-- | usr.bin/rdist/gram.y | 523 | ||||
-rw-r--r-- | usr.bin/rdist/lookup.c | 171 | ||||
-rw-r--r-- | usr.bin/rdist/main.c | 337 | ||||
-rw-r--r-- | usr.bin/rdist/pathnames.h | 39 | ||||
-rw-r--r-- | usr.bin/rdist/rshrcmd.c | 119 | ||||
-rw-r--r-- | usr.bin/rdist/server.c | 1634 |
11 files changed, 0 insertions, 4408 deletions
diff --git a/usr.bin/rdist/Makefile b/usr.bin/rdist/Makefile deleted file mode 100644 index ea47411..0000000 --- a/usr.bin/rdist/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# @(#)Makefile 8.3 (Berkeley) 7/19/93 -# $FreeBSD$ - -PROG= rdist -SRCS= docmd.c expand.c gram.y lookup.c main.c rshrcmd.c server.c -CFLAGS+=-I${.CURDIR} -YFLAGS= - -# To use the old method, which requires setuid-root and all the baggage and -# security holes that goes with it, uncomment: -# CFLAGS+= -DDIRECT_RCMD -# BINOWN= root -# BINMODE=4555 -# INSTALLFLAGS=-fschg - -.include <bsd.prog.mk> diff --git a/usr.bin/rdist/cron.entry b/usr.bin/rdist/cron.entry deleted file mode 100644 index 90968cf..0000000 --- a/usr.bin/rdist/cron.entry +++ /dev/null @@ -1 +0,0 @@ -30 3 * * * /usr/bin/rdist -f /etc/Distfile >& /var/log/rdist/rdist.err 2>&1 diff --git a/usr.bin/rdist/defs.h b/usr.bin/rdist/defs.h deleted file mode 100644 index 47fad20..0000000 --- a/usr.bin/rdist/defs.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)defs.h 8.1 (Berkeley) 6/9/93 - */ - -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/file.h> - -#include <netinet/in.h> - -#include <dirent.h> -#include <errno.h> -#include <pwd.h> -#include <grp.h> -#include <stdio.h> -#include <ctype.h> -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include "pathnames.h" - -/* - * The version number should be changed whenever the protocol changes. - */ -#define VERSION 3 - - /* defines for yacc */ -#define EQUAL 1 -#define LP 2 -#define RP 3 -#define SM 4 -#define ARROW 5 -#define COLON 6 -#define DCOLON 7 -#define NAME 8 -#define STRING 9 -#define INSTALL 10 -#define NOTIFY 11 -#define EXCEPT 12 -#define PATTERN 13 -#define SPECIAL 14 -#define OPTION 15 - - /* lexical definitions */ -#define QUOTE 0200 /* used internally for quoted characters */ -#define TRIM 0177 /* Mask to strip quote bit */ - - /* table sizes */ -#define HASHSIZE 1021 -#define INMAX 3500 - - /* option flags */ -#define VERIFY 0x1 -#define WHOLE 0x2 -#define YOUNGER 0x4 -#define COMPARE 0x8 -#define REMOVE 0x10 -#define FOLLOW 0x20 -#define IGNLNKS 0x40 - - /* expand type definitions */ -#define E_VARS 0x1 -#define E_SHELL 0x2 -#define E_TILDE 0x4 -#define E_ALL 0x7 - - /* actions for lookup() */ -#define LOOKUP 0 -#define INSERT 1 -#define REPLACE 2 - -#define ISDIR(m) (((m) & S_IFMT) == S_IFDIR) - -#define ALLOC(x) (struct x *) malloc(sizeof(struct x)) - -/* - * RSH Time Out interval (in seconds). - * Should be long enough to allow rsh to even the slowest hosts. - */ -#define RTIMEOUT 180 - - -struct namelist { /* for making lists of strings */ - char *n_name; - struct namelist *n_next; -}; - -struct subcmd { - short sc_type; /* type - INSTALL,NOTIFY,EXCEPT,SPECIAL */ - short sc_options; - char *sc_name; - struct namelist *sc_args; - struct subcmd *sc_next; -}; - -struct cmd { - int c_type; /* type - ARROW,DCOLON */ - char *c_name; /* hostname or time stamp file name */ - char *c_label; /* label for partial update */ - struct namelist *c_files; - struct subcmd *c_cmds; - struct cmd *c_next; -}; - -struct linkbuf { - ino_t inum; - dev_t devnum; - int count; - char pathname[BUFSIZ]; - char src[BUFSIZ]; - char target[BUFSIZ]; - struct linkbuf *nextp; -}; - -extern int debug; /* debugging flag */ -extern int nflag; /* NOP flag, don't execute commands */ -extern int qflag; /* Quiet. don't print messages */ -extern int options; /* global options */ - -extern int nerrs; /* number of errors seen */ -extern int rem; /* remote file descriptor */ -extern int iamremote; /* acting as remote server */ -extern char tempfile[]; /* file name for logging changes */ -extern struct linkbuf *ihead; /* list of files with more than one link */ -extern struct passwd *pw; /* pointer to static area used by getpwent */ -extern struct group *gr; /* pointer to static area used by getgrent */ -extern char host[]; /* host name of master copy */ -extern char buf[BUFSIZ]; /* general purpose buffer */ -extern char target[BUFSIZ]; /* target/source directory name */ -extern char *path_rsh; /* rsh command to use */ - -int any __P((int, char *)); -char *colon __P((char *)); -void cleanup __P((int)); -void define __P((char *)); -void docmds __P((char **, int, char **)); -void error __P((const char *, ...)); -int except __P((char *)); -struct namelist * - expand __P((struct namelist *, int)); -char *exptilde __P((char [], char *, int)); -void fatal __P((const char *, ...)); -int inlist __P((struct namelist *, char *)); -void insert __P((char *, - struct namelist *, struct namelist *, struct subcmd *)); -void install __P((char *, char *, int, int)); -void log __P((FILE *, const char *, ...)); -struct namelist * - lookup __P((char *, int, struct namelist *)); -void lostconn __P((int)); -struct namelist * - makenl __P((char *)); -struct subcmd * - makesubcmd __P((int)); -void prnames __P((struct namelist *)); -void server __P((void)); -void yyerror __P((char *)); -int yyparse __P((void)); -int rshrcmd __P((char **, u_short, char *, char *, char *, int *)); diff --git a/usr.bin/rdist/docmd.c b/usr.bin/rdist/docmd.c deleted file mode 100644 index 7ea9a8c..0000000 --- a/usr.bin/rdist/docmd.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "From: @(#)docmd.c 8.1 (Berkeley) 6/9/93"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include "defs.h" -#include <setjmp.h> -#include <netdb.h> -#include <regex.h> - -FILE *lfp; /* log file for recording files updated */ -struct subcmd *subcmds; /* list of sub-commands for current cmd */ -jmp_buf env; - -static int makeconn __P((char *)); -static int okname __P((char *)); -static void closeconn __P((void)); -static void cmptime __P((char *)); -static void doarrow __P((char **, - struct namelist *, char *, struct subcmd *)); -static void dodcolon __P((char **, - struct namelist *, char *, struct subcmd *)); -static void notify __P((char *, char *, struct namelist *, time_t)); -static void rcmptime __P((struct stat *)); -static int remotecmd __P((char *, char *, char *, char *)); - -/* - * Do the commands in cmds (initialized by yyparse). - */ -void -docmds(dhosts, argc, argv) - char **dhosts; - int argc; - char **argv; -{ - register struct cmd *c; - register struct namelist *f; - register char **cpp; - extern struct cmd *cmds; - - signal(SIGHUP, cleanup); - signal(SIGINT, cleanup); - signal(SIGQUIT, cleanup); - signal(SIGTERM, cleanup); - - for (c = cmds; c != NULL; c = c->c_next) { - if (dhosts != NULL && *dhosts != NULL) { - for (cpp = dhosts; *cpp; cpp++) - if (strcmp(c->c_name, *cpp) == 0) - goto fndhost; - continue; - } - fndhost: - if (argc) { - for (cpp = argv; *cpp; cpp++) { - if (c->c_label != NULL && - strcmp(c->c_label, *cpp) == 0) { - cpp = NULL; - goto found; - } - for (f = c->c_files; f != NULL; f = f->n_next) - if (strcmp(f->n_name, *cpp) == 0) - goto found; - } - continue; - } else - cpp = NULL; - found: - switch (c->c_type) { - case ARROW: - doarrow(cpp, c->c_files, c->c_name, c->c_cmds); - break; - case DCOLON: - dodcolon(cpp, c->c_files, c->c_name, c->c_cmds); - break; - default: - fatal("illegal command type %d\n", c->c_type); - } - } - closeconn(); -} - -/* - * Process commands for sending files to other machines. - */ -static void -doarrow(filev, files, rhost, cmds) - char **filev; - struct namelist *files; - char *rhost; - struct subcmd *cmds; -{ - register struct namelist *f; - register struct subcmd *sc; - register char **cpp; - int n, ddir, opts = options; - - if (debug) - printf("doarrow(%p, %s, %p)\n", files, rhost, cmds); - - if (files == NULL) { - error("no files to be updated\n"); - return; - } - - subcmds = cmds; - ddir = files->n_next != NULL; /* destination is a directory */ - if (nflag) - printf("updating host %s\n", rhost); - else { - if (setjmp(env)) - goto done; - signal(SIGPIPE, lostconn); - if (!makeconn(rhost)) - return; - if ((lfp = fopen(tempfile, "w")) == NULL) { - fatal("cannot open %s\n", tempfile); - exit(1); - } - } - for (f = files; f != NULL; f = f->n_next) { - if (filev) { - for (cpp = filev; *cpp; cpp++) - if (strcmp(f->n_name, *cpp) == 0) - goto found; - if (!nflag) - (void) fclose(lfp); - continue; - } - found: - n = 0; - for (sc = cmds; sc != NULL; sc = sc->sc_next) { - if (sc->sc_type != INSTALL) - continue; - n++; - install(f->n_name, sc->sc_name, - sc->sc_name == NULL ? 0 : ddir, sc->sc_options); - opts = sc->sc_options; - } - if (n == 0) - install(f->n_name, NULL, 0, options); - } -done: - if (!nflag) { - (void) signal(SIGPIPE, cleanup); - if (lfp) - (void) fclose(lfp); - lfp = NULL; - } - for (sc = cmds; sc != NULL; sc = sc->sc_next) - if (sc->sc_type == NOTIFY) - notify(tempfile, rhost, sc->sc_args, 0); - if (!nflag) { - struct linkbuf *nextihead; - - (void) unlink(tempfile); - for (; ihead != NULL; ihead = nextihead) { - nextihead = ihead->nextp; - if ((opts & IGNLNKS) || ihead->count == 0) - continue; - log(lfp, "%s: Warning: missing links\n", - ihead->pathname); - free(ihead); - } - } -} - -static int remotecmd(rhost, luser, ruser, cmd) - char *rhost; - char *luser, *ruser; - char *cmd; -{ - int desc; - static int port = -1; - - if (debug) { - printf("local user = %s remote user = %s\n", luser, ruser); - printf("Remote command = '%s'\n", cmd); - } - - (void) fflush(stdout); - (void) fflush(stderr); - (void) signal(SIGALRM, cleanup); - (void) alarm(RTIMEOUT); - - if (geteuid() == 0 && strcmp(path_rsh, _PATH_RSH) == 0) { - if (debug) - printf("I am root, therefore direct rcmd\n"); - - (void) signal(SIGPIPE, cleanup); - - if (port < 0) { - struct servent *sp; - - if ((sp = getservbyname("shell", "tcp")) == NULL) - fatal("shell/tcp: unknown service"); - port = sp->s_port; - } - - desc = rcmd(&rhost, port, luser, ruser, cmd, 0); - } else { - if (debug) - printf("Remote shell command = '%s'\n", path_rsh); - (void) signal(SIGPIPE, SIG_IGN); - desc = rshrcmd(&rhost, -1, luser, ruser, cmd, 0); - if (desc > 0) - (void) signal(SIGPIPE, cleanup); - } - - (void) alarm(0); - - return(desc); -} - - -/* - * Create a connection to the rdist server on the machine rhost. - */ -static int -makeconn(rhost) - char *rhost; -{ - register char *ruser, *cp; - static char *cur_host = NULL; - static int port = -1; - char tuser[20]; - int n; - extern char user[]; -#if defined(DIRECT_RCMD) - extern int userid; -#endif - - if (debug) - printf("makeconn(%s)\n", rhost); - - if (cur_host != NULL && rem >= 0) { - if (strcmp(cur_host, rhost) == 0) - return(1); - closeconn(); - } - cur_host = rhost; - cp = index(rhost, '@'); - if (cp != NULL) { - char c = *cp; - - *cp = '\0'; - strncpy(tuser, rhost, sizeof(tuser)-1); - *cp = c; - rhost = cp + 1; - ruser = tuser; - if (*ruser == '\0') - ruser = user; - else if (!okname(ruser)) - return(0); - } else - ruser = user; - if (!qflag) - printf("updating host %s\n", rhost); - (void) snprintf(buf, sizeof(buf), "%s -Server%s", - _PATH_RDIST, qflag ? " -q" : ""); - if (port < 0) { - struct servent *sp; - - if ((sp = getservbyname("shell", "tcp")) == NULL) - fatal("shell/tcp: unknown service"); - port = sp->s_port; - } - - if (debug) { - printf("port = %d, luser = %s, ruser = %s\n", ntohs(port), user, ruser); - printf("buf = %s\n", buf); - } - - fflush(stdout); -#if defined(DIRECT_RCMD) - seteuid(0); - rem = rcmd(&rhost, port, user, ruser, buf, 0); - seteuid(userid); -#else - rem = remotecmd(rhost, user, ruser, buf); -#endif - if (rem < 0) - return(0); - cp = buf; - if (read(rem, cp, 1) != 1) - lostconn(0); - if (*cp == 'V') { - do { - if (read(rem, cp, 1) != 1) - lostconn(0); - } while (*cp++ != '\n' && cp < &buf[BUFSIZ]); - *--cp = '\0'; - cp = buf; - n = 0; - while (*cp >= '0' && *cp <= '9') - n = (n * 10) + (*cp++ - '0'); - if (*cp == '\0' && n == VERSION) - return(1); - error("connection failed: version numbers don't match (local %d, remote %d)\n", VERSION, n); - } else { - error("connection failed: version numbers don't match\n"); - error("got unexpected input:"); - do { - error("%c", *cp); - } while (*cp != '\n' && read(rem, cp, 1) == 1); - } - closeconn(); - return(0); -} - -/* - * Signal end of previous connection. - */ -static void -closeconn() -{ - if (debug) - printf("closeconn()\n"); - - if (rem >= 0) { - (void) write(rem, "\2\n", 2); - (void) close(rem); - rem = -1; - } -} - -void -lostconn(signo) - int signo; -{ - if (iamremote) - cleanup(0); - log(lfp, "rdist: lost connection\n"); - longjmp(env, 1); -} - -static int -okname(name) - register char *name; -{ - register char *cp = name; - register int c; - - do { - c = *cp; - if (c & 0200) - goto bad; - if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-') - goto bad; - cp++; - } while (*cp); - return(1); -bad: - error("invalid user name %s\n", name); - return(0); -} - -time_t lastmod; -FILE *tfp; -extern char target[], *tp; - -/* - * Process commands for comparing files to time stamp files. - */ -static void -dodcolon(filev, files, stamp, cmds) - char **filev; - struct namelist *files; - char *stamp; - struct subcmd *cmds; -{ - register struct subcmd *sc; - register struct namelist *f; - register char **cpp; - struct timeval tv[2]; - struct timezone tz; - struct stat stb; - - if (debug) - printf("dodcolon()\n"); - - if (files == NULL) { - error("no files to be updated\n"); - return; - } - if (stat(stamp, &stb) < 0) { - error("%s: %s\n", stamp, strerror(errno)); - return; - } - if (debug) - printf("%s: %ld\n", stamp, stb.st_mtime); - - subcmds = cmds; - lastmod = stb.st_mtime; - if (nflag || (options & VERIFY)) - tfp = NULL; - else { - if ((tfp = fopen(tempfile, "w")) == NULL) { - error("%s: %s\n", stamp, strerror(errno)); - return; - } - (void) gettimeofday(&tv[0], &tz); - tv[1] = tv[0]; - (void) utimes(stamp, tv); - } - - for (f = files; f != NULL; f = f->n_next) { - if (filev) { - for (cpp = filev; *cpp; cpp++) - if (strcmp(f->n_name, *cpp) == 0) - goto found; - continue; - } - found: - tp = NULL; - cmptime(f->n_name); - } - - if (tfp != NULL) - (void) fclose(tfp); - for (sc = cmds; sc != NULL; sc = sc->sc_next) - if (sc->sc_type == NOTIFY) - notify(tempfile, NULL, sc->sc_args, lastmod); - if (!nflag && !(options & VERIFY)) - (void) unlink(tempfile); -} - -/* - * Compare the mtime of file to the list of time stamps. - */ -static void -cmptime(name) - char *name; -{ - struct stat stb; - - if (debug) - printf("cmptime(%s)\n", name); - - if (except(name)) - return; - - if (nflag) { - printf("comparing dates: %s\n", name); - return; - } - - /* - * first time cmptime() is called? - */ - if (tp == NULL) { - if (exptilde(target, name, sizeof(target)) == NULL) - return; - tp = name = target; - while (*tp) - tp++; - } - if (access(name, 4) < 0 || stat(name, &stb) < 0) { - error("%s: %s\n", name, strerror(errno)); - return; - } - - switch (stb.st_mode & S_IFMT) { - case S_IFREG: - break; - - case S_IFDIR: - rcmptime(&stb); - return; - - default: - error("%s: not a plain file\n", name); - return; - } - - if (stb.st_mtime > lastmod) - log(tfp, "new: %s\n", name); -} - -static void -rcmptime(st) - struct stat *st; -{ - register DIR *d; - register struct dirent *dp; - register char *cp; - char *otp; - int len; - - if (debug) - printf("rcmptime(%p)\n", st); - - if ((d = opendir(target)) == NULL) { - error("%s: %s\n", target, strerror(errno)); - return; - } - 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: Name too long\n", target, dp->d_name); - continue; - } - tp = otp; - *tp++ = '/'; - cp = dp->d_name; - while ((*tp++ = *cp++)) - ; - tp--; - cmptime(target); - } - closedir(d); - tp = otp; - *tp = '\0'; -} - -/* - * Notify the list of people the changes that were made. - * rhost == NULL if we are mailing a list of changes compared to at time - * stamp file. - */ -static void -notify(file, rhost, to, lmod) - char *file, *rhost; - register struct namelist *to; - time_t lmod; -{ - register int fd, len; - struct stat stb; - FILE *pf; - - if ((options & VERIFY) || to == NULL) - return; - if (!qflag) { - printf("notify "); - if (rhost) - printf("@%s ", rhost); - prnames(to); - } - if (nflag) - return; - - if ((fd = open(file, 0)) < 0) { - error("%s: %s\n", file, strerror(errno)); - return; - } - if (fstat(fd, &stb) < 0) { - error("%s: %s\n", file, strerror(errno)); - (void) close(fd); - return; - } - if (stb.st_size == 0) { - (void) close(fd); - return; - } - /* - * Create a pipe to mailling program. - */ - (void) snprintf(buf, sizeof(buf), "%s -oi -t", _PATH_SENDMAIL); - pf = popen(buf, "w"); - if (pf == NULL) { - error("notify: \"%s\" failed\n", _PATH_SENDMAIL); - (void) close(fd); - return; - } - /* - * Output the proper header information. - */ - fprintf(pf, "From: rdist (Remote distribution program)\n"); - fprintf(pf, "To:"); - if (!any('@', to->n_name) && rhost != NULL) - fprintf(pf, " %s@%s", to->n_name, rhost); - else - fprintf(pf, " %s", to->n_name); - to = to->n_next; - while (to != NULL) { - if (!any('@', to->n_name) && rhost != NULL) - fprintf(pf, ", %s@%s", to->n_name, rhost); - else - fprintf(pf, ", %s", to->n_name); - to = to->n_next; - } - putc('\n', pf); - if (rhost != NULL) - fprintf(pf, "Subject: files updated by rdist from %s to %s\n", - host, rhost); - else - fprintf(pf, "Subject: files updated after %s\n", ctime(&lmod)); - putc('\n', pf); - - while ((len = read(fd, buf, BUFSIZ)) > 0) - (void) fwrite(buf, 1, len, pf); - (void) close(fd); - (void) pclose(pf); -} - -/* - * Return true if name is in the list. - */ -int -inlist(list, file) - struct namelist *list; - char *file; -{ - register struct namelist *nl; - - for (nl = list; nl != NULL; nl = nl->n_next) - if (!strcmp(file, nl->n_name)) - return(1); - return(0); -} - -/* - * Return TRUE if file is in the exception list. - */ -int -except(file) - char *file; -{ - register struct subcmd *sc; - register struct namelist *nl; - regex_t rx; - int val; - - if (debug) - printf("except(%s)\n", file); - - for (sc = subcmds; sc != NULL; sc = sc->sc_next) { - if (sc->sc_type != EXCEPT && sc->sc_type != PATTERN) - continue; - for (nl = sc->sc_args; nl != NULL; nl = nl->n_next) { - if (sc->sc_type == EXCEPT) { - if (!strcmp(file, nl->n_name)) - return(1); - continue; - } - val = regcomp(&rx, nl->n_name, - REG_EXTENDED | REG_NOSUB); - if (!regexec(&rx, file, 0, 0, 0)) { - regfree(&rx); - return 1; - } - regfree(&rx); - } - } - return(0); -} - -char * -colon(cp) - register char *cp; -{ - - while (*cp) { - if (*cp == ':') - return(cp); - if (*cp == '/') - return(0); - cp++; - } - return(0); -} diff --git a/usr.bin/rdist/expand.c b/usr.bin/rdist/expand.c deleted file mode 100644 index d5f7ed4..0000000 --- a/usr.bin/rdist/expand.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)expand.c 8.1 (Berkeley) 6/9/93"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include "defs.h" - -#define GAVSIZ NCARGS / 6 -#define LC '{' -#define RC '}' - -static char shchars[] = "${[*?"; - -int which; /* bit mask of types to expand */ -int eargc; /* expanded arg count */ -char **eargv; /* expanded arg vectors */ -char *path; -char *pathp; -char *lastpathp; -char *tilde; /* "~user" if not expanding tilde, else "" */ -char *tpathp; -int nleft; - -int expany; /* any expansions done? */ -char *entp; -char **sortbase; - -#define sort() qsort((char *)sortbase, &eargv[eargc] - sortbase, \ - sizeof(*sortbase), argcmp), sortbase = &eargv[eargc] - -static void Cat __P((char *, char *)); -static void addpath __P((int)); -static int amatch __P((char *, char *)); -static int argcmp __P((const void *, const void *)); -static int execbrc __P((char *, char *)); -static void expsh __P((char *)); -static void expstr __P((char *)); -static int match __P((char *, char *)); -static void matchdir __P((char *)); -static int smatch __P((char *, char *)); - -/* - * Take a list of names and expand any macros, etc. - * wh = E_VARS if expanding variables. - * wh = E_SHELL if expanding shell characters. - * wh = E_TILDE if expanding `~'. - * or any of these or'ed together. - * - * Major portions of this were snarfed from csh/sh.glob.c. - */ -struct namelist * -expand(list, wh) - struct namelist *list; - int wh; -{ - register struct namelist *nl, *prev; - register int n; - char pathbuf[BUFSIZ]; - char *argvbuf[GAVSIZ]; - - if (debug) { - printf("expand(%p, %d)\nlist = ", list, wh); - prnames(list); - } - - if (wh == 0) { - register char *cp; - - for (nl = list; nl != NULL; nl = nl->n_next) - for (cp = nl->n_name; *cp; cp++) - *cp = *cp & TRIM; - return(list); - } - - which = wh; - path = tpathp = pathp = pathbuf; - *pathp = '\0'; - lastpathp = &path[sizeof pathbuf - 2]; - tilde = ""; - eargc = 0; - eargv = sortbase = argvbuf; - *eargv = 0; - nleft = NCARGS - 4; - /* - * Walk the name list and expand names into eargv[]; - */ - for (nl = list; nl != NULL; nl = nl->n_next) - expstr(nl->n_name); - /* - * Take expanded list of names from eargv[] and build a new list. - */ - list = prev = NULL; - for (n = 0; n < eargc; n++) { - nl = makenl(NULL); - nl->n_name = eargv[n]; - if (prev == NULL) - list = prev = nl; - else { - prev->n_next = nl; - prev = nl; - } - } - if (debug) { - printf("expanded list = "); - prnames(list); - } - return(list); -} - -static void -expstr(s) - char *s; -{ - register char *cp, *cp1; - register struct namelist *tp; - char *tail; - char buf[BUFSIZ]; - int savec, oeargc; - extern char homedir[]; - - if (s == NULL || *s == '\0') - return; - - if ((which & E_VARS) && (cp = index(s, '$')) != NULL) { - *cp++ = '\0'; - if (*cp == '\0') { - yyerror("no variable name after '$'"); - return; - } - if (*cp == LC) { - cp++; - if ((tail = index(cp, RC)) == NULL) { - yyerror("unmatched '{'"); - return; - } - *tail++ = savec = '\0'; - if (*cp == '\0') { - yyerror("no variable name after '$'"); - return; - } - } else { - tail = cp + 1; - savec = *tail; - *tail = '\0'; - } - tp = lookup(cp, NULL, 0); - if (savec != '\0') - *tail = savec; - if (tp != NULL) { - for (; tp != NULL; tp = tp->n_next) { - snprintf(buf, sizeof(buf), - "%s%s%s", s, tp->n_name, tail); - expstr(buf); - } - return; - } - snprintf(buf, sizeof(buf), "%s%s", s, tail); - expstr(buf); - return; - } - if ((which & ~E_VARS) == 0 || !strcmp(s, "{") || !strcmp(s, "{}")) { - Cat(s, ""); - sort(); - return; - } - if (*s == '~') { - cp = ++s; - if (*cp == '\0' || *cp == '/') { - tilde = "~"; - cp1 = homedir; - } else { - tilde = cp1 = buf; - *cp1++ = '~'; - do - *cp1++ = *cp++; - while (*cp && *cp != '/'); - *cp1 = '\0'; - if (pw == NULL || strcmp(pw->pw_name, buf+1) != 0) { - if ((pw = getpwnam(buf+1)) == NULL) { - strcat(buf, ": unknown user name"); - yyerror(buf+1); - return; - } - } - cp1 = pw->pw_dir; - s = cp; - } - for (cp = path; (*cp++ = *cp1++); ) - ; - tpathp = pathp = cp - 1; - } else { - tpathp = pathp = path; - tilde = ""; - } - *pathp = '\0'; - if (!(which & E_SHELL)) { - if (which & E_TILDE) - Cat(path, s); - else - Cat(tilde, s); - sort(); - return; - } - oeargc = eargc; - expany = 0; - expsh(s); - if (eargc == oeargc) - Cat(s, ""); /* "nonomatch" is set */ - sort(); -} - -static int -argcmp(a1, a2) - const void *a1, *a2; -{ - - return (strcmp(*(char **)a1, *(char **)a2)); -} - -/* - * If there are any Shell meta characters in the name, - * expand into a list, after searching directory - */ -static void -expsh(s) - char *s; -{ - register char *cp; - register char *spathp, *oldcp; - struct stat stb; - - spathp = pathp; - cp = s; - while (!any(*cp, shchars)) { - if (*cp == '\0') { - if (!expany || stat(path, &stb) >= 0) { - if (which & E_TILDE) - Cat(path, ""); - else - Cat(tilde, tpathp); - } - goto endit; - } - addpath(*cp++); - } - oldcp = cp; - while (cp > s && *cp != '/') - cp--, pathp--; - if (*cp == '/') - cp++, pathp++; - *pathp = '\0'; - if (*oldcp == '{') { - execbrc(cp, NULL); - return; - } - matchdir(cp); -endit: - pathp = spathp; - *pathp = '\0'; -} - -static void -matchdir(pattern) - char *pattern; -{ - struct stat stb; - register struct dirent *dp; - DIR *dirp; - - dirp = opendir(path); - if (dirp == NULL) { - if (expany) - return; - goto patherr2; - } - if (fstat(dirp->dd_fd, &stb) < 0) - goto patherr1; - if (!ISDIR(stb.st_mode)) { - errno = ENOTDIR; - goto patherr1; - } - while ((dp = readdir(dirp)) != NULL) - if (match(dp->d_name, pattern)) { - if (which & E_TILDE) - Cat(path, dp->d_name); - else { - strcpy(pathp, dp->d_name); - Cat(tilde, tpathp); - *pathp = '\0'; - } - } - closedir(dirp); - return; - -patherr1: - closedir(dirp); -patherr2: - strcat(path, ": "); - strcat(path, strerror(errno)); - yyerror(path); -} - -static int -execbrc(p, s) - char *p, *s; -{ - char restbuf[BUFSIZ + 2]; - register char *pe, *pm, *pl; - int brclev = 0; - char *lm, savec, *spathp; - - for (lm = restbuf; *p != '{'; *lm++ = *p++) - continue; - for (pe = ++p; *pe; pe++) - switch (*pe) { - - case '{': - brclev++; - continue; - - case '}': - if (brclev == 0) - goto pend; - brclev--; - continue; - - case '[': - for (pe++; *pe && *pe != ']'; pe++) - continue; - if (!*pe) - yyerror("Missing ']'"); - continue; - } -pend: - if (brclev || !*pe) { - yyerror("Missing '}'"); - return (0); - } - for (pl = pm = p; pm <= pe; pm++) - switch (*pm & (QUOTE|TRIM)) { - - case '{': - brclev++; - continue; - - case '}': - if (brclev) { - brclev--; - continue; - } - goto doit; - - case ',': - if (brclev) - continue; -doit: - savec = *pm; - *pm = 0; - strcpy(lm, pl); - strcat(restbuf, pe + 1); - *pm = savec; - if (s == 0) { - spathp = pathp; - expsh(restbuf); - pathp = spathp; - *pathp = 0; - } else if (amatch(s, restbuf)) - return (1); - sort(); - pl = pm + 1; - continue; - - case '[': - for (pm++; *pm && *pm != ']'; pm++) - continue; - if (!*pm) - yyerror("Missing ']'"); - continue; - } - return (0); -} - -static int -match(s, p) - char *s, *p; -{ - register int c; - register char *sentp; - char sexpany = expany; - - if (*s == '.' && *p != '.') - return (0); - sentp = entp; - entp = s; - c = amatch(s, p); - entp = sentp; - expany = sexpany; - return (c); -} - -static int -amatch(s, p) - register char *s, *p; -{ - register int scc; - int ok, lc; - char *spathp; - struct stat stb; - int c, cc; - - expany = 1; - for (;;) { - scc = *s++ & TRIM; - switch (c = *p++) { - - case '{': - return (execbrc(p - 1, s - 1)); - - case '[': - ok = 0; - lc = 077777; - while ((cc = *p++)) { - if (cc == ']') { - if (ok) - break; - return (0); - } - if (cc == '-') { - if (lc <= scc && scc <= *p++) - ok++; - } else - if (scc == (lc = cc)) - ok++; - } - if (cc == 0) { - yyerror("Missing ']'"); - return (0); - } - continue; - - case '*': - if (!*p) - return (1); - if (*p == '/') { - p++; - goto slash; - } - for (s--; *s; s++) - if (amatch(s, p)) - return (1); - return (0); - - case '\0': - return (scc == '\0'); - - default: - if ((c & TRIM) != scc) - return (0); - continue; - - case '?': - if (scc == '\0') - return (0); - continue; - - case '/': - if (scc) - return (0); -slash: - s = entp; - spathp = pathp; - while (*s) - addpath(*s++); - addpath('/'); - if (stat(path, &stb) == 0 && ISDIR(stb.st_mode)) { - if (*p == '\0') { - if (which & E_TILDE) - Cat(path, ""); - else - Cat(tilde, tpathp); - } else - expsh(p); - } - pathp = spathp; - *pathp = '\0'; - return (0); - } - } -} - -static int -smatch(s, p) - register char *s, *p; -{ - register int scc; - int ok, lc; - int c, cc; - - for (;;) { - scc = *s++ & TRIM; - switch (c = *p++) { - - case '[': - ok = 0; - lc = 077777; - while ((cc = *p++)) { - if (cc == ']') { - if (ok) - break; - return (0); - } - if (cc == '-') { - if (lc <= scc && scc <= *p++) - ok++; - } else - if (scc == (lc = cc)) - ok++; - } - if (cc == 0) { - yyerror("Missing ']'"); - return (0); - } - continue; - - case '*': - if (!*p) - return (1); - for (s--; *s; s++) - if (smatch(s, p)) - return (1); - return (0); - - case '\0': - return (scc == '\0'); - - default: - if ((c & TRIM) != scc) - return (0); - continue; - - case '?': - if (scc == 0) - return (0); - continue; - - } - } -} - -static void -Cat(s1, s2) - register char *s1, *s2; -{ - int len = strlen(s1) + strlen(s2) + 1; - register char *s; - - nleft -= len; - if (nleft <= 0 || ++eargc >= GAVSIZ) - yyerror("Arguments too long"); - eargv[eargc] = 0; - eargv[eargc - 1] = s = malloc(len); - if (s == NULL) - fatal("ran out of memory\n"); - while ((*s++ = *s1++ & TRIM)) - ; - s--; - while ((*s++ = *s2++ & TRIM)) - ; -} - -static void -addpath(c) - int c; -{ - - if (pathp >= lastpathp) - yyerror("Pathname too long"); - else { - *pathp++ = c & TRIM; - *pathp = '\0'; - } -} - -/* - * Expand file names beginning with `~' into the - * user's home directory path name. Return a pointer in buf to the - * part corresponding to `file'. - */ -char * -exptilde(buf, file, maxlen) - char buf[]; - register char *file; - int maxlen; -{ - register char *s1, *s2, *s3; - extern char homedir[]; - - if (strlen(file) >= maxlen) - return(NULL); - if (*file != '~') { - strcpy(buf, file); - return(buf); - } - if (*++file == '\0') { - s2 = homedir; - s3 = NULL; - } else if (*file == '/') { - s2 = homedir; - s3 = file; - } else { - s3 = file; - while (*s3 && *s3 != '/') - s3++; - if (*s3 == '/') - *s3 = '\0'; - else - s3 = NULL; - if (pw == NULL || strcmp(pw->pw_name, file) != 0) { - if ((pw = getpwnam(file)) == NULL) { - error("%s: unknown user name\n", file); - if (s3 != NULL) - *s3 = '/'; - return(NULL); - } - } - if (s3 != NULL) - *s3 = '/'; - s2 = pw->pw_dir; - } - for (s1 = buf; (*s1++ = *s2++) && s1 < buf+maxlen; ) - ; - s2 = --s1; - if (s3 != NULL && s1 < buf+maxlen) { - s2++; - while ((*s1++ = *s3++) && s1 < buf+maxlen) - ; - } - if (s1 == buf+maxlen) - return(NULL); - return(s2); -} diff --git a/usr.bin/rdist/gram.y b/usr.bin/rdist/gram.y deleted file mode 100644 index bd77901..0000000 --- a/usr.bin/rdist/gram.y +++ /dev/null @@ -1,523 +0,0 @@ -%{ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)gram.y 8.1 (Berkeley) 6/9/93"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include "defs.h" -#include <sys/types.h> -#include <regex.h> -#include <limits.h> - -struct cmd *cmds = NULL; -struct cmd *last_cmd; -struct namelist *last_n; -struct subcmd *last_sc; - -static char *makestr __P((char *)); - -%} - -%term EQUAL 1 -%term LP 2 -%term RP 3 -%term SM 4 -%term ARROW 5 -%term COLON 6 -%term DCOLON 7 -%term NAME 8 -%term STRING 9 -%term INSTALL 10 -%term NOTIFY 11 -%term EXCEPT 12 -%term PATTERN 13 -%term SPECIAL 14 -%term OPTION 15 - -%union { - int intval; - char *string; - struct subcmd *subcmd; - struct namelist *namel; -} - -%type <intval> OPTION, options -%type <string> NAME, STRING -%type <subcmd> INSTALL, NOTIFY, EXCEPT, PATTERN, SPECIAL, cmdlist, cmd -%type <namel> namelist, names, opt_namelist - -%% - -file: /* VOID */ - | file command - ; - -command: NAME EQUAL namelist = { - (void) lookup($1, INSERT, $3); - } - | namelist ARROW namelist cmdlist = { - insert(NULL, $1, $3, $4); - } - | NAME COLON namelist ARROW namelist cmdlist = { - insert($1, $3, $5, $6); - } - | namelist DCOLON NAME cmdlist = { - append(NULL, $1, $3, $4); - } - | NAME COLON namelist DCOLON NAME cmdlist = { - append($1, $3, $5, $6); - } - | error - ; - -namelist: NAME = { - $$ = makenl($1); - } - | LP names RP = { - $$ = $2; - } - ; - -names: /* VOID */ { - $$ = last_n = NULL; - } - | names NAME = { - if (last_n == NULL) - $$ = last_n = makenl($2); - else { - last_n->n_next = makenl($2); - last_n = last_n->n_next; - $$ = $1; - } - } - ; - -cmdlist: /* VOID */ { - $$ = last_sc = NULL; - } - | cmdlist cmd = { - if (last_sc == NULL) - $$ = last_sc = $2; - else { - last_sc->sc_next = $2; - last_sc = $2; - $$ = $1; - } - } - ; - -cmd: INSTALL options opt_namelist SM = { - register struct namelist *nl; - - $1->sc_options = $2 | options; - if ($3 != NULL) { - nl = expand($3, E_VARS); - if (nl) { - if (nl->n_next != NULL) - yyerror("only one name allowed\n"); - $1->sc_name = nl->n_name; - free(nl); - } else - $1->sc_name = NULL; - } - $$ = $1; - } - | NOTIFY namelist SM = { - if ($2 != NULL) - $1->sc_args = expand($2, E_VARS); - $$ = $1; - } - | EXCEPT namelist SM = { - if ($2 != NULL) - $1->sc_args = expand($2, E_ALL); - $$ = $1; - } - | PATTERN namelist SM = { - struct namelist *nl; - regex_t rx; - int val; - char errbuf[_POSIX2_LINE_MAX]; - - for (nl = $2; nl != NULL; nl = nl->n_next) { - if ((val = regcomp(&rx, nl->n_name, - REG_EXTENDED))) { - regerror(val, &rx, errbuf, - sizeof errbuf); - yyerror(errbuf); - } - regfree(&rx); - } - $1->sc_args = expand($2, E_VARS); - $$ = $1; - } - | SPECIAL opt_namelist STRING SM = { - if ($2 != NULL) - $1->sc_args = expand($2, E_ALL); - $1->sc_name = $3; - $$ = $1; - } - ; - -options: /* VOID */ = { - $$ = 0; - } - | options OPTION = { - $$ |= $2; - } - ; - -opt_namelist: /* VOID */ = { - $$ = NULL; - } - | namelist = { - $$ = $1; - } - ; - -%% - -int yylineno = 1; -extern FILE *fin; - -int -yylex() -{ - static char yytext[INMAX]; - register int c; - register char *cp1, *cp2; - static char quotechars[] = "[]{}*?$"; - -again: - switch (c = getc(fin)) { - case EOF: /* end of file */ - return(0); - - case '#': /* start of comment */ - while ((c = getc(fin)) != EOF && c != '\n') - ; - if (c == EOF) - return(0); - case '\n': - yylineno++; - case ' ': - case '\t': /* skip blanks */ - goto again; - - case '=': /* EQUAL */ - return(EQUAL); - - case '(': /* LP */ - return(LP); - - case ')': /* RP */ - return(RP); - - case ';': /* SM */ - return(SM); - - case '-': /* -> */ - if ((c = getc(fin)) == '>') - return(ARROW); - ungetc(c, fin); - c = '-'; - break; - - case '"': /* STRING */ - cp1 = yytext; - cp2 = &yytext[INMAX - 1]; - for (;;) { - if (cp1 >= cp2) { - yyerror("command string too long\n"); - break; - } - c = getc(fin); - if (c == EOF || c == '"') - break; - if (c == '\\') { - if ((c = getc(fin)) == EOF) { - *cp1++ = '\\'; - break; - } - } - if (c == '\n') { - yylineno++; - c = ' '; /* can't send '\n' */ - } - *cp1++ = c; - } - if (c != '"') - yyerror("missing closing '\"'\n"); - *cp1 = '\0'; - yylval.string = makestr(yytext); - return(STRING); - - case ':': /* : or :: */ - if ((c = getc(fin)) == ':') - return(DCOLON); - ungetc(c, fin); - return(COLON); - } - cp1 = yytext; - cp2 = &yytext[INMAX - 1]; - for (;;) { - if (cp1 >= cp2) { - yyerror("input line too long\n"); - break; - } - if (c == '\\') { - if ((c = getc(fin)) != EOF) { - if (any(c, quotechars)) - c |= QUOTE; - } else { - *cp1++ = '\\'; - break; - } - } - *cp1++ = c; - c = getc(fin); - if (c == EOF || any(c, " \"'\t()=;:\n")) { - ungetc(c, fin); - break; - } - } - *cp1 = '\0'; - if (yytext[0] == '-' && yytext[2] == '\0') { - switch (yytext[1]) { - case 'b': - yylval.intval = COMPARE; - return(OPTION); - - case 'R': - yylval.intval = REMOVE; - return(OPTION); - - case 'v': - yylval.intval = VERIFY; - return(OPTION); - - case 'w': - yylval.intval = WHOLE; - return(OPTION); - - case 'y': - yylval.intval = YOUNGER; - return(OPTION); - - case 'h': - yylval.intval = FOLLOW; - return(OPTION); - - case 'i': - yylval.intval = IGNLNKS; - return(OPTION); - } - } - if (!strcmp(yytext, "install")) - c = INSTALL; - else if (!strcmp(yytext, "notify")) - c = NOTIFY; - else if (!strcmp(yytext, "except")) - c = EXCEPT; - else if (!strcmp(yytext, "except_pat")) - c = PATTERN; - else if (!strcmp(yytext, "special")) - c = SPECIAL; - else { - yylval.string = makestr(yytext); - return(NAME); - } - yylval.subcmd = makesubcmd(c); - return(c); -} - -int -any(c, str) - register int c; - register char *str; -{ - while (*str) - if (c == *str++) - return(1); - return(0); -} - -/* - * Insert or append ARROW command to list of hosts to be updated. - */ -void -insert(label, files, hosts, subcmds) - char *label; - struct namelist *files, *hosts; - struct subcmd *subcmds; -{ - register struct cmd *c, *prev, *nc; - register struct namelist *h, *next_h; - - files = expand(files, E_VARS|E_SHELL); - hosts = expand(hosts, E_ALL); - for (h = hosts; h != NULL; next_h = h->n_next, free(h), h = next_h) { - /* - * Search command list for an update to the same host. - */ - for (prev = NULL, c = cmds; c!=NULL; prev = c, c = c->c_next) { - if (strcmp(c->c_name, h->n_name) == 0) { - do { - prev = c; - c = c->c_next; - } while (c != NULL && - strcmp(c->c_name, h->n_name) == 0); - break; - } - } - /* - * Insert new command to update host. - */ - nc = ALLOC(cmd); - if (nc == NULL) - fatal("ran out of memory\n"); - nc->c_type = ARROW; - nc->c_name = h->n_name; - nc->c_label = label; - nc->c_files = files; - nc->c_cmds = subcmds; - nc->c_next = c; - if (prev == NULL) - cmds = nc; - else - prev->c_next = nc; - /* update last_cmd if appending nc to cmds */ - if (c == NULL) - last_cmd = nc; - } -} - -/* - * Append DCOLON command to the end of the command list since these are always - * executed in the order they appear in the distfile. - */ -void -append(label, files, stamp, subcmds) - char *label; - struct namelist *files; - char *stamp; - struct subcmd *subcmds; -{ - register struct cmd *c; - - c = ALLOC(cmd); - if (c == NULL) - fatal("ran out of memory\n"); - c->c_type = DCOLON; - c->c_name = stamp; - c->c_label = label; - c->c_files = expand(files, E_ALL); - c->c_cmds = subcmds; - c->c_next = NULL; - if (cmds == NULL) - cmds = last_cmd = c; - else { - last_cmd->c_next = c; - last_cmd = c; - } -} - -/* - * Error printing routine in parser. - */ -void -yyerror(s) - char *s; -{ - ++nerrs; - fflush(stdout); - fprintf(stderr, "rdist: line %d: %s\n", yylineno, s); -} - -/* - * Return a copy of the string. - */ -static char * -makestr(str) - char *str; -{ - register char *cp, *s; - - str = cp = malloc(strlen(s = str) + 1); - if (cp == NULL) - fatal("ran out of memory\n"); - while ((*cp++ = *s++)) - ; - return(str); -} - -/* - * Allocate a namelist structure. - */ -struct namelist * -makenl(name) - char *name; -{ - register struct namelist *nl; - - nl = ALLOC(namelist); - if (nl == NULL) - fatal("ran out of memory\n"); - nl->n_name = name; - nl->n_next = NULL; - return(nl); -} - -/* - * Make a sub command for lists of variables, commands, etc. - */ -struct subcmd * -makesubcmd(type) - int type; -{ - register struct subcmd *sc; - - sc = ALLOC(subcmd); - if (sc == NULL) - fatal("ran out of memory\n"); - sc->sc_type = type; - sc->sc_args = NULL; - sc->sc_next = NULL; - sc->sc_name = NULL; - return(sc); -} diff --git a/usr.bin/rdist/lookup.c b/usr.bin/rdist/lookup.c deleted file mode 100644 index b97ce3f..0000000 --- a/usr.bin/rdist/lookup.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)lookup.c 8.1 (Berkeley) 6/9/93"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include "defs.h" - - /* symbol types */ -#define VAR 1 -#define CONST 2 - -struct syment { - int s_type; - char *s_name; - struct namelist *s_value; - struct syment *s_next; -}; - -static struct syment *hashtab[HASHSIZE]; - -/* - * Define a variable from a command line argument. - */ -void -define(name) - char *name; -{ - register char *cp, *s; - register struct namelist *nl; - struct namelist *value = NULL; - - if (debug) - printf("define(%s)\n", name); - - cp = index(name, '='); - if (cp == NULL) - value = NULL; - else if (cp[1] == '\0') { - *cp = '\0'; - value = NULL; - } else if (cp[1] != '(') { - *cp++ = '\0'; - value = makenl(cp); - } else { - nl = NULL; - *cp++ = '\0'; - do - cp++; - while (*cp == ' ' || *cp == '\t'); - for (s = cp; ; s++) { - switch (*s) { - case ')': - *s = '\0'; - case '\0': - break; - case ' ': - case '\t': - *s++ = '\0'; - while (*s == ' ' || *s == '\t') - s++; - if (*s == ')') - *s = '\0'; - break; - default: - continue; - } - if (nl == NULL) - value = nl = makenl(cp); - else { - nl->n_next = makenl(cp); - nl = nl->n_next; - } - if (*s == '\0') - break; - cp = s; - } - } - (void) lookup(name, REPLACE, value); -} - -/* - * Lookup name in the table and return a pointer to it. - * LOOKUP - just do lookup, return NULL if not found. - * INSERT - insert name with value, error if already defined. - * REPLACE - insert or replace name with value. - */ - -struct namelist * -lookup(name, action, value) - char *name; - int action; - struct namelist *value; -{ - register unsigned n; - register char *cp; - register struct syment *s; - char buf[BUFSIZ]; - - if (debug) - printf("lookup(%s, %d, %p)\n", name, action, value); - - n = 0; - for (cp = name; *cp; ) - n += *cp++; - n %= HASHSIZE; - - for (s = hashtab[n]; s != NULL; s = s->s_next) { - if (strcmp(name, s->s_name)) - continue; - if (action != LOOKUP) { - if (action != INSERT || s->s_type != CONST) { - (void)snprintf(buf, sizeof(buf), - "%s redefined", name); - yyerror(buf); - } - } - return(s->s_value); - } - - if (action == LOOKUP) { - (void)snprintf(buf, sizeof(buf), "%s undefined", name); - yyerror(buf); - return(NULL); - } - - s = ALLOC(syment); - if (s == NULL) - fatal("ran out of memory\n"); - s->s_next = hashtab[n]; - hashtab[n] = s; - s->s_type = action == INSERT ? VAR : CONST; - s->s_name = name; - s->s_value = value; - return(value); -} diff --git a/usr.bin/rdist/main.c b/usr.bin/rdist/main.c deleted file mode 100644 index d4d94a2..0000000 --- a/usr.bin/rdist/main.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1983, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#if 0 -static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/9/93"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include "defs.h" - -#define NHOSTS 100 - -/* - * Remote distribution program. - */ - -char *distfile = NULL; -#define _RDIST_TMP "/rdistXXXXXX" -char tempfile[sizeof _PATH_TMP + sizeof _RDIST_TMP + 1]; -char *tempname; - -int debug; /* debugging flag */ -int nflag; /* NOP flag, just print commands without executing */ -int qflag; /* Quiet. Don't print messages */ -int options; /* global options */ -int iamremote; /* act as remote server for transfering files */ - -FILE *fin = NULL; /* input file pointer */ -int rem = -1; /* file descriptor to remote source/sink process */ -char host[32]; /* host name */ -int nerrs; /* number of errors while sending/receiving */ -char user[10]; /* user's name */ -char homedir[128]; /* user's home directory */ -int userid; /* user's user ID */ -int groupid; /* user's group ID */ -char *path_rsh = _PATH_RSH; /* rsh (or equiv command) path */ - -struct passwd *pw; /* pointer to static area used by getpwent */ -struct group *gr; /* pointer to static area used by getgrent */ - -static void usage __P((void)); -static void docmdargs __P((int, char *[])); - -int -main(argc, argv) - int argc; - char *argv[]; -{ - register char *arg; - int cmdargs = 0; - char *dhosts[NHOSTS], **hp = dhosts; - - pw = getpwuid(userid = getuid()); - if (pw == NULL) { - fprintf(stderr, "%s: Who are you?\n", argv[0]); - exit(1); - } - strcpy(user, pw->pw_name); - strcpy(homedir, pw->pw_dir); - groupid = pw->pw_gid; - gethostname(host, sizeof(host)); - strcpy(tempfile, _PATH_TMP); - strcat(tempfile, _RDIST_TMP); - if ((tempname = rindex(tempfile, '/')) != 0) - tempname++; - else - tempname = tempfile; - - while (--argc > 0) { - if ((arg = *++argv)[0] != '-') - break; - if (!strcmp(arg, "-Server")) - iamremote++; - else while (*++arg) - switch (*arg) { - case 'P': - if (--argc <= 0) - usage(); - path_rsh = *++argv; - break; - - case 'f': - if (--argc <= 0) - usage(); - distfile = *++argv; - if (distfile[0] == '-' && distfile[1] == '\0') - fin = stdin; - break; - - case 'm': - if (--argc <= 0) - usage(); - if (hp >= &dhosts[NHOSTS-2]) { - fprintf(stderr, "rdist: too many destination hosts\n"); - exit(1); - } - *hp++ = *++argv; - break; - - case 'd': - if (--argc <= 0) - usage(); - define(*++argv); - break; - - case 'D': - debug++; - break; - - case 'c': - cmdargs++; - break; - - case 'n': - if (options & VERIFY) { - printf("rdist: -n overrides -v\n"); - options &= ~VERIFY; - } - nflag++; - break; - - case 'q': - qflag++; - break; - - case 'b': - options |= COMPARE; - break; - - case 'R': - options |= REMOVE; - break; - - case 'v': - if (nflag) { - printf("rdist: -n overrides -v\n"); - break; - } - options |= VERIFY; - break; - - case 'w': - options |= WHOLE; - break; - - case 'y': - options |= YOUNGER; - break; - - case 'h': - options |= FOLLOW; - break; - - case 'i': - options |= IGNLNKS; - break; - - default: - usage(); - } - } - *hp = NULL; - - seteuid(userid); - mktemp(tempfile); - - if (iamremote) { - server(); - exit(nerrs != 0); - } - - if (cmdargs) - docmdargs(argc, argv); - else { - if (fin == NULL) { - if(distfile == NULL) { - if((fin = fopen("distfile","r")) == NULL) - fin = fopen("Distfile", "r"); - } else - fin = fopen(distfile, "r"); - if(fin == NULL) { - perror(distfile ? distfile : "distfile"); - exit(1); - } - } - yyparse(); - if (nerrs == 0) - docmds(dhosts, argc, argv); - } - - exit(nerrs != 0); -} - -static void -usage() -{ - printf("%s\n%s\n%s\n", -"usage: rdist [-nqbhirvwyD] [-P /path/to/rsh ] [-f distfile] [-d var=value]", -" [-m host] [file ...]", -" rdist [-nqbhirvwyD] [-P /path/to/rsh ] -c source [...] machine[:dest]"); - exit(1); -} - -/* - * rcp like interface for distributing files. - */ -static void -docmdargs(nargs, args) - int nargs; - char *args[]; -{ - register struct namelist *nl, *prev; - register char *cp; - struct namelist *files = NULL, *hosts; - struct subcmd *cmds; - char *dest; - static struct namelist tnl = { NULL, NULL }; - int i; - - if (nargs < 2) - usage(); - - prev = NULL; - for (i = 0; i < nargs - 1; i++) { - nl = makenl(args[i]); - if (prev == NULL) - files = prev = nl; - else { - prev->n_next = nl; - prev = nl; - } - } - - cp = args[i]; - if ((dest = index(cp, ':')) != NULL) - *dest++ = '\0'; - tnl.n_name = cp; - hosts = expand(&tnl, E_ALL); - if (nerrs) - exit(1); - - if (dest == NULL || *dest == '\0') - cmds = NULL; - else { - cmds = makesubcmd(INSTALL); - cmds->sc_options = options; - cmds->sc_name = dest; - } - - if (debug) { - printf("docmdargs()\nfiles = "); - prnames(files); - printf("hosts = "); - prnames(hosts); - } - insert(NULL, files, hosts, cmds); - docmds(NULL, 0, NULL); -} - -/* - * Print a list of NAME blocks (mostly for debugging). - */ -void -prnames(nl) - register struct namelist *nl; -{ - printf("( "); - while (nl != NULL) { - printf("%s ", nl->n_name); - nl = nl->n_next; - } - printf(")\n"); -} - -#if __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif - -void -#if __STDC__ -warn(const char *fmt, ...) -#else -warn(fmt, va_alist) - char *fmt; - va_dcl -#endif -{ - extern int yylineno; - va_list ap; -#if __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - (void)fprintf(stderr, "rdist: line %d: Warning: ", yylineno); - (void)vfprintf(stderr, fmt, ap); - (void)fprintf(stderr, "\n"); - va_end(ap); -} diff --git a/usr.bin/rdist/pathnames.h b/usr.bin/rdist/pathnames.h deleted file mode 100644 index c772539..0000000 --- a/usr.bin/rdist/pathnames.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)pathnames.h 8.1 (Berkeley) 6/9/93 - */ - -#include <paths.h> - -#define _PATH_RDIST "rdist" -#define _PATH_RSH "/usr/bin/rsh" diff --git a/usr.bin/rdist/rshrcmd.c b/usr.bin/rdist/rshrcmd.c deleted file mode 100644 index c747cc6..0000000 --- a/usr.bin/rdist/rshrcmd.c +++ /dev/null @@ -1,119 +0,0 @@ - -/* - * This is an rcmd() replacement originally by - * Chris Siebenmann <cks@utcc.utoronto.ca>. - */ - -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include "defs.h" - -#if !defined(DIRECT_RCMD) - -#include <sys/socket.h> -#include <sys/wait.h> -#include <signal.h> -#include <netdb.h> - -static char * -xbasename(s) - char *s; -{ - char *ret; - - ret = strrchr(s, '/'); - if (ret && ret[1]) - return (ret + 1); - return s; -} - - -/* - * This is a replacement rcmd() function that uses the rsh(1c) - * program in place of a direct rcmd() function call so as to - * avoid having to be root. - */ -int -rshrcmd(ahost, port, luser, ruser, cmd, fd2p) - char **ahost; - u_short port; - char *luser, *ruser, *cmd; - int *fd2p; -{ - int cpid; - struct hostent *hp; - int sp[2]; - - /* insure that we are indeed being used as we thought. */ - if (fd2p != 0) - return -1; - /* validate remote hostname. */ - hp = gethostbyname(*ahost); - if (hp == 0) { - error("%s: unknown host", *ahost); - return -1; - } - /* *ahost = hp->h_name; *//* This makes me nervous. */ - - /* get a socketpair we'll use for stdin and stdout. */ - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) < 0) { - error("socketpair(AF_UNIX, SOCK_STREAM, 0) failed: %s.", - strerror(errno)); - return -1; - } - - cpid = fork(); - if (cpid < 0) { - error("fork failed: %s.", strerror(errno)); - return -1; /* error. */ - } - if (cpid == 0) { - /* child. we use sp[1] to be stdin/stdout, and close - sp[0]. */ - (void) close(sp[0]); - if (dup2(sp[1], 0) < 0 || dup2(0,1) < 0) { - error("dup2 failed: %s.", strerror(errno)); - _exit(255); - } - /* fork again to lose parent. */ - cpid = fork(); - if (cpid < 0) { - error("fork to lose parent failed: %s.", strerror(errno)); - _exit(255); - } - if (cpid > 0) - _exit(0); - /* in grandchild here. */ - - /* - * If we are rdist'ing to "localhost" as the same user - * as we are, then avoid running remote shell for efficiency. - */ - if (strcmp(*ahost, "localhost") == 0 && - strcmp(luser, ruser) == 0) { - execlp(_PATH_BSHELL, xbasename(_PATH_BSHELL), "-c", - cmd, (char *) NULL); - error("execlp %s failed: %s.", _PATH_BSHELL, strerror(errno)); - } else { - execlp(path_rsh, xbasename(path_rsh), - *ahost, "-l", ruser, cmd, (char *) NULL); - error("execlp %s failed: %s.", path_rsh, - strerror(errno)); - } - _exit(255); - } - if (cpid > 0) { - /* parent. close sp[1], return sp[0]. */ - (void) close(sp[1]); - /* reap child. */ - (void) wait(0); - return sp[0]; - } - /*NOTREACHED*/ - return (-1); -} - -#endif /* !DIRECT_RCMD */ diff --git a/usr.bin/rdist/server.c b/usr.bin/rdist/server.c deleted file mode 100644 index b2ae4d3..0000000 --- a/usr.bin/rdist/server.c +++ /dev/null @@ -1,1634 +0,0 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)server.c 8.1 (Berkeley) 6/9/93"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include <sys/types.h> - -#include <sys/wait.h> -#include "defs.h" - -#define ack() (void) write(rem, "\0\n", 2) -#define err() (void) write(rem, "\1\n", 2) - -struct linkbuf *ihead = NULL; /* list of files with more than one link */ -char buf[BUFSIZ]; /* general purpose buffer */ -char target[BUFSIZ]; /* target/source directory name */ -char source[BUFSIZ]; /* source directory name */ -char *tp; /* pointer to end of target name */ -char *Tdest; /* pointer to last T dest*/ -int catname; /* cat name to target name */ -char *stp[32]; /* stack of saved tp's for directories */ -int oumask; /* old umask for creating files */ - -extern FILE *lfp; /* log file for mailing changes */ - -static int chkparent __P((char *)); -static void clean __P((char *)); -static void comment __P((char *)); -static void dospecial __P((char *)); -static int fchog __P((int, char *, char *, char *, int)); -static void hardlink __P((char *)); -static void note __P((const char *, ...)); -static void query __P((char *)); -static void recvf __P((char *, int)); -static void removeit __P((struct stat *)); -static int response __P((void)); -static void rmchk __P((int)); -static struct linkbuf * - savelink __P((struct stat *)); -static void sendf __P((char *, int)); -static int update __P((char *, int, struct stat *)); - -/* - * Server routine to read requests and process them. - * Commands are: - * Tname - Transmit file if out of date - * Vname - Verify if file out of date or not - * Qname - Query if file exists. Return mtime & size if it does. - */ -void -server() -{ - char cmdbuf[BUFSIZ]; - register char *cp; - - signal(SIGHUP, cleanup); - signal(SIGINT, cleanup); - signal(SIGQUIT, cleanup); - signal(SIGTERM, cleanup); - signal(SIGPIPE, cleanup); - - rem = 0; - oumask = umask(0); - (void) snprintf(buf, sizeof(buf), "V%d\n", VERSION); - (void) write(rem, buf, strlen(buf)); - - for (;;) { - cp = cmdbuf; - if (read(rem, cp, 1) <= 0) - return; - if (*cp++ == '\n') { - error("server: expected control record\n"); - continue; - } - do { - if (read(rem, cp, 1) != 1) - cleanup(0); - } while (*cp++ != '\n' && cp < &cmdbuf[BUFSIZ]); - *--cp = '\0'; - cp = cmdbuf; - switch (*cp++) { - case 'T': /* init target file/directory name */ - catname = 1; /* target should be directory */ - goto dotarget; - - case 't': /* init target file/directory name */ - catname = 0; - dotarget: - if (exptilde(target, cp, sizeof(target)) == NULL) - continue; - tp = target; - while (*tp) - tp++; - ack(); - continue; - - case 'R': /* Transfer a regular file. */ - recvf(cp, S_IFREG); - continue; - - case 'D': /* Transfer a directory. */ - recvf(cp, S_IFDIR); - continue; - - case 'K': /* Transfer symbolic link. */ - recvf(cp, S_IFLNK); - continue; - - case 'k': /* Transfer hard link. */ - hardlink(cp); - continue; - - case 'E': /* End. (of directory) */ - *tp = '\0'; - if (catname <= 0) { - error("server: too many 'E's\n"); - continue; - } - tp = stp[--catname]; - *tp = '\0'; - ack(); - continue; - - case 'C': /* Clean. Cleanup a directory */ - clean(cp); - continue; - - case 'Q': /* Query. Does the file/directory exist? */ - query(cp); - continue; - - case 'S': /* Special. Execute commands */ - dospecial(cp); - continue; - -#ifdef notdef - /* - * These entries are reserved but not currently used. - * The intent is to allow remote hosts to have master copies. - * Currently, only the host rdist runs on can have masters. - */ - case 'X': /* start a new list of files to exclude */ - except = bp = NULL; - case 'x': /* add name to list of files to exclude */ - if (*cp == '\0') { - ack(); - continue; - } - if (*cp == '~') { - if (exptilde(buf, cp, sizeof(buf)) == NULL) - continue; - cp = buf; - } - if (bp == NULL) - except = bp = expand(makeblock(NAME, cp), E_VARS); - else - bp->b_next = expand(makeblock(NAME, cp), E_VARS); - while (bp->b_next != NULL) - bp = bp->b_next; - ack(); - continue; - - case 'I': /* Install. Transfer file if out of date. */ - opts = 0; - while (*cp >= '0' && *cp <= '7') - opts = (opts << 3) | (*cp++ - '0'); - if (*cp++ != ' ') { - error("server: options not delimited\n"); - return; - } - install(cp, opts); - continue; - - case 'L': /* Log. save message in log file */ - log(lfp, cp); - continue; -#endif - - case '\1': - nerrs++; - continue; - - case '\2': - return; - - default: - error("server: unknown command '%s'\n", cp); - case '\0': - continue; - } - } -} - -/* - * 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). - */ -void -install(src, dest, destdir, opts) - char *src, *dest; - int destdir, opts; -{ - char *rname; - char destcopy[BUFSIZ]; - - if (opts & WHOLE) - source[0] = '\0'; - else - strcpy(source, src); - - if (dest == NULL) { - opts &= ~WHOLE; /* WHOLE mode only useful if renaming */ - dest = src; - } - - if (nflag || debug) { - printf("%s%s%s%s%s %s %s\n", opts & VERIFY ? "verify":"install", - opts & WHOLE ? " -w" : "", - opts & YOUNGER ? " -y" : "", - opts & COMPARE ? " -b" : "", - opts & REMOVE ? " -R" : "", src, dest); - if (nflag) - return; - } - - rname = exptilde(target, src, sizeof(target)); - if (rname == NULL) - return; - tp = target; - while (*tp) - tp++; - /* - * If we are renaming a directory and we want to preserve - * the directory heirarchy (-w), we must strip off the leading - * directory name and preserve the rest. - */ - if (opts & WHOLE) { - while (*rname == '/') - rname++; - destdir = 1; - } else { - rname = rindex(target, '/'); - if (rname == NULL) - rname = target; - else - rname++; - } - if (debug) - printf("target = %s, rname = %s\n", target, rname); - /* - * Pass the destination file/directory name to remote. - */ - (void) snprintf(buf, sizeof(buf), "%c%s\n", destdir ? 'T' : 't', dest); - if (debug) - printf("buf = %s", buf); - (void) write(rem, buf, strlen(buf)); - if (response() < 0) - return; - - /* - * Save the name of the remote target destination if we are - * in WHOLE mode (destdir > 0) or if the source and destination - * are not the same. This info will be used later for maintaining - * hardlink info. - */ - if (destdir || (src && dest && strcmp(src, dest))) { - strcpy(destcopy, dest); - Tdest = destcopy; - } - sendf(rname, opts); - Tdest = 0; -} - -static char * -remotename(pathname, src) - char *pathname; - char *src; -{ - char *cp; - int len; - - cp = pathname; - len = strlen(src); - if (0 == strncmp(pathname, src, len)) - cp += len; - if (*cp == '/') - cp ++; - return(cp); -} - -void -installlink(lp, rname, opts) - struct linkbuf *lp; - char *rname; - int opts; -{ - if (*lp->target == 0) - (void) snprintf(buf, sizeof(buf), "k%o %s %s\n", - opts, lp->pathname, rname); - else - (void) snprintf(buf, sizeof(buf), "k%o %s/%s %s\n", - opts, lp->target, - remotename(lp->pathname, lp->src), rname); - - if (debug) { - printf("lp->src = %s\n", lp->src); - printf("lp->target = %s\n", lp->target); - printf("lp->pathname = %s\n", lp->pathname); - printf("rname = %s\n", rname); - printf("buf = %s", buf); - } - (void) write(rem, buf, strlen(buf)); - (void) response(); -} - -#define protoname() (pw ? pw->pw_name : user) -#define protogroup() (gr ? gr->gr_name : group) -/* - * Transfer the file or directory in target[]. - * rname is the name of the file on the remote host. - */ -static void -sendf(rname, opts) - char *rname; - int opts; -{ - register struct subcmd *sc; - struct stat stb; - int sizerr, f, u, len; - off_t i; - DIR *d; - struct dirent *dp; - char *otp, *cp; - extern struct subcmd *subcmds; - static char user[15], group[15]; - - if (debug) - printf("sendf(%s, %x)\n", rname, opts); - - if (except(target)) - return; - if ((opts & FOLLOW ? stat(target, &stb) : lstat(target, &stb)) < 0) { - error("%s: %s\n", target, strerror(errno)); - return; - } - if ((u = update(rname, opts, &stb)) == 0) { - if ((stb.st_mode & S_IFMT) == S_IFREG && stb.st_nlink > 1) - (void) savelink(&stb); - return; - } - - if (pw == NULL || pw->pw_uid != stb.st_uid) - if ((pw = getpwuid(stb.st_uid)) == NULL) { - log(lfp, "%s: no password entry for uid %d \n", - target, stb.st_uid); - pw = NULL; - (void)snprintf(user, sizeof(user), ":%lu", stb.st_uid); - } - if (gr == NULL || gr->gr_gid != stb.st_gid) - if ((gr = getgrgid(stb.st_gid)) == NULL) { - log(lfp, "%s: no name for group %d\n", - target, stb.st_gid); - gr = NULL; - (void)snprintf(group, sizeof(group), ":%lu", stb.st_gid); - } - if (u == 1) { - if (opts & VERIFY) { - log(lfp, "need to install: %s\n", target); - goto dospecial; - } - log(lfp, "installing: %s\n", target); - opts &= ~(COMPARE|REMOVE); - } - - switch (stb.st_mode & S_IFMT) { - case S_IFDIR: - if ((d = opendir(target)) == NULL) { - error("%s: %s\n", target, strerror(errno)); - return; - } - (void) snprintf(buf, sizeof(buf), "D%o %04o 0 0 %s %s %s\n", - opts, stb.st_mode & 07777, protoname(), protogroup(), - rname); - if (debug) - printf("buf = %s", buf); - (void) write(rem, buf, strlen(buf)); - if (response() < 0) { - closedir(d); - return; - } - - if (opts & REMOVE) - rmchk(opts); - - 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: Name too long\n", target, - dp->d_name); - continue; - } - tp = otp; - *tp++ = '/'; - cp = dp->d_name; - while ((*tp++ = *cp++)) - ; - tp--; - sendf(dp->d_name, opts); - } - closedir(d); - (void) write(rem, "E\n", 2); - (void) response(); - tp = otp; - *tp = '\0'; - return; - - case S_IFLNK: - if (u != 1) - opts |= COMPARE; - if (stb.st_nlink > 1) { - struct linkbuf *lp; - - if ((lp = savelink(&stb)) != NULL) { - installlink(lp, rname, opts); - return; - } - } - (void) snprintf(buf, sizeof(buf), - "K%o %o %qd %ld %s %s %s\n", opts, - stb.st_mode & 07777, stb.st_size, stb.st_mtime, - protoname(), protogroup(), rname); - if (debug) - printf("buf = %s", buf); - (void) write(rem, buf, strlen(buf)); - if (response() < 0) - return; - sizerr = (readlink(target, buf, BUFSIZ - 1) != stb.st_size); - (void) write(rem, buf, stb.st_size); - if (debug) - printf("readlink = %.*s\n", (int)stb.st_size, buf); - goto done; - - case S_IFREG: - break; - - default: - error("%s: not a file or directory\n", target); - return; - } - - if (u == 2) { - if (opts & VERIFY) { - log(lfp, "need to update: %s\n", target); - goto dospecial; - } - log(lfp, "updating: %s\n", target); - } - - if (stb.st_nlink > 1) { - struct linkbuf *lp; - - if ((lp = savelink(&stb)) != NULL) { - installlink(lp, rname, opts); - return; - } - } - - if ((f = open(target, O_RDONLY, 0)) < 0) { - error("%s: %s\n", target, strerror(errno)); - return; - } - (void) snprintf(buf, sizeof(buf), "R%o %o %qd %ld %s %s %s\n", opts, - stb.st_mode & 07777, stb.st_size, stb.st_mtime, - protoname(), protogroup(), rname); - if (debug) - printf("buf = %s", buf); - (void) write(rem, buf, strlen(buf)); - if (response() < 0) { - (void) close(f); - return; - } - sizerr = 0; - for (i = 0; i < stb.st_size; i += BUFSIZ) { - int amt = BUFSIZ; - if (i + amt > stb.st_size) - amt = stb.st_size - i; - if (sizerr == 0 && read(f, buf, amt) != amt) - sizerr = 1; - (void) write(rem, buf, amt); - } - (void) close(f); -done: - if (sizerr) { - error("%s: file changed size\n", target); - err(); - } else - ack(); - f = response(); - if (f < 0 || (f == 0 && (opts & COMPARE))) - return; -dospecial: - for (sc = subcmds; sc != NULL; sc = sc->sc_next) { - if (sc->sc_type != SPECIAL) - continue; - if (sc->sc_args != NULL && !inlist(sc->sc_args, target)) - continue; - log(lfp, "special \"%s\"\n", sc->sc_name); - if (opts & VERIFY) - continue; - (void) snprintf(buf, sizeof(buf), "SFILE=%s;%s\n", target, - sc->sc_name); - if (debug) - printf("buf = %s", buf); - (void) write(rem, buf, strlen(buf)); - while (response() > 0) - ; - } -} - -static struct linkbuf * -savelink(stp) - struct stat *stp; -{ - struct linkbuf *lp; - - for (lp = ihead; lp != NULL; lp = lp->nextp) - if (lp->inum == stp->st_ino && lp->devnum == stp->st_dev) { - lp->count--; - return(lp); - } - lp = (struct linkbuf *) malloc(sizeof(*lp)); - if (lp == NULL) - log(lfp, "out of memory, link information lost\n"); - else { - lp->nextp = ihead; - ihead = lp; - lp->inum = stp->st_ino; - lp->devnum = stp->st_dev; - lp->count = stp->st_nlink - 1; - strcpy(lp->pathname, target); - strcpy(lp->src, source); - if (Tdest) - strcpy(lp->target, Tdest); - else - *lp->target = 0; - } - return(NULL); -} - -/* - * Check to see if file needs to be updated on the remote machine. - * Returns 0 if no update, 1 if remote doesn't exist, 2 if out of date - * and 3 if comparing binaries to determine if out of date. - */ -static int -update(rname, opts, stp) - char *rname; - int opts; - struct stat *stp; -{ - register char *cp, *s; - register off_t size; - register time_t mtime; - - if (debug) - printf("update(%s, %x, %p)\n", rname, opts, stp); - - /* - * Check to see if the file exists on the remote machine. - */ - (void) snprintf(buf, sizeof(buf), "Q%s\n", rname); - if (debug) - printf("buf = %s", buf); - (void) write(rem, buf, strlen(buf)); -again: - cp = s = buf; - do { - if (read(rem, cp, 1) != 1) - lostconn(0); - } while (*cp++ != '\n' && cp < &buf[BUFSIZ]); - - switch (*s++) { - case 'Y': - break; - - case 'N': /* file doesn't exist so install it */ - return(1); - - case '\1': - nerrs++; - if (*s != '\n') { - if (!iamremote) { - fflush(stdout); - (void) write(2, s, cp - s); - } - if (lfp != NULL) - (void) fwrite(s, 1, cp - s, lfp); - } - return(0); - - case '\3': - *--cp = '\0'; - if (lfp != NULL) - log(lfp, "update: note: %s\n", s); - goto again; - - default: - *--cp = '\0'; - error("update: unexpected response '%s'\n", s); - return(0); - } - - if (*s == '\n') - return(2); - - if (opts & COMPARE) - return(3); - - size = 0; - while (isdigit(*s)) - size = size * 10 + (*s++ - '0'); - if (*s++ != ' ') { - error("update: size not delimited\n"); - return(0); - } - mtime = 0; - while (isdigit(*s)) - mtime = mtime * 10 + (*s++ - '0'); - if (*s != '\n') { - error("update: mtime not delimited\n"); - return(0); - } - /* - * File needs to be updated? - */ - if (opts & YOUNGER) { - if (stp->st_mtime == mtime) - return(0); - if (stp->st_mtime < mtime) { - log(lfp, "Warning: %s: remote copy is newer\n", target); - return(0); - } - } else if (stp->st_mtime == mtime && stp->st_size == size) - return(0); - return(2); -} - -/* - * Query. Check to see if file exists. Return one of the following: - * N\n - doesn't exist - * Ysize mtime\n - exists and its a regular file (size & mtime of file) - * Y\n - exists and its a directory or symbolic link - * ^Aerror message\n - */ -static void -query(name) - char *name; -{ - struct stat stb; - - if (catname) - (void) snprintf(tp, sizeof(target) - (tp - target), "/%s", - name); - - if (lstat(target, &stb) < 0) { - if (errno == ENOENT) - (void) write(rem, "N\n", 2); - else - error("%s:%s: %s\n", host, target, strerror(errno)); - *tp = '\0'; - return; - } - - switch (stb.st_mode & S_IFMT) { - case S_IFREG: - (void) snprintf(buf, sizeof(buf), "Y%qd %ld\n", stb.st_size, - stb.st_mtime); - (void) write(rem, buf, strlen(buf)); - break; - - case S_IFLNK: - case S_IFDIR: - (void) write(rem, "Y\n", 2); - break; - - default: - error("%s: not a file or directory\n", name); - break; - } - *tp = '\0'; -} - -static void -recvf(cmd, type) - char *cmd; - int type; -{ - register char *cp; - int f = -1, mode, opts, wrerr, olderrno; - off_t i, size; - time_t mtime; - struct stat stb; - struct timeval tvp[2]; - char *owner, *group; - char new[BUFSIZ]; - extern char *tempname; - - cp = cmd; - opts = 0; - while (*cp >= '0' && *cp <= '7') - opts = (opts << 3) | (*cp++ - '0'); - if (*cp++ != ' ') { - error("recvf: options not delimited\n"); - return; - } - mode = 0; - while (*cp >= '0' && *cp <= '7') - mode = (mode << 3) | (*cp++ - '0'); - if (*cp++ != ' ') { - error("recvf: mode not delimited\n"); - return; - } - size = 0; - while (isdigit(*cp)) - size = size * 10 + (*cp++ - '0'); - if (*cp++ != ' ') { - error("recvf: size not delimited\n"); - return; - } - mtime = 0; - while (isdigit(*cp)) - mtime = mtime * 10 + (*cp++ - '0'); - if (*cp++ != ' ') { - error("recvf: mtime not delimited\n"); - return; - } - owner = cp; - while (*cp && *cp != ' ') - cp++; - if (*cp != ' ') { - error("recvf: owner name not delimited\n"); - return; - } - *cp++ = '\0'; - group = cp; - while (*cp && *cp != ' ') - cp++; - if (*cp != ' ') { - error("recvf: group name not delimited\n"); - return; - } - *cp++ = '\0'; - - if (type == S_IFDIR) { - if (catname >= sizeof(stp)) { - error("%s:%s: too many directory levels\n", - host, target); - return; - } - stp[catname] = tp; - if (catname++) { - *tp++ = '/'; - while ((*tp++ = *cp++)) - ; - tp--; - } - if (opts & VERIFY) { - ack(); - return; - } - if (lstat(target, &stb) == 0) { - if (ISDIR(stb.st_mode)) { - if ((stb.st_mode & 07777) == mode) { - ack(); - return; - } - buf[0] = '\0'; - (void) snprintf(buf + 1, sizeof(buf) - 1, - "%s: Warning: remote mode %o != local mode %o\n", - target, stb.st_mode & 07777, mode); - (void) write(rem, buf, strlen(buf + 1) + 1); - return; - } - errno = ENOTDIR; - } else if ((errno == ENOENT && mkdir(target, mode) == 0) || - (chkparent(target) == 0 && mkdir(target, mode) == 0)) { - if (fchog(-1, target, owner, group, mode) == 0) - ack(); - return; - } - error("%s:%s: %s\n", host, target, strerror(errno)); - tp = stp[--catname]; - *tp = '\0'; - return; - } - - if (catname) - (void) snprintf(tp, sizeof(target) - (tp - target), "/%s", cp); - cp = rindex(target, '/'); - if (cp == NULL) - strcpy(new, tempname); - else if (cp == target) - (void) snprintf(new, sizeof(new), "/%s", tempname); - else { - *cp = '\0'; - (void) snprintf(new, sizeof(new), "%s/%s", target, tempname); - *cp = '/'; - } - - if (type == S_IFLNK) { - int j; - - ack(); - cp = buf; - for (i = 0; i < size; i += j) { - if ((j = read(rem, cp, size - i)) <= 0) - cleanup(0); - cp += j; - } - *cp = '\0'; - if (response() < 0) { - err(); - return; - } - if (symlink(buf, new) < 0) { - if (errno != ENOENT || chkparent(new) < 0 || - symlink(buf, new) < 0) - goto badnew1; - } - mode &= 0777; - if (opts & COMPARE) { - char tbuf[BUFSIZ]; - - if ((i = readlink(target, tbuf, BUFSIZ - 1)) >= 0 && - i == size && strncmp(buf, tbuf, size) == 0) { - (void) unlink(new); - ack(); - return; - } - if (opts & VERIFY) - goto differ; - } - goto fixup; - } - - if ((f = creat(new, mode)) < 0) { - if (errno != ENOENT || chkparent(new) < 0 || - (f = creat(new, mode)) < 0) - goto badnew1; - } - - ack(); - wrerr = 0; - for (i = 0; i < size; i += BUFSIZ) { - int amt = BUFSIZ; - - cp = buf; - if (i + amt > size) - amt = size - i; - do { - int j = read(rem, cp, amt); - - if (j <= 0) { - (void) close(f); - (void) unlink(new); - cleanup(0); - } - amt -= j; - cp += j; - } while (amt > 0); - amt = BUFSIZ; - if (i + amt > size) - amt = size - i; - if (wrerr == 0 && write(f, buf, amt) != amt) { - olderrno = errno; - wrerr++; - } - } - if (response() < 0) { - err(); - goto badnew2; - } - if (wrerr) - goto badnew1; - if (opts & COMPARE) { - FILE *f1, *f2; - int c; - - if ((f1 = fopen(target, "r")) == NULL) - goto badtarget; - if ((f2 = fopen(new, "r")) == NULL) { -badnew1: error("%s:%s: %s\n", host, new, strerror(errno)); - goto badnew2; - } - while ((c = getc(f1)) == getc(f2)) - if (c == EOF) { - (void) fclose(f1); - (void) fclose(f2); - ack(); - goto badnew2; - } - (void) fclose(f1); - (void) fclose(f2); - if (opts & VERIFY) { -differ: buf[0] = '\0'; - (void) snprintf(buf + 1, sizeof(buf) - 1, - "need to update: %s\n",target); - (void) write(rem, buf, strlen(buf + 1) + 1); - goto badnew2; - } - } - - /* - * Set last modified time - */ - tvp[0].tv_sec = time(0); - tvp[0].tv_usec = 0; - tvp[1].tv_sec = mtime; - tvp[1].tv_usec = 0; - if (utimes(new, tvp) < 0) - note("%s: utimes failed %s: %s\n", host, new, strerror(errno)); - - if (fchog(f, new, owner, group, mode) < 0) { -badnew2: if (f != -1) (void) close(f); - (void) unlink(new); - return; - } - (void) close(f); - -fixup: if (rename(new, target) < 0) { -badtarget: error("%s:%s: %s\n", host, target, strerror(errno)); - (void) unlink(new); - return; - } - - if (opts & COMPARE) { - buf[0] = '\0'; - (void) snprintf(buf + 1, sizeof(buf) - 1, - "updated %s\n", target); - (void) write(rem, buf, strlen(buf + 1) + 1); - } else - ack(); -} - -/* - * Creat a hard link to existing file. - */ -static void -hardlink(cmd) - char *cmd; -{ - register char *cp; - struct stat stb; - char *oldname; - int opts, exists = 0; - - cp = cmd; - opts = 0; - while (*cp >= '0' && *cp <= '7') - opts = (opts << 3) | (*cp++ - '0'); - if (*cp++ != ' ') { - error("hardlink: options not delimited\n"); - return; - } - oldname = cp; - while (*cp && *cp != ' ') - cp++; - if (*cp != ' ') { - error("hardlink: oldname name not delimited\n"); - return; - } - *cp++ = '\0'; - - if (catname) { - (void) snprintf(tp, sizeof(target) - (tp - target), "/%s", cp); - } - if (lstat(target, &stb) == 0) { - int mode = stb.st_mode & S_IFMT; - if (mode != S_IFREG && mode != S_IFLNK) { - error("%s:%s: not a regular file\n", host, target); - return; - } - exists = 1; - } - if (chkparent(target) < 0 ) { - error("%s:%s: %s (no parent)\n", - host, target, strerror(errno)); - return; - } - if (exists && (unlink(target) < 0)) { - error("%s:%s: %s (unlink)\n", - host, target, strerror(errno)); - return; - } - if (link(oldname, target) < 0) { - error("%s:can't link %s to %s\n", - host, target, oldname); - return; - } - ack(); -} - -/* - * Check to see if parent directory exists and create one if not. - */ -static int -chkparent(name) - char *name; -{ - register char *cp; - struct stat stb; - - cp = rindex(name, '/'); - if (cp == NULL || cp == name) - return(0); - *cp = '\0'; - if (lstat(name, &stb) < 0) { - if (errno == ENOENT && chkparent(name) >= 0 && - mkdir(name, 0777 & ~oumask) >= 0) { - *cp = '/'; - return(0); - } - } else if (ISDIR(stb.st_mode)) { - *cp = '/'; - return(0); - } - *cp = '/'; - return(-1); -} - -/* - * Change owner, group and mode of file. - */ -static int -fchog(fd, file, owner, group, mode) - int fd; - char *file, *owner, *group; - int mode; -{ - register int i; - int uid, gid; - extern char user[]; - extern int userid; - - uid = userid; - if (userid == 0) { - if (*owner == ':') { - uid = atoi(owner + 1); - } else if (pw == NULL || strcmp(owner, pw->pw_name) != 0) { - if ((pw = getpwnam(owner)) == NULL) { - if (mode & 04000) { - note("%s:%s: unknown login name, clearing setuid", - host, owner); - mode &= ~04000; - uid = 0; - } - } else - uid = pw->pw_uid; - } else - uid = pw->pw_uid; - if (*group == ':') { - gid = atoi(group + 1); - goto ok; - } - } else if ((mode & 04000) && strcmp(user, owner) != 0) - 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 void -rmchk(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) snprintf(buf, sizeof(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) snprintf(tp, sizeof(target) - (tp - target), - "/%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 void -clean(cp) - register char *cp; -{ - DIR *d; - register struct dirent *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) snprintf(buf, sizeof(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) snprintf(cp, sizeof(buf) - 1, - "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 void -removeit(stp) - struct stat *stp; -{ - DIR *d; - struct dirent *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) snprintf(cp, sizeof(buf) - 1, "removed %s\n", target); - (void) write(rem, buf, strlen(cp) + 1); -} - -/* - * Execute a shell command to handle special cases. - */ -static void -dospecial(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> -#endif - -void -#if __STDC__ -log(FILE *fp, const char *fmt, ...) -#else -log(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, ...) -#else -error(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, ...) -#else -fatal(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 int -response() -{ - 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. - */ -void -cleanup(signo) - int signo; -{ - (void) unlink(tempfile); - exit(1); -} - -static void -#if __STDC__ -note(const char *fmt, ...) -#else -note(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 void -comment(s) - char *s; -{ - char c; - - c = '\3'; - write(rem, &c, 1); - write(rem, s, strlen(s)); - c = '\n'; - write(rem, &c, 1); -} |