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 |
size_t cgul_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 (size_t)entries; |
41 |
} |
42 |
|
43 |
/** |
44 |
* returns the number of entries in list which start with pattern. If pattern of |
45 |
* list is NULL it also returns 0. |
46 |
*/ |
47 |
size_t cgul_patternentries(env_t list, const char *pattern) { |
48 |
int i,match=0; |
49 |
size_t patlen; |
50 |
/* Check if list exists: prevents common segfault situation */ |
51 |
if (!list || !pattern) |
52 |
return 0; |
53 |
patlen=strlen(pattern); |
54 |
/* Now loop over its entries */ |
55 |
for(i=0; list[i]; i++) { |
56 |
if (strncmp(list[i],pattern,patlen)==0) |
57 |
match++; |
58 |
} |
59 |
return (size_t)match; |
60 |
} |
61 |
|
62 |
/** |
63 |
* Returns the length of the name part of the var=value pair or -1 when there is |
64 |
* no '=' sign. |
65 |
*/ |
66 |
int cgul_getvarnamelen(const char *varname) { |
67 |
char *pos; |
68 |
/* find first '=' */ |
69 |
if (!varname) |
70 |
return -1; |
71 |
pos=strchr(varname,'='); |
72 |
if (pos==NULL) /* not var=value */ |
73 |
return -1; |
74 |
return (int)strlen(varname)-(int)strlen(pos); /* no pointer arithmetics */ |
75 |
} |
76 |
|
77 |
|
78 |
/** |
79 |
* Finds name for given var=value pair in namevalue. varname is a buffer |
80 |
* which will contain the result and has space for maxvarnamelen chars. |
81 |
* Returns integer, negative on error, -1 on no '=' sign, -2 name too long; |
82 |
* 0 success |
83 |
*/ |
84 |
int cgul_getvarname(char *varname,const int maxvarnamelen, |
85 |
const char *namevalue) { |
86 |
int varnamelen; |
87 |
|
88 |
if ((varnamelen=cgul_getvarnamelen(namevalue))==-1) |
89 |
return -1; |
90 |
if (varnamelen>maxvarnamelen) |
91 |
return -2; |
92 |
strncpy(varname,namevalue,(size_t)varnamelen); |
93 |
varname[varnamelen]='\0'; |
94 |
|
95 |
return 0; |
96 |
} |
97 |
|
98 |
/** |
99 |
* Finds index in **src matching variable name, in case of no match (including |
100 |
* env==NULL) returns -1 |
101 |
*/ |
102 |
int cgul_getvarindex(const env_t src, const char *varname) { |
103 |
int i; |
104 |
size_t len; |
105 |
|
106 |
if (src==NULL || varname==NULL) |
107 |
return -1; |
108 |
|
109 |
len=strlen(varname); |
110 |
/* Loop over env */ |
111 |
for (i=0; src[i]; i++) { |
112 |
if (strncmp(src[i],varname,len)==0 && src[i][len]=='=') |
113 |
/* Found match */ |
114 |
return i; |
115 |
} |
116 |
/* NO match found */ |
117 |
return -1; |
118 |
} |
119 |
|
120 |
/** |
121 |
* Finds the value of varname in src list. Returns NULL when no match, incl. |
122 |
* NULL valued src or varname. |
123 |
*/ |
124 |
char *cgul_getenv_src(const env_t src, char *varname) { |
125 |
int i; |
126 |
size_t len; |
127 |
char *match; |
128 |
|
129 |
/* Don't use getvarindex, since this saves us one strlen (-: */ |
130 |
if (src==NULL || varname==NULL) |
131 |
return NULL; |
132 |
|
133 |
len=strlen(varname); |
134 |
/* Loop over env */ |
135 |
for (i=0; src[i]; i++) { |
136 |
if (strncmp(src[i],varname,len)==0 && src[i][len]=='=') { |
137 |
/* Found match */ |
138 |
match=&(src[i][len+1]); |
139 |
return match; |
140 |
} |
141 |
} |
142 |
/* NO match found */ |
143 |
return NULL; |
144 |
} |
145 |
|
146 |
/** |
147 |
* As unsetenv(3) but using var=value pair, specified in namevalue. The maximum |
148 |
* var length is MAXVARNAMELEN. See also putenv(3). |
149 |
* Returns integer, 0 on success, negative on error. |
150 |
*/ |
151 |
int cgul_unsetenvpair(const char *namevalue) { |
152 |
char varname[MAXENVVARNAMELEN]; |
153 |
int rc; |
154 |
|
155 |
/* Get variable name for var=value pair */ |
156 |
if ((rc=cgul_getvarname(varname,MAXENVVARNAMELEN,namevalue))!=0) |
157 |
return rc; |
158 |
/* Unset variable */ |
159 |
if (unsetenv(varname)) |
160 |
return -1; |
161 |
|
162 |
return 0; |
163 |
} |
164 |
|
165 |
/** |
166 |
* Clears the entire environment |
167 |
* Returns integer, -1 on error, 0 on success |
168 |
*/ |
169 |
int cgul_clear_env(void) { |
170 |
while(environ[0]) { |
171 |
if (cgul_unsetenvpair(environ[0])) |
172 |
return -1; |
173 |
} |
174 |
return 0; |
175 |
} |
176 |
|
177 |
/* |
178 |
* Clears the environment of all variables starting with pattern, case |
179 |
* INsensitive. |
180 |
* Returns number of cleaned entries, -1 on error. |
181 |
*/ |
182 |
int cgul_clear_env_pattern(const char *pattern) { |
183 |
int i=0,match=0,rc; |
184 |
size_t patlen; |
185 |
|
186 |
if (!pattern) |
187 |
return -1; |
188 |
patlen=strlen(pattern); |
189 |
while(environ[i]) { |
190 |
if (strncasecmp(pattern,environ[i],patlen)==0) { |
191 |
if ((rc=cgul_unsetenvpair(environ[i]))) |
192 |
return rc; |
193 |
match++; |
194 |
} else |
195 |
i++; /* only increase when we haven't just removed an entry... */ |
196 |
} |
197 |
return match; |
198 |
} |
199 |
|
200 |
|
201 |
/** |
202 |
* Creates a duplicate of src. In case *dst!=NULL it will be used and should be |
203 |
* big enough. Otherwise space is malloc-ed. dst is only updated upon success. |
204 |
* Returns -1 upon error, 0 on success. |
205 |
*/ |
206 |
int cgul_copy_env(env_t *dst,const env_t src) { |
207 |
int i,j; |
208 |
size_t envlen; |
209 |
env_t newenv=*dst; |
210 |
|
211 |
/* If no dst exists, malloc it. */ |
212 |
if (newenv==NULL) { |
213 |
envlen=cgul_strarrlen((const char**)src); |
214 |
newenv=(env_t)malloc((envlen+1)*sizeof(char*)); |
215 |
if (newenv==NULL) |
216 |
return -1; |
217 |
} |
218 |
|
219 |
/* Copy src to newenv */ |
220 |
for (i=0; src[i]; i++) { |
221 |
if ( (newenv[i]=strdup(src[i]))==NULL ) { |
222 |
/* Error: cleanup memory and reset */ |
223 |
for (j=0; j<i; j++) |
224 |
free(newenv[j]); |
225 |
if (*dst==NULL) |
226 |
free(newenv); |
227 |
return -1; |
228 |
} |
229 |
} |
230 |
/* Finalize the new environ */ |
231 |
newenv[i]=NULL; |
232 |
if (*dst==NULL) |
233 |
*dst=newenv; |
234 |
|
235 |
return 0; |
236 |
} |
237 |
|
238 |
/** |
239 |
* Same as copy_env() but first unsets all environment variables starting with |
240 |
* MALLOC, case INsensitive. dst is again only updated upon success. |
241 |
* Returns -1 upon error, 0 on success. |
242 |
*/ |
243 |
int cgul_safe_copy_env(env_t *dst,const env_t src) { |
244 |
/* Clean all MALLOC* variables */ |
245 |
if (cgul_clear_env_pattern("MALLOC")) |
246 |
return -1; |
247 |
|
248 |
return cgul_copy_env(dst,src); |
249 |
} |
250 |
|
251 |
/** |
252 |
* Creates a list of the var=value pairs from src which have varname in list. |
253 |
* If it fails NULL is returned. This can also be done using add_src_list() |
254 |
* using dst==NULL, but this is more efficiently coded. All new entries are |
255 |
* strdup-ed from those in src. |
256 |
*/ |
257 |
env_t cgul_copy_src_list(const env_t src,const char *list[]) { |
258 |
int i,j,src_idx,match=0; |
259 |
size_t listlen=cgul_strarrlen(list); |
260 |
env_t newenv; |
261 |
|
262 |
/* Malloc space */ |
263 |
newenv=(env_t)malloc((listlen+1)*sizeof(char*)); |
264 |
if (newenv==NULL) |
265 |
return NULL; |
266 |
|
267 |
/* IMPORTANT: list must be NULL terminated! */ |
268 |
newenv[0]=NULL; |
269 |
|
270 |
/* Only do when list exists, otherwise return empty list, but not NO list! |
271 |
* Note it's not an error, just an empty list. */ |
272 |
if (src==NULL || list==NULL) |
273 |
return newenv; |
274 |
|
275 |
/* loop over list: Note we can have unmatched entries: match counts */ |
276 |
for (i=0; list[i]; i++) { |
277 |
/* Look if list[i] is in src */ |
278 |
if ( (src_idx=cgul_getvarindex(src,list[i])) >= 0) { |
279 |
/* Don't! check for duplicates... */ |
280 |
/* substitute existing: first try strdup */ |
281 |
if ((newenv[match]=strdup(src[src_idx]))==NULL) { |
282 |
/* error: cleanup */ |
283 |
for (j=0; j<match; j++) { |
284 |
free(newenv[j]); newenv[j]=NULL; |
285 |
} |
286 |
free(newenv); |
287 |
return NULL; |
288 |
} |
289 |
match++; |
290 |
/* Don't forget the final NULL pointer! */ |
291 |
newenv[match]=NULL; |
292 |
} |
293 |
} |
294 |
return newenv; |
295 |
} |
296 |
|
297 |
/** |
298 |
* Adds to dst the var=value pairs from src which have varname in list. |
299 |
* All entries will be strdup-ed from those in src. |
300 |
* If *dst is NULL, it will be malloc-ed, otherwise it will be realloc-ed. |
301 |
* Upon success returns 0. On error -1 is returned. If part of the environment |
302 |
* has been successfully copied, they will stay part of the environment. |
303 |
* See also copy_src_list() which is more efficient when dst is NULL ! |
304 |
*/ |
305 |
int cgul_add_src_list(env_t *dst,const env_t src,const char **list) { |
306 |
int i,src_idx,dst_idx,match; |
307 |
env_t newenv=*dst; |
308 |
size_t dstlen,listlen; |
309 |
char *dummy; |
310 |
|
311 |
listlen=cgul_strarrlen(list); |
312 |
/* Create space for combined array, might be too much if list is not fully |
313 |
* used or partially replaces old entries, but more efficient (single |
314 |
* realloc() call). |
315 |
* Note that we check for empty list AFTER the malloc, and BEFORE the |
316 |
* realloc */ |
317 |
if (newenv==NULL) { |
318 |
dstlen=0; |
319 |
newenv=(env_t)malloc((listlen+1)*sizeof(char*)); |
320 |
if (newenv==NULL) |
321 |
return -1; |
322 |
*dst=newenv; /* update *dst after malloc */ |
323 |
/* IMPORTANT: list must be NULL terminated! */ |
324 |
newenv[0]=NULL; |
325 |
/* Only continue when list and src exist, do alloc in this case, since |
326 |
* dst shouldn't return empty. Not an error. */ |
327 |
if (list==NULL || src==NULL) |
328 |
return 0; |
329 |
} else { |
330 |
/* Only do when list and src exist, no need to realloc, not an error. */ |
331 |
if (list==NULL || src==NULL) |
332 |
return 0; |
333 |
/* Count length of existing list */ |
334 |
dstlen=cgul_strarrlen((const char **)*dst); |
335 |
newenv=(env_t)realloc(newenv,(dstlen+listlen+1)*sizeof(char*)); |
336 |
if (newenv==NULL) |
337 |
return -1; |
338 |
*dst=newenv; /* update *dst after realloc */ |
339 |
} |
340 |
|
341 |
match=0; |
342 |
/* loop over list: Note we can have unmatched entries: match counts */ |
343 |
for (i=0; list[i]; i++) { |
344 |
/* Look if list[i] is in src */ |
345 |
if ( (src_idx=cgul_getvarindex(src,list[i])) >= 0) { |
346 |
/* Make already a copy, we need it in any case */ |
347 |
if ( (dummy=strdup(src[src_idx])) == NULL) |
348 |
/* Out of mem: cannot cleanup anymore, might have |
349 |
* substituted entries */ |
350 |
return -1; |
351 |
/* Look for list[i] in newenv: we might have it already. Note |
352 |
* that this is not checked when using copy_src_list() */ |
353 |
if ( (dst_idx=cgul_getvarindex((const env_t)newenv,list[i])) >= 0) { |
354 |
/* REPLACE: substitute existing: first try strdup */ |
355 |
/* Now substitute: free old entry in newenv and link to new |
356 |
* entry */ |
357 |
free(newenv[dst_idx]); |
358 |
newenv[dst_idx]=dummy; |
359 |
} else { |
360 |
/* ADD: create new one */ |
361 |
newenv[dstlen+match++]=dummy; /* created new entry: update match */ |
362 |
newenv[dstlen+match]=NULL; /* keep env NULL terminated */ |
363 |
} |
364 |
} |
365 |
} |
366 |
return 0; |
367 |
} |
368 |
|
369 |
/** |
370 |
* Adds to dst the var=value pairs from src which start with pattern. |
371 |
* All entries will be strdup-ed from those in src. |
372 |
* If *dst is NULL, it will be malloc-ed, otherwise it will be realloc-ed. |
373 |
* Upon success returns the number of matches. On error -1 is returned, if part |
374 |
* of the environment has been successfully copied, they will stay part of the |
375 |
* environment. |
376 |
* An empty pattern (either "" or NULL) or src is NOT considered error. |
377 |
* See also cgul_add_src_list() |
378 |
*/ |
379 |
int cgul_add_src_pattern(env_t *dst,const env_t src,const char *pattern) { |
380 |
int numpat,i,j,not_matched,match=0; |
381 |
env_t newenv=*dst; |
382 |
size_t dstlen,patlen,namelen; |
383 |
char *namevaluecopy; |
384 |
|
385 |
numpat=cgul_patternentries(src,pattern); |
386 |
/* Create space for combined array, might be too much if list is not fully |
387 |
* used or partially replaces old entries, but more efficient (single |
388 |
* realloc() call). |
389 |
* Note that we check for empty list AFTER the malloc, and BEFORE the |
390 |
* realloc */ |
391 |
if (newenv==NULL) { |
392 |
dstlen=0; |
393 |
newenv=(env_t)malloc((numpat+1)*sizeof(char*)); |
394 |
if (newenv==NULL) |
395 |
return -1; |
396 |
*dst=newenv; /* update *dst after malloc */ |
397 |
/* IMPORTANT: list must be NULL terminated! */ |
398 |
newenv[0]=NULL; |
399 |
/* Only continue when list and src exist, do alloc in this case, since |
400 |
* dst shouldn't return empty. Not an error. */ |
401 |
if (pattern==NULL || src==NULL) |
402 |
return 0; |
403 |
} else { |
404 |
/* Only do when list and src exist, no need to realloc, not an error. */ |
405 |
if (pattern==NULL || src==NULL) |
406 |
return 0; |
407 |
/* Count length of existing list */ |
408 |
dstlen=cgul_strarrlen((const char **)*dst); |
409 |
newenv=(env_t)realloc(newenv,(dstlen+numpat+1)*sizeof(char*)); |
410 |
if (newenv==NULL) |
411 |
return -1; |
412 |
*dst=newenv; /* update *dst after realloc */ |
413 |
} |
414 |
/* Make sure all unset entries are NULL */ |
415 |
for (i=dstlen+1; i<dstlen+numpat+1; i++) newenv[i]=NULL; |
416 |
|
417 |
patlen=strlen(pattern); |
418 |
/* loop over src */ |
419 |
for (i=0; src[i]; i++) { |
420 |
/* Look if src[i] matches pattern */ |
421 |
if (strncmp(src[i],pattern,patlen)==0) { |
422 |
/* Look for length of name part (negative = means no name) */ |
423 |
if ( (namelen=cgul_getvarnamelen(src[i])) < 0) |
424 |
break; |
425 |
/* Make already a copy, we need it in any case */ |
426 |
if ( (namevaluecopy=strdup(src[i])) == NULL) |
427 |
/* Out of mem: cannot cleanup anymore, might have substituted |
428 |
* entries */ |
429 |
return -1; |
430 |
/* look for possibly existing entry */ |
431 |
not_matched=1; |
432 |
for (j=0; not_matched && newenv[j]; j++) { |
433 |
if (strncmp(newenv[j],namevaluecopy,namelen)==0 && |
434 |
newenv[j][namelen]=='=') { |
435 |
/* REPLACE: substitute existing */ |
436 |
free(newenv[j]); /* free old */ |
437 |
newenv[j]=namevaluecopy; /* set new */ |
438 |
not_matched=0; /* found match -> done */ |
439 |
} |
440 |
} |
441 |
if (not_matched) { |
442 |
/* ADD: no old match */ |
443 |
newenv[dstlen+match++]=namevaluecopy; /* created new entry: |
444 |
update match */ |
445 |
newenv[dstlen+match]=NULL; /* keep env NULL terminated */ |
446 |
} |
447 |
} |
448 |
} |
449 |
return match; |
450 |
} |
451 |
|
452 |
/** |
453 |
* adds var=value pair to dst. If the variable already exists, it's entry is |
454 |
* replaced. Otherwise *dst is realloc-ed and a new entry is added, the |
455 |
* resulting array is returned. |
456 |
* Upon success returns 0. In case of error -1 is returned and dst remains |
457 |
* unchanged. namevalue is strdup-ed into dst and hence can be freed by the |
458 |
* caller (unlike putenv(3p) ) |
459 |
*/ |
460 |
int cgul_add_namevalue(env_t *dst,const char *namevalue) { |
461 |
int i,namelen; |
462 |
size_t dstlen; |
463 |
char *namevaluecopy; |
464 |
env_t newenv=*dst; |
465 |
|
466 |
/* Look for length of name part (no = means no name) */ |
467 |
if ( (namelen=cgul_getvarnamelen(namevalue)) < 0) |
468 |
return -1; |
469 |
/* Make already a copy, we need it in any case, unless realloc fails */ |
470 |
if ( (namevaluecopy=strdup(namevalue)) == NULL) |
471 |
return -1; |
472 |
/* look for existing entry */ |
473 |
for (i=0; newenv[i]; i++) { |
474 |
if (strncmp(namevalue,newenv[i],namelen)==0 && newenv[i][namelen]=='=') |
475 |
{ |
476 |
free(newenv[i]); |
477 |
newenv[i]=namevaluecopy; |
478 |
return 0; |
479 |
} |
480 |
} |
481 |
/* No old match, make a new entry, add two, because strarrlen doesn't count |
482 |
* the NULL string at the end. First create new entry, since that's easier |
483 |
* to undo. */ |
484 |
dstlen=cgul_strarrlen((const char**)newenv); |
485 |
newenv=(env_t)realloc(newenv,(dstlen+2)*sizeof(char*)); |
486 |
if (newenv==NULL) { |
487 |
free(namevaluecopy); |
488 |
return -1; |
489 |
} |
490 |
*dst=newenv; /* update *dst after (re/m)alloc */ |
491 |
newenv[dstlen]=namevaluecopy; |
492 |
newenv[dstlen+1]=NULL; |
493 |
|
494 |
return 0; |
495 |
} |
496 |
|
497 |
/** |
498 |
* adds name=value pair to dst, as in setenv() with a 'external environment' . |
499 |
* If the variable already exists, it's entry is replaced. Otherwise *dst is |
500 |
* realloc-ed and a new entry is added. |
501 |
* Upon success returns 0. In case of error -1 is returned and dst remains |
502 |
* unchanged. name and value can be freed by the caller (unlike putenv(3p) ) |
503 |
*/ |
504 |
int cgul_setenv_dst(env_t *dst,const char *name, const char *value) { |
505 |
int i,dstlen; |
506 |
size_t namelen,valuelen,totallen; |
507 |
char *namevalue; |
508 |
const char *realvalue; |
509 |
env_t newenv=*dst; |
510 |
|
511 |
/* Check arguments */ |
512 |
if (name==NULL) |
513 |
return -1; |
514 |
if (value==NULL) { |
515 |
realvalue=""; |
516 |
valuelen=0; |
517 |
} else { |
518 |
realvalue=value; |
519 |
valuelen=strlen(realvalue); |
520 |
} |
521 |
namelen=strlen(name); |
522 |
/* Add two: '=' and '\0' */ |
523 |
totallen=namelen+valuelen+2*sizeof(char); |
524 |
if ((namevalue=(char*)malloc(totallen))==NULL) |
525 |
return -1; |
526 |
sprintf(namevalue,"%s=%s",name,realvalue); |
527 |
|
528 |
/* look for existing entry */ |
529 |
for (i=0; newenv[i]; i++) { |
530 |
if (strncmp(name,newenv[i],namelen)==0 && newenv[i][namelen]=='=') { |
531 |
free(newenv[i]); |
532 |
newenv[i]=namevalue; |
533 |
return 0; |
534 |
} |
535 |
} |
536 |
/* No old match, make a new entry, add two, because strarrlen doesn't count |
537 |
* the NULL string at the end. */ |
538 |
dstlen=cgul_strarrlen((const char **)newenv); |
539 |
newenv=(env_t)realloc(newenv,(dstlen+2)*sizeof(char*)); |
540 |
if (newenv==NULL) { |
541 |
free(namevalue); |
542 |
return -1; |
543 |
} |
544 |
*dst=newenv; /* update *dst after (re/m)alloc */ |
545 |
newenv[dstlen]=namevalue; |
546 |
newenv[dstlen+1]=NULL; |
547 |
|
548 |
return 0; |
549 |
} |
550 |
|
551 |
/** |
552 |
* Removes a variable from dst as in unsetenv() with a 'external environment'. |
553 |
*/ |
554 |
int cgul_unsetenv_dst(env_t *dst,const char *name) { |
555 |
int namelen,i; |
556 |
env_t newenv=*dst; |
557 |
int entry=-1; |
558 |
|
559 |
/* Check arguments */ |
560 |
if (name==NULL) |
561 |
return -1; |
562 |
namelen=strlen(name); |
563 |
|
564 |
/* look for existing entry */ |
565 |
for (i=0; newenv[i]; i++) { |
566 |
if (strncmp(name,newenv[i],namelen)==0 && newenv[i][namelen]=='=') { |
567 |
entry=i; |
568 |
break; |
569 |
} |
570 |
} |
571 |
/* no match */ |
572 |
if (entry<0) return 0; |
573 |
|
574 |
/* Remainder of list... */ |
575 |
for (; newenv[i]; i++); |
576 |
|
577 |
/* Now clean entry if it's there and swap with the last in the list */ |
578 |
free(newenv[entry]); |
579 |
|
580 |
/* If there were more than one elements, move the last to the removed one */ |
581 |
if (i>0) { |
582 |
newenv[entry]=newenv[i-1]; /* last element */ |
583 |
newenv[i-1]=NULL; |
584 |
} else |
585 |
newenv[entry]=NULL; |
586 |
return 0; |
587 |
} |
588 |
|
589 |
/** |
590 |
* Adds to the current environment the var=value pairs from src which have |
591 |
* varname in list. Returns number of entries added or -1 on error. |
592 |
* NOTE: we do a strdup before the actual putenv, so even though putenv doesn't |
593 |
* reserve new memory, we stil can free src ! |
594 |
*/ |
595 |
int cgul_putenv_src_list(env_t src,const char **list) { |
596 |
int i,src_idx,match=0; |
597 |
char *dummy; |
598 |
|
599 |
/* Only do when list exists...*/ |
600 |
if (!list) |
601 |
return 0; |
602 |
|
603 |
/* loop over list */ |
604 |
for (i=0; list[i]; i++) { |
605 |
if ((src_idx=cgul_getvarindex((const env_t)src,list[i]))>=0) { |
606 |
/* Found match */ |
607 |
/* Make copy, so that src eventually can be freed! */ |
608 |
if ( (dummy=strdup(src[src_idx]))==NULL ) |
609 |
return -1; |
610 |
/* Now do the putenv */ |
611 |
if (putenv(dummy)) |
612 |
return -1; |
613 |
match++; |
614 |
} |
615 |
} |
616 |
return match; |
617 |
} |
618 |
|
619 |
/** |
620 |
* Adds to the current environment the var=value pairs from src which start with |
621 |
* pattern. Returns number of entries added or -1 on error. |
622 |
* NOTE: we do a strdup before the actual putenv, so even though putenv doesn't |
623 |
* reserve new memory, we stil can free src ! |
624 |
*/ |
625 |
int cgul_putenv_src_pattern(env_t src,const char *pattern) { |
626 |
int i,match=0; |
627 |
size_t len; |
628 |
char *dummy; |
629 |
|
630 |
if (!pattern) |
631 |
return -1; |
632 |
len=strlen(pattern); |
633 |
/* loop over src environ */ |
634 |
for (i=0; src[i]; i++) { |
635 |
if (strncmp(src[i],pattern,len)==0) { |
636 |
/* Found match */ |
637 |
/* Make copy, so that src eventually can be freed! */ |
638 |
if ( (dummy=strdup(src[i]))==NULL ) |
639 |
return -1; |
640 |
/* Now do the putenv */ |
641 |
if (putenv(dummy)) |
642 |
return -1; |
643 |
match++; |
644 |
} |
645 |
} |
646 |
return match; |
647 |
} |
648 |
|