diff options
author | Lars Hjemli <hjemli@gmail.com> | 2011-03-26 19:22:35 (JST) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2011-03-26 19:27:29 (JST) |
commit | c2b58ed8539fcfa4f05cc9da316bbc782f4b8f10 (patch) | |
tree | 96fc98e1cff5caebbd73725d4ca0605211ebe83f /shared.c | |
parent | b2cf630a4b423bbda6507b7f658042563e76b36e (diff) | |
download | cgit-c2b58ed8539fcfa4f05cc9da316bbc782f4b8f10.zip cgit-c2b58ed8539fcfa4f05cc9da316bbc782f4b8f10.tar.gz |
shared.c: use execvp() to execute filter commands
This reintroduces the use of execvp(), since the filter commands doesn't
always contain an absolute path (i.e. snapshot compression filters).
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'shared.c')
-rw-r--r-- | shared.c | 68 |
1 files changed, 11 insertions, 57 deletions
@@ -383,7 +383,7 @@ typedef struct { | |||
383 | char * value; | 383 | char * value; |
384 | } cgit_env_var; | 384 | } cgit_env_var; |
385 | 385 | ||
386 | static char * prepare_env(struct cgit_repo * repo) { | 386 | static void prepare_env(struct cgit_repo * repo) { |
387 | cgit_env_var env_vars[] = { | 387 | cgit_env_var env_vars[] = { |
388 | { .name = "CGIT_REPO_URL", .value = repo->url }, | 388 | { .name = "CGIT_REPO_URL", .value = repo->url }, |
389 | { .name = "CGIT_REPO_NAME", .value = repo->name }, | 389 | { .name = "CGIT_REPO_NAME", .value = repo->name }, |
@@ -394,52 +394,14 @@ static char * prepare_env(struct cgit_repo * repo) { | |||
394 | { .name = "CGIT_REPO_CLONE_URL", .value = repo->clone_url } | 394 | { .name = "CGIT_REPO_CLONE_URL", .value = repo->clone_url } |
395 | }; | 395 | }; |
396 | int env_var_count = ARRAY_SIZE(env_vars); | 396 | int env_var_count = ARRAY_SIZE(env_vars); |
397 | long values_space = (env_var_count * (PATH_MAX + 64)); | 397 | cgit_env_var *p, *q; |
398 | 398 | static char *warn = "cgit warning: failed to set env: %s=%s\n"; | |
399 | void * buffer; | 399 | |
400 | char ** vars; | 400 | p = env_vars; |
401 | char * values; | 401 | q = p + env_var_count; |
402 | int vars_index = 0; | 402 | for (; p < q; p++) |
403 | unsigned int chars_printed; | 403 | if (setenv(p->name, p->value, 1)) |
404 | 404 | fprintf(stderr, warn, p->name, p->value); | |
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 | } | 405 | } |
444 | 406 | ||
445 | int cgit_open_filter(struct cgit_filter *filter, struct cgit_repo * repo) | 407 | int cgit_open_filter(struct cgit_filter *filter, struct cgit_repo * repo) |
@@ -450,20 +412,12 @@ int cgit_open_filter(struct cgit_filter *filter, struct cgit_repo * repo) | |||
450 | chk_zero(pipe(filter->pipe_fh), "Unable to create pipe to subprocess"); | 412 | chk_zero(pipe(filter->pipe_fh), "Unable to create pipe to subprocess"); |
451 | filter->pid = chk_non_negative(fork(), "Unable to create subprocess"); | 413 | filter->pid = chk_non_negative(fork(), "Unable to create subprocess"); |
452 | if (filter->pid == 0) { | 414 | if (filter->pid == 0) { |
453 | char * env = NULL; | ||
454 | |||
455 | close(filter->pipe_fh[1]); | 415 | close(filter->pipe_fh[1]); |
456 | chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO), | 416 | chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO), |
457 | "Unable to use pipe as STDIN"); | 417 | "Unable to use pipe as STDIN"); |
458 | |||
459 | if (repo) | 418 | if (repo) |
460 | env = prepare_env(repo); | 419 | prepare_env(repo); |
461 | 420 | execvp(filter->cmd, filter->argv); | |
462 | execve(filter->cmd, filter->argv, (char **)env); | ||
463 | |||
464 | if (env) | ||
465 | free(env); | ||
466 | |||
467 | die("Unable to exec subprocess %s: %s (%d)", filter->cmd, | 421 | die("Unable to exec subprocess %s: %s (%d)", filter->cmd, |
468 | strerror(errno), errno); | 422 | strerror(errno), errno); |
469 | } | 423 | } |