diff options
author | Elliott Hughes <enh@google.com> | 2019-07-11 14:00:07 -0700 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2019-07-12 13:18:11 -0500 |
commit | a7b8b772dee4f159028e3b998454d7466fbbc88f (patch) | |
tree | f8cdf969a4a42ff39bad63e5d3a7aaf4844cb541 | |
parent | 5194d4ad66ad130cb730e0b192ba1e2b5181184d (diff) | |
download | toybox-a7b8b772dee4f159028e3b998454d7466fbbc88f.tar.gz |
pidof: fix default behavior, add -x.
Before this patch, we're effectively doing `pidof -x` all the time. This
patch changes names_to_pid() to allow us to say whether or not we want to
include scripts, and adjusts the callers appropriately.
Also add tests for `pidof` versus `pidof -x` which pass after this
patch, without regressing the existing killall tests.
-rw-r--r-- | lib/lib.c | 21 | ||||
-rw-r--r-- | lib/lib.h | 3 | ||||
-rw-r--r-- | tests/pidof.test | 33 | ||||
-rw-r--r-- | toys/lsb/killall.c | 2 | ||||
-rw-r--r-- | toys/lsb/pidof.c | 5 | ||||
-rw-r--r-- | toys/pending/bootchartd.c | 38 |
6 files changed, 63 insertions, 39 deletions
@@ -1041,7 +1041,8 @@ char *fileunderdir(char *file, char *dir) } // Execute a callback for each PID that matches a process name from a list. -void names_to_pid(char **names, int (*callback)(pid_t pid, char *name)) +void names_to_pid(char **names, int (*callback)(pid_t pid, char *name), + int scripts) { DIR *dp; struct dirent *entry; @@ -1050,18 +1051,20 @@ void names_to_pid(char **names, int (*callback)(pid_t pid, char *name)) while ((entry = readdir(dp))) { unsigned u = atoi(entry->d_name); - char *cmd = 0, *comm, **cur; + char *cmd = 0, *comm = 0, **cur; off_t len; if (!u) continue; // Comm is original name of executable (argv[0] could be #! interpreter) // but it's limited to 15 characters - sprintf(libbuf, "/proc/%u/comm", u); - len = sizeof(libbuf); - if (!(comm = readfileat(AT_FDCWD, libbuf, libbuf, &len)) || !len) - continue; - if (libbuf[len-1] == '\n') libbuf[--len] = 0; + if (scripts) { + sprintf(libbuf, "/proc/%u/comm", u); + len = sizeof(libbuf); + if (!(comm = readfileat(AT_FDCWD, libbuf, libbuf, &len)) || !len) + continue; + if (libbuf[len-1] == '\n') libbuf[--len] = 0; + } for (cur = names; *cur; cur++) { struct stat st1, st2; @@ -1071,7 +1074,7 @@ void names_to_pid(char **names, int (*callback)(pid_t pid, char *name)) // Fast path: only matching a filename (no path) that fits in comm. // `len` must be 14 or less because with a full 15 bytes we don't // know whether the name fit or was truncated. - if (len<=14 && bb==*cur && !strcmp(comm, bb)) goto match; + if (scripts && len<=14 && bb==*cur && !strcmp(comm, bb)) goto match; // If we have a path to existing file only match if same inode if (bb!=*cur && !stat(*cur, &st1)) { @@ -1093,7 +1096,7 @@ void names_to_pid(char **names, int (*callback)(pid_t pid, char *name)) cmd[len] = 0; } if (!strcmp(bb, getbasename(cmd))) goto match; - if (!strcmp(bb, getbasename(cmd+strlen(cmd)+1))) goto match; + if (scripts && !strcmp(bb, getbasename(cmd+strlen(cmd)+1))) goto match; continue; match: if (callback(u, *cur)) break; @@ -401,7 +401,8 @@ void mode_to_string(mode_t mode, char *buf); char *getdirname(char *name); char *getbasename(char *name); char *fileunderdir(char *file, char *dir); -void names_to_pid(char **names, int (*callback)(pid_t pid, char *name)); +void names_to_pid(char **names, int (*callback)(pid_t pid, char *name), + int scripts); pid_t __attribute__((returns_twice)) xvforkwrap(pid_t pid); #define XVFORK() xvforkwrap(vfork()) diff --git a/tests/pidof.test b/tests/pidof.test new file mode 100644 index 00000000..7de31fc2 --- /dev/null +++ b/tests/pidof.test @@ -0,0 +1,33 @@ +#!/bin/bash + +[ -f testing.sh ] && . testing.sh + +#testing "name" "command" "result" "infile" "stdin" + +# +# pidof (unlike killall) doesn't match argv[1] unless you supply -x. +# + +echo "#!$(which sh) +while true; do + sleep 0.1 +done" > toybox.pidof.test.script +chmod a+x toybox.pidof.test.script +cp toybox.pidof.test.script pidof.test + +./pidof.test & +pid=$! +testcmd "short argv[1]" "pidof.test" "" "" "" +testcmd "short argv[1] -x" "-x pidof.test" "$pid\n" "" "" +kill $pid + +./toybox.pidof.test.script & +pid=$! +testcmd "long argv[1]" "toybox.pidof.test.script" "" "" "" +testcmd "long argv[1] -x" "-x toybox.pidof.test.script" "$pid\n" "" "" +kill $pid + +rm -f toybox.pidof.test.script toybox.test + +# pidof (unlike killall) will match itself. +testcmd "pidof pidof" "pidof > /dev/null && echo found" "found\n" "" "" diff --git a/toys/lsb/killall.c b/toys/lsb/killall.c index 47aea23d..c81360b1 100644 --- a/toys/lsb/killall.c +++ b/toys/lsb/killall.c @@ -89,7 +89,7 @@ void killall_main(void) TT.err = xmalloc(2*toys.optc); for (i=0; i<toys.optc; i++) TT.err[i] = ESRCH; - names_to_pid(TT.names, kill_process); + names_to_pid(TT.names, kill_process, 1); for (i=0; i<toys.optc; i++) { if (TT.err[i]) { toys.exitval = 1; diff --git a/toys/lsb/pidof.c b/toys/lsb/pidof.c index 4f266b84..cd705a7c 100644 --- a/toys/lsb/pidof.c +++ b/toys/lsb/pidof.c @@ -5,7 +5,7 @@ * * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/pidof.html -USE_PIDOF(NEWTOY(pidof, "<1so:", TOYFLAG_BIN)) +USE_PIDOF(NEWTOY(pidof, "<1so:x", TOYFLAG_BIN)) config PIDOF bool "pidof" @@ -17,6 +17,7 @@ config PIDOF -s Single shot, only return one pid -o Omit PID(s) + -x Match shell scripts too */ #define FOR_pidof @@ -39,6 +40,6 @@ static int print_pid(pid_t pid, char *name) void pidof_main(void) { toys.exitval = 1; - names_to_pid(toys.optargs, print_pid); + names_to_pid(toys.optargs, print_pid, FLAG(x)); if (!toys.exitval) xputc('\n'); } diff --git a/toys/pending/bootchartd.c b/toys/pending/bootchartd.c index 7e5a136f..1fe6aff6 100644 --- a/toys/pending/bootchartd.c +++ b/toys/pending/bootchartd.c @@ -34,24 +34,9 @@ GLOBALS( int proc_accounting; int is_login; - void *head; + pid_t cur_pid; ) -struct pid_list { - struct pid_list *next, *prev; - int pid; -}; - -static int push_pids_in_list(pid_t pid, char *name) -{ - struct pid_list *new = xzalloc(sizeof(struct pid_list)); - - new->pid = pid; - dlist_add_nomalloc((void *)&TT.head, (void *)new); - - return 0; -} - static void dump_data_in_file(char *fname, int wfd) { int rfd = open(fname, O_RDONLY); @@ -253,13 +238,21 @@ static void stop_logging(char *tmp_dir, char *prog) } } +static int signal_pid(pid_t pid, char *name) +{ + if (pid != TT.cur_pid) kill(pid, SIGUSR1); + return 0; +} + void bootchartd_main() { - pid_t lgr_pid, self_pid = getpid(); + pid_t lgr_pid; int bchartd_opt = 0; // 0=PID1, 1=start, 2=stop, 3=init + + TT.cur_pid = getpid(); TT.smpl_period_usec = 200 * 1000; - TT.is_login = (self_pid == 1); + TT.is_login = (TT.cur_pid == 1); if (*toys.optargs) { if (!strcmp("start", *toys.optargs)) bchartd_opt = 1; else if (!strcmp("stop", *toys.optargs)) bchartd_opt = 2; @@ -267,16 +260,9 @@ void bootchartd_main() else error_exit("Unknown option '%s'", *toys.optargs); if (bchartd_opt == 2) { - struct pid_list *temp; char *process_name[] = {"bootchartd", NULL}; - names_to_pid(process_name, push_pids_in_list); - temp = TT.head; - if (temp) temp->prev->next = 0; - for (; temp; temp = temp->next) - if (temp->pid != self_pid) kill(temp->pid, SIGUSR1); - llist_traverse(TT.head, free); - + names_to_pid(process_name, signal_pid, 0); return; } } else if (!TT.is_login) error_exit("not PID 1"); |