xref: /illumos-gate/usr/src/boot/libsa/environment.c (revision 22028508)
1*22028508SToomas Soome /*
2*22028508SToomas Soome  * Copyright (c) 1998 Michael Smith.
3*22028508SToomas Soome  * All rights reserved.
4*22028508SToomas Soome  *
5*22028508SToomas Soome  * Redistribution and use in source and binary forms, with or without
6*22028508SToomas Soome  * modification, are permitted provided that the following conditions
7*22028508SToomas Soome  * are met:
8*22028508SToomas Soome  * 1. Redistributions of source code must retain the above copyright
9*22028508SToomas Soome  *    notice, this list of conditions and the following disclaimer.
10*22028508SToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
11*22028508SToomas Soome  *    notice, this list of conditions and the following disclaimer in the
12*22028508SToomas Soome  *    documentation and/or other materials provided with the distribution.
13*22028508SToomas Soome  *
14*22028508SToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*22028508SToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*22028508SToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*22028508SToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*22028508SToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*22028508SToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*22028508SToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*22028508SToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*22028508SToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*22028508SToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*22028508SToomas Soome  * SUCH DAMAGE.
25*22028508SToomas Soome  */
26*22028508SToomas Soome 
27*22028508SToomas Soome #include <sys/cdefs.h>
28*22028508SToomas Soome 
29*22028508SToomas Soome /*
30*22028508SToomas Soome  * Manage an environment-like space in which string variables may be stored.
31*22028508SToomas Soome  * Provide support for some method-like operations for setting/retrieving
32*22028508SToomas Soome  * variables in order to allow some type strength.
33*22028508SToomas Soome  */
34*22028508SToomas Soome 
35*22028508SToomas Soome #include "stand.h"
36*22028508SToomas Soome 
37*22028508SToomas Soome #include <string.h>
38*22028508SToomas Soome 
39*22028508SToomas Soome struct env_var *environ = NULL;
40*22028508SToomas Soome 
41*22028508SToomas Soome /*
42*22028508SToomas Soome  * Look up (name) and return it's env_var structure.
43*22028508SToomas Soome  */
44*22028508SToomas Soome struct env_var	*
env_getenv(const char * name)45*22028508SToomas Soome env_getenv(const char *name)
46*22028508SToomas Soome {
47*22028508SToomas Soome 	struct env_var	*ev;
48*22028508SToomas Soome 
49*22028508SToomas Soome 	for (ev = environ; ev != NULL; ev = ev->ev_next)
50*22028508SToomas Soome 		if (strcmp(ev->ev_name, name) == 0)
51*22028508SToomas Soome 			break;
52*22028508SToomas Soome 	return (ev);
53*22028508SToomas Soome }
54*22028508SToomas Soome 
55*22028508SToomas Soome /*
56*22028508SToomas Soome  * Some notes:
57*22028508SToomas Soome  *
58*22028508SToomas Soome  * If the EV_VOLATILE flag is set, a copy of the variable is made.
59*22028508SToomas Soome  * If EV_DYNAMIC is set, the variable has been allocated with
60*22028508SToomas Soome  * malloc and ownership transferred to the environment.
61*22028508SToomas Soome  * If (value) is NULL, the variable is set but has no value.
62*22028508SToomas Soome  */
63*22028508SToomas Soome int
env_setenv(const char * name,int flags,const void * value,ev_sethook_t sethook,ev_unsethook_t unsethook)64*22028508SToomas Soome env_setenv(const char *name, int flags, const void *value,
65*22028508SToomas Soome     ev_sethook_t sethook, ev_unsethook_t unsethook)
66*22028508SToomas Soome {
67*22028508SToomas Soome 	struct env_var	*ev, *curr, *last;
68*22028508SToomas Soome 
69*22028508SToomas Soome 	if ((ev = env_getenv(name)) != NULL) {
70*22028508SToomas Soome 		/*
71*22028508SToomas Soome 		 * If there's a set hook, let it do the work
72*22028508SToomas Soome 		 * (unless we are working for one already).
73*22028508SToomas Soome 		 */
74*22028508SToomas Soome 		if ((ev->ev_sethook != NULL) && !(flags & EV_NOHOOK))
75*22028508SToomas Soome 			return (ev->ev_sethook(ev, flags, value));
76*22028508SToomas Soome 
77*22028508SToomas Soome 		/* If there is data in the variable, discard it. */
78*22028508SToomas Soome 		if (ev->ev_value != NULL && (ev->ev_flags & EV_DYNAMIC) != 0)
79*22028508SToomas Soome 			free(ev->ev_value);
80*22028508SToomas Soome 		ev->ev_value = NULL;
81*22028508SToomas Soome 		ev->ev_flags &= ~EV_DYNAMIC;
82*22028508SToomas Soome 
83*22028508SToomas Soome 	} else {
84*22028508SToomas Soome 		/*
85*22028508SToomas Soome 		 * New variable; create and sort into list
86*22028508SToomas Soome 		 */
87*22028508SToomas Soome 		ev = malloc(sizeof (struct env_var));
88*22028508SToomas Soome 		ev->ev_name = strdup(name);
89*22028508SToomas Soome 		ev->ev_value = NULL;
90*22028508SToomas Soome 		ev->ev_flags = 0;
91*22028508SToomas Soome 		/* hooks can only be set when the variable is instantiated */
92*22028508SToomas Soome 		ev->ev_sethook = sethook;
93*22028508SToomas Soome 		ev->ev_unsethook = unsethook;
94*22028508SToomas Soome 
95*22028508SToomas Soome 		/* Sort into list */
96*22028508SToomas Soome 		ev->ev_prev = NULL;
97*22028508SToomas Soome 		ev->ev_next = NULL;
98*22028508SToomas Soome 		/* Search for the record to insert before */
99*22028508SToomas Soome 		for (last = NULL, curr = environ; curr != NULL;
100*22028508SToomas Soome 		    last = curr, curr = curr->ev_next) {
101*22028508SToomas Soome 
102*22028508SToomas Soome 			if (strcmp(ev->ev_name, curr->ev_name) < 0) {
103*22028508SToomas Soome 				if (curr->ev_prev) {
104*22028508SToomas Soome 					curr->ev_prev->ev_next = ev;
105*22028508SToomas Soome 				} else {
106*22028508SToomas Soome 					environ = ev;
107*22028508SToomas Soome 				}
108*22028508SToomas Soome 				ev->ev_next = curr;
109*22028508SToomas Soome 				ev->ev_prev = curr->ev_prev;
110*22028508SToomas Soome 				curr->ev_prev = ev;
111*22028508SToomas Soome 				break;
112*22028508SToomas Soome 			}
113*22028508SToomas Soome 		}
114*22028508SToomas Soome 		if (curr == NULL) {
115*22028508SToomas Soome 			if (last == NULL) {
116*22028508SToomas Soome 				environ = ev;
117*22028508SToomas Soome 			} else {
118*22028508SToomas Soome 				last->ev_next = ev;
119*22028508SToomas Soome 				ev->ev_prev = last;
120*22028508SToomas Soome 			}
121*22028508SToomas Soome 		}
122*22028508SToomas Soome 	}
123*22028508SToomas Soome 
124*22028508SToomas Soome 	/* If we have a new value, use it */
125*22028508SToomas Soome 	if (flags & EV_VOLATILE) {
126*22028508SToomas Soome 		ev->ev_value = strdup(value);
127*22028508SToomas Soome 		ev->ev_flags |= EV_DYNAMIC;
128*22028508SToomas Soome 	} else {
129*22028508SToomas Soome 		ev->ev_value = (char *)value;
130*22028508SToomas Soome 		ev->ev_flags |= flags & EV_DYNAMIC;
131*22028508SToomas Soome 	}
132*22028508SToomas Soome 
133*22028508SToomas Soome 	return (0);
134*22028508SToomas Soome }
135*22028508SToomas Soome 
136*22028508SToomas Soome char *
getenv(const char * name)137*22028508SToomas Soome getenv(const char *name)
138*22028508SToomas Soome {
139*22028508SToomas Soome 	struct env_var	*ev;
140*22028508SToomas Soome 
141*22028508SToomas Soome 	/* Set but no value gives empty string */
142*22028508SToomas Soome 	if ((ev = env_getenv(name)) != NULL) {
143*22028508SToomas Soome 		if (ev->ev_value != NULL)
144*22028508SToomas Soome 			return (ev->ev_value);
145*22028508SToomas Soome 		return ("");
146*22028508SToomas Soome 	}
147*22028508SToomas Soome 	return (NULL);
148*22028508SToomas Soome }
149*22028508SToomas Soome 
150*22028508SToomas Soome int
setenv(const char * name,const char * value,int overwrite)151*22028508SToomas Soome setenv(const char *name, const char *value, int overwrite)
152*22028508SToomas Soome {
153*22028508SToomas Soome 	/* No guarantees about state, always assume volatile */
154*22028508SToomas Soome 	if (overwrite || (env_getenv(name) == NULL))
155*22028508SToomas Soome 		return (env_setenv(name, EV_VOLATILE, value, NULL, NULL));
156*22028508SToomas Soome 	return (0);
157*22028508SToomas Soome }
158*22028508SToomas Soome 
159*22028508SToomas Soome int
putenv(const char * string)160*22028508SToomas Soome putenv(const char *string)
161*22028508SToomas Soome {
162*22028508SToomas Soome 	char	*value, *copy;
163*22028508SToomas Soome 	int	result;
164*22028508SToomas Soome 
165*22028508SToomas Soome 	copy = strdup(string);
166*22028508SToomas Soome 	if ((value = strchr(copy, '=')) != NULL)
167*22028508SToomas Soome 		*(value++) = 0;
168*22028508SToomas Soome 	result = setenv(copy, value, 1);
169*22028508SToomas Soome 	free(copy);
170*22028508SToomas Soome 	return (result);
171*22028508SToomas Soome }
172*22028508SToomas Soome 
173*22028508SToomas Soome int
unsetenv(const char * name)174*22028508SToomas Soome unsetenv(const char *name)
175*22028508SToomas Soome {
176*22028508SToomas Soome 	struct env_var	*ev;
177*22028508SToomas Soome 	int		err;
178*22028508SToomas Soome 
179*22028508SToomas Soome 	err = 0;
180*22028508SToomas Soome 	if ((ev = env_getenv(name)) == NULL) {
181*22028508SToomas Soome 		err = ENOENT;
182*22028508SToomas Soome 	} else {
183*22028508SToomas Soome 		if (ev->ev_unsethook != NULL)
184*22028508SToomas Soome 			err = ev->ev_unsethook(ev);
185*22028508SToomas Soome 		if (err == 0) {
186*22028508SToomas Soome 			env_discard(ev);
187*22028508SToomas Soome 		}
188*22028508SToomas Soome 	}
189*22028508SToomas Soome 	return (err);
190*22028508SToomas Soome }
191*22028508SToomas Soome 
192*22028508SToomas Soome void
env_discard(struct env_var * ev)193*22028508SToomas Soome env_discard(struct env_var *ev)
194*22028508SToomas Soome {
195*22028508SToomas Soome 	if (ev->ev_prev)
196*22028508SToomas Soome 		ev->ev_prev->ev_next = ev->ev_next;
197*22028508SToomas Soome 	if (ev->ev_next)
198*22028508SToomas Soome 		ev->ev_next->ev_prev = ev->ev_prev;
199*22028508SToomas Soome 	if (environ == ev)
200*22028508SToomas Soome 		environ = ev->ev_next;
201*22028508SToomas Soome 	free(ev->ev_name);
202*22028508SToomas Soome 	if (ev->ev_value != NULL && (ev->ev_flags & EV_DYNAMIC) != 0)
203*22028508SToomas Soome 		free(ev->ev_value);
204*22028508SToomas Soome 	free(ev);
205*22028508SToomas Soome }
206*22028508SToomas Soome 
207*22028508SToomas Soome int
env_noset(struct env_var * ev __unused,int flags __unused,const void * value __unused)208*22028508SToomas Soome env_noset(struct env_var *ev __unused, int flags __unused,
209*22028508SToomas Soome     const void *value __unused)
210*22028508SToomas Soome {
211*22028508SToomas Soome 	return (EPERM);
212*22028508SToomas Soome }
213*22028508SToomas Soome 
214*22028508SToomas Soome int
env_nounset(struct env_var * ev __unused)215*22028508SToomas Soome env_nounset(struct env_var *ev __unused)
216*22028508SToomas Soome {
217*22028508SToomas Soome 	return (EPERM);
218*22028508SToomas Soome }
219