killall5.c (2295B)
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 static void 26 usage(void) 27 { 28 eprintf("usage: %s [-o pid1,pid2,..,pidN] [-s signal]\n", argv0); 29 } 30 31 struct pidentry { 32 pid_t pid; 33 TAILQ_ENTRY(pidentry) entry; 34 }; 35 36 static TAILQ_HEAD(omitpid_head, pidentry) omitpid_head; 37 38 int 39 main(int argc, char *argv[]) 40 { 41 struct pidentry *pe, *tmp; 42 int oflag = 0; 43 char *p, *arg = NULL; 44 DIR *dp; 45 struct dirent *entry; 46 char *end, *v; 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 TAILQ_INIT(&omitpid_head); 75 76 for (p = strtok(arg, ","); p; p = strtok(NULL, ",")) { 77 pe = emalloc(sizeof(*pe)); 78 pe->pid = estrtol(p, 10); 79 TAILQ_INSERT_TAIL(&omitpid_head, pe, entry); 80 } 81 82 if (sig != SIGSTOP && sig != SIGCONT) 83 kill(-1, SIGSTOP); 84 85 if (!(dp = opendir("/proc"))) 86 eprintf("opendir /proc:"); 87 while ((entry = readdir(dp))) { 88 if (pidfile(entry->d_name) == 0) 89 continue; 90 pid = estrtol(entry->d_name, 10); 91 if (pid == 1 || pid == getpid() || 92 getsid(pid) == getsid(0) || getsid(pid) == 0) 93 continue; 94 if (oflag == 1) { 95 TAILQ_FOREACH(pe, &omitpid_head, entry) 96 if (pe->pid == pid) 97 break; 98 if (pe) 99 continue; 100 } 101 kill(pid, sig); 102 } 103 closedir(dp); 104 105 if (sig != SIGSTOP && sig != SIGCONT) 106 kill(-1, SIGCONT); 107 108 for (pe = TAILQ_FIRST(&omitpid_head); pe; pe = tmp) { 109 tmp = TAILQ_NEXT(pe, entry); 110 TAILQ_REMOVE(&omitpid_head, pe, entry); 111 free(pe); 112 } 113 114 return 0; 115 }