--- busybox-1.10.1/debianutils/start_stop_daemon.c Sat Apr 19 05:50:30 2008 +++ busybox-1.10.1-ssd/debianutils/start_stop_daemon.c Tue Apr 22 03:13:13 2008 @@ -11,7 +11,6 @@ /* NB: we have a problem here with /proc/NN/exe usage, similar to * one fixed in killall/pidof */ -#include #include /* Override ENABLE_FEATURE_PIDFILE */ @@ -33,6 +32,7 @@ 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 @@ #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 @@ } 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 @@ 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; + char buf[256]; /* is it big enough? */ + char *p, *pe; - 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; + 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 @@ 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 @@ 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 @@ }; 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 @@ // if (retry_arg) // retries = xatoi_u(retry_arg); // ) - argc -= optind; + //argc -= optind; argv += optind; if (userspec) { @@ -301,13 +300,15 @@ 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)