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

1.25    ! nicm        1: /* $OpenBSD: environ.c,v 1.24 2020/03/31 17:14:40 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);
1.24      nicm       89:                else {
                     90:                        environ_set(dstenv, envent->name, envent->flags,
                     91:                            "%s", envent->value);
                     92:                }
1.10      nicm       93:        }
1.1       nicm       94: }
                     95:
1.4       nicm       96: /* Find an environment variable. */
1.1       nicm       97: struct environ_entry *
                     98: environ_find(struct environ *env, const char *name)
                     99: {
                    100:        struct environ_entry    envent;
                    101:
                    102:        envent.name = (char *) name;
                    103:        return (RB_FIND(environ, env, &envent));
                    104: }
                    105:
1.4       nicm      106: /* Set an environment variable. */
1.1       nicm      107: void
1.24      nicm      108: environ_set(struct environ *env, const char *name, int flags, const char *fmt,
                    109:     ...)
1.1       nicm      110: {
                    111:        struct environ_entry    *envent;
1.10      nicm      112:        va_list                  ap;
1.1       nicm      113:
1.10      nicm      114:        va_start(ap, fmt);
1.1       nicm      115:        if ((envent = environ_find(env, name)) != NULL) {
1.24      nicm      116:                envent->flags = flags;
1.5       nicm      117:                free(envent->value);
1.10      nicm      118:                xvasprintf(&envent->value, fmt, ap);
                    119:        } else {
                    120:                envent = xmalloc(sizeof *envent);
                    121:                envent->name = xstrdup(name);
1.24      nicm      122:                envent->flags = flags;
1.10      nicm      123:                xvasprintf(&envent->value, fmt, ap);
                    124:                RB_INSERT(environ, env, envent);
                    125:        }
                    126:        va_end(ap);
                    127: }
                    128:
                    129: /* Clear an environment variable. */
                    130: void
                    131: environ_clear(struct environ *env, const char *name)
                    132: {
                    133:        struct environ_entry    *envent;
                    134:
                    135:        if ((envent = environ_find(env, name)) != NULL) {
                    136:                free(envent->value);
                    137:                envent->value = NULL;
1.1       nicm      138:        } else {
                    139:                envent = xmalloc(sizeof *envent);
                    140:                envent->name = xstrdup(name);
1.24      nicm      141:                envent->flags = 0;
1.10      nicm      142:                envent->value = NULL;
1.1       nicm      143:                RB_INSERT(environ, env, envent);
                    144:        }
                    145: }
                    146:
1.4       nicm      147: /* Set an environment variable from a NAME=VALUE string. */
1.1       nicm      148: void
1.24      nicm      149: environ_put(struct environ *env, const char *var, int flags)
1.1       nicm      150: {
1.4       nicm      151:        char    *name, *value;
1.1       nicm      152:
                    153:        value = strchr(var, '=');
                    154:        if (value == NULL)
                    155:                return;
                    156:        value++;
                    157:
                    158:        name = xstrdup(var);
                    159:        name[strcspn(name, "=")] = '\0';
                    160:
1.24      nicm      161:        environ_set(env, name, flags, "%s", value);
1.5       nicm      162:        free(name);
1.1       nicm      163: }
                    164:
1.4       nicm      165: /* Unset an environment variable. */
1.1       nicm      166: void
                    167: environ_unset(struct environ *env, const char *name)
                    168: {
                    169:        struct environ_entry    *envent;
                    170:
                    171:        if ((envent = environ_find(env, name)) == NULL)
                    172:                return;
                    173:        RB_REMOVE(environ, env, envent);
1.5       nicm      174:        free(envent->name);
                    175:        free(envent->value);
                    176:        free(envent);
1.1       nicm      177: }
                    178:
1.24      nicm      179: /* Copy variables from a destination into a source environment. */
1.1       nicm      180: void
1.17      nicm      181: environ_update(struct options *oo, struct environ *src, struct environ *dst)
1.1       nicm      182: {
1.21      nicm      183:        struct environ_entry            *envent;
                    184:        struct options_entry            *o;
                    185:        struct options_array_item       *a;
1.22      nicm      186:        union options_value             *ov;
1.1       nicm      187:
1.17      nicm      188:        o = options_get(oo, "update-environment");
1.21      nicm      189:        if (o == NULL)
1.17      nicm      190:                return;
1.21      nicm      191:        a = options_array_first(o);
                    192:        while (a != NULL) {
1.22      nicm      193:                ov = options_array_item_value(a);
                    194:                if ((envent = environ_find(src, ov->string)) == NULL)
                    195:                        environ_clear(dst, ov->string);
1.1       nicm      196:                else
1.24      nicm      197:                        environ_set(dst, envent->name, 0, "%s", envent->value);
1.21      nicm      198:                a = options_array_next(a);
1.1       nicm      199:        }
1.4       nicm      200: }
                    201:
                    202: /* Push environment into the real environment - use after fork(). */
                    203: void
                    204: environ_push(struct environ *env)
                    205: {
1.13      nicm      206:        struct environ_entry    *envent;
1.4       nicm      207:
1.13      nicm      208:        environ = xcalloc(1, sizeof *environ);
1.4       nicm      209:        RB_FOREACH(envent, environ, env) {
1.24      nicm      210:                if (envent->value != NULL &&
                    211:                    *envent->name != '\0' &&
                    212:                    (~envent->flags & ENVIRON_HIDDEN))
1.4       nicm      213:                        setenv(envent->name, envent->value, 1);
                    214:        }
1.14      nicm      215: }
                    216:
                    217: /* Log the environment. */
                    218: void
1.20      nicm      219: environ_log(struct environ *env, const char *fmt, ...)
1.14      nicm      220: {
                    221:        struct environ_entry    *envent;
1.20      nicm      222:        va_list                  ap;
                    223:        char                    *prefix;
                    224:
                    225:        va_start(ap, fmt);
                    226:        vasprintf(&prefix, fmt, ap);
                    227:        va_end(ap);
1.14      nicm      228:
1.15      nicm      229:        RB_FOREACH(envent, environ, env) {
                    230:                if (envent->value != NULL && *envent->name != '\0') {
                    231:                        log_debug("%s%s=%s", prefix, envent->name,
                    232:                            envent->value);
                    233:                }
                    234:        }
1.20      nicm      235:
                    236:        free(prefix);
1.18      nicm      237: }
                    238:
                    239: /* Create initial environment for new child. */
                    240: struct environ *
1.19      nicm      241: environ_for_session(struct session *s, int no_TERM)
1.18      nicm      242: {
                    243:        struct environ  *env;
                    244:        const char      *value;
                    245:        int              idx;
                    246:
                    247:        env = environ_create();
                    248:        environ_copy(global_environ, env);
                    249:        if (s != NULL)
                    250:                environ_copy(s->environ, env);
                    251:
1.19      nicm      252:        if (!no_TERM) {
                    253:                value = options_get_string(global_options, "default-terminal");
1.24      nicm      254:                environ_set(env, "TERM", 0, "%s", value);
1.25    ! nicm      255:                environ_set(env, "TERM_PROGRAM", 0, "%s", "tmux");
        !           256:                environ_set(env, "TERM_PROGRAM_VERSION", 0, "%s", getversion());
1.19      nicm      257:        }
1.18      nicm      258:
                    259:        if (s != NULL)
                    260:                idx = s->id;
                    261:        else
                    262:                idx = -1;
1.24      nicm      263:        environ_set(env, "TMUX", 0, "%s,%ld,%d", socket_path, (long)getpid(),
                    264:            idx);
1.18      nicm      265:
                    266:        return (env);
1.1       nicm      267: }