summaryrefslogtreecommitdiff
path: root/debianutils
diff options
context:
space:
mode:
Diffstat (limited to 'debianutils')
-rw-r--r--debianutils/start_stop_daemon.c91
1 files changed, 46 insertions, 45 deletions
diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c
index 6f4b6b2..4e816bd 100644
--- a/debianutils/start_stop_daemon.c
+++ b/debianutils/start_stop_daemon.c
@@ -11,7 +11,6 @@
/* NB: we have a problem here with /proc/NN/exe usage, similar to
* one fixed in killall/pidof */
-#include <getopt.h>
#include <sys/resource.h>
/* Override ENABLE_FEATURE_PIDFILE */
@@ -33,6 +32,7 @@ struct globals {
int user_id;
smallint quiet;
smallint signal_nr;
+ struct stat execstat;
};
#define G (*(struct globals*)&bb_common_bufsiz1)
#define found (G.found )
@@ -43,6 +43,7 @@ struct globals {
#define user_id (G.user_id )
#define quiet (G.quiet )
#define signal_nr (G.signal_nr )
+#define execstat (G.execstat )
#define INIT_G() \
do { \
user_id = -1; \
@@ -50,25 +51,21 @@ struct globals {
} while (0)
-static int pid_is_exec(pid_t pid, const char *name)
+static int pid_is_exec(pid_t pid)
{
+ struct stat st;
char buf[sizeof("/proc//exe") + sizeof(int)*3];
- char *execbuf;
- int n;
sprintf(buf, "/proc/%u/exe", pid);
- n = strlen(name) + 1;
- execbuf = xzalloc(n + 1);
- readlink(buf, execbuf, n);
- /* if readlink fails because link target is longer than strlen(name),
- * execbuf still contains "", and strcmp will return !0. */
- n = strcmp(execbuf, name);
- if (ENABLE_FEATURE_CLEAN_UP)
- free(execbuf);
- return !n; /* nonzero (true) if execbuf == name */
+ if (stat(buf, &st) < 0)
+ return 0;
+ if (st.st_dev == execstat.st_dev
+ && st.st_ino == execstat.st_ino)
+ return 1;
+ return 0;
}
-static int pid_is_user(int pid, int uid)
+static int pid_is_user(int pid)
{
struct stat sb;
char buf[sizeof("/proc/") + sizeof(int)*3];
@@ -76,42 +73,39 @@ static int pid_is_user(int pid, int uid)
sprintf(buf, "/proc/%u", pid);
if (stat(buf, &sb) != 0)
return 0;
- return (sb.st_uid == uid);
+ return (sb.st_uid == user_id);
}
-static int pid_is_cmd(pid_t pid, const char *name)
+static int pid_is_cmd(pid_t pid)
{
- char fname[sizeof("/proc//stat") + sizeof(int)*3];
- char *buf;
- int r = 0;
-
- sprintf(fname, "/proc/%u/stat", pid);
- buf = xmalloc_open_read_close(fname, NULL);
- if (buf) {
- char *p = strchr(buf, '(');
- if (p) {
- char *pe = strrchr(++p, ')');
- if (pe) {
- *pe = '\0';
- r = !strcmp(p, name);
- }
- }
- free(buf);
- }
- return r;
+ char buf[256]; /* is it big enough? */
+ char *p, *pe;
+
+ sprintf(buf, "/proc/%u/stat", pid);
+ if (open_read_close(buf, buf, sizeof(buf) - 1) < 0)
+ return 0;
+ buf[sizeof(buf) - 1] = '\0'; /* paranoia */
+ p = strchr(buf, '(');
+ if (!p)
+ return 0;
+ pe = strrchr(++p, ')');
+ if (!pe)
+ return 0;
+ *pe = '\0';
+ return !strcmp(p, cmdname);
}
static void check(int pid)
{
struct pid_list *p;
- if (execname && !pid_is_exec(pid, execname)) {
+ if (execname && !pid_is_exec(pid)) {
return;
}
- if (userspec && !pid_is_user(pid, user_id)) {
+ if (userspec && !pid_is_user(pid)) {
return;
}
- if (cmdname && !pid_is_cmd(pid, cmdname)) {
+ if (cmdname && !pid_is_cmd(pid)) {
return;
}
p = xmalloc(sizeof(*p));
@@ -148,9 +142,16 @@ static void do_procinit(void)
procdir = xopendir("/proc");
pid = 0;
- while ((entry = readdir(procdir)) != NULL) {
+ while(1) {
+ errno = 0; /* clear any previous error */
+ entry = readdir(procdir);
+// TODO: check for exact errno(s) which mean that we got stale entry
+ if (errno) /* Stale entry, process has died after opendir */
+ continue;
+ if (!entry) /* EOF, no more entries */
+ break;
pid = bb_strtou(entry->d_name, NULL, 10);
- if (errno)
+ if (errno) /* NaN */
continue;
check(pid);
}
@@ -165,8 +166,6 @@ static int do_stop(void)
struct pid_list *p;
int killed = 0;
- do_procinit();
-
if (cmdname) {
if (ENABLE_FEATURE_CLEAN_UP) what = xstrdup(cmdname);
if (!ENABLE_FEATURE_CLEAN_UP) what = cmdname;
@@ -251,7 +250,7 @@ enum {
};
int start_stop_daemon_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int start_stop_daemon_main(int argc, char **argv)
+int start_stop_daemon_main(int argc ATTRIBUTE_UNUSED, char **argv)
{
unsigned opt;
char *signame;
@@ -293,7 +292,7 @@ int start_stop_daemon_main(int argc, char **argv)
// if (retry_arg)
// retries = xatoi_u(retry_arg);
// )
- argc -= optind;
+ //argc -= optind;
argv += optind;
if (userspec) {
@@ -301,14 +300,16 @@ int start_stop_daemon_main(int argc, char **argv)
if (errno)
user_id = xuname2uid(userspec);
}
+ if (execname)
+ xstat(execname, &execstat);
+
+ do_procinit(); /* Both start and stop needs to know current processes */
if (opt & CTX_STOP) {
int i = do_stop();
return (opt & OPT_OKNODO) ? 0 : (i <= 0);
}
- do_procinit();
-
if (found) {
if (!quiet)
printf("%s already running\n%d\n", execname, found->pid);