aboutsummaryrefslogtreecommitdiff
path: root/toys/pending/pgrep.c
diff options
context:
space:
mode:
Diffstat (limited to 'toys/pending/pgrep.c')
-rw-r--r--toys/pending/pgrep.c164
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;
+}