Skip to content
Browse files

Bump start-stop-daemon

  • Loading branch information...
1 parent 8a06600 commit 2f4e4048afac487b33a2e4aef0d335d27dde1312 Ozan Çağlayan committed Feb 26, 2009
Showing with 376 additions and 170 deletions.
  1. +2 −2 src/Makefile
  2. +26 −0 src/headers.h
  3. +348 −168 src/start-stop-daemon.c
View
4 src/Makefile
@@ -1,4 +1,4 @@
-# Copyright © 2005 TUBITAK/UEKAE
+# Copyright © 2005-2009 TUBITAK/UEKAE
# Licensed under the GNU General Public License, version 2.
# See the file http://www.gnu.org/copyleft/gpl.txt.
#
@@ -17,7 +17,7 @@ TARGET = $(BIN_TARGETS) $(SBIN_TARGETS)
all: $(TARGET)
start-stop-daemon: start-stop-daemon.c
- $(CC) -o $@ $(CFLAGS) -DHAVE_ERROR_H -DHAVE_TIOCNOTTY -DHAVE_SETSID $^
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
install: $(TARGET)
install -m 0755 -d $(DESTDIR)/sbin
View
26 src/headers.h
@@ -0,0 +1,26 @@
+/*
+ * header.h
+ * Dirty little file to include header files w/out autotools.
+ *
+ * Copyright 1999-2007 Gentoo Foundation
+ * Distributed under the terms of the GNU General Public License v2
+ * $Header$
+ */
+
+/* Common includes */
+#define HAVE_TIOCNOTTY
+#define HAVE_SETSID
+
+/* OS-specific includes */
+#if defined(__GLIBC__)
+# define HAVE_SYS_SYSMACROS_H
+# define HAVE_ERROR_H
+#endif
+
+/* Now we actually include crap ;) */
+#ifdef HAVE_ERROR_H
+# include <error.h>
+#endif
+#ifdef HAVE_SYS_SYSMACROS_H
+# include <sys/sysmacros.h>
+#endif
View
516 src/start-stop-daemon.c
@@ -19,26 +19,29 @@
*
* Changes by Ian Jackson: added --retry (and associated rearrangements).
*
- * Modified for Gentoo rc-scripts by Donny Davies <woodchip@gentoo.org>:
- * I removed the BSD/Hurd/OtherOS stuff, added #include <stddef.h>
- * and stuck in a #define VERSION "1.9.18". Now it compiles without
- * the whole automake/config.h dance.
+ *
+ * Changes by Quequero <quequero@bitchx.it>:
+ * Added -e|--env for setting an environment variable before starting the
+ * process.
+ * Moved --make-pidfile after chrooting process (pid file will be wrote in
+ * new root if -r option is used!).
+ * Daemon binary will be stat()ed correctly if it's going to be chrooted
+ * with -r|--chroot.
*
- * Updated by Aron Griffis <agriffis@gentoo.org>:
- * Fetched updates from Debian's dpkg-1.10.20, including fix for
- * Gentoo bug 22686 (start-stop-daemon in baselayout doesn't allow
- * altered nicelevel).
+ * Changes by Iain Buchanan <iaindb@netspace.net.au>: added to public domain.
+ * Added --stdin --stdout and --stderr for redirecting input and output (eg to
+ * vt's) when run with --background.
+ *
*/
-#define VERSION "1.10.20"
-#include <stddef.h>
+#define VERSION "1.13.11+gentoo"
#define NONRETURNPRINTFFORMAT(x, y) \
__attribute__((noreturn, format(printf, x, y)))
#define NONRETURNING \
__attribute__((noreturn))
-#if defined(linux)
+#if defined(linux) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
# define OSLinux
#elif defined(__GNU__)
# define OSHURD
@@ -52,6 +55,8 @@
# define OSFreeBSD
#elif defined(__NetBSD__)
# define OSNetBSD
+#elif defined(__APPLE__)
+# define OSDarwin
#else
# error Unknown architecture - cannot build start-stop-daemon
#endif
@@ -63,14 +68,14 @@
# include <ps.h>
#endif
-#if defined(OSOpenBSD) || defined(OSFreeBSD) || defined(OSNetBSD)
+#if defined(OSOpenBSD) || defined(OSFreeBSD) || defined(OSNetBSD) || defined(OSDarwin)
#include <sys/param.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/types.h>
-
+
#include <err.h>
#include <kvm.h>
#include <limits.h>
@@ -102,11 +107,12 @@
#include <assert.h>
#include <ctype.h>
-#ifdef HAVE_ERROR_H
-# include <error.h>
-#endif
+#include <stddef.h>
+
+#include "headers.h"
+
#ifdef HURD_IHASH_H
- #include <hurd/ihash.h>
+# include <hurd/ihash.h>
#endif
static int testmode = 0;
@@ -121,11 +127,12 @@ static const char *signal_str = NULL;
static int user_id = -1;
static int runas_uid = -1;
static int runas_gid = -1;
+static char *env = NULL;
static const char *userspec = NULL;
static char *changeuser = NULL;
static const char *changegroup = NULL;
static char *changeroot = NULL;
-static const char *changedir = NULL;
+static const char *changedir = "/";
static const char *cmdname = NULL;
static char *execname = NULL;
static char *startas = NULL;
@@ -134,10 +141,13 @@ static char what_stop[1024];
static const char *schedule_str = NULL;
static const char *progname = "";
static int nicelevel = 0;
+static const char *stdindev = NULL;
+static const char *stdoutdev = NULL;
+static const char *stderrdev = NULL;
static struct stat exec_stat;
#if defined(OSHURD)
-static struct proc_stat_list *procset;
+static struct proc_stat_list *procset = NULL;
#endif
@@ -198,18 +208,18 @@ static void badusage(const char *msg);
typedef long tvselector(const struct timeval*);
static long tvselector_sec(const struct timeval *tv) { return tv->tv_sec; }
static long tvselector_usec(const struct timeval *tv) { return tv->tv_usec; }
-#define TVCALC_ELEM(result, expr, sec, adj) \
-{ \
- const long TVADJUST = adj; \
- long (*const TVELEM)(const struct timeval*) = tvselector_##sec; \
- (result).tv_##sec = (expr); \
+#define TVCALC_ELEM(result, expr, sec, adj) \
+{ \
+ const long TVADJUST = adj; \
+ long (*const TVELEM)(const struct timeval*) = tvselector_##sec; \
+ (result).tv_##sec = (expr); \
}
-#define TVCALC(result,expr) \
-do { \
- TVCALC_ELEM(result, expr, sec, (-1)); \
- TVCALC_ELEM(result, expr, usec, (+1000000)); \
- (result).tv_sec += (result).tv_usec / 1000000; \
- (result).tv_usec %= 1000000; \
+#define TVCALC(result,expr) \
+do { \
+ TVCALC_ELEM(result, expr, sec, (-1)); \
+ TVCALC_ELEM(result, expr, usec, (+1000000)); \
+ (result).tv_sec += (result).tv_usec / 1000000; \
+ (result).tv_usec %= 1000000; \
} while(0)
@@ -222,7 +232,7 @@ fatal(const char *format, ...)
va_start(arglist, format);
vfprintf(stderr, format, arglist);
va_end(arglist);
- putc('\n', stderr);
+ fprintf(stderr, " (%s)\n", strerror (errno));
exit(2);
}
@@ -299,10 +309,15 @@ do_help(void)
" -b|--background force the process to detach\n"
" -m|--make-pidfile create the pidfile before starting\n"
" -R|--retry <schedule> check whether processes die, and retry\n"
+" -e|--env <env-name> set an environment variable (PWD=\"/\")\n"
+" -r|--chroot <path> chroot process to given directory\n"
" -t|--test test mode, don't do anything\n"
" -o|--oknodo exit status 0 (not 1) if nothing done\n"
" -q|--quiet be more quiet\n"
" -v|--verbose be more verbose\n"
+" -0|--stdin <device> redirect stdin from <device> when run with --background\n"
+" -1|--stdout <device> redirect stdout to <device> when run with --background\n"
+" -2|--stderr <device> redirect stderr to <device> when run with --background\n"
"Retry <schedule> is <item>|/<item>/... where <item> is one of\n"
" -<signal-num>|[-]<signal-name> send that signal\n"
" <timeout> wait that many seconds\n"
@@ -462,34 +477,38 @@ static void
parse_options(int argc, char * const *argv)
{
static struct option longopts[] = {
- { "help", 0, NULL, 'H'},
- { "stop", 0, NULL, 'K'},
- { "start", 0, NULL, 'S'},
- { "version", 0, NULL, 'V'},
- { "startas", 1, NULL, 'a'},
- { "name", 1, NULL, 'n'},
- { "oknodo", 0, NULL, 'o'},
- { "pidfile", 1, NULL, 'p'},
- { "quiet", 0, NULL, 'q'},
- { "signal", 1, NULL, 's'},
- { "test", 0, NULL, 't'},
- { "user", 1, NULL, 'u'},
- { "group", 1, NULL, 'g'},
- { "chroot", 1, NULL, 'r'},
- { "verbose", 0, NULL, 'v'},
- { "exec", 1, NULL, 'x'},
- { "chuid", 1, NULL, 'c'},
- { "nicelevel", 1, NULL, 'N'},
+ { "help", 0, NULL, 'H'},
+ { "stop", 0, NULL, 'K'},
+ { "start", 0, NULL, 'S'},
+ { "version", 0, NULL, 'V'},
+ { "startas", 1, NULL, 'a'},
+ { "env", 1, NULL, 'e'},
+ { "name", 1, NULL, 'n'},
+ { "oknodo", 0, NULL, 'o'},
+ { "pidfile", 1, NULL, 'p'},
+ { "quiet", 0, NULL, 'q'},
+ { "signal", 1, NULL, 's'},
+ { "test", 0, NULL, 't'},
+ { "user", 1, NULL, 'u'},
+ { "group", 1, NULL, 'g'},
+ { "chroot", 1, NULL, 'r'},
+ { "verbose", 0, NULL, 'v'},
+ { "exec", 1, NULL, 'x'},
+ { "chuid", 1, NULL, 'c'},
+ { "nicelevel", 1, NULL, 'N'},
{ "background", 0, NULL, 'b'},
{ "make-pidfile", 0, NULL, 'm'},
- { "retry", 1, NULL, 'R'},
+ { "retry", 1, NULL, 'R'},
{ "chdir", 1, NULL, 'd'},
- { NULL, 0, NULL, 0}
+ { "stdin", 1, NULL, '0'},
+ { "stdout", 1, NULL, '1'},
+ { "stderr", 1, NULL, '2'},
+ { NULL, 0, NULL, 0}
};
int c;
for (;;) {
- c = getopt_long(argc, argv, "HKSV:a:n:op:qr:s:tu:vx:c:N:bmR:g:d:",
+ c = getopt_long(argc, argv, "HKSVa:n:op:qr:e:s:tu:vx:c:N:bmR:g:d:",
longopts, (int *) 0);
if (c == -1)
break;
@@ -549,6 +568,9 @@ parse_options(int argc, char * const *argv)
case 'r': /* --chroot /new/root */
changeroot = optarg;
break;
+ case 'e': /* --env <env-name> */
+ env = optarg;
+ break;
case 'N': /* --nice */
nicelevel = atoi(optarg);
break;
@@ -564,6 +586,16 @@ parse_options(int argc, char * const *argv)
case 'd': /* --chdir /new/dir */
changedir = optarg;
break;
+ case '0': /* --stdin new_stdin */
+ stdindev = optarg;
+ break;
+ case '1': /* --stdout new_stdout */
+ stdoutdev = optarg;
+ break;
+ case '2': /* --stderr new_stderr */
+ stderrdev = optarg;
+ break;
+
default:
badusage(NULL); /* message printed by getopt */
}
@@ -597,6 +629,10 @@ parse_options(int argc, char * const *argv)
if (background && !start)
badusage("--background is only relevant with --start");
+ if ((stdindev != NULL || stdoutdev != NULL || stderrdev != NULL) && !background) {
+ fprintf(stderr, "start-stop-daemon: redirecting stdin, stdout or stderr without --background\n");
+ fprintf(stderr, "may stop you from interacting with this process from the terminal.\n");
+ }
}
#if defined(OSLinux)
@@ -653,36 +689,70 @@ pid_is_cmd(pid_t pid, const char *name)
#if defined(OSHURD)
+static void
+init_procset(void)
+{
+ struct ps_context *context;
+ error_t err;
+
+ err = ps_context_create(getproc(), &context);
+ if (err)
+ error(1, err, "ps_context_create");
+
+ err = proc_stat_list_create(context, &procset);
+ if (err)
+ error(1, err, "proc_stat_list_create");
+
+ err = proc_stat_list_add_all(procset, 0, 0);
+ if (err)
+ error(1, err, "proc_stat_list_add_all");
+}
+
+static struct proc_stat *
+get_proc_stat (pid_t pid, ps_flags_t flags)
+{
+ struct proc_stat *ps;
+ ps_flags_t wanted_flags = PSTAT_PID | flags;
+
+ if (!procset)
+ init_procset();
+
+ ps = proc_stat_list_pid_proc_stat(procset, pid);
+ if (!ps)
+ return NULL;
+ if (proc_stat_set_flags(ps, wanted_flags))
+ return NULL;
+ if ((proc_stat_flags(ps) & wanted_flags) != wanted_flags)
+ return NULL;
+
+ return ps;
+}
+
static int
pid_is_user(pid_t pid, uid_t uid)
{
- struct stat sb;
- char buf[32];
- struct proc_stat *pstat;
+ struct proc_stat *ps;
- sprintf(buf, "/proc/%d", pid);
- if (stat(buf, &sb) != 0)
- return 0;
- return (sb.st_uid == uid);
- pstat = proc_stat_list_pid_proc_stat (procset, pid);
- if (pstat == NULL)
- fatal ("Error getting process information: NULL proc_stat struct");
- proc_stat_set_flags (pstat, PSTAT_PID | PSTAT_OWNER_UID);
- return (pstat->owner_uid == uid);
+ ps = get_proc_stat(pid, PSTAT_OWNER_UID);
+ return ps && proc_stat_owner_uid(ps) == uid;
}
static int
pid_is_cmd(pid_t pid, const char *name)
{
- struct proc_stat *pstat;
- pstat = proc_stat_list_pid_proc_stat (procset, pid);
- if (pstat == NULL)
- fatal ("Error getting process information: NULL proc_stat struct");
- proc_stat_set_flags (pstat, PSTAT_PID | PSTAT_ARGS);
- return (!strcmp (name, pstat->args));
+ struct proc_stat *ps;
+
+ ps = get_proc_stat(pid, PSTAT_ARGS);
+ return ps && !strcmp(proc_stat_args(ps), name);
+}
+
+static int
+pid_is_running(pid_t pid)
+{
+ return get_proc_stat(pid, 0) != NULL;
}
-#endif /* OSHURD */
+#else /* !OSHURD */
static int
pid_is_running(pid_t pid)
@@ -700,16 +770,19 @@ pid_is_running(pid_t pid)
return 1;
}
+#endif /* OSHURD */
+
static void
check(pid_t pid)
{
#if defined(OSLinux) || defined(OShpux)
if (execname && !pid_is_exec(pid, &exec_stat))
-#elif defined(OSHURD) || defined(OSFreeBSD) || defined(OSNetBSD)
- /* I will try this to see if it works */
+ return;
+#elif defined(OSHURD) || defined(OSFreeBSD) || defined(OSNetBSD) || defined(OSDarwin)
+ /* I will try this to see if it works */
if (execname && !pid_is_cmd(pid, execname))
-#endif
return;
+#endif
if (userspec && !pid_is_user(pid, user_id))
return;
if (cmdname && !pid_is_cmd(pid, cmdname))
@@ -766,98 +839,92 @@ do_procinit(void)
#if defined(OSHURD)
-error_t
-check_all(void *ptr)
+static int
+check_proc_stat (struct proc_stat *ps)
{
- struct proc_stat *pstat = ptr;
-
- check(pstat->pid);
+ check(ps->pid);
return 0;
}
static void
do_procinit(void)
{
- struct ps_context *context;
- error_t err;
-
- err = ps_context_create(getproc(), &context);
- if (err)
- error(1, err, "ps_context_create");
-
- err = proc_stat_list_create(context, &procset);
- if (err)
- error(1, err, "proc_stat_list_create");
-
- err = proc_stat_list_add_all(procset, 0, 0);
- if (err)
- error(1, err, "proc_stat_list_add_all");
+ if (!procset)
+ init_procset();
- /* Check all pids */
- ihash_iterate(context->procs, check_all);
+ proc_stat_list_for_each (procset, check_proc_stat);
}
#endif /* OSHURD */
#if defined(OSOpenBSD) || defined(OSFreeBSD) || defined(OSNetBSD)
+
+# if defined(OSNetBSD)
+# define _KINFO_PROC2 kinfo_proc2
+# define _GET_KINFO_UID(kp) (kp->p_ruid)
+# define _GET_KINFO_COMM(kp) (kp->p_comm)
+# else
+# define _KINFO_PROC2 kinfo_proc
+# define _GET_KINFO_UID(kp) (kp->ki_ruid)
+# define _GET_KINFO_COMM(kp) (kp->ki_comm)
+# endif
+
static int
pid_is_cmd(pid_t pid, const char *name)
{
- kvm_t *kd;
- int nentries, argv_len=0;
- struct kinfo_proc *kp;
- char errbuf[_POSIX2_LINE_MAX], buf[_POSIX2_LINE_MAX];
+ kvm_t *kd;
+ int nentries, argv_len=0;
+ struct kinfo_proc *kp;
+ char errbuf[_POSIX2_LINE_MAX], buf[_POSIX2_LINE_MAX];
char **pid_argv_p;
char *start_argv_0_p, *end_argv_0_p;
-
-
- kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
- if (kd == 0)
- errx(1, "%s", errbuf);
- if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == 0)
- errx(1, "%s", kvm_geterr(kd));
+
+ kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
+ if (kd == 0)
+ errx(1, "%s", errbuf);
+ if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == 0)
+ errx(1, "%s", kvm_geterr(kd));
if ((pid_argv_p = kvm_getargv(kd, kp, argv_len)) == 0)
- errx(1, "%s", kvm_geterr(kd));
+ errx(1, "%s", kvm_geterr(kd));
start_argv_0_p = *pid_argv_p;
/* find and compare string */
-
+
/* find end of argv[0] then copy and cut of str there. */
- if ((end_argv_0_p = strchr(*pid_argv_p, ' ')) == 0 )
- /* There seems to be no space, so we have the command
- * allready in its desired form. */
- start_argv_0_p = *pid_argv_p;
+ if ((end_argv_0_p = strchr(*pid_argv_p, ' ')) == 0 )
+ /* There seems to be no space, so we have the command
+ * allready in its desired form. */
+ start_argv_0_p = *pid_argv_p;
else {
- /* Tests indicate that this never happens, since
- * kvm_getargv itselfe cuts of tailing stuff. This is
- * not what the manpage says, however. */
- strncpy(buf, *pid_argv_p, (end_argv_0_p - start_argv_0_p));
- buf[(end_argv_0_p - start_argv_0_p) + 1] = '\0';
- start_argv_0_p = buf;
+ /* Tests indicate that this never happens, since
+ * kvm_getargv itselfe cuts of tailing stuff. This is
+ * not what the manpage says, however. */
+ strncpy(buf, *pid_argv_p, (end_argv_0_p - start_argv_0_p));
+ buf[(end_argv_0_p - start_argv_0_p) + 1] = '\0';
+ start_argv_0_p = buf;
}
-
+
if (strlen(name) != strlen(start_argv_0_p))
- return 0;
- return (strcmp(name, start_argv_0_p) == 0) ? 1 : 0;
+ return 0;
+ return (strcmp(name, start_argv_0_p) == 0) ? 1 : 0;
}
-
+
static int
pid_is_user(pid_t pid, uid_t uid)
{
kvm_t *kd;
int nentries; /* Value not used */
uid_t proc_uid;
- struct kinfo_proc *kp;
+ struct _KINFO_PROC2 *kp;
char errbuf[_POSIX2_LINE_MAX];
-
kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
if (kd == 0)
errx(1, "%s", errbuf);
if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == 0)
errx(1, "%s", kvm_geterr(kd));
- if (kp->kp_proc.p_cred )
- kvm_read(kd, (u_long)&(kp->kp_proc.p_cred->p_ruid),
+ if (_GET_KINFO_UID(kp))
+ kvm_read(kd, (u_long)&(_GET_KINFO_UID(kp)),
&proc_uid, sizeof(uid_t));
else
return 0;
@@ -869,15 +936,15 @@ pid_is_exec(pid_t pid, const char *name)
{
kvm_t *kd;
int nentries;
- struct kinfo_proc *kp;
+ struct _KINFO_PROC2 *kp;
char errbuf[_POSIX2_LINE_MAX], *pidexec;
kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
if (kd == 0)
errx(1, "%s", errbuf);
if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == 0)
errx(1, "%s", kvm_geterr(kd));
- pidexec = (&kp->kp_proc)->p_comm;
+ pidexec = _GET_KINFO_COMM(kp);
if (strlen(name) != strlen(pidexec))
return 0;
return (strcmp(name, pidexec) == 0) ? 1 : 0;
@@ -892,6 +959,78 @@ do_procinit(void)
#endif /* OSOpenBSD */
+#if defined(OSDarwin)
+int
+pid_is_user(pid_t pid, uid_t uid)
+{
+ int mib[4];
+ size_t size;
+ struct kinfo_proc ki;
+
+ size = sizeof(ki);
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = pid;
+ if (sysctl(mib, 4, &ki, &size, NULL, 0) < 0)
+ errx(1, "%s", "Failure calling sysctl");
+ return (uid == ki.kp_eproc.e_pcred.p_ruid);
+}
+
+static int
+pid_is_cmd(pid_t pid, const char *name)
+{
+ int mib[4];
+ size_t size;
+ struct kinfo_proc ki;
+
+ size = sizeof(ki);
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = pid;
+ if (sysctl(mib, 4, &ki, &size, NULL, 0) < 0)
+ errx(1, "%s", "Failure calling sysctl");
+ return (!strncmp(name, ki.kp_proc.p_comm, MAXCOMLEN));
+}
+
+static void
+do_procinit(void)
+{
+ int mib[3];
+ size_t size;
+ int nprocs, ret, i;
+ struct kinfo_proc *procs = NULL, *newprocs;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_ALL;
+ ret = sysctl(mib, 3, NULL, &size, NULL, 0);
+ /* Allocate enough memory for entire process table */
+ do {
+ size += size / 10;
+ newprocs = realloc(procs, size);
+ if (newprocs == NULL) {
+ if (procs)
+ free(procs);
+ errx(1, "%s", "Could not reallocate memory");
+ }
+ procs = newprocs;
+ ret = sysctl(mib, 3, procs, &size, NULL, 0);
+ } while (ret >= 0 && errno == ENOMEM);
+
+ if (ret < 0)
+ errx(1, "%s", "Failure calling sysctl");
+
+ /* Verify size of proc structure */
+ if (size % sizeof(struct kinfo_proc) != 0)
+ errx(1, "%s", "proc size mismatch, userland out of sync with kernel");
+ nprocs = size / sizeof(struct kinfo_proc);
+ for (i = 0; i < nprocs; i++) {
+ check(procs[i].kp_proc.p_pid);
+ }
+}
+#endif /* OSDarwin */
#if defined(OShpux)
static int
@@ -933,9 +1072,9 @@ do_procinit(void)
int idx = 0;
while ((count = pstat_getproc(pst, sizeof(pst[0]), 10, idx)) > 0) {
- for (i = 0; i < count; i++)
+ for (i = 0; i < count; i++)
check(pst[i].pst_pid);
- idx = pst[count - 1].pst_idx + 1;
+ idx = pst[count - 1].pst_idx + 1;
}
}
#endif /* OShpux */
@@ -945,7 +1084,7 @@ static void
do_findprocs(void)
{
clear(&found);
-
+
if (pidfile)
do_pidfile(pidfile);
else
@@ -958,15 +1097,15 @@ do_stop(int signal_nr, int quietmode, int *n_killed, int *n_notkilled, int retry
{
struct pid_list *p;
- do_findprocs();
-
- *n_killed = 0;
- *n_notkilled = 0;
-
- if (!found)
- return;
-
- clear(&killed);
+ do_findprocs();
+
+ *n_killed = 0;
+ *n_notkilled = 0;
+
+ if (!found)
+ return;
+
+ clear(&killed);
for (p = found; p; p = p->next) {
if (testmode) {
@@ -975,21 +1114,21 @@ do_stop(int signal_nr, int quietmode, int *n_killed, int *n_notkilled, int retry
(*n_killed)++;
} else if (kill(p->pid, signal_nr) == 0) {
push(&killed, p->pid);
- (*n_killed)++;
+ (*n_killed)++;
} else {
printf("%s: warning: failed to kill %d: %s\n",
progname, p->pid, strerror(errno));
- (*n_notkilled)++;
+ (*n_notkilled)++;
}
}
if (quietmode < 0 && killed) {
- printf("Stopped %s (pid", what_stop);
+ printf("Stopped %s (pid", what_stop);
for (p = killed; p; p = p->next)
printf(" %d", p->pid);
- putchar(')');
- if (retry_nr > 0)
- printf(", retry #%d", retry_nr);
- printf(".\n");
+ putchar(')');
+ if (retry_nr > 0)
+ printf(", retry #%d", retry_nr);
+ printf(".\n");
}
}
@@ -1105,7 +1244,7 @@ run_stop_schedule(void)
if (interval.tv_sec == 0 &&
interval.tv_usec <= MIN_POLL_INTERVAL)
- interval.tv_usec = MIN_POLL_INTERVAL;
+ interval.tv_usec = MIN_POLL_INTERVAL;
r = select(0,0,0,0,&interval);
if (r < 0 && errno != EINTR)
@@ -1139,11 +1278,13 @@ run_stop_schedule(void)
}
-int main(int argc, char **argv) NONRETURNING;
int
main(int argc, char **argv)
{
int devnull_fd = -1;
+ int stdin_fd = -1;
+ int stdout_fd = -1;
+ int stderr_fd = -1;
#ifdef HAVE_TIOCNOTTY
int tty_fd = -1;
#endif
@@ -1153,8 +1294,25 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
- if (execname && stat(execname, &exec_stat))
- fatal("stat %s: %s", execname, strerror(errno));
+ if (changeroot == NULL) {
+ if (execname && stat(execname, &exec_stat))
+ fatal("stat %s: %s", execname, strerror(errno));
+ } else {
+ if (execname) {
+ char *tmp = NULL;
+
+ tmp = malloc(strlen(changeroot) + strlen(execname) + 1);
+ strncpy(tmp, changeroot, strlen(changeroot));
+ strncat(tmp, execname, strlen(execname));
+
+ if (stat(tmp, &exec_stat)) {
+ fatal("stat %s: %s", tmp, strerror(errno));
+ free(tmp);
+ } else {
+ free(tmp);
+ }
+ }
+ }
if (userspec && sscanf(userspec, "%d", &user_id) != 1) {
struct passwd *pw;
@@ -1219,7 +1377,7 @@ main(int argc, char **argv)
if (background) { /* ok, we need to detach this process */
int i;
if (quietmode < 0)
- printf("Detatching to start %s...", startas);
+ printf("Detaching to start %s...", startas);
i = fork();
if (i<0) {
fatal("Unable to fork.\n");
@@ -1236,37 +1394,47 @@ main(int argc, char **argv)
#endif
devnull_fd=open("/dev/null", O_RDWR);
}
+ if (stdindev != NULL)
+ stdin_fd=open(stdindev, O_RDWR | O_APPEND);
+ if (stdoutdev != NULL)
+ stdout_fd=open(stdoutdev, O_RDWR | O_APPEND);
+ if (stderrdev != NULL)
+ stderr_fd=open(stderrdev, O_RDWR | O_APPEND);
if (nicelevel) {
errno=0;
if ((nice(nicelevel)==-1) && (errno!=0))
fatal("Unable to alter nice level by %i: %s", nicelevel,
strerror(errno));
}
- if (mpidfile && pidfile != NULL) { /* user wants _us_ to make the pidfile :) */
- FILE *pidf = fopen(pidfile, "w");
- pid_t pidt = getpid();
- if (pidf == NULL)
- fatal("Unable to open pidfile `%s' for writing: %s", pidfile,
- strerror(errno));
- fprintf(pidf, "%d\n", pidt);
- fclose(pidf);
- }
if (changeroot != NULL) {
if (chdir(changeroot) < 0)
fatal("Unable to chdir() to %s", changeroot);
if (chroot(changeroot) < 0)
fatal("Unable to chroot() to %s", changeroot);
}
- if (changedir != NULL && chdir(changedir) < 0)
+ if (chdir(changedir) < 0)
fatal("Unable to chdir() to %s", changedir);
+ if (mpidfile && pidfile != NULL) { /* user wants _us_ to make the pidfile :) */
+ FILE *pidf = fopen(pidfile, "w");
+ pid_t pidt = getpid();
+ if (pidf == NULL)
+ fatal("Unable to open pidfile `%s' for writing: %s", pidfile,
+ strerror(errno));
+ fprintf(pidf, "%d\n", pidt);
+ fclose(pidf);
+ }
if (changeuser != NULL) {
- if (setgid(runas_gid))
- fatal("Unable to set gid to %d", runas_gid);
+ if (setgid(runas_gid))
+ fatal("Unable to set gid to %d", runas_gid);
if (initgroups(changeuser, runas_gid))
fatal("Unable to set initgroups() with gid %d", runas_gid);
if (setuid(runas_uid))
fatal("Unable to set uid to %s", changeuser);
}
+ if (env != NULL) {
+ if(putenv(env))
+ fatal("Unable to set variable: %s", env);
+ }
if (background) { /* continue background setup */
int i;
#ifdef HAVE_TIOCNOTTY
@@ -1275,9 +1443,7 @@ main(int argc, char **argv)
close(tty_fd);
#endif
umask(022); /* set a default for dumb programs */
- dup2(devnull_fd,0); /* stdin */
- dup2(devnull_fd,1); /* stdout */
- dup2(devnull_fd,2); /* stderr */
+
#if defined(OShpux)
/* now close all extra fds */
for (i=sysconf(_SC_OPEN_MAX)-1; i>=3; --i) close(i);
@@ -1293,7 +1459,21 @@ main(int argc, char **argv)
setpgid(0,0);
#endif
}
+ if (stdin_fd == -1)
+ dup2(devnull_fd,0); /* stdin */
+ else
+ dup2(stdin_fd,0); /* stdin */
+
+ if (stdout_fd == -1)
+ dup2(devnull_fd,1); /* stdout */
+ else
+ dup2(stdout_fd,1); /* stdout */
+
+ if (stderr_fd == -1)
+ dup2(devnull_fd,2); /* stderr */
+ else
+ dup2(stderr_fd,2); /* stderr */
+
execv(startas, argv);
fatal("Unable to start %s: %s", startas, strerror(errno));
}
-

0 comments on commit 2f4e404

Please sign in to comment.
Something went wrong with that request. Please try again.