| 448 | } |
| 449 | |
| 450 | static char **prep_childenv(const char *const *deltaenv) |
| 451 | { |
| 452 | extern char **environ; |
| 453 | char **childenv; |
| 454 | struct string_list env = STRING_LIST_INIT_DUP; |
| 455 | struct strbuf key = STRBUF_INIT; |
| 456 | const char *const *p; |
| 457 | int i; |
| 458 | |
| 459 | /* Construct a sorted string list consisting of the current environ */ |
| 460 | for (p = (const char *const *) environ; p && *p; p++) { |
| 461 | const char *equals = strchr(*p, '='); |
| 462 | |
| 463 | if (equals) { |
| 464 | strbuf_reset(&key); |
| 465 | strbuf_add(&key, *p, equals - *p); |
| 466 | string_list_append(&env, key.buf)->util = (void *) *p; |
| 467 | } else { |
| 468 | string_list_append(&env, *p)->util = (void *) *p; |
| 469 | } |
| 470 | } |
| 471 | string_list_sort(&env); |
| 472 | |
| 473 | /* Merge in 'deltaenv' with the current environ */ |
| 474 | for (p = deltaenv; p && *p; p++) { |
| 475 | const char *equals = strchr(*p, '='); |
| 476 | |
| 477 | if (equals) { |
| 478 | /* ('key=value'), insert or replace entry */ |
| 479 | strbuf_reset(&key); |
| 480 | strbuf_add(&key, *p, equals - *p); |
| 481 | string_list_insert(&env, key.buf)->util = (void *) *p; |
| 482 | } else { |
| 483 | /* otherwise ('key') remove existing entry */ |
| 484 | string_list_remove(&env, *p, 0); |
| 485 | } |
| 486 | } |
| 487 | |
| 488 | /* Create an array of 'char *' to be used as the childenv */ |
| 489 | ALLOC_ARRAY(childenv, env.nr + 1); |
| 490 | for (i = 0; i < env.nr; i++) |
| 491 | childenv[i] = env.items[i].util; |
| 492 | childenv[env.nr] = NULL; |
| 493 | |
| 494 | string_list_clear(&env, 0); |
| 495 | strbuf_release(&key); |
| 496 | return childenv; |
| 497 | } |
| 498 | |
| 499 | struct atfork_state { |
| 500 | #ifndef NO_PTHREADS |
no test coverage detected