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
42char*
43setenviron(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