[BACK]Return to environ.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/environ.c, Revision 1.11

1.11    ! nicm        1: /* $OpenBSD: environ.c,v 1.10 2015/11/24 23:46:15 nicm Exp $ */
1.1       nicm        2:
                      3: /*
                      4:  * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
                     15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                     16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/types.h>
                     20:
                     21: #include <stdlib.h>
                     22: #include <string.h>
                     23:
                     24: #include "tmux.h"
                     25:
                     26: /*
                     27:  * Environment - manipulate a set of environment variables.
                     28:  */
                     29:
1.9       nicm       30: RB_HEAD(environ, environ_entry);
                     31: int    environ_cmp(struct environ_entry *, struct environ_entry *);
                     32: RB_PROTOTYPE(environ, environ_entry, entry, environ_cmp);
1.1       nicm       33: RB_GENERATE(environ, environ_entry, entry, environ_cmp);
                     34:
                     35: int
                     36: environ_cmp(struct environ_entry *envent1, struct environ_entry *envent2)
                     37: {
                     38:        return (strcmp(envent1->name, envent2->name));
                     39: }
                     40:
1.4       nicm       41: /* Initialise the environment. */
1.9       nicm       42: struct environ *
                     43: environ_create(void)
1.1       nicm       44: {
1.9       nicm       45:        struct environ  *env;
                     46:
                     47:        env = xcalloc(1, sizeof *env);
1.1       nicm       48:        RB_INIT(env);
1.9       nicm       49:
                     50:        return (env);
1.1       nicm       51: }
                     52:
1.4       nicm       53: /* Free an environment. */
1.1       nicm       54: void
                     55: environ_free(struct environ *env)
                     56: {
1.9       nicm       57:        struct environ_entry    *envent, *envent1;
1.1       nicm       58:
1.9       nicm       59:        RB_FOREACH_SAFE(envent, environ, env, envent1) {
1.1       nicm       60:                RB_REMOVE(environ, env, envent);
1.5       nicm       61:                free(envent->name);
                     62:                free(envent->value);
                     63:                free(envent);
1.1       nicm       64:        }
1.9       nicm       65:        free(env);
                     66: }
                     67:
                     68: struct environ_entry *
                     69: environ_first(struct environ *env)
                     70: {
                     71:        return (RB_MIN(environ, env));
                     72: }
                     73:
                     74: struct environ_entry *
                     75: environ_next(struct environ_entry *envent)
                     76: {
                     77:        return (RB_NEXT(environ, env, envent));
1.1       nicm       78: }
                     79:
1.4       nicm       80: /* Copy one environment into another. */
1.1       nicm       81: void
                     82: environ_copy(struct environ *srcenv, struct environ *dstenv)
                     83: {
                     84:        struct environ_entry    *envent;
                     85:
1.10      nicm       86:        RB_FOREACH(envent, environ, srcenv) {
                     87:                if (envent->value == NULL)
                     88:                        environ_clear(dstenv, envent->name);
                     89:                else
                     90:                        environ_set(dstenv, envent->name, "%s", envent->value);
                     91:        }
1.1       nicm       92: }
                     93:
1.4       nicm       94: /* Find an environment variable. */
1.1       nicm       95: struct environ_entry *
                     96: environ_find(struct environ *env, const char *name)
                     97: {
                     98:        struct environ_entry    envent;
                     99:
                    100:        envent.name = (char *) name;
                    101:        return (RB_FIND(environ, env, &envent));
                    102: }
                    103:
1.4       nicm      104: /* Set an environment variable. */
1.1       nicm      105: void
1.10      nicm      106: environ_set(struct environ *env, const char *name, const char *fmt, ...)
1.1       nicm      107: {
                    108:        struct environ_entry    *envent;
1.10      nicm      109:        va_list                  ap;
1.1       nicm      110:
1.10      nicm      111:        va_start(ap, fmt);
1.1       nicm      112:        if ((envent = environ_find(env, name)) != NULL) {
1.5       nicm      113:                free(envent->value);
1.10      nicm      114:                xvasprintf(&envent->value, fmt, ap);
                    115:        } else {
                    116:                envent = xmalloc(sizeof *envent);
                    117:                envent->name = xstrdup(name);
                    118:                xvasprintf(&envent->value, fmt, ap);
                    119:                RB_INSERT(environ, env, envent);
                    120:        }
                    121:        va_end(ap);
                    122: }
                    123:
                    124: /* Clear an environment variable. */
                    125: void
                    126: environ_clear(struct environ *env, const char *name)
                    127: {
                    128:        struct environ_entry    *envent;
                    129:
                    130:        if ((envent = environ_find(env, name)) != NULL) {
                    131:                free(envent->value);
                    132:                envent->value = NULL;
1.1       nicm      133:        } else {
                    134:                envent = xmalloc(sizeof *envent);
                    135:                envent->name = xstrdup(name);
1.10      nicm      136:                envent->value = NULL;
1.1       nicm      137:                RB_INSERT(environ, env, envent);
                    138:        }
                    139: }
                    140:
1.4       nicm      141: /* Set an environment variable from a NAME=VALUE string. */
1.1       nicm      142: void
                    143: environ_put(struct environ *env, const char *var)
                    144: {
1.4       nicm      145:        char    *name, *value;
1.1       nicm      146:
                    147:        value = strchr(var, '=');
                    148:        if (value == NULL)
                    149:                return;
                    150:        value++;
                    151:
                    152:        name = xstrdup(var);
                    153:        name[strcspn(name, "=")] = '\0';
                    154:
1.10      nicm      155:        environ_set(env, name, "%s", value);
1.5       nicm      156:        free(name);
1.1       nicm      157: }
                    158:
1.4       nicm      159: /* Unset an environment variable. */
1.1       nicm      160: void
                    161: environ_unset(struct environ *env, const char *name)
                    162: {
                    163:        struct environ_entry    *envent;
                    164:
                    165:        if ((envent = environ_find(env, name)) == NULL)
                    166:                return;
                    167:        RB_REMOVE(environ, env, envent);
1.5       nicm      168:        free(envent->name);
                    169:        free(envent->value);
                    170:        free(envent);
1.1       nicm      171: }
                    172:
1.4       nicm      173: /*
                    174:  * Copy a space-separated list of variables from a destination into a source
                    175:  * environment.
                    176:  */
1.1       nicm      177: void
1.6       nicm      178: environ_update(const char *vars, struct environ *srcenv,
                    179:     struct environ *dstenv)
1.1       nicm      180: {
                    181:        struct environ_entry    *envent;
1.2       nicm      182:        char                    *copyvars, *var, *next;
1.1       nicm      183:
1.2       nicm      184:        copyvars = next = xstrdup(vars);
1.1       nicm      185:        while ((var = strsep(&next, " ")) != NULL) {
                    186:                if ((envent = environ_find(srcenv, var)) == NULL)
1.10      nicm      187:                        environ_clear(dstenv, var);
1.1       nicm      188:                else
1.10      nicm      189:                        environ_set(dstenv, envent->name, "%s", envent->value);
1.1       nicm      190:        }
1.5       nicm      191:        free(copyvars);
1.4       nicm      192: }
                    193:
                    194: /* Push environment into the real environment - use after fork(). */
                    195: void
                    196: environ_push(struct environ *env)
                    197: {
1.8       nicm      198:        struct environ_entry     *envent;
1.11    ! nicm      199:        char                    *v;
1.8       nicm      200:
1.11    ! nicm      201:        while (*environ != NULL) {
        !           202:                v = xstrdup(*environ);
1.8       nicm      203:                v[strcspn(v, "=")] = '\0';
                    204:
                    205:                unsetenv(v);
                    206:                free(v);
1.7       nicm      207:        }
1.4       nicm      208:
                    209:        RB_FOREACH(envent, environ, env) {
                    210:                if (envent->value != NULL)
                    211:                        setenv(envent->name, envent->value, 1);
                    212:        }
1.1       nicm      213: }