/[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 1453 - (show annotations) (download) (as text)
Wed Feb 3 21:29:34 2010 UTC (11 years, 11 months ago) by msalle
File MIME type: text/x-chdr
File size: 13816 byte(s)
- Use properly size_t when needed

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

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