| pidof.c - ubase - suckless linux base utils | |
| git clone git://git.suckless.org/ubase | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| pidof.c (2017B) | |
| --- | |
| 1 /* See LICENSE file for copyright and license details. */ | |
| 2 #include <sys/types.h> | |
| 3 | |
| 4 #include <dirent.h> | |
| 5 #include <libgen.h> | |
| 6 #include <limits.h> | |
| 7 #include <stdio.h> | |
| 8 #include <stdlib.h> | |
| 9 #include <string.h> | |
| 10 #include <unistd.h> | |
| 11 | |
| 12 #include "proc.h" | |
| 13 #include "queue.h" | |
| 14 #include "util.h" | |
| 15 | |
| 16 struct pidentry { | |
| 17 pid_t pid; | |
| 18 SLIST_ENTRY(pidentry) entry; | |
| 19 }; | |
| 20 | |
| 21 static SLIST_HEAD(, pidentry) omitpid_head; | |
| 22 | |
| 23 static void | |
| 24 usage(void) | |
| 25 { | |
| 26 eprintf("usage: %s [-o pid1,pid2,...pidN] [-s] [program...]\n", … | |
| 27 } | |
| 28 | |
| 29 int | |
| 30 main(int argc, char *argv[]) | |
| 31 { | |
| 32 DIR *dp; | |
| 33 struct dirent *entry; | |
| 34 pid_t pid; | |
| 35 struct procstat ps; | |
| 36 char cmdline[BUFSIZ], *cmd, *cmdbase = NULL, *p, *arg = NULL; | |
| 37 int i, found = 0; | |
| 38 int sflag = 0, oflag = 0; | |
| 39 struct pidentry *pe; | |
| 40 | |
| 41 ARGBEGIN { | |
| 42 case 's': | |
| 43 sflag = 1; | |
| 44 break; | |
| 45 case 'o': | |
| 46 oflag = 1; | |
| 47 arg = EARGF(usage()); | |
| 48 break; | |
| 49 default: | |
| 50 usage(); | |
| 51 } ARGEND; | |
| 52 | |
| 53 if (!argc) | |
| 54 return 1; | |
| 55 | |
| 56 SLIST_INIT(&omitpid_head); | |
| 57 | |
| 58 for (p = strtok(arg, ","); p; p = strtok(NULL, ",")) { | |
| 59 pe = emalloc(sizeof(*pe)); | |
| 60 if (strcmp(p, "%PPID") == 0) | |
| 61 pe->pid = getppid(); | |
| 62 else | |
| 63 pe->pid = estrtol(p, 10); | |
| 64 SLIST_INSERT_HEAD(&omitpid_head, pe, entry); | |
| 65 } | |
| 66 | |
| 67 if (!(dp = opendir("/proc"))) | |
| 68 eprintf("opendir /proc:"); | |
| 69 | |
| 70 while ((entry = readdir(dp))) { | |
| 71 if (!pidfile(entry->d_name)) | |
| 72 continue; | |
| 73 pid = estrtol(entry->d_name, 10); | |
| 74 if (oflag) { | |
| 75 SLIST_FOREACH(pe, &omitpid_head, entry) | |
| 76 if (pe->pid == pid) | |
| 77 break; | |
| 78 if (pe) | |
| 79 continue; | |
| 80 } | |
| 81 if (parsestat(pid, &ps) < 0) | |
| 82 continue; | |
| 83 if (parsecmdline(ps.pid, cmdline, | |
| 84 sizeof(cmdline)) < 0) { | |
| 85 cmd = ps.comm; | |
| 86 cmdbase = cmd; | |
| 87 } else { | |
| 88 if ((p = strchr(cmdline, ' '))) | |
| 89 *p = '\0'; | |
| 90 cmd = cmdline; | |
| 91 cmdbase = basename(cmdline); | |
| 92 } | |
| 93 /* Workaround for login shells */ | |
| 94 if (cmd[0] == '-') | |
| 95 cmd++; | |
| 96 for (i = 0; i < argc; i++) { | |
| 97 if (strcmp(cmd, argv[i]) == 0 || | |
| 98 strcmp(cmdbase, argv[i]) == 0) { | |
| 99 putword(entry->d_name); | |
| 100 found++; | |
| 101 if (sflag) | |
| 102 goto out; | |
| 103 } | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 out: | |
| 108 if (found) | |
| 109 putchar('\n'); | |
| 110 | |
| 111 closedir(dp); | |
| 112 | |
| 113 return 0; | |
| 114 } |