aboutsummaryrefslogtreecommitdiffstats
path: root/shared.c
diff options
context:
space:
mode:
authorGravatar Ferry Huberts <ferry.huberts@pelagic.nl>2011-03-23 19:57:43 (JST)
committerGravatar Lars Hjemli <hjemli@gmail.com>2011-03-26 19:03:42 (JST)
commit14f28923a2ed31fba9bf7042e8e2dff21717c333 (patch)
treee3943ff98a2a59f4503e96bbc4ea135d80aa8c81 /shared.c
parentd87bba846d368e560193a1f75de6d66bffe986cf (diff)
downloadcgit-14f28923a2ed31fba9bf7042e8e2dff21717c333.zip
cgit-14f28923a2ed31fba9bf7042e8e2dff21717c333.tar.gz
cgit_open_filter: hand down repo configuration to script
The environment variables can be used to (for example) resolve the following situation: Suppose a server setup in which each repository has a trac instance; the commit filter needs to know with which repository it's dealing in order to be able to resolve the #123 ticket numbers in the commit messages into hyperlinks into the correct trac instance. Signed-off-by: Ferry Huberts <ferry.huberts@pelagic.nl> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'shared.c')
-rw-r--r--shared.c78
1 files changed, 77 insertions, 1 deletions
diff --git a/shared.c b/shared.c
index e4879df..8c3d18a 100644
--- a/shared.c
+++ b/shared.c
@@ -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
11struct cgit_repolist cgit_repolist; 13struct cgit_repolist cgit_repolist;
12struct cgit_context ctx; 14struct 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
381typedef struct {
382 char * name;
383 char * value;
384} cgit_env_var;
385
386static 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
379int cgit_open_filter(struct cgit_filter *filter, struct cgit_repo * repo) 445int 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 }