diff options
-rw-r--r-- | shared.c | 78 |
1 files changed, 77 insertions, 1 deletions
@@ -7,6 +7,8 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include "cgit.h" | 9 | #include "cgit.h" |
10 | #include <stdio.h> | ||
11 | #include <linux/limits.h> | ||
10 | 12 | ||
11 | struct cgit_repolist cgit_repolist; | 13 | struct cgit_repolist cgit_repolist; |
12 | struct cgit_context ctx; | 14 | struct cgit_context ctx; |
@@ -376,6 +378,70 @@ int cgit_parse_snapshots_mask(const char *str) | |||
376 | return rv; | 378 | return rv; |
377 | } | 379 | } |
378 | 380 | ||
381 | typedef struct { | ||
382 | char * name; | ||
383 | char * value; | ||
384 | } cgit_env_var; | ||
385 | |||
386 | static char * prepare_env(struct cgit_repo * repo) { | ||
387 | cgit_env_var env_vars[] = { | ||
388 | { .name = "CGIT_REPO_URL", .value = repo->url }, | ||
389 | { .name = "CGIT_REPO_NAME", .value = repo->name }, | ||
390 | { .name = "CGIT_REPO_PATH", .value = repo->path }, | ||
391 | { .name = "CGIT_REPO_OWNER", .value = repo->owner }, | ||
392 | { .name = "CGIT_REPO_DEFBRANCH", .value = repo->defbranch }, | ||
393 | { .name = "CGIT_REPO_SECTION", .value = repo->section }, | ||
394 | { .name = "CGIT_REPO_CLONE_URL", .value = repo->clone_url } | ||
395 | }; | ||
396 | int env_var_count = ARRAY_SIZE(env_vars); | ||
397 | long values_space = (env_var_count * (PATH_MAX + 64)); | ||
398 | |||
399 | void * buffer; | ||
400 | char ** vars; | ||
401 | char * values; | ||
402 | int vars_index = 0; | ||
403 | unsigned int chars_printed; | ||
404 | |||
405 | /* Allocate buffer for environment variables: first in the buffer is an | ||
406 | * array of pointers to argument strings, terminated with a NULL pointer. | ||
407 | * After that the argument strings are placed after each other */ | ||
408 | buffer = malloc(((env_var_count + 1) * sizeof(char *)) + values_space); | ||
409 | if (!buffer) | ||
410 | return NULL; | ||
411 | |||
412 | vars = buffer; | ||
413 | values = (char *) &vars[env_var_count + 1]; | ||
414 | |||
415 | /* loop over all defined environment variables and their values */ | ||
416 | while (vars_index < env_var_count) { | ||
417 | char * name = env_vars[vars_index].name; | ||
418 | char * value = env_vars[vars_index].value; | ||
419 | |||
420 | if (!value) | ||
421 | value = ""; | ||
422 | |||
423 | chars_printed = snprintf(values, (values_space - 1), "%s=%s", name, | ||
424 | value); | ||
425 | if (chars_printed > (values_space - 1)) { | ||
426 | /* Buffer space exhausted: stop adding variables. | ||
427 | * Not all environment variables are defined, but the best we can | ||
428 | * do is to provide the ones that _are_ defined */ | ||
429 | break; | ||
430 | } | ||
431 | |||
432 | values[chars_printed] = '\0'; | ||
433 | *&vars[vars_index] = values; | ||
434 | values += (chars_printed + 1); | ||
435 | values_space -= (chars_printed + 1); | ||
436 | vars_index++; | ||
437 | } | ||
438 | |||
439 | /* terminate the array with pointers */ | ||
440 | *&vars[vars_index] = NULL; | ||
441 | |||
442 | return (char *) buffer; | ||
443 | } | ||
444 | |||
379 | int cgit_open_filter(struct cgit_filter *filter, struct cgit_repo * repo) | 445 | int cgit_open_filter(struct cgit_filter *filter, struct cgit_repo * repo) |
380 | { | 446 | { |
381 | 447 | ||
@@ -384,10 +450,20 @@ int cgit_open_filter(struct cgit_filter *filter, struct cgit_repo * repo) | |||
384 | chk_zero(pipe(filter->pipe_fh), "Unable to create pipe to subprocess"); | 450 | chk_zero(pipe(filter->pipe_fh), "Unable to create pipe to subprocess"); |
385 | filter->pid = chk_non_negative(fork(), "Unable to create subprocess"); | 451 | filter->pid = chk_non_negative(fork(), "Unable to create subprocess"); |
386 | if (filter->pid == 0) { | 452 | if (filter->pid == 0) { |
453 | char * env = NULL; | ||
454 | |||
387 | close(filter->pipe_fh[1]); | 455 | close(filter->pipe_fh[1]); |
388 | chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO), | 456 | chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO), |
389 | "Unable to use pipe as STDIN"); | 457 | "Unable to use pipe as STDIN"); |
390 | execvp(filter->cmd, filter->argv); | 458 | |
459 | if (repo) | ||
460 | env = prepare_env(repo); | ||
461 | |||
462 | execve(filter->cmd, filter->argv, (char **)env); | ||
463 | |||
464 | if (env) | ||
465 | free(env); | ||
466 | |||
391 | die("Unable to exec subprocess %s: %s (%d)", filter->cmd, | 467 | die("Unable to exec subprocess %s: %s (%d)", filter->cmd, |
392 | strerror(errno), errno); | 468 | strerror(errno), errno); |
393 | } | 469 | } |