From: Sascha Wildner Date: Sat, 28 Oct 2017 10:48:15 +0000 (+0200) Subject: Remove the ancient rdist(1) tool along with related periodic(8) scripts. X-Git-Tag: v5.3.0~967 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/f874c792999219ae6eb6188002f67c411bde1d45 Remove the ancient rdist(1) tool along with related periodic(8) scripts. There are substitutes in dports' net/44bsd-rdist and net/rdist6. --- diff --git a/Makefile_upgrade.inc b/Makefile_upgrade.inc index cfd7dab41a..ebc95f35d2 100644 --- a/Makefile_upgrade.inc +++ b/Makefile_upgrade.inc @@ -3261,6 +3261,10 @@ TO_REMOVE+=/usr/share/man/man4/if_ppp.4.gz TO_REMOVE+=/usr/share/man/man4/ppp.4.gz TO_REMOVE+=/usr/share/man/man8/pppd.8.gz TO_REMOVE+=/usr/share/man/man8/pppstats.8.gz +TO_REMOVE+=/etc/periodic/daily/220.backup-distfile +TO_REMOVE+=/etc/periodic/daily/320.rdist +TO_REMOVE+=/usr/bin/rdist +TO_REMOVE+=/usr/share/man/man1/rdist.1.gz .if !defined(WANT_INSTALLER) TO_REMOVE+=/usr/sbin/dfuibe_installer diff --git a/etc/defaults/periodic.conf b/etc/defaults/periodic.conf index 3bdc9263bb..2b0f1e99e9 100644 --- a/etc/defaults/periodic.conf +++ b/etc/defaults/periodic.conf @@ -83,9 +83,6 @@ daily_backup_passwd_enable="YES" # Backup passwd & group # 210.backup-aliases daily_backup_aliases_enable="YES" # Backup mail aliases -# 220.backup-distfile -daily_backup_distfile_enable="YES" # Backup /etc/Distfile - # 300.calendar daily_calendar_enable="NO" # Run calendar -a @@ -95,9 +92,6 @@ daily_accounting_compress="NO" # Gzip rotated files daily_accounting_flags=-q # Flags to /usr/sbin/sa daily_accounting_save=3 # How many files to save -# 320.distfile -daily_distfile_enable="YES" # Run rdist daily - # 330.news daily_news_expire_enable="YES" # Run news.expire diff --git a/etc/periodic/daily/220.backup-distfile b/etc/periodic/daily/220.backup-distfile deleted file mode 100644 index 7046bb7673..0000000000 --- a/etc/periodic/daily/220.backup-distfile +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh -# -# $FreeBSD: src/etc/periodic/daily/220.backup-distfile,v 1.3.2.2 2000/09/20 02:46:15 jkh Exp $ -# $DragonFly: src/etc/periodic/daily/220.backup-distfile,v 1.2 2003/06/17 04:24:48 dillon Exp $ -# - -# If there is a global system configuration file, suck it in. -# -if [ -r /etc/defaults/periodic.conf ] -then - . /etc/defaults/periodic.conf - source_periodic_confs -fi - -case "$daily_backup_distfile_enable" in - [Yy][Ee][Ss]) - if [ ! -f /etc/Distfile ] - then - echo '$daily_backup_distfile_enable is set but /etc/Distfile' \ - "doesn't exist" - rc=2 - else - bak=/var/backups - rc=0 - - echo "" - echo "Backing up /etc/Distfile:" - - if ! cmp -s $bak/Distfile.bak /etc/Distfile - then - rc=1 - mv $bak/Distfile.bak $bak/Distfile.bak2 - cp /etc/Distfile $bak/Distfile.bak || rc=3 - fi - fi;; - - *) rc=0;; -esac - -exit $rc diff --git a/etc/periodic/daily/320.rdist b/etc/periodic/daily/320.rdist deleted file mode 100644 index b9ac84f4ab..0000000000 --- a/etc/periodic/daily/320.rdist +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# -# $FreeBSD: src/etc/periodic/daily/320.rdist,v 1.3.2.2 2000/09/20 02:46:15 jkh Exp $ -# $DragonFly: src/etc/periodic/daily/320.rdist,v 1.2 2003/06/17 04:24:48 dillon Exp $ -# - -# If there is a global system configuration file, suck it in. -# -if [ -r /etc/defaults/periodic.conf ] -then - . /etc/defaults/periodic.conf - source_periodic_confs -fi - -case "$daily_distfile_enable" in - [Yy][Ee][Ss]) - if [ ! -f /etc/Distfile ] - then - echo '$daily_distfile_enable is set but /etc/Distfile' \ - "doesn't exist" - rc=2 - else - echo "" - echo "Running rdist with /etc/Distfile:" - - rdist -f /etc/Distfile && rc=0 || rc=3 - fi;; - - *) rc=0;; -esac - -exit $rc diff --git a/etc/periodic/daily/Makefile b/etc/periodic/daily/Makefile index 4c603916ee..074cbfccba 100644 --- a/etc/periodic/daily/Makefile +++ b/etc/periodic/daily/Makefile @@ -1,5 +1,4 @@ # $FreeBSD: src/etc/periodic/daily/Makefile,v 1.4.2.4 2002/07/18 12:36:07 ru Exp $ -# $DragonFly: src/etc/periodic/daily/Makefile,v 1.4 2008/10/22 20:15:55 swildner Exp $ FILES= 100.clean-disks \ 110.clean-tmps \ @@ -10,10 +9,8 @@ FILES= 100.clean-disks \ 160.clean-hammer \ 200.backup-passwd \ 210.backup-aliases \ - 220.backup-distfile \ 300.calendar \ 310.accounting \ - 320.rdist \ 330.news \ 400.status-disks \ 420.status-network \ diff --git a/share/man/man5/periodic.conf.5 b/share/man/man5/periodic.conf.5 index 01f86f17f6..478670023a 100644 --- a/share/man/man5/periodic.conf.5 +++ b/share/man/man5/periodic.conf.5 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD: src/share/man/man5/periodic.conf.5,v 1.8.2.22 2003/02/08 21:42:01 gshapiro Exp $ .\" -.Dd June 9, 2016 +.Dd September 3, 2017 .Dt PERIODIC.CONF 5 .Os .Sh NAME @@ -314,13 +314,6 @@ Set to if you want the .Pa /etc/mail/aliases file backed up and modifications to be displayed in your daily output. -.It Va daily_backup_distfile_enable -.Pq Vt bool -Set to -.Dq YES -if you want the -.Pa /etc/Distfile -file backed up and modifications to be displayed in your daily output. .It Va daily_calendar_enable .Pq Vt bool Set to @@ -363,16 +356,6 @@ is set to .Dq YES . The default is .Fl q . -.It Va daily_distfile_enable -.Pq Vt bool -Set to -.Dq YES -if you want to run -.Xr rdist 1 -daily. -The -.Pa /etc/Distfile -file must also exist. .It Va daily_news_expire_enable .Pq Vt bool Set to @@ -765,7 +748,6 @@ is shared or distributed. .Xr msgs 1 , .Xr netstat 1 , .Xr nice 1 , -.Xr rdist 1 , .Xr HAMMER 5 , .Xr rc.conf 5 , .Xr ac 8 , diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 88d31ceb4d..1b203d7010 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -153,7 +153,6 @@ SUBDIR= alias \ printf \ pwait \ quota \ - rdist \ relpath \ renice \ rev \ diff --git a/usr.bin/rdist/Makefile b/usr.bin/rdist/Makefile deleted file mode 100644 index fd01174b20..0000000000 --- a/usr.bin/rdist/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# @(#)Makefile 8.3 (Berkeley) 7/19/93 -# $FreeBSD: src/usr.bin/rdist/Makefile,v 1.6 1999/08/28 01:05:05 peter Exp $ - -PROG= rdist -SRCS= docmd.c expand.c gram.y lookup.c main.c rshrcmd.c server.c -CFLAGS+=-I${.CURDIR} -YFLAGS= -WARNS?= 2 - -# 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 diff --git a/usr.bin/rdist/cron.entry b/usr.bin/rdist/cron.entry deleted file mode 100644 index 90968cf3fa..0000000000 --- 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 15a1313fe0..0000000000 --- a/usr.bin/rdist/defs.h +++ /dev/null @@ -1,189 +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. 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 - * $DragonFly: src/usr.bin/rdist/defs.h,v 1.5 2004/07/24 19:45:10 eirikn Exp $ - */ - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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(int, char *); -char *colon(char *); -void cleanup(int); -void define(char *); -void docmds(char **, int, char **); -void error(const char *, ...) __printflike(1, 2); -int except(char *); -struct namelist * - expand(struct namelist *, int); -char *exptilde(char [], char *, int); -void fatal(const char *, ...) __printflike(1, 2); -int inlist(struct namelist *, char *); -void insert(char *, - struct namelist *, struct namelist *, struct subcmd *); -void install(char *, char *, int, int); -void dolog(FILE *, const char *, ...) __printflike(2, 3); -struct namelist * - lookup(char *, int, struct namelist *); -void lostconn(int); -struct namelist * - makenl(char *); -struct subcmd * - makesubcmd(int); -void prnames(struct namelist *); -void server(void); -void yyerror(char *); -int yyparse(void); -int rshrcmd(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 796995b947..0000000000 --- a/usr.bin/rdist/docmd.c +++ /dev/null @@ -1,671 +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. 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. - * - * @(#)docmd.c 8.1 (Berkeley) 6/9/93 - * $FreeBSD: src/usr.bin/rdist/docmd.c,v 1.12 1999/08/28 01:05:06 peter Exp $ - * $DragonFly: src/usr.bin/rdist/docmd.c,v 1.5 2008/10/16 01:52:32 swildner Exp $ - */ - -#include - -#include -#include -#include - -#include "defs.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(char *); -static int okname(char *); -static void closeconn(void); -static void cmptime(char *); -static void doarrow(char **, - struct namelist *, char *, struct subcmd *); -static void dodcolon(char **, - struct namelist *, char *, struct subcmd *); -static void notify(char *, char *, struct namelist *, time_t); -static void rcmptime(struct stat *); -static int remotecmd(char *, char *, char *, char *); - -/* - * Do the commands in cmds (initialized by yyparse). - */ -void -docmds(char **dhosts, int argc, char **argv) -{ - struct cmd *c; - struct namelist *f; - 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(char **filev, struct namelist *files, char *rhost, struct subcmd *cmds) -{ - struct namelist *f; - struct subcmd *sc; - 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) - 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) { - signal(SIGPIPE, cleanup); - if (lfp) - 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; - - unlink(tempfile); - for (; ihead != NULL; ihead = nextihead) { - nextihead = ihead->nextp; - if ((opts & IGNLNKS) || ihead->count == 0) - continue; - dolog(lfp, "%s: Warning: missing links\n", - ihead->pathname); - free(ihead); - } - } -} - -static int remotecmd(char *rhost, char *luser, char *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); - } - - fflush(stdout); - fflush(stderr); - signal(SIGALRM, cleanup); - alarm(RTIMEOUT); - - if (geteuid() == 0 && strcmp(path_rsh, _PATH_RSH) == 0) { - if (debug) - printf("I am root, therefore direct rcmd\n"); - - 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); - signal(SIGPIPE, SIG_IGN); - desc = rshrcmd(&rhost, -1, luser, ruser, cmd, 0); - if (desc > 0) - signal(SIGPIPE, cleanup); - } - - alarm(0); - - return(desc); -} - - -/* - * Create a connection to the rdist server on the machine rhost. - */ -static int -makeconn(char *rhost) -{ - 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); - 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(void) -{ - if (debug) - printf("closeconn()\n"); - - if (rem >= 0) { - write(rem, "\2\n", 2); - close(rem); - rem = -1; - } -} - -void -lostconn(int signo) -{ - if (iamremote) - cleanup(0); - dolog(lfp, "rdist: lost connection\n"); - longjmp(env, 1); -} - -static int -okname(char *name) -{ - char *cp; - int c; - - cp = name; - - 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(char **filev, struct namelist *files, char *stamp, struct subcmd *cmds) -{ - struct subcmd *sc; - struct namelist *f; - 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; - } - gettimeofday(&tv[0], &tz); - tv[1] = tv[0]; - 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) - 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)) - unlink(tempfile); -} - -/* - * Compare the mtime of file to the list of time stamps. - */ -static void -cmptime(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) - dolog(tfp, "new: %s\n", name); -} - -static void -rcmptime(struct stat *st) -{ - DIR *d; - struct dirent *dp; - 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(char *file, char *rhost, struct namelist *to, time_t lmod) -{ - 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)); - close(fd); - return; - } - if (stb.st_size == 0) { - close(fd); - return; - } - /* - * Create a pipe to mailling program. - */ - snprintf(buf, sizeof(buf), "%s -oi -t", _PATH_SENDMAIL); - pf = popen(buf, "w"); - if (pf == NULL) { - error("notify: \"%s\" failed\n", _PATH_SENDMAIL); - 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) - fwrite(buf, 1, len, pf); - - close(fd); - pclose(pf); -} - -/* - * Return true if name is in the list. - */ -int -inlist(struct namelist *list, char *file) -{ - 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(char *file) -{ - struct subcmd *sc; - 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(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 366f73f771..0000000000 --- a/usr.bin/rdist/expand.c +++ /dev/null @@ -1,597 +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. 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. - * - * @(#)expand.c 8.1 (Berkeley) 6/9/93 - * $FreeBSD: src/usr.bin/rdist/expand.c,v 1.8 1999/08/28 01:05:06 peter Exp $ - */ - -#include "defs.h" - -#define GAVSIZ NCARGS / 6 -#define LC '{' -#define RC '}' - -#define sort() qsort((char *)sortbase, &eargv[eargc] - sortbase, \ - sizeof(*sortbase), argcmp), sortbase = &eargv[eargc] - -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; - -static void Cat(char *, char *); -static void addpath(int); -static int amatch(char *, char *); -static int argcmp(const void *, const void *); -static int execbrc(char *, char *); -static void expsh(char *); -static void expstr(char *); -static int match(char *, char *); -static void matchdir(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(struct namelist *list, int wh) -{ - struct namelist *nl, *prev; - int n; - char pathbuf[BUFSIZ]; - char *argvbuf[GAVSIZ]; - - if (debug) { - printf("expand(%p, %d)\nlist = ", list, wh); - prnames(list); - } - - if (wh == 0) { - 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 = NULL; - 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(char *s) -{ - char *cp, *cp1; - 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, 0, NULL); - 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(const void *a1, const void *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(char *s) -{ - char *cp; - 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(char *pattern) -{ - struct stat stb; - struct dirent *dp; - DIR *dirp; - - dirp = opendir(path); - if (dirp == NULL) { - if (expany) - return; - goto patherr2; - } - if (fstat(dirfd(dirp), &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(char *p, char *s) -{ - char restbuf[BUFSIZ + 2]; - char *pe, *pm, *pl; - int brclev; - char *lm, savec, *spathp; - - brclev = 0; - - 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 == NULL) { - 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(char *s, char *p) -{ - int c; - char *sentp; - char sexpany; - - sexpany = expany; - if (*s == '.' && *p != '.') - return (0); - sentp = entp; - entp = s; - c = amatch(s, p); - entp = sentp; - expany = sexpany; - return (c); -} - -static int -amatch(char *s, char *p) -{ - int scc; - int ok, lc, c, cc; - char *spathp; - struct stat stb; - - 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 void -Cat(char *s1, char *s2) -{ - int len; - char *s; - - len = strlen(s1) + strlen(s2) + 1; - nleft -= len; - if (nleft <= 0 || ++eargc >= GAVSIZ) - yyerror("Arguments too long"); - eargv[eargc] = NULL; - 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(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(char buf[], char *file, int maxlen) -{ - 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 82e5f56562..0000000000 --- a/usr.bin/rdist/gram.y +++ /dev/null @@ -1,504 +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. 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. - * - * @(#)gram.y 8.1 (Berkeley) 6/9/93 - * $FreeBSD: src/usr.bin/rdist/gram.y,v 1.6 1999/08/28 01:05:07 peter Exp $ - * $DragonFly: src/usr.bin/rdist/gram.y,v 1.5 2008/10/16 01:52:33 swildner Exp $ - */ - -#include - -#include -#include - -#include "defs.h" - -struct cmd *cmds = NULL; -struct cmd *last_cmd; -struct namelist *last_n; -struct subcmd *last_sc; - -static char *makestr(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 OPTION, options -%type NAME, STRING -%type INSTALL, NOTIFY, EXCEPT, PATTERN, SPECIAL, cmdlist, cmd -%type 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 = { - 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(void) -{ - static char yytext[INMAX]; - int c; - 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(int c, 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(char *label, struct namelist *files, struct namelist *hosts, struct subcmd *subcmds) -{ - struct cmd *c, *prev, *nc; - 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(char *label, struct namelist *files, char *stamp, struct subcmd *subcmds) -{ - 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(char *s) -{ - ++nerrs; - fflush(stdout); - fprintf(stderr, "rdist: line %d: %s\n", yylineno, s); -} - -/* - * Return a copy of the string. - */ -static char * -makestr(char *str) -{ - 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(char *name) -{ - 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(int type) -{ - 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 794a2af1e0..0000000000 --- a/usr.bin/rdist/lookup.c +++ /dev/null @@ -1,159 +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. 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. - * - * @(#)lookup.c 8.1 (Berkeley) 6/9/93 - * $FreeBSD: src/usr.bin/rdist/lookup.c,v 1.6 1999/08/28 01:05:07 peter Exp $ - * $DragonFly: src/usr.bin/rdist/lookup.c,v 1.4 2008/10/16 01:52:33 swildner Exp $ - */ - -#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(char *name) -{ - char *cp, *s; - struct namelist *nl; - struct namelist *value; - - 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; - } - } - 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(char *name, int action, struct namelist *value) -{ - unsigned n; - char *cp; - 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) { - snprintf(buf, sizeof(buf),"%s redefined", name); - yyerror(buf); - } - } - return(s->s_value); - } - - if (action == LOOKUP) { - 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 26efb6afc6..0000000000 --- a/usr.bin/rdist/main.c +++ /dev/null @@ -1,298 +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. 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. - * - * @(#) Copyright (c) 1983, 1993 The Regents of the University of California. All rights reserved. - * @(#)main.c 8.1 (Berkeley) 6/9/93 - * $FreeBSD: src/usr.bin/rdist/main.c,v 1.5 1999/08/28 01:05:07 peter Exp $ - */ -/* - * Remote distribution program. - */ - -#include - -#include "defs.h" - -#define NHOSTS 100 -#define _RDIST_TMP "/rdistXXXXXX" - -char *distfile = NULL; -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(void); -static void docmdargs(int, char *[]); - -int -main(int argc, char **argv) -{ - char *arg; - int cmdargs; - char *dhosts[NHOSTS], **hp = dhosts; - - cmdargs = 0; - - 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, '/')) != NULL) - 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(void) -{ - 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(int nargs, char **args) -{ - struct namelist *nl, *prev; - char *cp; - struct namelist *files, *hosts; - struct subcmd *cmds; - char *dest; - static struct namelist tnl = { NULL, NULL }; - int i; - - files = NULL; - - 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(struct namelist *nl) -{ - printf("( "); - while (nl != NULL) { - printf("%s ", nl->n_name); - nl = nl->n_next; - } - printf(")\n"); -} diff --git a/usr.bin/rdist/pathnames.h b/usr.bin/rdist/pathnames.h deleted file mode 100644 index 88f1dc841d..0000000000 --- a/usr.bin/rdist/pathnames.h +++ /dev/null @@ -1,35 +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. 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 - -#define _PATH_RDIST "rdist" -#define _PATH_RSH "/usr/bin/rsh" diff --git a/usr.bin/rdist/rdist.1 b/usr.bin/rdist/rdist.1 deleted file mode 100644 index 80b2aae5a0..0000000000 --- a/usr.bin/rdist/rdist.1 +++ /dev/null @@ -1,452 +0,0 @@ -.\" Copyright (c) 1985, 1990, 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. 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. -.\" -.\" @(#)rdist.1 8.3 (Berkeley) 3/17/94 -.\" $FreeBSD: src/usr.bin/rdist/rdist.1,v 1.13.2.4 2001/12/21 10:07:20 ru Exp $ -.\" -.Dd March 17, 1994 -.Dt RDIST 1 -.Os -.Sh NAME -.Nm rdist -.Nd remote file distribution program -.Sh SYNOPSIS -.Nm -.Op Fl nqbRhivwyD -.Op Fl P Ar rshcmd -.Op Fl f Ar distfile -.Op Fl d Ar var=value -.Op Fl m Ar host -.Op Ar name ...\& -.Nm -.Op Fl nqbRhivwyD -.Op Fl P Ar rshcmd -.Fl c -.Ar name ...\& -.Oo Ar login Ns @ Oc Ns Xo -.Ar host Ns Op : Ns Ar dest -.Xc -.Sh DESCRIPTION -.Nm Rdist -is a program to maintain identical copies of files over multiple hosts. -It preserves the owner, group, mode, and mtime of files if possible and -can update programs that are executing. -.Nm Rdist -reads commands from -.Ar distfile -to direct the updating of files and/or directories. -.Pp -Options specific to the first SYNOPSIS form: -.Bl -tag -width indent -.It Fl -If -.Ar distfile -is -.Sq Fl , -the standard input is used. -.It Fl f Ar distfile -Use the specified -.Ar distfile . -.El -.Pp -If either the -.Fl f -or -.Sq Fl -option is not specified, the program looks first for -.Dq Pa distfile , -then -.Dq Pa Distfile -to use as the input. -If no names are specified on the command line, -.Nm -will update all of the files and directories listed in -.Ar distfile . -Otherwise, the argument is taken to be the name of a file to be updated -or the label of a command to execute. -If label and file names conflict, -it is assumed to be a label. -These may be used together to update specific files -using specific commands. -.Pp -Options specific to the second SYNOPSIS form: -.Bl -tag -width Fl -.It Fl c -Forces -.Nm -to interpret the remaining arguments as a small -.Ar distfile . -.Pp -The equivalent distfile is as follows. -.Pp -.Bd -ragged -offset indent -compact -.Pq Ar name ...\& -.Li -> -.Op Ar login Ns @ -.Ar host -.Ed -.Bd -ragged -offset indentindent -compact -.Li install -.Op Ar dest ; -.Ed -.El -.Pp -Options common to both forms: -.Bl -tag -width Ic -.It Fl P Ar rshcmd -Alternative program to provide -.Xr rsh 1 Ns -like -transport to the remote server. It must provide a binary-transparent path -to the remote server, and must have a command argument syntax that is -compatible with -.Xr rsh 1 . -.It Fl d Ar var=value -Define -.Ar var -to have -.Ar value . -The -.Fl d -option is used to define or override variable definitions in the -.Ar distfile . -.Ar Value -can be the empty string, one name, or a list of names surrounded by -parentheses and separated by tabs and/or spaces. -.It Fl h -Follow symbolic links. -Copy the file that the link points to rather than the -link itself. -.It Fl i -Ignore unresolved links. -.Nm Rdist -will normally try to maintain the link structure of files being transferred -and warn the user if all the links cannot be found. -.It Fl m Ar host -Limit which machines are to be updated. -Multiple -.Fl m -arguments can be given to limit updates to a subset of the hosts listed in the -.Ar distfile . -.It Fl n -Print the commands without executing them. -This option is -useful for debugging -.Ar distfile . -.It Fl q -Quiet mode. -Files that are being modified are normally -printed on standard output. -The -.Fl q -option suppresses this. -.It Fl R -Remove extraneous files. -If a directory is being updated, any files that exist -on the remote host that do not exist in the master directory are removed. -This is useful for maintaining truly identical copies of directories. -.It Fl v -Verify that the files are up to date on all the hosts. -Any files -that are out of date will be displayed but no files will be changed -nor any mail sent. -.It Fl w -Whole mode. -The whole file name is appended to the destination directory -name. -Normally, only the last component of a name is used when renaming files. -This will preserve the directory structure of the files being -copied instead of flattening the directory structure. -For example, -renaming a list of files such as ( dir1/f1 dir2/f2 ) to dir3 would create -files dir3/dir1/f1 and dir3/dir2/f2 instead of dir3/f1 and dir3/f2. -.It Fl y -Younger mode. -Files are normally updated if their -.Ar mtime -and -.Ar size -(see -.Xr stat 2 ) -disagree. -The -.Fl y -option causes -.Nm -not to update files that are younger than the master copy. -This can be used -to prevent newer copies on other hosts from being replaced. -A warning message is printed for files which are newer than the master copy. -.It Fl D -Debug mode. -.El -.Pp -.Ar Distfile -contains a sequence of entries that specify the files -to be copied, the destination hosts, and what operations to perform -to do the updating. -Each entry has one of the following formats. -.Pp -.Bd -literal -offset indent -compact - `=' -[label:] `\->' -[label:] `::' -.Ed -.Pp -The first format is used for defining variables. -The second format is used for distributing files to other hosts. -The third format is used for making lists of files that have been changed -since some given date. -The -.Ar source list -specifies a -list of files and/or directories on the local host which are to be used -as the master copy for distribution. -The -.Ar destination list -is the list of hosts to which these files are to be -copied. Each file in the source list is added to a list of changes -if the file is out of date on the host which is being updated (second format) or -the file is newer than the time stamp file (third format). -.Pp -Labels are optional. -They are used to identify a command for partial updates. -.Pp -Newlines, tabs, and blanks are only used as separators and are -otherwise ignored. -Comments begin with `#' and end with a newline. -.Pp -Variables to be expanded begin with `$' followed by one character or -a name enclosed in curly braces (see the examples at the end). -.Pp -The source and destination lists have the following format: -.Bd -literal -offset indent - -.Ed -or -.Bd -literal -offset indent -compact -`(' `)' -.Ed -.Pp -The shell meta-characters `[', `]', `{', `}', `*', and `?' -are recognized and expanded (on the local host only) in the same way as -.Xr csh 1 . -They can be escaped with a backslash. -The `~' character is also expanded in the same way as -.Xr csh 1 -but is expanded separately on the local and destination hosts. -When the -.Fl w -option is used with a file name that begins with `~', everything except the -home directory is appended to the destination name. -File names which do not begin with `/' or `~' use the destination user's -home directory as the root directory for the rest of the file name. -.Pp -The command list consists of zero or more commands of the following -format. -.Bd -ragged -offset indent -compact -.Bl -column except_patx pattern\ listx -.It "`install' opt_dest_name `;'" -.It "`notify' `;'" -.It "`except' `;'" -.It "`except_pat' `;'" -.It "`special' string `;'" -.El -.Ed -.Pp -The -.Ic install -command is used to copy out of date files and/or directories. -Each source file is copied to each host in the destination list. -Directories are recursively copied in the same way. -.Ar Opt_dest_name -is an optional parameter to rename files. -If no -.Ic install -command appears in the command list or -the destination name is not specified, -the source file name is used. -Directories in the path name will be created if they -do not exist on the remote host. -To help prevent disasters, a non-empty directory on a target host will -never be replaced with a regular file or a symbolic link. -However, under the `\-R' option a non-empty directory will be removed -if the corresponding filename is completely absent on the master host. -The -.Ar options -are `\-R', `\-h', `\-i', `\-v', `\-w', `\-y', and `\-b' -and have the same semantics as -options on the command line except they only apply to the files -in the source list. -The login name used on the destination host is the same as the local host -unless the destination name is of the format ``login@host". -.Pp -The -.Ic notify -command is used to mail the list of files updated (and any errors -that may have occurred) to the listed names. -If no `@' appears in the name, the destination host is appended to -the name -(e.g., name1@host, name2@host, ...). -.Pp -The -.Ic except -command is used to update all of the files in the source list -.Ic except -for the files listed in -.Ar name list . -This is usually used to copy everything in a directory except certain files. -.Pp -The -.Ic except_pat -command is like the -.Ic except -command except that -.Ar pattern list -is a list of regular expressions -(see -.Xr re_format 7 -for details). -If one of the patterns matches some string within a file name, that file will -be ignored. -Note that since `\e' is a quote character, it must be doubled to become -part of the regular expression. Variables are expanded in -.Ar pattern list -but not shell file pattern matching characters. To include a `$', it -must be escaped with `\e'. -.Pp -The -.Ic special -command is used to specify -.Xr sh 1 -commands that are to be executed on the -remote host after the file in -.Ar name list -is updated or installed. -If the -.Ar name list -is omitted then the shell commands will be executed -for every file updated or installed. The shell variable `FILE' is set -to the current filename before executing the commands in -.Ar string . -.Ar String -starts and ends with `"' and can cross multiple lines in -.Ar distfile . -Multiple commands to the shell should be separated by `;'. -Commands are executed in the user's home directory on the host -being updated. -The -.Ar special -command can be used to rebuild private databases, etc. -after a program has been updated. -.Pp -The following is a small example: -.Bd -literal -offset indent -HOSTS = ( matisse root@arpa ) - -FILES = ( /bin /lib /usr/bin /usr/games -\t/usr/include/{*.h,{stand,sys,vax*,pascal,machine}/*.h} -\t/usr/lib /usr/man/man? /usr/ucb /usr/local/rdist ) - -EXLIB = ( Mail.rc aliases aliases.dir aliases.pag crontab dshrc -\tsendmail.cf sendmail.fc sendmail.hf sendmail.st uucp vfont ) - -${FILES} -> ${HOSTS} -\tinstall -R ; -\texcept /usr/lib/${EXLIB} ; -\texcept /usr/games/lib ; -\tspecial /usr/lib/sendmail "/usr/lib/sendmail -bz" ; - -srcs: -/usr/src/bin -> arpa -\texcept_pat ( \e\e.o\e$ /SCCS\e$ ) ; - -IMAGEN = (ips dviimp catdvi) - -imagen: -/usr/local/${IMAGEN} -> arpa -\tinstall /usr/local/lib ; -\tnotify ralph ; - -${FILES} :: stamp.cory -\tnotify root@cory ; -.Ed -.Sh FILES -.Bl -tag -width /tmp/rdist* -compact -.It Pa distfile -input command file -.It Pa /tmp/rdist* -temporary file for update lists -.El -.Sh DIAGNOSTICS -A complaint about mismatch of -.Nm -version numbers may really stem -from some problem with starting your shell, e.g., you are in too many groups. -.Pp -.Nm Rdist -relies on -.Xr rcmd 3 -type remote services executing successfully and in silence. -A common error is for non-interactive initialization scripts, like -.Pa .cshrc , -to generate output (or to run other programs which generate output -when not attached to a terminal -- the most frequent offender is -.Xr stty 1 ) . -This extra output will cause -.Nm -to fail with the error message: -.Pp -.Dl rdist: connection failed: version numbers don't match -.Sh SEE ALSO -.Xr csh 1 , -.Xr sh 1 , -.Xr stat 2 , -.Xr re_format 7 -.Sh HISTORY -The -.Nm -command appeared in -.Bx 4.3 . -.Sh BUGS -Source files must reside on the local host where -.Nm -is executed. -.Pp -There is no easy way to have a -.Ic special -command executed after all files -in a directory have been updated. -.Pp -Variable expansion only works for name lists; there should be a general macro -facility. -.Pp -.Nm Rdist -aborts on files which have a negative mtime (before Jan 1, 1970). -.Pp -There should be a `force' option to allow replacement of non-empty directories -by regular files or symlinks. A means of updating file modes and owners -of otherwise identical files is also needed. diff --git a/usr.bin/rdist/rshrcmd.c b/usr.bin/rdist/rshrcmd.c deleted file mode 100644 index da242a4302..0000000000 --- a/usr.bin/rdist/rshrcmd.c +++ /dev/null @@ -1,111 +0,0 @@ - -/* - * This is an rcmd() replacement originally by - * Chris Siebenmann . - * - * $FreeBSD: src/usr.bin/rdist/rshrcmd.c,v 1.6 1999/08/28 01:05:08 peter Exp $ - */ - -#include -#include -#include - -#include -#include - -#include "defs.h" - -#if !defined(DIRECT_RCMD) - -static char * -xbasename(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(char **ahost, u_short port, char *luser, char *ruser, char *cmd, int *fd2p) -{ - int cpid, sp[2]; - struct hostent *hp; - - /* insure that we are indeed being used as we thought. */ - if (fd2p != NULL) - return -1; - /* validate remote hostname. */ - hp = gethostbyname(*ahost); - if (hp == NULL) { - error("%s: unknown host", *ahost); - return -1; - } - - /* 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]. */ - 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, NULL); - error("execlp %s failed: %s.", _PATH_BSHELL, strerror(errno)); - } else { - execlp(path_rsh, xbasename(path_rsh), - *ahost, "-l", ruser, cmd, NULL); - error("execlp %s failed: %s.", path_rsh, - strerror(errno)); - } - _exit(255); - } - if (cpid > 0) { - /* parent. close sp[1], return sp[0]. */ - close(sp[1]); - /* reap child. */ - 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 ca322d5194..0000000000 --- a/usr.bin/rdist/server.c +++ /dev/null @@ -1,1556 +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. 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. - * - * @(#)server.c 8.1 (Berkeley) 6/9/93 - * $FreeBSD: src/usr.bin/rdist/server.c,v 1.10 1999/08/28 01:05:09 peter Exp $ - */ - -#include - -#include - -#include "defs.h" - -#define ack() write(rem, "\0\n", 2) -#define err() write(rem, "\1\n", 2) -#define protoname() (pw ? pw->pw_name : user) -#define protogroup() (gr ? gr->gr_name : group) - -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(char *); -static void clean(char *); -static void comment(char *); -static void dospecial(char *); -static int fchog(int, char *, char *, char *, int); -static void hardlink(char *); -static void note(const char *, ...) __printflike(1, 2); -static void query(char *); -static void recvf(char *, int); -static void removeit(struct stat *); -static int response(void); -static void rmchk(int); -static struct linkbuf *savelink(struct stat *); -static void sendf(char *, int); -static int update(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(void) -{ - char cmdbuf[BUFSIZ]; - char *cp; - - signal(SIGHUP, cleanup); - signal(SIGINT, cleanup); - signal(SIGQUIT, cleanup); - signal(SIGTERM, cleanup); - signal(SIGPIPE, cleanup); - - rem = 0; - oumask = umask(0); - snprintf(buf, sizeof(buf), "V%d\n", VERSION); - 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 */ - dolog(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(char *src, char *dest, int destdir, int 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. - */ - snprintf(buf, sizeof(buf), "%c%s\n", destdir ? 'T' : 't', dest); - if (debug) - printf("buf = %s", buf); - 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 = NULL; -} - -static char * -remotename(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(struct linkbuf *lp, char *rname, int opts) -{ - if (*lp->target == 0) - snprintf(buf, sizeof(buf), "k%o %s %s\n", opts, lp->pathname, rname); - else - 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); - } - write(rem, buf, strlen(buf)); - response(); -} - -/* - * Transfer the file or directory in target[]. - * rname is the name of the file on the remote host. - */ -static void -sendf(char *rname, int opts) -{ - 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) - savelink(&stb); - return; - } - - if (pw == NULL || pw->pw_uid != stb.st_uid) - if ((pw = getpwuid(stb.st_uid)) == NULL) { - dolog(lfp, "%s: no password entry for uid %d \n", - target, stb.st_uid); - pw = NULL; - snprintf(user, sizeof(user), ":%u", stb.st_uid); - } - if (gr == NULL || gr->gr_gid != stb.st_gid) - if ((gr = getgrgid(stb.st_gid)) == NULL) { - dolog(lfp, "%s: no name for group %d\n", - target, stb.st_gid); - gr = NULL; - snprintf(group, sizeof(group), ":%u", stb.st_gid); - } - if (u == 1) { - if (opts & VERIFY) { - dolog(lfp, "need to install: %s\n", target); - goto dospecial; - } - dolog(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; - } - 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); - 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); - write(rem, "E\n", 2); - 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; - } - } - snprintf(buf, sizeof(buf), - "K%o %o %jd %ld %s %s %s\n", opts, - stb.st_mode & 07777, (intmax_t)stb.st_size, stb.st_mtime, - protoname(), protogroup(), rname); - if (debug) - printf("buf = %s", buf); - write(rem, buf, strlen(buf)); - if (response() < 0) - return; - sizerr = (readlink(target, buf, BUFSIZ - 1) != stb.st_size); - 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) { - dolog(lfp, "need to update: %s\n", target); - goto dospecial; - } - dolog(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; - } - snprintf(buf, sizeof(buf), "R%o %o %jd %ld %s %s %s\n", opts, - stb.st_mode & 07777, (intmax_t)stb.st_size, stb.st_mtime, - protoname(), protogroup(), rname); - if (debug) - printf("buf = %s", buf); - write(rem, buf, strlen(buf)); - if (response() < 0) { - 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; - write(rem, buf, amt); - } - 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; - dolog(lfp, "special \"%s\"\n", sc->sc_name); - if (opts & VERIFY) - continue; - snprintf(buf, sizeof(buf), "SFILE=%s;%s\n", target, - sc->sc_name); - if (debug) - printf("buf = %s", buf); - write(rem, buf, strlen(buf)); - while (response() > 0) - ; - } -} - -static struct linkbuf * -savelink(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) - dolog(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(char *rname, int opts, struct stat *stp) -{ - char *cp, *s; - off_t size; - 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. - */ - snprintf(buf, sizeof(buf), "Q%s\n", rname); - if (debug) - printf("buf = %s", buf); - 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); - write(2, s, cp - s); - } - if (lfp != NULL) - fwrite(s, 1, cp - s, lfp); - } - return(0); - - case '\3': - *--cp = '\0'; - if (lfp != NULL) - dolog(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) { - dolog(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(char *name) -{ - struct stat stb; - - if (catname) - snprintf(tp, sizeof(target) - (tp - target), "/%s", - name); - - if (lstat(target, &stb) < 0) { - if (errno == ENOENT) - 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: - snprintf(buf, sizeof(buf), "Y%jd %ld\n", (intmax_t)stb.st_size, - stb.st_mtime); - write(rem, buf, strlen(buf)); - break; - - case S_IFLNK: - case S_IFDIR: - write(rem, "Y\n", 2); - break; - - default: - error("%s: not a file or directory\n", name); - break; - } - *tp = '\0'; -} - -static void -recvf(char *cmd, int type) -{ - char *cp; - int f, 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; - f = -1; - 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'; - snprintf(buf + 1, sizeof(buf) - 1, - "%s: Warning: remote mode %o != local mode %o\n", - target, stb.st_mode & 07777, mode); - 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) - snprintf(tp, sizeof(target) - (tp - target), "/%s", cp); - cp = rindex(target, '/'); - if (cp == NULL) - strcpy(new, tempname); - else if (cp == target) - snprintf(new, sizeof(new), "/%s", tempname); - else { - *cp = '\0'; - 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) { - 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; - - amt = BUFSIZ; - cp = buf; - if (i + amt > size) - amt = size - i; - do { - int j = read(rem, cp, amt); - - if (j <= 0) { - close(f); - 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) { - fclose(f1); - fclose(f2); - ack(); - goto badnew2; - } - fclose(f1); - fclose(f2); - if (opts & VERIFY) { -differ: buf[0] = '\0'; - snprintf(buf + 1, sizeof(buf) - 1, - "need to update: %s\n",target); - 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) - close(f); - unlink(new); - return; - } - close(f); - -fixup: if (rename(new, target) < 0) { -badtarget: error("%s:%s: %s\n", host, target, strerror(errno)); - unlink(new); - return; - } - - if (opts & COMPARE) { - buf[0] = '\0'; - snprintf(buf + 1, sizeof(buf) - 1, - "updated %s\n", target); - write(rem, buf, strlen(buf + 1) + 1); - } else - ack(); -} - -/* - * Creat a hard link to existing file. - */ -static void -hardlink(char *cmd) -{ - char *cp; - struct stat stb; - char *oldname; - int opts, exists; - - cp = cmd; - opts = 0; - exists = 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) { - 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(char *name) -{ - 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(int fd, char *file, char *owner, char *group, int mode) -{ - 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(int opts) -{ - char *cp, *s; - struct stat stb; - - if (debug) - printf("rmchk()\n"); - - /* - * Tell the remote to clean the files from the last directory sent. - */ - snprintf(buf, sizeof(buf), "C%o\n", opts & VERIFY); - if (debug) - printf("buf = %s", buf); - 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'; - snprintf(tp, sizeof(target) - (tp - target), "/%s", s); - if (debug) - printf("check %s\n", target); - if (except(target)) - write(rem, "N\n", 2); - else if (lstat(target, &stb) < 0) - write(rem, "Y\n", 2); - else - write(rem, "N\n", 2); - break; - - case '\0': - *--cp = '\0'; - if (*s != '\0') - dolog(lfp, "%s\n", s); - break; - - case 'E': - *tp = '\0'; - ack(); - return; - - case '\1': - case '\2': - nerrs++; - if (*s != '\n') { - if (!iamremote) { - fflush(stdout); - write(2, s, cp - s); - } - if (lfp != NULL) - 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(char *cp) -{ - DIR *d; - 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; - } - snprintf(buf, sizeof(buf), "Q%s\n", dp->d_name); - 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'; - snprintf(cp, sizeof(buf) - 1, "need to remove: %s\n", target); - write(rem, buf, strlen(cp) + 1); - } else - removeit(&stb); - } - closedir(d); - write(rem, "E\n", 2); - response(); - tp = otp; - *tp = '\0'; -} - -/* - * Remove a file or directory (recursively) and send back an acknowledge - * or an error message. - */ -static void -removeit(struct stat *stp) -{ - DIR *d; - struct dirent *dp; - 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'; - snprintf(cp, sizeof(buf) - 1, "removed %s\n", target); - write(rem, buf, strlen(cp) + 1); -} - -/* - * Execute a shell command to handle special cases. - */ -static void -dospecial(char *cmd) -{ - int fd[2], status, pid, i; - 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. - */ - close(0); - close(1); - close(2); - open(_PATH_DEVNULL, O_RDONLY); - dup(fd[1]); - dup(fd[1]); - close(fd[0]); - close(fd[1]); - setgid(groupid); - setuid(userid); - execl(_PATH_BSHELL, "sh", "-c", cmd, NULL); - _exit(127); - } - 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; - } - write(rem, sbuf, s - sbuf); - s = &sbuf[1]; - } while (--i); - } - if (s > &sbuf[1]) { - *s++ = '\n'; - write(rem, sbuf, s - sbuf); - } - while ((i = wait(&status)) != pid && i != -1) - ; - if (i == -1) - status = -1; - close(fd[0]); - if (status) - error("shell returned %d\n", status); - else - ack(); -} - -void -dolog(FILE *fp, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - /* Print changes locally if not quiet mode */ - if (!qflag) - vprintf(fmt, ap); - - /* Save changes (for mailing) if really updating files */ - if (!(options & VERIFY) && fp != NULL) - vfprintf(fp, fmt, ap); - va_end(ap); -} - -void -error(const char *fmt, ...) -{ - static FILE *fp; - va_list ap; - - va_start(ap, fmt); - - ++nerrs; - if (!fp && !(fp = fdopen(rem, "w"))) - return; - if (iamremote) { - fprintf(fp, "%crdist: ", 0x01); - vfprintf(fp, fmt, ap); - fflush(fp); - } - else { - fflush(stdout); - fprintf(stderr, "rdist: "); - vfprintf(stderr, fmt, ap); - fflush(stderr); - } - if (lfp != NULL) { - fprintf(lfp, "rdist: "); - vfprintf(lfp, fmt, ap); - fflush(lfp); - } - va_end(ap); -} - -void -fatal(const char *fmt, ...) -{ - static FILE *fp; - va_list ap; - - va_start(ap, fmt); - - ++nerrs; - if (!fp && !(fp = fdopen(rem, "w"))) - return; - if (iamremote) { - fprintf(fp, "%crdist: ", 0x02); - vfprintf(fp, fmt, ap); - fflush(fp); - } - else { - fflush(stdout); - fprintf(stderr, "rdist: "); - vfprintf(stderr, fmt, ap); - fflush(stderr); - } - if (lfp != NULL) { - fprintf(lfp, "rdist: "); - vfprintf(lfp, fmt, ap); - fflush(lfp); - } - va_end(ap); - cleanup(0); -} - -static int -response(void) -{ - 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') { - dolog(lfp, "%s\n", s); - return(1); - } - return(0); - case '\3': - *--cp = '\0'; - dolog(lfp, "Note: %s\n",s); - return(response()); - - default: - s--; - /* fall into... */ - case '\1': - case '\2': - nerrs++; - if (*s != '\n') { - if (!iamremote) { - fflush(stdout); - write(2, s, cp - s); - } - if (lfp != NULL) - 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(int signo) -{ - unlink(tempfile); - exit(1); -} - -static void -note(const char *fmt, ...) -{ - static char buf[BUFSIZ]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - comment(buf); -} - -static void -comment(char *s) -{ - char c; - - c = '\3'; - write(rem, &c, 1); - write(rem, s, strlen(s)); - c = '\n'; - write(rem, &c, 1); -}