toybox/toys/posix/kill.c
<<
>>
Prefs
   1/* kill.c - a program to send signals to processes
   2 *
   3 * Copyright 2012 Daniel Walter <d.walter@0x90.at>
   4 *
   5 * See http://opengroup.org/onlinepubs/9699919799/utilities/kill.html
   6 *
   7 * killall5.c - Send signal to all processes outside current session.
   8 *
   9 * Copyright 2014 Ranjan Kumar <ranjankumar.bth@gmail.com>
  10 * Copyright 2014 Kyungwan Han <asura321@gamil.com>
  11 *
  12 * No Standard
  13
  14USE_KILL(NEWTOY(kill, "?ls: ", TOYFLAG_BIN|TOYFLAG_MAYFORK))
  15USE_KILLALL5(NEWTOY(killall5, "?o*ls: [!lo][!ls]", TOYFLAG_SBIN))
  16
  17config KILL
  18  bool "kill"
  19  default y
  20  help
  21    usage: kill [-l [SIGNAL] | -s SIGNAL | -SIGNAL] PID...
  22
  23    Send signal to process(es).
  24
  25    -l  List signal name(s) and number(s)
  26    -s  Send SIGNAL (default SIGTERM)
  27
  28config KILLALL5
  29  bool "killall5"
  30  default y
  31  depends on KILL
  32  help
  33    usage: killall5 [-l [SIGNAL]] [-SIGNAL|-s SIGNAL] [-o PID]...
  34
  35    Send a signal to all processes outside current session.
  36
  37    -l  List signal name(s) and number(s)
  38    -o PID      Omit PID
  39    -s  Send SIGNAL (default SIGTERM)
  40*/
  41
  42// This has to match the filename:
  43#define FOR_kill
  44#define FORCE_FLAGS
  45#include "toys.h"
  46
  47GLOBALS(
  48  char *s;
  49  struct arg_list *o;
  50)
  51
  52// But kill's flags are a subset of killall5's
  53
  54#define FOR_killall5
  55#include "generated/flags.h"
  56
  57void kill_main(void)
  58{
  59  int signum;
  60  char *tmp, **args = toys.optargs;
  61  pid_t pid;
  62
  63  // list signal(s)
  64  if (FLAG(l)) {
  65    if (*args) {
  66      int signum = sig_to_num(*args);
  67      char *s = 0;
  68
  69      if (signum>=0) s = num_to_sig(signum&127);
  70      if (isdigit(**args)) puts(s ? s : "UNKNOWN");
  71      else printf("%d\n", signum);
  72    } else list_signals();
  73
  74    return;
  75  }
  76
  77  // signal must come before pids, so "kill -9 -1" isn't confusing.
  78
  79  if (!TT.s && *args && **args=='-') TT.s = *(args++)+1;
  80  if (TT.s) {
  81    char *arg;
  82    int i = strtol(TT.s, &arg, 10);
  83
  84    if (!*arg) arg = num_to_sig(i);
  85    else arg = TT.s;
  86
  87    if (!arg || -1 == (signum = sig_to_num(arg)))
  88      error_exit("Unknown signal '%s'", arg);
  89  } else signum = SIGTERM;
  90
  91  // is it killall5?
  92  if (CFG_KILLALL5 && toys.which->name[4]=='a') {
  93    DIR *dp;
  94    struct dirent *entry;
  95    int pid, sid;
  96    long *olist = 0, ocount = 0;
  97
  98    // parse omit list
  99    if (FLAG(o)) {
 100      struct arg_list *ptr;
 101
 102      for (ptr = TT.o; ptr; ptr = ptr->next) ocount++;
 103      olist = xmalloc(ocount*sizeof(long));
 104      ocount = 0;
 105      for (ptr = TT.o; ptr; ptr=ptr->next) olist[ocount++] = atolx(ptr->arg);
 106    }
 107
 108    sid = getsid(pid = getpid());
 109
 110    if (!(dp = opendir("/proc"))) {
 111      free(olist);
 112      perror_exit("/proc");
 113    }
 114    while ((entry = readdir(dp))) {
 115      int count, procpid, procsid;
 116
 117      if (!(procpid = atoi(entry->d_name))) continue;
 118
 119      snprintf(toybuf, sizeof(toybuf), "/proc/%d/stat", procpid);
 120      if (!readfile(toybuf, toybuf, sizeof(toybuf))) continue;
 121      if (sscanf(toybuf, "%*d %*s %*c %*d %*d %d", &procsid) != 1) continue;
 122      if (pid == procpid || sid == procsid || procpid == 1) continue;
 123
 124      // Check for kernel threads.
 125      snprintf(toybuf, sizeof(toybuf), "/proc/%d/cmdline", procpid);
 126      if (!readfile(toybuf, toybuf, sizeof(toybuf)) || !*toybuf) continue;
 127
 128      // Check with omit list.
 129      for (count = 0; count < ocount; count++) 
 130        if (procpid == olist[count]) break;
 131      if (count != ocount) continue;
 132
 133      kill(procpid, signum);
 134    }
 135    closedir(dp);
 136    free(olist);
 137
 138  // is it kill?
 139  } else {
 140
 141    // "<1" in optstr wouldn't cover this because "-SIGNAL"
 142    if (!*args) help_exit("missing argument");
 143
 144    while (*args) {
 145      char *arg = *(args++);
 146
 147      pid = estrtol(arg, &tmp, 10);
 148      if (!errno && *tmp) errno = ESRCH;
 149      if (errno || kill(pid, signum)<0) perror_msg("bad pid '%s'", arg);
 150    }
 151  }
 152}
 153
 154void killall5_main(void)
 155{
 156  kill_main();
 157}
 158