[systemd-devel] [PATCH 3/4] util: add function getting proc environ
Jakub Filak
jfilak at redhat.com
Wed Nov 19 02:01:21 PST 2014
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
More information about the systemd-devel
mailing list