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))
  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#include "toys.h"
  45
  46GLOBALS(
  47  char *signame;
  48  struct arg_list *olist;
  49)
  50
  51// But kill's flags are a subset of killall5's
  52
  53#define CLEANUP_kill
  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 (toys.optflags & FLAG_l) {
  65    if (*args) {
  66      int signum = sig_to_num(*args);
  67      char *s = NULL;
  68
  69      if (signum>=0) s = num_to_sig(signum&127);
  70      puts(s ? s : "UNKNOWN");
  71    } else sig_to_num(NULL);
  72    return;
  73  }
  74
  75  // signal must come before pids, so "kill -9 -1" isn't confusing.
  76
  77  if (!TT.signame && *args && **args=='-') TT.signame=*(args++)+1;
  78  if (TT.signame) {
  79    char *arg;
  80    int i = strtol(TT.signame, &arg, 10);
  81    if (!*arg) arg = num_to_sig(i);
  82    else arg = TT.signame;
  83
  84    if (!arg || -1 == (signum = sig_to_num(arg)))
  85      error_exit("Unknown signal '%s'", arg);
  86  } else signum = SIGTERM;
  87
  88  // is it killall5?
  89  if (CFG_KILLALL5 && toys.which->name[4]=='a') {
  90    DIR *dp;
  91    struct dirent *entry;
  92    int pid, sid;
  93    long *olist = 0, ocount = 0;
  94
  95    // parse omit list
  96    if (toys.optflags & FLAG_o) {
  97      struct arg_list *ptr;
  98
  99      for (ptr = TT.olist; ptr; ptr = ptr->next) ocount++;
 100      olist = xmalloc(ocount*sizeof(long));
 101      ocount = 0;
 102      for (ptr = TT.olist; ptr; ptr=ptr->next)
 103        olist[ocount++] = atolx(ptr->arg);
 104    }
 105
 106    sid = getsid(pid = getpid());
 107
 108    if (!(dp = opendir("/proc"))) perror_exit("/proc");
 109    while ((entry = readdir(dp))) {
 110      int count, procpid, procsid;
 111
 112      if (!(procpid = atoi(entry->d_name))) continue;
 113
 114      snprintf(toybuf, sizeof(toybuf), "/proc/%d/stat", procpid);
 115      if (!readfile(toybuf, toybuf, sizeof(toybuf))) continue;
 116      if (sscanf(toybuf, "%*d %*s %*c %*d %*d %d", &procsid) != 1) continue;
 117      if (pid == procpid || sid == procsid || procpid == 1) continue;
 118
 119      // Check for kernel threads.
 120      snprintf(toybuf, sizeof(toybuf), "/proc/%d/cmdline", procpid);
 121      if (!readfile(toybuf, toybuf, sizeof(toybuf)) || !*toybuf) continue;
 122
 123      // Check with omit list.
 124      for (count = 0; count < ocount; count++) 
 125        if (procpid == olist[count]) break;
 126      if (count != ocount) continue;
 127
 128      kill(procpid, signum);
 129    }
 130    if (CFG_TOYBOX_FREE) {
 131      closedir(dp);
 132      free(olist);
 133    }
 134
 135  // is it kill?
 136  } else {
 137
 138    // "<1" in optstr wouldn't cover this because "-SIGNAL"
 139    if (!*args) help_exit("missing argument");
 140
 141    while (*args) {
 142      char *arg = *(args++);
 143
 144      pid = strtol(arg, &tmp, 10);
 145      if (*tmp || kill(pid, signum) < 0) error_msg("unknown pid '%s'", arg);
 146    }
 147  }
 148}
 149
 150void killall5_main(void)
 151{
 152  kill_main();
 153}
 154