killall.c revision 4696bfc4057e87ea8a66bd64aafb9ca14a64290e
1/* vi: set sw=4 ts=4:
2 *
3 * killall.c - Send signal (default: TERM) to all processes with given names.
4 *
5 * Copyright 2012 Andreas Heck <aheck@gmx.de>
6 *
7 * Not in SUSv4.
8
9USE_KILLALL(NEWTOY(killall, "<1?lq", TOYFLAG_USR|TOYFLAG_BIN))
10
11config KILLALL
12	bool "killall"
13	default y
14	help
15	  usage: killall [-l] [-q] [-SIG] PROCESS_NAME...
16
17	  Send a signal (default: TERM) to all processes with the given names.
18
19		-l	print list of all available signals
20		-q	don't print any warnings or error messages
21*/
22
23#include "toys.h"
24
25#define FLAG_q	1
26#define FLAG_l	2
27
28DEFINE_GLOBALS(
29	int signum;
30)
31#define TT this.killall
32
33struct signame {
34	int num;
35	char *name;
36};
37
38// Signals required by POSIX 2008:
39// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html
40
41#define SIGNIFY(x) {SIG##x, #x}
42
43static struct signame signames[] = {
44	SIGNIFY(ABRT), SIGNIFY(ALRM), SIGNIFY(BUS), SIGNIFY(CHLD), SIGNIFY(CONT),
45	SIGNIFY(FPE), SIGNIFY(HUP), SIGNIFY(ILL), SIGNIFY(INT), SIGNIFY(KILL),
46	SIGNIFY(PIPE), SIGNIFY(QUIT), SIGNIFY(SEGV), SIGNIFY(STOP), SIGNIFY(TERM),
47	SIGNIFY(TSTP), SIGNIFY(TTIN), SIGNIFY(TTOU), SIGNIFY(USR1), SIGNIFY(USR2),
48	SIGNIFY(SYS), SIGNIFY(TRAP), SIGNIFY(URG), SIGNIFY(VTALRM), SIGNIFY(XCPU),
49	SIGNIFY(XFSZ)
50};
51
52// SIGNIFY(STKFLT), SIGNIFY(WINCH), SIGNIFY(IO), SIGNIFY(PWR)
53
54// Convert name to signal number.  If name == NULL print names.
55static int sig_to_num(char *pidstr)
56{
57	int i;
58
59	if (pidstr) {
60		if (isdigit(*pidstr)) return atol(pidstr);
61		if (!strncasecmp(pidstr, "sig", 3)) pidstr+=3;
62	}
63	for (i = 0; i < sizeof(signames)/sizeof(struct signame); i++)
64		if (!pidstr) xputs(signames[i].name);
65		else if (!strcasecmp(pidstr, signames[i].name))
66			return signames[i].num;
67
68	return -1;
69}
70
71static void kill_process(pid_t pid)
72{
73	int ret;
74
75	toys.exitval = 0;
76	ret = kill(pid, TT.signum);
77
78	if (ret == -1 && !(toys.optflags & FLAG_q)) perror("kill");
79}
80
81void killall_main(void)
82{
83	char **names;
84
85	if (toys.optflags & FLAG_l) {
86		sig_to_num(NULL);
87		return;
88	}
89
90	TT.signum = SIGTERM;
91	toys.exitval++;
92
93	if (!*toys.optargs) {
94		toys.exithelp = 1;
95		error_exit("Process name missing!");
96	}
97
98	names = toys.optargs;
99
100	if (**names == '-') {
101		if (0 > (TT.signum = sig_to_num((*names)+1))) {
102			if (toys.optflags & FLAG_q) exit(1);
103			error_exit("Invalid signal");
104		}
105		names++;
106
107		if (!*names) {
108			toys.exithelp++;
109			error_exit("Process name missing!");
110		}
111	}
112
113	for_each_pid_with_name_in(names, kill_process);
114
115	if (toys.exitval && !(toys.optflags & FLAG_q))
116		error_exit("No such process");
117}
118