Home | History | Annotate | Line # | Download | only in dist
environ.c revision 1.3.8.1
      1 /* Id */
      2 
      3 /*
      4  * Copyright (c) 2009 Nicholas Marriott <nicm (at) users.sourceforge.net>
      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 
     24 #include "tmux.h"
     25 
     26 /*
     27  * Environment - manipulate a set of environment variables.
     28  */
     29 
     30 RB_GENERATE(environ, environ_entry, entry, environ_cmp);
     31 
     32 int
     33 environ_cmp(struct environ_entry *envent1, struct environ_entry *envent2)
     34 {
     35 	return (strcmp(envent1->name, envent2->name));
     36 }
     37 
     38 /* Initialise the environment. */
     39 void
     40 environ_init(struct environ *env)
     41 {
     42 	RB_INIT(env);
     43 }
     44 
     45 /* Free an environment. */
     46 void
     47 environ_free(struct environ *env)
     48 {
     49 	struct environ_entry	*envent;
     50 
     51 	while (!RB_EMPTY(env)) {
     52 		envent = RB_ROOT(env);
     53 		RB_REMOVE(environ, env, envent);
     54 		free(envent->name);
     55 		free(envent->value);
     56 		free(envent);
     57 	}
     58 }
     59 
     60 /* Copy one environment into another. */
     61 void
     62 environ_copy(struct environ *srcenv, struct environ *dstenv)
     63 {
     64 	struct environ_entry	*envent;
     65 
     66 	RB_FOREACH(envent, environ, srcenv)
     67 		environ_set(dstenv, envent->name, envent->value);
     68 }
     69 
     70 /* Find an environment variable. */
     71 struct environ_entry *
     72 environ_find(struct environ *env, const char *name)
     73 {
     74 	struct environ_entry	envent;
     75 
     76 	envent.name = __UNCONST(name);
     77 	return (RB_FIND(environ, env, &envent));
     78 }
     79 
     80 /* Set an environment variable. */
     81 void
     82 environ_set(struct environ *env, const char *name, const char *value)
     83 {
     84 	struct environ_entry	*envent;
     85 
     86 	if ((envent = environ_find(env, name)) != NULL) {
     87 		free(envent->value);
     88 		if (value != NULL)
     89 			envent->value = xstrdup(value);
     90 		else
     91 			envent->value = NULL;
     92 	} else {
     93 		envent = xmalloc(sizeof *envent);
     94 		envent->name = xstrdup(name);
     95 		if (value != NULL)
     96 			envent->value = xstrdup(value);
     97 		else
     98 			envent->value = NULL;
     99 		RB_INSERT(environ, env, envent);
    100 	}
    101 }
    102 
    103 /* Set an environment variable from a NAME=VALUE string. */
    104 void
    105 environ_put(struct environ *env, const char *var)
    106 {
    107 	char	*name, *value;
    108 
    109 	value = strchr(var, '=');
    110 	if (value == NULL)
    111 		return;
    112 	value++;
    113 
    114 	name = xstrdup(var);
    115 	name[strcspn(name, "=")] = '\0';
    116 
    117 	environ_set(env, name, value);
    118 	free(name);
    119 }
    120 
    121 /* Unset an environment variable. */
    122 void
    123 environ_unset(struct environ *env, const char *name)
    124 {
    125 	struct environ_entry	*envent;
    126 
    127 	if ((envent = environ_find(env, name)) == NULL)
    128 		return;
    129 	RB_REMOVE(environ, env, envent);
    130 	free(envent->name);
    131 	free(envent->value);
    132 	free(envent);
    133 }
    134 
    135 /*
    136  * Copy a space-separated list of variables from a destination into a source
    137  * environment.
    138  */
    139 void
    140 environ_update(const char *vars, struct environ *srcenv, struct environ *dstenv)
    141 {
    142 	struct environ_entry	*envent;
    143 	char			*copyvars, *var, *next;
    144 
    145 	copyvars = next = xstrdup(vars);
    146 	while ((var = strsep(&next, " ")) != NULL) {
    147 		if ((envent = environ_find(srcenv, var)) == NULL)
    148 			environ_set(dstenv, var, NULL);
    149 		else
    150 			environ_set(dstenv, envent->name, envent->value);
    151 	}
    152 	free(copyvars);
    153 }
    154 
    155 /* Push environment into the real environment - use after fork(). */
    156 void
    157 environ_push(struct environ *env)
    158 {
    159 	ARRAY_DECL(, char *)	varlist;
    160 	struct environ_entry   *envent;
    161 	char		      **varp, *var;
    162 	u_int			i;
    163 
    164 	ARRAY_INIT(&varlist);
    165 	for (varp = environ; *varp != NULL; varp++) {
    166 		var = xstrdup(*varp);
    167 		var[strcspn(var, "=")] = '\0';
    168 		ARRAY_ADD(&varlist, var);
    169 	}
    170 	for (i = 0; i < ARRAY_LENGTH(&varlist); i++)
    171 		unsetenv(ARRAY_ITEM(&varlist, i));
    172 	ARRAY_FREE(&varlist);
    173 
    174 	RB_FOREACH(envent, environ, env) {
    175 		if (envent->value != NULL)
    176 			setenv(envent->name, envent->value, 1);
    177 	}
    178 }
    179