diff options
Diffstat (limited to 'toys/pending/pgrep.c')
-rw-r--r-- | toys/pending/pgrep.c | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/toys/pending/pgrep.c b/toys/pending/pgrep.c new file mode 100644 index 00000000..90fee089 --- /dev/null +++ b/toys/pending/pgrep.c @@ -0,0 +1,164 @@ +/* pgrep.c - pgrep and pkill implementation + * + * Copyright 2012 Madhur Verma <mad.flexi@gmail.com> + * + +USE_PGREP(NEWTOY(pgrep, "?P# s# xvonlf[!sP]", TOYFLAG_USR|TOYFLAG_BIN)) +USE_PGREP(OLDTOY(pkill, pgrep, "?P# s# xvonlf[!sP]", TOYFLAG_USR|TOYFLAG_BIN)) + +config PGREP + bool "pgrep" + default n + help + usage: pgrep [-flnovx] [-s SID|-P PPID|PATTERN] + pkill [-l|-SIGNAL] [-fnovx] [-s SID|-P PPID|PATTERN] + + -l Show command name too / List all signals + -f Match against entire command line + -n Show/Signal the newest process only + -o Show/Signal the oldest process only + -v Negate the match + -x Match whole name (not substring) + -s Match session ID (0 for current) + -P Match parent process ID +*/ + +#define FOR_pgrep +#include "toys.h" +#include <regex.h> + +#define flag_get(f,v,d) ((toys.optflags & f) ? v : d) +#define flag_chk(f) ((toys.optflags & f) ? 1 : 0) + +GLOBALS( + long sid; //-s + long ppid; //-P + char *signame; +) + +static int exec_action(unsigned pid, char *name, int signal) +{ + if (toys.which->name[1] == 'g') { + printf("%d", pid); + if (flag_chk(FLAG_l)) printf(" %s", name); + printf("\n"); + } else { + kill(pid, signal); + } + return 0; +} + +static int regex_match(regex_t *rp, char *tar, char *patt) +{ + regmatch_t rm[1]; + int len = strlen(tar); + if (regexec(rp, tar, 1, rm, 0) == 0) { + if (flag_chk(FLAG_x)) { + if ((rm[0].rm_so == 0) && ((rm[0].rm_eo - rm[0].rm_so) == len)) return 1; + } else return 1; + } + return 0; +} + +void pgrep_main(void) +{ + int signum=0, eval=0, ret=1; + DIR *dp=NULL; + struct dirent *entry=NULL; + regex_t rp; + unsigned pid=0, ppid=0, sid=0, latest_pid=0; + char *cmdline=NULL, *latest_cmdline = NULL; + pid_t self = getpid(); + + if (!(dp = opendir("/proc"))) perror_exit("OPENDIR: failed to open /proc"); + setlinebuf(stdout); + + if (toys.which->name[1] == 'k') { + if (flag_chk(FLAG_l)) { + sig_to_num(NULL); + return; + } + if (!TT.signame && *toys.optargs && **toys.optargs == '-') { + TT.signame = *(toys.optargs++) + 1; + } + if (TT.signame) { + char *arg; + int i = strtol(TT.signame, &arg, 10); + if (!*arg) arg = num_to_sig(i); + else arg = TT.signame; + if (!arg || (signum = sig_to_num(arg)) == -1) + error_exit("Unknown signal '%s'", arg); + } else signum = SIGTERM; + } + if (!(flag_chk(FLAG_s) || flag_chk(FLAG_P)) && !*toys.optargs) { + toys.exithelp++; + error_exit("missing argument"); + } + if (*(toys.optargs+1) && !(flag_chk(FLAG_s) || flag_chk(FLAG_P))) { + toys.exithelp++; + error_exit("max argument > 1"); + } + if (*toys.optargs) { /* compile regular expression(PATTERN) */ + if ((eval = regcomp(&rp, *toys.optargs, REG_EXTENDED | REG_NOSUB)) != 0) { + char errbuf[256]; + (void) regerror(eval, &rp, errbuf, sizeof(errbuf)); + error_exit("%s", errbuf); + } + } + if (flag_chk(FLAG_s)&&(TT.sid==0)) TT.sid = getsid(0); + while ((entry = readdir(dp))) { + int fd = -1, n = 0; + if (!isdigit(*entry->d_name)) continue; + + pid = strtol(entry->d_name, NULL, 10); + if (pid == self) continue; + + snprintf(toybuf, sizeof(toybuf), "/proc/%s/cmdline", entry->d_name); + if ((fd = open(toybuf, O_RDONLY)) == -1) goto cmdline_fail; + n = read(fd, toybuf, sizeof(toybuf)); + close(fd); + toybuf[n--] = '\0'; + if (n < 0) { +cmdline_fail: + snprintf(toybuf, sizeof(toybuf), "/proc/%s/comm", entry->d_name); + if ((fd = open(toybuf, O_RDONLY)) == -1) continue; + n = read(fd, toybuf, sizeof(toybuf)); + close(fd); + toybuf[--n] = '\0'; + if (n < 1) continue; + } + if (flag_chk(FLAG_f)) { + while (--n) + if (toybuf[n] < ' ') toybuf[n] = ' '; + } + if (cmdline) free(cmdline); + cmdline = xstrdup(toybuf); + if (flag_chk(FLAG_s) || flag_chk(FLAG_P)) { + snprintf(toybuf, sizeof(toybuf), "/proc/%s/stat", entry->d_name); + if ((fd = open(toybuf, O_RDONLY)) == -1) continue; + n = read(fd, toybuf, sizeof(toybuf)); + close(fd); + if (n<1) continue; + n = sscanf(toybuf, "%*u %*s %*c %u %*u %u", &ppid, &sid); + if (flag_chk(FLAG_s)) if (sid != TT.sid) continue; + if (flag_chk(FLAG_P)) if (ppid != TT.ppid) continue; + } + if (!*toys.optargs || (regex_match(&rp, cmdline, *toys.optargs)^flag_chk(FLAG_v))) { + if (flag_chk(FLAG_n)) { + if (latest_cmdline) free(latest_cmdline); + latest_cmdline = xstrdup(cmdline); + latest_pid = pid; + } else exec_action(pid, cmdline, signum); + ret = 0; + if (flag_chk(FLAG_o)) break; + } + } + if (cmdline) free(cmdline); + if (latest_cmdline) { + exec_action(latest_pid, latest_cmdline, signum); + free(latest_cmdline); + } + if (*toys.optargs) regfree(&rp); + closedir(dp); + toys.exitval = ret; +} |