summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/cvs/child.c271
-rw-r--r--usr.bin/cvs/cvsd-child/Makefile19
-rw-r--r--usr.bin/cvs/cvsd.c373
-rw-r--r--usr.bin/cvs/cvsd.h53
-rw-r--r--usr.bin/cvs/cvsd/Makefile4
5 files changed, 407 insertions, 313 deletions
diff --git a/usr.bin/cvs/child.c b/usr.bin/cvs/child.c
new file mode 100644
index 00000000000..a9ad357906b
--- /dev/null
+++ b/usr.bin/cvs/child.c
@@ -0,0 +1,271 @@
+/* $OpenBSD: child.c,v 1.1 2005/02/22 22:33:01 jfb Exp $ */
+/*
+ * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ */
+/*
+ * cvsd-child
+ * ----------
+ *
+ * This is the process taking care of cvs(1) repository requests
+ * This program is not meant to be run standalone and should only be started
+ * by the cvsd(8) process.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/uio.h>
+
+#include <err.h>
+#include <pwd.h>
+#include <grp.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sysexits.h>
+
+#include "log.h"
+#include "cvs.h"
+#include "cvsd.h"
+#include "cvspr.h"
+
+
+
+extern char *__progname;
+
+
+int cvsd_fg = 0;
+
+volatile sig_atomic_t cvsd_running = 1;
+
+static int cvsd_privfd = -1;
+static char cvsd_root[MAXPATHLEN];
+static char *cvsd_motd;
+static uid_t cvsd_uid = -1;
+static gid_t cvsd_gid = -1;
+
+
+/* session info */
+static uid_t cvsd_sess_ruid = 0; /* UID of the cvs issuing requests */
+static gid_t cvsd_sess_rgid = 0; /* UID of the cvs issuing requests */
+static int cvsd_sess_fd = -1;
+
+
+void usage (void);
+void cvsd_sighdlr (int);
+int cvsd_child_getreq (struct cvsd_req *);
+
+
+/*
+ * cvsd_sighdlr()
+ *
+ * Generic signal handler.
+ */
+void
+cvsd_sighdlr(int signo)
+{
+ switch (signo) {
+ case SIGINT:
+ case SIGTERM:
+ case SIGQUIT:
+ cvsd_running = 0;
+ break;
+ }
+}
+
+
+/*
+ * usage()
+ *
+ * Display program usage.
+ */
+void
+usage(void)
+{
+ fprintf(stderr,
+ "Usage: %s [-dfhv] [-g group] "
+ "[-u user]\n"
+ "\t-d\t\tStart the server in debugging mode (very verbose)\n"
+ "\t-u user\t\tUse user <user> for privilege revocation\n"
+ "\t-v\t\tBe verbose\n",
+ __progname);
+}
+
+
+int
+main(int argc, char **argv)
+{
+ int ret;
+ struct cvsd_req req;
+
+ if (cvs_log_init(LD_STD|LD_SYSLOG, LF_PID) < 0)
+ err(1, "failed to initialize logging mechanism");
+
+ cvsd_sess_fd = CVSD_CHILD_SOCKFD;
+ if (getpeereid(cvsd_sess_fd, &cvsd_sess_ruid, &cvsd_sess_rgid) == -1) {
+ cvs_log(LP_ERRNO, "failed to get remote credentials");
+ exit(EX_OSERR);
+ }
+
+ while ((ret = getopt(argc, argv, "dfg:hr:u:v")) != -1) {
+ switch (ret) {
+ case 'd':
+ cvs_log_filter(LP_FILTER_UNSET, LP_DEBUG);
+ cvs_log_filter(LP_FILTER_UNSET, LP_INFO);
+ break;
+ case 'f':
+ cvsd_fg = 1;
+ break;
+ case 'g':
+ cvsd_gid = atoi(optarg);
+ break;
+ case 'h':
+ usage();
+ exit(0);
+ /* NOTREACHED */
+ break;
+ case 'r':
+ strlcpy(cvsd_root, optarg, sizeof(cvsd_root));
+ break;
+ case 'u':
+ cvsd_uid = atoi(optarg);
+ break;
+ case 'v':
+ cvs_log_filter(LP_FILTER_UNSET, LP_INFO);
+ break;
+ default:
+ usage();
+ exit(EX_USAGE);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc > 0)
+ errx(EX_USAGE, "unrecognized trailing arguments");
+
+ /* Before getting any further, chroot to the CVS repository's root
+ * directory and drop all privileges to the appropriate user and
+ * group so we can't cause damage outside of the CVS data.
+ */
+ if (chroot(cvsd_root) == -1) {
+ cvs_log(LP_ERRNO, "failed to chroot to %s", cvsd_root);
+ exit(EX_OSERR);
+ }
+ (void)chdir("/");
+ cvs_log(LP_INFO, "dropping privileges to %d:%d", cvsd_uid, cvsd_gid);
+ if (setgid(cvsd_gid) == -1) {
+ cvs_log(LP_ERRNO, "failed to drop group privileges to %s",
+ CVSD_GROUP);
+ return (-1);
+ }
+
+ if (setuid(cvsd_uid) == -1) {
+ cvs_log(LP_ERRNO, "failed to drop user privileges to %s",
+ CVSD_USER);
+ return (-1);
+ }
+
+ signal(SIGINT, cvsd_sighdlr);
+ signal(SIGQUIT, cvsd_sighdlr);
+ signal(SIGTERM, cvsd_sighdlr);
+ signal(SIGPIPE, SIG_IGN);
+
+ setproctitle("%s [child %d]", __progname, getpid());
+
+ for (;;) {
+ ret = cvsd_child_getreq(&req);
+ if (ret <= 0)
+ break;
+
+ switch (req.cr_op) {
+ case CVS_OP_DIFF:
+ case CVS_OP_UPDATE:
+ default:
+ }
+ printf("request ID: %d, nfiles = %d\n", req.cr_op,
+ req.cr_nfiles);
+ }
+
+ close(cvsd_sess_fd);
+
+ cvs_log_cleanup();
+
+ return (0);
+}
+
+
+/*
+ * cvsd_child_getreq()
+ *
+ * Read the next request available on the session socket.
+ * Returns 1 if a request was received, 0 if there are no more requests to
+ * serve, and -1 in case of failure.
+ */
+int
+cvsd_child_getreq(struct cvsd_req *reqp)
+{
+ ssize_t ret;
+ if ((ret = read(cvsd_sess_fd, reqp, sizeof(*reqp))) == -1) {
+ cvs_log(LP_ERRNO, "failed to read request");
+ } else if (ret > 0) {
+ printf("reqlen = %d\n", ret);
+ ret = 1;
+ }
+
+ return ((int)ret);
+}
+
+
+/*
+ * cvsd_child_reqhdlr()
+ *
+ */
+int
+cvsd_child_reqhdlr(struct cvsp_req *req)
+{
+ int ret;
+
+ switch (req->req_code) {
+ case CVSP_REQ_MOTD:
+ ret = cvs_proto_sendresp(cvsd_sess_fd, CVSP_RESP_DONE,
+ cvsd_motd, strlen(cvsd_motd) + 1);
+ break;
+ case CVSP_REQ_VERSION:
+ case CVSP_REQ_GETMSG:
+ case CVSP_REQ_SETMSG:
+ default:
+ ret = cvs_proto_sendresp(cvsd_sess_fd, CVSP_RESP_INVREQ,
+ req->req_seq, NULL, 0);
+ }
+
+ return (ret);
+}
diff --git a/usr.bin/cvs/cvsd-child/Makefile b/usr.bin/cvs/cvsd-child/Makefile
new file mode 100644
index 00000000000..dbe956d324a
--- /dev/null
+++ b/usr.bin/cvs/cvsd-child/Makefile
@@ -0,0 +1,19 @@
+# $Id: Makefile,v 1.1 2005/02/22 22:33:01 jfb Exp $
+
+.PATH: ${.CURDIR}/..
+
+PROG=cvsd-child
+SRCS= child.c buf.c log.c msg.c rcs.c rcsnum.c
+
+BINDIR=/usr/sbin
+MAN=
+
+CFLAGS+= -Wall -I${.CURDIR}/..
+CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS+= -Wmissing-declarations
+CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
+CFLAGS+= -Wsign-compare
+CFLAGS+= -DCVSD
+YFLAGS=
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/cvs/cvsd.c b/usr.bin/cvs/cvsd.c
index dea0e39cc02..487c47400c7 100644
--- a/usr.bin/cvs/cvsd.c
+++ b/usr.bin/cvs/cvsd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cvsd.c,v 1.17 2005/02/15 15:17:34 jfb Exp $ */
+/* $OpenBSD: cvsd.c,v 1.18 2005/02/22 22:33:01 jfb Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -46,12 +46,11 @@
#include "log.h"
#include "sock.h"
#include "cvs.h"
+#include "repo.h"
#include "cvsd.h"
static void cvsd_parent_loop (void);
-static void cvsd_child_main (void);
-static int cvsd_privdrop (void);
static void cvsd_report (void);
@@ -59,8 +58,8 @@ extern char *__progname;
int cvsd_fg = 0;
-uid_t cvsd_uid = -1;
-gid_t cvsd_gid = -1;
+uid_t cvsd_uid = 0;
+gid_t cvsd_gid = 0;
volatile sig_atomic_t cvsd_running = 1;
volatile sig_atomic_t cvsd_restart = 0;
@@ -68,20 +67,21 @@ volatile sig_atomic_t cvsd_restart = 0;
static char *cvsd_user = NULL;
static char *cvsd_group = NULL;
static char *cvsd_root = NULL;
-static char *cvsd_conffile = CVSD_CONF;
+static char *cvsd_conffile = CVSD_PATH_CONF;
static char *cvsd_moddir = NULL;
static int cvsd_privfd = -1;
+static CVSREPO *cvsd_repo;
+
static TAILQ_HEAD(,cvsd_child) cvsd_children;
static volatile sig_atomic_t cvsd_chnum = 0;
-static volatile sig_atomic_t cvsd_chmin = CVSD_CHILD_DEFMIN;
static volatile sig_atomic_t cvsd_chmax = CVSD_CHILD_DEFMAX;
static volatile sig_atomic_t cvsd_sigchld = 0;
static volatile sig_atomic_t cvsd_siginfo = 0;
-void usage (void);
+void usage (void);
void cvsd_sighdlr (int);
int cvsd_msghdlr (struct cvsd_child *, int);
@@ -141,12 +141,11 @@ usage(void)
int
main(int argc, char **argv)
{
- u_int i;
- int ret, checkrepo;
+ int ret, repo_flags;
struct passwd *pwd;
struct group *grp;
- checkrepo = 0;
+ repo_flags = 0;
cvsd_set(CVSD_SET_SOCK, CVSD_SOCK_PATH);
cvsd_set(CVSD_SET_USER, CVSD_USER);
cvsd_set(CVSD_SET_GROUP, CVSD_GROUP);
@@ -154,7 +153,7 @@ main(int argc, char **argv)
if (cvs_log_init(LD_STD|LD_SYSLOG, LF_PID) < 0)
err(1, "failed to initialize logging mechanism");
- while ((ret = getopt(argc, argv, "a:c:dfhpr:s:v")) != -1) {
+ while ((ret = getopt(argc, argv, "c:dfg:hpr:s:u:v")) != -1) {
switch (ret) {
case 'c':
cvsd_conffile = optarg;
@@ -175,7 +174,7 @@ main(int argc, char **argv)
/* NOTREACHED */
break;
case 'p':
- checkrepo = 1;
+ repo_flags |= CVS_REPO_CHKPERM;
break;
case 'r':
cvsd_set(CVSD_SET_ROOT, optarg);
@@ -217,6 +216,9 @@ main(int argc, char **argv)
if (grp == NULL)
err(EX_NOUSER, "failed to get group `%s'", cvsd_group);
+ endpwent();
+ endgrent();
+
cvsd_uid = pwd->pw_uid;
cvsd_gid = grp->gr_gid;
@@ -232,6 +234,11 @@ main(int argc, char **argv)
exit(EX_OSERR);
}
+ if ((cvsd_repo = cvs_repo_load(cvsd_root, repo_flags)) == NULL) {
+ cvs_log(LP_ERR, "failed to load repository");
+ exit(EX_OSERR);
+ };
+
if (cvsd_sock_open() < 0) {
exit(1);
}
@@ -245,182 +252,44 @@ main(int argc, char **argv)
exit(EX_OSERR);
}
- if (checkrepo && cvsd_checkperms("/") != 0) {
- cvs_log(LP_ERR,
- "exiting due to permission errors on repository");
- exit(1);
- }
-
- /* spawn the initial pool of children */
- for (i = 0; i < (u_int)cvsd_chmin; i++)
- if (cvsd_child_fork(NULL) < 0)
- exit(EX_OSERR);
-
signal(SIGINFO, cvsd_sighdlr);
cvsd_parent_loop();
- cvs_log(LP_NOTICE, "shutting down");
- cvs_log_cleanup();
-
cvsd_sock_close();
- return (0);
-}
-
-
-/*
- * cvsd_privdrop()
- *
- * Drop privileges.
- */
-int
-cvsd_privdrop(void)
-{
- cvs_log(LP_INFO, "dropping privileges to %s[%d]:%s[%d]",
- cvsd_user, cvsd_uid, cvsd_group, cvsd_gid);
- if (setgid(cvsd_gid) == -1) {
- cvs_log(LP_ERRNO, "failed to drop group privileges to %s",
- CVSD_GROUP);
- return (-1);
- }
-
- if (setuid(cvsd_uid) == -1) {
- cvs_log(LP_ERRNO, "failed to drop user privileges to %s",
- CVSD_USER);
- return (-1);
- }
+ cvs_repo_free(cvsd_repo);
+ cvs_log(LP_NOTICE, "shutting down");
+ cvs_log_cleanup();
return (0);
}
/*
- * cvsd_checkperms()
- *
- * Check permissions on the CVS repository and log warnings for any
- * weird of loose permissions.
- * Returns the number of warnings on success, or -1 on failure.
- */
-int
-cvsd_checkperms(const char *path)
-{
- int fd, nbwarn, ret;
- mode_t fmode;
- long base;
- u_char *dp, *endp;
- char buf[1024], spath[MAXPATHLEN];
- struct stat st;
- struct dirent *dep;
-
- nbwarn = 0;
-
- cvs_log(LP_DEBUG, "checking permissions on `%s'", path);
-
- if (stat(path, &st) == -1) {
- cvs_log(LP_ERRNO, "failed to stat `%s'", path);
- return (-1);
- }
-
- if (S_ISDIR(st.st_mode))
- fmode = CVSD_DPERM;
- else
- fmode = CVSD_FPERM;
-
- if (st.st_uid != cvsd_uid) {
- cvs_log(LP_WARN, "owner of `%s' is not %s", path, CVSD_USER);
- nbwarn++;
- }
-
- if (st.st_gid != cvsd_gid) {
- cvs_log(LP_WARN, "group of `%s' is not %s", path, CVSD_GROUP);
- nbwarn++;
- }
-
- if (st.st_mode & S_IWGRP) {
- cvs_log(LP_WARN, "file `%s' is group-writable", path,
- fmode);
- nbwarn++;
- }
-
- if (st.st_mode & S_IWOTH) {
- cvs_log(LP_WARN, "file `%s' is world-writable", path,
- fmode);
- nbwarn++;
- }
-
- if (S_ISDIR(st.st_mode)) {
- fd = open(path, O_RDONLY, 0);
- if (fd == -1) {
- cvs_log(LP_ERRNO, "failed to open directory `%s'",
- path);
- return (nbwarn);
- }
- /* recurse */
- ret = getdirentries(fd, buf, sizeof(buf), &base);
- if (ret == -1) {
- cvs_log(LP_ERRNO,
- "failed to get directory entries for `%s'", path);
- (void)close(fd);
- return (nbwarn);
- }
-
- dp = buf;
- endp = buf + ret;
-
- while (dp < endp) {
- dep = (struct dirent *)dp;
- dp += dep->d_reclen;
-
- if ((dep->d_namlen == 1) && (dep->d_name[0] == '.'))
- continue;
- if ((dep->d_namlen == 2) && (dep->d_name[0] == '.') &&
- (dep->d_name[1] == '.'))
- continue;
-
- /* skip the CVSROOT directory */
- if (strcmp(dep->d_name, CVS_PATH_ROOT) == 0)
- continue;
-
- snprintf(spath, sizeof(spath), "%s/%s", path,
- dep->d_name);
- ret = cvsd_checkperms(spath);
- if (ret == -1)
- nbwarn++;
- else
- nbwarn += ret;
- }
- (void)close(fd);
- }
-
-
- return (nbwarn);
-}
-
-
-/*
* cvsd_child_fork()
*
- * Fork a child process which chroots to the CVS repository's root directory.
- * If the <chpp> argument is not NULL, a reference to the newly created child
- * structure will be returned.
- * On success, returns 0 in the child process context, 1 in the parent's
- * context, or -1 on failure.
+ * Fork a child process which chroots to the CVS repository's root directory,
+ * drops all privileges, and then executes the cvsd-child process, which will
+ * handle the incoming CVS requests.
+ * On success, returns a pointer to the new child structure,
+ * or NULL on failure.
*/
-int
-cvsd_child_fork(struct cvsd_child **chpp)
+struct cvsd_child*
+cvsd_child_fork(int sock)
{
- int svec[2];
+ int argc, svec[2];
pid_t pid;
+ char *argv[16], ubuf[8], gbuf[8];
struct cvsd_child *chp;
if (cvsd_chnum == cvsd_chmax) {
cvs_log(LP_WARN, "child pool reached limit of processes");
- return (-1);
+ return (NULL);
}
if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, svec) == -1) {
cvs_log(LP_ERRNO, "failed to create socket pair");
- return (-1);
+ return (NULL);
}
/*
@@ -429,7 +298,7 @@ cvsd_child_fork(struct cvsd_child **chpp)
*/
if (seteuid(0) == -1) {
cvs_log(LP_ERRNO, "failed to regain privileges");
- return (-1);
+ return (NULL);
}
pid = fork();
@@ -437,43 +306,70 @@ cvsd_child_fork(struct cvsd_child **chpp)
cvs_log(LP_ERRNO, "failed to fork child");
(void)close(svec[0]);
(void)close(svec[1]);
- return (-1);
+ return (NULL);
}
if (pid == 0) {
cvsd_privfd = svec[1];
(void)close(svec[0]);
- cvsd_child_main();
- /* NOTREACHED */
+ /*
+ * Move the accepted socket to descriptor 3, where the child
+ * expects it to be. This could become troublesome if the
+ * descriptor is already taken, but then again, the child
+ * shouldn't have access to other descriptors except the
+ * connection and its side of the socket pair it shares with
+ * the parent.
+ */
+ if (dup2(sock, CVSD_CHILD_SOCKFD) == -1) {
+ cvs_log(LP_ERRNO, "failed to dup child socket");
+ exit(EX_OSERR);
+ }
+ (void)close(sock);
+
+ argc = 0;
+ argv[argc++] = CVSD_PATH_CHILD;
+ argv[argc++] = "-r";
+ argv[argc++] = cvsd_root;
+ if (cvsd_uid != 0) {
+ snprintf(ubuf, sizeof(ubuf), "%d", cvsd_uid);
+ argv[argc++] = "-u";
+ argv[argc++] = ubuf;
+ }
+ if (cvsd_gid != 0) {
+ snprintf(gbuf, sizeof(gbuf), "%d", cvsd_gid);
+ argv[argc++] = "-g";
+ argv[argc++] = gbuf;
+ }
+ argv[argc] = NULL;
+
+ execv(CVSD_PATH_CHILD, argv);
+ err(1, "FUCK");
+ exit(EX_OSERR);
}
cvs_log(LP_INFO, "spawning child %d", pid);
- if (seteuid(cvsd_uid) == -1) {
+ (void)close(svec[1]);
+
+ if (seteuid(cvsd_uid) == -1)
cvs_log(LP_ERRNO, "failed to redrop privs");
- return (-1);
- }
chp = (struct cvsd_child *)malloc(sizeof(*chp));
if (chp == NULL) {
+ /* XXX kill child */
cvs_log(LP_ERRNO, "failed to allocate child data");
- return (-1);
+ return (NULL);
}
chp->ch_pid = pid;
chp->ch_sock = svec[0];
chp->ch_state = CVSD_ST_IDLE;
- signal(SIGCHLD, SIG_IGN);
TAILQ_INSERT_TAIL(&cvsd_children, chp, ch_list);
cvsd_chnum++;
- signal(SIGCHLD, cvsd_sighdlr);
- if (chpp != NULL)
- *chpp = chp;
- (void)close(svec[1]);
- return (1);
+ return (chp);
}
@@ -482,8 +378,7 @@ cvsd_child_fork(struct cvsd_child **chpp)
*
* Wait for a child's status and perform the proper actions depending on it.
* If the child has exited or has been terminated by a signal, it will be
- * removed from the list and new children will be created until the pool has
- * at least <cvsd_chmin> children in it.
+ * removed from the list.
* Returns 0 on success, or -1 on failure.
*/
int
@@ -522,41 +417,11 @@ cvsd_child_reap(void)
}
}
- while (cvsd_chnum < cvsd_chmin)
- cvsd_child_fork(NULL);
-
return (0);
}
/*
- * cvsd_child_get()
- *
- * Find a child process in idle state and return a pointer to the child's
- * structure. If there are no available child processes, a new one will be
- * created unless the number of children has attained the maximum, in which
- * case NULL is returned.
- */
-struct cvsd_child*
-cvsd_child_get(void)
-{
- struct cvsd_child *chp;
-
- TAILQ_FOREACH(chp, &cvsd_children, ch_list)
- if (chp->ch_state == CVSD_ST_IDLE)
- return (chp);
-
- /* no available child, attempt to fork a new one */
- chp = NULL;
- if ((cvsd_chnum < cvsd_chmax) && (cvsd_child_fork(&chp) < 0))
- return (NULL);
-
- return (chp);
-}
-
-
-
-/*
* cvsd_parent_loop()
*
* Main loop of the parent cvsd process, which listens on its end of the
@@ -628,10 +493,10 @@ cvsd_parent_loop(void)
uid_t uid;
gid_t gid;
- cfd = cvsd_sock_accept(pfd[0].fd);
- if (cfd == -1)
- chp = cvsd_child_get();
- if (chp == NULL) {
+ if ((cfd = cvsd_sock_accept(pfd[0].fd)) == -1)
+ continue;
+
+ if ((chp = cvsd_child_fork(cfd)) == NULL) {
cvs_log(LP_ALERT,
"request queue not implemented");
break;
@@ -669,78 +534,6 @@ cvsd_parent_loop(void)
/*
- * cvsd_child_main()
- *
- */
-static void
-cvsd_child_main(void)
-{
- int ret, timeout;
- u_int mtype;
- size_t mlen;
- char mbuf[CVSD_MSG_MAXLEN];
- struct pollfd pfd[1];
- struct cvsd_sess *sessp;
-
- cvs_log(LP_INFO, "changing root to %s", cvsd_root);
- if (chroot(cvsd_root) == -1) {
- cvs_log(LP_ERRNO, "failed to chroot to `%s'", cvsd_root);
- exit(EX_OSERR);
- }
- (void)chdir("/");
-
- if (cvsd_privdrop() < 0)
- exit(EX_OSERR);
-
- setproctitle("%s [child %d]", __progname, getpid());
-
- pfd[0].fd = cvsd_privfd;
- pfd[0].events = POLLIN;
- timeout = INFTIM;
- sessp = NULL;
-
- while (cvsd_running) {
- ret = poll(pfd, 1, timeout);
- if (ret == -1) {
- if (errno == EINTR)
- continue;
- cvs_log(LP_ERRNO, "poll error");
- break;
- } else if (ret == 0)
- continue;
-
- if (pfd[0].revents & (POLLERR|POLLNVAL)) {
- cvs_log(LP_ERR, "poll error");
- break;
- }
-
- mlen = sizeof(mbuf);
- ret = cvsd_recvmsg(pfd[0].fd, &mtype, mbuf, &mlen);
- if (ret == -1) {
- continue;
- } else if (ret == 0)
- break;
-
- switch (mtype) {
- case CVSD_MSG_PASSFD:
- sessp = cvsd_sess_alloc(*(int *)mbuf);
- break;
- case CVSD_MSG_SHUTDOWN:
- cvsd_running = 0;
- break;
- default:
- cvs_log(LP_ERR,
- "unexpected message type %u from parent", mtype);
- break;
- }
-
- }
-
- exit(0);
-}
-
-
-/*
* cvsd_msghdlr()
*
* Handler for messages received from child processes.
@@ -887,10 +680,6 @@ cvsd_set(int what, ...)
free(cvsd_moddir);
cvsd_moddir = str;
break;
- case CVSD_SET_CHMIN:
- cvsd_chmin = va_arg(vap, int);
- /* we should increase the number of children accordingly */
- break;
case CVSD_SET_CHMAX:
cvsd_chmax = va_arg(vap, int);
/* we should decrease the number of children accordingly */
@@ -912,6 +701,8 @@ cvsd_set(int what, ...)
/*
* cvsd_report()
+ *
+ * Report about the current state of child processes on the repository.
*/
static void
cvsd_report(void)
diff --git a/usr.bin/cvs/cvsd.h b/usr.bin/cvs/cvsd.h
index 4a271478c26..bd4ff0549c4 100644
--- a/usr.bin/cvs/cvsd.h
+++ b/usr.bin/cvs/cvsd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cvsd.h,v 1.7 2004/12/07 17:10:56 tedu Exp $ */
+/* $OpenBSD: cvsd.h,v 1.8 2005/02/22 22:33:01 jfb Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -42,10 +42,12 @@
#define CVSD_USER "_cvsd"
#define CVSD_GROUP "_cvsd"
-#define CVSD_CONF "/etc/cvsd.conf"
-#define CVSD_CHILD_DEFMIN 3
+#define CVSD_PATH_CONF "/etc/cvsd.conf"
+#define CVSD_PATH_CHILD "/usr/sbin/cvsd-child"
+
#define CVSD_CHILD_DEFMAX 5
+#define CVSD_CHILD_SOCKFD 3
#define CVSD_FPERM (S_IRUSR | S_IWUSR)
@@ -105,37 +107,48 @@ struct cvsd_addr {
} ca_addr;
};
-#define CVSD_SESS_LOCAL 0
-#define CVSD_SESS_REMOTE 1
-
-struct cvsd_sess {
- int cs_fd;
- int cs_type;
- uid_t cs_uid; /* user ID of the session */
- struct cvsd_addr cs_raddr; /* remote address */
-};
-
struct cvsd_child {
pid_t ch_pid;
int ch_sock;
u_int ch_state;
- struct cvsd_sess *ch_sess;
-
TAILQ_ENTRY(cvsd_child) ch_list;
};
+/*
+ * The following structures are used to vehicle information to and from the
+ * cvsd-child process handling the cvs session.
+ */
+
+struct cvsd_req {
+ int cr_op; /* operation (see CVS_OP_* in cvs.h) */
+ int cr_nfiles;
+};
+
+struct cvsd_resp {
+ int cr_code;
+};
+
+
+/* cvsd-child response codes */
+#define CVSD_RESP_OK 0
+#define CVSD_RESP_INVREQ 1 /* invalid request */
+#define CVSD_RESP_DENIED 2 /* access denied */
+#define CVSD_RESP_SYSERR 3 /* system error */
+#define CVSD_RESP_RDONLY 4 /* repository is read-only */
+#define CVSD_RESP_INVFILE 5 /* one or more files are unknown */
+#define CVSD_RESP_INVMOD 6
+
+
extern uid_t cvsd_uid;
extern gid_t cvsd_gid;
-int cvsd_set (int, ...);
-int cvsd_checkperms (const char *);
-int cvsd_child_fork (struct cvsd_child **);
-struct cvsd_child* cvsd_child_get (void);
-int cvsd_child_reap (void);
+int cvsd_set (int, ...);
+struct cvsd_child* cvsd_child_fork (int);
+int cvsd_child_reap (void);
/* from conf.y */
diff --git a/usr.bin/cvs/cvsd/Makefile b/usr.bin/cvs/cvsd/Makefile
index 15c09b5b650..f2ba2e2e436 100644
--- a/usr.bin/cvs/cvsd/Makefile
+++ b/usr.bin/cvs/cvsd/Makefile
@@ -1,9 +1,9 @@
-# $Id: Makefile,v 1.8 2004/12/08 18:52:53 xsa Exp $
+# $Id: Makefile,v 1.9 2005/02/22 22:33:01 jfb Exp $
.PATH: ${.CURDIR}/..
PROG=cvsd
-SRCS= cvsd.c buf.c conf.y log.c msg.c rcs.c rcsnum.c session.c sock.c
+SRCS= cvsd.c buf.c conf.y log.c msg.c repo.c sock.c
BINDIR=/usr/sbin
MAN=cvsd.8 cvsd.conf.5