vkill.c (2421B)
1#include <linux/limits.h> 2#include <strings.h> 3#include <unistd.h> 4#include <termios.h> 5#include <dirent.h> 6#include <wait.h> 7#include <ctype.h> 8#include <signal.h> 9#include <err.h> 10#include <string.h> 11#include <stdlib.h> 12#include <stdio.h> 13 14static const char usage[] = "vkill [-h] [-SIG] CMD"; 15static int signum = SIGTERM; 16 17const char * 18strcasestr(const char *haystack, const char *needle) 19{ 20 size_t needle_len; 21 22 needle_len = strlen(needle); 23 while (*haystack) { 24 if (!strncasecmp(haystack, needle, needle_len)) 25 return haystack; 26 haystack++; 27 } 28 29 return NULL; 30} 31 32char * 33readcmd(pid_t pid) 34{ 35 char pathbuf[PATH_MAX]; 36 size_t i, cap, size; 37 FILE *file; 38 char *cmd; 39 40 snprintf(pathbuf, PATH_MAX, "/proc/%u/cmdline", pid); 41 file = fopen(pathbuf, "r"); 42 if (!file) return NULL; 43 44 cap = 4096; 45 cmd = malloc(cap + 1); 46 if (!cmd) err(1, "malloc"); 47 48 if (!(size = fread(cmd, 1, cap, file))) { 49 free(cmd); 50 fclose(file); 51 return NULL; 52 } 53 54 for (i = 0; i < size; i++) 55 if (!cmd[i]) cmd[i] = ' '; 56 cmd[size] = '\0'; 57 58 fclose(file); 59 60 return cmd; 61} 62 63void 64killprompt(pid_t pid) 65{ 66 struct termios old, new; 67 char c; 68 69 tcgetattr(0, &old); 70 tcgetattr(0, &new); 71 new.c_lflag &= ~ECHO; 72 new.c_lflag &= ~ICANON; 73 new.c_lflag &= ~ISIG; 74 tcsetattr(0, TCSANOW, &new); 75 76 c = getchar(); 77 if (c == 'y') { 78 kill(pid, signum); 79 waitpid(pid, NULL, 0); 80 } 81 82 tcsetattr(0, TCSANOW, &old); 83 84 if (c == 3) exit(0); 85} 86 87int 88main(int argc, const char **argv) 89{ 90 pid_t pid, cpid; 91 struct dirent *ent; 92 const char **arg; 93 const char *query; 94 char *end, *cmd; 95 DIR *dir; 96 int i; 97 98 query = NULL; 99 for (arg = &argv[1]; *arg; arg++) { 100 if (!strcmp(*arg, "-h")) { 101 printf("Usage: %s\n", usage); 102 return 0; 103 } else if (**arg == '-') { 104 signum = strtoul(*arg+1, &end, 10); 105 if (end && *end) errx(1, "Invalid signum"); 106 } else if (!query) { 107 query = *arg; 108 } else { 109 fprintf(stderr, "Usage: %s\n", usage); 110 return 1; 111 } 112 } 113 114 if (!query) { 115 fprintf(stderr, "Usage: %s\n", usage); 116 return 1; 117 } 118 119 cpid = getpid(); 120 121 dir = opendir("/proc"); 122 if (!dir) err(1, "opendir"); 123 124 while ((ent = readdir(dir))) { 125 pid = strtoul(ent->d_name, &end, 10); 126 if (end && *end) continue; 127 if (pid == cpid) continue; 128 129 cmd = readcmd(pid); 130 for (i = 1; i < argc; i++) { 131 if (cmd && strcasestr(cmd, argv[i])) { 132 printf("%u: %s", pid, cmd ? cmd : "???"); 133 killprompt(pid); 134 printf("\n"); 135 break; 136 } 137 } 138 free(cmd); 139 } 140 141 closedir(dir); 142}