[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.21

1.21    ! nicm        1: /* $OpenBSD: environ.c,v 1.20 2017/05/11 07:34:54 nicm Exp $ */
1.1       nicm        2:
                      3: /*
1.12      nicm        4:  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
1.1       nicm        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>
1.18      nicm       23: #include <unistd.h>
1.1       nicm       24:
                     25: #include "tmux.h"
                     26:
                     27: /*
                     28:  * Environment - manipulate a set of environment variables.
                     29:  */
                     30:
1.9       nicm       31: RB_HEAD(environ, environ_entry);
1.16      nicm       32: static int environ_cmp(struct environ_entry *, struct environ_entry *);
                     33: RB_GENERATE_STATIC(environ, environ_entry, entry, environ_cmp);
1.1       nicm       34:
1.16      nicm       35: static int
1.1       nicm       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.17      nicm      173: /* Copy variables from a destination into a source * environment. */
1.1       nicm      174: void
1.17      nicm      175: environ_update(struct options *oo, struct environ *src, struct environ *dst)
1.1       nicm      176: {
1.21    ! nicm      177:        struct environ_entry            *envent;
        !           178:        struct options_entry            *o;
        !           179:        struct options_array_item       *a;
        !           180:        const char                      *value;
1.1       nicm      181:
1.17      nicm      182:        o = options_get(oo, "update-environment");
1.21    ! nicm      183:        if (o == NULL)
1.17      nicm      184:                return;
1.21    ! nicm      185:        a = options_array_first(o);
        !           186:        while (a != NULL) {
        !           187:                value = options_array_item_value(a);
        !           188:                if (value == NULL) {
        !           189:                        a = options_array_next(a);
1.17      nicm      190:                        continue;
1.21    ! nicm      191:                }
1.17      nicm      192:                if ((envent = environ_find(src, value)) == NULL)
                    193:                        environ_clear(dst, value);
1.1       nicm      194:                else
1.17      nicm      195:                        environ_set(dst, envent->name, "%s", envent->value);
1.21    ! nicm      196:                a = options_array_next(a);
1.1       nicm      197:        }
1.4       nicm      198: }
                    199:
                    200: /* Push environment into the real environment - use after fork(). */
                    201: void
                    202: environ_push(struct environ *env)
                    203: {
1.13      nicm      204:        struct environ_entry    *envent;
1.4       nicm      205:
1.13      nicm      206:        environ = xcalloc(1, sizeof *environ);
1.4       nicm      207:        RB_FOREACH(envent, environ, env) {
1.13      nicm      208:                if (envent->value != NULL && *envent->name != '\0')
1.4       nicm      209:                        setenv(envent->name, envent->value, 1);
                    210:        }
1.14      nicm      211: }
                    212:
                    213: /* Log the environment. */
                    214: void
1.20      nicm      215: environ_log(struct environ *env, const char *fmt, ...)
1.14      nicm      216: {
                    217:        struct environ_entry    *envent;
1.20      nicm      218:        va_list                  ap;
                    219:        char                    *prefix;
                    220:
                    221:        va_start(ap, fmt);
                    222:        vasprintf(&prefix, fmt, ap);
                    223:        va_end(ap);
1.14      nicm      224:
1.15      nicm      225:        RB_FOREACH(envent, environ, env) {
                    226:                if (envent->value != NULL && *envent->name != '\0') {
                    227:                        log_debug("%s%s=%s", prefix, envent->name,
                    228:                            envent->value);
                    229:                }
                    230:        }
1.20      nicm      231:
                    232:        free(prefix);
1.18      nicm      233: }
                    234:
                    235: /* Create initial environment for new child. */
                    236: struct environ *
1.19      nicm      237: environ_for_session(struct session *s, int no_TERM)
1.18      nicm      238: {
                    239:        struct environ  *env;
                    240:        const char      *value;
                    241:        int              idx;
                    242:
                    243:        env = environ_create();
                    244:        environ_copy(global_environ, env);
                    245:        if (s != NULL)
                    246:                environ_copy(s->environ, env);
                    247:
1.19      nicm      248:        if (!no_TERM) {
                    249:                value = options_get_string(global_options, "default-terminal");
                    250:                environ_set(env, "TERM", "%s", value);
                    251:        }
1.18      nicm      252:
                    253:        if (s != NULL)
                    254:                idx = s->id;
                    255:        else
                    256:                idx = -1;
                    257:        environ_set(env, "TMUX", "%s,%ld,%d", socket_path, (long)getpid(), idx);
                    258:
                    259:        return (env);
1.1       nicm      260: }