xref: /titanic_41/usr/src/lib/libast/common/misc/setenviron.c (revision 160abee025ef30c34521b981edd40ffcaab560aa)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                      by AT&T Knowledge Ventures                      *
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  * put name=value in the environment
25  * pointer to value returned
26  * environ==0 is ok
27  *
28  *	setenviron("N=V")	add N=V
29  *	setenviron("N")		delete N
30  *	setenviron(0)		expect more (pre-fork optimization)
31  *
32  * _ always placed at the top
33  */
34 
35 #include <ast.h>
36 #include <fs3d.h>
37 
38 #define INCREMENT	16		/* environ increment		*/
39 
40 char*
41 setenviron(const char* akey)
42 {
43 	static char**	envv;		/* recorded environ		*/
44 	static char**	next;		/* next free slot		*/
45 	static char**	last;		/* last free slot (0)		*/
46 	static char	ok[] = "";	/* delete/optimization ok return*/
47 
48 	char*		key = (char*)akey;
49 	register char**	v = environ;
50 	register char**	p = envv;
51 	register char*	s;
52 	register char*	t;
53 	int		n;
54 
55 	ast.env_serial++;
56 	if (p && !v)
57 	{
58 		environ = next = p;
59 		*++next = 0;
60 	}
61 	else if (p != v || !v)
62 	{
63 		if (v)
64 		{
65 			while (*v++);
66 			n = v - environ + INCREMENT;
67 			v = environ;
68 		}
69 		else
70 			n = INCREMENT;
71 		if (!p || (last - p + 1) < n)
72 		{
73 			if (!p && fs3d(FS3D_TEST))
74 			{
75 				/*
76 				 * kick 3d initialization
77 				 */
78 
79 				close(open(".", O_RDONLY));
80 				v = environ;
81 			}
82 			if (!(p = newof(p, char*, n, 0)))
83 				return 0;
84 			last = p + n - 1;
85 		}
86 		envv = environ = p;
87 		if (v && v[0] && v[0][0] == '_' && v[0][1] == '=')
88 			*p++ = *v++;
89 		else
90 			*p++ = "_=";
91 		if (!v)
92 			*p = 0;
93 		else
94 			while (*p = *v++)
95 				if (p[0][0] == '_' && p[0][1] == '=')
96 					envv[0] = *p;
97 				else
98 					p++;
99 		next = p;
100 		p = envv;
101 	}
102 	else if (next == last)
103 	{
104 		n = last - v + INCREMENT + 1;
105 		if (!(p = newof(p, char*, n, 0)))
106 			return 0;
107 		last = p + n - 1;
108 		next = last - INCREMENT;
109 		envv = environ = p;
110 	}
111 	if (!key)
112 		return ok;
113 	for (; s = *p; p++)
114 	{
115 		t = key;
116 		do
117 		{
118 			if (!*t || *t == '=')
119 			{
120 				if (*s == '=')
121 				{
122 					if (!*t)
123 					{
124 						v = p++;
125 						while (*v++ = *p++);
126 						next--;
127 						return ok;
128 					}
129 					*p = key;
130 					return (s = strchr(key, '=')) ? s + 1 : (char*)0;
131 				}
132 				break;
133 			}
134 		} while (*t++ == *s++);
135 	}
136 	if (!(s = strchr(key, '=')))
137 		return ok;
138 	p = next;
139 	*++next = 0;
140 	*p = key;
141 	return s + 1;
142 }
143