From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andrew Jones Subject: [PATCH kvm-unit-tests 10/15] lib/argv: introduce setup_env and getenv Date: Fri, 13 Jan 2017 19:15:28 +0100 Message-ID: <20170113181533.15145-11-drjones@redhat.com> References: <20170113181533.15145-1-drjones@redhat.com> Cc: rkrcmar@redhat.com, pbonzini@redhat.com, lvivier@redhat.com, thuth@redhat.com To: kvm@vger.kernel.org Return-path: Received: from mx1.redhat.com ([209.132.183.28]:58294 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751111AbdAMSPw (ORCPT ); Fri, 13 Jan 2017 13:15:52 -0500 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EC64C61B96 for ; Fri, 13 Jan 2017 18:15:52 +0000 (UTC) In-Reply-To: <20170113181533.15145-1-drjones@redhat.com> Sender: kvm-owner@vger.kernel.org List-ID: 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 --- 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