killall.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2018 K. Lange
  5. *
  6. * killall - Send signals to processes matching name
  7. *
  8. * Find processes by name and send them signals.
  9. */
  10. #include <sys/stat.h>
  11. #include <sys/signal.h>
  12. #include <fcntl.h>
  13. #include <stdint.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18. #include <dirent.h>
  19. #include <signal.h>
  20. #include <getopt.h>
  21. typedef struct process {
  22. int pid;
  23. int ppid;
  24. int tgid;
  25. char name[100];
  26. char path[200];
  27. } p_t;
  28. #define LINE_LEN 4096
  29. p_t * build_entry(struct dirent * dent) {
  30. char tmp[256];
  31. FILE * f;
  32. char line[LINE_LEN];
  33. sprintf(tmp, "/proc/%s/status", dent->d_name);
  34. f = fopen(tmp, "r");
  35. p_t * proc = malloc(sizeof(p_t));
  36. while (fgets(line, LINE_LEN, f) != NULL) {
  37. char * n = strstr(line,"\n");
  38. if (n) { *n = '\0'; }
  39. char * tab = strstr(line,"\t");
  40. if (tab) {
  41. *tab = '\0';
  42. tab++;
  43. }
  44. if (strstr(line, "Pid:") == line) {
  45. proc->pid = atoi(tab);
  46. } else if (strstr(line, "PPid:") == line) {
  47. proc->ppid = atoi(tab);
  48. } else if (strstr(line, "Tgid:") == line) {
  49. proc->tgid = atoi(tab);
  50. } else if (strstr(line, "Name:") == line) {
  51. strcpy(proc->name, tab);
  52. } else if (strstr(line, "Path:") == line) {
  53. strcpy(proc->path, tab);
  54. }
  55. }
  56. if (strstr(proc->name,"python") == proc->name) {
  57. char * name = proc->path + strlen(proc->path) - 1;
  58. while (1) {
  59. if (*name == '/') {
  60. name++;
  61. break;
  62. }
  63. if (name == proc->name) break;
  64. name--;
  65. }
  66. memcpy(proc->name, name, strlen(name)+1);
  67. }
  68. if (proc->tgid != proc->pid) {
  69. char tmp[100] = {0};
  70. sprintf(tmp, "{%s}", proc->name);
  71. memcpy(proc->name, tmp, strlen(tmp)+1);
  72. }
  73. fclose(f);
  74. return proc;
  75. }
  76. void show_usage(int argc, char * argv[]) {
  77. printf(
  78. "killall - send signal to processes with given name\n"
  79. "\n"
  80. "usage: %s [-s SIG] name\n"
  81. "\n"
  82. " -s \033[3msignal to send\033[0m\n"
  83. " -? \033[3mshow this help text\033[0m\n"
  84. "\n", argv[0]);
  85. }
  86. struct sig_def {
  87. int sig;
  88. const char * name;
  89. };
  90. struct sig_def signals[] = {
  91. {SIGHUP,"HUP"},
  92. {SIGINT,"INT"},
  93. {SIGQUIT,"QUIT"},
  94. {SIGILL,"ILL"},
  95. {SIGTRAP,"TRAP"},
  96. {SIGABRT,"ABRT"},
  97. {SIGEMT,"EMT"},
  98. {SIGFPE,"FPE"},
  99. {SIGKILL,"KILL"},
  100. {SIGBUS,"BUS"},
  101. {SIGSEGV,"SEGV"},
  102. {SIGSYS,"SYS"},
  103. {SIGPIPE,"PIPE"},
  104. {SIGALRM,"ALRM"},
  105. {SIGTERM,"TERM"},
  106. {SIGUSR1,"USR1"},
  107. {SIGUSR2,"USR2"},
  108. {SIGCHLD,"CHLD"},
  109. {SIGPWR,"PWR"},
  110. {SIGWINCH,"WINCH"},
  111. {SIGURG,"URG"},
  112. {SIGPOLL,"POLL"},
  113. {SIGSTOP,"STOP"},
  114. {SIGTSTP,"TSTP"},
  115. {SIGCONT,"CONT"},
  116. {SIGTTIN,"TTIN"},
  117. {SIGTTOUT,"TTOUT"},
  118. {SIGVTALRM,"VTALRM"},
  119. {SIGPROF,"PROF"},
  120. {SIGXCPU,"XCPU"},
  121. {SIGXFSZ,"XFSZ"},
  122. {SIGWAITING,"WAITING"},
  123. {SIGDIAF,"DIAF"},
  124. {SIGHATE,"HATE"},
  125. {SIGWINEVENT,"WINEVENT"},
  126. {SIGCAT,"CAT"},
  127. {0,NULL},
  128. };
  129. int main (int argc, char * argv[]) {
  130. int signum = SIGTERM;
  131. /* Open the directory */
  132. DIR * dirp = opendir("/proc");
  133. char c;
  134. while ((c = getopt(argc, argv, "s:?")) != -1) {
  135. switch (c) {
  136. case 's':
  137. {
  138. signum = -1;
  139. if (strlen(optarg) > 3 && strstr(optarg,"SIG") == (optarg)) {
  140. struct sig_def * s = signals;
  141. while (s->name) {
  142. if (!strcmp(optarg+3,s->name)) {
  143. signum = s->sig;
  144. break;
  145. }
  146. s++;
  147. }
  148. } else {
  149. if (optarg[0] < '0' || optarg[0] > '9') {
  150. struct sig_def * s = signals;
  151. while (s->name) {
  152. if (!strcmp(optarg,s->name)) {
  153. signum = s->sig;
  154. break;
  155. }
  156. s++;
  157. }
  158. } else {
  159. signum = atoi(optarg);
  160. }
  161. }
  162. if (signum == -1) {
  163. fprintf(stderr,"%s: %s: invalid signal specification\n",argv[0],optarg);
  164. return 1;
  165. }
  166. }
  167. break;
  168. case '?':
  169. show_usage(argc, argv);
  170. return 0;
  171. }
  172. }
  173. if (optind >= argc) {
  174. show_usage(argc, argv);
  175. return 1;
  176. }
  177. int killed_something = 0;
  178. struct dirent * ent = readdir(dirp);
  179. while (ent != NULL) {
  180. if (ent->d_name[0] >= '0' && ent->d_name[0] <= '9') {
  181. p_t * proc = build_entry(ent);
  182. if (!strcmp(proc->name, argv[optind])) {
  183. kill(proc->pid, signum);
  184. killed_something = 1;
  185. }
  186. }
  187. ent = readdir(dirp);
  188. }
  189. closedir(dirp);
  190. if (!killed_something) {
  191. fprintf(stderr, "%s: no process found\n", argv[optind]);
  192. return 1;
  193. }
  194. return 0;
  195. }