GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/tmux/environ.c Lines: 0 62 0.0 %
Date: 2016-12-06 Branches: 0 236 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: environ.c,v 1.15 2016/07/15 09:52:34 nicm Exp $ */
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
24
#include "tmux.h"
25
26
/*
27
 * Environment - manipulate a set of environment variables.
28
 */
29
30
RB_HEAD(environ, environ_entry);
31
int	environ_cmp(struct environ_entry *, struct environ_entry *);
32
RB_PROTOTYPE(environ, environ_entry, entry, environ_cmp);
33
RB_GENERATE(environ, environ_entry, entry, environ_cmp);
34
35
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
/*
174
 * Copy a space-separated list of variables from a destination into a source
175
 * environment.
176
 */
177
void
178
environ_update(const char *vars, struct environ *srcenv,
179
    struct environ *dstenv)
180
{
181
	struct environ_entry	*envent;
182
	char			*copyvars, *var, *next;
183
184
	copyvars = next = xstrdup(vars);
185
	while ((var = strsep(&next, " ")) != NULL) {
186
		if ((envent = environ_find(srcenv, var)) == NULL)
187
			environ_clear(dstenv, var);
188
		else
189
			environ_set(dstenv, envent->name, "%s", envent->value);
190
	}
191
	free(copyvars);
192
}
193
194
/* Push environment into the real environment - use after fork(). */
195
void
196
environ_push(struct environ *env)
197
{
198
	struct environ_entry	*envent;
199
200
	environ = xcalloc(1, sizeof *environ);
201
	RB_FOREACH(envent, environ, env) {
202
		if (envent->value != NULL && *envent->name != '\0')
203
			setenv(envent->name, envent->value, 1);
204
	}
205
}
206
207
/* Log the environment. */
208
void
209
environ_log(struct environ *env, const char *prefix)
210
{
211
	struct environ_entry	*envent;
212
213
	RB_FOREACH(envent, environ, env) {
214
		if (envent->value != NULL && *envent->name != '\0') {
215
			log_debug("%s%s=%s", prefix, envent->name,
216
			    envent->value);
217
		}
218
	}
219
}