1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1982-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * David Korn <dgk@research.att.com> *
19 ***********************************************************************/
25 #define env_change() (++ast.env_serial)
27 typedef struct _venv_ Evar_t
;
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 */
59 * Compares the name portion of name=... only.
61 static int compare(Dt_t
*dt
, Void_t
* key1
, Void_t
* key2
, Dtdisc_t
* disc
)
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
)
75 static Dtdisc_t env_disc
=
85 * return a pointer to the environment in sorted order
86 * NULL is returned if there if there is nospace
88 char **env_get(Env_t
* ep
)
91 register int n
=ep
->extra
;
92 if(ep
->flags
&ENV_VALID
)
94 if(ep
->count
> ep
->max
)
96 if(ep
->flags
&ENV_MALLOCED
)
98 if(!(ep
->env
= (char**)malloc(sizeof(char*)*(ep
->count
+1))))
100 ep
->flags
|= ENV_MALLOCED
;
103 for(vp
=(Evar_t
*)dtfirst(ep
->dt
);vp
; vp
=(Evar_t
*)dtnext(ep
->dt
,vp
))
105 vp
->index
= (n
<<ENV_BITS
) | (vp
->index
&((1<<ENV_BITS
)-1));
106 ep
->env
[n
++] = vp
->un
.ptr
;
109 ep
->flags
|= ENV_VALID
;
110 environ
= ep
->env
+ep
->extra
;
111 return(ep
->env
+ep
->extra
);
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
120 int env_add(Env_t
*ep
, const char *str
, int flags
)
122 Evar_t
*vp
= (Evar_t
*)dtmatch(ep
->dt
,(void*)str
);
123 if(vp
&& strcmp(str
,vp
->un
.ptr
)==0)
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
;
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))
142 vp
->index
= ENV_VMALLOC
;
143 ep
->freelist
= (vp
+1);
144 ep
->freelist
->un
.next
= 0;
148 vp
->un
.ptr
= (void*)str
;
149 if(!(vp
=dtinsert(ep
->dt
,vp
)))
154 vp
->index
|= ENV_PMALLOC
;
156 vp
->index
&= ~ENV_PMALLOC
;
162 * delete name from <ep>
163 * The environment list may become invalidated
164 * Returns 1 for success, 0 for if name is not present
166 int env_delete(Env_t
*ep
, const char *str
)
168 Evar_t
*vp
= (Evar_t
*)dtmatch(ep
->dt
,(void*)str
);
171 ep
->flags
&= ~ENV_VALID
;
172 if(vp
->index
&ENV_PMALLOC
)
173 free((void*)vp
->un
.ptr
);
175 vp
->un
.next
= ep
->freelist
;
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
189 Env_t
*env_open(char **envp
, int extra
)
195 if(!(ep
= newof((Env_t
*)0,Env_t
,1,0)))
197 if(!(ep
->dt
= dtopen(&env_disc
,Dtoset
)))
204 if(extra
==ENV_STABLE
)
210 ep
->count
= ep
->extra
= extra
;
211 ep
->freelist
= vp
= newof((Evar_t
*)0,Evar_t
,n
,0);
212 vp
->index
= ENV_VMALLOC
;
215 vp
->un
.next
= (vp
+1);
221 for(env
=envp
; *env
; env
++)
228 * close <ep> and free up all space used by it
230 void env_close(Env_t
*ep
)
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
)
237 vpnext
= (Evar_t
*)dtnext(ep
->dt
,vp
);
238 env_delete(ep
,vp
->un
.ptr
);
240 for(top
=0,vp
= ep
->freelist
; vp
; vp
= vpnext
)
242 vpnext
= vp
->un
.next
;
243 if(vp
->index
&ENV_VMALLOC
)
249 for(vp
=top
; vp
; vp
= vpnext
)
251 vpnext
= vp
->un
.next
;