Home | History | Annotate | Download | only in posix
      1 /* kill.c - a program to send signals to processes
      2  *
      3  * Copyright 2012 Daniel Walter <d.walter (at) 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 (at) gmail.com>
     10  * Copyright 2014 Kyungwan Han <asura321 (at) gamil.com>
     11  *
     12  * No Standard
     13 
     14 USE_KILL(NEWTOY(kill, "?ls: ", TOYFLAG_BIN))
     15 USE_KILLALL5(NEWTOY(killall5, "?o*ls: [!lo][!ls]", TOYFLAG_SBIN))
     16 
     17 config 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 
     28 config 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 
     46 GLOBALS(
     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 
     57 void 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 
    150 void killall5_main(void)
    151 {
    152   kill_main();
    153 }
    154