killall5.c (2155B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <dirent.h> 3 #include <limits.h> 4 #include <signal.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <unistd.h> 9 10 #include "proc.h" 11 #include "queue.h" 12 #include "util.h" 13 14 struct { 15 const char *name; 16 int sig; 17 } sigs[] = { 18 #define SIG(n) { #n, SIG##n } 19 SIG(ABRT), SIG(ALRM), SIG(BUS), SIG(CHLD), SIG(CONT), SIG(FPE), SIG(HUP), 20 SIG(ILL), SIG(INT), SIG(KILL), SIG(PIPE), SIG(QUIT), SIG(SEGV), SIG(STOP), 21 SIG(TERM), SIG(TSTP), SIG(TTIN), SIG(TTOU), SIG(USR1), SIG(USR2), SIG(URG), 22 #undef SIG 23 }; 24 25 struct pidentry { 26 pid_t pid; 27 SLIST_ENTRY(pidentry) entry; 28 }; 29 30 static SLIST_HEAD(, pidentry) omitpid_head; 31 32 static void 33 usage(void) 34 { 35 eprintf("usage: %s [-o pid1,pid2,..,pidN] [-s signal]\n", argv0); 36 } 37 38 int 39 main(int argc, char *argv[]) 40 { 41 struct pidentry *pe; 42 struct dirent *entry; 43 DIR *dp; 44 char *p, *arg = NULL; 45 char *end, *v; 46 int oflag = 0; 47 int sig = SIGTERM; 48 pid_t pid; 49 size_t i; 50 51 ARGBEGIN { 52 case 's': 53 v = EARGF(usage()); 54 sig = strtol(v, &end, 0); 55 if (*end == '\0') 56 break; 57 for (i = 0; i < LEN(sigs); i++) { 58 if (strcasecmp(v, sigs[i].name) == 0) { 59 sig = sigs[i].sig; 60 break; 61 } 62 } 63 if (i == LEN(sigs)) 64 eprintf("%s: unknown signal\n", v); 65 break; 66 case 'o': 67 oflag = 1; 68 arg = EARGF(usage()); 69 break; 70 default: 71 usage(); 72 } ARGEND; 73 74 SLIST_INIT(&omitpid_head); 75 76 if (oflag) { 77 for (p = strtok(arg, ","); p; p = strtok(NULL, ",")) { 78 pe = emalloc(sizeof(*pe)); 79 pe->pid = estrtol(p, 10); 80 SLIST_INSERT_HEAD(&omitpid_head, pe, entry); 81 } 82 } 83 84 if (sig != SIGSTOP && sig != SIGCONT) 85 kill(-1, SIGSTOP); 86 87 if (!(dp = opendir("/proc"))) 88 eprintf("opendir /proc:"); 89 while ((entry = readdir(dp))) { 90 if (pidfile(entry->d_name) == 0) 91 continue; 92 pid = estrtol(entry->d_name, 10); 93 if (pid == 1 || pid == getpid() || 94 getsid(pid) == getsid(0) || getsid(pid) == 0) 95 continue; 96 if (oflag == 1) { 97 SLIST_FOREACH(pe, &omitpid_head, entry) 98 if (pe->pid == pid) 99 break; 100 if (pe) 101 continue; 102 } 103 kill(pid, sig); 104 } 105 closedir(dp); 106 107 if (sig != SIGSTOP && sig != SIGCONT) 108 kill(-1, SIGCONT); 109 110 return 0; 111 }