diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 75bbebd60fb..c5883b05d1b 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -25,6 +25,7 @@ #include "alloc-util.h" #include "architecture.h" #include "argv-util.h" +#include "dirent-util.h" #include "env-file.h" #include "env-util.h" #include "errno-util.h" @@ -1963,6 +1964,74 @@ fail: return -r; } +int proc_dir_open(DIR **ret) { + DIR *d; + + assert(ret); + + d = opendir("/proc"); + if (!d) + return -errno; + + *ret = d; + return 0; +} + +int proc_dir_read(DIR *d, pid_t *ret) { + assert(d); + + for (;;) { + struct dirent *de; + + errno = 0; + de = readdir_no_dot(d); + if (!de) { + if (errno != 0) + return -errno; + + break; + } + + if (!IN_SET(de->d_type, DT_DIR, DT_UNKNOWN)) + continue; + + if (parse_pid(de->d_name, ret) >= 0) + return 1; + } + + if (ret) + *ret = 0; + return 0; +} + +int proc_dir_read_pidref(DIR *d, PidRef *ret) { + int r; + + assert(d); + + for (;;) { + pid_t pid; + + r = proc_dir_read(d, &pid); + if (r < 0) + return r; + if (r == 0) + break; + + r = pidref_set_pid(ret, pid); + if (r == -ESRCH) /* gone by now? skip it */ + continue; + if (r < 0) + return r; + + return 1; + } + + if (ret) + *ret = PIDREF_NULL; + return 0; +} + static const char *const sigchld_code_table[] = { [CLD_EXITED] = "exited", [CLD_KILLED] = "killed", diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 7c05a69ca09..a18a7309362 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -223,3 +223,7 @@ int is_reaper_process(void); int make_reaper_process(bool b); int posix_spawn_wrapper(const char *path, char *const *argv, char *const *envp, pid_t *ret_pid); + +int proc_dir_open(DIR **ret); +int proc_dir_read(DIR *d, pid_t *ret); +int proc_dir_read_pidref(DIR *d, PidRef *ret);