aboutsummaryrefslogtreecommitdiff
path: root/toys/pending/killall5.c
blob: 4d9dadcefdfcceb043b01d08eed1b4215039a86c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/* killall5.c - Send signal (default: TERM) to all processes outside current session.
 *
 * Copyright 2014 Ranjan Kumar <ranjankumar.bth@gmail.com>
 * Copyright 2014 Kyungwan Han <asura321@gamil.com>
 *
 * No Standard

USE_KILLALL5(NEWTOY(killall5, "?o*ls:[!lo]", TOYFLAG_SBIN))

config KILLALL5
  bool "killall5"
  default n
  help
    usage: killall5 [-l] [-SIGNAL|-s SIGNAL] [-o PID]...

    Send a signal (default: TERM) to all processes outside current session.

    -l     List all signal names and numbers
    -o PID Don't signal this PID
    -s     send SIGNAL instead of SIGTERM
*/
#define FOR_killall5
#include "toys.h"

GLOBALS(
  char *signame;
  struct arg_list *olist;
)

void killall5_main(void)
{
  DIR *dp;
  struct dirent *entry;
  int signo, pid, sid, signum = SIGTERM;
  long *olist = NULL, ocount = 0;
  char *s, **args = toys.optargs;

  // list all signal names and numbers
  if (toys.optflags & FLAG_l) {
    if (*args) {
      for (; *args; args++) {
    	signo = sig_to_num(*args);
    	if (isdigit(**args) && (s = num_to_sig(signo&127))) xputs(s);
    	else if (signo > 0) xprintf("%d\n", signo);
    	else error_exit("UNKNOWN signal '%s'", *args);
      }
    } else sig_to_num(NULL);
    return;
  }

  // when SIGNUM will be in the form of -SIGNUM
  if (TT.signame || (*args && **args == '-')) {
    if (0 > (signum = sig_to_num(TT.signame ? TT.signame : (*args)+1)))
      error_exit("Unknown signal '%s'", *args);
    if (!TT.signame) args++;
  }
  pid = getpid();
  sid = getsid(pid);

  // prepare omit list
  if (toys.optflags & FLAG_o) {
    struct arg_list *ptr = TT.olist;

    if (*args) error_exit("invalid omit list");
    for (; ptr; ptr=ptr->next) {
      long val = atolx(ptr->arg);
      olist = xrealloc(olist, (ocount+1)*sizeof(long));
      olist[ocount++] = val;
    }
  }

  if (!(dp = opendir("/proc"))) perror_exit("opendir");
  while ((entry = readdir(dp))) {
    int count, procpid, procsid;

    if (!(procpid = atoi(entry->d_name))) continue;
    snprintf(toybuf, sizeof(toybuf), "/proc/%d/stat", procpid);
    if (!readfile(toybuf, toybuf, sizeof(toybuf))) continue;
    if (sscanf(toybuf, "%*d %*s %*c %*d %*d %d", &procsid) != 1) continue;
    if (pid == procpid || sid == procsid || procpid == 1) continue;

    // Check for kernel threads.
    snprintf(toybuf, sizeof(toybuf), "/proc/%d/cmdline", procpid);
    if (readfile(toybuf, toybuf, sizeof(toybuf)) && !*toybuf) continue;

    // Check with omit list.
    if (toys.optflags & FLAG_o) {
      for (count = 0; count < ocount; count++) {
        if (procpid == olist[count]) goto OMIT;
      }
    }    
    kill(procpid, signum);
OMIT: ;
  }
  closedir(dp);
  if (CFG_TOYBOX_FREE && olist) free(olist);
}