/[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 1452 - (show annotations) (download) (as text)
Tue Feb 2 19:09:23 2010 UTC (11 years, 11 months ago) by msalle
File MIME type: text/x-chdr
File size: 13698 byte(s)
- introducing env_t (char **): now use &dst for creation/updating of
  environments instead of return value of functions.
  This makes it easier to have a few additions in a row etc.

- make sure when input whitelist and/or src is null everything works as
  expected: new environment should be created and initialized to empty, old
  environment should be left unchanged.

- make sure environ.h is effectively included once using a #ifndef

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 env_t 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 env_t 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 * Creates a duplicate of src. In case *dst!=NULL it will be used and should be
171 * big enough. Otherwise space is malloc-ed. dst is only updated upon success.
172 * Returns -1 upon error, 0 on success.
173 */
174 int copy_env(env_t *dst,const env_t src) {
175 int i,j,envlen;
176 env_t newenv=*dst;
177
178 /* If no dst exists, malloc it. */
179 if (newenv==NULL) {
180 envlen=strarrlen((const char**)src);
181 newenv=(env_t)malloc((envlen+1)*sizeof(char*));
182 if (newenv==NULL)
183 return -1;
184 }
185
186 /* Copy src to newenv */
187 for (i=0; src[i]; i++) {
188 if ( (newenv[i]=strdup(src[i]))==NULL ) {
189 /* Error: cleanup memory and reset */
190 for (j=0; j<i; j++)
191 free(newenv[j]);
192 if (*dst==NULL)
193 free(newenv);
194 return -1;
195 }
196 }
197 /* Finalize the new environ */
198 newenv[i]=NULL;
199 if (*dst==NULL)
200 *dst=newenv;
201
202 return 0;
203 }
204
205 /**
206 * Same as copy_env() but first unsets all environment variables starting with
207 * MALLOC, case INsensitive. dst is again only updated upon success.
208 * Returns -1 upon error, 0 on success.
209 */
210 int safe_copy_env(env_t *dst,const env_t src) {
211 /* Clean all MALLOC* variables */
212 if (clear_env_pattern("MALLOC"))
213 return -1;
214
215 return copy_env(dst,src);
216 }
217
218 /**
219 * Creates a list of the var=value pairs from src which have varname in list.
220 * If it fails NULL is returned. This can also be done using add_src_list()
221 * using dst==NULL, but this is more efficiently coded. All new entries are
222 * strdup-ed from those in src.
223 */
224 env_t copy_src_list(const env_t src,const char *list[]) {
225 int i,j,src_idx,match=0,listlen=strarrlen(list);
226 env_t newenv;
227
228 /* Malloc space */
229 newenv=(env_t)malloc((listlen+1)*sizeof(char*));
230 if (newenv==NULL)
231 return NULL;
232
233 /* IMPORTANT: list must be NULL terminated! */
234 newenv[0]=NULL;
235
236 /* Only do when list exists, otherwise return empty list, but not NO list!
237 * Note it's not an error, just an empty list. */
238 if (src==NULL || list==NULL)
239 return newenv;
240
241 /* loop over list: Note we can have unmatched entries: match counts */
242 for (i=0; list[i]; i++) {
243 /* Look if list[i] is in src */
244 if ( (src_idx=getvarindex(src,list[i])) >= 0) {
245 /* Don't! check for duplicates... */
246 /* substitute existing: first try strdup */
247 if ((newenv[match]=strdup(src[src_idx]))==NULL) {
248 /* error: cleanup */
249 for (j=0; j<match; j++) {
250 free(newenv[j]); newenv[j]=NULL;
251 }
252 free(newenv);
253 return NULL;
254 }
255 match++;
256 /* Don't forget the final NULL pointer! */
257 newenv[match]=NULL;
258 }
259 }
260 return newenv;
261 }
262
263 /**
264 * Adds to dst the var=value pairs from src which have varname in list.
265 * All entries will be strdup-ed from those in src.
266 * If *dst is NULL, it will be malloc-ed, otherwise it will be realloc-ed.
267 * Upon success returns 0. On error -1 is returned, and dst stays unchanged.
268 * See also copy_src_list() which is more efficient when dst is NULL !
269 */
270 int add_src_list(env_t *dst,const env_t src,const char **list) {
271 int i,j,src_idx,dst_idx,match=0;
272 env_t newenv=*dst;
273 int dstlen,listlen;
274 char *dummy;
275
276 dstlen=strarrlen((const char **)*dst);
277 listlen=strarrlen(list);
278 /* Create space for combined array, might be too much if list is not fully
279 * used or partially replaces old entries, but more efficient (single
280 * realloc() call).
281 * Note that we check for empty list AFTER the malloc, and BEFORE the
282 * realloc */
283 if (newenv==NULL) {
284 newenv=(env_t)malloc((listlen+1)*sizeof(char*));
285 if (newenv==NULL)
286 return -1;
287 *dst=newenv; /* update *dst after malloc */
288 /* IMPORTANT: list must be NULL terminated! */
289 newenv[0]=NULL;
290 /* Only continue when list and src exist, do alloc in this case, since
291 * dst shouldn't return empty. Not an error. */
292 if (list==NULL || src==NULL)
293 return 0;
294 } else {
295 /* Only do when list and src exist, no need to realloc, not an error. */
296 if (list==NULL || src==NULL)
297 return 0;
298 newenv=(env_t)realloc(newenv,(dstlen+listlen+1)*sizeof(char*));
299 if (newenv==NULL)
300 return -1;
301 *dst=newenv; /* update *dst after realloc */
302 }
303
304 /* loop over list: Note we can have unmatched entries: match counts */
305 for (i=0; list[i]; i++) {
306 /* Look if list[i] is in src */
307 if ( (src_idx=getvarindex(src,list[i])) >= 0) {
308 /* Look for list[i] in newenv: we might have it already. Note
309 * that this is not checked when using copy_src_list() */
310 if ( (dst_idx=getvarindex((const env_t)newenv,list[i])) >= 0) {
311 /* substitute existing: first try strdup */
312 if ( (dummy=strdup(src[src_idx])) == NULL) { /* error: cleanup*/
313 for (j=dstlen; j<dstlen+match; j++) {
314 free(newenv[j]); newenv[j]=NULL;
315 }
316 return -1;
317 }
318 /* Now substitute: free old entry in newenv and link to new
319 * entry */
320 free(newenv[dst_idx]);
321 newenv[dst_idx]=dummy;
322 } else {
323 /* create new one */
324 if ((newenv[dstlen+match]=strdup(src[src_idx]))==NULL) {
325 /* Error: cleanup */
326 for (j=dstlen; j<dstlen+match; j++) {
327 free(newenv[j]); newenv[j]=NULL;
328 }
329 return -1;
330 }
331 /* We created a new entry, increase match */
332 match++;
333 /* Don't forget the final NULL pointer! */
334 newenv[dstlen+match]=NULL;
335 }
336 }
337 }
338 return 0;
339 }
340
341 /**
342 * adds var=value pair to dst. If the variable already exists, it's entry is
343 * replaced. Otherwise *dst is realloc-ed and a new entry is added, the
344 * resulting array is returned.
345 * Upon success returns 0. In case of error -1 is returned and dst remains
346 * unchanged. namevalue is strdup-ed into dst and hence can be freed by the
347 * caller (unlike putenv(3p) )
348 */
349 int add_namevalue(env_t *dst,const char *namevalue) {
350 int i,namelen,dstlen;
351 char *namevaluecopy;
352 env_t newenv=*dst;
353
354 /* Look for length of name part (no = means no name) */
355 if ( (namelen=getvarnamelen(namevalue)) < 0)
356 return -1;
357 /* Make already a copy, we need it in any case, unless realloc fails */
358 if ( (namevaluecopy=strdup(namevalue)) == NULL)
359 return -1;
360 /* look for existing entry */
361 for (i=0; newenv[i]; i++) {
362 if (strncmp(namevalue,newenv[i],namelen)==0 && newenv[i][namelen]=='=')
363 {
364 free(newenv[i]);
365 newenv[i]=namevaluecopy;
366 return 0;
367 }
368 }
369 /* No old match, make a new entry, add two, because strarrlen doesn't count
370 * the NULL string at the end. First create new entry, since that's easier
371 * to undo. */
372 dstlen=strarrlen((const char**)newenv);
373 newenv=(env_t)realloc(newenv,(dstlen+2)*sizeof(char*));
374 if (newenv==NULL) {
375 free(namevaluecopy);
376 return -1;
377 }
378 *dst=newenv; /* update *dst after (re/m)alloc */
379 newenv[dstlen]=namevaluecopy;
380 newenv[dstlen+1]=NULL;
381
382 return 0;
383 }
384
385 /**
386 * adds name=value pair to dst, as in setenv() with a 'external environment' .
387 * If the variable already exists, it's entry is replaced. Otherwise *dst is
388 * realloc-ed and a new entry is added.
389 * Upon success returns 0. In case of error -1 is returned and dst remains
390 * unchanged. name and value can be freed by the caller (unlike putenv(3p) )
391 */
392 int setenv_dst(env_t *dst,const char *name, const char *value) {
393 int i,namelen,valuelen,dstlen;
394 char *namevalue;
395 env_t newenv=*dst;
396
397 /* Check arguments */
398 if (name==NULL)
399 return -1;
400 if (value==NULL) {
401 value="";
402 valuelen=0;
403 } else
404 valuelen=strlen(value);
405 namelen=strlen(name);
406 /* Add two: = and \0 */
407 if ((namevalue=(char*)malloc((namelen+valuelen+2)*sizeof(char)))==NULL)
408 return -1;
409 sprintf(namevalue,"%s=%s",name,value);
410
411 /* look for existing entry */
412 for (i=0; newenv[i]; i++) {
413 if (strncmp(name,newenv[i],namelen)==0 && newenv[i][namelen]=='=') {
414 free(newenv[i]);
415 newenv[i]=namevalue;
416 return 0;
417 }
418 }
419 /* No old match, make a new entry, add two, because strarrlen doesn't count
420 * the NULL string at the end. */
421 dstlen=strarrlen((const char **)newenv);
422 newenv=(env_t)realloc(newenv,(dstlen+2)*sizeof(char*));
423 if (newenv==NULL) {
424 free(namevalue);
425 return -1;
426 }
427 *dst=newenv; /* update *dst after (re/m)alloc */
428 newenv[dstlen]=namevalue;
429 newenv[dstlen+1]=NULL;
430
431 return 0;
432 }
433
434 /**
435 * Adds to the current environment the var=value pairs from src which have
436 * varname in list. Returns number of entries added or -1 on error.
437 * NOTE: putenv doesn't reserve new memory so src should NOT be
438 * free()d.
439 */
440 int putenv_src_list(env_t src,const char **list) {
441 int i,src_idx,match=0;
442
443 /* Only do when list exists...*/
444 if (!list)
445 return 0;
446
447 /* loop over list */
448 for (i=0; list[i]; i++) {
449 if ((src_idx=getvarindex((const env_t)src,list[i]))>=0) {
450 /* Found match */
451 if (putenv(src[src_idx]))
452 return -1;
453 match++;
454 }
455 }
456 return match;
457 }
458
459 /**
460 * Adds to the current environment the var=value pairs from src which start with
461 * pattern. Returns number of entries added or -1 on error.
462 * NOTE: putenv doesn't reserve new memory so src should NOT be
463 * free()d.
464 */
465 int putenv_src_pattern(env_t src,const char *pattern) {
466 int i,len=strlen(pattern),match=0;
467
468 /* loop over src environ */
469 for (i=0; src[i]; i++) {
470 if (strncmp(src[i],pattern,len)==0) {
471 /* Found match */
472 if (putenv(src[i]))
473 return -1;
474 match++;
475 }
476 }
477 return match;
478 }
479

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