xref: /third_party/toybox/toys/posix/kill.c (revision 0f66f451)
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|TOYFLAG_MAYFORK))
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] | -s 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    -s	Send SIGNAL (default SIGTERM)
270f66f451Sopenharmony_ci
280f66f451Sopenharmony_ciconfig KILLALL5
290f66f451Sopenharmony_ci  bool "killall5"
300f66f451Sopenharmony_ci  default y
310f66f451Sopenharmony_ci  depends on KILL
320f66f451Sopenharmony_ci  help
330f66f451Sopenharmony_ci    usage: killall5 [-l [SIGNAL]] [-SIGNAL|-s SIGNAL] [-o PID]...
340f66f451Sopenharmony_ci
350f66f451Sopenharmony_ci    Send a signal to all processes outside current session.
360f66f451Sopenharmony_ci
370f66f451Sopenharmony_ci    -l	List signal name(s) and number(s)
380f66f451Sopenharmony_ci    -o PID	Omit PID
390f66f451Sopenharmony_ci    -s	Send SIGNAL (default SIGTERM)
400f66f451Sopenharmony_ci*/
410f66f451Sopenharmony_ci
420f66f451Sopenharmony_ci// This has to match the filename:
430f66f451Sopenharmony_ci#define FOR_kill
440f66f451Sopenharmony_ci#define FORCE_FLAGS
450f66f451Sopenharmony_ci#include "toys.h"
460f66f451Sopenharmony_ci
470f66f451Sopenharmony_ciGLOBALS(
480f66f451Sopenharmony_ci  char *s;
490f66f451Sopenharmony_ci  struct arg_list *o;
500f66f451Sopenharmony_ci)
510f66f451Sopenharmony_ci
520f66f451Sopenharmony_ci// But kill's flags are a subset of killall5's
530f66f451Sopenharmony_ci
540f66f451Sopenharmony_ci#define CLEANUP_kill
550f66f451Sopenharmony_ci#define FOR_killall5
560f66f451Sopenharmony_ci#include "generated/flags.h"
570f66f451Sopenharmony_ci
580f66f451Sopenharmony_civoid kill_main(void)
590f66f451Sopenharmony_ci{
600f66f451Sopenharmony_ci  int signum;
610f66f451Sopenharmony_ci  char *tmp, **args = toys.optargs;
620f66f451Sopenharmony_ci  pid_t pid;
630f66f451Sopenharmony_ci
640f66f451Sopenharmony_ci  // list signal(s)
650f66f451Sopenharmony_ci  if (FLAG(l)) {
660f66f451Sopenharmony_ci    if (*args) {
670f66f451Sopenharmony_ci      int signum = sig_to_num(*args);
680f66f451Sopenharmony_ci      char *s = 0;
690f66f451Sopenharmony_ci
700f66f451Sopenharmony_ci      if (signum>=0) s = num_to_sig(signum&127);
710f66f451Sopenharmony_ci      if (isdigit(**args)) puts(s ? s : "UNKNOWN");
720f66f451Sopenharmony_ci      else printf("%d\n", signum);
730f66f451Sopenharmony_ci    } else list_signals();
740f66f451Sopenharmony_ci
750f66f451Sopenharmony_ci    return;
760f66f451Sopenharmony_ci  }
770f66f451Sopenharmony_ci
780f66f451Sopenharmony_ci  // signal must come before pids, so "kill -9 -1" isn't confusing.
790f66f451Sopenharmony_ci
800f66f451Sopenharmony_ci  if (!TT.s && *args && **args=='-') TT.s = *(args++)+1;
810f66f451Sopenharmony_ci  if (TT.s) {
820f66f451Sopenharmony_ci    char *arg;
830f66f451Sopenharmony_ci    int i = strtol(TT.s, &arg, 10);
840f66f451Sopenharmony_ci
850f66f451Sopenharmony_ci    if (!*arg) arg = num_to_sig(i);
860f66f451Sopenharmony_ci    else arg = TT.s;
870f66f451Sopenharmony_ci
880f66f451Sopenharmony_ci    if (!arg || -1 == (signum = sig_to_num(arg)))
890f66f451Sopenharmony_ci      error_exit("Unknown signal '%s'", arg);
900f66f451Sopenharmony_ci  } else signum = SIGTERM;
910f66f451Sopenharmony_ci
920f66f451Sopenharmony_ci  // is it killall5?
930f66f451Sopenharmony_ci  if (CFG_KILLALL5 && toys.which->name[4]=='a') {
940f66f451Sopenharmony_ci    DIR *dp;
950f66f451Sopenharmony_ci    struct dirent *entry;
960f66f451Sopenharmony_ci    int pid, sid;
970f66f451Sopenharmony_ci    long *olist = 0, ocount = 0;
980f66f451Sopenharmony_ci
990f66f451Sopenharmony_ci    // parse omit list
1000f66f451Sopenharmony_ci    if (FLAG(o)) {
1010f66f451Sopenharmony_ci      struct arg_list *ptr;
1020f66f451Sopenharmony_ci
1030f66f451Sopenharmony_ci      for (ptr = TT.o; ptr; ptr = ptr->next) ocount++;
1040f66f451Sopenharmony_ci      olist = xmalloc(ocount*sizeof(long));
1050f66f451Sopenharmony_ci      ocount = 0;
1060f66f451Sopenharmony_ci      for (ptr = TT.o; ptr; ptr=ptr->next) olist[ocount++] = atolx(ptr->arg);
1070f66f451Sopenharmony_ci    }
1080f66f451Sopenharmony_ci
1090f66f451Sopenharmony_ci    sid = getsid(pid = getpid());
1100f66f451Sopenharmony_ci
1110f66f451Sopenharmony_ci    if (!(dp = opendir("/proc"))) {
1120f66f451Sopenharmony_ci      free(olist);
1130f66f451Sopenharmony_ci      perror_exit("/proc");
1140f66f451Sopenharmony_ci    }
1150f66f451Sopenharmony_ci    while ((entry = readdir(dp))) {
1160f66f451Sopenharmony_ci      int count, procpid, procsid;
1170f66f451Sopenharmony_ci
1180f66f451Sopenharmony_ci      if (!(procpid = atoi(entry->d_name))) continue;
1190f66f451Sopenharmony_ci
1200f66f451Sopenharmony_ci      snprintf(toybuf, sizeof(toybuf), "/proc/%d/stat", procpid);
1210f66f451Sopenharmony_ci      if (!readfile(toybuf, toybuf, sizeof(toybuf))) continue;
1220f66f451Sopenharmony_ci      if (sscanf(toybuf, "%*d %*s %*c %*d %*d %d", &procsid) != 1) continue;
1230f66f451Sopenharmony_ci      if (pid == procpid || sid == procsid || procpid == 1) continue;
1240f66f451Sopenharmony_ci
1250f66f451Sopenharmony_ci      // Check for kernel threads.
1260f66f451Sopenharmony_ci      snprintf(toybuf, sizeof(toybuf), "/proc/%d/cmdline", procpid);
1270f66f451Sopenharmony_ci      if (!readfile(toybuf, toybuf, sizeof(toybuf)) || !*toybuf) continue;
1280f66f451Sopenharmony_ci
1290f66f451Sopenharmony_ci      // Check with omit list.
1300f66f451Sopenharmony_ci      for (count = 0; count < ocount; count++)
1310f66f451Sopenharmony_ci        if (procpid == olist[count]) break;
1320f66f451Sopenharmony_ci      if (count != ocount) continue;
1330f66f451Sopenharmony_ci
1340f66f451Sopenharmony_ci      kill(procpid, signum);
1350f66f451Sopenharmony_ci    }
1360f66f451Sopenharmony_ci    closedir(dp);
1370f66f451Sopenharmony_ci    free(olist);
1380f66f451Sopenharmony_ci
1390f66f451Sopenharmony_ci  // is it kill?
1400f66f451Sopenharmony_ci  } else {
1410f66f451Sopenharmony_ci
1420f66f451Sopenharmony_ci    // "<1" in optstr wouldn't cover this because "-SIGNAL"
1430f66f451Sopenharmony_ci    if (!*args) help_exit("missing argument");
1440f66f451Sopenharmony_ci
1450f66f451Sopenharmony_ci    while (*args) {
1460f66f451Sopenharmony_ci      char *arg = *(args++);
1470f66f451Sopenharmony_ci
1480f66f451Sopenharmony_ci      pid = strtol(arg, &tmp, 10);
1490f66f451Sopenharmony_ci      if (*tmp || kill(pid, signum) < 0) error_msg("unknown pid '%s'", arg);
1500f66f451Sopenharmony_ci    }
1510f66f451Sopenharmony_ci  }
1520f66f451Sopenharmony_ci}
1530f66f451Sopenharmony_ci
1540f66f451Sopenharmony_civoid killall5_main(void)
1550f66f451Sopenharmony_ci{
1560f66f451Sopenharmony_ci  kill_main();
1570f66f451Sopenharmony_ci}
158