aboutsummaryrefslogtreecommitdiff
path: root/src/rc/start-stop-daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rc/start-stop-daemon.c')
-rw-r--r--src/rc/start-stop-daemon.c973
1 files changed, 482 insertions, 491 deletions
diff --git a/src/rc/start-stop-daemon.c b/src/rc/start-stop-daemon.c
index 9ffeba05..bfb737a5 100644
--- a/src/rc/start-stop-daemon.c
+++ b/src/rc/start-stop-daemon.c
@@ -46,6 +46,7 @@
#include <sys/termios.h>
#include <sys/time.h>
#include <sys/wait.h>
+
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -71,63 +72,57 @@ static struct pam_conv conv = { NULL, NULL};
#include "einfo.h"
#include "rc.h"
#include "rc-misc.h"
-#include "strlist.h"
-typedef struct schedulelist
+typedef struct scheduleitem
{
enum
{
- schedule_timeout,
- schedule_signal,
- schedule_goto,
- schedule_forever
+ SC_TIMEOUT,
+ SC_SIGNAL,
+ SC_GOTO,
+ SC_FOREVER
} type;
int value;
- struct schedulelist *gotolist;
- struct schedulelist *next;
-} schedulelist_t;
-static schedulelist_t *schedule;
+ struct scheduleitem *gotoitem;
+ STAILQ_ENTRY(scheduleitem) entries;
+} SCHEDULEITEM;
+STAILQ_HEAD(, scheduleitem) schedule;
extern const char *applet;
static char *changeuser;
-static char **newenv;
extern char **environ;
-static void free_schedulelist (schedulelist_t **list)
+static void free_schedulelist(void)
{
- schedulelist_t *here;
- schedulelist_t *next;
+ SCHEDULEITEM *s1 = STAILQ_FIRST(&schedule);
+ SCHEDULEITEM *s2;
- for (here = *list; here; here = next) {
- next = here->next;
- free (here);
+ while (s1) {
+ s2 = STAILQ_NEXT(s1, entries);
+ free(s1);
+ s1 = s2;
}
-
- *list = NULL;
+ STAILQ_INIT(&schedule);
}
-static void cleanup (void)
+static void cleanup(void)
{
if (changeuser)
- free (changeuser);
-
- if (schedule)
- free_schedulelist (&schedule);
+ free(changeuser);
- if (newenv)
- rc_strlist_free (newenv);
+ free_schedulelist();
}
-static int parse_signal (const char *sig)
+static int parse_signal(const char *sig)
{
typedef struct signalpair
{
const char *name;
int signal;
- } signalpair_t;
+ } SIGNALPAIR;
- static const signalpair_t signallist[] = {
+ static const SIGNALPAIR signallist[] = {
{ "ABRT", SIGABRT },
{ "ALRM", SIGALRM },
{ "FPE", SIGFPE },
@@ -153,161 +148,158 @@ static int parse_signal (const char *sig)
const char *s;
if (! sig || *sig == '\0')
- return (-1);
+ return -1;
- if (sscanf (sig, "%u", &i) == 1) {
- if (i > 0 && i < sizeof (signallist) / sizeof (signallist[0]))
- return (i);
- eerrorx ("%s: `%s' is not a valid signal", applet, sig);
+ if (sscanf(sig, "%u", &i) == 1) {
+ if (i > 0 && i < sizeof(signallist) / sizeof(signallist[0]))
+ return i;
+ eerrorx("%s: `%s' is not a valid signal", applet, sig);
}
- if (strncmp (sig, "SIG", 3) == 0)
+ if (strncmp(sig, "SIG", 3) == 0)
s = sig + 3;
else
s = NULL;
- for (i = 0; i < sizeof (signallist) / sizeof (signallist[0]); i++)
- if (strcmp (sig, signallist[i].name) == 0 ||
- (s && strcmp (s, signallist[i].name) == 0))
- return (signallist[i].signal);
+ for (i = 0; i < sizeof(signallist) / sizeof(signallist[0]); i++)
+ if (strcmp(sig, signallist[i].name) == 0 ||
+ (s && strcmp(s, signallist[i].name) == 0))
+ return signallist[i].signal;
- eerrorx ("%s: `%s' is not a valid signal", applet, sig);
+ eerrorx("%s: `%s' is not a valid signal", applet, sig);
/* NOTREACHED */
}
-static void parse_schedule_item (schedulelist_t *item, const char *string)
+static SCHEDULEITEM *parse_schedule_item(const char *string)
{
const char *after_hyph;
int sig;
-
- if (strcmp (string,"forever") == 0)
- item->type = schedule_forever;
- else if (isdigit ((int) string[0])) {
- item->type = schedule_timeout;
+ SCHEDULEITEM *item = xmalloc(sizeof(*item));
+
+ item->value = 0;
+ item->gotoitem = NULL;
+ if (strcmp(string,"forever") == 0)
+ item->type = SC_FOREVER;
+ else if (isdigit((int) string[0])) {
+ item->type = SC_TIMEOUT;
errno = 0;
- if (sscanf (string, "%d", &item->value) != 1)
- eerrorx ("%s: invalid timeout value in schedule `%s'", applet,
- string);
+ if (sscanf(string, "%d", &item->value) != 1)
+ eerrorx("%s: invalid timeout value in schedule `%s'", applet,
+ string);
} else if ((after_hyph = string + (string[0] == '-')) &&
- ((sig = parse_signal (after_hyph)) != -1))
+ ((sig = parse_signal(after_hyph)) != -1))
{
- item->type = schedule_signal;
- item->value = (int) sig;
+ item->type = SC_SIGNAL;
+ item->value = (int)sig;
}
else
- eerrorx ("%s: invalid schedule item `%s'", applet, string);
+ eerrorx("%s: invalid schedule item `%s'", applet, string);
+
+ return item;
}
-static void parse_schedule (const char *string, int default_signal)
+static void parse_schedule(const char *string, int timeout)
{
char buffer[20];
const char *slash;
int count = 0;
- schedulelist_t *repeatat = NULL;
+ SCHEDULEITEM *repeatat = NULL;
size_t len;
- schedulelist_t *next;
+ SCHEDULEITEM *item;
if (string)
for (slash = string; *slash; slash++)
if (*slash == '/')
count++;
- if (schedule)
- free_schedulelist (&schedule);
-
- schedule = xmalloc (sizeof (*schedule));
- schedule->gotolist = NULL;
+ free_schedulelist();
if (count == 0) {
- schedule->type = schedule_signal;
- schedule->value = default_signal;
- schedule->next = xmalloc (sizeof (*schedule->next));
- next = schedule->next;
- next->type = schedule_timeout;
- next->gotolist = NULL;
+ item = xmalloc(sizeof(*item));
+ item->type = SC_SIGNAL;
+ item->value = timeout;
+ item->gotoitem = NULL;
+ STAILQ_INSERT_TAIL(&schedule, item, entries);
+
+ item = xmalloc(sizeof(*item));
+ item->type = SC_TIMEOUT;
+ item->gotoitem = NULL;
+ STAILQ_INSERT_TAIL(&schedule, item, entries);
if (string) {
- if (sscanf (string, "%d", &next->value) != 1)
- eerrorx ("%s: invalid timeout value in schedule", applet);
- }
- else
- next->value = 5;
- next->next = NULL;
+ if (sscanf(string, "%d", &item->value) != 1)
+ eerrorx("%s: invalid timeout value in schedule", applet);
+ } else
+ item->value = 5;
return;
}
- next = schedule;
while (string != NULL) {
- if ((slash = strchr (string, '/')))
+ if ((slash = strchr(string, '/')))
len = slash - string;
else
- len = strlen (string);
+ len = strlen(string);
- if (len >= (ptrdiff_t) sizeof (buffer))
- eerrorx ("%s: invalid schedule item, far too long", applet);
+ if (len >= (ptrdiff_t) sizeof(buffer))
+ eerrorx("%s: invalid schedule item, far too long", applet);
- memcpy (buffer, string, len);
+ memcpy(buffer, string, len);
buffer[len] = 0;
string = slash ? slash + 1 : NULL;
- parse_schedule_item (next, buffer);
- if (next->type == schedule_forever) {
+ item = parse_schedule_item(buffer);
+ STAILQ_INSERT_TAIL(&schedule, item, entries);
+ if (item->type == SC_FOREVER) {
if (repeatat)
- eerrorx ("%s: invalid schedule, `forever' appears more than once",
- applet);
+ eerrorx("%s: invalid schedule, `forever' "
+ "appears more than once", applet);
- repeatat = next;
+ repeatat = item;
continue;
}
-
- if (string) {
- next->next = xmalloc (sizeof (*next->next));
- next = next->next;
- next->gotolist = NULL;
- }
}
if (repeatat) {
- next->next = xmalloc (sizeof (*next->next));
- next = next->next;
- next->type = schedule_goto;
- next->value = 0;
- next->gotolist = repeatat;
+ item = xmalloc(sizeof(*item));
+ item->type = SC_GOTO;
+ item->value = 0;
+ item->gotoitem = repeatat;
+ STAILQ_INSERT_TAIL(&schedule, item, entries);
}
- next->next = NULL;
return;
}
-static pid_t get_pid (const char *pidfile, bool quiet)
+static pid_t get_pid(const char *pidfile, bool quiet)
{
FILE *fp;
pid_t pid;
if (! pidfile)
- return (-1);
+ return -1;
- if ((fp = fopen (pidfile, "r")) == NULL) {
+ if ((fp = fopen(pidfile, "r")) == NULL) {
if (! quiet)
- eerror ("%s: fopen `%s': %s", applet, pidfile, strerror (errno));
- return (-1);
+ eerror("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
+ return -1;
}
- if (fscanf (fp, "%d", &pid) != 1) {
+ if (fscanf(fp, "%d", &pid) != 1) {
if (! quiet)
- eerror ("%s: no pid found in `%s'", applet, pidfile);
- fclose (fp);
- return (-1);
+ eerror("%s: no pid found in `%s'", applet, pidfile);
+ fclose(fp);
+ return -1;
}
- fclose (fp);
+
+ fclose(fp);
- return (pid);
+ return pid;
}
/* return number of processed killed, -1 on error */
-static int do_stop (const char *const *argv, const char *cmd,
- const char *pidfile, uid_t uid,int sig,
- bool quiet, bool verbose, bool test)
+static int do_stop(const char *const *argv, const char *cmd,
+ const char *pidfile, uid_t uid,int sig,
+ bool quiet, bool verbose, bool test)
{
pid_t *pids;
bool killed;
@@ -316,30 +308,30 @@ static int do_stop (const char *const *argv, const char *cmd,
int i;
if (pidfile) {
- if ((pid = get_pid (pidfile, quiet)) == -1)
- return (quiet ? 0 : -1);
- pids = rc_find_pids (NULL, NULL, 0, pid);
+ if ((pid = get_pid(pidfile, quiet)) == -1)
+ return quiet ? 0 : -1;
+ pids = rc_find_pids(NULL, NULL, 0, pid);
} else
- pids = rc_find_pids (argv, cmd, uid, pid);
+ pids = rc_find_pids(argv, cmd, uid, pid);
if (! pids)
- return (0);
+ return 0;
for (i = 0; pids[i]; i++) {
if (test) {
if (! quiet)
- einfo ("Would send signal %d to PID %d", sig, pids[i]);
+ einfo("Would send signal %d to PID %d", sig, pids[i]);
nkilled++;
continue;
}
if (verbose)
- ebegin ("Sending signal %d to PID %d", sig, pids[i]);
+ ebegin("Sending signal %d to PID %d", sig, pids[i]);
errno = 0;
- killed = (kill (pids[i], sig) == 0 || errno == ESRCH ? true : false);
+ killed = (kill(pids[i], sig) == 0 || errno == ESRCH ? true : false);
if (verbose)
- eend (killed ? 0 : 1, "%s: failed to send signal %d to PID %d: %s",
- applet, sig, pids[i], strerror (errno));
+ eend(killed ? 0 : 1, "%s: failed to send signal %d to PID %d: %s",
+ applet, sig, pids[i], strerror(errno));
if (! killed) {
nkilled = -1;
} else {
@@ -348,15 +340,15 @@ static int do_stop (const char *const *argv, const char *cmd,
}
}
- free (pids);
- return (nkilled);
+ free(pids);
+ return nkilled;
}
-static int run_stop_schedule (const char *const *argv, const char *cmd,
- const char *pidfile, uid_t uid,
- bool quiet, bool verbose, bool test)
+static int run_stop_schedule(const char *const *argv, const char *cmd,
+ const char *pidfile, uid_t uid,
+ bool quiet, bool verbose, bool test)
{
- schedulelist_t *item = schedule;
+ SCHEDULEITEM *item = STAILQ_FIRST(&schedule);
int nkilled = 0;
int tkilled = 0;
int nrunning = 0;
@@ -365,119 +357,121 @@ static int run_stop_schedule (const char *const *argv, const char *cmd,
if (verbose) {
if (pidfile)
- einfo ("Will stop PID in pidfile `%s'", pidfile);
+ einfo("Will stop PID in pidfile `%s'", pidfile);
if (uid)
- einfo ("Will stop processes owned by UID %d", uid);
+ einfo("Will stop processes owned by UID %d", uid);
if (argv && *argv)
- einfo ("Will stop processes of `%s'", *argv);
+ einfo("Will stop processes of `%s'", *argv);
if (cmd)
- einfo ("Will stop processes called `%s'", cmd);
+ einfo("Will stop processes called `%s'", cmd);
}
while (item) {
- switch (item->type) {
- case schedule_goto:
- item = item->gotolist;
- continue;
+ switch (item->type) {
+ case SC_GOTO:
+ item = item->gotoitem;
+ continue;
- case schedule_signal:
- nrunning = 0;
- nkilled = do_stop (argv, cmd, pidfile, uid, item->value,
- quiet, verbose, test);
- if (nkilled == 0) {
- if (tkilled == 0) {
- if (! quiet)
- eerror ("%s: no matching processes found", applet);
- }
- return (tkilled);
+ case SC_SIGNAL:
+ nrunning = 0;
+ nkilled = do_stop(argv, cmd, pidfile, uid, item->value,
+ quiet, verbose, test);
+ if (nkilled == 0) {
+ if (tkilled == 0) {
+ if (! quiet)
+ eerror("%s: no matching "
+ "processes found", applet);
}
- else if (nkilled == -1)
- return (0);
+ return tkilled;
+ }
+ else if (nkilled == -1)
+ return 0;
- tkilled += nkilled;
+ tkilled += nkilled;
+ break;
+ case SC_TIMEOUT:
+ if (item->value < 1) {
+ item = NULL;
break;
- case schedule_timeout:
- if (item->value < 1) {
- item = NULL;
- break;
- }
+ }
- nloops = (ONE_SECOND / POLL_INTERVAL) * item->value;
- ts.tv_sec = 0;
- ts.tv_nsec = POLL_INTERVAL;
-
- while (nloops) {
- if ((nrunning = do_stop (argv, cmd, pidfile,
- uid, 0, true, false, true)) == 0)
- return (true);
-
- if (nanosleep (&ts, NULL) == -1) {
- if (errno == EINTR)
- eerror ("%s: caught an interrupt", applet);
- else {
- eerror ("%s: nanosleep: %s", applet, strerror (errno));
- return (0);
- }
+ nloops = (ONE_SECOND / POLL_INTERVAL) * item->value;
+ ts.tv_sec = 0;
+ ts.tv_nsec = POLL_INTERVAL;
+
+ while (nloops) {
+ if ((nrunning = do_stop(argv, cmd, pidfile,
+ uid, 0, true, false, true)) == 0)
+ return true;
+
+ if (nanosleep(&ts, NULL) == -1) {
+ if (errno == EINTR)
+ eerror("%s: caught an interrupt", applet);
+ else {
+ eerror("%s: nanosleep: %s",
+ applet, strerror(errno));
+ return 0;
}
- nloops --;
}
- break;
+ nloops --;
+ }
+ break;
- default:
- eerror ("%s: invalid schedule item `%d'", applet, item->type);
- return (0);
+ default:
+ eerror("%s: invalid schedule item `%d'", applet, item->type);
+ return 0;
}
if (item)
- item = item->next;
+ item = STAILQ_NEXT(item, entries);
}
if (test || (tkilled > 0 && nrunning == 0))
- return (nkilled);
+ return nkilled;
if (! quiet) {
if (nrunning == 1)
- eerror ("%s: %d process refused to stop", applet, nrunning);
+ eerror("%s: %d process refused to stop", applet, nrunning);
else
- eerror ("%s: %d process(es) refused to stop", applet, nrunning);
+ eerror("%s: %d process(es) refused to stop", applet, nrunning);
}
- return (-nrunning);
+ return -nrunning;
}
-static void handle_signal (int sig)
+static void handle_signal(int sig)
{
int status;
int serrno = errno;
char signame[10] = { '\0' };
switch (sig) {
- case SIGINT:
- if (! signame[0])
- snprintf (signame, sizeof (signame), "SIGINT");
- /* FALLTHROUGH */
- case SIGTERM:
- if (! signame[0])
- snprintf (signame, sizeof (signame), "SIGTERM");
- /* FALLTHROUGH */
- case SIGQUIT:
- if (! signame[0])
- snprintf (signame, sizeof (signame), "SIGQUIT");
- eerrorx ("%s: caught %s, aborting", applet, signame);
- /* NOTREACHED */
-
- case SIGCHLD:
- for (;;) {
- if (waitpid (-1, &status, WNOHANG) < 0) {
- if (errno != ECHILD)
- eerror ("%s: waitpid: %s", applet, strerror (errno));
- break;
- }
+ case SIGINT:
+ if (! signame[0])
+ snprintf(signame, sizeof(signame), "SIGINT");
+ /* FALLTHROUGH */
+ case SIGTERM:
+ if (! signame[0])
+ snprintf(signame, sizeof(signame), "SIGTERM");
+ /* FALLTHROUGH */
+ case SIGQUIT:
+ if (! signame[0])
+ snprintf(signame, sizeof(signame), "SIGQUIT");
+ eerrorx("%s: caught %s, aborting", applet, signame);
+ /* NOTREACHED */
+
+ case SIGCHLD:
+ for (;;) {
+ if (waitpid(-1, &status, WNOHANG) < 0) {
+ if (errno != ECHILD)
+ eerror("%s: waitpid: %s", applet, strerror(errno));
+ break;
}
- break;
+ }
+ break;
- default:
- eerror ("%s: caught unknown signal %d", applet, sig);
+ default:
+ eerror("%s: caught unknown signal %d", applet, sig);
}
/* Restore errno */
@@ -537,7 +531,7 @@ static const char * const longopts_help[] = {
};
#include "_usage.c"
-int start_stop_daemon (int argc, char **argv)
+int start_stop_daemon(int argc, char **argv)
{
int devnull_fd = -1;
#ifdef TIOCNOTTY
@@ -574,154 +568,160 @@ int start_stop_daemon (int argc, char **argv)
int stderr_fd;
pid_t pid;
int i;
- char *svcname = getenv ("SVCNAME");
- char *env;
+ char *svcname = getenv("SVCNAME");
+ RC_STRINGLIST *env_list;
+ RC_STRING *env;
+ char *path;
bool sethome = false;
bool setuser = false;
+ char *p;
+ char *tmp;
+ struct passwd *pw;
+ struct group *gr;
+ char line[130];
+ FILE *fp;
+ size_t len;
- atexit (cleanup);
+ STAILQ_INIT(&schedule);
+ atexit(cleanup);
- signal_setup (SIGINT, handle_signal);
- signal_setup (SIGQUIT, handle_signal);
- signal_setup (SIGTERM, handle_signal);
+ signal_setup(SIGINT, handle_signal);
+ signal_setup(SIGQUIT, handle_signal);
+ signal_setup(SIGTERM, handle_signal);
- if ((env = getenv ("SSD_NICELEVEL")))
- if (sscanf (env, "%d", &nicelevel) != 1)
- eerror ("%s: invalid nice level `%s' (SSD_NICELEVEL)", applet, env);
+ if ((path = getenv("SSD_NICELEVEL")))
+ if (sscanf(path, "%d", &nicelevel) != 1)
+ eerror("%s: invalid nice level `%s' (SSD_NICELEVEL)",
+ applet, path);
- while ((opt = getopt_long (argc, argv, "e:" getoptstring, longopts,
- (int *) 0)) != -1)
+ while ((opt = getopt_long(argc, argv, "e:" getoptstring, longopts,
+ (int *) 0)) != -1)
switch (opt) {
- case 'K': /* --stop */
- stop = true;
- break;
-
- case 'N': /* --nice */
- if (sscanf (optarg, "%d", &nicelevel) != 1)
- eerrorx ("%s: invalid nice level `%s'", applet, optarg);
- break;
+ case 'K': /* --stop */
+ stop = true;
+ break;
- case 'R': /* --retry <schedule>|<timeout> */
- parse_schedule (optarg, sig);
- break;
+ case 'N': /* --nice */
+ if (sscanf(optarg, "%d", &nicelevel) != 1)
+ eerrorx("%s: invalid nice level `%s'", applet, optarg);
+ break;
- case 'S': /* --start */
- start = true;
- break;
+ case 'R': /* --retry <schedule>|<timeout> */
+ parse_schedule(optarg, sig);
+ break;
- case 'b': /* --background */
- background = true;
- break;
+ case 'S': /* --start */
+ start = true;
+ break;
- case 'u': /* --user <username>|<uid> */
- case 'c': /* --chuid <username>|<uid> */
- {
- char *p = optarg;
- char *cu = strsep (&p, ":");
- struct passwd *pw = NULL;
+ case 'b': /* --background */
+ background = true;
+ break;
- changeuser = xstrdup (cu);
- if (sscanf (cu, "%d", &tid) != 1)
- pw = getpwnam (cu);
+ case 'u': /* --user <username>|<uid> */
+ case 'c': /* --chuid <username>|<uid> */
+ {
+ p = optarg;
+ tmp = strsep(&p, ":");
+ changeuser = xstrdup(tmp);
+ if (sscanf(tmp, "%d", &tid) != 1)
+ pw = getpwnam(tmp);
+ else
+ pw = getpwuid((uid_t) tid);
+
+ if (! pw)
+ eerrorx("%s: user `%s' not found", applet, tmp);
+ uid = pw->pw_uid;
+ if (! gid)
+ gid = pw->pw_gid;
+
+ if (p) {
+ tmp = strsep (&p, ":");
+ if (sscanf(tmp, "%d", &tid) != 1)
+ gr = getgrnam(tmp);
else
- pw = getpwuid ((uid_t) tid);
-
- if (! pw)
- eerrorx ("%s: user `%s' not found", applet, cu);
- uid = pw->pw_uid;
- if (! gid)
- gid = pw->pw_gid;
-
- if (p) {
- struct group *gr = NULL;
- char *cg = strsep (&p, ":");
-
- if (sscanf (cg, "%d", &tid) != 1)
- gr = getgrnam (cg);
- else
- gr = getgrgid ((gid_t) tid);
-
- if (! gr)
- eerrorx ("%s: group `%s' not found", applet, cg);
- gid = gr->gr_gid;
- }
- }
- break;
+ gr = getgrgid((gid_t) tid);
- case 'd': /* --chdir /new/dir */
- ch_dir = optarg;
- break;
-
- case 'e': /* --env */
- if (putenv (optarg) == 0) {
- if (strncmp ("HOME=", optarg, 5) == 0)
- sethome = true;
- else if (strncmp ("USER=", optarg, 5) == 0)
- setuser = true;
+ if (! gr)
+ eerrorx("%s: group `%s' not found",
+ applet, tmp);
+ gid = gr->gr_gid;
}
- break;
+ }
+ break;
- case 'g': /* --group <group>|<gid> */
- {
- struct group *gr = getgrnam (optarg);
+ case 'd': /* --chdir /new/dir */
+ ch_dir = optarg;
+ break;
- if (sscanf (optarg, "%d", &tid) != 1)
- gr = getgrnam (optarg);
- else
- gr = getgrgid ((gid_t) tid);
+ case 'e': /* --env */
+ if (putenv(optarg) == 0) {
+ if (strncmp("HOME=", optarg, 5) == 0)
+ sethome = true;
+ else if (strncmp("USER=", optarg, 5) == 0)
+ setuser = true;
+ }
+ break;
- if (! gr)
- eerrorx ("%s: group `%s' not found", applet, optarg);
- gid = gr->gr_gid;
- }
- break;
+ case 'g': /* --group <group>|<gid> */
+ {
+ if (sscanf(optarg, "%d", &tid) != 1)
+ gr = getgrnam(optarg);
+ else
+ gr = getgrgid((gid_t) tid);
- case 'm': /* --make-pidfile */
- makepidfile = true;
- break;
+ if (! gr)
+ eerrorx("%s: group `%s' not found", applet, optarg);
+ gid = gr->gr_gid;
+ }
+ break;
- case 'n': /* --name <process-name> */
- cmd = optarg;
- break;
+ case 'm': /* --make-pidfile */
+ makepidfile = true;
+ break;
- case 'o': /* --oknodo */
- oknodo = true;
- break;
+ case 'n': /* --name <process-name> */
+ cmd = optarg;
+ break;
- case 'p': /* --pidfile <pid-file> */
- pidfile = optarg;
- break;
+ case 'o': /* --oknodo */
+ oknodo = true;
+ break;
- case 's': /* --signal <signal> */
- sig = parse_signal (optarg);
- break;
+ case 'p': /* --pidfile <pid-file> */
+ pidfile = optarg;
+ break;
- case 't': /* --test */
- test = true;
- break;
+ case 's': /* --signal <signal> */
+ sig = parse_signal(optarg);
+ break;
- case 'r': /* --chroot /new/root */
- ch_root = optarg;
- break;
+ case 't': /* --test */
+ test = true;
+ break;
- case 'a':
- case 'x': /* --exec <executable> */
- exec = optarg;
- break;
+ case 'r': /* --chroot /new/root */
+ ch_root = optarg;
+ break;
- case '1': /* --stdout /path/to/stdout.lgfile */
- redirect_stdout = optarg;
- break;
+ case 'a':
+ case 'x': /* --exec <executable> */
+ exec = optarg;
+ break;
- case '2': /* --stderr /path/to/stderr.logfile */
- redirect_stderr = optarg;
- break;
+ case '1': /* --stdout /path/to/stdout.lgfile */
+ redirect_stdout = optarg;
+ break;
+
+ case '2': /* --stderr /path/to/stderr.logfile */
+ redirect_stderr = optarg;
+ break;
- case_RC_COMMON_GETOPT
+ case_RC_COMMON_GETOPT
}
- quiet = rc_yesno (getenv ("EINFO_QUIET"));
- verbose = rc_yesno (getenv ("EINFO_VERBOSE"));
+ quiet = rc_yesno(getenv("EINFO_QUIET"));
+ verbose = rc_yesno(getenv("EINFO_VERBOSE"));
/* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq
* instead of forcing --stop --oknodo as well */
@@ -736,22 +736,22 @@ int start_stop_daemon (int argc, char **argv)
}
if (start == stop)
- eerrorx ("%s: need one of --start or --stop", applet);
+ eerrorx("%s: need one of --start or --stop", applet);
if (start && ! exec)
- eerrorx ("%s: --start needs --exec", applet);
+ eerrorx("%s: --start needs --exec", applet);
if (stop && ! exec && ! pidfile && ! cmd && ! uid)
- eerrorx ("%s: --stop needs --exec, --pidfile, --name or --user", applet);
+ eerrorx("%s: --stop needs --exec, --pidfile, --name or --user", applet);
if (makepidfile && ! pidfile)
- eerrorx ("%s: --make-pidfile is only relevant with --pidfile", applet);
+ eerrorx("%s: --make-pidfile is only relevant with --pidfile", applet);
if (background && ! start)
- eerrorx ("%s: --background is only relevant with --start", applet);
+ eerrorx("%s: --background is only relevant with --start", applet);
if ((redirect_stdout || redirect_stderr) && ! background)
- eerrorx ("%s: --stdout and --stderr are only relevant with --background",
+ eerrorx("%s: --stdout and --stderr are only relevant with --background",
applet);
argc -= optind;
@@ -759,52 +759,49 @@ int start_stop_daemon (int argc, char **argv)
/* Validate that the binary exists if we are starting */
if (exec) {
- char *tmp;
if (ch_root)
- tmp = rc_strcatpaths (ch_root, exec, (char *) NULL);
+ tmp = rc_strcatpaths(ch_root, exec, (char *) NULL);
else
tmp = exec;
- if (start && ! exists (tmp)) {
- eerror ("%s: %s does not exist", applet, tmp);
+ if (start && ! exists(tmp)) {
+ eerror("%s: %s does not exist", applet, tmp);
if (ch_root)
- free (tmp);
- exit (EXIT_FAILURE);
+ free(tmp);
+ exit(EXIT_FAILURE);
}
/* If we don't have a pidfile or name, check it's not
* interpreted, otherwise we should fail */
if (! pidfile && ! cmd) {
- char line[130];
- FILE *fp = fopen (tmp, "r");
-
+ fp = fopen (tmp, "r");
if (fp) {
- fgets (line, sizeof (line), fp);
- fclose (fp);
+ fgets(line, sizeof(line), fp);
+ fclose(fp);
if (line[0] == '#' && line[1] == '!') {
- size_t len = strlen (line) - 1;
+ len = strlen (line) - 1;
/* Remove the trailing newline */
if (line[len] == '\n')
line[len] = '\0';
- eerror ("%s: %s is a script",
+ eerror("%s: %s is a script",
applet, exec);
- eerror ("%s: and should be started, stopped or signalled with ",
- applet);
- eerror ("%s: --exec %s %s",
+ eerror("%s: and should be started, stopped"
+ " or signalled with ", applet);
+ eerror("%s: --exec %s %s",
applet, line + 2, exec);
- eerror ("%s: or you should specify a pidfile or process name",
- applet);
+ eerror("%s: or you should specify a pidfile"
+ " or process name", applet);
if (ch_root)
- free (tmp);
- exit (EXIT_FAILURE);
+ free(tmp);
+ exit(EXIT_FAILURE);
}
}
}
if (ch_root)
- free (tmp);
+ free(tmp);
}
/* Add exec to our arguments */
@@ -813,83 +810,79 @@ int start_stop_daemon (int argc, char **argv)
if (stop) {
int result;
- if (! schedule) {
+ if (! STAILQ_FIRST(&schedule)) {
if (test || oknodo)
- parse_schedule ("0", sig);
+ parse_schedule("0", sig);
else
- parse_schedule (NULL, sig);
+ parse_schedule(NULL, sig);
}
- result = run_stop_schedule ((const char *const *)argv, cmd,
- pidfile, uid, quiet, verbose, test);
+ result = run_stop_schedule((const char *const *)argv, cmd,
+ pidfile, uid, quiet, verbose, test);
if (result < 0)
/* We failed to stop something */
- exit (EXIT_FAILURE);
+ exit(EXIT_FAILURE);
if (test || oknodo)
- return (result > 0 ? EXIT_SUCCESS : EXIT_FAILURE);
+ return result > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
/* Even if we have not actually killed anything, we should
* remove information about it as it may have unexpectedly
* crashed out. We should also return success as the end
* result would be the same. */
- if (pidfile && exists (pidfile))
- unlink (pidfile);
+ if (pidfile && exists(pidfile))
+ unlink(pidfile);
if (svcname)
- rc_service_daemon_set (svcname,
- (const char *const *)argv,
- cmd, pidfile, false);
+ rc_service_daemon_set(svcname,
+ (const char *const *)argv,
+ cmd, pidfile, false);
- exit (EXIT_SUCCESS);
+ exit(EXIT_SUCCESS);
}
- if (do_stop ((const char * const *)argv, cmd, pidfile, uid,
- 0, true, false, true) > 0)
- eerrorx ("%s: %s is already running", applet, exec);
+ if (do_stop((const char * const *)argv, cmd, pidfile, uid,
+ 0, true, false, true) > 0)
+ eerrorx("%s: %s is already running", applet, exec);
if (test) {
if (quiet)
exit (EXIT_SUCCESS);
- einfon ("Would start");
+ einfon("Would start");
while (argc-- >= 0)
printf(" %s", *argv++);
- printf ("\n");
- eindent ();
+ printf("\n");
+ eindent();
if (uid != 0)
- einfo ("as user id %d", uid);
+ einfo("as user id %d", uid);
if (gid != 0)
- einfo ("as group id %d", gid);
+ einfo("as group id %d", gid);
if (ch_root)
- einfo ("in root `%s'", ch_root);
+ einfo("in root `%s'", ch_root);
if (ch_dir)
- einfo ("in dir `%s'", ch_dir);
+ einfo("in dir `%s'", ch_dir);
if (nicelevel != 0)
- einfo ("with a priority of %d", nicelevel);
- eoutdent ();
- exit (EXIT_SUCCESS);
+ einfo("with a priority of %d", nicelevel);
+ eoutdent();
+ exit(EXIT_SUCCESS);
}
- /* Ensure this is unset, so if the daemon does /etc/init.d/foo
- Then we filter the environment accordingly */
- unsetenv ("RC_SOFTLEVEL");
-
if (verbose) {
- ebegin ("Detaching to start `%s'", exec);
- eindent ();
+ ebegin("Detaching to start `%s'", exec);
+ eindent();
}
if (background)
- signal_setup (SIGCHLD, handle_signal);
+ signal_setup(SIGCHLD, handle_signal);
- if ((pid = fork ()) == -1)
- eerrorx ("%s: fork: %s", applet, strerror (errno));
+ if ((pid = fork()) == -1)
+ eerrorx("%s: fork: %s", applet, strerror(errno));
/* Child process - lets go! */
if (pid == 0) {
- pid_t mypid = getpid ();
+ pid_t mypid = getpid();
#ifdef TIOCNOTTY
tty_fd = open("/dev/tty", O_RDWR);
@@ -898,66 +891,66 @@ int start_stop_daemon (int argc, char **argv)
devnull_fd = open("/dev/null", O_RDWR);
if (nicelevel) {
- if (setpriority (PRIO_PROCESS, mypid, nicelevel) == -1)
- eerrorx ("%s: setpritory %d: %s", applet, nicelevel,
+ if (setpriority(PRIO_PROCESS, mypid, nicelevel) == -1)
+ eerrorx("%s: setpritory %d: %s", applet, nicelevel,
strerror(errno));
}
- if (ch_root && chroot (ch_root) < 0)
- eerrorx ("%s: chroot `%s': %s", applet, ch_root, strerror (errno));
+ if (ch_root && chroot(ch_root) < 0)
+ eerrorx("%s: chroot `%s': %s", applet, ch_root, strerror(errno));
if (ch_dir && chdir (ch_dir) < 0)
- eerrorx ("%s: chdir `%s': %s", applet, ch_dir, strerror (errno));
+ eerrorx("%s: chdir `%s': %s", applet, ch_dir, strerror(errno));
if (makepidfile && pidfile) {
- FILE *fp = fopen (pidfile, "w");
+ fp = fopen(pidfile, "w");
if (! fp)
- eerrorx ("%s: fopen `%s': %s", applet, pidfile, strerror
- (errno));
- fprintf (fp, "%d\n", mypid);
- fclose (fp);
+ eerrorx("%s: fopen `%s': %s", applet, pidfile,
+ strerror(errno));
+ fprintf(fp, "%d\n", mypid);
+ fclose(fp);
}
#ifdef HAVE_PAM
if (changeuser != NULL)
- pamr = pam_start ("start-stop-daemon", changeuser, &conv, &pamh);
+ pamr = pam_start("start-stop-daemon", changeuser, &conv, &pamh);
else
- pamr = pam_start ("start-stop-daemon", "nobody", &conv, &pamh);
+ pamr = pam_start("start-stop-daemon", "nobody", &conv, &pamh);
if (pamr == PAM_SUCCESS)
- pamr = pam_authenticate (pamh, PAM_SILENT);
+ pamr = pam_authenticate(pamh, PAM_SILENT);
if (pamr == PAM_SUCCESS)
- pamr = pam_acct_mgmt (pamh, PAM_SILENT);
+ pamr = pam_acct_mgmt(pamh, PAM_SILENT);
if (pamr == PAM_SUCCESS)
- pamr = pam_open_session (pamh, PAM_SILENT);
+ pamr = pam_open_session(pamh, PAM_SILENT);
if (pamr != PAM_SUCCESS)
- eerrorx ("%s: pam error: %s", applet, pam_strerror(pamh, pamr));
+ eerrorx("%s: pam error: %s", applet, pam_strerror(pamh, pamr));
#endif
- if (gid && setgid (gid))
- eerrorx ("%s: unable to set groupid to %d", applet, gid);
- if (changeuser && initgroups (changeuser, gid))
- eerrorx ("%s: initgroups (%s, %d)", applet, changeuser, gid);
- if (uid && setuid (uid))
+ if (gid && setgid(gid))
+ eerrorx("%s: unable to set groupid to %d", applet, gid);
+ if (changeuser && initgroups(changeuser, gid))
+ eerrorx("%s: initgroups (%s, %d)", applet, changeuser, gid);
+ if (uid && setuid(uid))
eerrorx ("%s: unable to set userid to %d", applet, uid);
else {
- struct passwd *passwd = getpwuid (uid);
- if (passwd) {
+ pw = getpwuid(uid);
+ if (pw) {
if (! sethome) {
- unsetenv ("HOME");
- if (passwd->pw_dir)
- setenv ("HOME", passwd->pw_dir, 1);
+ unsetenv("HOME");
+ if (pw->pw_dir)
+ setenv("HOME", pw->pw_dir, 1);
}
if (! setuser) {
- unsetenv ("USER");
- if (passwd->pw_name)
- setenv ("USER", passwd->pw_name, 1);
+ unsetenv("USER");
+ if (pw->pw_name)
+ setenv("USER", pw->pw_name, 1);
}
}
}
/* Close any fd's to the passwd database */
- endpwent ();
+ endpwent();
#ifdef TIOCNOTTY
ioctl(tty_fd, TIOCNOTTY, 0);
@@ -965,84 +958,81 @@ int start_stop_daemon (int argc, char **argv)
#endif
/* Clean the environment of any RC_ variables */
- STRLIST_FOREACH (environ, env, i) {
- if ((strncmp (env, "RC_", 3) == 0 &&
- strncmp (env, "RC_SERVICE=", strlen ("RC_SERVICE=")) != 0) ||
- strncmp (env, "SSD_NICELEVEL=", strlen ("SSD_NICELEVEL=")) == 0)
+ env_list = rc_stringlist_new();
+ i = 0;
+ while(environ[i])
+ rc_stringlist_add(env_list, environ[i++]);
+ TAILQ_FOREACH(env, env_list, entries) {
+ if ((strncmp(env->value, "RC_", 3) == 0 &&
+ strncmp(env->value, "RC_SERVICE=", strlen("RC_SERVICE=")) != 0) ||
+ strncmp(env->value, "SSD_NICELEVEL=", strlen("SSD_NICELEVEL=")) == 0)
+ {
+ p = strchr(env->value, '=');
+ *p = '\0';
+ unsetenv(env->value);
continue;
-
- /* For the path, remove the rcscript bin dir from it */
- if (strncmp (env, "PATH=", 5) == 0) {
- char *path = xstrdup (env);
- char *newpath = NULL;
- char *p = path;
- char *token;
- char *np;
- size_t l;
- int t;
-
- p += 5;
- while ((token = strsep (&p, ":"))) {
- if (strcmp (token, RC_LIBDIR "/bin") == 0 ||
- strcmp (token, RC_LIBDIR "/sbin") == 0)
- continue;
-
- t = strlen (token);
- if (newpath) {
- l = strlen (newpath);
- newpath = xrealloc (newpath, sizeof (char) * (l + t + 2));
- np = newpath + l;
- *np++ = ':';
- memcpy (np, token, sizeof (char) * strlen (token));
- np += t;
- *np = '\0';
- } else {
- l = strlen ("PATH=") + t + 1;
- newpath = xmalloc (sizeof (char) * l);
- snprintf (newpath, l, "PATH=%s", token);
- }
- }
- rc_strlist_add (&newenv, newpath);
- free (path);
- free (newpath);
- } else
- rc_strlist_add (&newenv, env);
+ }
+ }
+ rc_stringlist_free(env_list);
+
+ /* For the path, remove the rcscript bin dir from it */
+ if ((path = getenv("PATH"))) {
+ size_t mx = strlen(path);
+ char *newpath = xmalloc(mx);
+ char *token;
+ char *np = newpath;
+ size_t l;
+
+ p = path;
+ while ((token = strsep (&p, ":"))) {
+ if (strcmp (token, RC_LIBDIR "/bin") == 0 ||
+ strcmp (token, RC_LIBDIR "/sbin") == 0)
+ continue;
+
+ l = strlen (token);
+ if (np != newpath)
+ *np++ = ':';
+ memcpy (np, token, l);
+ np += l;
+ *np = '\0';
+ }
+ unsetenv("PATH");
+ setenv("PATH", newpath, 1);
}
- umask (022);
+ umask(022);
stdout_fd = devnull_fd;
stderr_fd = devnull_fd;
if (redirect_stdout) {
- if ((stdout_fd = open (redirect_stdout, O_WRONLY | O_CREAT | O_APPEND,
- S_IRUSR | S_IWUSR)) == -1)
- eerrorx ("%s: unable to open the logfile for stdout `%s': %s",
- applet, redirect_stdout, strerror (errno));
+ if ((stdout_fd = open(redirect_stdout, O_WRONLY | O_CREAT | O_APPEND,
+ S_IRUSR | S_IWUSR)) == -1)
+ eerrorx("%s: unable to open the logfile for stdout `%s': %s",
+ applet, redirect_stdout, strerror(errno));
}
if (redirect_stderr) {
- if ((stderr_fd = open (redirect_stderr, O_WRONLY | O_CREAT | O_APPEND,
- S_IRUSR | S_IWUSR)) == -1)
- eerrorx ("%s: unable to open the logfile for stderr `%s': %s",
- applet, redirect_stderr, strerror (errno));
+ if ((stderr_fd = open(redirect_stderr, O_WRONLY | O_CREAT | O_APPEND,
+ S_IRUSR | S_IWUSR)) == -1)
+ eerrorx("%s: unable to open the logfile for stderr `%s': %s",
+ applet, redirect_stderr, strerror(errno));
}
/* We don't redirect stdin as some daemons may need it */
if (background || quiet || redirect_stdout)
- dup2 (stdout_fd, STDOUT_FILENO);
+ dup2(stdout_fd, STDOUT_FILENO);
if (background || quiet || redirect_stderr)
- dup2 (stderr_fd, STDERR_FILENO);
+ dup2(stderr_fd, STDERR_FILENO);
- for (i = getdtablesize () - 1; i >= 3; --i)
+ for (i = getdtablesize() - 1; i >= 3; --i)
close(i);
- setsid ();
-
- execve (exec, argv, newenv);
+ setsid();
+ execv(exec, argv);
#ifdef HAVE_PAM
if (pamr == PAM_SUCCESS)
- pam_close_session (pamh, PAM_SILENT);
+ pam_close_session(pamh, PAM_SILENT);
#endif
- eerrorx ("%s: failed to exec `%s': %s", applet, exec, strerror (errno));
+ eerrorx("%s: failed to exec `%s': %s", applet, exec, strerror(errno));
}
/* Parent process */
@@ -1053,17 +1043,17 @@ int start_stop_daemon (int argc, char **argv)
errno = 0;
do {
- pid = waitpid (savepid, &status, 0);
+ pid = waitpid(savepid, &status, 0);
if (pid < 1) {
- eerror ("waitpid %d: %s", savepid, strerror (errno));
- return (-1);
+ eerror("waitpid %d: %s", savepid, strerror(errno));
+ return -1;
}
- } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
+ } while (! WIFEXITED(status) && ! WIFSIGNALED(status));
- if (! WIFEXITED (status) || WEXITSTATUS (status) != 0) {
+ if (! WIFEXITED(status) || WEXITSTATUS(status) != 0) {
if (! quiet)
- eerrorx ("%s: failed to start `%s'", applet, exec);
- exit (EXIT_FAILURE);
+ eerrorx("%s: failed to start `%s'", applet, exec);
+ exit(EXIT_FAILURE);
}
pid = savepid;
@@ -1081,12 +1071,12 @@ int start_stop_daemon (int argc, char **argv)
ts.tv_nsec = POLL_INTERVAL;
while (nloops) {
- if (nanosleep (&ts, NULL) == -1) {
+ if (nanosleep(&ts, NULL) == -1) {
if (errno == EINTR)
- eerror ("%s: caught an interrupt", applet);
+ eerror("%s: caught an interrupt", applet);
else {
- eerror ("%s: nanosleep: %s", applet, strerror (errno));
- return (0);
+ eerror("%s: nanosleep: %s", applet, strerror(errno));
+ return 0;
}
}
@@ -1111,27 +1101,28 @@ int start_stop_daemon (int argc, char **argv)
} else {
if (pidfile) {
/* The pidfile may not have been written yet - give it some time */
- if (get_pid (pidfile, true) == -1) {
+ if (get_pid(pidfile, true) == -1) {
if (! nloopsp)
- eerrorx ("%s: did not create a valid pid in `%s'",
- applet, pidfile);
+ eerrorx("%s: did not create a valid pid in `%s'",
+ applet, pidfile);
alive = true;
} else
nloopsp = 0;
}
- if (do_stop ((const char *const *)argv, cmd,
- pidfile, uid, 0, true, false, true) > 0)
+ if (do_stop((const char *const *)argv, cmd,
+ pidfile, uid, 0, true, false, true) > 0)
alive = true;
}
if (! alive)
- eerrorx ("%s: %s died", applet, exec);
+ eerrorx("%s: %s died", applet, exec);
}
}
if (svcname)
- rc_service_daemon_set (svcname, (const char *const *)argv, cmd, pidfile, true);
+ rc_service_daemon_set(svcname, (const char *const *)argv,
+ cmd, pidfile, true);
- exit (EXIT_SUCCESS);
+ exit(EXIT_SUCCESS);
/* NOTREACHED */
}