From afe0c36d832df68c19373b2a99abba4fc840f0e1 Mon Sep 17 00:00:00 2001 From: Martin Kutlak Date: Tue, 21 May 2019 10:42:53 +0200 Subject: [PATCH] lib: add get env variable from a file Introduced a new argument called 'delim' because /proc/PID/environ is delimited with 0 but FILENAME_ENVIRON is escaped version of that file with '\0's replaced by '\n'. While /proc/PID/environ entries are always delimted by '\0' (even the last one), other files might not use this style and the function must handle EOF without the entry delimiter. Cherry-picked from https://github.com/abrt/libreport/commit/a71e4149c85212c72af0cc67c5b99a5029491ed2 --- src/include/internal_libreport.h | 2 ++ src/lib/get_cmdline.c | 38 ++++++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/include/internal_libreport.h b/src/include/internal_libreport.h index d7bab4e..fc0242c 100644 --- a/src/include/internal_libreport.h +++ b/src/include/internal_libreport.h @@ -638,6 +638,8 @@ struct strbuf *strbuf_prepend_strfv(struct strbuf *strbuf, char* get_cmdline(pid_t pid); #define get_environ libreport_get_environ char* get_environ(pid_t pid); +#define get_env_variable_ext libreport_get_env_variable_ext +int get_env_variable_ext(int fd, char delim, const char *name, char **value); #define get_env_variable libreport_get_env_variable int get_env_variable(pid_t pid, const char *name, char **value); diff --git a/src/lib/get_cmdline.c b/src/lib/get_cmdline.c index 0fc0cbf..9e83994 100644 --- a/src/lib/get_cmdline.c +++ b/src/lib/get_cmdline.c @@ -149,15 +149,20 @@ char* get_environ(pid_t pid) return get_escaped(path, '\n'); } -int get_env_variable(pid_t pid, const char *name, char **value) +int get_env_variable_ext(int fd, char delim, const char *name, char **value) { - char path[sizeof("/proc/%lu/environ") + sizeof(long)*3]; - snprintf(path, sizeof(path), "/proc/%lu/environ", (long)pid); + int workfd = dup(fd); + if (workfd < 0) + { + perror_msg("dup()"); + return -errno; + } - FILE *fenv = fopen(path, "re"); + FILE *fenv = fdopen(workfd, "re"); if (fenv == NULL) { - pwarn_msg("Failed to open environ file"); + close(workfd); + perror_msg("fdopen()"); return -errno; } @@ -177,17 +182,18 @@ int get_env_variable(pid_t pid, const char *name, char **value) i = 0; /* Read to the end of variable entry */ - while ((c = fgetc(fenv)) != EOF && c !='\0') + while ((c = fgetc(fenv)) != EOF && c != delim) ++i; /* Go to the next entry if the read entry isn't the searched variable */ if (skip) continue; + const int eof = c != EOF; *value = xmalloc(i+1); /* i+1 because we didn't count '\0' */ - if (fseek(fenv, -(i+1), SEEK_CUR) < 0) + if (fseek(fenv, -(i+eof), SEEK_CUR) < 0) error_msg_and_die("Failed to seek"); if (fread(*value, 1, i, fenv) != i) @@ -201,3 +207,21 @@ int get_env_variable(pid_t pid, const char *name, char **value) fclose(fenv); return 0; } + +int get_env_variable(pid_t pid, const char *name, char **value) +{ + char path[sizeof("/proc/%lu/environ") + sizeof(long)*3]; + snprintf(path, sizeof(path), "/proc/%lu/environ", (long)pid); + + const int envfd = open(path, O_RDONLY); + if (envfd < 0) + { + pwarn_msg("Failed to open environ file"); + return -errno; + } + + const int r = get_env_variable_ext(envfd, '\0', name, value); + close(envfd); + + return r; +} -- 2.21.0