diff options
Diffstat (limited to 'src/rc/kill_all.c')
-rw-r--r-- | src/rc/kill_all.c | 260 |
1 files changed, 0 insertions, 260 deletions
diff --git a/src/rc/kill_all.c b/src/rc/kill_all.c deleted file mode 100644 index 551572b7..00000000 --- a/src/rc/kill_all.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * kill_all.c - * Sends a signal to all processes on the system. - */ - -/* - * Copyright (c) 2017 The OpenRC Authors. - * See the Authors file at the top-level directory of this distribution and - * https://github.com/OpenRC/openrc/blob/HEAD/AUTHORS - * - * This file is part of OpenRC. It is subject to the license terms in - * the LICENSE file found in the top-level directory of this - * distribution and at https://github.com/OpenRC/openrc/blob/HEAD/LICENSE - * This file may not be copied, modified, propagated, or distributed - * except according to the terms contained in the LICENSE file. - */ - - -#include <dirent.h> -#include <errno.h> -#include <getopt.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/wait.h> - -#include "einfo.h" -#include "rc.h" -#include "rc-misc.h" -#include "_usage.h" - -const char *applet = NULL; -const char *extraopts = "[signal number]"; -const char getoptstring[] = "do:" getoptstring_COMMON; -const struct option longopts[] = { - { "dry-run", 0, NULL, 'd' }, - { "omit", 1, NULL, 'o' }, - longopts_COMMON -}; -const char * const longopts_help[] = { - "print what would be done", - "omit this pid (can be repeated)", - longopts_help_COMMON -}; -const char *usagestring = NULL; - -static int mount_proc(void) -{ - pid_t pid; - pid_t rc; - int status; - - if (exists("/proc/version")) - return 0; - pid = fork(); - switch (pid) { - case -1: - syslog(LOG_ERR, "Unable to fork"); - return -1; - break; - case 0: - /* attempt to mount /proc */ - execlp("mount", "mount", "-t", "proc", "proc", "/proc", NULL); - syslog(LOG_ERR, "Unable to execute mount"); - exit(1); - break; - default: - /* wait for child process */ - while ((rc = wait(&status)) != pid) - if (rc < 0 && errno == ECHILD) - break; - if (rc != pid || WEXITSTATUS(status) != 0) - syslog(LOG_ERR, "mount returned non-zero exit status"); - break; - } - if (!exists("/proc/version")) { - syslog(LOG_ERR, "Could not mount /proc"); - return -1; - } - return 0; -} - -static bool is_user_process(pid_t pid) -{ - char *buf = NULL; - FILE *fp; - char *path = NULL; - pid_t temp_pid; - size_t size; - bool user_process = true; - - while (pid >0 && user_process) { - if (pid == 2) { - user_process = false; - continue; - } - xasprintf(&path, "/proc/%d/status", pid); - fp = fopen(path, "r"); - free(path); - /* - * if we could not open the file, the process disappeared, which - * leaves us no way to determine for sure whether it was a user - * process or kernel thread, so we say it is a kernel thread to - * avoid accidentally killing it. - */ - if (!fp) { - user_process = false; - continue; - } - temp_pid = -1; - while (!feof(fp)) { - buf = NULL; - if (getline(&buf, &size, fp) != -1) { - sscanf(buf, "PPid: %d", &temp_pid); - free(buf); - } else { - free(buf); - break; - } - } - fclose(fp); - if (temp_pid == -1) { - syslog(LOG_ERR, "Unable to read pid from /proc/%d/status", pid); - user_process = false; - continue; - } - pid = temp_pid; - } - return user_process; -} - -static int signal_processes(int sig, RC_STRINGLIST *omits, bool dryrun) -{ - sigset_t signals; - sigset_t oldsigs; - DIR *dir; - struct dirent *d; - char *buf = NULL; - pid_t pid; - int sendcount = 0; - - kill(-1, SIGSTOP); - sigfillset(&signals); - sigemptyset(&oldsigs); - sigprocmask(SIG_SETMASK, &signals, &oldsigs); - /* - * Open the /proc directory. - * CWD must be /proc to avoid problems if / is affected by the killing - * (i.e. depends on fuse). - */ - if (chdir("/proc") == -1) { - syslog(LOG_ERR, "chdir /proc failed"); - sigprocmask(SIG_SETMASK, &oldsigs, NULL); - kill(-1, SIGCONT); - return -1; - } - dir = opendir("."); - if (!dir) { - syslog(LOG_ERR, "cannot opendir(/proc)"); - sigprocmask(SIG_SETMASK, &oldsigs, NULL); - kill(-1, SIGCONT); - return -1; - } - - /* Walk through the directory. */ - while ((d = readdir(dir)) != NULL) { - /* Is this a process? */ - pid = (pid_t) atoi(d->d_name); - if (pid == 0) - continue; - - /* Is this a process we have been requested to omit? */ - if (buf) { - free(buf); - buf = NULL; - } - xasprintf(&buf, "%d", pid); - if (rc_stringlist_find(omits, buf)) - continue; - - /* Is this process in our session? */ - if (getsid(getpid()) == getsid(pid)) - continue; - - /* Is this a kernel thread? */ - if (!is_user_process(pid)) - continue; - - if (dryrun) - einfo("Would send signal %d to process %d", sig, pid); - else if (kill(pid, sig) == 0) - sendcount++; - } - closedir(dir); - sigprocmask(SIG_SETMASK, &oldsigs, NULL); - kill(-1, SIGCONT); - return sendcount; -} - -int main(int argc, char **argv) -{ - char *arg = NULL; - int opt; - bool dryrun = false; - RC_STRINGLIST *omits = rc_stringlist_new(); - int sig = SIGKILL; - char *here; - char *token; - - /* Ensure that we are only quiet when explicitly told to be */ - unsetenv("EINFO_QUIET"); - - applet = basename_c(argv[0]); - rc_stringlist_addu(omits, "1"); - while ((opt = getopt_long(argc, argv, getoptstring, - longopts, (int *) 0)) != -1) - { - switch (opt) { - case 'd': - dryrun = true; - break; - case 'o': - here = optarg; - while ((token = strsep(&here, ",;:"))) { - if ((pid_t) atoi(token) > 0) - rc_stringlist_addu(omits, token); - else { - eerror("Invalid omit pid value %s", token); - usage(EXIT_FAILURE); - } - } - break; - case_RC_COMMON_GETOPT - } - } - - if (argc > optind) { - arg = argv[optind]; - sig = atoi(arg); - if (sig <= 0 || sig > 31) { - rc_stringlist_free(omits); - eerror("Invalid signal %s", arg); - usage(EXIT_FAILURE); - } - } - - openlog(applet, LOG_CONS|LOG_PID, LOG_DAEMON); - if (mount_proc() != 0) { - rc_stringlist_free(omits); - eerrorx("Unable to mount /proc file system"); - } - signal_processes(sig, omits, dryrun); - rc_stringlist_free(omits); - return 0; -} |