diff options
Diffstat (limited to 'chproc.c')
-rw-r--r-- | chproc.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/chproc.c b/chproc.c new file mode 100644 index 0000000..6d407fb --- /dev/null +++ b/chproc.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * chproc.c - simple process checker + * + * Iterate over /proc and print PIDs of processes matching the given name. + */ + +#include <stdio.h> +#include <sys/types.h> +#include <dirent.h> +#include <ctype.h> +#include <sys/stat.h> +#include <unistd.h> +#include <limits.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <getopt.h> +#include <signal.h> +#include <stdbool.h> + +#define PROGRAM_NAME "chproc" + +struct options { + int list; + int kill; + char *process_name; + char *process_pid; +}; + + +static void options_init(struct options *x) +{ + x->list = false; + x->kill = false; + x->process_pid = NULL; + x->process_name = NULL; +} + + +static void usage(void) +{ + fprintf(stderr, + "Usage: %s <option> [process_name, pid]\n" + " -l, --list <name> list all PID of that process\n" + " -k, --kill <PID> kill a proces give then PID\n" + , PROGRAM_NAME); +} + + + +static int process_list(DIR *dir, + const char *proc_name) +{ + char path[PATH_MAX]; + char buffer[256]; + char *endptr; + FILE *f; + int count; + long pid; + struct dirent *entry; + size_t len; + + count = 0; + + while ((entry = readdir(dir)) != NULL) { + /* skip "." and ".." */ + if (strcmp(entry->d_name, ".") == 0) + continue; + if (strcmp(entry->d_name, "..") == 0) + continue; + + + pid = strtol(entry->d_name, &endptr, 10); + + if (*endptr != '\0') /* not a pure number */ + continue; + + snprintf(path, sizeof(path), "/proc/%ld/comm", pid); + + f = fopen(path, "r"); + + if (!f) { + fprintf(stderr, "Failed to open %s: %s\n", + path, strerror(errno)); + continue; + } + + if (fgets(buffer, sizeof(buffer), f)) { + len = strlen(buffer); + + if (len > 0 && buffer[len-1] == '\n') + buffer[len-1] = '\0'; + + if (strcmp(buffer, proc_name) == 0) { + printf("%s - %s\n", entry->d_name, buffer); + ++count; + } + } + fclose(f); + } + + closedir(dir); + + if (count == 0) + return 1; + else + return 0; +} + + +static int process_kill(const char *process_id) +{ + pid_t pid; + + if (atoi(process_id) < 1) { + fprintf(stderr, "'%s': not a pid or valid job\n", process_id); + usage(); + return 1; + } + + pid = (pid_t) atoi(process_id); + + if (kill(pid, SIGTERM) == -1) { + perror("kill failed"); + return 1; + } + + printf("Process '%d' killed.\n", pid); + return 0; +} + + +int main(int argc, char *argv[]) +{ + int opt; + DIR *dir_proc; + + struct options x; + + struct option long_options[] = { + {"list", required_argument, 0, 'l'}, + {"kill", required_argument, 0, 'k'}, + {0, 0, 0, 0} + }; + + options_init(&x); + + /* /proc/ must to exist */ + dir_proc = opendir("/proc"); + if (dir_proc == NULL) { + fprintf(stderr, "/proc/ not found.\n"); + return EXIT_FAILURE; + } + + if (argc < 3) { + usage(); + return 2; + } + + while ((opt = getopt_long(argc, argv, "l:k:", + long_options, NULL)) != -1) { + switch (opt) { + case 'l': + x.list = true; + x.process_name = optarg; + break; + case 'k': + x.kill = true; + x.process_pid = optarg; + break; + default: + fprintf(stderr, + "Unknow option.\n"); + usage(); + exit(2); + } + } + + if (x.list) + if (process_list(dir_proc, x.process_name) == 1) + return 1; + + if (x.kill) + if (process_kill(x.process_pid) == 1) + return 1; + + return 0; +} + + + |