xref: /openbsd-src/usr.bin/tmux/environ.c (revision 43003dfe3ad45d1698bed8a37f2b0f5b14f20d4f)
1 /* $OpenBSD: environ.c,v 1.3 2009/08/09 15:17:50 nicm Exp $ */
2 
3 /*
4  * Copyright (c) 2009 Nicholas Marriott <nicm@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 void
39 environ_init(struct environ *env)
40 {
41 	RB_INIT(env);
42 }
43 
44 void
45 environ_free(struct environ *env)
46 {
47 	struct environ_entry	*envent;
48 
49 	while (!RB_EMPTY(env)) {
50 		envent = RB_ROOT(env);
51 		RB_REMOVE(environ, env, envent);
52 		xfree(envent->name);
53 		if (envent->value != NULL)
54 			xfree(envent->value);
55 		xfree(envent);
56 	}
57 }
58 
59 void
60 environ_copy(struct environ *srcenv, struct environ *dstenv)
61 {
62 	struct environ_entry	*envent;
63 
64 	RB_FOREACH(envent, environ, srcenv)
65 		environ_set(dstenv, envent->name, envent->value);
66 }
67 
68 struct environ_entry *
69 environ_find(struct environ *env, const char *name)
70 {
71 	struct environ_entry	envent;
72 
73 	envent.name = (char *) name;
74 	return (RB_FIND(environ, env, &envent));
75 }
76 
77 void
78 environ_set(struct environ *env, const char *name, const char *value)
79 {
80 	struct environ_entry	*envent;
81 
82 	if ((envent = environ_find(env, name)) != NULL) {
83 		if (envent->value != NULL)
84 			xfree(envent->value);
85 		if (value != NULL)
86 			envent->value = xstrdup(value);
87 		else
88 			envent->value = NULL;
89 	} else {
90 		envent = xmalloc(sizeof *envent);
91 		envent->name = xstrdup(name);
92 		if (value != NULL)
93 			envent->value = xstrdup(value);
94 		else
95 			envent->value = NULL;
96 		RB_INSERT(environ, env, envent);
97 	}
98 }
99 
100 void
101 environ_put(struct environ *env, const char *var)
102 {
103 	char		*name, *value;
104 
105 	value = strchr(var, '=');
106 	if (value == NULL)
107 		return;
108 	value++;
109 
110 	name = xstrdup(var);
111 	name[strcspn(name, "=")] = '\0';
112 
113 	environ_set(env, name, value);
114 	xfree(name);
115 }
116 
117 void
118 environ_unset(struct environ *env, const char *name)
119 {
120 	struct environ_entry	*envent;
121 
122 	if ((envent = environ_find(env, name)) == NULL)
123 		return;
124 	RB_REMOVE(environ, env, envent);
125 	xfree(envent->name);
126 	if (envent->value != NULL)
127 		xfree(envent->value);
128 	xfree(envent);
129 }
130 
131 void
132 environ_update(const char *vars, struct environ *srcenv, struct environ *dstenv)
133 {
134 	struct environ_entry	*envent;
135 	char			*copyvars, *var, *next;
136 
137 	copyvars = next = xstrdup(vars);
138 	while ((var = strsep(&next, " ")) != NULL) {
139 		if ((envent = environ_find(srcenv, var)) == NULL)
140 			environ_set(dstenv, var, NULL);
141 		else
142 			environ_set(dstenv, envent->name, envent->value);
143 	}
144 	xfree(copyvars);
145 }
146