xref: /third_party/toybox/toys/lsb/killall.c (revision 0f66f451)
1/* killall.c - Send signal (default: TERM) to all processes with given names.
2 *
3 * Copyright 2012 Andreas Heck <aheck@gmx.de>
4 *
5 * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/killall.html
6
7USE_KILLALL(NEWTOY(killall, "?s:ilqvw", TOYFLAG_USR|TOYFLAG_BIN))
8
9config KILLALL
10  bool "killall"
11  default y
12  help
13    usage: killall [-l] [-iqv] [-SIGNAL|-s SIGNAL] PROCESS_NAME...
14
15    Send a signal (default: TERM) to all processes with the given names.
16
17    -i	Ask for confirmation before killing
18    -l	Print list of all available signals
19    -q	Don't print any warnings or error messages
20    -s	Send SIGNAL instead of SIGTERM
21    -v	Report if the signal was successfully sent
22    -w	Wait until all signaled processes are dead
23*/
24
25#define FOR_killall
26#include "toys.h"
27
28GLOBALS(
29  char *s;
30
31  int signum;
32  pid_t cur_pid;
33  char **names;
34  short *err;
35  struct int_list { struct int_list *next; int val; } *pids;
36)
37
38static int kill_process(pid_t pid, char *name)
39{
40  int offset = 0;
41
42  if (pid == TT.cur_pid) return 0;
43
44  if (FLAG(i)) {
45    fprintf(stderr, "Signal %s(%d)", name, (int)pid);
46    if (!yesno(0)) return 0;
47  }
48
49  errno = 0;
50  kill(pid, TT.signum);
51  if (FLAG(w)) {
52    struct int_list *new = xmalloc(sizeof(*TT.pids));
53    new->val = pid;
54    new->next = TT.pids;
55    TT.pids = new;
56  }
57  for (;;) {
58    if (TT.names[offset] == name) {
59      TT.err[offset] = errno;
60      break;
61    } else offset++;
62  }
63  if (errno) {
64    if (!FLAG(q)) perror_msg("pid %d", (int)pid);
65  } else if (FLAG(v))
66    printf("Killed %s(%d) with signal %d\n", name, pid, TT.signum);
67
68  return 0;
69}
70
71void killall_main(void)
72{
73  int i;
74
75  TT.names = toys.optargs;
76  TT.signum = SIGTERM;
77
78  if (FLAG(l)) {
79    list_signals();
80    return;
81  }
82
83  if (TT.s || (*TT.names && **TT.names == '-')) {
84    if (0 > (TT.signum = sig_to_num(TT.s ? TT.s : (*TT.names)+1))) {
85      if (FLAG(q)) exit(1);
86      error_exit("Invalid signal");
87    }
88    if (!TT.s) {
89      TT.names++;
90      toys.optc--;
91    }
92  }
93
94  if (!toys.optc) help_exit("no name");
95
96  TT.cur_pid = getpid();
97
98  TT.err = xmalloc(2*toys.optc);
99  for (i=0; i<toys.optc; i++) TT.err[i] = ESRCH;
100  names_to_pid(TT.names, kill_process, 1);
101  for (i=0; i<toys.optc; i++) {
102    if (TT.err[i]) {
103      toys.exitval = 1;
104      errno = TT.err[i];
105      perror_msg_raw(TT.names[i]);
106    }
107  }
108  if (FLAG(w)) {
109    for (;;) {
110      struct int_list *p = TT.pids;
111      int c = 0;
112
113      for (; p; p=p->next) if (kill(p->val, 0) != -1 || errno != ESRCH) ++c;
114      if (!c) break;
115      sleep(1);
116    }
117  }
118  if (CFG_TOYBOX_FREE) {
119    free(TT.err);
120    llist_traverse(TT.pids, free);
121  }
122}
123