/[pdpsoft]/trunk/grid-mw-security/cgul/environ/environ.c
ViewVC logotype

Contents of /trunk/grid-mw-security/cgul/environ/environ.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1449 - (show annotations) (download) (as text)
Tue Feb 2 02:35:46 2010 UTC (12 years, 6 months ago) by msalle
File MIME type: text/x-chdr
File size: 12867 byte(s)
- added new function setenv_dst() adding a name, value pair to the dst
  environment, similar to add_namevalue()

- check explicitly that whitelists aren't NULL, which lead to a segfault...


1 /**
2 * Copyright (c) Members of the EGEE Collaboration. 2010.
3 * See http://www.eu-egee.org/partners/ for details on the copyright
4 * holders.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Authors: Oscar Koeroo, Mischa Sall\'e, Aram Verstegen
19 * NIKHEF Amsterdam, the Netherlands
20 * <grid-mw-security@nikhef.nl>
21 */
22
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27
28 #include "environ.h"
29
30 /**
31 * returns number of entries in NULL terminated string array, such as argv and
32 * environ(7). In case list is NULL it also returns 0.
33 */
34 int strarrlen(const char **list) {
35 int entries;
36 /* Check if list exists: prevents common segfault situation */
37 if (!list) return 0;
38 /* Now loop over its entries */
39 for(entries=0; list[entries]; entries++);
40 return entries;
41 }
42
43 /**
44 * Returns the length of the name part of the var=value pair or -1 when there is
45 * no '=' sign.
46 */
47 int getvarnamelen(const char *varname) {
48 char *pos;
49 /* find first '=' */
50 pos=strchr(varname,'=');
51 if (pos==NULL) /* not var=value */
52 return -1;
53 return strlen(varname)-strlen(pos); /* no pointer arithmetics */
54 }
55
56
57 /**
58 * Finds name for given var=value pair in namevalue. varname is a buffer
59 * which will contain the result and has space for maxvarnamelen chars.
60 * Returns integer, negative on error, -1 on no '=' sign, -2 name too long;
61 * 0 success
62 */
63 int getvarname(char *varname,const int maxvarnamelen, const char *namevalue) {
64 int varnamelen;
65
66 if ((varnamelen=getvarnamelen(namevalue))==-1)
67 return -1;
68 if (varnamelen>maxvarnamelen)
69 return -2;
70 strncpy(varname,namevalue,varnamelen);
71 varname[varnamelen]='\0';
72
73 return 0;
74 }
75
76 /**
77 * Finds index in **src matching variable name, in case of no match (including
78 * env==NULL) returns -1
79 */
80 int getvarindex(const char **src, const char *varname) {
81 int i,len;
82
83 if (src==NULL || varname==NULL)
84 return -1;
85
86 len=strlen(varname);
87 /* Loop over env */
88 for (i=0; src[i]; i++) {
89 if (strncmp(src[i],varname,len)==0 && src[i][len]=='=')
90 /* Found match */
91 return i;
92 }
93 /* NO match found */
94 return -1;
95 }
96
97 /**
98 * Finds the value of varname in src list. Returns NULL when no match, incl.
99 * NULL valued src or varname.
100 */
101 char *getenv_src(const char **src, char *varname) {
102 int i,len;
103
104 /* Don't use getvarindex, since this saves us one strlen (-: */
105 if (src==NULL || varname==NULL)
106 return NULL;
107
108 len=strlen(varname);
109 /* Loop over env */
110 for (i=0; src[i]; i++) {
111 if (strncmp(src[i],varname,len)==0 && src[i][len]=='=')
112 /* Found match */
113 return (char *)&(src[i][len+1]);
114 }
115 /* NO match found */
116 return NULL;
117 }
118
119 /**
120 * As unsetenv(3) but using var=value pair, specified in namevalue. The maximum
121 * var length is MAXVARNAMELEN. See also putenv(3).
122 * Returns integer, 0 on success, negative on error.
123 */
124 int unsetenvpair(const char *namevalue) {
125 char varname[MAXENVVARNAMELEN];
126 int rc;
127
128 /* Get variable name for var=value pair */
129 if ((rc=getvarname(varname,MAXENVVARNAMELEN,namevalue))!=0)
130 return rc;
131 /* Unset variable */
132 if (unsetenv(varname))
133 return -1;
134
135 return 0;
136 }
137
138 /**
139 * Clears the entire environment
140 * Returns integer, -1 on error, 0 on success
141 */
142 int clear_env(void) {
143 while(environ[0])
144 if (unsetenvpair(environ[0]))
145 return -1;
146 return 0;
147 }
148
149 /*
150 * Clears the environment of all variables starting with pattern, case
151 * INsensitive.
152 * Returns number of cleaned entries, -1 on error.
153 */
154 int clear_env_pattern(const char *pattern) {
155 int i=0,match=0,patlen=strlen(pattern),rc;
156
157 while(environ[i]) {
158 if (strncasecmp(pattern,environ[i],patlen)==0) {
159 if ((rc=unsetenvpair(environ[i])))
160 return rc;
161 match++;
162 } else
163 i++; /* only increase when we haven't just removed an entry... */
164 }
165 return match;
166 }
167
168
169 /**
170 * Returns a duplicate of src. In case dst!=NULL it will be used and should be
171 * big enough. Otherwise space is malloced.
172 */
173 char **copy_env(char **dst,const char **src) {
174 int i,j,envlen;
175 char **newenv;
176
177 /* If no dst exists, malloc it. */
178 if (dst==NULL) {
179 envlen=strarrlen(src);
180 if ( (newenv=(char **)malloc((envlen+1)*sizeof(char*)))==NULL )
181 return NULL;
182 } else
183 newenv=dst;
184
185 /* Copy src to newenv */
186 for (i=0; src[i]; i++) {
187 if ( (newenv[i]=strdup(src[i]))==NULL ) {
188 /* Error: cleanup memory and reset */
189 for (j=0; j<i; j++)
190 free(newenv[j]);
191 if (dst==NULL)
192 free(newenv);
193 return NULL;
194 }
195 }
196 /* Finalize the new environ */
197 newenv[i]=NULL;
198
199 return newenv;
200 }
201
202 /**
203 * Same as copy_env() but first unsets all environment variables starting with
204 * MALLOC, case INsensitive.
205 */
206 char **safe_copy_env(char **dst,const char **src) {
207 /* Clean all MALLOC* variables */
208 if (clear_env_pattern("MALLOC"))
209 return NULL;
210
211 return copy_env(dst,src);
212 }
213
214 /**
215 * Creates a list of the var=value pairs from src which have varname in list.
216 * If it fails NULL is returned. This can also be done using add_src_list()
217 * using dst==NULL, but this is more efficiently coded. All new entries are
218 * strdup-ed from those in src.
219 */
220 char **copy_src_list(const char **src,const char **list) {
221 /* Create target space */
222 int i,j,src_idx,match=0,listlen=strarrlen(list);
223 char **newenv;
224
225 if ((newenv=(char **)malloc((listlen+1)*sizeof(char*)))==NULL)
226 return NULL;
227 /* IMPORTANT: list must be NULL terminated! */
228 newenv[0]=NULL;
229
230 /* Only do when list exists...*/
231 if (!list)
232 return newenv;
233
234 /* loop over list: Note we can have unmatched entries: match counts */
235 for (i=0; list[i]; i++) {
236 /* Look if list[i] is in src */
237 if ((src_idx=getvarindex(src,list[i]))>=0) {
238 /* Don't! check for duplicates... */
239 /* substitute existing: first try strdup */
240 if ((newenv[match]=strdup(src[src_idx]))==NULL) {
241 /* error: cleanup */
242 for (j=0; j<match; j++) {
243 free(newenv[j]); newenv[j]=NULL;
244 }
245 free(newenv);
246 return NULL;
247 }
248 match++;
249 /* Don't forget the final NULL pointer! */
250 newenv[match]=NULL;
251 }
252 }
253 return newenv;
254 }
255
256 /**
257 * Adds to dst the var=value pairs from src which have varname in list.
258 * All entries will be strdup-ed from those in src.
259 * If dst is NULL, it will create a new one. dst will be realloc-ed. If it fails
260 * NULL is returned, when failure occurs later on, dst will be returned, being
261 * equal to the original src but at a different memory location.
262 * See also copy_src_list() which is more efficient when dst is NULL !
263 */
264 char **add_src_list(char **dst,const char **src,const char **list) {
265 int i,j,src_idx,dst_idx,match=0;
266 int dstlen=strarrlen((const char**)dst),listlen=strarrlen(list);
267 char **newenv,*dummy;
268
269 /* Create space for combined array, might be too much if list is not fully
270 * used or partially replaces old entries, but more efficient (single
271 * realloc() call) */
272 if (dst==NULL) {
273 newenv=(char **)malloc((listlen+1)*sizeof(char*));
274 if (newenv==NULL)
275 return NULL;
276 /* IMPORTANT: list must be NULL terminated! */
277 newenv[0]=NULL;
278 } else {
279 newenv=(char **)realloc(dst,(dstlen+listlen+1)*sizeof(char*));
280 if (newenv==NULL)
281 return NULL;
282 }
283
284 /* Only do when list exists...*/
285 if (!list)
286 return newenv;
287
288 /* loop over list: Note we can have unmatched entries: match counts */
289 for (i=0; list[i]; i++) {
290 /* Look if list[i] is in src */
291 if ((src_idx=getvarindex(src,list[i]))>=0) {
292 /* Look for list[i] in dst/newenv: we might have it already. Note
293 * that this is not checked when using copy_src_list() */
294 if ((dst_idx=getvarindex((const char**)newenv,list[i]))>=0) {
295 /* substitute existing: first try strdup */
296 if ((dummy=strdup(src[src_idx]))==NULL) { /* error: cleanup */
297 for (j=dstlen; j<dstlen+match; j++) {
298 free(newenv[j]); newenv[j]=NULL;
299 }
300 return newenv;
301 }
302 /* Now substitute: free old entry in newenv and link to new
303 * entry */
304 free(newenv[dst_idx]);
305 newenv[dst_idx]=dummy;
306 } else {
307 /* create new one */
308 if ((newenv[dstlen+match]=strdup(src[src_idx]))==NULL) {
309 /* Error: cleanup */
310 for (j=dstlen; j<dstlen+match; j++) {
311 free(newenv[j]); newenv[j]=NULL;
312 }
313 return newenv;
314 }
315 /* We created a new entry, increase match */
316 match++;
317 /* Don't forget the final NULL pointer! */
318 newenv[dstlen+match]=NULL;
319 }
320 }
321 }
322 return newenv;
323 }
324
325 /**
326 * adds var=value pair to dst. If the variable already exists, it's entry is
327 * replaced. Otherwise dst is realloc-ed and a new entry is added, the resulting
328 * array is returned. In case of error NULL is returned and dst is unchanged.
329 * namevalue is strdup-ed into dst and hence can be freed by the caller (unlike
330 * putenv(3p) )
331 */
332 char **add_namevalue(char **dst,const char *namevalue) {
333 int i,namelen,dstlen;
334 char *namevaluecopy, **newenv;
335
336 /* Look for length of name part (no = means no name) */
337 if ((namelen=getvarnamelen(namevalue))<0)
338 return NULL;
339 /* Make already a copy, we need it in any case, unless realloc fails */
340 if ((namevaluecopy=strdup(namevalue))==NULL)
341 return NULL;
342 /* look for existing entry */
343 for (i=0; dst[i]; i++) {
344 if (strncmp(namevalue,dst[i],namelen)==0 && dst[i][namelen]=='=') {
345 free(dst[i]);
346 dst[i]=namevaluecopy;
347 return dst;
348 }
349 }
350 /* No old match, make a new entry, add two, because strarrlen doesn't count
351 * the NULL string at the end. First create new entry, since that's easier
352 * to undo. */
353 dstlen=strarrlen((const char **)dst);
354 if ((newenv=(char **)realloc(dst,(dstlen+2)*sizeof(char*)))==NULL) {
355 free(namevaluecopy);
356 return NULL;
357 }
358 newenv[dstlen]=namevaluecopy;
359 newenv[dstlen+1]=NULL;
360
361 return newenv;
362 }
363
364 /**
365 * adds name=value pair to dst, as in setenv() with a 'external environment' .
366 * If the variable already exists, it's entry is replaced. Otherwise dst is
367 * realloc-ed and a new entry is added, the resulting array is returned. In case
368 * of error NULL is returned and dst is unchanged. name and value can be freed
369 * by the caller (unlike putenv(3p) )
370 */
371 char **setenv_dst(char **dst,const char *name, const char *value) {
372 int i,namelen,valuelen,dstlen;
373 char *namevalue,**newenv;
374
375 /* Check arguments */
376 if (name==NULL)
377 return NULL;
378 if (value==NULL) {
379 value="";
380 valuelen=0;
381 } else
382 valuelen=strlen(value);
383 namelen=strlen(name);
384 /* Add two: = and \0 */
385 if ((namevalue=(char*)malloc((namelen+valuelen+2)*sizeof(char)))==NULL)
386 return NULL;
387 sprintf(namevalue,"%s=%s",name,value);
388
389 /* look for existing entry */
390 for (i=0; dst[i]; i++) {
391 if (strncmp(name,dst[i],namelen)==0 && dst[i][namelen]=='=') {
392 free(dst[i]);
393 dst[i]=namevalue;
394 return dst;
395 }
396 }
397 /* No old match, make a new entry, add two, because strarrlen doesn't count
398 * the NULL string at the end. */
399 dstlen=strarrlen((const char **)dst);
400 if ((newenv=(char **)realloc(dst,(dstlen+2)*sizeof(char*)))==NULL) {
401 free(namevalue);
402 return NULL;
403 }
404 newenv[dstlen]=namevalue;
405 newenv[dstlen+1]=NULL;
406
407 return newenv;
408 }
409
410 /**
411 * Adds to the current environment the var=value pairs from src which have
412 * varname in list. Returns number of entries added or -1 on error.
413 * NOTE: putenv doesn't reserve new memory so src should NOT be
414 * free()d.
415 */
416 int putenv_src_list(char **src,const char **list) {
417 int i,src_idx,match=0;
418
419 /* Only do when list exists...*/
420 if (!list)
421 return 0;
422
423 /* loop over list */
424 for (i=0; list[i]; i++) {
425 if ((src_idx=getvarindex((const char **)src,list[i]))>=0) {
426 /* Found match */
427 if (putenv(src[src_idx]))
428 return -1;
429 match++;
430 }
431 }
432 return match;
433 }
434
435 /**
436 * Adds to the current environment the var=value pairs from src which start with
437 * pattern. Returns number of entries added or -1 on error.
438 * NOTE: putenv doesn't reserve new memory so src should NOT be
439 * free()d.
440 */
441 int putenv_src_pattern(char **src,const char *pattern) {
442 int i,len=strlen(pattern),match=0;
443
444 /* loop over src environ */
445 for (i=0; src[i]; i++) {
446 if (strncmp(src[i],pattern,len)==0) {
447 /* Found match */
448 if (putenv(src[i]))
449 return -1;
450 match++;
451 }
452 }
453 return match;
454 }
455

grid.support@nikhef.nl
ViewVC Help
Powered by ViewVC 1.1.28