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