aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Hubbs <w.d.hubbs@gmail.com>2017-08-24 11:34:18 -0500
committerWilliam Hubbs <w.d.hubbs@gmail.com>2017-08-24 11:34:18 -0500
commitd7938f54f29193251e083ad35a7d464949829096 (patch)
tree91d82fb509a0f731578927a494c47e3358eb296a
parentcfbe9c2ede24dac530ef58e5c35bd57f22a788a3 (diff)
start-stop-daemon: move --retry processing code to a shared module
This was part of start-stop-daemon; however, it needs to be shared in order to be used by supervise-daemon.
-rw-r--r--src/rc/Makefile2
-rw-r--r--src/rc/rc-schedules.c425
-rw-r--r--src/rc/rc-schedules.h27
-rw-r--r--src/rc/start-stop-daemon.c402
4 files changed, 461 insertions, 395 deletions
diff --git a/src/rc/Makefile b/src/rc/Makefile
index 19adcafb..e6c9f4a2 100644
--- a/src/rc/Makefile
+++ b/src/rc/Makefile
@@ -156,7 +156,7 @@ rc-service service: rc-service.o _usage.o rc-misc.o
rc-update: rc-update.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
-start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o
+start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-schedules.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o
diff --git a/src/rc/rc-schedules.c b/src/rc/rc-schedules.c
new file mode 100644
index 00000000..0390ef9c
--- /dev/null
+++ b/src/rc/rc-schedules.c
@@ -0,0 +1,425 @@
+/*
+ * The functions in this file control the stopping of daemons by
+ * start-stop-daemon and supervise-daemon.
+ */
+
+/*
+ * Copyright (c) 2015 The OpenRC Authors.
+ * See the Authors file at the top-level directory of this distribution and
+ * https://github.com/OpenRC/openrc/blob/master/AUTHORS
+ *
+ * This file is part of OpenRC. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+/* nano seconds */
+#define POLL_INTERVAL 20000000
+#define WAIT_PIDFILE 500000000
+#define ONE_SECOND 1000000000
+#define ONE_MS 1000000
+
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "einfo.h"
+#include "queue.h"
+#include "rc.h"
+#include "rc-misc.h"
+#include "rc-schedules.h"
+#include "helpers.h"
+
+typedef struct scheduleitem {
+ enum {
+ SC_TIMEOUT,
+ SC_SIGNAL,
+ SC_GOTO,
+ SC_FOREVER,
+ } type;
+ int value;
+ struct scheduleitem *gotoitem;
+ TAILQ_ENTRY(scheduleitem) entries;
+} SCHEDULEITEM;
+
+static TAILQ_HEAD(, scheduleitem) schedule;
+
+void initialize_schedulelist(void)
+{
+ TAILQ_INIT(&schedule);
+}
+
+void free_schedulelist(void)
+{
+ SCHEDULEITEM *s1 = TAILQ_FIRST(&schedule);
+ SCHEDULEITEM *s2;
+
+ while (s1) {
+ s2 = TAILQ_NEXT(s1, entries);
+ free(s1);
+ s1 = s2;
+ }
+ TAILQ_INIT(&schedule);
+}
+
+int parse_signal(const char *applet, const char *sig)
+{
+ typedef struct signalpair
+ {
+ const char *name;
+ int signal;
+ } SIGNALPAIR;
+
+#define signalpair_item(name) { #name, SIG##name },
+
+ static const SIGNALPAIR signallist[] = {
+ signalpair_item(HUP)
+ signalpair_item(INT)
+ signalpair_item(QUIT)
+ signalpair_item(ILL)
+ signalpair_item(TRAP)
+ signalpair_item(ABRT)
+ signalpair_item(BUS)
+ signalpair_item(FPE)
+ signalpair_item(KILL)
+ signalpair_item(USR1)
+ signalpair_item(SEGV)
+ signalpair_item(USR2)
+ signalpair_item(PIPE)
+ signalpair_item(ALRM)
+ signalpair_item(TERM)
+ signalpair_item(CHLD)
+ signalpair_item(CONT)
+ signalpair_item(STOP)
+ signalpair_item(TSTP)
+ signalpair_item(TTIN)
+ signalpair_item(TTOU)
+ signalpair_item(URG)
+ signalpair_item(XCPU)
+ signalpair_item(XFSZ)
+ signalpair_item(VTALRM)
+ signalpair_item(PROF)
+#ifdef SIGWINCH
+ signalpair_item(WINCH)
+#endif
+#ifdef SIGIO
+ signalpair_item(IO)
+#endif
+#ifdef SIGPWR
+ signalpair_item(PWR)
+#endif
+ signalpair_item(SYS)
+ { "NULL", 0 },
+ };
+
+ unsigned int i = 0;
+ const char *s;
+
+ if (!sig || *sig == '\0')
+ return -1;
+
+ if (sscanf(sig, "%u", &i) == 1) {
+ if (i < NSIG)
+ return i;
+ eerrorx("%s: `%s' is not a valid signal", applet, sig);
+ }
+
+ if (strncmp(sig, "SIG", 3) == 0)
+ s = sig + 3;
+ else
+ s = NULL;
+
+ for (i = 0; i < ARRAY_SIZE(signallist); ++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);
+ /* NOTREACHED */
+}
+
+static SCHEDULEITEM *parse_schedule_item(const char *applet, const char *string)
+{
+ const char *after_hyph;
+ int sig;
+ SCHEDULEITEM *item = xmalloc(sizeof(*item));
+
+ item->value = 0;
+ item->gotoitem = NULL;
+ if (strcmp(string,"forever") == 0)
+ item->type = SC_FOREVER;
+ else if (isdigit((unsigned char)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);
+ } else if ((after_hyph = string + (string[0] == '-')) &&
+ ((sig = parse_signal(applet, after_hyph)) != -1))
+ {
+ item->type = SC_SIGNAL;
+ item->value = (int)sig;
+ } else
+ eerrorx("%s: invalid schedule item `%s'", applet, string);
+
+ return item;
+}
+
+void parse_schedule(const char *applet, const char *string, int timeout)
+{
+ char buffer[20];
+ const char *slash;
+ int count = 0;
+ SCHEDULEITEM *repeatat = NULL;
+ size_t len;
+ SCHEDULEITEM *item;
+
+ if (string)
+ for (slash = string; *slash; slash++)
+ if (*slash == '/')
+ count++;
+
+ free_schedulelist();
+
+ if (count == 0) {
+ item = xmalloc(sizeof(*item));
+ item->type = SC_SIGNAL;
+ item->value = timeout;
+ item->gotoitem = NULL;
+ TAILQ_INSERT_TAIL(&schedule, item, entries);
+
+ item = xmalloc(sizeof(*item));
+ item->type = SC_TIMEOUT;
+ item->gotoitem = NULL;
+ TAILQ_INSERT_TAIL(&schedule, item, entries);
+ if (string) {
+ if (sscanf(string, "%d", &item->value) != 1)
+ eerrorx("%s: invalid timeout in schedule",
+ applet);
+ } else
+ item->value = 5;
+
+ return;
+ }
+
+ while (string != NULL) {
+ if ((slash = strchr(string, '/')))
+ len = slash - string;
+ else
+ len = strlen(string);
+
+ if (len >= (ptrdiff_t)sizeof(buffer))
+ eerrorx("%s: invalid schedule item, far too long",
+ applet);
+
+ memcpy(buffer, string, len);
+ buffer[len] = 0;
+ string = slash ? slash + 1 : NULL;
+
+ item = parse_schedule_item(applet, buffer);
+ TAILQ_INSERT_TAIL(&schedule, item, entries);
+ if (item->type == SC_FOREVER) {
+ if (repeatat)
+ eerrorx("%s: invalid schedule, `forever' "
+ "appears more than once", applet);
+
+ repeatat = item;
+ continue;
+ }
+ }
+
+ if (repeatat) {
+ item = xmalloc(sizeof(*item));
+ item->type = SC_GOTO;
+ item->value = 0;
+ item->gotoitem = repeatat;
+ TAILQ_INSERT_TAIL(&schedule, item, entries);
+ }
+
+ return;
+}
+
+/* return number of processes killed, -1 on error */
+int do_stop(const char *applet, const char *exec, const char *const *argv,
+ pid_t pid, uid_t uid,int sig, bool test)
+{
+ RC_PIDLIST *pids;
+ RC_PID *pi;
+ RC_PID *np;
+ bool killed;
+ int nkilled = 0;
+
+ if (pid)
+ pids = rc_find_pids(NULL, NULL, 0, pid);
+ else
+ pids = rc_find_pids(exec, argv, uid, pid);
+
+ if (!pids)
+ return 0;
+
+ LIST_FOREACH_SAFE(pi, pids, entries, np) {
+ if (test) {
+ einfo("Would send signal %d to PID %d", sig, pi->pid);
+ nkilled++;
+ } else {
+ ebeginv("Sending signal %d to PID %d", sig, pi->pid);
+ errno = 0;
+ killed = (kill(pi->pid, sig) == 0 ||
+ errno == ESRCH ? true : false);
+ eendv(killed ? 0 : 1,
+ "%s: failed to send signal %d to PID %d: %s",
+ applet, sig, pi->pid, strerror(errno));
+ if (!killed) {
+ nkilled = -1;
+ } else {
+ if (nkilled != -1)
+ nkilled++;
+ }
+ }
+ free(pi);
+ }
+
+ free(pids);
+ return nkilled;
+}
+
+int run_stop_schedule(const char *applet,
+ const char *exec, const char *const *argv,
+ const char *pidfile, uid_t uid,
+ bool test, bool progress)
+{
+ SCHEDULEITEM *item = TAILQ_FIRST(&schedule);
+ int nkilled = 0;
+ int tkilled = 0;
+ int nrunning = 0;
+ long nloops, nsecs;
+ struct timespec ts;
+ pid_t pid = 0;
+ const char *const *p;
+ bool progressed = false;
+
+ if (exec)
+ einfov("Will stop %s", exec);
+ if (pidfile)
+ einfov("Will stop PID in pidfile `%s'", pidfile);
+ if (uid)
+ einfov("Will stop processes owned by UID %d", uid);
+ if (argv && *argv) {
+ einfovn("Will stop processes of `");
+ if (rc_yesno(getenv("EINFO_VERBOSE"))) {
+ for (p = argv; p && *p; p++) {
+ if (p != argv)
+ printf(" ");
+ printf("%s", *p);
+ }
+ printf("'\n");
+ }
+ }
+
+ if (pidfile) {
+ pid = get_pid(applet, pidfile);
+ if (pid == -1)
+ return 0;
+ }
+
+ while (item) {
+ switch (item->type) {
+ case SC_GOTO:
+ item = item->gotoitem;
+ continue;
+
+ case SC_SIGNAL:
+ nrunning = 0;
+ nkilled = do_stop(applet, exec, argv, pid, uid, item->value, test);
+ if (nkilled == 0) {
+ if (tkilled == 0) {
+ if (progressed)
+ printf("\n");
+ eerror("%s: no matching processes found", applet);
+ }
+ return tkilled;
+ }
+ else if (nkilled == -1)
+ return 0;
+
+ tkilled += nkilled;
+ break;
+ case SC_TIMEOUT:
+ if (item->value < 1) {
+ item = NULL;
+ break;
+ }
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = POLL_INTERVAL;
+
+ for (nsecs = 0; nsecs < item->value; nsecs++) {
+ for (nloops = 0;
+ nloops < ONE_SECOND / POLL_INTERVAL;
+ nloops++)
+ {
+ if ((nrunning = do_stop(applet, exec, argv,
+ pid, uid, 0, test)) == 0)
+ return 0;
+
+
+ if (nanosleep(&ts, NULL) == -1) {
+ if (progressed) {
+ printf("\n");
+ progressed = false;
+ }
+ if (errno == EINTR)
+ eerror("%s: caught an"
+ " interrupt", applet);
+ else {
+ eerror("%s: nanosleep: %s",
+ applet, strerror(errno));
+ return 0;
+ }
+ }
+ }
+ if (progress) {
+ printf(".");
+ fflush(stdout);
+ progressed = true;
+ }
+ }
+ break;
+ default:
+ if (progressed) {
+ printf("\n");
+ progressed = false;
+ }
+ eerror("%s: invalid schedule item `%d'",
+ applet, item->type);
+ return 0;
+ }
+
+ if (item)
+ item = TAILQ_NEXT(item, entries);
+ }
+
+ if (test || (tkilled > 0 && nrunning == 0))
+ return nkilled;
+
+ if (progressed)
+ printf("\n");
+ if (nrunning == 1)
+ eerror("%s: %d process refused to stop", applet, nrunning);
+ else
+ eerror("%s: %d process(es) refused to stop", applet, nrunning);
+
+ return -nrunning;
+}
diff --git a/src/rc/rc-schedules.h b/src/rc/rc-schedules.h
new file mode 100644
index 00000000..6bed7916
--- /dev/null
+++ b/src/rc/rc-schedules.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017 The OpenRC Authors.
+ * See the Authors file at the top-level directory of this distribution and
+ * https://github.com/OpenRC/openrc/blob/master/AUTHORS
+ *
+ * This file is part of OpenRC. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#ifndef __RC_SCHEDULES_H
+#define __RC_SCHEDULES_H
+
+void initialize_schedulelist(void);
+void free_schedulelist(void);
+int parse_signal(const char *applet, const char *sig);
+void parse_schedule(const char *applet, const char *string, int timeout);
+int do_stop(const char *applet, const char *exec, const char *const *argv,
+ pid_t pid, uid_t uid,int sig, bool test);
+int run_stop_schedule(const char *applet,
+ const char *exec, const char *const *argv,
+ const char *pidfile, uid_t uid,
+ bool test, bool progress);
+
+#endif
diff --git a/src/rc/start-stop-daemon.c b/src/rc/start-stop-daemon.c
index 451d4a5c..df5b3184 100644
--- a/src/rc/start-stop-daemon.c
+++ b/src/rc/start-stop-daemon.c
@@ -19,10 +19,6 @@
* except according to the terms contained in the LICENSE file.
*/
-/* nano seconds */
-#define POLL_INTERVAL 20000000
-#define WAIT_PIDFILE 500000000
-#define ONE_SECOND 1000000000
#define ONE_MS 1000000
#include <sys/types.h>
@@ -63,6 +59,7 @@ static struct pam_conv conv = { NULL, NULL};
#include "queue.h"
#include "rc.h"
#include "rc-misc.h"
+#include "rc-schedules.h"
#include "_usage.h"
#include "helpers.h"
@@ -130,20 +127,6 @@ const char * const longopts_help[] = {
};
const char *usagestring = NULL;
-typedef struct scheduleitem
-{
- enum
- {
- SC_TIMEOUT,
- SC_SIGNAL,
- SC_GOTO,
- SC_FOREVER
- } type;
- int value;
- struct scheduleitem *gotoitem;
- TAILQ_ENTRY(scheduleitem) entries;
-} SCHEDULEITEM;
-TAILQ_HEAD(, scheduleitem) schedule;
static char **nav;
static char *changeuser, *ch_root, *ch_dir;
@@ -167,20 +150,6 @@ static inline int ioprio_set(int which _unused,
#endif
static void
-free_schedulelist(void)
-{
- SCHEDULEITEM *s1 = TAILQ_FIRST(&schedule);
- SCHEDULEITEM *s2;
-
- while (s1) {
- s2 = TAILQ_NEXT(s1, entries);
- free(s1);
- s1 = s2;
- }
- TAILQ_INIT(&schedule);
-}
-
-static void
cleanup(void)
{
free(changeuser);
@@ -188,360 +157,6 @@ cleanup(void)
free_schedulelist();
}
-static int
-parse_signal(const char *sig)
-{
- typedef struct signalpair
- {
- const char *name;
- int signal;
- } SIGNALPAIR;
-
-#define signalpair_item(name) { #name, SIG##name },
-
- static const SIGNALPAIR signallist[] = {
- signalpair_item(HUP)
- signalpair_item(INT)
- signalpair_item(QUIT)
- signalpair_item(ILL)
- signalpair_item(TRAP)
- signalpair_item(ABRT)
- signalpair_item(BUS)
- signalpair_item(FPE)
- signalpair_item(KILL)
- signalpair_item(USR1)
- signalpair_item(SEGV)
- signalpair_item(USR2)
- signalpair_item(PIPE)
- signalpair_item(ALRM)
- signalpair_item(TERM)
- signalpair_item(CHLD)
- signalpair_item(CONT)
- signalpair_item(STOP)
- signalpair_item(TSTP)
- signalpair_item(TTIN)
- signalpair_item(TTOU)
- signalpair_item(URG)
- signalpair_item(XCPU)
- signalpair_item(XFSZ)
- signalpair_item(VTALRM)
- signalpair_item(PROF)
-#ifdef SIGWINCH
- signalpair_item(WINCH)
-#endif
-#ifdef SIGIO
- signalpair_item(IO)
-#endif
-#ifdef SIGPWR
- signalpair_item(PWR)
-#endif
- signalpair_item(SYS)
- { "NULL", 0 },
- };
-
- unsigned int i = 0;
- const char *s;
-
- if (!sig || *sig == '\0')
- return -1;
-
- if (sscanf(sig, "%u", &i) == 1) {
- if (i < NSIG)
- return i;
- eerrorx("%s: `%s' is not a valid signal", applet, sig);
- }
-
- if (strncmp(sig, "SIG", 3) == 0)
- s = sig + 3;
- else
- s = NULL;
-
- for (i = 0; i < ARRAY_SIZE(signallist); ++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);
- /* NOTREACHED */
-}
-
-static SCHEDULEITEM *
-parse_schedule_item(const char *string)
-{
- const char *after_hyph;
- int sig;
- SCHEDULEITEM *item = xmalloc(sizeof(*item));
-
- item->value = 0;
- item->gotoitem = NULL;
- if (strcmp(string,"forever") == 0)
- item->type = SC_FOREVER;
- else if (isdigit((unsigned char)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);
- } else if ((after_hyph = string + (string[0] == '-')) &&
- ((sig = parse_signal(after_hyph)) != -1))
- {
- item->type = SC_SIGNAL;
- item->value = (int)sig;
- } else
- eerrorx("%s: invalid schedule item `%s'", applet, string);
-
- return item;
-}
-
-static void
-parse_schedule(const char *string, int timeout)
-{
- char buffer[20];
- const char *slash;
- int count = 0;
- SCHEDULEITEM *repeatat = NULL;
- size_t len;
- SCHEDULEITEM *item;
-
- if (string)
- for (slash = string; *slash; slash++)
- if (*slash == '/')
- count++;
-
- free_schedulelist();
-
- if (count == 0) {
- item = xmalloc(sizeof(*item));
- item->type = SC_SIGNAL;
- item->value = timeout;
- item->gotoitem = NULL;
- TAILQ_INSERT_TAIL(&schedule, item, entries);
-
- item = xmalloc(sizeof(*item));
- item->type = SC_TIMEOUT;
- item->gotoitem = NULL;
- TAILQ_INSERT_TAIL(&schedule, item, entries);
- if (string) {
- if (sscanf(string, "%d", &item->value) != 1)
- eerrorx("%s: invalid timeout in schedule",
- applet);
- } else
- item->value = 5;
-
- return;
- }
-
- while (string != NULL) {
- if ((slash = strchr(string, '/')))
- len = slash - string;
- else
- len = strlen(string);
-
- if (len >= (ptrdiff_t)sizeof(buffer))
- eerrorx("%s: invalid schedule item, far too long",
- applet);
-
- memcpy(buffer, string, len);
- buffer[len] = 0;
- string = slash ? slash + 1 : NULL;
-
- item = parse_schedule_item(buffer);
- TAILQ_INSERT_TAIL(&schedule, item, entries);
- if (item->type == SC_FOREVER) {
- if (repeatat)
- eerrorx("%s: invalid schedule, `forever' "
- "appears more than once", applet);
-
- repeatat = item;
- continue;
- }
- }
-
- if (repeatat) {
- item = xmalloc(sizeof(*item));
- item->type = SC_GOTO;
- item->value = 0;
- item->gotoitem = repeatat;
- TAILQ_INSERT_TAIL(&schedule, item, entries);
- }
-
- return;
-}
-
-/* return number of processed killed, -1 on error */
-static int
-do_stop(const char *exec, const char *const *argv,
- pid_t pid, uid_t uid,int sig, bool test)
-{
- RC_PIDLIST *pids;
- RC_PID *pi;
- RC_PID *np;
- bool killed;
- int nkilled = 0;
-
- if (pid)
- pids = rc_find_pids(NULL, NULL, 0, pid);
- else
- pids = rc_find_pids(exec, argv, uid, pid);
-
- if (!pids)
- return 0;
-
- LIST_FOREACH_SAFE(pi, pids, entries, np) {
- if (test) {
- einfo("Would send signal %d to PID %d", sig, pi->pid);
- nkilled++;
- } else {
- ebeginv("Sending signal %d to PID %d", sig, pi->pid);
- errno = 0;
- killed = (kill(pi->pid, sig) == 0 ||
- errno == ESRCH ? true : false);
- eendv(killed ? 0 : 1,
- "%s: failed to send signal %d to PID %d: %s",
- applet, sig, pi->pid, strerror(errno));
- if (!killed) {
- nkilled = -1;
- } else {
- if (nkilled != -1)
- nkilled++;
- }
- }
- free(pi);
- }
-
- free(pids);
- return nkilled;
-}
-
-static int
-run_stop_schedule(const char *exec, const char *const *argv,
- const char *pidfile, uid_t uid,
- bool test, bool progress)
-{
- SCHEDULEITEM *item = TAILQ_FIRST(&schedule);
- int nkilled = 0;
- int tkilled = 0;
- int nrunning = 0;
- long nloops, nsecs;
- struct timespec ts;
- pid_t pid = 0;
- const char *const *p;
- bool progressed = false;
-
- if (exec)
- einfov("Will stop %s", exec);
- if (pidfile)
- einfov("Will stop PID in pidfile `%s'", pidfile);
- if (uid)
- einfov("Will stop processes owned by UID %d", uid);
- if (argv && *argv) {
- einfovn("Will stop processes of `");
- if (rc_yesno(getenv("EINFO_VERBOSE"))) {
- for (p = argv; p && *p; p++) {
- if (p != argv)
- printf(" ");
- printf("%s", *p);
- }
- printf("'\n");
- }
- }
-
- if (pidfile) {
- pid = get_pid(applet, pidfile);
- if (pid == -1)
- return 0;
- }
-
- while (item) {
- switch (item->type) {
- case SC_GOTO:
- item = item->gotoitem;
- continue;
-
- case SC_SIGNAL:
- nrunning = 0;
- nkilled = do_stop(exec, argv, pid, uid, item->value, test);
- if (nkilled == 0) {
- if (tkilled == 0) {
- if (progressed)
- printf("\n");
- eerror("%s: no matching processes found", applet);
- }
- return tkilled;
- }
- else if (nkilled == -1)
- return 0;
-
- tkilled += nkilled;
- break;
- case SC_TIMEOUT:
- if (item->value < 1) {
- item = NULL;
- break;
- }
-
- ts.tv_sec = 0;
- ts.tv_nsec = POLL_INTERVAL;
-
- for (nsecs = 0; nsecs < item->value; nsecs++) {
- for (nloops = 0;
- nloops < ONE_SECOND / POLL_INTERVAL;
- nloops++)
- {
- if ((nrunning = do_stop(exec, argv,
- pid, uid, 0, test)) == 0)
- return 0;
-
-
- if (nanosleep(&ts, NULL) == -1) {
- if (progressed) {
- printf("\n");
- progressed = false;
- }
- if (errno == EINTR)
- eerror("%s: caught an"
- " interrupt", applet);
- else {
- eerror("%s: nanosleep: %s",
- applet, strerror(errno));
- return 0;
- }
- }
- }
- if (progress) {
- printf(".");
- fflush(stdout);
- progressed = true;
- }
- }
- break;
- default:
- if (progressed) {
- printf("\n");
- progressed = false;
- }
- eerror("%s: invalid schedule item `%d'",
- applet, item->type);
- return 0;
- }
-
- if (item)
- item = TAILQ_NEXT(item, entries);
- }
-
- if (test || (tkilled > 0 && nrunning == 0))
- return nkilled;
-
- if (progressed)
- printf("\n");
- if (nrunning == 1)
- eerror("%s: %d process refused to stop", applet, nrunning);
- else
- eerror("%s: %d process(es) refused to stop", applet, nrunning);
-
- return -nrunning;
-}
-
static void
handle_signal(int sig)
{
@@ -682,7 +297,6 @@ int main(int argc, char **argv)
unsigned int start_wait = 0;
applet = basename_c(argv[0]);
- TAILQ_INIT(&schedule);
atexit(cleanup);
signal_setup(SIGINT, handle_signal);
@@ -851,7 +465,7 @@ int main(int argc, char **argv)
break;
case 's': /* --signal <signal> */
- sig = parse_signal(optarg);
+ sig = parse_signal(applet, optarg);
break;
case 't': /* --test */
@@ -1037,12 +651,12 @@ int main(int argc, char **argv)
if (!stop)
oknodo = true;
if (retry)
- parse_schedule(retry, sig);
+ parse_schedule(applet, retry, sig);
else if (test || oknodo)
- parse_schedule("0", sig);
+ parse_schedule(applet, "0", sig);
else
- parse_schedule(NULL, sig);
- i = run_stop_schedule(exec, (const char *const *)margv,
+ parse_schedule(applet, NULL, sig);
+ i = run_stop_schedule(applet, exec, (const char *const *)margv,
pidfile, uid, test, progress);
if (i < 0)
@@ -1069,7 +683,7 @@ int main(int argc, char **argv)
else
pid = 0;
- if (do_stop(exec, (const char * const *)margv, pid, uid,
+ if (do_stop(applet, exec, (const char * const *)margv, pid, uid,
0, test) > 0)
eerrorx("%s: %s is already running", applet, exec);
@@ -1349,7 +963,7 @@ int main(int argc, char **argv)
}
} else
pid = 0;
- if (do_stop(exec, (const char *const *)margv,
+ if (do_stop(applet, exec, (const char *const *)margv,
pid, uid, 0, test) > 0)
alive = true;
}