10f66f451Sopenharmony_ci/* kill.c - a program to send signals to processes
20f66f451Sopenharmony_ci *
30f66f451Sopenharmony_ci * Copyright 2012 Daniel Walter <d.walter@0x90.at>
40f66f451Sopenharmony_ci *
50f66f451Sopenharmony_ci * See http://opengroup.org/onlinepubs/9699919799/utilities/kill.html
60f66f451Sopenharmony_ci *
70f66f451Sopenharmony_ci * killall5.c - Send signal to all processes outside current session.
80f66f451Sopenharmony_ci *
90f66f451Sopenharmony_ci * Copyright 2014 Ranjan Kumar <ranjankumar.bth@gmail.com>
100f66f451Sopenharmony_ci * Copyright 2014 Kyungwan Han <asura321@gamil.com>
110f66f451Sopenharmony_ci *
120f66f451Sopenharmony_ci * No Standard
130f66f451Sopenharmony_ci
140f66f451Sopenharmony_ciUSE_KILL(NEWTOY(kill, "?ls: ", TOYFLAG_BIN))
150f66f451Sopenharmony_ciUSE_KILLALL5(NEWTOY(killall5, "?o*ls: [!lo][!ls]", TOYFLAG_SBIN))
160f66f451Sopenharmony_ci
170f66f451Sopenharmony_ciconfig KILL
180f66f451Sopenharmony_ci  bool "kill"
190f66f451Sopenharmony_ci  default y
200f66f451Sopenharmony_ci  help
210f66f451Sopenharmony_ci    usage: kill [-l [SIGNAL] | SIGNAL | -SIGNAL] pid...
220f66f451Sopenharmony_ci
230f66f451Sopenharmony_ci    Send signal to process(es).
240f66f451Sopenharmony_ci
250f66f451Sopenharmony_ci    -l	List signal name(s) and number(s)
260f66f451Sopenharmony_ci
270f66f451Sopenharmony_ciconfig KILLALL5
280f66f451Sopenharmony_ci  bool "killall5"
290f66f451Sopenharmony_ci  default n
300f66f451Sopenharmony_ci  depends on KILL
310f66f451Sopenharmony_ci  help
320f66f451Sopenharmony_ci    usage: killall5 [-l [SIGNAL]] [-SIGNAL|-s SIGNAL] [-o PID]...
330f66f451Sopenharmony_ci
340f66f451Sopenharmony_ci    Send a signal to all processes outside current session.
350f66f451Sopenharmony_ci
360f66f451Sopenharmony_ci    -l	List signal name(s) and number(s)
370f66f451Sopenharmony_ci    -o PID	Omit PID
380f66f451Sopenharmony_ci    -s	Send SIGNAL (default SIGTERM)
390f66f451Sopenharmony_ci*/
400f66f451Sopenharmony_ci
410f66f451Sopenharmony_ci// This has to match the filename:
420f66f451Sopenharmony_ci#define FOR_kill
430f66f451Sopenharmony_ci#define FORCE_FLAGS
440f66f451Sopenharmony_ci#include "toys.h"
450f66f451Sopenharmony_ci
460f66f451Sopenharmony_ciGLOBALS(
470f66f451Sopenharmony_ci  char *s;
480f66f451Sopenharmony_ci  struct arg_list *o;
490f66f451Sopenharmony_ci)
500f66f451Sopenharmony_ci
510f66f451Sopenharmony_ci// But kill's flags are a subset of killall5's
520f66f451Sopenharmony_ci
530f66f451Sopenharmony_ci#define CLEANUP_kill
540f66f451Sopenharmony_ci#define FOR_killall5
550f66f451Sopenharmony_ci#include "generated/flags.h"
560f66f451Sopenharmony_ci
570f66f451Sopenharmony_civoid kill_main(void)
580f66f451Sopenharmony_ci{
590f66f451Sopenharmony_ci  int signum;
600f66f451Sopenharmony_ci  char *tmp, **args = toys.optargs;
610f66f451Sopenharmony_ci  pid_t pid;
620f66f451Sopenharmony_ci
630f66f451Sopenharmony_ci  // list signal(s)
640f66f451Sopenharmony_ci  if (FLAG(l)) {
650f66f451Sopenharmony_ci    if (*args) {
660f66f451Sopenharmony_ci      int signum = sig_to_num(*args);
670f66f451Sopenharmony_ci      char *s = NULL;
680f66f451Sopenharmony_ci
690f66f451Sopenharmony_ci      if (signum>=0) s = num_to_sig(signum&127);
700f66f451Sopenharmony_ci      if (isdigit(**args)) puts(s ? s : "UNKNOWN");
710f66f451Sopenharmony_ci      else printf("%d\n", signum);
720f66f451Sopenharmony_ci    } else list_signals();
730f66f451Sopenharmony_ci    return;
740f66f451Sopenharmony_ci  }
750f66f451Sopenharmony_ci
760f66f451Sopenharmony_ci  // signal must come before pids, so "kill -9 -1" isn't confusing.
770f66f451Sopenharmony_ci
780f66f451Sopenharmony_ci  if (!TT.s && *args && **args=='-') TT.s = *(args++)+1;
790f66f451Sopenharmony_ci  if (TT.s) {
800f66f451Sopenharmony_ci    char *arg;
810f66f451Sopenharmony_ci    int i = strtol(TT.s, &arg, 10);
820f66f451Sopenharmony_ci    if (!*arg) arg = num_to_sig(i);
830f66f451Sopenharmony_ci    else arg = TT.s;
840f66f451Sopenharmony_ci
850f66f451Sopenharmony_ci    if (!arg || -1 == (signum = sig_to_num(arg)))
860f66f451Sopenharmony_ci      error_exit("Unknown signal '%s'", arg);
870f66f451Sopenharmony_ci  } else signum = SIGTERM;
880f66f451Sopenharmony_ci
890f66f451Sopenharmony_ci  // is it killall5?
900f66f451Sopenharmony_ci  if (CFG_KILLALL5 && toys.which->name[4]=='a') {
910f66f451Sopenharmony_ci    DIR *dp;
920f66f451Sopenharmony_ci    struct dirent *entry;
930f66f451Sopenharmony_ci    int pid, sid;
940f66f451Sopenharmony_ci    long *olist = 0, ocount = 0;
950f66f451Sopenharmony_ci
960f66f451Sopenharmony_ci    // parse omit list
970f66f451Sopenharmony_ci    if (FLAG(o)) {
980f66f451Sopenharmony_ci      struct arg_list *ptr;
990f66f451Sopenharmony_ci
1000f66f451Sopenharmony_ci      for (ptr = TT.o; ptr; ptr = ptr->next) ocount++;
1010f66f451Sopenharmony_ci      olist = xmalloc(ocount*sizeof(long));
1020f66f451Sopenharmony_ci      ocount = 0;
1030f66f451Sopenharmony_ci      for (ptr = TT.o; ptr; ptr=ptr->next) olist[ocount++] = atolx(ptr->arg);
1040f66f451Sopenharmony_ci    }
1050f66f451Sopenharmony_ci
1060f66f451Sopenharmony_ci    sid = getsid(pid = getpid());
1070f66f451Sopenharmony_ci
1080f66f451Sopenharmony_ci    if (!(dp = opendir("/proc"))) perror_exit("/proc");
1090f66f451Sopenharmony_ci    while ((entry = readdir(dp))) {
1100f66f451Sopenharmony_ci      int count, procpid, procsid;
1110f66f451Sopenharmony_ci
1120f66f451Sopenharmony_ci      if (!(procpid = atoi(entry->d_name))) continue;
1130f66f451Sopenharmony_ci
1140f66f451Sopenharmony_ci      snprintf(toybuf, sizeof(toybuf), "/proc/%d/stat", procpid);
1150f66f451Sopenharmony_ci      if (!readfile(toybuf, toybuf, sizeof(toybuf))) continue;
1160f66f451Sopenharmony_ci      if (sscanf(toybuf, "%*d %*s %*c %*d %*d %d", &procsid) != 1) continue;
1170f66f451Sopenharmony_ci      if (pid == procpid || sid == procsid || procpid == 1) continue;
1180f66f451Sopenharmony_ci
1190f66f451Sopenharmony_ci      // Check for kernel threads.
1200f66f451Sopenharmony_ci      snprintf(toybuf, sizeof(toybuf), "/proc/%d/cmdline", procpid);
1210f66f451Sopenharmony_ci      if (!readfile(toybuf, toybuf, sizeof(toybuf)) || !*toybuf) continue;
1220f66f451Sopenharmony_ci
1230f66f451Sopenharmony_ci      // Check with omit list.
1240f66f451Sopenharmony_ci      for (count = 0; count < ocount; count++)
1250f66f451Sopenharmony_ci        if (procpid == olist[count]) break;
1260f66f451Sopenharmony_ci      if (count != ocount) continue;
1270f66f451Sopenharmony_ci
1280f66f451Sopenharmony_ci      kill(procpid, signum);
1290f66f451Sopenharmony_ci    }
1300f66f451Sopenharmony_ci    if (CFG_TOYBOX_FREE) {
1310f66f451Sopenharmony_ci      closedir(dp);
1320f66f451Sopenharmony_ci      free(olist);
1330f66f451Sopenharmony_ci    }
1340f66f451Sopenharmony_ci
1350f66f451Sopenharmony_ci  // is it kill?
1360f66f451Sopenharmony_ci  } else {
1370f66f451Sopenharmony_ci
1380f66f451Sopenharmony_ci    // "<1" in optstr wouldn't cover this because "-SIGNAL"
1390f66f451Sopenharmony_ci    if (!*args) help_exit("missing argument");
1400f66f451Sopenharmony_ci
1410f66f451Sopenharmony_ci    while (*args) {
1420f66f451Sopenharmony_ci      char *arg = *(args++);
1430f66f451Sopenharmony_ci
1440f66f451Sopenharmony_ci      pid = strtol(arg, &tmp, 10);
1450f66f451Sopenharmony_ci      if (*tmp || kill(pid, signum) < 0) error_msg("unknown pid '%s'", arg);
1460f66f451Sopenharmony_ci    }
1470f66f451Sopenharmony_ci  }
1480f66f451Sopenharmony_ci}
1490f66f451Sopenharmony_ci
1500f66f451Sopenharmony_civoid killall5_main(void)
1510f66f451Sopenharmony_ci{
1520f66f451Sopenharmony_ci  kill_main();
1530f66f451Sopenharmony_ci}
154