util: add function getting proc environ
On the contrary of env, the added function returns all characters cescaped, because it improves reproducibility.
This commit is contained in:
parent
59580681f5
commit
c593bb360e
|
@ -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;
|
||||
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue