kill.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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. USE_KILL(NEWTOY(kill, "?ls: ", TOYFLAG_BIN|TOYFLAG_MAYFORK))
  14. USE_KILLALL5(NEWTOY(killall5, "?o*ls: [!lo][!ls]", TOYFLAG_SBIN))
  15. config KILL
  16. bool "kill"
  17. default y
  18. help
  19. usage: kill [-l [SIGNAL] | -s SIGNAL | -SIGNAL] PID...
  20. Send signal to process(es).
  21. -l List signal name(s) and number(s)
  22. -s Send SIGNAL (default SIGTERM)
  23. config KILLALL5
  24. bool "killall5"
  25. default y
  26. depends on KILL
  27. help
  28. usage: killall5 [-l [SIGNAL]] [-SIGNAL|-s SIGNAL] [-o PID]...
  29. Send a signal to all processes outside current session.
  30. -l List signal name(s) and number(s)
  31. -o PID Omit PID
  32. -s Send SIGNAL (default SIGTERM)
  33. */
  34. // This has to match the filename:
  35. #define FOR_kill
  36. #define FORCE_FLAGS
  37. #include "toys.h"
  38. GLOBALS(
  39. char *s;
  40. struct arg_list *o;
  41. )
  42. // But kill's flags are a subset of killall5's
  43. #define FOR_killall5
  44. #include "generated/flags.h"
  45. void kill_main(void)
  46. {
  47. int signum;
  48. char *tmp, **args = toys.optargs;
  49. pid_t pid;
  50. // list signal(s)
  51. if (FLAG(l)) {
  52. if (*args) {
  53. int signum = sig_to_num(*args);
  54. char *s = 0;
  55. if (signum>=0) s = num_to_sig(signum&127);
  56. if (isdigit(**args)) puts(s ? s : "UNKNOWN");
  57. else printf("%d\n", signum);
  58. } else list_signals();
  59. return;
  60. }
  61. // signal must come before pids, so "kill -9 -1" isn't confusing.
  62. if (!TT.s && *args && **args=='-') TT.s = *(args++)+1;
  63. if (TT.s) {
  64. char *arg;
  65. int i = strtol(TT.s, &arg, 10);
  66. if (!*arg) arg = num_to_sig(i);
  67. else arg = TT.s;
  68. if (!arg || -1 == (signum = sig_to_num(arg)))
  69. error_exit("Unknown signal '%s'", arg);
  70. } else signum = SIGTERM;
  71. // is it killall5?
  72. if (CFG_KILLALL5 && toys.which->name[4]=='a') {
  73. DIR *dp;
  74. struct dirent *entry;
  75. int pid, sid;
  76. long *olist = 0, ocount = 0;
  77. // parse omit list
  78. if (FLAG(o)) {
  79. struct arg_list *ptr;
  80. for (ptr = TT.o; ptr; ptr = ptr->next) ocount++;
  81. olist = xmalloc(ocount*sizeof(long));
  82. ocount = 0;
  83. for (ptr = TT.o; ptr; ptr=ptr->next) olist[ocount++] = atolx(ptr->arg);
  84. }
  85. sid = getsid(pid = getpid());
  86. if (!(dp = opendir("/proc"))) {
  87. free(olist);
  88. perror_exit("/proc");
  89. }
  90. while ((entry = readdir(dp))) {
  91. int count, procpid, procsid;
  92. if (!(procpid = atoi(entry->d_name))) continue;
  93. snprintf(toybuf, sizeof(toybuf), "/proc/%d/stat", procpid);
  94. if (!readfile(toybuf, toybuf, sizeof(toybuf))) continue;
  95. if (sscanf(toybuf, "%*d %*s %*c %*d %*d %d", &procsid) != 1) continue;
  96. if (pid == procpid || sid == procsid || procpid == 1) continue;
  97. // Check for kernel threads.
  98. snprintf(toybuf, sizeof(toybuf), "/proc/%d/cmdline", procpid);
  99. if (!readfile(toybuf, toybuf, sizeof(toybuf)) || !*toybuf) continue;
  100. // Check with omit list.
  101. for (count = 0; count < ocount; count++)
  102. if (procpid == olist[count]) break;
  103. if (count != ocount) continue;
  104. kill(procpid, signum);
  105. }
  106. closedir(dp);
  107. free(olist);
  108. // is it kill?
  109. } else {
  110. // "<1" in optstr wouldn't cover this because "-SIGNAL"
  111. if (!*args) help_exit("missing argument");
  112. while (*args) {
  113. char *arg = *(args++);
  114. pid = strtol(arg, &tmp, 10);
  115. if (*tmp || kill(pid, signum) < 0) error_msg("unknown pid '%s'", arg);
  116. }
  117. }
  118. }
  119. void killall5_main(void)
  120. {
  121. kill_main();
  122. }