From: Blue Swirl Date: Sat, 15 Aug 2009 08:47:42 +0000 (+0000) Subject: linux-user: compile envlist.c only once X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=6af5a2524646ddc027114d80912cdd8ee0b7c7c8;p=qemu.git linux-user: compile envlist.c only once Signed-off-by: Blue Swirl --- diff --git a/Makefile b/Makefile index 343798988b..912284a708 100644 --- a/Makefile +++ b/Makefile @@ -162,7 +162,7 @@ libqemu_common.a: $(obj-y) ####################################################################### # user-obj-y is code used by qemu userspace emulation -user-obj-y = cutils.o cache-utils.o path.o +user-obj-y = cutils.o cache-utils.o path.o envlist.o libqemu_user.a: $(user-obj-y) diff --git a/Makefile.target b/Makefile.target index 74f869db48..1e91cf2d8f 100644 --- a/Makefile.target +++ b/Makefile.target @@ -87,7 +87,7 @@ VPATH+=:$(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) obj-y = main.o syscall.o strace.o mmap.o signal.o thunk.o \ - elfload.o linuxload.o uaccess.o envlist.o gdbstub.o gdbstub-xml.o + elfload.o linuxload.o uaccess.o gdbstub.o gdbstub-xml.o obj-$(TARGET_HAS_BFLT) += flatload.o obj-$(TARGET_HAS_ELFLOAD32) += elfload32.o diff --git a/envlist.c b/envlist.c new file mode 100644 index 0000000000..e13c2d3e14 --- /dev/null +++ b/envlist.c @@ -0,0 +1,247 @@ +#include + +#include +#include +#include +#include +#include + +#include "envlist.h" + +struct envlist_entry { + const char *ev_var; /* actual env value */ + LIST_ENTRY(envlist_entry) ev_link; +}; + +struct envlist { + LIST_HEAD(, envlist_entry) el_entries; /* actual entries */ + size_t el_count; /* number of entries */ +}; + +static int envlist_parse(envlist_t *envlist, + const char *env, int (*)(envlist_t *, const char *)); + +/* + * Allocates new envlist and returns pointer to that or + * NULL in case of error. + */ +envlist_t * +envlist_create(void) +{ + envlist_t *envlist; + + if ((envlist = malloc(sizeof (*envlist))) == NULL) + return (NULL); + + LIST_INIT(&envlist->el_entries); + envlist->el_count = 0; + + return (envlist); +} + +/* + * Releases given envlist and its entries. + */ +void +envlist_free(envlist_t *envlist) +{ + struct envlist_entry *entry; + + assert(envlist != NULL); + + while (envlist->el_entries.lh_first != NULL) { + entry = envlist->el_entries.lh_first; + LIST_REMOVE(entry, ev_link); + + free((char *)entry->ev_var); + free(entry); + } + free(envlist); +} + +/* + * Parses comma separated list of set/modify environment + * variable entries and updates given enlist accordingly. + * + * For example: + * envlist_parse(el, "HOME=foo,SHELL=/bin/sh"); + * + * inserts/sets environment variables HOME and SHELL. + * + * Returns 0 on success, errno otherwise. + */ +int +envlist_parse_set(envlist_t *envlist, const char *env) +{ + return (envlist_parse(envlist, env, &envlist_setenv)); +} + +/* + * Parses comma separated list of unset environment variable + * entries and removes given variables from given envlist. + * + * Returns 0 on success, errno otherwise. + */ +int +envlist_parse_unset(envlist_t *envlist, const char *env) +{ + return (envlist_parse(envlist, env, &envlist_unsetenv)); +} + +/* + * Parses comma separated list of set, modify or unset entries + * and calls given callback for each entry. + * + * Returns 0 in case of success, errno otherwise. + */ +static int +envlist_parse(envlist_t *envlist, const char *env, + int (*callback)(envlist_t *, const char *)) +{ + char *tmpenv, *envvar; + char *envsave = NULL; + + assert(callback != NULL); + + if ((envlist == NULL) || (env == NULL)) + return (EINVAL); + + /* + * We need to make temporary copy of the env string + * as strtok_r(3) modifies it while it tokenizes. + */ + if ((tmpenv = strdup(env)) == NULL) + return (errno); + + envvar = strtok_r(tmpenv, ",", &envsave); + while (envvar != NULL) { + if ((*callback)(envlist, envvar) != 0) { + free(tmpenv); + return (errno); + } + envvar = strtok_r(NULL, ",", &envsave); + } + + free(tmpenv); + return (0); +} + +/* + * Sets environment value to envlist in similar manner + * than putenv(3). + * + * Returns 0 in success, errno otherwise. + */ +int +envlist_setenv(envlist_t *envlist, const char *env) +{ + struct envlist_entry *entry = NULL; + const char *eq_sign; + size_t envname_len; + + if ((envlist == NULL) || (env == NULL)) + return (EINVAL); + + /* find out first equals sign in given env */ + if ((eq_sign = strchr(env, '=')) == NULL) + return (EINVAL); + envname_len = eq_sign - env + 1; + + /* + * If there already exists variable with given name + * we remove and release it before allocating a whole + * new entry. + */ + for (entry = envlist->el_entries.lh_first; entry != NULL; + entry = entry->ev_link.le_next) { + if (strncmp(entry->ev_var, env, envname_len) == 0) + break; + } + + if (entry != NULL) { + LIST_REMOVE(entry, ev_link); + free((char *)entry->ev_var); + free(entry); + } else { + envlist->el_count++; + } + + if ((entry = malloc(sizeof (*entry))) == NULL) + return (errno); + if ((entry->ev_var = strdup(env)) == NULL) { + free(entry); + return (errno); + } + LIST_INSERT_HEAD(&envlist->el_entries, entry, ev_link); + + return (0); +} + +/* + * Removes given env value from envlist in similar manner + * than unsetenv(3). Returns 0 in success, errno otherwise. + */ +int +envlist_unsetenv(envlist_t *envlist, const char *env) +{ + struct envlist_entry *entry; + size_t envname_len; + + if ((envlist == NULL) || (env == NULL)) + return (EINVAL); + + /* env is not allowed to contain '=' */ + if (strchr(env, '=') != NULL) + return (EINVAL); + + /* + * Find out the requested entry and remove + * it from the list. + */ + envname_len = strlen(env); + for (entry = envlist->el_entries.lh_first; entry != NULL; + entry = entry->ev_link.le_next) { + if (strncmp(entry->ev_var, env, envname_len) == 0) + break; + } + if (entry != NULL) { + LIST_REMOVE(entry, ev_link); + free((char *)entry->ev_var); + free(entry); + + envlist->el_count--; + } + return (0); +} + +/* + * Returns given envlist as array of strings (in same form that + * global variable environ is). Caller must free returned memory + * by calling free(3) for each element and for the array. Returned + * array and given envlist are not related (no common references). + * + * If caller provides count pointer, number of items in array is + * stored there. In case of error, NULL is returned and no memory + * is allocated. + */ +char ** +envlist_to_environ(const envlist_t *envlist, size_t *count) +{ + struct envlist_entry *entry; + char **env, **penv; + + penv = env = malloc((envlist->el_count + 1) * sizeof (char *)); + if (env == NULL) + return (NULL); + + for (entry = envlist->el_entries.lh_first; entry != NULL; + entry = entry->ev_link.le_next) { + *(penv++) = strdup(entry->ev_var); + } + *penv = NULL; /* NULL terminate the list */ + + if (count != NULL) + *count = envlist->el_count; + + return (env); +} diff --git a/envlist.h b/envlist.h new file mode 100644 index 0000000000..e76d4a101b --- /dev/null +++ b/envlist.h @@ -0,0 +1,22 @@ +#ifndef ENVLIST_H +#define ENVLIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct envlist envlist_t; + +extern envlist_t *envlist_create(void); +extern void envlist_free(envlist_t *); +extern int envlist_setenv(envlist_t *, const char *); +extern int envlist_unsetenv(envlist_t *, const char *); +extern int envlist_parse_set(envlist_t *, const char *); +extern int envlist_parse_unset(envlist_t *, const char *); +extern char **envlist_to_environ(const envlist_t *, size_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* ENVLIST_H */ diff --git a/linux-user/envlist.c b/linux-user/envlist.c deleted file mode 100644 index e13c2d3e14..0000000000 --- a/linux-user/envlist.c +++ /dev/null @@ -1,247 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -#include "envlist.h" - -struct envlist_entry { - const char *ev_var; /* actual env value */ - LIST_ENTRY(envlist_entry) ev_link; -}; - -struct envlist { - LIST_HEAD(, envlist_entry) el_entries; /* actual entries */ - size_t el_count; /* number of entries */ -}; - -static int envlist_parse(envlist_t *envlist, - const char *env, int (*)(envlist_t *, const char *)); - -/* - * Allocates new envlist and returns pointer to that or - * NULL in case of error. - */ -envlist_t * -envlist_create(void) -{ - envlist_t *envlist; - - if ((envlist = malloc(sizeof (*envlist))) == NULL) - return (NULL); - - LIST_INIT(&envlist->el_entries); - envlist->el_count = 0; - - return (envlist); -} - -/* - * Releases given envlist and its entries. - */ -void -envlist_free(envlist_t *envlist) -{ - struct envlist_entry *entry; - - assert(envlist != NULL); - - while (envlist->el_entries.lh_first != NULL) { - entry = envlist->el_entries.lh_first; - LIST_REMOVE(entry, ev_link); - - free((char *)entry->ev_var); - free(entry); - } - free(envlist); -} - -/* - * Parses comma separated list of set/modify environment - * variable entries and updates given enlist accordingly. - * - * For example: - * envlist_parse(el, "HOME=foo,SHELL=/bin/sh"); - * - * inserts/sets environment variables HOME and SHELL. - * - * Returns 0 on success, errno otherwise. - */ -int -envlist_parse_set(envlist_t *envlist, const char *env) -{ - return (envlist_parse(envlist, env, &envlist_setenv)); -} - -/* - * Parses comma separated list of unset environment variable - * entries and removes given variables from given envlist. - * - * Returns 0 on success, errno otherwise. - */ -int -envlist_parse_unset(envlist_t *envlist, const char *env) -{ - return (envlist_parse(envlist, env, &envlist_unsetenv)); -} - -/* - * Parses comma separated list of set, modify or unset entries - * and calls given callback for each entry. - * - * Returns 0 in case of success, errno otherwise. - */ -static int -envlist_parse(envlist_t *envlist, const char *env, - int (*callback)(envlist_t *, const char *)) -{ - char *tmpenv, *envvar; - char *envsave = NULL; - - assert(callback != NULL); - - if ((envlist == NULL) || (env == NULL)) - return (EINVAL); - - /* - * We need to make temporary copy of the env string - * as strtok_r(3) modifies it while it tokenizes. - */ - if ((tmpenv = strdup(env)) == NULL) - return (errno); - - envvar = strtok_r(tmpenv, ",", &envsave); - while (envvar != NULL) { - if ((*callback)(envlist, envvar) != 0) { - free(tmpenv); - return (errno); - } - envvar = strtok_r(NULL, ",", &envsave); - } - - free(tmpenv); - return (0); -} - -/* - * Sets environment value to envlist in similar manner - * than putenv(3). - * - * Returns 0 in success, errno otherwise. - */ -int -envlist_setenv(envlist_t *envlist, const char *env) -{ - struct envlist_entry *entry = NULL; - const char *eq_sign; - size_t envname_len; - - if ((envlist == NULL) || (env == NULL)) - return (EINVAL); - - /* find out first equals sign in given env */ - if ((eq_sign = strchr(env, '=')) == NULL) - return (EINVAL); - envname_len = eq_sign - env + 1; - - /* - * If there already exists variable with given name - * we remove and release it before allocating a whole - * new entry. - */ - for (entry = envlist->el_entries.lh_first; entry != NULL; - entry = entry->ev_link.le_next) { - if (strncmp(entry->ev_var, env, envname_len) == 0) - break; - } - - if (entry != NULL) { - LIST_REMOVE(entry, ev_link); - free((char *)entry->ev_var); - free(entry); - } else { - envlist->el_count++; - } - - if ((entry = malloc(sizeof (*entry))) == NULL) - return (errno); - if ((entry->ev_var = strdup(env)) == NULL) { - free(entry); - return (errno); - } - LIST_INSERT_HEAD(&envlist->el_entries, entry, ev_link); - - return (0); -} - -/* - * Removes given env value from envlist in similar manner - * than unsetenv(3). Returns 0 in success, errno otherwise. - */ -int -envlist_unsetenv(envlist_t *envlist, const char *env) -{ - struct envlist_entry *entry; - size_t envname_len; - - if ((envlist == NULL) || (env == NULL)) - return (EINVAL); - - /* env is not allowed to contain '=' */ - if (strchr(env, '=') != NULL) - return (EINVAL); - - /* - * Find out the requested entry and remove - * it from the list. - */ - envname_len = strlen(env); - for (entry = envlist->el_entries.lh_first; entry != NULL; - entry = entry->ev_link.le_next) { - if (strncmp(entry->ev_var, env, envname_len) == 0) - break; - } - if (entry != NULL) { - LIST_REMOVE(entry, ev_link); - free((char *)entry->ev_var); - free(entry); - - envlist->el_count--; - } - return (0); -} - -/* - * Returns given envlist as array of strings (in same form that - * global variable environ is). Caller must free returned memory - * by calling free(3) for each element and for the array. Returned - * array and given envlist are not related (no common references). - * - * If caller provides count pointer, number of items in array is - * stored there. In case of error, NULL is returned and no memory - * is allocated. - */ -char ** -envlist_to_environ(const envlist_t *envlist, size_t *count) -{ - struct envlist_entry *entry; - char **env, **penv; - - penv = env = malloc((envlist->el_count + 1) * sizeof (char *)); - if (env == NULL) - return (NULL); - - for (entry = envlist->el_entries.lh_first; entry != NULL; - entry = entry->ev_link.le_next) { - *(penv++) = strdup(entry->ev_var); - } - *penv = NULL; /* NULL terminate the list */ - - if (count != NULL) - *count = envlist->el_count; - - return (env); -} diff --git a/linux-user/envlist.h b/linux-user/envlist.h deleted file mode 100644 index e76d4a101b..0000000000 --- a/linux-user/envlist.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef ENVLIST_H -#define ENVLIST_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct envlist envlist_t; - -extern envlist_t *envlist_create(void); -extern void envlist_free(envlist_t *); -extern int envlist_setenv(envlist_t *, const char *); -extern int envlist_unsetenv(envlist_t *, const char *); -extern int envlist_parse_set(envlist_t *, const char *); -extern int envlist_parse_unset(envlist_t *, const char *); -extern char **envlist_to_environ(const envlist_t *, size_t *); - -#ifdef __cplusplus -} -#endif - -#endif /* ENVLIST_H */