On the contrary of env, the added function returns all characters cescaped, because it improves reproducibility. --- src/shared/util.c | 160 +++++++++++++++++++++++++++++++++------------------ src/shared/util.h | 1 + src/test/test-util.c | 6 +- 3 files changed, 109 insertions(+), 58 deletions(-)
diff --git a/src/shared/util.c b/src/shared/util.c index d62d90c..448efa5 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -174,6 +174,69 @@ char* first_word(const char *s, const char *word) { return (char*) p; } +static size_t cescape_char(char c, char *buf) { + char * buf_old = buf; + + switch (c) { + + case '\a': + *(buf++) = '\\'; + *(buf++) = 'a'; + break; + case '\b': + *(buf++) = '\\'; + *(buf++) = 'b'; + break; + case '\f': + *(buf++) = '\\'; + *(buf++) = 'f'; + break; + case '\n': + *(buf++) = '\\'; + *(buf++) = 'n'; + break; + case '\r': + *(buf++) = '\\'; + *(buf++) = 'r'; + break; + case '\t': + *(buf++) = '\\'; + *(buf++) = 't'; + break; + case '\v': + *(buf++) = '\\'; + *(buf++) = 'v'; + break; + case '\\': + *(buf++) = '\\'; + *(buf++) = '\\'; + break; + case '"': + *(buf++) = '\\'; + *(buf++) = '"'; + break; + case '\'': + *(buf++) = '\\'; + *(buf++) = '\''; + break; + + default: + /* For special chars we prefer octal over + * hexadecimal encoding, simply because glib's + * g_strescape() does the same */ + if ((c < ' ') || (c >= 127)) { + *(buf++) = '\\'; + *(buf++) = octchar((unsigned char) c >> 6); + *(buf++) = octchar((unsigned char) c >> 3); + *(buf++) = octchar((unsigned char) c); + } else + *(buf++) = c; + break; + } + + return buf - buf_old; +} + int close_nointr(int fd) { assert(fd >= 0); @@ -905,6 +968,45 @@ DEFINE_FN_GET_PROCESS_FULL_FILE(maps) DEFINE_FN_GET_PROCESS_FULL_FILE(limits) DEFINE_FN_GET_PROCESS_FULL_FILE(cgroup) +int get_process_environ(pid_t pid, char **environ) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *outcome = NULL; + int c; + const char *p; + char escaped[4]; + size_t allocated = 0, sz = 0, escaped_len = 0; + + assert(pid >= 0); + assert(environ); + + p = procfs_file_alloca(pid, "environ"); + + f = fopen(p, "re"); + if (!f) + return -errno; + + while ((c = fgetc(f)) != EOF) { + if (c == '\0') { + escaped[0] = '\n'; + escaped_len = 1; + } + else + escaped_len = cescape_char(c, escaped); + + if (!GREEDY_REALLOC(outcome, allocated, sz + escaped_len + 1)) + return -ENOMEM; + + memcpy(outcome + sz, escaped, escaped_len); + sz += escaped_len; + } + + outcome[sz] = '\0'; + *environ = outcome; + outcome = NULL; + + return 0; +} + char *strnappend(const char *s, const char *suffix, size_t b) { size_t a; char *r; @@ -1284,63 +1386,7 @@ char *cescape(const char *s) { return NULL; for (f = s, t = r; *f; f++) - - switch (*f) { - - case '\a': - *(t++) = '\\'; - *(t++) = 'a'; - break; - case '\b': - *(t++) = '\\'; - *(t++) = 'b'; - break; - case '\f': - *(t++) = '\\'; - *(t++) = 'f'; - break; - case '\n': - *(t++) = '\\'; - *(t++) = 'n'; - break; - case '\r': - *(t++) = '\\'; - *(t++) = 'r'; - break; - case '\t': - *(t++) = '\\'; - *(t++) = 't'; - break; - case '\v': - *(t++) = '\\'; - *(t++) = 'v'; - break; - case '\\': - *(t++) = '\\'; - *(t++) = '\\'; - break; - case '"': - *(t++) = '\\'; - *(t++) = '"'; - break; - case '\'': - *(t++) = '\\'; - *(t++) = '\''; - break; - - default: - /* For special chars we prefer octal over - * hexadecimal encoding, simply because glib's - * g_strescape() does the same */ - if ((*f < ' ') || (*f >= 127)) { - *(t++) = '\\'; - *(t++) = octchar((unsigned char) *f >> 6); - *(t++) = octchar((unsigned char) *f >> 3); - *(t++) = octchar((unsigned char) *f); - } else - *(t++) = *f; - break; - } + t += cescape_char(*f, t); *t = 0; diff --git a/src/shared/util.h b/src/shared/util.h index 2c9e4fe..0b245bb 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -301,6 +301,7 @@ int get_process_status(pid_t pid, char **status); int get_process_maps(pid_t pid, char **maps); int get_process_limits(pid_t pid, char **limits); int get_process_cgroup(pid_t pid, char **cgroup); +int get_process_environ(pid_t pid, char **environ); char hexchar(int x) _const_; int unhexchar(char c) _const_; diff --git a/src/test/test-util.c b/src/test/test-util.c index f7c0210..c4176a8 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -491,7 +491,7 @@ static void test_u64log2(void) { 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 *s = NULL, *l = NULL, *m = NULL, *cg = NULL; + _cleanup_free_ char *s = NULL, *l = NULL, *m = NULL, *cg = NULL, *env = NULL; unsigned long long b; pid_t e; uid_t u; @@ -560,6 +560,10 @@ static void test_get_process_comm(void) { assert_se(r >= 0 || r == -EACCES); log_info("pid1 strlen(cgroup): '%zd'", strlen(cg)); + r = get_process_environ(me, &env); + assert_se(r >= 0 || r == -EACCES); + log_info("pid1 strlen(environ): '%zd'", strlen(env)); + assert_se(get_ctty_devnr(1, &h) == -ENOENT); getenv_for_pid(1, "PATH", &i); -- 1.8.3.1 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel