version 1.7, 2004/09/25 12:21:43 |
version 1.8, 2004/09/27 12:16:05 |
|
|
static void cvsd_parent_loop (void); |
static void cvsd_parent_loop (void); |
static void cvsd_child_loop (void); |
static void cvsd_child_loop (void); |
static int cvsd_privdrop (void); |
static int cvsd_privdrop (void); |
|
static void cvsd_report (void); |
|
|
|
|
extern char *__progname; |
extern char *__progname; |
|
|
volatile sig_atomic_t restart = 0; |
volatile sig_atomic_t restart = 0; |
|
|
|
|
uid_t cvsd_uid = -1; |
uid_t cvsd_uid = -1; |
gid_t cvsd_gid = -1; |
gid_t cvsd_gid = -1; |
|
|
|
static char *cvsd_user = CVSD_USER; |
|
static char *cvsd_group = CVSD_GROUP; |
static char *cvsd_root = NULL; |
static char *cvsd_root = NULL; |
static char *cvsd_conffile = CVSD_CONF; |
static char *cvsd_conffile = CVSD_CONF; |
static int cvsd_privfd = -1; |
static int cvsd_privfd = -1; |
|
|
static volatile sig_atomic_t cvsd_chmin = CVSD_CHILD_DEFMIN; |
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_chmax = CVSD_CHILD_DEFMAX; |
static volatile sig_atomic_t cvsd_sigchld = 0; |
static volatile sig_atomic_t cvsd_sigchld = 0; |
|
static volatile sig_atomic_t cvsd_siginfo = 0; |
|
|
|
|
void usage (void); |
void usage (void); |
void sighup_handler (int); |
void cvsd_sighdlr (int); |
void sigint_handler (int); |
int cvsd_msghdlr (struct cvsd_child *, int); |
void sigchld_handler (int); |
|
int cvsd_msghdlr (struct cvsd_child *, int); |
|
|
|
|
|
/* |
/* |
* sighup_handler() |
* cvsd_sighdlr() |
* |
* |
* Handler for the SIGHUP signal. |
* Generic signal handler. |
*/ |
*/ |
|
|
void |
void |
sighup_handler(int signo) |
cvsd_sighdlr(int signo) |
{ |
{ |
restart = 1; |
switch (signo) { |
|
case SIGHUP: |
|
restart = 1; |
|
break; |
|
case SIGCHLD: |
|
cvsd_sigchld = 1; |
|
break; |
|
case SIGINT: |
|
case SIGTERM: |
|
case SIGQUIT: |
|
running = 0; |
|
break; |
|
case SIGINFO: |
|
cvsd_siginfo = 1; |
|
break; |
|
} |
} |
} |
|
|
|
|
/* |
/* |
* sigint_handler() |
|
* |
|
* Handler for the SIGINT signal. |
|
*/ |
|
|
|
void |
|
sigint_handler(int signo) |
|
{ |
|
running = 0; |
|
} |
|
|
|
|
|
/* |
|
* sigchld_handler() |
|
* |
|
* Handler for the SIGCHLD signal. |
|
*/ |
|
|
|
void |
|
sigchld_handler(int signo) |
|
{ |
|
cvsd_sigchld = 1; |
|
signal(SIGCHLD, sigchld_handler); |
|
} |
|
|
|
|
|
/* |
|
* usage() |
* usage() |
* |
* |
* Display program usage. |
* Display program usage. |
|
|
usage(void) |
usage(void) |
{ |
{ |
fprintf(stderr, |
fprintf(stderr, |
"Usage: %s [-dfhpv] [-c config] [-r root] [-s path]\n" |
"Usage: %s [-dfhpv] [-c config] [-g group] [-r root] " |
|
"[-s path] [-u user]\n" |
"\t-c config\tUse <config> as the configuration file\n" |
"\t-c config\tUse <config> as the configuration file\n" |
"\t-d\t\tStart the server in debugging mode (very verbose)\n" |
"\t-d\t\tStart the server in debugging mode (very verbose)\n" |
"\t-f\t\tStay in foreground instead of becoming a daemon\n" |
"\t-f\t\tStay in foreground instead of becoming a daemon\n" |
|
"\t-g group\tUse group <group> for privilege revocation\n" |
"\t-h\t\tPrint the usage and exit\n" |
"\t-h\t\tPrint the usage and exit\n" |
"\t-p\t\tPerform repository sanity check on startup\n" |
"\t-p\t\tPerform repository sanity check on startup\n" |
"\t-r root\t\tUse <root> as the root directory of the repository\n" |
"\t-r root\t\tUse <root> as the root directory of the repository\n" |
"\t-s path\t\tUse <path> as the path for the CVS server socket\n" |
"\t-s path\t\tUse <path> as the path for the CVS server socket\n" |
|
"\t-u user\tUse user <user> for privilege revocation\n" |
"\t-v\t\tBe verbose\n", |
"\t-v\t\tBe verbose\n", |
__progname); |
__progname); |
} |
} |
|
|
case 'f': |
case 'f': |
foreground = 1; |
foreground = 1; |
break; |
break; |
|
case 'g': |
|
cvsd_group = optarg; |
|
break; |
case 'h': |
case 'h': |
usage(); |
usage(); |
exit(0); |
exit(0); |
|
|
case 's': |
case 's': |
cvsd_sock_path = optarg; |
cvsd_sock_path = optarg; |
break; |
break; |
|
case 'u': |
|
cvsd_user = optarg; |
|
break; |
case 'v': |
case 'v': |
cvs_log_filter(LP_FILTER_UNSET, LP_INFO); |
cvs_log_filter(LP_FILTER_UNSET, LP_INFO); |
break; |
break; |
|
|
|
|
TAILQ_INIT(&cvsd_children); |
TAILQ_INIT(&cvsd_children); |
|
|
pwd = getpwnam(CVSD_USER); |
pwd = getpwnam(cvsd_user); |
if (pwd == NULL) |
if (pwd == NULL) |
err(EX_NOUSER, "failed to get user `%s'", CVSD_USER); |
err(EX_NOUSER, "failed to get user `%s'", cvsd_user); |
|
|
grp = getgrnam(CVSD_GROUP); |
grp = getgrnam(cvsd_group); |
if (grp == NULL) |
if (grp == NULL) |
err(EX_NOUSER, "failed to get group `%s'", CVSD_GROUP); |
err(EX_NOUSER, "failed to get group `%s'", cvsd_group); |
|
|
cvsd_uid = pwd->pw_uid; |
cvsd_uid = pwd->pw_uid; |
cvsd_gid = grp->gr_gid; |
cvsd_gid = grp->gr_gid; |
|
|
signal(SIGHUP, sighup_handler); |
signal(SIGHUP, cvsd_sighdlr); |
signal(SIGINT, sigint_handler); |
signal(SIGINT, cvsd_sighdlr); |
signal(SIGQUIT, sigint_handler); |
signal(SIGQUIT, cvsd_sighdlr); |
signal(SIGTERM, sigint_handler); |
signal(SIGTERM, cvsd_sighdlr); |
signal(SIGCHLD, sigchld_handler); |
signal(SIGCHLD, cvsd_sighdlr); |
|
|
if (!foreground && daemon(0, 0) == -1) { |
if (!foreground && daemon(0, 0) == -1) { |
cvs_log(LP_ERRNO, "failed to become a daemon"); |
cvs_log(LP_ERRNO, "failed to become a daemon"); |
|
|
} |
} |
} |
} |
|
|
|
signal(SIGINFO, cvsd_sighdlr); |
cvsd_parent_loop(); |
cvsd_parent_loop(); |
|
|
cvs_log(LP_NOTICE, "shutting down"); |
cvs_log(LP_NOTICE, "shutting down"); |
|
|
int |
int |
cvsd_privdrop(void) |
cvsd_privdrop(void) |
{ |
{ |
cvs_log(LP_INFO, "dropping privileges to %s:%s", CVSD_USER, |
cvs_log(LP_INFO, "dropping privileges to %s[%d]:%s[%d]", |
CVSD_GROUP); |
cvsd_user, cvsd_uid, cvsd_group, cvsd_gid); |
if (setgid(cvsd_gid) == -1) { |
if (setgid(cvsd_gid) == -1) { |
cvs_log(LP_ERRNO, "failed to drop group privileges to %s", |
cvs_log(LP_ERRNO, "failed to drop group privileges to %s", |
CVSD_GROUP); |
CVSD_GROUP); |
|
|
signal(SIGCHLD, SIG_IGN); |
signal(SIGCHLD, SIG_IGN); |
TAILQ_INSERT_TAIL(&cvsd_children, chp, ch_list); |
TAILQ_INSERT_TAIL(&cvsd_children, chp, ch_list); |
cvsd_chnum++; |
cvsd_chnum++; |
signal(SIGCHLD, sigchld_handler); |
signal(SIGCHLD, cvsd_sighdlr); |
|
|
if (chpp != NULL) |
if (chpp != NULL) |
*chpp = chp; |
*chpp = chp; |
|
|
signal(SIGCHLD, SIG_IGN); |
signal(SIGCHLD, SIG_IGN); |
TAILQ_REMOVE(&cvsd_children, ch, ch_list); |
TAILQ_REMOVE(&cvsd_children, ch, ch_list); |
cvsd_chnum--; |
cvsd_chnum--; |
signal(SIGCHLD, sigchld_handler); |
signal(SIGCHLD, cvsd_sighdlr); |
|
|
break; |
break; |
} |
} |
|
|
cvsd_sigchld = 0; |
cvsd_sigchld = 0; |
cvsd_child_reap(); |
cvsd_child_reap(); |
} |
} |
|
if (cvsd_siginfo) { |
|
cvsd_siginfo = 0; |
|
cvsd_report(); |
|
} |
|
|
nfds = cvsd_chnum + 1; |
nfds = cvsd_chnum + 1; |
pfd = (struct pollfd *)realloc(pfd, |
pfd = (struct pollfd *)realloc(pfd, |
|
|
break; |
break; |
|
|
switch (mtype) { |
switch (mtype) { |
|
case CVSD_MSG_PASSFD: |
|
break; |
case CVSD_MSG_SHUTDOWN: |
case CVSD_MSG_SHUTDOWN: |
running = 0; |
running = 0; |
break; |
break; |
|
|
va_end(vap); |
va_end(vap); |
|
|
return (0); |
return (0); |
|
} |
|
|
|
|
|
/* |
|
* cvsd_report() |
|
*/ |
|
|
|
static void |
|
cvsd_report(void) |
|
{ |
|
u_int nb_idle, nb_busy, nb_unknown; |
|
struct cvsd_child *ch; |
|
|
|
nb_idle = 0; |
|
nb_busy = 0; |
|
nb_unknown = 0; |
|
|
|
signal(SIGCHLD, SIG_IGN); |
|
TAILQ_FOREACH(ch, &cvsd_children, ch_list) { |
|
if (ch->ch_state == CVSD_ST_IDLE) |
|
nb_idle++; |
|
else if (ch->ch_state == CVSD_ST_BUSY) |
|
nb_busy++; |
|
else if (ch->ch_state == CVSD_ST_UNKNOWN) |
|
nb_unknown++; |
|
} |
|
|
|
cvs_log(LP_WARN, "%u children, %u idle, %u busy, %u unknown", |
|
cvsd_chnum, nb_idle, nb_busy, nb_unknown); |
|
|
|
TAILQ_FOREACH(ch, &cvsd_children, ch_list) |
|
cvs_log(LP_WARN, ""); |
|
signal(SIGCHLD, cvsd_sighdlr); |
} |
} |