pidof.c (2179B)
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 static void 17 usage(void) 18 { 19 eprintf("usage: %s [-o pid1,pid2,...pidN] [-s] [program...]\n", argv0); 20 } 21 22 struct pidentry { 23 pid_t pid; 24 TAILQ_ENTRY(pidentry) entry; 25 }; 26 27 static TAILQ_HEAD(omitpid_head, pidentry) omitpid_head; 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, *tmp; 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 TAILQ_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 TAILQ_INSERT_TAIL(&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 TAILQ_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 for (pe = TAILQ_FIRST(&omitpid_head); pe; pe = tmp) { 114 tmp = TAILQ_NEXT(pe, entry); 115 TAILQ_REMOVE(&omitpid_head, pe, entry); 116 free(pe); 117 } 118 119 return 0; 120 }