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