Annotation of embedaddon/tmux/environ.c, revision 1.1.1.1

1.1       misho       1: /* $OpenBSD$ */
                      2: 
                      3: /*
                      4:  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
                      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: #include <unistd.h>
                     24: 
                     25: #include "tmux.h"
                     26: 
                     27: /*
                     28:  * Environment - manipulate a set of environment variables.
                     29:  */
                     30: 
                     31: RB_HEAD(environ, environ_entry);
                     32: static int environ_cmp(struct environ_entry *, struct environ_entry *);
                     33: RB_GENERATE_STATIC(environ, environ_entry, entry, environ_cmp);
                     34: 
                     35: static int
                     36: environ_cmp(struct environ_entry *envent1, struct environ_entry *envent2)
                     37: {
                     38:        return (strcmp(envent1->name, envent2->name));
                     39: }
                     40: 
                     41: /* Initialise the environment. */
                     42: struct environ *
                     43: environ_create(void)
                     44: {
                     45:        struct environ  *env;
                     46: 
                     47:        env = xcalloc(1, sizeof *env);
                     48:        RB_INIT(env);
                     49: 
                     50:        return (env);
                     51: }
                     52: 
                     53: /* Free an environment. */
                     54: void
                     55: environ_free(struct environ *env)
                     56: {
                     57:        struct environ_entry    *envent, *envent1;
                     58: 
                     59:        RB_FOREACH_SAFE(envent, environ, env, envent1) {
                     60:                RB_REMOVE(environ, env, envent);
                     61:                free(envent->name);
                     62:                free(envent->value);
                     63:                free(envent);
                     64:        }
                     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));
                     78: }
                     79: 
                     80: /* Copy one environment into another. */
                     81: void
                     82: environ_copy(struct environ *srcenv, struct environ *dstenv)
                     83: {
                     84:        struct environ_entry    *envent;
                     85: 
                     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:        }
                     92: }
                     93: 
                     94: /* Find an environment variable. */
                     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: 
                    104: /* Set an environment variable. */
                    105: void
                    106: environ_set(struct environ *env, const char *name, const char *fmt, ...)
                    107: {
                    108:        struct environ_entry    *envent;
                    109:        va_list                  ap;
                    110: 
                    111:        va_start(ap, fmt);
                    112:        if ((envent = environ_find(env, name)) != NULL) {
                    113:                free(envent->value);
                    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;
                    133:        } else {
                    134:                envent = xmalloc(sizeof *envent);
                    135:                envent->name = xstrdup(name);
                    136:                envent->value = NULL;
                    137:                RB_INSERT(environ, env, envent);
                    138:        }
                    139: }
                    140: 
                    141: /* Set an environment variable from a NAME=VALUE string. */
                    142: void
                    143: environ_put(struct environ *env, const char *var)
                    144: {
                    145:        char    *name, *value;
                    146: 
                    147:        value = strchr(var, '=');
                    148:        if (value == NULL)
                    149:                return;
                    150:        value++;
                    151: 
                    152:        name = xstrdup(var);
                    153:        name[strcspn(name, "=")] = '\0';
                    154: 
                    155:        environ_set(env, name, "%s", value);
                    156:        free(name);
                    157: }
                    158: 
                    159: /* Unset an environment variable. */
                    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);
                    168:        free(envent->name);
                    169:        free(envent->value);
                    170:        free(envent);
                    171: }
                    172: 
                    173: /* Copy variables from a destination into a source * environment. */
                    174: void
                    175: environ_update(struct options *oo, struct environ *src, struct environ *dst)
                    176: {
                    177:        struct environ_entry    *envent;
                    178:        struct options_entry    *o;
                    179:        u_int                    size, idx;
                    180:        const char              *value;
                    181: 
                    182:        o = options_get(oo, "update-environment");
                    183:        if (o == NULL || options_array_size(o, &size) == -1)
                    184:                return;
                    185:        for (idx = 0; idx < size; idx++) {
                    186:                value = options_array_get(o, idx);
                    187:                if (value == NULL)
                    188:                        continue;
                    189:                if ((envent = environ_find(src, value)) == NULL)
                    190:                        environ_clear(dst, value);
                    191:                else
                    192:                        environ_set(dst, envent->name, "%s", envent->value);
                    193:        }
                    194: }
                    195: 
                    196: /* Push environment into the real environment - use after fork(). */
                    197: void
                    198: environ_push(struct environ *env)
                    199: {
                    200:        struct environ_entry    *envent;
                    201: 
                    202:        environ = xcalloc(1, sizeof *environ);
                    203:        RB_FOREACH(envent, environ, env) {
                    204:                if (envent->value != NULL && *envent->name != '\0')
                    205:                        setenv(envent->name, envent->value, 1);
                    206:        }
                    207: }
                    208: 
                    209: /* Log the environment. */
                    210: void
                    211: environ_log(struct environ *env, const char *prefix)
                    212: {
                    213:        struct environ_entry    *envent;
                    214: 
                    215:        RB_FOREACH(envent, environ, env) {
                    216:                if (envent->value != NULL && *envent->name != '\0') {
                    217:                        log_debug("%s%s=%s", prefix, envent->name,
                    218:                            envent->value);
                    219:                }
                    220:        }
                    221: }
                    222: 
                    223: /* Create initial environment for new child. */
                    224: struct environ *
                    225: environ_for_session(struct session *s)
                    226: {
                    227:        struct environ  *env;
                    228:        const char      *value;
                    229:        int              idx;
                    230: 
                    231:        env = environ_create();
                    232:        environ_copy(global_environ, env);
                    233:        if (s != NULL)
                    234:                environ_copy(s->environ, env);
                    235: 
                    236:        value = options_get_string(global_options, "default-terminal");
                    237:        environ_set(env, "TERM", "%s", value);
                    238: 
                    239:        if (s != NULL)
                    240:                idx = s->id;
                    241:        else
                    242:                idx = -1;
                    243:        environ_set(env, "TMUX", "%s,%ld,%d", socket_path, (long)getpid(), idx);
                    244: 
                    245:        return (env);
                    246: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>