Annotation of embedaddon/tmux/environ.c, revision 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>