xref: /titanic_41/usr/src/lib/libast/common/misc/setenviron.c (revision fbe82215144da71ed02c3a920667472cc567fafd)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *            http://www.opensource.org/licenses/cpl1.0.txt             *
11 *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                  David Korn <dgk@research.att.com>                   *
19 *                   Phong Vo <kpv@research.att.com>                    *
20 *                                                                      *
21 ***********************************************************************/
22 #pragma prototyped
23 
24 #include "intercepts.h"
25 
26 #include <fs3d.h>
27 
28 /*
29  * put name=value in the environment
30  * pointer to value returned
31  * environ==0 is ok
32  *
33  *	setenviron("N=V")	add N=V
34  *	setenviron("N")		delete N
35  *	setenviron(0)		expect more (pre-fork optimization)
36  *
37  * _ always placed at the top
38  */
39 
40 #define INCREMENT	16		/* environ increment		*/
41 
42 char*
43 setenviron(const char* akey)
44 {
45 #undef	setenviron
46 	static char**	envv;		/* recorded environ		*/
47 	static char**	next;		/* next free slot		*/
48 	static char**	last;		/* last free slot (0)		*/
49 	static char	ok[] = "";	/* delete/optimization ok return*/
50 
51 	char*		key = (char*)akey;
52 	register char**	v = environ;
53 	register char**	p = envv;
54 	register char*	s;
55 	register char*	t;
56 	int		n;
57 
58 	ast.env_serial++;
59 	if (intercepts.intercept_setenviron)
60 		return (*intercepts.intercept_setenviron)(akey);
61 	if (p && !v)
62 	{
63 		environ = next = p;
64 		*++next = 0;
65 	}
66 	else if (p != v || !v)
67 	{
68 		if (v)
69 		{
70 			while (*v++);
71 			n = v - environ + INCREMENT;
72 			v = environ;
73 		}
74 		else
75 			n = INCREMENT;
76 		if (!p || (last - p + 1) < n)
77 		{
78 			if (!p && fs3d(FS3D_TEST))
79 			{
80 				/*
81 				 * kick 3d initialization
82 				 */
83 
84 				close(open(".", O_RDONLY));
85 				v = environ;
86 			}
87 			if (!(p = newof(p, char*, n, 0)))
88 				return 0;
89 			last = p + n - 1;
90 		}
91 		envv = environ = p;
92 		if (v && v[0] && v[0][0] == '_' && v[0][1] == '=')
93 			*p++ = *v++;
94 		else
95 			*p++ = "_=";
96 		if (!v)
97 			*p = 0;
98 		else
99 			while (*p = *v++)
100 				if (p[0][0] == '_' && p[0][1] == '=')
101 					envv[0] = *p;
102 				else
103 					p++;
104 		next = p;
105 		p = envv;
106 	}
107 	else if (next == last)
108 	{
109 		n = last - v + INCREMENT + 1;
110 		if (!(p = newof(p, char*, n, 0)))
111 			return 0;
112 		last = p + n - 1;
113 		next = last - INCREMENT;
114 		envv = environ = p;
115 	}
116 	if (!key)
117 		return ok;
118 	for (; s = *p; p++)
119 	{
120 		t = key;
121 		do
122 		{
123 			if (!*t || *t == '=')
124 			{
125 				if (*s == '=')
126 				{
127 					if (!*t)
128 					{
129 						v = p++;
130 						while (*v++ = *p++);
131 						next--;
132 						return ok;
133 					}
134 					*p = key;
135 					return (s = strchr(key, '=')) ? s + 1 : (char*)0;
136 				}
137 				break;
138 			}
139 		} while (*t++ == *s++);
140 	}
141 	if (!(s = strchr(key, '=')))
142 		return ok;
143 	p = next;
144 	*++next = 0;
145 	*p = key;
146 	return s + 1;
147 }
148