X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fbasic%2Fprocess-util.c;h=94ca0401d097e0e22970b8957d39df081936efef;hp=9e7ddca91e75b355dd43feba1e711072f033440d;hb=eaca07ccfdf5d7dabc50afc7e539c2413dd69d3e;hpb=1cfc78c91965df340cdde100ad6cb3ed50b28927 diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 9e7ddca91..94ca0401d 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -17,22 +17,33 @@ along with systemd; If not, see . ***/ -#include -#include -#include -#include #include +#include #include -#include -#include +#include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "alloc-util.h" +#include "escape.h" +#include "fd-util.h" #include "fileio.h" -#include "util.h" +#include "fs-util.h" +//#include "ioprio.h" #include "log.h" -#include "signal-util.h" #include "process-util.h" +#include "signal-util.h" +#include "string-table.h" +#include "string-util.h" +#include "user-util.h" +#include "util.h" int get_process_state(pid_t pid) { const char *p; @@ -43,7 +54,10 @@ int get_process_state(pid_t pid) { assert(pid >= 0); p = procfs_file_alloca(pid, "stat"); + r = read_one_line_file(p, &line); + if (r == -ENOENT) + return -ESRCH; if (r < 0) return r; @@ -87,8 +101,11 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * p = procfs_file_alloca(pid, "cmdline"); f = fopen(p, "re"); - if (!f) + if (!f) { + if (errno == ENOENT) + return -ESRCH; return -errno; + } if (max_length == 0) { size_t len = 0, allocated = 0; @@ -168,6 +185,40 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * return 0; } +/// UNNEEDED by elogind +#if 0 +void rename_process(const char name[8]) { + assert(name); + + /* This is a like a poor man's setproctitle(). It changes the + * comm field, argv[0], and also the glibc's internally used + * name of the process. For the first one a limit of 16 chars + * applies, to the second one usually one of 10 (i.e. length + * of "/sbin/init"), to the third one one of 7 (i.e. length of + * "systemd"). If you pass a longer string it will be + * truncated */ + + prctl(PR_SET_NAME, name); + + if (program_invocation_name) + strncpy(program_invocation_name, name, strlen(program_invocation_name)); + + if (saved_argc > 0) { + int i; + + if (saved_argv[0]) + strncpy(saved_argv[0], name, strlen(saved_argv[0])); + + for (i = 1; i < saved_argc; i++) { + if (!saved_argv[i]) + break; + + memzero(saved_argv[i], strlen(saved_argv[i])); + } + } +} +#endif // 0 + int is_kernel_thread(pid_t pid) { const char *p; size_t count; @@ -175,15 +226,18 @@ int is_kernel_thread(pid_t pid) { bool eof; FILE *f; - if (pid == 0) + if (pid == 0 || pid == 1) /* pid 1, and we ourselves certainly aren't a kernel thread */ return 0; - assert(pid > 0); + assert(pid > 1); p = procfs_file_alloca(pid, "cmdline"); f = fopen(p, "re"); - if (!f) + if (!f) { + if (errno == ENOENT) + return -ESRCH; return -errno; + } count = fread(&c, 1, 1, f); eof = feof(f); @@ -201,13 +255,18 @@ int is_kernel_thread(pid_t pid) { #if 0 int get_process_capeff(pid_t pid, char **capeff) { const char *p; + int r; assert(capeff); assert(pid >= 0); p = procfs_file_alloca(pid, "status"); - return get_status_field(p, "\nCapEff:", capeff); + r = get_proc_field(p, "CapEff", WHITESPACE, capeff); + if (r == -ENOENT) + return -ESRCH; + + return r; } #endif // 0 @@ -218,8 +277,10 @@ static int get_process_link_contents(const char *proc_file, char **name) { assert(name); r = readlink_malloc(proc_file, name); + if (r == -ENOENT) + return -ESRCH; if (r < 0) - return r == -ENOENT ? -ESRCH : r; + return r; return 0; } @@ -243,6 +304,8 @@ int get_process_exe(pid_t pid, char **name) { return 0; } +/// UNNEEDED by elogind +#if 0 static int get_process_id(pid_t pid, const char *field, uid_t *uid) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; @@ -256,8 +319,11 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) { p = procfs_file_alloca(pid, "status"); f = fopen(p, "re"); - if (!f) + if (!f) { + if (errno == ENOENT) + return -ESRCH; return -errno; + } FOREACH_LINE(line, f, return -errno) { char *l; @@ -281,8 +347,6 @@ int get_process_uid(pid_t pid, uid_t *uid) { return get_process_id(pid, "Uid:", uid); } -/// UNNEEDED by elogind -#if 0 int get_process_gid(pid_t pid, gid_t *gid) { assert_cc(sizeof(uid_t) == sizeof(gid_t)); return get_process_id(pid, "Gid:", gid); @@ -321,8 +385,11 @@ int get_process_environ(pid_t pid, char **env) { p = procfs_file_alloca(pid, "environ"); f = fopen(p, "re"); - if (!f) + if (!f) { + if (errno == ENOENT) + return -ESRCH; return -errno; + } while ((c = fgetc(f)) != EOF) { if (!GREEDY_REALLOC(outcome, allocated, sz + 5)) @@ -334,15 +401,20 @@ int get_process_environ(pid_t pid, char **env) { sz += cescape_char(c, outcome + sz); } + if (!outcome) { + outcome = strdup(""); + if (!outcome) + return -ENOMEM; + } else outcome[sz] = '\0'; + *env = outcome; outcome = NULL; return 0; } -#endif // 0 -int get_parent_of_pid(pid_t pid, pid_t *_ppid) { +int get_process_ppid(pid_t pid, pid_t *_ppid) { int r; _cleanup_free_ char *line = NULL; long unsigned ppid; @@ -358,6 +430,8 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) { p = procfs_file_alloca(pid, "stat"); r = read_one_line_file(p, &line); + if (r == -ENOENT) + return -ESRCH; if (r < 0) return r; @@ -384,6 +458,7 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) { return 0; } +#endif // 0 int wait_for_terminate(pid_t pid, siginfo_t *status) { siginfo_t dummy; @@ -452,6 +527,18 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_cod return -EPROTO; } +void sigkill_wait(pid_t *pid) { + if (!pid) + return; + if (*pid <= 1) + return; + + if (kill(*pid, SIGKILL) > 0) + (void) wait_for_terminate(*pid, NULL); +} + +/// UNNEEDED by elogind +#if 0 int kill_and_sigcont(pid_t pid, int sig) { int r; @@ -462,6 +549,7 @@ int kill_and_sigcont(pid_t pid, int sig) { return r; } +#endif // 0 int getenv_for_pid(pid_t pid, const char *field, char **_value) { _cleanup_fclose_ FILE *f = NULL; @@ -478,8 +566,11 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) { path = procfs_file_alloca(pid, "environ"); f = fopen(path, "re"); - if (!f) + if (!f) { + if (errno == ENOENT) + return -ESRCH; return -errno; + } l = strlen(field); r = 0; @@ -520,9 +611,12 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) { bool pid_is_unwaited(pid_t pid) { /* Checks whether a PID is still valid at all, including a zombie */ - if (pid <= 0) + if (pid < 0) return false; + if (pid <= 1) /* If we or PID 1 would be dead and have been waited for, this code would not be running */ + return true; + if (kill(pid, 0) >= 0) return true; @@ -534,12 +628,144 @@ bool pid_is_alive(pid_t pid) { /* Checks whether a PID is still valid and not a zombie */ - if (pid <= 0) + if (pid < 0) return false; + if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */ + return true; + r = get_process_state(pid); - if (r == -ENOENT || r == 'Z') + if (r == -ESRCH || r == 'Z') return false; return true; } + +bool is_main_thread(void) { + static thread_local int cached = 0; + + if (_unlikely_(cached == 0)) + cached = getpid() == gettid() ? 1 : -1; + + return cached > 0; +} + +/// UNNEEDED by elogind +#if 0 +noreturn void freeze(void) { + + /* Make sure nobody waits for us on a socket anymore */ + close_all_fds(NULL, 0); + + sync(); + + for (;;) + pause(); +} + +bool oom_score_adjust_is_valid(int oa) { + return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX; +} + +unsigned long personality_from_string(const char *p) { + + /* Parse a personality specifier. We introduce our own + * identifiers that indicate specific ABIs, rather than just + * hints regarding the register size, since we want to keep + * things open for multiple locally supported ABIs for the + * same register size. We try to reuse the ABI identifiers + * used by libseccomp. */ + +#if defined(__x86_64__) + + if (streq(p, "x86")) + return PER_LINUX32; + + if (streq(p, "x86-64")) + return PER_LINUX; + +#elif defined(__i386__) + + if (streq(p, "x86")) + return PER_LINUX; + +#elif defined(__s390x__) + + if (streq(p, "s390")) + return PER_LINUX32; + + if (streq(p, "s390x")) + return PER_LINUX; + +#elif defined(__s390__) + + if (streq(p, "s390")) + return PER_LINUX; +#endif + + return PERSONALITY_INVALID; +} + +const char* personality_to_string(unsigned long p) { + +#if defined(__x86_64__) + + if (p == PER_LINUX32) + return "x86"; + + if (p == PER_LINUX) + return "x86-64"; + +#elif defined(__i386__) + + if (p == PER_LINUX) + return "x86"; + +#elif defined(__s390x__) + + if (p == PER_LINUX) + return "s390x"; + + if (p == PER_LINUX32) + return "s390"; + +#elif defined(__s390__) + + if (p == PER_LINUX) + return "s390"; + +#endif + + return NULL; +} + +static const char *const ioprio_class_table[] = { + [IOPRIO_CLASS_NONE] = "none", + [IOPRIO_CLASS_RT] = "realtime", + [IOPRIO_CLASS_BE] = "best-effort", + [IOPRIO_CLASS_IDLE] = "idle" +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX); + +static const char *const sigchld_code_table[] = { + [CLD_EXITED] = "exited", + [CLD_KILLED] = "killed", + [CLD_DUMPED] = "dumped", + [CLD_TRAPPED] = "trapped", + [CLD_STOPPED] = "stopped", + [CLD_CONTINUED] = "continued", +}; + +DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int); + +static const char* const sched_policy_table[] = { + [SCHED_OTHER] = "other", + [SCHED_BATCH] = "batch", + [SCHED_IDLE] = "idle", + [SCHED_FIFO] = "fifo", + [SCHED_RR] = "rr" +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX); +#endif // 0