cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

envlist.c (5155B)


      1#include "qemu/osdep.h"
      2#include "qemu/queue.h"
      3#include "qemu/envlist.h"
      4
      5struct envlist_entry {
      6	const char *ev_var;			/* actual env value */
      7	QLIST_ENTRY(envlist_entry) ev_link;
      8};
      9
     10struct envlist {
     11	QLIST_HEAD(, envlist_entry) el_entries;	/* actual entries */
     12	size_t el_count;			/* number of entries */
     13};
     14
     15static int envlist_parse(envlist_t *envlist,
     16    const char *env, int (*)(envlist_t *, const char *));
     17
     18/*
     19 * Allocates new envlist and returns pointer to it.
     20 */
     21envlist_t *
     22envlist_create(void)
     23{
     24	envlist_t *envlist;
     25
     26	envlist = g_malloc(sizeof(*envlist));
     27
     28	QLIST_INIT(&envlist->el_entries);
     29	envlist->el_count = 0;
     30
     31	return (envlist);
     32}
     33
     34/*
     35 * Releases given envlist and its entries.
     36 */
     37void
     38envlist_free(envlist_t *envlist)
     39{
     40	struct envlist_entry *entry;
     41
     42	assert(envlist != NULL);
     43
     44	while (envlist->el_entries.lh_first != NULL) {
     45		entry = envlist->el_entries.lh_first;
     46		QLIST_REMOVE(entry, ev_link);
     47
     48		g_free((char *)entry->ev_var);
     49		g_free(entry);
     50	}
     51	g_free(envlist);
     52}
     53
     54/*
     55 * Parses comma separated list of set/modify environment
     56 * variable entries and updates given enlist accordingly.
     57 *
     58 * For example:
     59 *     envlist_parse(el, "HOME=foo,SHELL=/bin/sh");
     60 *
     61 * inserts/sets environment variables HOME and SHELL.
     62 *
     63 * Returns 0 on success, errno otherwise.
     64 */
     65int
     66envlist_parse_set(envlist_t *envlist, const char *env)
     67{
     68	return (envlist_parse(envlist, env, &envlist_setenv));
     69}
     70
     71/*
     72 * Parses comma separated list of unset environment variable
     73 * entries and removes given variables from given envlist.
     74 *
     75 * Returns 0 on success, errno otherwise.
     76 */
     77int
     78envlist_parse_unset(envlist_t *envlist, const char *env)
     79{
     80	return (envlist_parse(envlist, env, &envlist_unsetenv));
     81}
     82
     83/*
     84 * Parses comma separated list of set, modify or unset entries
     85 * and calls given callback for each entry.
     86 *
     87 * Returns 0 in case of success, errno otherwise.
     88 */
     89static int
     90envlist_parse(envlist_t *envlist, const char *env,
     91    int (*callback)(envlist_t *, const char *))
     92{
     93	char *tmpenv, *envvar;
     94	char *envsave = NULL;
     95    int ret = 0;
     96    assert(callback != NULL);
     97
     98	if ((envlist == NULL) || (env == NULL))
     99		return (EINVAL);
    100
    101	tmpenv = g_strdup(env);
    102    envsave = tmpenv;
    103
    104    do {
    105        envvar = strchr(tmpenv, ',');
    106        if (envvar != NULL) {
    107            *envvar = '\0';
    108        }
    109        if ((*callback)(envlist, tmpenv) != 0) {
    110            ret = errno;
    111            break;
    112		}
    113        tmpenv = envvar + 1;
    114    } while (envvar != NULL);
    115
    116    g_free(envsave);
    117    return ret;
    118}
    119
    120/*
    121 * Sets environment value to envlist in similar manner
    122 * than putenv(3).
    123 *
    124 * Returns 0 in success, errno otherwise.
    125 */
    126int
    127envlist_setenv(envlist_t *envlist, const char *env)
    128{
    129	struct envlist_entry *entry = NULL;
    130	const char *eq_sign;
    131	size_t envname_len;
    132
    133	if ((envlist == NULL) || (env == NULL))
    134		return (EINVAL);
    135
    136	/* find out first equals sign in given env */
    137	if ((eq_sign = strchr(env, '=')) == NULL)
    138		return (EINVAL);
    139	envname_len = eq_sign - env + 1;
    140
    141	/*
    142	 * If there already exists variable with given name
    143	 * we remove and release it before allocating a whole
    144	 * new entry.
    145	 */
    146	for (entry = envlist->el_entries.lh_first; entry != NULL;
    147	    entry = entry->ev_link.le_next) {
    148		if (strncmp(entry->ev_var, env, envname_len) == 0)
    149			break;
    150	}
    151
    152	if (entry != NULL) {
    153		QLIST_REMOVE(entry, ev_link);
    154		g_free((char *)entry->ev_var);
    155		g_free(entry);
    156	} else {
    157		envlist->el_count++;
    158	}
    159
    160	entry = g_malloc(sizeof(*entry));
    161	entry->ev_var = g_strdup(env);
    162	QLIST_INSERT_HEAD(&envlist->el_entries, entry, ev_link);
    163
    164	return (0);
    165}
    166
    167/*
    168 * Removes given env value from envlist in similar manner
    169 * than unsetenv(3).  Returns 0 in success, errno otherwise.
    170 */
    171int
    172envlist_unsetenv(envlist_t *envlist, const char *env)
    173{
    174	struct envlist_entry *entry;
    175	size_t envname_len;
    176
    177	if ((envlist == NULL) || (env == NULL))
    178		return (EINVAL);
    179
    180	/* env is not allowed to contain '=' */
    181	if (strchr(env, '=') != NULL)
    182		return (EINVAL);
    183
    184	/*
    185	 * Find out the requested entry and remove
    186	 * it from the list.
    187	 */
    188	envname_len = strlen(env);
    189	for (entry = envlist->el_entries.lh_first; entry != NULL;
    190	    entry = entry->ev_link.le_next) {
    191		if (strncmp(entry->ev_var, env, envname_len) == 0)
    192			break;
    193	}
    194	if (entry != NULL) {
    195		QLIST_REMOVE(entry, ev_link);
    196		g_free((char *)entry->ev_var);
    197		g_free(entry);
    198
    199		envlist->el_count--;
    200	}
    201	return (0);
    202}
    203
    204/*
    205 * Returns given envlist as array of strings (in same form that
    206 * global variable environ is).  Caller must free returned memory
    207 * by calling g_free for each element and the array.
    208 * Returned array and given envlist are not related (no common
    209 * references).
    210 *
    211 * If caller provides count pointer, number of items in array is
    212 * stored there.
    213 */
    214char **
    215envlist_to_environ(const envlist_t *envlist, size_t *count)
    216{
    217	struct envlist_entry *entry;
    218	char **env, **penv;
    219
    220	penv = env = g_malloc((envlist->el_count + 1) * sizeof(char *));
    221
    222	for (entry = envlist->el_entries.lh_first; entry != NULL;
    223	    entry = entry->ev_link.le_next) {
    224		*(penv++) = g_strdup(entry->ev_var);
    225	}
    226	*penv = NULL; /* NULL terminate the list */
    227
    228	if (count != NULL)
    229		*count = envlist->el_count;
    230
    231	return (env);
    232}