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*
setenviron(const char * akey)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