summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/shared/util.c154
-rw-r--r--src/shared/util.h1
-rw-r--r--src/test/test-util.c5
3 files changed, 103 insertions, 57 deletions
diff --git a/src/shared/util.c b/src/shared/util.c
index b1ba0ed857..e987abc423 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);
@@ -892,6 +955,39 @@ int get_process_root(pid_t pid, char **root) {
return get_process_link_contents(p, root);
}
+int get_process_environ(pid_t pid, char **environ) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *outcome = NULL;
+ int c;
+ const char *p;
+ size_t allocated = 0, sz = 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 (!GREEDY_REALLOC(outcome, allocated, sz + 5))
+ return -ENOMEM;
+
+ if (c == '\0')
+ outcome[sz++] = '\n';
+ else
+ sz += cescape_char(c, outcome + sz);
+ }
+
+ 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;
@@ -1271,63 +1367,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 13a0b968d3..d36a632785 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -297,6 +297,7 @@ int get_process_gid(pid_t pid, gid_t *gid);
int get_process_capeff(pid_t pid, char **capeff);
int get_process_cwd(pid_t pid, char **cwd);
int get_process_root(pid_t pid, char **root);
+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 b33e15aef0..1602aa6393 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -491,6 +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 *env = NULL;
unsigned long long b;
pid_t e;
uid_t u;
@@ -543,6 +544,10 @@ static void test_get_process_comm(void) {
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): '%zd'", strlen(env));
+
assert_se(get_ctty_devnr(1, &h) == -ENOENT);
getenv_for_pid(1, "PATH", &i);