[PATCH kvm-unit-tests 10/15] lib/argv: introduce setup_env and getenv

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux