Retire this ancient version of rdist.

This commit is contained in:
David E. O'Brien 2000-12-07 19:24:55 +00:00
parent ee0610eb99
commit a3cea3dde5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=69716
12 changed files with 0 additions and 4409 deletions

View File

@ -124,7 +124,6 @@ SUBDIR= apply \
printenv \
printf \
quota \
rdist \
renice \
rev \
rlogin \

View File

@ -1,16 +0,0 @@
# @(#)Makefile 8.3 (Berkeley) 7/19/93
# $FreeBSD$
PROG= rdist
SRCS= docmd.c expand.c gram.y lookup.c main.c rshrcmd.c server.c
CFLAGS+=-I${.CURDIR}
YFLAGS=
# To use the old method, which requires setuid-root and all the baggage and
# security holes that goes with it, uncomment:
# CFLAGS+= -DDIRECT_RCMD
# BINOWN= root
# BINMODE=4555
# INSTALLFLAGS=-fschg
.include <bsd.prog.mk>

View File

@ -1 +0,0 @@
30 3 * * * /usr/bin/rdist -f /etc/Distfile >& /var/log/rdist/rdist.err 2>&1

View File

@ -1,191 +0,0 @@
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)defs.h 8.1 (Berkeley) 6/9/93
*/
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/file.h>
#include <netinet/in.h>
#include <dirent.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include "pathnames.h"
/*
* The version number should be changed whenever the protocol changes.
*/
#define VERSION 3
/* defines for yacc */
#define EQUAL 1
#define LP 2
#define RP 3
#define SM 4
#define ARROW 5
#define COLON 6
#define DCOLON 7
#define NAME 8
#define STRING 9
#define INSTALL 10
#define NOTIFY 11
#define EXCEPT 12
#define PATTERN 13
#define SPECIAL 14
#define OPTION 15
/* lexical definitions */
#define QUOTE 0200 /* used internally for quoted characters */
#define TRIM 0177 /* Mask to strip quote bit */
/* table sizes */
#define HASHSIZE 1021
#define INMAX 3500
/* option flags */
#define VERIFY 0x1
#define WHOLE 0x2
#define YOUNGER 0x4
#define COMPARE 0x8
#define REMOVE 0x10
#define FOLLOW 0x20
#define IGNLNKS 0x40
/* expand type definitions */
#define E_VARS 0x1
#define E_SHELL 0x2
#define E_TILDE 0x4
#define E_ALL 0x7
/* actions for lookup() */
#define LOOKUP 0
#define INSERT 1
#define REPLACE 2
#define ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define ALLOC(x) (struct x *) malloc(sizeof(struct x))
/*
* RSH Time Out interval (in seconds).
* Should be long enough to allow rsh to even the slowest hosts.
*/
#define RTIMEOUT 180
struct namelist { /* for making lists of strings */
char *n_name;
struct namelist *n_next;
};
struct subcmd {
short sc_type; /* type - INSTALL,NOTIFY,EXCEPT,SPECIAL */
short sc_options;
char *sc_name;
struct namelist *sc_args;
struct subcmd *sc_next;
};
struct cmd {
int c_type; /* type - ARROW,DCOLON */
char *c_name; /* hostname or time stamp file name */
char *c_label; /* label for partial update */
struct namelist *c_files;
struct subcmd *c_cmds;
struct cmd *c_next;
};
struct linkbuf {
ino_t inum;
dev_t devnum;
int count;
char pathname[BUFSIZ];
char src[BUFSIZ];
char target[BUFSIZ];
struct linkbuf *nextp;
};
extern int debug; /* debugging flag */
extern int nflag; /* NOP flag, don't execute commands */
extern int qflag; /* Quiet. don't print messages */
extern int options; /* global options */
extern int nerrs; /* number of errors seen */
extern int rem; /* remote file descriptor */
extern int iamremote; /* acting as remote server */
extern char tempfile[]; /* file name for logging changes */
extern struct linkbuf *ihead; /* list of files with more than one link */
extern struct passwd *pw; /* pointer to static area used by getpwent */
extern struct group *gr; /* pointer to static area used by getgrent */
extern char host[]; /* host name of master copy */
extern char buf[BUFSIZ]; /* general purpose buffer */
extern char target[BUFSIZ]; /* target/source directory name */
extern char *path_rsh; /* rsh command to use */
int any __P((int, char *));
char *colon __P((char *));
void cleanup __P((int));
void define __P((char *));
void docmds __P((char **, int, char **));
void error __P((const char *, ...));
int except __P((char *));
struct namelist *
expand __P((struct namelist *, int));
char *exptilde __P((char [], char *, int));
void fatal __P((const char *, ...));
int inlist __P((struct namelist *, char *));
void insert __P((char *,
struct namelist *, struct namelist *, struct subcmd *));
void install __P((char *, char *, int, int));
void log __P((FILE *, const char *, ...));
struct namelist *
lookup __P((char *, int, struct namelist *));
void lostconn __P((int));
struct namelist *
makenl __P((char *));
struct subcmd *
makesubcmd __P((int));
void prnames __P((struct namelist *));
void server __P((void));
void yyerror __P((char *));
int yyparse __P((void));
int rshrcmd __P((char **, u_short, char *, char *, char *, int *));

View File

@ -1,700 +0,0 @@
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
#if 0
static char sccsid[] = "From: @(#)docmd.c 8.1 (Berkeley) 6/9/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "defs.h"
#include <setjmp.h>
#include <netdb.h>
#include <regex.h>
FILE *lfp; /* log file for recording files updated */
struct subcmd *subcmds; /* list of sub-commands for current cmd */
jmp_buf env;
static int makeconn __P((char *));
static int okname __P((char *));
static void closeconn __P((void));
static void cmptime __P((char *));
static void doarrow __P((char **,
struct namelist *, char *, struct subcmd *));
static void dodcolon __P((char **,
struct namelist *, char *, struct subcmd *));
static void notify __P((char *, char *, struct namelist *, time_t));
static void rcmptime __P((struct stat *));
static int remotecmd __P((char *, char *, char *, char *));
/*
* Do the commands in cmds (initialized by yyparse).
*/
void
docmds(dhosts, argc, argv)
char **dhosts;
int argc;
char **argv;
{
register struct cmd *c;
register struct namelist *f;
register char **cpp;
extern struct cmd *cmds;
signal(SIGHUP, cleanup);
signal(SIGINT, cleanup);
signal(SIGQUIT, cleanup);
signal(SIGTERM, cleanup);
for (c = cmds; c != NULL; c = c->c_next) {
if (dhosts != NULL && *dhosts != NULL) {
for (cpp = dhosts; *cpp; cpp++)
if (strcmp(c->c_name, *cpp) == 0)
goto fndhost;
continue;
}
fndhost:
if (argc) {
for (cpp = argv; *cpp; cpp++) {
if (c->c_label != NULL &&
strcmp(c->c_label, *cpp) == 0) {
cpp = NULL;
goto found;
}
for (f = c->c_files; f != NULL; f = f->n_next)
if (strcmp(f->n_name, *cpp) == 0)
goto found;
}
continue;
} else
cpp = NULL;
found:
switch (c->c_type) {
case ARROW:
doarrow(cpp, c->c_files, c->c_name, c->c_cmds);
break;
case DCOLON:
dodcolon(cpp, c->c_files, c->c_name, c->c_cmds);
break;
default:
fatal("illegal command type %d\n", c->c_type);
}
}
closeconn();
}
/*
* Process commands for sending files to other machines.
*/
static void
doarrow(filev, files, rhost, cmds)
char **filev;
struct namelist *files;
char *rhost;
struct subcmd *cmds;
{
register struct namelist *f;
register struct subcmd *sc;
register char **cpp;
int n, ddir, opts = options;
if (debug)
printf("doarrow(%p, %s, %p)\n", files, rhost, cmds);
if (files == NULL) {
error("no files to be updated\n");
return;
}
subcmds = cmds;
ddir = files->n_next != NULL; /* destination is a directory */
if (nflag)
printf("updating host %s\n", rhost);
else {
if (setjmp(env))
goto done;
signal(SIGPIPE, lostconn);
if (!makeconn(rhost))
return;
if ((lfp = fopen(tempfile, "w")) == NULL) {
fatal("cannot open %s\n", tempfile);
exit(1);
}
}
for (f = files; f != NULL; f = f->n_next) {
if (filev) {
for (cpp = filev; *cpp; cpp++)
if (strcmp(f->n_name, *cpp) == 0)
goto found;
if (!nflag)
(void) fclose(lfp);
continue;
}
found:
n = 0;
for (sc = cmds; sc != NULL; sc = sc->sc_next) {
if (sc->sc_type != INSTALL)
continue;
n++;
install(f->n_name, sc->sc_name,
sc->sc_name == NULL ? 0 : ddir, sc->sc_options);
opts = sc->sc_options;
}
if (n == 0)
install(f->n_name, NULL, 0, options);
}
done:
if (!nflag) {
(void) signal(SIGPIPE, cleanup);
if (lfp)
(void) fclose(lfp);
lfp = NULL;
}
for (sc = cmds; sc != NULL; sc = sc->sc_next)
if (sc->sc_type == NOTIFY)
notify(tempfile, rhost, sc->sc_args, 0);
if (!nflag) {
struct linkbuf *nextihead;
(void) unlink(tempfile);
for (; ihead != NULL; ihead = nextihead) {
nextihead = ihead->nextp;
if ((opts & IGNLNKS) || ihead->count == 0)
continue;
log(lfp, "%s: Warning: missing links\n",
ihead->pathname);
free(ihead);
}
}
}
static int remotecmd(rhost, luser, ruser, cmd)
char *rhost;
char *luser, *ruser;
char *cmd;
{
int desc;
static int port = -1;
if (debug) {
printf("local user = %s remote user = %s\n", luser, ruser);
printf("Remote command = '%s'\n", cmd);
}
(void) fflush(stdout);
(void) fflush(stderr);
(void) signal(SIGALRM, cleanup);
(void) alarm(RTIMEOUT);
if (geteuid() == 0 && strcmp(path_rsh, _PATH_RSH) == 0) {
if (debug)
printf("I am root, therefore direct rcmd\n");
(void) signal(SIGPIPE, cleanup);
if (port < 0) {
struct servent *sp;
if ((sp = getservbyname("shell", "tcp")) == NULL)
fatal("shell/tcp: unknown service");
port = sp->s_port;
}
desc = rcmd(&rhost, port, luser, ruser, cmd, 0);
} else {
if (debug)
printf("Remote shell command = '%s'\n", path_rsh);
(void) signal(SIGPIPE, SIG_IGN);
desc = rshrcmd(&rhost, -1, luser, ruser, cmd, 0);
if (desc > 0)
(void) signal(SIGPIPE, cleanup);
}
(void) alarm(0);
return(desc);
}
/*
* Create a connection to the rdist server on the machine rhost.
*/
static int
makeconn(rhost)
char *rhost;
{
register char *ruser, *cp;
static char *cur_host = NULL;
static int port = -1;
char tuser[20];
int n;
extern char user[];
#if defined(DIRECT_RCMD)
extern int userid;
#endif
if (debug)
printf("makeconn(%s)\n", rhost);
if (cur_host != NULL && rem >= 0) {
if (strcmp(cur_host, rhost) == 0)
return(1);
closeconn();
}
cur_host = rhost;
cp = index(rhost, '@');
if (cp != NULL) {
char c = *cp;
*cp = '\0';
strncpy(tuser, rhost, sizeof(tuser)-1);
*cp = c;
rhost = cp + 1;
ruser = tuser;
if (*ruser == '\0')
ruser = user;
else if (!okname(ruser))
return(0);
} else
ruser = user;
if (!qflag)
printf("updating host %s\n", rhost);
(void) snprintf(buf, sizeof(buf), "%s -Server%s",
_PATH_RDIST, qflag ? " -q" : "");
if (port < 0) {
struct servent *sp;
if ((sp = getservbyname("shell", "tcp")) == NULL)
fatal("shell/tcp: unknown service");
port = sp->s_port;
}
if (debug) {
printf("port = %d, luser = %s, ruser = %s\n", ntohs(port), user, ruser);
printf("buf = %s\n", buf);
}
fflush(stdout);
#if defined(DIRECT_RCMD)
seteuid(0);
rem = rcmd(&rhost, port, user, ruser, buf, 0);
seteuid(userid);
#else
rem = remotecmd(rhost, user, ruser, buf);
#endif
if (rem < 0)
return(0);
cp = buf;
if (read(rem, cp, 1) != 1)
lostconn(0);
if (*cp == 'V') {
do {
if (read(rem, cp, 1) != 1)
lostconn(0);
} while (*cp++ != '\n' && cp < &buf[BUFSIZ]);
*--cp = '\0';
cp = buf;
n = 0;
while (*cp >= '0' && *cp <= '9')
n = (n * 10) + (*cp++ - '0');
if (*cp == '\0' && n == VERSION)
return(1);
error("connection failed: version numbers don't match (local %d, remote %d)\n", VERSION, n);
} else {
error("connection failed: version numbers don't match\n");
error("got unexpected input:");
do {
error("%c", *cp);
} while (*cp != '\n' && read(rem, cp, 1) == 1);
}
closeconn();
return(0);
}
/*
* Signal end of previous connection.
*/
static void
closeconn()
{
if (debug)
printf("closeconn()\n");
if (rem >= 0) {
(void) write(rem, "\2\n", 2);
(void) close(rem);
rem = -1;
}
}
void
lostconn(signo)
int signo;
{
if (iamremote)
cleanup(0);
log(lfp, "rdist: lost connection\n");
longjmp(env, 1);
}
static int
okname(name)
register char *name;
{
register char *cp = name;
register int c;
do {
c = *cp;
if (c & 0200)
goto bad;
if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
goto bad;
cp++;
} while (*cp);
return(1);
bad:
error("invalid user name %s\n", name);
return(0);
}
time_t lastmod;
FILE *tfp;
extern char target[], *tp;
/*
* Process commands for comparing files to time stamp files.
*/
static void
dodcolon(filev, files, stamp, cmds)
char **filev;
struct namelist *files;
char *stamp;
struct subcmd *cmds;
{
register struct subcmd *sc;
register struct namelist *f;
register char **cpp;
struct timeval tv[2];
struct timezone tz;
struct stat stb;
if (debug)
printf("dodcolon()\n");
if (files == NULL) {
error("no files to be updated\n");
return;
}
if (stat(stamp, &stb) < 0) {
error("%s: %s\n", stamp, strerror(errno));
return;
}
if (debug)
printf("%s: %ld\n", stamp, stb.st_mtime);
subcmds = cmds;
lastmod = stb.st_mtime;
if (nflag || (options & VERIFY))
tfp = NULL;
else {
if ((tfp = fopen(tempfile, "w")) == NULL) {
error("%s: %s\n", stamp, strerror(errno));
return;
}
(void) gettimeofday(&tv[0], &tz);
tv[1] = tv[0];
(void) utimes(stamp, tv);
}
for (f = files; f != NULL; f = f->n_next) {
if (filev) {
for (cpp = filev; *cpp; cpp++)
if (strcmp(f->n_name, *cpp) == 0)
goto found;
continue;
}
found:
tp = NULL;
cmptime(f->n_name);
}
if (tfp != NULL)
(void) fclose(tfp);
for (sc = cmds; sc != NULL; sc = sc->sc_next)
if (sc->sc_type == NOTIFY)
notify(tempfile, NULL, sc->sc_args, lastmod);
if (!nflag && !(options & VERIFY))
(void) unlink(tempfile);
}
/*
* Compare the mtime of file to the list of time stamps.
*/
static void
cmptime(name)
char *name;
{
struct stat stb;
if (debug)
printf("cmptime(%s)\n", name);
if (except(name))
return;
if (nflag) {
printf("comparing dates: %s\n", name);
return;
}
/*
* first time cmptime() is called?
*/
if (tp == NULL) {
if (exptilde(target, name, sizeof(target)) == NULL)
return;
tp = name = target;
while (*tp)
tp++;
}
if (access(name, 4) < 0 || stat(name, &stb) < 0) {
error("%s: %s\n", name, strerror(errno));
return;
}
switch (stb.st_mode & S_IFMT) {
case S_IFREG:
break;
case S_IFDIR:
rcmptime(&stb);
return;
default:
error("%s: not a plain file\n", name);
return;
}
if (stb.st_mtime > lastmod)
log(tfp, "new: %s\n", name);
}
static void
rcmptime(st)
struct stat *st;
{
register DIR *d;
register struct dirent *dp;
register char *cp;
char *otp;
int len;
if (debug)
printf("rcmptime(%p)\n", st);
if ((d = opendir(target)) == NULL) {
error("%s: %s\n", target, strerror(errno));
return;
}
otp = tp;
len = tp - target;
while ((dp = readdir(d))) {
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
continue;
if (len + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
error("%s/%s: Name too long\n", target, dp->d_name);
continue;
}
tp = otp;
*tp++ = '/';
cp = dp->d_name;
while ((*tp++ = *cp++))
;
tp--;
cmptime(target);
}
closedir(d);
tp = otp;
*tp = '\0';
}
/*
* Notify the list of people the changes that were made.
* rhost == NULL if we are mailing a list of changes compared to at time
* stamp file.
*/
static void
notify(file, rhost, to, lmod)
char *file, *rhost;
register struct namelist *to;
time_t lmod;
{
register int fd, len;
struct stat stb;
FILE *pf;
if ((options & VERIFY) || to == NULL)
return;
if (!qflag) {
printf("notify ");
if (rhost)
printf("@%s ", rhost);
prnames(to);
}
if (nflag)
return;
if ((fd = open(file, 0)) < 0) {
error("%s: %s\n", file, strerror(errno));
return;
}
if (fstat(fd, &stb) < 0) {
error("%s: %s\n", file, strerror(errno));
(void) close(fd);
return;
}
if (stb.st_size == 0) {
(void) close(fd);
return;
}
/*
* Create a pipe to mailling program.
*/
(void) snprintf(buf, sizeof(buf), "%s -oi -t", _PATH_SENDMAIL);
pf = popen(buf, "w");
if (pf == NULL) {
error("notify: \"%s\" failed\n", _PATH_SENDMAIL);
(void) close(fd);
return;
}
/*
* Output the proper header information.
*/
fprintf(pf, "From: rdist (Remote distribution program)\n");
fprintf(pf, "To:");
if (!any('@', to->n_name) && rhost != NULL)
fprintf(pf, " %s@%s", to->n_name, rhost);
else
fprintf(pf, " %s", to->n_name);
to = to->n_next;
while (to != NULL) {
if (!any('@', to->n_name) && rhost != NULL)
fprintf(pf, ", %s@%s", to->n_name, rhost);
else
fprintf(pf, ", %s", to->n_name);
to = to->n_next;
}
putc('\n', pf);
if (rhost != NULL)
fprintf(pf, "Subject: files updated by rdist from %s to %s\n",
host, rhost);
else
fprintf(pf, "Subject: files updated after %s\n", ctime(&lmod));
putc('\n', pf);
while ((len = read(fd, buf, BUFSIZ)) > 0)
(void) fwrite(buf, 1, len, pf);
(void) close(fd);
(void) pclose(pf);
}
/*
* Return true if name is in the list.
*/
int
inlist(list, file)
struct namelist *list;
char *file;
{
register struct namelist *nl;
for (nl = list; nl != NULL; nl = nl->n_next)
if (!strcmp(file, nl->n_name))
return(1);
return(0);
}
/*
* Return TRUE if file is in the exception list.
*/
int
except(file)
char *file;
{
register struct subcmd *sc;
register struct namelist *nl;
regex_t rx;
int val;
if (debug)
printf("except(%s)\n", file);
for (sc = subcmds; sc != NULL; sc = sc->sc_next) {
if (sc->sc_type != EXCEPT && sc->sc_type != PATTERN)
continue;
for (nl = sc->sc_args; nl != NULL; nl = nl->n_next) {
if (sc->sc_type == EXCEPT) {
if (!strcmp(file, nl->n_name))
return(1);
continue;
}
val = regcomp(&rx, nl->n_name,
REG_EXTENDED | REG_NOSUB);
if (!regexec(&rx, file, 0, 0, 0)) {
regfree(&rx);
return 1;
}
regfree(&rx);
}
}
return(0);
}
char *
colon(cp)
register char *cp;
{
while (*cp) {
if (*cp == ':')
return(cp);
if (*cp == '/')
return(0);
cp++;
}
return(0);
}

View File

@ -1,677 +0,0 @@
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
#if 0
static char sccsid[] = "@(#)expand.c 8.1 (Berkeley) 6/9/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "defs.h"
#define GAVSIZ NCARGS / 6
#define LC '{'
#define RC '}'
static char shchars[] = "${[*?";
int which; /* bit mask of types to expand */
int eargc; /* expanded arg count */
char **eargv; /* expanded arg vectors */
char *path;
char *pathp;
char *lastpathp;
char *tilde; /* "~user" if not expanding tilde, else "" */
char *tpathp;
int nleft;
int expany; /* any expansions done? */
char *entp;
char **sortbase;
#define sort() qsort((char *)sortbase, &eargv[eargc] - sortbase, \
sizeof(*sortbase), argcmp), sortbase = &eargv[eargc]
static void Cat __P((char *, char *));
static void addpath __P((int));
static int amatch __P((char *, char *));
static int argcmp __P((const void *, const void *));
static int execbrc __P((char *, char *));
static void expsh __P((char *));
static void expstr __P((char *));
static int match __P((char *, char *));
static void matchdir __P((char *));
static int smatch __P((char *, char *));
/*
* Take a list of names and expand any macros, etc.
* wh = E_VARS if expanding variables.
* wh = E_SHELL if expanding shell characters.
* wh = E_TILDE if expanding `~'.
* or any of these or'ed together.
*
* Major portions of this were snarfed from csh/sh.glob.c.
*/
struct namelist *
expand(list, wh)
struct namelist *list;
int wh;
{
register struct namelist *nl, *prev;
register int n;
char pathbuf[BUFSIZ];
char *argvbuf[GAVSIZ];
if (debug) {
printf("expand(%p, %d)\nlist = ", list, wh);
prnames(list);
}
if (wh == 0) {
register char *cp;
for (nl = list; nl != NULL; nl = nl->n_next)
for (cp = nl->n_name; *cp; cp++)
*cp = *cp & TRIM;
return(list);
}
which = wh;
path = tpathp = pathp = pathbuf;
*pathp = '\0';
lastpathp = &path[sizeof pathbuf - 2];
tilde = "";
eargc = 0;
eargv = sortbase = argvbuf;
*eargv = 0;
nleft = NCARGS - 4;
/*
* Walk the name list and expand names into eargv[];
*/
for (nl = list; nl != NULL; nl = nl->n_next)
expstr(nl->n_name);
/*
* Take expanded list of names from eargv[] and build a new list.
*/
list = prev = NULL;
for (n = 0; n < eargc; n++) {
nl = makenl(NULL);
nl->n_name = eargv[n];
if (prev == NULL)
list = prev = nl;
else {
prev->n_next = nl;
prev = nl;
}
}
if (debug) {
printf("expanded list = ");
prnames(list);
}
return(list);
}
static void
expstr(s)
char *s;
{
register char *cp, *cp1;
register struct namelist *tp;
char *tail;
char buf[BUFSIZ];
int savec, oeargc;
extern char homedir[];
if (s == NULL || *s == '\0')
return;
if ((which & E_VARS) && (cp = index(s, '$')) != NULL) {
*cp++ = '\0';
if (*cp == '\0') {
yyerror("no variable name after '$'");
return;
}
if (*cp == LC) {
cp++;
if ((tail = index(cp, RC)) == NULL) {
yyerror("unmatched '{'");
return;
}
*tail++ = savec = '\0';
if (*cp == '\0') {
yyerror("no variable name after '$'");
return;
}
} else {
tail = cp + 1;
savec = *tail;
*tail = '\0';
}
tp = lookup(cp, NULL, 0);
if (savec != '\0')
*tail = savec;
if (tp != NULL) {
for (; tp != NULL; tp = tp->n_next) {
snprintf(buf, sizeof(buf),
"%s%s%s", s, tp->n_name, tail);
expstr(buf);
}
return;
}
snprintf(buf, sizeof(buf), "%s%s", s, tail);
expstr(buf);
return;
}
if ((which & ~E_VARS) == 0 || !strcmp(s, "{") || !strcmp(s, "{}")) {
Cat(s, "");
sort();
return;
}
if (*s == '~') {
cp = ++s;
if (*cp == '\0' || *cp == '/') {
tilde = "~";
cp1 = homedir;
} else {
tilde = cp1 = buf;
*cp1++ = '~';
do
*cp1++ = *cp++;
while (*cp && *cp != '/');
*cp1 = '\0';
if (pw == NULL || strcmp(pw->pw_name, buf+1) != 0) {
if ((pw = getpwnam(buf+1)) == NULL) {
strcat(buf, ": unknown user name");
yyerror(buf+1);
return;
}
}
cp1 = pw->pw_dir;
s = cp;
}
for (cp = path; (*cp++ = *cp1++); )
;
tpathp = pathp = cp - 1;
} else {
tpathp = pathp = path;
tilde = "";
}
*pathp = '\0';
if (!(which & E_SHELL)) {
if (which & E_TILDE)
Cat(path, s);
else
Cat(tilde, s);
sort();
return;
}
oeargc = eargc;
expany = 0;
expsh(s);
if (eargc == oeargc)
Cat(s, ""); /* "nonomatch" is set */
sort();
}
static int
argcmp(a1, a2)
const void *a1, *a2;
{
return (strcmp(*(char **)a1, *(char **)a2));
}
/*
* If there are any Shell meta characters in the name,
* expand into a list, after searching directory
*/
static void
expsh(s)
char *s;
{
register char *cp;
register char *spathp, *oldcp;
struct stat stb;
spathp = pathp;
cp = s;
while (!any(*cp, shchars)) {
if (*cp == '\0') {
if (!expany || stat(path, &stb) >= 0) {
if (which & E_TILDE)
Cat(path, "");
else
Cat(tilde, tpathp);
}
goto endit;
}
addpath(*cp++);
}
oldcp = cp;
while (cp > s && *cp != '/')
cp--, pathp--;
if (*cp == '/')
cp++, pathp++;
*pathp = '\0';
if (*oldcp == '{') {
execbrc(cp, NULL);
return;
}
matchdir(cp);
endit:
pathp = spathp;
*pathp = '\0';
}
static void
matchdir(pattern)
char *pattern;
{
struct stat stb;
register struct dirent *dp;
DIR *dirp;
dirp = opendir(path);
if (dirp == NULL) {
if (expany)
return;
goto patherr2;
}
if (fstat(dirp->dd_fd, &stb) < 0)
goto patherr1;
if (!ISDIR(stb.st_mode)) {
errno = ENOTDIR;
goto patherr1;
}
while ((dp = readdir(dirp)) != NULL)
if (match(dp->d_name, pattern)) {
if (which & E_TILDE)
Cat(path, dp->d_name);
else {
strcpy(pathp, dp->d_name);
Cat(tilde, tpathp);
*pathp = '\0';
}
}
closedir(dirp);
return;
patherr1:
closedir(dirp);
patherr2:
strcat(path, ": ");
strcat(path, strerror(errno));
yyerror(path);
}
static int
execbrc(p, s)
char *p, *s;
{
char restbuf[BUFSIZ + 2];
register char *pe, *pm, *pl;
int brclev = 0;
char *lm, savec, *spathp;
for (lm = restbuf; *p != '{'; *lm++ = *p++)
continue;
for (pe = ++p; *pe; pe++)
switch (*pe) {
case '{':
brclev++;
continue;
case '}':
if (brclev == 0)
goto pend;
brclev--;
continue;
case '[':
for (pe++; *pe && *pe != ']'; pe++)
continue;
if (!*pe)
yyerror("Missing ']'");
continue;
}
pend:
if (brclev || !*pe) {
yyerror("Missing '}'");
return (0);
}
for (pl = pm = p; pm <= pe; pm++)
switch (*pm & (QUOTE|TRIM)) {
case '{':
brclev++;
continue;
case '}':
if (brclev) {
brclev--;
continue;
}
goto doit;
case ',':
if (brclev)
continue;
doit:
savec = *pm;
*pm = 0;
strcpy(lm, pl);
strcat(restbuf, pe + 1);
*pm = savec;
if (s == 0) {
spathp = pathp;
expsh(restbuf);
pathp = spathp;
*pathp = 0;
} else if (amatch(s, restbuf))
return (1);
sort();
pl = pm + 1;
continue;
case '[':
for (pm++; *pm && *pm != ']'; pm++)
continue;
if (!*pm)
yyerror("Missing ']'");
continue;
}
return (0);
}
static int
match(s, p)
char *s, *p;
{
register int c;
register char *sentp;
char sexpany = expany;
if (*s == '.' && *p != '.')
return (0);
sentp = entp;
entp = s;
c = amatch(s, p);
entp = sentp;
expany = sexpany;
return (c);
}
static int
amatch(s, p)
register char *s, *p;
{
register int scc;
int ok, lc;
char *spathp;
struct stat stb;
int c, cc;
expany = 1;
for (;;) {
scc = *s++ & TRIM;
switch (c = *p++) {
case '{':
return (execbrc(p - 1, s - 1));
case '[':
ok = 0;
lc = 077777;
while ((cc = *p++)) {
if (cc == ']') {
if (ok)
break;
return (0);
}
if (cc == '-') {
if (lc <= scc && scc <= *p++)
ok++;
} else
if (scc == (lc = cc))
ok++;
}
if (cc == 0) {
yyerror("Missing ']'");
return (0);
}
continue;
case '*':
if (!*p)
return (1);
if (*p == '/') {
p++;
goto slash;
}
for (s--; *s; s++)
if (amatch(s, p))
return (1);
return (0);
case '\0':
return (scc == '\0');
default:
if ((c & TRIM) != scc)
return (0);
continue;
case '?':
if (scc == '\0')
return (0);
continue;
case '/':
if (scc)
return (0);
slash:
s = entp;
spathp = pathp;
while (*s)
addpath(*s++);
addpath('/');
if (stat(path, &stb) == 0 && ISDIR(stb.st_mode)) {
if (*p == '\0') {
if (which & E_TILDE)
Cat(path, "");
else
Cat(tilde, tpathp);
} else
expsh(p);
}
pathp = spathp;
*pathp = '\0';
return (0);
}
}
}
static int
smatch(s, p)
register char *s, *p;
{
register int scc;
int ok, lc;
int c, cc;
for (;;) {
scc = *s++ & TRIM;
switch (c = *p++) {
case '[':
ok = 0;
lc = 077777;
while ((cc = *p++)) {
if (cc == ']') {
if (ok)
break;
return (0);
}
if (cc == '-') {
if (lc <= scc && scc <= *p++)
ok++;
} else
if (scc == (lc = cc))
ok++;
}
if (cc == 0) {
yyerror("Missing ']'");
return (0);
}
continue;
case '*':
if (!*p)
return (1);
for (s--; *s; s++)
if (smatch(s, p))
return (1);
return (0);
case '\0':
return (scc == '\0');
default:
if ((c & TRIM) != scc)
return (0);
continue;
case '?':
if (scc == 0)
return (0);
continue;
}
}
}
static void
Cat(s1, s2)
register char *s1, *s2;
{
int len = strlen(s1) + strlen(s2) + 1;
register char *s;
nleft -= len;
if (nleft <= 0 || ++eargc >= GAVSIZ)
yyerror("Arguments too long");
eargv[eargc] = 0;
eargv[eargc - 1] = s = malloc(len);
if (s == NULL)
fatal("ran out of memory\n");
while ((*s++ = *s1++ & TRIM))
;
s--;
while ((*s++ = *s2++ & TRIM))
;
}
static void
addpath(c)
int c;
{
if (pathp >= lastpathp)
yyerror("Pathname too long");
else {
*pathp++ = c & TRIM;
*pathp = '\0';
}
}
/*
* Expand file names beginning with `~' into the
* user's home directory path name. Return a pointer in buf to the
* part corresponding to `file'.
*/
char *
exptilde(buf, file, maxlen)
char buf[];
register char *file;
int maxlen;
{
register char *s1, *s2, *s3;
extern char homedir[];
if (strlen(file) >= maxlen)
return(NULL);
if (*file != '~') {
strcpy(buf, file);
return(buf);
}
if (*++file == '\0') {
s2 = homedir;
s3 = NULL;
} else if (*file == '/') {
s2 = homedir;
s3 = file;
} else {
s3 = file;
while (*s3 && *s3 != '/')
s3++;
if (*s3 == '/')
*s3 = '\0';
else
s3 = NULL;
if (pw == NULL || strcmp(pw->pw_name, file) != 0) {
if ((pw = getpwnam(file)) == NULL) {
error("%s: unknown user name\n", file);
if (s3 != NULL)
*s3 = '/';
return(NULL);
}
}
if (s3 != NULL)
*s3 = '/';
s2 = pw->pw_dir;
}
for (s1 = buf; (*s1++ = *s2++) && s1 < buf+maxlen; )
;
s2 = --s1;
if (s3 != NULL && s1 < buf+maxlen) {
s2++;
while ((*s1++ = *s3++) && s1 < buf+maxlen)
;
}
if (s1 == buf+maxlen)
return(NULL);
return(s2);
}

View File

@ -1,523 +0,0 @@
%{
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
#if 0
static char sccsid[] = "@(#)gram.y 8.1 (Berkeley) 6/9/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "defs.h"
#include <sys/types.h>
#include <regex.h>
#include <limits.h>
struct cmd *cmds = NULL;
struct cmd *last_cmd;
struct namelist *last_n;
struct subcmd *last_sc;
static char *makestr __P((char *));
%}
%term EQUAL 1
%term LP 2
%term RP 3
%term SM 4
%term ARROW 5
%term COLON 6
%term DCOLON 7
%term NAME 8
%term STRING 9
%term INSTALL 10
%term NOTIFY 11
%term EXCEPT 12
%term PATTERN 13
%term SPECIAL 14
%term OPTION 15
%union {
int intval;
char *string;
struct subcmd *subcmd;
struct namelist *namel;
}
%type <intval> OPTION, options
%type <string> NAME, STRING
%type <subcmd> INSTALL, NOTIFY, EXCEPT, PATTERN, SPECIAL, cmdlist, cmd
%type <namel> namelist, names, opt_namelist
%%
file: /* VOID */
| file command
;
command: NAME EQUAL namelist = {
(void) lookup($1, INSERT, $3);
}
| namelist ARROW namelist cmdlist = {
insert(NULL, $1, $3, $4);
}
| NAME COLON namelist ARROW namelist cmdlist = {
insert($1, $3, $5, $6);
}
| namelist DCOLON NAME cmdlist = {
append(NULL, $1, $3, $4);
}
| NAME COLON namelist DCOLON NAME cmdlist = {
append($1, $3, $5, $6);
}
| error
;
namelist: NAME = {
$$ = makenl($1);
}
| LP names RP = {
$$ = $2;
}
;
names: /* VOID */ {
$$ = last_n = NULL;
}
| names NAME = {
if (last_n == NULL)
$$ = last_n = makenl($2);
else {
last_n->n_next = makenl($2);
last_n = last_n->n_next;
$$ = $1;
}
}
;
cmdlist: /* VOID */ {
$$ = last_sc = NULL;
}
| cmdlist cmd = {
if (last_sc == NULL)
$$ = last_sc = $2;
else {
last_sc->sc_next = $2;
last_sc = $2;
$$ = $1;
}
}
;
cmd: INSTALL options opt_namelist SM = {
register struct namelist *nl;
$1->sc_options = $2 | options;
if ($3 != NULL) {
nl = expand($3, E_VARS);
if (nl) {
if (nl->n_next != NULL)
yyerror("only one name allowed\n");
$1->sc_name = nl->n_name;
free(nl);
} else
$1->sc_name = NULL;
}
$$ = $1;
}
| NOTIFY namelist SM = {
if ($2 != NULL)
$1->sc_args = expand($2, E_VARS);
$$ = $1;
}
| EXCEPT namelist SM = {
if ($2 != NULL)
$1->sc_args = expand($2, E_ALL);
$$ = $1;
}
| PATTERN namelist SM = {
struct namelist *nl;
regex_t rx;
int val;
char errbuf[_POSIX2_LINE_MAX];
for (nl = $2; nl != NULL; nl = nl->n_next) {
if ((val = regcomp(&rx, nl->n_name,
REG_EXTENDED))) {
regerror(val, &rx, errbuf,
sizeof errbuf);
yyerror(errbuf);
}
regfree(&rx);
}
$1->sc_args = expand($2, E_VARS);
$$ = $1;
}
| SPECIAL opt_namelist STRING SM = {
if ($2 != NULL)
$1->sc_args = expand($2, E_ALL);
$1->sc_name = $3;
$$ = $1;
}
;
options: /* VOID */ = {
$$ = 0;
}
| options OPTION = {
$$ |= $2;
}
;
opt_namelist: /* VOID */ = {
$$ = NULL;
}
| namelist = {
$$ = $1;
}
;
%%
int yylineno = 1;
extern FILE *fin;
int
yylex()
{
static char yytext[INMAX];
register int c;
register char *cp1, *cp2;
static char quotechars[] = "[]{}*?$";
again:
switch (c = getc(fin)) {
case EOF: /* end of file */
return(0);
case '#': /* start of comment */
while ((c = getc(fin)) != EOF && c != '\n')
;
if (c == EOF)
return(0);
case '\n':
yylineno++;
case ' ':
case '\t': /* skip blanks */
goto again;
case '=': /* EQUAL */
return(EQUAL);
case '(': /* LP */
return(LP);
case ')': /* RP */
return(RP);
case ';': /* SM */
return(SM);
case '-': /* -> */
if ((c = getc(fin)) == '>')
return(ARROW);
ungetc(c, fin);
c = '-';
break;
case '"': /* STRING */
cp1 = yytext;
cp2 = &yytext[INMAX - 1];
for (;;) {
if (cp1 >= cp2) {
yyerror("command string too long\n");
break;
}
c = getc(fin);
if (c == EOF || c == '"')
break;
if (c == '\\') {
if ((c = getc(fin)) == EOF) {
*cp1++ = '\\';
break;
}
}
if (c == '\n') {
yylineno++;
c = ' '; /* can't send '\n' */
}
*cp1++ = c;
}
if (c != '"')
yyerror("missing closing '\"'\n");
*cp1 = '\0';
yylval.string = makestr(yytext);
return(STRING);
case ':': /* : or :: */
if ((c = getc(fin)) == ':')
return(DCOLON);
ungetc(c, fin);
return(COLON);
}
cp1 = yytext;
cp2 = &yytext[INMAX - 1];
for (;;) {
if (cp1 >= cp2) {
yyerror("input line too long\n");
break;
}
if (c == '\\') {
if ((c = getc(fin)) != EOF) {
if (any(c, quotechars))
c |= QUOTE;
} else {
*cp1++ = '\\';
break;
}
}
*cp1++ = c;
c = getc(fin);
if (c == EOF || any(c, " \"'\t()=;:\n")) {
ungetc(c, fin);
break;
}
}
*cp1 = '\0';
if (yytext[0] == '-' && yytext[2] == '\0') {
switch (yytext[1]) {
case 'b':
yylval.intval = COMPARE;
return(OPTION);
case 'R':
yylval.intval = REMOVE;
return(OPTION);
case 'v':
yylval.intval = VERIFY;
return(OPTION);
case 'w':
yylval.intval = WHOLE;
return(OPTION);
case 'y':
yylval.intval = YOUNGER;
return(OPTION);
case 'h':
yylval.intval = FOLLOW;
return(OPTION);
case 'i':
yylval.intval = IGNLNKS;
return(OPTION);
}
}
if (!strcmp(yytext, "install"))
c = INSTALL;
else if (!strcmp(yytext, "notify"))
c = NOTIFY;
else if (!strcmp(yytext, "except"))
c = EXCEPT;
else if (!strcmp(yytext, "except_pat"))
c = PATTERN;
else if (!strcmp(yytext, "special"))
c = SPECIAL;
else {
yylval.string = makestr(yytext);
return(NAME);
}
yylval.subcmd = makesubcmd(c);
return(c);
}
int
any(c, str)
register int c;
register char *str;
{
while (*str)
if (c == *str++)
return(1);
return(0);
}
/*
* Insert or append ARROW command to list of hosts to be updated.
*/
void
insert(label, files, hosts, subcmds)
char *label;
struct namelist *files, *hosts;
struct subcmd *subcmds;
{
register struct cmd *c, *prev, *nc;
register struct namelist *h, *next_h;
files = expand(files, E_VARS|E_SHELL);
hosts = expand(hosts, E_ALL);
for (h = hosts; h != NULL; next_h = h->n_next, free(h), h = next_h) {
/*
* Search command list for an update to the same host.
*/
for (prev = NULL, c = cmds; c!=NULL; prev = c, c = c->c_next) {
if (strcmp(c->c_name, h->n_name) == 0) {
do {
prev = c;
c = c->c_next;
} while (c != NULL &&
strcmp(c->c_name, h->n_name) == 0);
break;
}
}
/*
* Insert new command to update host.
*/
nc = ALLOC(cmd);
if (nc == NULL)
fatal("ran out of memory\n");
nc->c_type = ARROW;
nc->c_name = h->n_name;
nc->c_label = label;
nc->c_files = files;
nc->c_cmds = subcmds;
nc->c_next = c;
if (prev == NULL)
cmds = nc;
else
prev->c_next = nc;
/* update last_cmd if appending nc to cmds */
if (c == NULL)
last_cmd = nc;
}
}
/*
* Append DCOLON command to the end of the command list since these are always
* executed in the order they appear in the distfile.
*/
void
append(label, files, stamp, subcmds)
char *label;
struct namelist *files;
char *stamp;
struct subcmd *subcmds;
{
register struct cmd *c;
c = ALLOC(cmd);
if (c == NULL)
fatal("ran out of memory\n");
c->c_type = DCOLON;
c->c_name = stamp;
c->c_label = label;
c->c_files = expand(files, E_ALL);
c->c_cmds = subcmds;
c->c_next = NULL;
if (cmds == NULL)
cmds = last_cmd = c;
else {
last_cmd->c_next = c;
last_cmd = c;
}
}
/*
* Error printing routine in parser.
*/
void
yyerror(s)
char *s;
{
++nerrs;
fflush(stdout);
fprintf(stderr, "rdist: line %d: %s\n", yylineno, s);
}
/*
* Return a copy of the string.
*/
static char *
makestr(str)
char *str;
{
register char *cp, *s;
str = cp = malloc(strlen(s = str) + 1);
if (cp == NULL)
fatal("ran out of memory\n");
while ((*cp++ = *s++))
;
return(str);
}
/*
* Allocate a namelist structure.
*/
struct namelist *
makenl(name)
char *name;
{
register struct namelist *nl;
nl = ALLOC(namelist);
if (nl == NULL)
fatal("ran out of memory\n");
nl->n_name = name;
nl->n_next = NULL;
return(nl);
}
/*
* Make a sub command for lists of variables, commands, etc.
*/
struct subcmd *
makesubcmd(type)
int type;
{
register struct subcmd *sc;
sc = ALLOC(subcmd);
if (sc == NULL)
fatal("ran out of memory\n");
sc->sc_type = type;
sc->sc_args = NULL;
sc->sc_next = NULL;
sc->sc_name = NULL;
return(sc);
}

View File

@ -1,171 +0,0 @@
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
#if 0
static char sccsid[] = "@(#)lookup.c 8.1 (Berkeley) 6/9/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "defs.h"
/* symbol types */
#define VAR 1
#define CONST 2
struct syment {
int s_type;
char *s_name;
struct namelist *s_value;
struct syment *s_next;
};
static struct syment *hashtab[HASHSIZE];
/*
* Define a variable from a command line argument.
*/
void
define(name)
char *name;
{
register char *cp, *s;
register struct namelist *nl;
struct namelist *value = NULL;
if (debug)
printf("define(%s)\n", name);
cp = index(name, '=');
if (cp == NULL)
value = NULL;
else if (cp[1] == '\0') {
*cp = '\0';
value = NULL;
} else if (cp[1] != '(') {
*cp++ = '\0';
value = makenl(cp);
} else {
nl = NULL;
*cp++ = '\0';
do
cp++;
while (*cp == ' ' || *cp == '\t');
for (s = cp; ; s++) {
switch (*s) {
case ')':
*s = '\0';
case '\0':
break;
case ' ':
case '\t':
*s++ = '\0';
while (*s == ' ' || *s == '\t')
s++;
if (*s == ')')
*s = '\0';
break;
default:
continue;
}
if (nl == NULL)
value = nl = makenl(cp);
else {
nl->n_next = makenl(cp);
nl = nl->n_next;
}
if (*s == '\0')
break;
cp = s;
}
}
(void) lookup(name, REPLACE, value);
}
/*
* Lookup name in the table and return a pointer to it.
* LOOKUP - just do lookup, return NULL if not found.
* INSERT - insert name with value, error if already defined.
* REPLACE - insert or replace name with value.
*/
struct namelist *
lookup(name, action, value)
char *name;
int action;
struct namelist *value;
{
register unsigned n;
register char *cp;
register struct syment *s;
char buf[BUFSIZ];
if (debug)
printf("lookup(%s, %d, %p)\n", name, action, value);
n = 0;
for (cp = name; *cp; )
n += *cp++;
n %= HASHSIZE;
for (s = hashtab[n]; s != NULL; s = s->s_next) {
if (strcmp(name, s->s_name))
continue;
if (action != LOOKUP) {
if (action != INSERT || s->s_type != CONST) {
(void)snprintf(buf, sizeof(buf),
"%s redefined", name);
yyerror(buf);
}
}
return(s->s_value);
}
if (action == LOOKUP) {
(void)snprintf(buf, sizeof(buf), "%s undefined", name);
yyerror(buf);
return(NULL);
}
s = ALLOC(syment);
if (s == NULL)
fatal("ran out of memory\n");
s->s_next = hashtab[n];
hashtab[n] = s;
s->s_type = action == INSERT ? VAR : CONST;
s->s_name = name;
s->s_value = value;
return(value);
}

View File

@ -1,337 +0,0 @@
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1983, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#if 0
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/9/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "defs.h"
#define NHOSTS 100
/*
* Remote distribution program.
*/
char *distfile = NULL;
#define _RDIST_TMP "/rdistXXXXXX"
char tempfile[sizeof _PATH_TMP + sizeof _RDIST_TMP + 1];
char *tempname;
int debug; /* debugging flag */
int nflag; /* NOP flag, just print commands without executing */
int qflag; /* Quiet. Don't print messages */
int options; /* global options */
int iamremote; /* act as remote server for transfering files */
FILE *fin = NULL; /* input file pointer */
int rem = -1; /* file descriptor to remote source/sink process */
char host[32]; /* host name */
int nerrs; /* number of errors while sending/receiving */
char user[10]; /* user's name */
char homedir[128]; /* user's home directory */
int userid; /* user's user ID */
int groupid; /* user's group ID */
char *path_rsh = _PATH_RSH; /* rsh (or equiv command) path */
struct passwd *pw; /* pointer to static area used by getpwent */
struct group *gr; /* pointer to static area used by getgrent */
static void usage __P((void));
static void docmdargs __P((int, char *[]));
int
main(argc, argv)
int argc;
char *argv[];
{
register char *arg;
int cmdargs = 0;
char *dhosts[NHOSTS], **hp = dhosts;
pw = getpwuid(userid = getuid());
if (pw == NULL) {
fprintf(stderr, "%s: Who are you?\n", argv[0]);
exit(1);
}
strcpy(user, pw->pw_name);
strcpy(homedir, pw->pw_dir);
groupid = pw->pw_gid;
gethostname(host, sizeof(host));
strcpy(tempfile, _PATH_TMP);
strcat(tempfile, _RDIST_TMP);
if ((tempname = rindex(tempfile, '/')) != 0)
tempname++;
else
tempname = tempfile;
while (--argc > 0) {
if ((arg = *++argv)[0] != '-')
break;
if (!strcmp(arg, "-Server"))
iamremote++;
else while (*++arg)
switch (*arg) {
case 'P':
if (--argc <= 0)
usage();
path_rsh = *++argv;
break;
case 'f':
if (--argc <= 0)
usage();
distfile = *++argv;
if (distfile[0] == '-' && distfile[1] == '\0')
fin = stdin;
break;
case 'm':
if (--argc <= 0)
usage();
if (hp >= &dhosts[NHOSTS-2]) {
fprintf(stderr, "rdist: too many destination hosts\n");
exit(1);
}
*hp++ = *++argv;
break;
case 'd':
if (--argc <= 0)
usage();
define(*++argv);
break;
case 'D':
debug++;
break;
case 'c':
cmdargs++;
break;
case 'n':
if (options & VERIFY) {
printf("rdist: -n overrides -v\n");
options &= ~VERIFY;
}
nflag++;
break;
case 'q':
qflag++;
break;
case 'b':
options |= COMPARE;
break;
case 'R':
options |= REMOVE;
break;
case 'v':
if (nflag) {
printf("rdist: -n overrides -v\n");
break;
}
options |= VERIFY;
break;
case 'w':
options |= WHOLE;
break;
case 'y':
options |= YOUNGER;
break;
case 'h':
options |= FOLLOW;
break;
case 'i':
options |= IGNLNKS;
break;
default:
usage();
}
}
*hp = NULL;
seteuid(userid);
mktemp(tempfile);
if (iamremote) {
server();
exit(nerrs != 0);
}
if (cmdargs)
docmdargs(argc, argv);
else {
if (fin == NULL) {
if(distfile == NULL) {
if((fin = fopen("distfile","r")) == NULL)
fin = fopen("Distfile", "r");
} else
fin = fopen(distfile, "r");
if(fin == NULL) {
perror(distfile ? distfile : "distfile");
exit(1);
}
}
yyparse();
if (nerrs == 0)
docmds(dhosts, argc, argv);
}
exit(nerrs != 0);
}
static void
usage()
{
printf("%s\n%s\n%s\n",
"usage: rdist [-nqbhirvwyD] [-P /path/to/rsh ] [-f distfile] [-d var=value]",
" [-m host] [file ...]",
" rdist [-nqbhirvwyD] [-P /path/to/rsh ] -c source [...] machine[:dest]");
exit(1);
}
/*
* rcp like interface for distributing files.
*/
static void
docmdargs(nargs, args)
int nargs;
char *args[];
{
register struct namelist *nl, *prev;
register char *cp;
struct namelist *files = NULL, *hosts;
struct subcmd *cmds;
char *dest;
static struct namelist tnl = { NULL, NULL };
int i;
if (nargs < 2)
usage();
prev = NULL;
for (i = 0; i < nargs - 1; i++) {
nl = makenl(args[i]);
if (prev == NULL)
files = prev = nl;
else {
prev->n_next = nl;
prev = nl;
}
}
cp = args[i];
if ((dest = index(cp, ':')) != NULL)
*dest++ = '\0';
tnl.n_name = cp;
hosts = expand(&tnl, E_ALL);
if (nerrs)
exit(1);
if (dest == NULL || *dest == '\0')
cmds = NULL;
else {
cmds = makesubcmd(INSTALL);
cmds->sc_options = options;
cmds->sc_name = dest;
}
if (debug) {
printf("docmdargs()\nfiles = ");
prnames(files);
printf("hosts = ");
prnames(hosts);
}
insert(NULL, files, hosts, cmds);
docmds(NULL, 0, NULL);
}
/*
* Print a list of NAME blocks (mostly for debugging).
*/
void
prnames(nl)
register struct namelist *nl;
{
printf("( ");
while (nl != NULL) {
printf("%s ", nl->n_name);
nl = nl->n_next;
}
printf(")\n");
}
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
void
#if __STDC__
warn(const char *fmt, ...)
#else
warn(fmt, va_alist)
char *fmt;
va_dcl
#endif
{
extern int yylineno;
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
(void)fprintf(stderr, "rdist: line %d: Warning: ", yylineno);
(void)vfprintf(stderr, fmt, ap);
(void)fprintf(stderr, "\n");
va_end(ap);
}

View File

@ -1,39 +0,0 @@
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)pathnames.h 8.1 (Berkeley) 6/9/93
*/
#include <paths.h>
#define _PATH_RDIST "rdist"
#define _PATH_RSH "/usr/bin/rsh"

View File

@ -1,119 +0,0 @@
/*
* This is an rcmd() replacement originally by
* Chris Siebenmann <cks@utcc.utoronto.ca>.
*/
#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include "defs.h"
#if !defined(DIRECT_RCMD)
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
#include <netdb.h>
static char *
xbasename(s)
char *s;
{
char *ret;
ret = strrchr(s, '/');
if (ret && ret[1])
return (ret + 1);
return s;
}
/*
* This is a replacement rcmd() function that uses the rsh(1c)
* program in place of a direct rcmd() function call so as to
* avoid having to be root.
*/
int
rshrcmd(ahost, port, luser, ruser, cmd, fd2p)
char **ahost;
u_short port;
char *luser, *ruser, *cmd;
int *fd2p;
{
int cpid;
struct hostent *hp;
int sp[2];
/* insure that we are indeed being used as we thought. */
if (fd2p != 0)
return -1;
/* validate remote hostname. */
hp = gethostbyname(*ahost);
if (hp == 0) {
error("%s: unknown host", *ahost);
return -1;
}
/* *ahost = hp->h_name; *//* This makes me nervous. */
/* get a socketpair we'll use for stdin and stdout. */
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) < 0) {
error("socketpair(AF_UNIX, SOCK_STREAM, 0) failed: %s.",
strerror(errno));
return -1;
}
cpid = fork();
if (cpid < 0) {
error("fork failed: %s.", strerror(errno));
return -1; /* error. */
}
if (cpid == 0) {
/* child. we use sp[1] to be stdin/stdout, and close
sp[0]. */
(void) close(sp[0]);
if (dup2(sp[1], 0) < 0 || dup2(0,1) < 0) {
error("dup2 failed: %s.", strerror(errno));
_exit(255);
}
/* fork again to lose parent. */
cpid = fork();
if (cpid < 0) {
error("fork to lose parent failed: %s.", strerror(errno));
_exit(255);
}
if (cpid > 0)
_exit(0);
/* in grandchild here. */
/*
* If we are rdist'ing to "localhost" as the same user
* as we are, then avoid running remote shell for efficiency.
*/
if (strcmp(*ahost, "localhost") == 0 &&
strcmp(luser, ruser) == 0) {
execlp(_PATH_BSHELL, xbasename(_PATH_BSHELL), "-c",
cmd, (char *) NULL);
error("execlp %s failed: %s.", _PATH_BSHELL, strerror(errno));
} else {
execlp(path_rsh, xbasename(path_rsh),
*ahost, "-l", ruser, cmd, (char *) NULL);
error("execlp %s failed: %s.", path_rsh,
strerror(errno));
}
_exit(255);
}
if (cpid > 0) {
/* parent. close sp[1], return sp[0]. */
(void) close(sp[1]);
/* reap child. */
(void) wait(0);
return sp[0];
}
/*NOTREACHED*/
return (-1);
}
#endif /* !DIRECT_RCMD */

File diff suppressed because it is too large Load Diff