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 } |