toybox/toys/lsb/killall.c
<<
>>
Prefs
   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