1 /* Copyright (C) 2021 Free Software Foundation, Inc. 2 Contributed by Oracle. 3 4 This file is part of GNU Binutils. 5 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) 9 any later version. 10 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. 15 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. */ 20 21 /* 22 * Routines for managing the target's environment array 23 */ 24 25 #include "config.h" 26 #include "descendants.h" 27 28 #define MAX_LD_PRELOADS 2 29 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 33 #define DBG_LT2 2 34 #define DBG_LT3 3 35 #define DBG_LT4 4 36 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]; 40 char **sp_env_backup; 41 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; 54 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 */ 63 #if DEBUG 64 "SP_COLLECTOR_SIGACTION", /* dispatcher, hwprofile */ 65 #endif 66 /* JAVA* */ 67 /* LD_DEBUG=audit,bindings,detail */ 68 /* LD_ORIGIN=yes */ 69 NULL 70 }; 71 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 */ 76 NULL 77 }; 78 79 static const char *SP_PRELOAD[] = { 80 SP_PRELOAD_STRINGS, 81 NULL 82 }; 83 84 static const char *LD_PRELOAD[] = { 85 LD_PRELOAD_STRINGS, 86 NULL 87 }; 88 89 static const char *SP_LIBRARY_PATH[] = { 90 SP_LIBPATH_STRINGS, 91 NULL 92 }; 93 static const char *LD_LIBRARY_PATH[] = { 94 LD_LIBPATH_STRINGS, 95 NULL 96 }; 97 98 void 99 __collector_env_save_preloads () 100 { 101 /* save the list of SP_PRELOADs */ 102 int v; 103 for (v = 0; SP_PRELOAD[v]; v++) 104 { 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]); 107 } 108 NUM_SP_PRELOADS = v; 109 for (v = 0; SP_LIBRARY_PATH[v]; v++) 110 { 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"); 114 } 115 NUM_SP_LIBPATHS = v; 116 for (v = 0; LD_PRELOAD[v]; v++) 117 ; 118 NUM_LD_PRELOADS = v; 119 for (v = 0; LD_LIBRARY_PATH[v]; v++) 120 ; 121 NUM_LD_LIBPATHS = v; 122 for (v = 0; SP_ENV[v]; v++) 123 ; 124 NUM_SP_ENV_VARS = v; 125 for (v = 0; LD_ENV[v]; v++) 126 ; 127 NUM_LD_ENV_VARS = v; 128 } 129 130 /* free the memory involved in backing up the environment */ 131 void 132 __collector_env_backup_free () 133 { 134 int v = 0; 135 TprintfT (DBG_LT2, "env_backup_free()\n"); 136 for (v = 0; sp_env_backup[v]; v++) 137 { 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); 140 } 141 __collector_freeCSize (__collector_heap, (char**) sp_env_backup, 142 (NUM_SP_ENV_VARS + NUM_LD_ENV_VARS + 1) * sizeof (char*)); 143 } 144 145 char ** 146 __collector_env_backup () 147 { 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"); 152 return backup; 153 } 154 155 /* 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> 160 params: 161 old_str: original string 162 str: substring to prepend 163 return: pointer to updated string or NULL if string was not updated. 164 */ 165 static char * 166 env_prepend (const char *envvar, const char *str, const char *separator, 167 const char *old_str) 168 { 169 if (!envvar || *envvar == 0 || !str || *str == 0) 170 { 171 /* nothing to do */ 172 TprintfT (DBG_LT2, "env_prepend(\"%s\", \"%s\", \"%s\", \"%s\") -- nothing to do\n", 173 envvar, str, separator, old_str); 174 175 return NULL; 176 } 177 TprintfT (DBG_LT2, "env_prepend(\"%s\", \"%s\", \"%s\", \"%s\")\n", 178 envvar, str, separator, old_str); 179 char *ev; 180 size_t strsz; 181 if (!old_str || *old_str == 0) 182 { 183 strsz = __collector_strlen (envvar) + 1 + __collector_strlen (str) + 1; 184 ev = (char*) __collector_allocCSize (__collector_heap, strsz, 1); 185 if (ev) 186 { 187 CALL_UTIL (snprintf)(ev, strsz, "%s=%s", envvar, str); 188 assert (__collector_strlen (ev) + 1 == strsz); 189 } 190 else 191 TprintfT (DBG_LT2, "env_prepend(): could not allocate memory\n"); 192 } 193 else 194 { 195 char *p = CALL_UTIL (strstr)(old_str, str); 196 if (p) 197 { 198 TprintfT (DBG_LT2, "env_prepend(): %s=%s was already set\n", 199 envvar, old_str); 200 return NULL; 201 } 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); 205 if (ev) 206 { 207 CALL_UTIL (snprintf)(ev, strsz, "%s=%s%s%s", envvar, str, separator, old_str); 208 assert (__collector_strlen (ev) + 1 == strsz); 209 } 210 else 211 TprintfT (DBG_LT2, "env_prepend(): could not allocate memory\n"); 212 } 213 TprintfT (DBG_LT2, "env_prepend(\"%s\", \"%s\", \"%s\", \"%s\") returns \"%s\"\n", 214 envvar, str, separator, old_str, (ev == NULL ? "NULL" : ev)); 215 return ev; 216 } 217 218 /* 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. 223 params: 224 envvar: environment variable 225 str: substring to find 226 return: 0==success, nonzero on failure. 227 */ 228 int 229 putenv_prepend (const char *envvar, const char *str, const char *separator) 230 { 231 if (!envvar || *envvar == 0) 232 return 1; 233 const char * old_str = CALL_UTIL (getenv)(envvar); 234 char * newstr = env_prepend (envvar, str, separator, old_str); 235 if (newstr) 236 // now put the new variable into the environment 237 if (CALL_UTIL (putenv)(newstr) != 0) 238 { 239 TprintfT (DBG_LT2, "putenv_prepend(): ERROR %s is not set!\n", newstr); 240 return 1; 241 } 242 return 0; 243 } 244 245 /* 246 function: env_strip() 247 Finds substr in origstr; Removes 248 all characters from previous ':' or ' ' 249 up to and including any trailing ':' or ' '. 250 params: 251 env: environment variable contents 252 str: substring to find 253 return: count of instances removed from env 254 */ 255 static int 256 env_strip (char *origstr, const char *substr) 257 { 258 int removed = 0; 259 char *p, *q; 260 if (origstr == NULL || substr == NULL || *substr == 0) 261 return 0; 262 while ((p = q = CALL_UTIL (strstr)(origstr, substr))) 263 { 264 p += __collector_strlen (substr); 265 while (*p == ':' || *p == ' ') /* strip trailing separator */ 266 p++; 267 while (*q != ':' && *q != ' ' && *q != '=' && q != origstr) /* strip path */ 268 q--; 269 if (q != origstr) /* restore leading separator (if any) */ 270 q++; 271 __collector_strlcpy (q, p, __collector_strlen (p) + 1); 272 removed++; 273 } 274 return removed; 275 } 276 277 /* 278 function: env_ld_preload_strip() 279 Removes known libcollector shared objects from envv. 280 params: 281 var: shared object name (leading characters don't have to match) 282 return: 0 = so's removed, non-zero = so's not found. 283 */ 284 static int 285 env_ld_preload_strip (char *envv) 286 { 287 if (!envv || *envv == 0) 288 { 289 TprintfT (DBG_LT2, "env_ld_preload_strip(): WARNING - envv is NULL\n"); 290 return -1; 291 } 292 for (int v = 0; SP_PRELOAD[v]; v++) 293 if (env_strip (envv, sp_preloads[v])) 294 return 0; 295 if (line_mode != LM_CLOSED) 296 TprintfT (DBG_LT2, "env_ld_preload_strip(): WARNING - could not strip SP_PRELOADS from '%s'\n", 297 envv); 298 return -2; 299 } 300 301 void 302 __collector_env_print (char * label) 303 { 304 #if DEBUG 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++) 310 { 311 char *s = CALL_UTIL (getenv)(SP_ENV[v]); 312 if (s == NULL) 313 s = "<null>"; 314 TprintfT (DBG_LT2, " %s SP_ENV[%d] (0x%p): %s=\"%s\"\n", label, v, SP_ENV[v], SP_ENV[v], s); 315 } 316 for (int v = 0; LD_ENV[v]; v++) 317 { 318 char *s = CALL_UTIL (getenv)(LD_ENV[v]); 319 if (s == NULL) 320 s = "<null>"; 321 TprintfT (DBG_LT2, " %s LD_ENV[%d] (0x%p): %s=\"%s\"\n", label, v, LD_ENV[v], LD_ENV[v], s); 322 } 323 #endif 324 } 325 326 void 327 __collector_env_printall (char *label, char *envp[]) 328 { 329 #if DEBUG 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]); 333 #endif 334 } 335 336 /* match collector environment variable */ 337 int 338 env_match (char *envp[], const char *envvar) 339 { 340 int match = -1; 341 if (envp == NULL) 342 TprintfT (DBG_LT1, "env_match(%s): NULL envp!\n", envvar); 343 else 344 { 345 int i = 0; 346 while ((envp[i] != NULL) && (__collector_strStartWith (envp[i], envvar))) 347 i++; 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); 350 else 351 { 352 TprintfT (DBG_LT4, "env_match(): @%p [%d]%s defined in envp\n", envp, i, envp[i]); 353 match = i; 354 } 355 } 356 TprintfT (DBG_LT1, "env_match(%s): found in slot %d\n", envvar, match); 357 return (match); 358 } 359 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 */ 367 368 /* __collector__env_update() need be called after this to set LD_ENV*/ 369 char ** 370 __collector_env_allocate (char *const old_env[], int allocate_env) 371 { 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; 378 379 /* determine number of (used) slots in old_env */ 380 if (old_env) 381 while (old_env[old_env_size] != NULL) 382 old_env_size++; 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); 386 if (new_env == NULL) 387 return NULL; 388 TprintfT (DBG_LT4, "__collector_env_allocate(): old_env has %d entries, new_env @ 0x%p\n", old_env_size, new_env); 389 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]; 394 395 /* check each required environment variable, adding as required */ 396 const char * env_var; 397 int v; 398 for (v = 0; (env_var = SP_ENV[v]) != NULL; v++) 399 { 400 if (env_match ((char**) old_env, env_var) == -1) 401 { 402 int idx; 403 /* not found in old_env */ 404 if (allocate_env) 405 { 406 if ((idx = env_match (environ, env_var)) != -1) 407 { 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); 413 if (var == NULL) 414 return NULL; 415 __collector_strlcpy (var, environ[idx], varsz); 416 new_env[new_env_size++] = var; 417 } 418 else 419 { 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", 424 env_var); 425 } 426 } 427 else 428 { 429 if ((idx = env_match (sp_env_backup, env_var)) != -1) 430 { 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]; 435 } 436 else 437 { 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", 442 env_var); 443 } 444 } 445 } 446 } 447 448 for (v = 0; (env_var = LD_ENV[v]) != NULL; v++) 449 { 450 if (env_match ((char**) old_env, env_var) == -1) 451 { 452 int idx; 453 /* not found in old_env */ 454 if (allocate_env) 455 { 456 if ((idx = env_match (environ, env_var)) != -1) 457 { 458 /* found in environ */ 459 TprintfT (DBG_LT4, "__collector_env_allocate(): [%d]%s env restored!\n", 460 new_env_size, environ[idx]); 461 462 int varsz = __collector_strlen (env_var) + 2; 463 char * var = (char*) __collector_allocCSize (__collector_heap, varsz, 1); 464 if (var == NULL) 465 return NULL; 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; 469 } 470 } 471 else 472 { 473 if ((idx = env_match (sp_env_backup, env_var)) != -1) 474 { 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]; 479 } 480 } 481 } 482 } 483 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); 493 return (new_env); 494 } 495 496 /* unset collection environment variables */ 497 /* if they exist in env... */ 498 /* 1) push non-collectorized version to env */ 499 500 /* Not mt safe */ 501 void 502 __collector_env_unset (char *envp[]) 503 { 504 int v; 505 const char * env_name; 506 TprintfT (DBG_LT3, "env_unset(envp=0x%p)\n", envp); 507 if (envp == NULL) 508 { 509 for (v = 0; (env_name = LD_PRELOAD[v]); v++) 510 { 511 const char *env_val = CALL_UTIL (getenv)(env_name); 512 if (env_val && CALL_UTIL (strstr)(env_val, sp_preloads[v])) 513 { 514 size_t sz = __collector_strlen (env_name) + 1 + __collector_strlen (env_val) + 1; 515 char * ev = (char*) __collector_allocCSize (__collector_heap, sz, 1); 516 if (ev == NULL) 517 return; 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); 524 } 525 } 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)) 530 { 531 size_t sz = __collector_strlen (env_name) + 1 + __collector_strlen (env_val) + 1; 532 char * ev = (char*) __collector_allocCSize (__collector_heap, sz, 1); 533 if (ev == NULL) 534 return; 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); 541 } 542 __collector_env_print ("__collector_env_unset"); 543 } 544 else 545 { 546 __collector_env_printall ("__collector_env_unset, before", envp); 547 for (v = 0; (env_name = LD_PRELOAD[v]); v++) 548 { 549 int idx = env_match (envp, env_name); 550 if (idx != -1) 551 { 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); 556 envp[idx] = env_val; 557 TprintfT (DBG_LT4, "env_unset(): new %s\n", envp[idx]); 558 } 559 } 560 // unset JAVA_TOOL_OPTIONS 561 env_name = JAVA_TOOL_OPTIONS; 562 int idx = env_match(envp, env_name); 563 if (idx != -1) { 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); 568 envp[idx] = env_val; 569 TprintfT(DBG_LT4, "env_unset(): new %s\n", envp[idx]); 570 } 571 __collector_env_printall ("__collector_env_unset, after", envp ); 572 } 573 } 574 575 /* update collection environment variables */ 576 /* update LD_PRELOADs and push them */ 577 /* not mt safe */ 578 void 579 __collector_env_update (char *envp[]) 580 { 581 const char *env_name; 582 TprintfT (DBG_LT1, "__collector_env_update(envp=0x%p)\n", envp); 583 extern char **environ; 584 if (envp == NULL) 585 { 586 int v; 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 "); 590 591 /* SP_ENV */ 592 for (v = 0; (env_name = SP_ENV[v]) != NULL; v++) 593 { 594 if (env_match (environ, env_name) == -1) 595 { 596 int idx; 597 if ((idx = env_match (sp_env_backup, env_name)) != -1) 598 { 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", 604 sp_env_backup[idx]); 605 } 606 } 607 } 608 __collector_env_print (" env_update after SP_ENV settings "); 609 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 "); 617 618 /* LD_PRELOAD */ 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 "); 625 626 /* JAVA_TOOL_OPTIONS */ 627 if (java_mode) 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 "); 632 } 633 else 634 { 635 int v; 636 int idx; 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++) 641 { 642 int idx = env_match (envp, env_name); 643 if (idx != -1) 644 { 645 char *env_val = __collector_strchr (envp[idx], '='); 646 if (env_val) 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], 650 ":", env_val); 651 if (new_str) 652 envp[idx] = new_str; 653 } 654 } 655 656 /* LD_PRELOAD */ 657 for (v = 0; (env_name = LD_PRELOAD[v]); v++) 658 { 659 int idx = env_match (envp, env_name); 660 if (idx != -1) 661 { 662 char *env_val = __collector_strchr (envp[idx], '='); 663 if (env_val) 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], 667 " ", env_val); 668 if (new_str) 669 envp[idx] = new_str; 670 } 671 } 672 673 /* JAVA_TOOL_OPTIONS */ 674 if (java_mode) 675 { 676 env_name = JAVA_TOOL_OPTIONS; 677 idx = env_match (envp, env_name); 678 if (idx != -1) 679 { 680 char *env_val = __collector_strchr (envp[idx], '='); 681 if (env_val) 682 env_val++; /* skip '=' */ 683 char *new_str = env_prepend (env_name, COLLECTOR_JVMTI_OPTION, 684 " ", env_val); 685 if (new_str) 686 envp[idx] = new_str; 687 } 688 } 689 } 690 __collector_env_printall ("__collector_env_update, after", environ); 691 } 692 693 694 /*------------------------------------------------------------- putenv */ 695 int putenv () __attribute__ ((weak, alias ("__collector_putenv"))); 696 int _putenv () __attribute__ ((weak, alias ("__collector_putenv"))); 697 698 int 699 __collector_putenv (char * string) 700 { 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) 708 { 709 TprintfT (DBG_LT2, "__collector_putenv(): ERROR: no pointer found.\n"); 710 errno = EBUSY; 711 return -1; 712 } 713 } 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]); 719 } 720 721 /*------------------------------------------------------------- setenv */ 722 int setenv () __attribute__ ((weak, alias ("__collector_setenv"))); 723 int _setenv () __attribute__ ((weak, alias ("__collector_setenv"))); 724 725 int 726 __collector_setenv (const char *name, const char *value, int overwrite) 727 { 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) 735 { 736 TprintfT (DBG_LT2, "__collector_setenv(): ERROR: no pointer found.\n"); 737 errno = EBUSY; 738 return -1; 739 } 740 } 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); 745 if (ev == NULL) 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); 750 if (envp[0] == ev) 751 { 752 __collector_freeCSize (__collector_heap, ev, sz); 753 return CALL_UTIL (setenv)(name, value, overwrite); 754 } 755 else 756 { 757 char *env_val = __collector_strchr (envp[0], '='); 758 if (env_val) 759 { 760 *env_val = '\0'; 761 env_val++; /* skip '=' */ 762 } 763 return CALL_UTIL (setenv)(envp[0], env_val, overwrite); 764 } 765 } 766 767 /*------------------------------------------------------------- unsetenv */ 768 int unsetenv () __attribute__ ((weak, alias ("__collector_unsetenv"))); 769 int _unsetenv () __attribute__ ((weak, alias ("__collector_unsetenv"))); 770 771 int 772 __collector_unsetenv (const char *name) 773 { 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) 781 { 782 TprintfT (DBG_LT2, "__collector_unsetenv(): ERROR: no pointer found.\n"); 783 errno = EBUSY; 784 return -1; 785 } 786 } 787 int ret = CALL_UTIL (unsetenv)(name); 788 if (user_follow_mode == FOLLOW_NONE) 789 return ret; 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); 793 if (ev == NULL) 794 return ret; 795 CALL_UTIL (snprintf)(ev, sz, "%s=", name); 796 char * envp[] = {ev, NULL}; 797 __collector_env_update (envp); 798 if (envp[0] == ev) 799 __collector_freeCSize (__collector_heap, ev, sz); 800 else 801 CALL_UTIL (putenv)(envp[0]); 802 return ret; 803 } 804 805 /*------------------------------------------------------------- clearenv */ 806 int clearenv () __attribute__ ((weak, alias ("__collector_clearenv"))); 807 808 int 809 __collector_clearenv (void) 810 { 811 if (CALL_UTIL (clearenv) == __collector_clearenv || CALL_UTIL (clearenv) == NULL) 812 { 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) 819 { 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 ()); 823 errno = EBUSY; 824 return -1; 825 } 826 } 827 int ret = CALL_UTIL (clearenv)(); 828 if (user_follow_mode == FOLLOW_NONE) 829 return ret; 830 if (sp_env_backup == NULL) 831 { 832 TprintfT (DBG_LT2, "__collector_clearenv: ERROR sp_env_backup is not set!\n"); 833 return ret; 834 } 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", 838 sp_env_backup[v]); 839 return ret; 840 } 841