Annotation of qemu/envlist.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com