static void test_get_process_comm(pid_t pid) { struct stat st; _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL; _cleanup_free_ char *env = NULL; char path[strlen("/proc//comm") + DECIMAL_STR_MAX(pid_t)]; pid_t e; uid_t u; gid_t g; dev_t h; int r; xsprintf(path, "/proc/"PID_FMT"/comm", pid); if (stat(path, &st) == 0) { assert_se(get_process_comm(pid, &a) >= 0); log_info("PID"PID_FMT" comm: '%s'", pid, a); } else log_warning("%s not exist.", path); assert_se(get_process_cmdline(pid, 0, true, &c) >= 0); log_info("PID"PID_FMT" cmdline: '%s'", pid, c); assert_se(get_process_cmdline(pid, 8, false, &d) >= 0); log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d); free(d); assert_se(get_process_cmdline(pid, 1, false, &d) >= 0); log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d); assert_se(get_process_ppid(pid, &e) >= 0); log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e); assert_se(pid == 1 ? e == 0 : e > 0); assert_se(is_kernel_thread(pid) == 0 || pid != 1); r = get_process_exe(pid, &f); assert_se(r >= 0 || r == -EACCES); log_info("PID"PID_FMT" exe: '%s'", pid, strna(f)); assert_se(get_process_uid(pid, &u) == 0); log_info("PID"PID_FMT" UID: "UID_FMT, pid, u); assert_se(u == 0 || pid != 1); assert_se(get_process_gid(pid, &g) == 0); log_info("PID"PID_FMT" GID: "GID_FMT, pid, g); assert_se(g == 0 || pid != 1); r = get_process_environ(pid, &env); assert_se(r >= 0 || r == -EACCES); log_info("PID"PID_FMT" strlen(environ): %zi", pid, env ? (ssize_t)strlen(env) : (ssize_t)-errno); if (!detect_container()) assert_se(get_ctty_devnr(pid, &h) == -ENXIO || pid != 1); getenv_for_pid(pid, "PATH", &i); log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i)); }
static int killall(int sig, Set *pids, bool send_sighup) { _cleanup_closedir_ DIR *dir = NULL; struct dirent *d; dir = opendir("/proc"); if (!dir) return -errno; while ((d = readdir(dir))) { pid_t pid; int r; if (d->d_type != DT_DIR && d->d_type != DT_UNKNOWN) continue; if (parse_pid(d->d_name, &pid) < 0) continue; if (ignore_proc(pid, sig == SIGKILL && !in_initrd())) continue; if (sig == SIGKILL) { _cleanup_free_ char *s = NULL; get_process_comm(pid, &s); log_notice("Sending SIGKILL to PID "PID_FMT" (%s).", pid, strna(s)); } if (kill(pid, sig) >= 0) { if (pids) { r = set_put(pids, PID_TO_PTR(pid)); if (r < 0) log_oom(); } } else if (errno != ENOENT) log_warning_errno(errno, "Could not kill %d: %m", pid); if (send_sighup) { /* Optionally, also send a SIGHUP signal, but only if the process has a controlling tty. This is useful to allow handling of shells which ignore SIGTERM but react to SIGHUP. We do not send this to processes that have no controlling TTY since we don't want to trigger reloads of daemon processes. Also we make sure to only send this after SIGTERM so that SIGTERM is always first in the queue. */ if (get_ctty_devnr(pid, NULL) >= 0) kill(pid, SIGHUP); } } return set_size(pids); }
int get_ctty(pid_t pid, dev_t *_devnr, char **r) { char fn[sizeof("/dev/char/")-1 + 2*DECIMAL_STR_MAX(unsigned) + 1 + 1], *b = NULL; _cleanup_free_ char *s = NULL; const char *p; dev_t devnr; int k; assert(r); k = get_ctty_devnr(pid, &devnr); if (k < 0) return k; sprintf(fn, "/dev/char/%u:%u", major(devnr), minor(devnr)); k = readlink_malloc(fn, &s); if (k < 0) { if (k != -ENOENT) return k; /* This is an ugly hack */ if (major(devnr) == 136) { if (asprintf(&b, "pts/%u", minor(devnr)) < 0) return -ENOMEM; } else { /* Probably something like the ptys which have no * symlink in /dev/char. Let's return something * vaguely useful. */ b = strdup(fn + 5); if (!b) return -ENOMEM; } } else { if (startswith(s, "/dev/")) p = s + 5; else if (startswith(s, "../")) p = s + 3; else p = s; b = strdup(p); if (!b) return -ENOMEM; } *r = b; if (_devnr) *_devnr = devnr; return 0; }
static void test_get_process_comm(void) { struct stat st; _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL, *cwd = NULL, *root = NULL; _cleanup_free_ char *env = NULL; pid_t e; uid_t u; gid_t g; dev_t h; int r; pid_t me; if (stat("/proc/1/comm", &st) == 0) { assert_se(get_process_comm(1, &a) >= 0); log_info("pid1 comm: '%s'", a); } else log_warning("/proc/1/comm does not exist."); assert_se(get_process_cmdline(1, 0, true, &c) >= 0); log_info("pid1 cmdline: '%s'", c); assert_se(get_process_cmdline(1, 8, false, &d) >= 0); log_info("pid1 cmdline truncated: '%s'", d); assert_se(get_process_ppid(1, &e) >= 0); log_info("pid1 ppid: "PID_FMT, e); assert_se(e == 0); assert_se(is_kernel_thread(1) == 0); r = get_process_exe(1, &f); assert_se(r >= 0 || r == -EACCES); log_info("pid1 exe: '%s'", strna(f)); assert_se(get_process_uid(1, &u) == 0); log_info("pid1 uid: "UID_FMT, u); assert_se(u == 0); assert_se(get_process_gid(1, &g) == 0); log_info("pid1 gid: "GID_FMT, g); assert_se(g == 0); me = getpid(); r = get_process_cwd(me, &cwd); assert_se(r >= 0 || r == -EACCES); log_info("pid1 cwd: '%s'", cwd); r = get_process_root(me, &root); assert_se(r >= 0 || r == -EACCES); log_info("pid1 root: '%s'", root); r = get_process_environ(me, &env); assert_se(r >= 0 || r == -EACCES); log_info("self strlen(environ): '%zu'", strlen(env)); if (!detect_container()) assert_se(get_ctty_devnr(1, &h) == -ENXIO); getenv_for_pid(1, "PATH", &i); log_info("pid1 $PATH: '%s'", strna(i)); }