1 /* Copyright (C) 2021-2023 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
22 * Routines for managing the target's environment array
26 #include "descendants.h"
28 #define MAX_LD_PRELOADS 2
30 /* TprintfT(<level>,...) definitions. Adjust per module as needed */
31 #define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
32 #define DBG_LT1 1 // for configuration details, warnings
37 /* original environment settings to be saved for later restoration */
38 static char *sp_preloads
[MAX_LD_PRELOADS
];
39 static char *sp_libpaths
[MAX_LD_PRELOADS
];
42 static const char *SP_ENV
[];
43 static const char *LD_ENV
[];
44 static const char *SP_PRELOAD
[];
45 static const char *LD_PRELOAD
[];
46 static const char *SP_LIBRARY_PATH
[];
47 static const char *LD_LIBRARY_PATH
[];
48 static int NUM_SP_ENV_VARS
;
49 static int NUM_LD_ENV_VARS
;
50 static int NUM_SP_PRELOADS
;
51 static int NUM_LD_PRELOADS
;
52 static int NUM_SP_LIBPATHS
;
53 static int NUM_LD_LIBPATHS
;
55 static const char *SP_ENV
[] = {
56 SP_COLLECTOR_PARAMS
, /* data descriptor */
57 SP_COLLECTOR_EXPNAME
, /* experiment name */
58 SP_COLLECTOR_FOLLOW_SPEC
, /* linetrace */
59 SP_COLLECTOR_FOUNDER
, /* determine founder exp */
60 SP_PRELOAD_STRINGS
, /* LD_PRELOADs for data collection */
61 SP_LIBPATH_STRINGS
, /* LD_LIBRARY_PATHs for data collection */
62 "SP_COLLECTOR_TRACELEVEL", /* tprintf */
64 "SP_COLLECTOR_SIGACTION", /* dispatcher, hwprofile */
67 /* LD_DEBUG=audit,bindings,detail */
72 static const char *LD_ENV
[] = {
73 LD_PRELOAD_STRINGS
, /* LD_PRELOADs */
74 LD_LIBPATH_STRINGS
, /* LD_LIBRARY_PATHs */
75 JAVA_TOOL_OPTIONS
, /* enable -agentlib:collector for JVMTI */
79 static const char *SP_PRELOAD
[] = {
84 static const char *LD_PRELOAD
[] = {
89 static const char *SP_LIBRARY_PATH
[] = {
93 static const char *LD_LIBRARY_PATH
[] = {
99 __collector_env_save_preloads ()
101 /* save the list of SP_PRELOADs */
103 for (v
= 0; SP_PRELOAD
[v
]; v
++)
105 sp_preloads
[v
] = __collector_strdup (CALL_UTIL (getenv
)(SP_PRELOAD
[v
]));
106 TprintfT (DBG_LT3
, "__collector_env_save_preloads: %s=%s\n", SP_PRELOAD
[v
], sp_preloads
[v
]);
109 for (v
= 0; SP_LIBRARY_PATH
[v
]; v
++)
111 sp_libpaths
[v
] = __collector_strdup (CALL_UTIL (getenv
)(SP_LIBRARY_PATH
[v
]));
112 TprintfT (DBG_LT4
, "__collector_env_save_preloads: %s=%s\n", SP_LIBRARY_PATH
[v
],
113 sp_libpaths
[v
] ? sp_libpaths
[v
] : "NULL");
116 for (v
= 0; LD_PRELOAD
[v
]; v
++)
119 for (v
= 0; LD_LIBRARY_PATH
[v
]; v
++)
122 for (v
= 0; SP_ENV
[v
]; v
++)
125 for (v
= 0; LD_ENV
[v
]; v
++)
130 /* free the memory involved in backing up the environment */
132 __collector_env_backup_free ()
135 TprintfT (DBG_LT2
, "env_backup_free()\n");
136 for (v
= 0; sp_env_backup
[v
]; v
++)
138 TprintfT (DBG_LT2
, "env_backup_free():sp_env_backup[%d]=%s \n", v
, sp_env_backup
[v
]);
139 __collector_freeCSize (__collector_heap
, (char *) sp_env_backup
[v
], __collector_strlen (sp_env_backup
[v
]) + 1);
141 __collector_freeCSize (__collector_heap
, (char**) sp_env_backup
,
142 (NUM_SP_ENV_VARS
+ NUM_LD_ENV_VARS
+ 1) * sizeof (char*));
146 __collector_env_backup ()
148 TprintfT (DBG_LT2
, "env_backup_()\n");
149 char **backup
= __collector_env_allocate (NULL
, 1);
150 __collector_env_update (backup
);
151 TprintfT (DBG_LT2
, "env_backup_()\n");
156 function: env_prepend()
157 given an <old_str>, check to see if <str>
158 is already defined by it. If not, allocate
159 a new string and concat <envvar>=<str><separator><old_str>
161 old_str: original string
162 str: substring to prepend
163 return: pointer to updated string or NULL if string was not updated.
166 env_prepend (const char *envvar
, const char *str
, const char *separator
,
169 if (!envvar
|| *envvar
== 0 || !str
|| *str
== 0)
172 TprintfT (DBG_LT2
, "env_prepend(\"%s\", \"%s\", \"%s\", \"%s\") -- nothing to do\n",
173 envvar
, str
, separator
, old_str
);
177 TprintfT (DBG_LT2
, "env_prepend(\"%s\", \"%s\", \"%s\", \"%s\")\n",
178 envvar
, str
, separator
, old_str
);
181 if (!old_str
|| *old_str
== 0)
183 strsz
= __collector_strlen (envvar
) + 1 + __collector_strlen (str
) + 1;
184 ev
= (char*) __collector_allocCSize (__collector_heap
, strsz
, 1);
187 CALL_UTIL (snprintf
)(ev
, strsz
, "%s=%s", envvar
, str
);
188 assert (__collector_strlen (ev
) + 1 == strsz
);
191 TprintfT (DBG_LT2
, "env_prepend(): could not allocate memory\n");
195 char *p
= CALL_UTIL (strstr
)(old_str
, str
);
198 TprintfT (DBG_LT2
, "env_prepend(): %s=%s was already set\n",
202 strsz
= __collector_strlen (envvar
) + 1 + __collector_strlen (str
) +
203 __collector_strlen (separator
) + __collector_strlen (old_str
) + 1;
204 ev
= (char*) __collector_allocCSize (__collector_heap
, strsz
, 1);
207 CALL_UTIL (snprintf
)(ev
, strsz
, "%s=%s%s%s", envvar
, str
, separator
, old_str
);
208 assert (__collector_strlen (ev
) + 1 == strsz
);
211 TprintfT (DBG_LT2
, "env_prepend(): could not allocate memory\n");
213 TprintfT (DBG_LT2
, "env_prepend(\"%s\", \"%s\", \"%s\", \"%s\") returns \"%s\"\n",
214 envvar
, str
, separator
, old_str
, (ev
== NULL
? "NULL" : ev
));
219 function: putenv_prepend()
220 get environment variable <envvar>, check to see if <str>
221 is already defined by it. If not prepend <str>
222 and put it back to environment.
224 envvar: environment variable
225 str: substring to find
226 return: 0==success, nonzero on failure.
229 putenv_prepend (const char *envvar
, const char *str
, const char *separator
)
231 if (!envvar
|| *envvar
== 0)
233 const char * old_str
= CALL_UTIL (getenv
)(envvar
);
234 char * newstr
= env_prepend (envvar
, str
, separator
, old_str
);
236 // now put the new variable into the environment
237 if (CALL_UTIL (putenv
)(newstr
) != 0)
239 TprintfT (DBG_LT2
, "putenv_prepend(): ERROR %s is not set!\n", newstr
);
246 function: env_strip()
247 Finds substr in origstr; Removes
248 all characters from previous ':' or ' '
249 up to and including any trailing ':' or ' '.
251 env: environment variable contents
252 str: substring to find
253 return: count of instances removed from env
256 env_strip (char *origstr
, const char *substr
)
260 if (origstr
== NULL
|| substr
== NULL
|| *substr
== 0)
262 while ((p
= q
= CALL_UTIL (strstr
)(origstr
, substr
)))
264 p
+= __collector_strlen (substr
);
265 while (*p
== ':' || *p
== ' ') /* strip trailing separator */
267 while (*q
!= ':' && *q
!= ' ' && *q
!= '=' && q
!= origstr
) /* strip path */
269 if (q
!= origstr
) /* restore leading separator (if any) */
271 __collector_strlcpy (q
, p
, __collector_strlen (p
) + 1);
278 function: env_ld_preload_strip()
279 Removes known libcollector shared objects from envv.
281 var: shared object name (leading characters don't have to match)
282 return: 0 = so's removed, non-zero = so's not found.
285 env_ld_preload_strip (char *envv
)
287 if (!envv
|| *envv
== 0)
289 TprintfT (DBG_LT2
, "env_ld_preload_strip(): WARNING - envv is NULL\n");
292 for (int v
= 0; SP_PRELOAD
[v
]; v
++)
293 if (env_strip (envv
, sp_preloads
[v
]))
295 if (line_mode
!= LM_CLOSED
)
296 TprintfT (DBG_LT2
, "env_ld_preload_strip(): WARNING - could not strip SP_PRELOADS from '%s'\n",
302 __collector_env_print (char * label
)
305 TprintfT (DBG_LT2
, "__collector_env_print(%s)\n", label
);
306 for (int v
= 0; v
< MAX_LD_PRELOADS
; v
++)
307 TprintfT (DBG_LT2
, " %s sp_preloads[%d] (0x%p)=%s\n", label
,
308 v
, sp_preloads
[v
], (sp_preloads
[v
] == NULL
? "NULL" : sp_preloads
[v
]));
309 for (int v
= 0; SP_ENV
[v
]; v
++)
311 char *s
= CALL_UTIL (getenv
)(SP_ENV
[v
]);
314 TprintfT (DBG_LT2
, " %s SP_ENV[%d] (0x%p): %s=\"%s\"\n", label
, v
, SP_ENV
[v
], SP_ENV
[v
], s
);
316 for (int v
= 0; LD_ENV
[v
]; v
++)
318 char *s
= CALL_UTIL (getenv
)(LD_ENV
[v
]);
321 TprintfT (DBG_LT2
, " %s LD_ENV[%d] (0x%p): %s=\"%s\"\n", label
, v
, LD_ENV
[v
], LD_ENV
[v
], s
);
327 __collector_env_printall (char *label
, char *envp
[])
330 TprintfT (DBG_LT2
, "__collector_env_printall(%s): environment @ 0x%p\n", label
, envp
);
331 for (int i
= 0; envp
[i
]; i
++)
332 Tprintf (DBG_LT2
, "\tenv[%d]@0x%p == %s\n", i
, envp
[i
], envp
[i
]);
336 /* match collector environment variable */
338 env_match (char *envp
[], const char *envvar
)
342 TprintfT (DBG_LT1
, "env_match(%s): NULL envp!\n", envvar
);
346 while ((envp
[i
] != NULL
) && (__collector_strStartWith (envp
[i
], envvar
)))
348 if ((envp
[i
] == NULL
) || (envp
[i
][__collector_strlen (envvar
)] != '='))
349 TprintfT (DBG_LT4
, "env_match(): @%p []%s not defined in envp\n", envp
, envvar
);
352 TprintfT (DBG_LT4
, "env_match(): @%p [%d]%s defined in envp\n", envp
, i
, envp
[i
]);
356 TprintfT (DBG_LT1
, "env_match(%s): found in slot %d\n", envvar
, match
);
360 /* allocate new environment with collector variables */
361 /* 1) copy all current envp[] ptrs into a new array, coll_env[] */
362 /* 2) if collector-related env ptrs not in envp[], append them to coll_env */
363 /* from processes' "environ" (allocate_env==1) */
364 /* or from sp_env_backup (allocate_env==0)*/
365 /* If they already exist in envp, probably is an error... */
366 /* 3) return coll_env */
368 /* __collector__env_update() need be called after this to set LD_ENV*/
370 __collector_env_allocate (char *const old_env
[], int allocate_env
)
372 extern char **environ
; /* the process' actual environment */
373 char **new_env
; /* a new environment for collection */
374 TprintfT (DBG_LT3
, "__collector_env_allocate(old_env=0x%p %s environ=0x%p)\n",
375 old_env
, (old_env
== environ
) ? "==" : "!=", environ
);
376 /* set up a copy of the provided old_env for collector use */
377 int old_env_size
= 0;
379 /* determine number of (used) slots in old_env */
381 while (old_env
[old_env_size
] != NULL
)
383 /* allocate a new vector with additional slots */
384 int new_env_alloc_sz
= old_env_size
+ NUM_SP_ENV_VARS
+ NUM_LD_ENV_VARS
+ 1;
385 new_env
= (char**) __collector_allocCSize (__collector_heap
, new_env_alloc_sz
* sizeof (char*), 1);
388 TprintfT (DBG_LT4
, "__collector_env_allocate(): old_env has %d entries, new_env @ 0x%p\n", old_env_size
, new_env
);
390 /* copy provided old_env pointers to new collector environment */
391 int new_env_size
= 0;
392 for (new_env_size
= 0; new_env_size
< old_env_size
; new_env_size
++)
393 new_env
[new_env_size
] = old_env
[new_env_size
];
395 /* check each required environment variable, adding as required */
396 const char * env_var
;
398 for (v
= 0; (env_var
= SP_ENV
[v
]) != NULL
; v
++)
400 if (env_match ((char**) old_env
, env_var
) == -1)
403 /* not found in old_env */
406 if ((idx
= env_match (environ
, env_var
)) != -1)
408 /* found in environ */
409 TprintfT (DBG_LT4
, "__collector_env_allocate(): [%d]%s env restored!\n",
410 new_env_size
, environ
[idx
]);
411 int varsz
= __collector_strlen (environ
[idx
]) + 1;
412 char * var
= (char*) __collector_allocCSize (__collector_heap
, varsz
, 1);
415 __collector_strlcpy (var
, environ
[idx
], varsz
);
416 new_env
[new_env_size
++] = var
;
420 /* not found in environ */
421 if ((__collector_strcmp (env_var
, SP_COLLECTOR_PARAMS
) == 0) ||
422 (__collector_strcmp (env_var
, SP_COLLECTOR_EXPNAME
) == 0))
423 TprintfT (DBG_LT1
, "__collector_env_allocate(): note: %s environment variable not found\n",
429 if ((idx
= env_match (sp_env_backup
, env_var
)) != -1)
431 /* found in backup */
432 TprintfT (DBG_LT4
, "__collector_env_allocate(): [%d]%s env restored!\n",
433 new_env_size
, sp_env_backup
[idx
]);
434 new_env
[new_env_size
++] = sp_env_backup
[idx
];
438 /* not found in environ */
439 if ((__collector_strcmp (env_var
, SP_COLLECTOR_PARAMS
) == 0) ||
440 (__collector_strcmp (env_var
, SP_COLLECTOR_EXPNAME
) == 0))
441 TprintfT (DBG_LT1
, "__collector_env_allocate(): note: %s environment variable not found\n",
448 for (v
= 0; (env_var
= LD_ENV
[v
]) != NULL
; v
++)
450 if (env_match ((char**) old_env
, env_var
) == -1)
453 /* not found in old_env */
456 if ((idx
= env_match (environ
, env_var
)) != -1)
458 /* found in environ */
459 TprintfT (DBG_LT4
, "__collector_env_allocate(): [%d]%s env restored!\n",
460 new_env_size
, environ
[idx
]);
462 int varsz
= __collector_strlen (env_var
) + 2;
463 char * var
= (char*) __collector_allocCSize (__collector_heap
, varsz
, 1);
466 // assume __collector_env_update() will fill content of env_var
467 CALL_UTIL (snprintf
)(var
, varsz
, "%s=", env_var
);
468 new_env
[new_env_size
++] = var
;
473 if ((idx
= env_match (sp_env_backup
, env_var
)) != -1)
475 /* found in backup */
476 TprintfT (DBG_LT4
, "__collector_env_allocate(): [%d]%s env restored!\n",
477 new_env_size
, sp_env_backup
[idx
]);
478 new_env
[new_env_size
++] = sp_env_backup
[idx
];
484 /* ensure new_env vector ends with NULL */
485 new_env
[new_env_size
] = NULL
;
486 assert (new_env_size
<= new_env_alloc_sz
);
487 TprintfT (DBG_LT4
, "__collector_env_allocate(): new_env has %d entries (%d added), new_env=0x%p\n",
488 new_env_size
, new_env_size
- old_env_size
, new_env
);
489 if (new_env_size
!= old_env_size
&& !allocate_env
)
490 __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d</event>\n",
491 SP_JCMD_CWARN
, COL_WARN_EXECENV
, new_env_size
- old_env_size
);
492 __collector_env_printall ("__collector_env_allocate", new_env
);
496 /* unset collection environment variables */
497 /* if they exist in env... */
498 /* 1) push non-collectorized version to env */
502 __collector_env_unset (char *envp
[])
505 const char * env_name
;
506 TprintfT (DBG_LT3
, "env_unset(envp=0x%p)\n", envp
);
509 for (v
= 0; (env_name
= LD_PRELOAD
[v
]); v
++)
511 const char *env_val
= CALL_UTIL (getenv
)(env_name
);
512 if (env_val
&& CALL_UTIL (strstr
)(env_val
, sp_preloads
[v
]))
514 size_t sz
= __collector_strlen (env_name
) + 1 + __collector_strlen (env_val
) + 1;
515 char * ev
= (char*) __collector_allocCSize (__collector_heap
, sz
, 1);
518 CALL_UTIL (snprintf
)(ev
, sz
, "%s=%s", env_name
, env_val
);
519 assert (__collector_strlen (ev
) + 1 == sz
);
520 TprintfT (DBG_LT4
, "env_unset(): old %s\n", ev
);
521 env_ld_preload_strip (ev
);
522 CALL_UTIL (putenv
)(ev
);
523 TprintfT (DBG_LT4
, "env_unset(): new %s\n", ev
);
526 // unset JAVA_TOOL_OPTIONS
527 env_name
= JAVA_TOOL_OPTIONS
;
528 const char * env_val
= CALL_UTIL (getenv
)(env_name
);
529 if (env_val
&& CALL_UTIL (strstr
)(env_val
, COLLECTOR_JVMTI_OPTION
))
531 size_t sz
= __collector_strlen (env_name
) + 1 + __collector_strlen (env_val
) + 1;
532 char * ev
= (char*) __collector_allocCSize (__collector_heap
, sz
, 1);
535 CALL_UTIL (snprintf
)(ev
, sz
, "%s=%s", env_name
, env_val
);
536 assert (__collector_strlen (ev
) + 1 == sz
);
537 TprintfT (DBG_LT4
, "env_unset(): old %s\n", ev
);
538 env_strip (ev
, COLLECTOR_JVMTI_OPTION
);
539 CALL_UTIL (putenv
)(ev
);
540 TprintfT (DBG_LT4
, "env_unset(): new %s\n", ev
);
542 __collector_env_print ("__collector_env_unset");
546 __collector_env_printall ("__collector_env_unset, before", envp
);
547 for (v
= 0; (env_name
= LD_PRELOAD
[v
]); v
++)
549 int idx
= env_match (envp
, env_name
);
552 char *env_val
= envp
[idx
];
553 TprintfT (DBG_LT4
, "env_unset(): old %s\n", env_val
);
554 envp
[idx
] = "junk="; /* xxxx is it ok to use original string? */
555 env_ld_preload_strip (env_val
);
557 TprintfT (DBG_LT4
, "env_unset(): new %s\n", envp
[idx
]);
560 // unset JAVA_TOOL_OPTIONS
561 env_name
= JAVA_TOOL_OPTIONS
;
562 int idx
= env_match(envp
, env_name
);
564 char *env_val
= envp
[idx
];
565 TprintfT(DBG_LT4
, "env_unset(): old %s\n", env_val
);
566 envp
[idx
] = "junk="; /* xxxx is it ok to use original string? */
567 env_strip(env_val
, COLLECTOR_JVMTI_OPTION
);
569 TprintfT(DBG_LT4
, "env_unset(): new %s\n", envp
[idx
]);
571 __collector_env_printall ("__collector_env_unset, after", envp
);
575 /* update collection environment variables */
576 /* update LD_PRELOADs and push them */
579 __collector_env_update (char *envp
[])
581 const char *env_name
;
582 TprintfT (DBG_LT1
, "__collector_env_update(envp=0x%p)\n", envp
);
583 extern char **environ
;
587 TprintfT (DBG_LT2
, "__collector_env_update(envp=NULL)\n");
588 __collector_env_printall (" environ array, before", environ
);
589 __collector_env_print (" env_update at entry ");
592 for (v
= 0; (env_name
= SP_ENV
[v
]) != NULL
; v
++)
594 if (env_match (environ
, env_name
) == -1)
597 if ((idx
= env_match (sp_env_backup
, env_name
)) != -1)
599 unsigned strsz
= __collector_strlen (sp_env_backup
[idx
]) + 1;
600 char *ev
= (char*) __collector_allocCSize (__collector_heap
, strsz
, 1);
601 CALL_UTIL (snprintf
)(ev
, strsz
, "%s", sp_env_backup
[idx
]);
602 if (CALL_UTIL (putenv
)(ev
) != 0)
603 TprintfT (DBG_LT2
, "__collector_env_update(): ERROR %s is not set!\n",
608 __collector_env_print (" env_update after SP_ENV settings ");
610 /* LD_LIBRARY_PATH */
611 for (v
= 0; (env_name
= LD_LIBRARY_PATH
[v
]); v
++)
612 /* assumes same index used between LD and SP vars */
613 if (putenv_prepend (env_name
, sp_libpaths
[v
], ":"))
614 TprintfT (DBG_LT2
, "collector: ERROR %s=%s could not be set\n",
615 env_name
, sp_libpaths
[v
]);
616 __collector_env_print (" env_update after LD_LIBRARY_PATH settings ");
619 for (v
= 0; (env_name
= LD_PRELOAD
[v
]); v
++)
620 /* assumes same index used between LD and SP vars */
621 if (putenv_prepend (env_name
, sp_preloads
[v
], " "))
622 TprintfT (DBG_LT2
, "collector: ERROR %s=%s could not be set\n",
623 env_name
, sp_preloads
[v
]);
624 __collector_env_print (" env_update after LD_PRELOAD settings ");
626 /* JAVA_TOOL_OPTIONS */
628 if (putenv_prepend (JAVA_TOOL_OPTIONS
, COLLECTOR_JVMTI_OPTION
, " "))
629 TprintfT (DBG_LT2
, "collector: ERROR %s=%s could not be set\n",
630 JAVA_TOOL_OPTIONS
, COLLECTOR_JVMTI_OPTION
);
631 __collector_env_print (" env_update after JAVA_TOOL settings ");
637 TprintfT (DBG_LT2
, "__collector_env_update(envp=0x%p) not NULL\n", envp
);
638 __collector_env_printall ("__collector_env_update, before", envp
);
639 /* LD_LIBRARY_PATH */
640 for (v
= 0; (env_name
= LD_LIBRARY_PATH
[v
]); v
++)
642 int idx
= env_match (envp
, env_name
);
645 char *env_val
= __collector_strchr (envp
[idx
], '=');
647 env_val
++; /* skip '=' */
648 /* assumes same index used between LD and SP vars */
649 char *new_str
= env_prepend (env_name
, sp_libpaths
[v
],
657 for (v
= 0; (env_name
= LD_PRELOAD
[v
]); v
++)
659 int idx
= env_match (envp
, env_name
);
662 char *env_val
= __collector_strchr (envp
[idx
], '=');
664 env_val
++; /* skip '=' */
665 /* assumes same index used between LD and SP vars */
666 char *new_str
= env_prepend (env_name
, sp_preloads
[v
],
673 /* JAVA_TOOL_OPTIONS */
676 env_name
= JAVA_TOOL_OPTIONS
;
677 idx
= env_match (envp
, env_name
);
680 char *env_val
= __collector_strchr (envp
[idx
], '=');
682 env_val
++; /* skip '=' */
683 char *new_str
= env_prepend (env_name
, COLLECTOR_JVMTI_OPTION
,
690 __collector_env_printall ("__collector_env_update, after", environ
);
694 /*------------------------------------------------------------- putenv */
695 int putenv () __attribute__ ((weak
, alias ("__collector_putenv")));
696 int _putenv () __attribute__ ((weak
, alias ("__collector_putenv")));
699 __collector_putenv (char * string
)
701 if (CALL_UTIL (putenv
) == __collector_putenv
||
702 CALL_UTIL (putenv
) == NULL
)
703 { // __collector_libc_funcs_init failed
704 CALL_UTIL (putenv
) = (int(*)())dlsym (RTLD_NEXT
, "putenv");
705 if (CALL_UTIL (putenv
) == NULL
|| CALL_UTIL (putenv
) == __collector_putenv
)
706 CALL_UTIL (putenv
) = (int(*)())dlsym (RTLD_DEFAULT
, "putenv");
707 if (CALL_UTIL (putenv
) == NULL
|| CALL_UTIL (putenv
) == __collector_putenv
)
709 TprintfT (DBG_LT2
, "__collector_putenv(): ERROR: no pointer found.\n");
714 if (user_follow_mode
== FOLLOW_NONE
)
715 return CALL_UTIL (putenv
)(string
);
716 char * envp
[] = {string
, NULL
};
717 __collector_env_update (envp
);
718 return CALL_UTIL (putenv
)(envp
[0]);
721 /*------------------------------------------------------------- setenv */
722 int setenv () __attribute__ ((weak
, alias ("__collector_setenv")));
723 int _setenv () __attribute__ ((weak
, alias ("__collector_setenv")));
726 __collector_setenv (const char *name
, const char *value
, int overwrite
)
728 if (CALL_UTIL (setenv
) == __collector_setenv
||
729 CALL_UTIL (setenv
) == NULL
)
730 { // __collector_libc_funcs_init failed
731 CALL_UTIL (setenv
) = (int(*)())dlsym (RTLD_NEXT
, "setenv");
732 if (CALL_UTIL (setenv
) == NULL
|| CALL_UTIL (setenv
) == __collector_setenv
)
733 CALL_UTIL (setenv
) = (int(*)())dlsym (RTLD_DEFAULT
, "setenv");
734 if (CALL_UTIL (setenv
) == NULL
|| CALL_UTIL (setenv
) == __collector_setenv
)
736 TprintfT (DBG_LT2
, "__collector_setenv(): ERROR: no pointer found.\n");
741 if (user_follow_mode
== FOLLOW_NONE
|| !overwrite
)
742 return CALL_UTIL (setenv
)(name
, value
, overwrite
);
743 size_t sz
= __collector_strlen (name
) + 1 + __collector_strlen (value
) + 1;
744 char *ev
= (char*) __collector_allocCSize (__collector_heap
, sz
, 1);
746 return CALL_UTIL (setenv
)(name
, value
, overwrite
);
747 CALL_UTIL (snprintf
)(ev
, sz
, "%s=%s", name
, value
);
748 char * envp
[] = {ev
, NULL
};
749 __collector_env_update (envp
);
752 __collector_freeCSize (__collector_heap
, ev
, sz
);
753 return CALL_UTIL (setenv
)(name
, value
, overwrite
);
757 char *env_val
= __collector_strchr (envp
[0], '=');
761 env_val
++; /* skip '=' */
763 return CALL_UTIL (setenv
)(envp
[0], env_val
, overwrite
);
767 /*------------------------------------------------------------- unsetenv */
768 int unsetenv () __attribute__ ((weak
, alias ("__collector_unsetenv")));
769 int _unsetenv () __attribute__ ((weak
, alias ("__collector_unsetenv")));
772 __collector_unsetenv (const char *name
)
774 if (CALL_UTIL (unsetenv
) == __collector_unsetenv
||
775 CALL_UTIL (unsetenv
) == NULL
)
776 { // __collector_libc_funcs_init failed
777 CALL_UTIL (unsetenv
) = (int(*)())dlsym (RTLD_NEXT
, "unsetenv");
778 if (CALL_UTIL (unsetenv
) == NULL
|| CALL_UTIL (unsetenv
) == __collector_unsetenv
)
779 CALL_UTIL (unsetenv
) = (int(*)())dlsym (RTLD_DEFAULT
, "unsetenv");
780 if (CALL_UTIL (unsetenv
) == NULL
|| CALL_UTIL (unsetenv
) == __collector_unsetenv
)
782 TprintfT (DBG_LT2
, "__collector_unsetenv(): ERROR: no pointer found.\n");
787 int ret
= CALL_UTIL (unsetenv
)(name
);
788 if (user_follow_mode
== FOLLOW_NONE
)
790 TprintfT (DBG_LT2
, "__collector_unsetenv(): %d.\n", user_follow_mode
);
791 size_t sz
= __collector_strlen (name
) + 1 + 1;
792 char *ev
= (char*) __collector_allocCSize (__collector_heap
, sz
, 1);
795 CALL_UTIL (snprintf
)(ev
, sz
, "%s=", name
);
796 char * envp
[] = {ev
, NULL
};
797 __collector_env_update (envp
);
799 __collector_freeCSize (__collector_heap
, ev
, sz
);
801 CALL_UTIL (putenv
)(envp
[0]);
805 /*------------------------------------------------------------- clearenv */
806 int clearenv () __attribute__ ((weak
, alias ("__collector_clearenv")));
809 __collector_clearenv (void)
811 if (CALL_UTIL (clearenv
) == __collector_clearenv
|| CALL_UTIL (clearenv
) == NULL
)
813 /* __collector_libc_funcs_init failed; look up clearenv now */
814 CALL_UTIL (clearenv
) = (int(*)())dlsym (RTLD_NEXT
, "clearenv");
815 if (CALL_UTIL (clearenv
) == NULL
|| CALL_UTIL (clearenv
) == __collector_clearenv
)
816 /* still not found; try again */
817 CALL_UTIL (clearenv
) = (int(*)())dlsym (RTLD_DEFAULT
, "clearenv");
818 if (CALL_UTIL (clearenv
) == NULL
|| CALL_UTIL (clearenv
) == __collector_clearenv
)
820 /* still not found -- a fatal error */
821 TprintfT (DBG_LT2
, "__collector_clearenv(): ERROR: %s\n", dlerror ());
822 CALL_UTIL (fprintf
)(stderr
, "__collector_clearenv(): ERROR: %s\n", dlerror ());
827 int ret
= CALL_UTIL (clearenv
)();
828 if (user_follow_mode
== FOLLOW_NONE
)
830 if (sp_env_backup
== NULL
)
832 TprintfT (DBG_LT2
, "__collector_clearenv: ERROR sp_env_backup is not set!\n");
835 for (int v
= 0; v
< NUM_SP_ENV_VARS
+ NUM_LD_ENV_VARS
; v
++)
836 if (sp_env_backup
[v
] && CALL_UTIL (putenv
)(sp_env_backup
[v
]) != 0)
837 TprintfT (DBG_LT2
, "__collector_clearenv: ERROR %s is not set!\n",