Provide a function that imports an environ (a list of key=value environment variables). The list may be delimited by either '\0' or '\n'. If the list is delimited by '\n', then we assume it's user input and do additional sanity checking, as well as allow variables to be commented out with '#'. We also provide getenv() to lookup the variables. Signed-off-by: Andrew Jones <drjones@xxxxxxxxxx> --- lib/libcflat.h | 1 + lib/argv.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- lib/string.c | 15 ++++++++++ 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/lib/libcflat.h b/lib/libcflat.h index e80fc5071f61..96a37926f302 100644 --- a/lib/libcflat.h +++ b/lib/libcflat.h @@ -85,6 +85,7 @@ extern void puts(const char *s); extern void exit(int code); extern void abort(void); extern long atol(const char *ptr); +extern char *getenv(const char *name); extern int printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); diff --git a/lib/argv.c b/lib/argv.c index fe8826255c18..a37fc8792a92 100644 --- a/lib/argv.c +++ b/lib/argv.c @@ -2,13 +2,18 @@ #include "auxinfo.h" int __argc; -char *__argv[100]; char *__args; +char *__argv[100]; +char *__environ[200]; + +char **environ = __environ; static char args_copy[1000]; static char *copy_ptr = args_copy; #define isblank(c) ((c) == ' ' || (c) == '\t') +#define isalpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z') || (c) == '_') +#define isalnum(c) (isalpha(c) || ((c) >= '0' && (c) <= '9')) static char *skip_blanks(char *p) { @@ -51,3 +56,86 @@ void setup_args_progname(char *args) __setup_args(); } } + +static char *env_eol(char *env) +{ + while (*env && *env != '\n') + ++env; + return env; +} + +static char *env_invalid_eol(char *env) +{ + char *eol = env_eol(env); + char eol_old = *eol; + + *eol = '\0'; + printf("Invalid environment variable: %s\n", env); + *eol = eol_old; + return eol; +} + +static char *env_next(char *env) +{ + char *p; + + if (!*env) + return env; + + if (isalpha(*env)) { + bool invalid = false; + + p = env + 1; + while (*p && *p != '=' && *p != '\n') { + if (!isalnum(*p)) + invalid = true; + ++p; + } + + if (*p != '=') + invalid = true; + + if (invalid) { + env = env_invalid_eol(env); + return *env ? env_next(env + 1) : env; + } + return env; + } + + p = env; + while (isblank(*p)) + ++p; + + if (*p == '\n') + return env_next(p + 1); + + if (*p == '#') + env = env_eol(env); + else + env = env_invalid_eol(env); + + return *env ? env_next(env + 1) : env; +} + +void setup_env(char *env, int size) +{ + char *eof = env + size, *p = env; + bool newline = false; + int i = 0; + + while (*p) + ++p; + if (p == eof) + newline = true; + + while (env < eof) { + if (newline) + env = env_next(env); + if (!*env || env >= eof) + break; + __environ[i++] = env; + while (env < eof && *env && !(newline && *env == '\n')) + ++env; + *env++ = '\0'; + } +} diff --git a/lib/string.c b/lib/string.c index ee93e25e9821..833f22be48c5 100644 --- a/lib/string.c +++ b/lib/string.c @@ -158,3 +158,18 @@ long atol(const char *ptr) return acc; } + +extern char **environ; + +char *getenv(const char *name) +{ + char **envp = environ, *delim; + + while (*envp) { + delim = strchr(*envp, '='); + if (delim && strncmp(name, *envp, delim - *envp) == 0) + return delim + 1; + ++envp; + } + return NULL; +} -- 2.9.3 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html