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

1.26    ! nicm        1: /* $OpenBSD: environ.c,v 1.25 2020/05/16 15:40:44 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:
1.26    ! nicm       21: #include <fnmatch.h>
1.1       nicm       22: #include <stdlib.h>
                     23: #include <string.h>
1.18      nicm       24: #include <unistd.h>
1.1       nicm       25:
                     26: #include "tmux.h"
                     27:
                     28: /*
                     29:  * Environment - manipulate a set of environment variables.
                     30:  */
                     31:
1.9       nicm       32: RB_HEAD(environ, environ_entry);
1.16      nicm       33: static int environ_cmp(struct environ_entry *, struct environ_entry *);
                     34: RB_GENERATE_STATIC(environ, environ_entry, entry, environ_cmp);
1.1       nicm       35:
1.16      nicm       36: static int
1.1       nicm       37: environ_cmp(struct environ_entry *envent1, struct environ_entry *envent2)
                     38: {
                     39:        return (strcmp(envent1->name, envent2->name));
                     40: }
                     41:
1.4       nicm       42: /* Initialise the environment. */
1.9       nicm       43: struct environ *
                     44: environ_create(void)
1.1       nicm       45: {
1.9       nicm       46:        struct environ  *env;
                     47:
                     48:        env = xcalloc(1, sizeof *env);
1.1       nicm       49:        RB_INIT(env);
1.9       nicm       50:
                     51:        return (env);
1.1       nicm       52: }
                     53:
1.4       nicm       54: /* Free an environment. */
1.1       nicm       55: void
                     56: environ_free(struct environ *env)
                     57: {
1.9       nicm       58:        struct environ_entry    *envent, *envent1;
1.1       nicm       59:
1.9       nicm       60:        RB_FOREACH_SAFE(envent, environ, env, envent1) {
1.1       nicm       61:                RB_REMOVE(environ, env, envent);
1.5       nicm       62:                free(envent->name);
                     63:                free(envent->value);
                     64:                free(envent);
1.1       nicm       65:        }
1.9       nicm       66:        free(env);
                     67: }
                     68:
                     69: struct environ_entry *
                     70: environ_first(struct environ *env)
                     71: {
                     72:        return (RB_MIN(environ, env));
                     73: }
                     74:
                     75: struct environ_entry *
                     76: environ_next(struct environ_entry *envent)
                     77: {
                     78:        return (RB_NEXT(environ, env, envent));
1.1       nicm       79: }
                     80:
1.4       nicm       81: /* Copy one environment into another. */
1.1       nicm       82: void
                     83: environ_copy(struct environ *srcenv, struct environ *dstenv)
                     84: {
                     85:        struct environ_entry    *envent;
                     86:
1.10      nicm       87:        RB_FOREACH(envent, environ, srcenv) {
                     88:                if (envent->value == NULL)
                     89:                        environ_clear(dstenv, envent->name);
1.24      nicm       90:                else {
                     91:                        environ_set(dstenv, envent->name, envent->flags,
                     92:                            "%s", envent->value);
                     93:                }
1.10      nicm       94:        }
1.1       nicm       95: }
                     96:
1.4       nicm       97: /* Find an environment variable. */
1.1       nicm       98: struct environ_entry *
                     99: environ_find(struct environ *env, const char *name)
                    100: {
                    101:        struct environ_entry    envent;
                    102:
                    103:        envent.name = (char *) name;
                    104:        return (RB_FIND(environ, env, &envent));
                    105: }
                    106:
1.4       nicm      107: /* Set an environment variable. */
1.1       nicm      108: void
1.24      nicm      109: environ_set(struct environ *env, const char *name, int flags, const char *fmt,
                    110:     ...)
1.1       nicm      111: {
                    112:        struct environ_entry    *envent;
1.10      nicm      113:        va_list                  ap;
1.1       nicm      114:
1.10      nicm      115:        va_start(ap, fmt);
1.1       nicm      116:        if ((envent = environ_find(env, name)) != NULL) {
1.24      nicm      117:                envent->flags = flags;
1.5       nicm      118:                free(envent->value);
1.10      nicm      119:                xvasprintf(&envent->value, fmt, ap);
                    120:        } else {
                    121:                envent = xmalloc(sizeof *envent);
                    122:                envent->name = xstrdup(name);
1.24      nicm      123:                envent->flags = flags;
1.10      nicm      124:                xvasprintf(&envent->value, fmt, ap);
                    125:                RB_INSERT(environ, env, envent);
                    126:        }
                    127:        va_end(ap);
                    128: }
                    129:
                    130: /* Clear an environment variable. */
                    131: void
                    132: environ_clear(struct environ *env, const char *name)
                    133: {
                    134:        struct environ_entry    *envent;
                    135:
                    136:        if ((envent = environ_find(env, name)) != NULL) {
                    137:                free(envent->value);
                    138:                envent->value = NULL;
1.1       nicm      139:        } else {
                    140:                envent = xmalloc(sizeof *envent);
                    141:                envent->name = xstrdup(name);
1.24      nicm      142:                envent->flags = 0;
1.10      nicm      143:                envent->value = NULL;
1.1       nicm      144:                RB_INSERT(environ, env, envent);
                    145:        }
                    146: }
                    147:
1.4       nicm      148: /* Set an environment variable from a NAME=VALUE string. */
1.1       nicm      149: void
1.24      nicm      150: environ_put(struct environ *env, const char *var, int flags)
1.1       nicm      151: {
1.4       nicm      152:        char    *name, *value;
1.1       nicm      153:
                    154:        value = strchr(var, '=');
                    155:        if (value == NULL)
                    156:                return;
                    157:        value++;
                    158:
                    159:        name = xstrdup(var);
                    160:        name[strcspn(name, "=")] = '\0';
                    161:
1.24      nicm      162:        environ_set(env, name, flags, "%s", value);
1.5       nicm      163:        free(name);
1.1       nicm      164: }
                    165:
1.4       nicm      166: /* Unset an environment variable. */
1.1       nicm      167: void
                    168: environ_unset(struct environ *env, const char *name)
                    169: {
                    170:        struct environ_entry    *envent;
                    171:
                    172:        if ((envent = environ_find(env, name)) == NULL)
                    173:                return;
                    174:        RB_REMOVE(environ, env, envent);
1.5       nicm      175:        free(envent->name);
                    176:        free(envent->value);
                    177:        free(envent);
1.1       nicm      178: }
                    179:
1.24      nicm      180: /* Copy variables from a destination into a source environment. */
1.1       nicm      181: void
1.17      nicm      182: environ_update(struct options *oo, struct environ *src, struct environ *dst)
1.1       nicm      183: {
1.21      nicm      184:        struct environ_entry            *envent;
                    185:        struct options_entry            *o;
                    186:        struct options_array_item       *a;
1.22      nicm      187:        union options_value             *ov;
1.1       nicm      188:
1.17      nicm      189:        o = options_get(oo, "update-environment");
1.21      nicm      190:        if (o == NULL)
1.17      nicm      191:                return;
1.21      nicm      192:        a = options_array_first(o);
                    193:        while (a != NULL) {
1.22      nicm      194:                ov = options_array_item_value(a);
1.26    ! nicm      195:                RB_FOREACH(envent, environ, src) {
        !           196:                        if (fnmatch(ov->string, envent->name, 0) == 0)
        !           197:                                break;
        !           198:                }
        !           199:                if (envent == NULL)
1.22      nicm      200:                        environ_clear(dst, ov->string);
1.1       nicm      201:                else
1.24      nicm      202:                        environ_set(dst, envent->name, 0, "%s", envent->value);
1.21      nicm      203:                a = options_array_next(a);
1.1       nicm      204:        }
1.4       nicm      205: }
                    206:
                    207: /* Push environment into the real environment - use after fork(). */
                    208: void
                    209: environ_push(struct environ *env)
                    210: {
1.13      nicm      211:        struct environ_entry    *envent;
1.4       nicm      212:
1.13      nicm      213:        environ = xcalloc(1, sizeof *environ);
1.4       nicm      214:        RB_FOREACH(envent, environ, env) {
1.24      nicm      215:                if (envent->value != NULL &&
                    216:                    *envent->name != '\0' &&
                    217:                    (~envent->flags & ENVIRON_HIDDEN))
1.4       nicm      218:                        setenv(envent->name, envent->value, 1);
                    219:        }
1.14      nicm      220: }
                    221:
                    222: /* Log the environment. */
                    223: void
1.20      nicm      224: environ_log(struct environ *env, const char *fmt, ...)
1.14      nicm      225: {
                    226:        struct environ_entry    *envent;
1.20      nicm      227:        va_list                  ap;
                    228:        char                    *prefix;
                    229:
                    230:        va_start(ap, fmt);
                    231:        vasprintf(&prefix, fmt, ap);
                    232:        va_end(ap);
1.14      nicm      233:
1.15      nicm      234:        RB_FOREACH(envent, environ, env) {
                    235:                if (envent->value != NULL && *envent->name != '\0') {
                    236:                        log_debug("%s%s=%s", prefix, envent->name,
                    237:                            envent->value);
                    238:                }
                    239:        }
1.20      nicm      240:
                    241:        free(prefix);
1.18      nicm      242: }
                    243:
                    244: /* Create initial environment for new child. */
                    245: struct environ *
1.19      nicm      246: environ_for_session(struct session *s, int no_TERM)
1.18      nicm      247: {
                    248:        struct environ  *env;
                    249:        const char      *value;
                    250:        int              idx;
                    251:
                    252:        env = environ_create();
                    253:        environ_copy(global_environ, env);
                    254:        if (s != NULL)
                    255:                environ_copy(s->environ, env);
                    256:
1.19      nicm      257:        if (!no_TERM) {
                    258:                value = options_get_string(global_options, "default-terminal");
1.24      nicm      259:                environ_set(env, "TERM", 0, "%s", value);
1.25      nicm      260:                environ_set(env, "TERM_PROGRAM", 0, "%s", "tmux");
                    261:                environ_set(env, "TERM_PROGRAM_VERSION", 0, "%s", getversion());
1.19      nicm      262:        }
1.18      nicm      263:
                    264:        if (s != NULL)
                    265:                idx = s->id;
                    266:        else
                    267:                idx = -1;
1.24      nicm      268:        environ_set(env, "TMUX", 0, "%s,%ld,%d", socket_path, (long)getpid(),
                    269:            idx);
1.18      nicm      270:
                    271:        return (env);
1.1       nicm      272: }