Annotation of qemu/envlist.c, revision 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