aboutsummaryrefslogtreecommitdiff
path: root/src/rc/kill_all.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rc/kill_all.c')
-rw-r--r--src/rc/kill_all.c260
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;
-}