pidof.c (2054B)
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", argv0); 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 if (oflag) { 59 for (p = strtok(arg, ","); p; p = strtok(NULL, ",")) { 60 pe = emalloc(sizeof(*pe)); 61 if (strcmp(p, "%PPID") == 0) 62 pe->pid = getppid(); 63 else 64 pe->pid = estrtol(p, 10); 65 SLIST_INSERT_HEAD(&omitpid_head, pe, entry); 66 } 67 } 68 69 if (!(dp = opendir("/proc"))) 70 eprintf("opendir /proc:"); 71 72 while ((entry = readdir(dp))) { 73 if (!pidfile(entry->d_name)) 74 continue; 75 pid = estrtol(entry->d_name, 10); 76 if (oflag) { 77 SLIST_FOREACH(pe, &omitpid_head, entry) 78 if (pe->pid == pid) 79 break; 80 if (pe) 81 continue; 82 } 83 if (parsestat(pid, &ps) < 0) 84 continue; 85 if (parsecmdline(ps.pid, cmdline, 86 sizeof(cmdline)) < 0) { 87 cmd = ps.comm; 88 cmdbase = cmd; 89 } else { 90 if ((p = strchr(cmdline, ' '))) 91 *p = '\0'; 92 cmd = cmdline; 93 cmdbase = basename(cmdline); 94 } 95 /* Workaround for login shells */ 96 if (cmd[0] == '-') 97 cmd++; 98 for (i = 0; i < argc; i++) { 99 if (strcmp(cmd, argv[i]) == 0 || 100 strcmp(cmdbase, argv[i]) == 0) { 101 putword(entry->d_name); 102 found++; 103 if (sflag) 104 goto out; 105 } 106 } 107 } 108 109 out: 110 if (found) 111 putchar('\n'); 112 113 closedir(dp); 114 115 return found ? 0 : 1; 116 }