killall.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /* killall.c - Send signal (default: TERM) to all processes with given names.
  2. *
  3. * Copyright 2012 Andreas Heck <aheck@gmx.de>
  4. *
  5. * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/killall.html
  6. USE_KILLALL(NEWTOY(killall, "?s:ilqvw", TOYFLAG_USR|TOYFLAG_BIN))
  7. config KILLALL
  8. bool "killall"
  9. default y
  10. help
  11. usage: killall [-l] [-iqv] [-SIGNAL|-s SIGNAL] PROCESS_NAME...
  12. Send a signal (default: TERM) to all processes with the given names.
  13. -i Ask for confirmation before killing
  14. -l Print list of all available signals
  15. -q Don't print any warnings or error messages
  16. -s Send SIGNAL instead of SIGTERM
  17. -v Report if the signal was successfully sent
  18. -w Wait until all signaled processes are dead
  19. */
  20. #define FOR_killall
  21. #include "toys.h"
  22. GLOBALS(
  23. char *s;
  24. int signum;
  25. pid_t cur_pid;
  26. char **names;
  27. short *err;
  28. struct int_list { struct int_list *next; int val; } *pids;
  29. )
  30. static int kill_process(pid_t pid, char *name)
  31. {
  32. int offset = 0;
  33. if (pid == TT.cur_pid) return 0;
  34. if (FLAG(i)) {
  35. fprintf(stderr, "Signal %s(%d)", name, (int)pid);
  36. if (!yesno(0)) return 0;
  37. }
  38. errno = 0;
  39. kill(pid, TT.signum);
  40. if (FLAG(w)) {
  41. struct int_list *new = xmalloc(sizeof(*TT.pids));
  42. new->val = pid;
  43. new->next = TT.pids;
  44. TT.pids = new;
  45. }
  46. for (;;) {
  47. if (TT.names[offset] == name) {
  48. TT.err[offset] = errno;
  49. break;
  50. } else offset++;
  51. }
  52. if (errno) {
  53. if (!FLAG(q)) perror_msg("pid %d", (int)pid);
  54. } else if (FLAG(v))
  55. printf("Killed %s(%d) with signal %d\n", name, pid, TT.signum);
  56. return 0;
  57. }
  58. void killall_main(void)
  59. {
  60. int i;
  61. TT.names = toys.optargs;
  62. TT.signum = SIGTERM;
  63. if (FLAG(l)) {
  64. list_signals();
  65. return;
  66. }
  67. if (TT.s || (*TT.names && **TT.names == '-')) {
  68. if (0 > (TT.signum = sig_to_num(TT.s ? TT.s : (*TT.names)+1))) {
  69. if (FLAG(q)) exit(1);
  70. error_exit("Invalid signal");
  71. }
  72. if (!TT.s) {
  73. TT.names++;
  74. toys.optc--;
  75. }
  76. }
  77. if (!toys.optc) help_exit("no name");
  78. TT.cur_pid = getpid();
  79. TT.err = xmalloc(2*toys.optc);
  80. for (i=0; i<toys.optc; i++) TT.err[i] = ESRCH;
  81. names_to_pid(TT.names, kill_process, 1);
  82. for (i=0; i<toys.optc; i++) {
  83. if (TT.err[i]) {
  84. toys.exitval = 1;
  85. errno = TT.err[i];
  86. perror_msg_raw(TT.names[i]);
  87. }
  88. }
  89. if (FLAG(w)) {
  90. for (;;) {
  91. struct int_list *p = TT.pids;
  92. int c = 0;
  93. for (; p; p=p->next) if (kill(p->val, 0) != -1 || errno != ESRCH) ++c;
  94. if (!c) break;
  95. sleep(1);
  96. }
  97. }
  98. if (CFG_TOYBOX_FREE) {
  99. free(TT.err);
  100. llist_traverse(TT.pids, free);
  101. }
  102. }