Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/ksh93/sh/env.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1982-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* David Korn <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
#include <ast.h>
23
#include <cdt.h>
24
25
#define env_change() (++ast.env_serial)
26
27
typedef struct _venv_ Evar_t;
28
struct _venv_
29
{
30
union
31
{
32
Evar_t *next;
33
char *ptr;
34
} un;
35
Dtlink_t link;
36
int index;
37
};
38
39
typedef struct _env_
40
{
41
Dt_t *dt;
42
Evar_t *freelist;
43
char **env;
44
int count;
45
int extra;
46
int max;
47
int flags;
48
} Env_t;
49
50
#define _BLD_env 1
51
#include <env.h>
52
53
#define ENV_VALID 2 /* set if env is valid */
54
#define ENV_PMALLOC 1 /* set if Evar_t->un.ptr *s malloced */
55
#define ENV_VMALLOC 2 /* set of Evar_t was malloced */
56
#define ENV_BITS 3
57
58
/*
59
* Compares the name portion of name=... only.
60
*/
61
static int compare(Dt_t *dt, Void_t* key1, Void_t* key2, Dtdisc_t* disc)
62
{
63
register int c,d;
64
const unsigned char *s1=(unsigned const char*)key1;
65
const unsigned char *s2=(unsigned const char*)key2;
66
while((c= *s1++) && c!='=' && c==*s2)
67
s2++;
68
if(c=='=')
69
c = 0;
70
if((d=*s2)=='=')
71
d = 0;
72
return(c-d);
73
}
74
75
static Dtdisc_t env_disc =
76
{
77
0, -1,
78
sizeof(char*),
79
0,
80
0,
81
compare
82
};
83
84
/*
85
* return a pointer to the environment in sorted order
86
* NULL is returned if there if there is nospace
87
*/
88
char **env_get(Env_t* ep)
89
{
90
register Evar_t *vp;
91
register int n=ep->extra;
92
if(ep->flags&ENV_VALID)
93
return(ep->env+n);
94
if(ep->count > ep->max)
95
{
96
if(ep->flags&ENV_MALLOCED)
97
free((void*)ep->env);
98
if(!(ep->env = (char**)malloc(sizeof(char*)*(ep->count+1))))
99
return(0);
100
ep->flags |= ENV_MALLOCED;
101
ep->max = ep->count;
102
}
103
for(vp=(Evar_t*)dtfirst(ep->dt);vp; vp=(Evar_t*)dtnext(ep->dt,vp))
104
{
105
vp->index = (n<<ENV_BITS) | (vp->index&((1<<ENV_BITS)-1));
106
ep->env[n++] = vp->un.ptr;
107
}
108
ep->env[n] = 0;
109
ep->flags |= ENV_VALID;
110
environ = ep->env+ep->extra;
111
return(ep->env+ep->extra);
112
}
113
114
/*
115
* add name=value pair given by <str> to <ep>
116
* if malloced is set, the variable will be freed when reassigned
117
* The environment list may become invalidated
118
* Returns 1 for success, 0 for failure
119
*/
120
int env_add(Env_t *ep, const char *str, int flags)
121
{
122
Evar_t *vp = (Evar_t*)dtmatch(ep->dt,(void*)str);
123
if(vp && strcmp(str,vp->un.ptr)==0)
124
return(1);
125
if(flags&ENV_STRDUP)
126
str = strdup(str);
127
if(vp)
128
{
129
if(vp->index&ENV_PMALLOC)
130
free((void*)vp->un.ptr);
131
vp->un.ptr = (char*)str;
132
if(ep->env && (ep->flags&ENV_VALID))
133
ep->env[vp->index>>ENV_BITS] = vp->un.ptr;
134
}
135
else
136
{
137
ep->flags &= ~ENV_VALID;
138
if(vp = ep->freelist)
139
ep->freelist = vp->un.next;
140
else if(vp = newof((Evar_t*)0,Evar_t,2,0))
141
{
142
vp->index = ENV_VMALLOC;
143
ep->freelist = (vp+1);
144
ep->freelist->un.next = 0;
145
}
146
else
147
return(0);
148
vp->un.ptr = (void*)str;
149
if(!(vp=dtinsert(ep->dt,vp)))
150
return(0);
151
ep->count++;
152
}
153
if(flags)
154
vp->index |= ENV_PMALLOC;
155
else
156
vp->index &= ~ENV_PMALLOC;
157
env_change();
158
return(1);
159
}
160
161
/*
162
* delete name from <ep>
163
* The environment list may become invalidated
164
* Returns 1 for success, 0 for if name is not present
165
*/
166
int env_delete(Env_t *ep, const char *str)
167
{
168
Evar_t *vp = (Evar_t*)dtmatch(ep->dt,(void*)str);
169
if(!vp)
170
return(0);
171
ep->flags &= ~ENV_VALID;
172
if(vp->index&ENV_PMALLOC)
173
free((void*)vp->un.ptr);
174
dtdelete(ep->dt,vp);
175
vp->un.next = ep->freelist;
176
ep->freelist = vp;
177
env_change();
178
return(1);
179
}
180
181
/*
182
* open up a structure to support environment variables
183
* initialize with environment give by <envp>
184
* If <extra> > 0, <extra> slots will be left at beginning of
185
* environment list when env_get() is involed.
186
* If <extra>==ENV_USABLE, then the original environ can be
187
* used and returned. Otherwise, a new one will be returned
188
*/
189
Env_t *env_open(char **envp, int extra)
190
{
191
char **env;
192
Env_t *ep;
193
Evar_t *vp;
194
int n=2;
195
if(!(ep = newof((Env_t*)0,Env_t,1,0)))
196
return(0);
197
if(!(ep->dt = dtopen(&env_disc,Dtoset)))
198
return(0);
199
if(env=envp)
200
{
201
while(*env++);
202
n = (env+2)-envp;
203
}
204
if(extra==ENV_STABLE)
205
{
206
ep->env = envp;
207
ep->max = n-1;
208
}
209
else
210
ep->count = ep->extra = extra;
211
ep->freelist = vp = newof((Evar_t*)0,Evar_t,n,0);
212
vp->index = ENV_VMALLOC;
213
while(--n>0)
214
{
215
vp->un.next = (vp+1);
216
vp++;
217
}
218
vp->un.next = 0;
219
if(env)
220
{
221
for(env=envp; *env; env++)
222
env_add(ep,*env,0);
223
}
224
return(ep);
225
}
226
227
/*
228
* close <ep> and free up all space used by it
229
*/
230
void env_close(Env_t *ep)
231
{
232
Evar_t *vp, *vpnext,*top;
233
if(ep->env && (ep->flags&ENV_MALLOCED))
234
free((void*)ep->env);
235
for(vp=(Evar_t*)dtfirst(ep->dt);vp; vp=vpnext)
236
{
237
vpnext = (Evar_t*)dtnext(ep->dt,vp);
238
env_delete(ep,vp->un.ptr);
239
}
240
for(top=0,vp = ep->freelist; vp; vp = vpnext)
241
{
242
vpnext = vp->un.next;
243
if(vp->index&ENV_VMALLOC)
244
{
245
vp->un.next = top;
246
top = vp;
247
}
248
}
249
for(vp=top; vp; vp = vpnext)
250
{
251
vpnext = vp->un.next;
252
free((void*)vp);
253
}
254
dtclose(ep->dt);
255
}
256
257