diff options
author | Lars Hjemli | 2009-07-31 17:38:38 +0200 |
---|---|---|
committer | Lars Hjemli | 2009-07-31 17:39:51 +0200 |
commit | d6f6072560c963065b13c704fa1fa6f8950e4bac (patch) | |
tree | 096a542cd404d4a174f2f4a1da44ab0df99aa7c3 | |
parent | Merge branch 'lh/embedded' (diff) | |
download | cgit-d6f6072560c963065b13c704fa1fa6f8950e4bac.tar.gz cgit-d6f6072560c963065b13c704fa1fa6f8950e4bac.zip |
Add generic filter/plugin infrastructure
The functions cgit_open_filter() and cgit_close_filter() can be used to execute filters on the output stream from cgit. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | cgit.c | 15 | ||||
-rw-r--r-- | cgit.h | 12 | ||||
-rw-r--r-- | shared.c | 35 |
3 files changed, 62 insertions, 0 deletions
diff --git a/cgit.c b/cgit.c index 2039ab1..779a464 100644 --- a/cgit.c +++ b/cgit.c | |||
@@ -17,6 +17,21 @@ | |||
17 | 17 | ||
18 | const char *cgit_version = CGIT_VERSION; | 18 | const char *cgit_version = CGIT_VERSION; |
19 | 19 | ||
20 | struct cgit_filter *new_filter(const char *cmd, int extra_args) | ||
21 | { | ||
22 | struct cgit_filter *f; | ||
23 | |||
24 | if (!cmd) | ||
25 | return NULL; | ||
26 | |||
27 | f = xmalloc(sizeof(struct cgit_filter)); | ||
28 | f->cmd = xstrdup(cmd); | ||
29 | f->argv = xmalloc((2 + extra_args) * sizeof(char *)); | ||
30 | f->argv[0] = f->cmd; | ||
31 | f->argv[1] = NULL; | ||
32 | return f; | ||
33 | } | ||
34 | |||
20 | void config_cb(const char *name, const char *value) | 35 | void config_cb(const char *name, const char *value) |
21 | { | 36 | { |
22 | if (!strcmp(name, "root-title")) | 37 | if (!strcmp(name, "root-title")) |
diff --git a/cgit.h b/cgit.h index 8c64efe..d0fff1f 100644 --- a/cgit.h +++ b/cgit.h | |||
@@ -129,6 +129,15 @@ struct cgit_query { | |||
129 | int showmsg; | 129 | int showmsg; |
130 | }; | 130 | }; |
131 | 131 | ||
132 | struct cgit_filter { | ||
133 | char *cmd; | ||
134 | char **argv; | ||
135 | int old_stdout; | ||
136 | int pipe_fh[2]; | ||
137 | int pid; | ||
138 | int exitstatus; | ||
139 | }; | ||
140 | |||
132 | struct cgit_config { | 141 | struct cgit_config { |
133 | char *agefile; | 142 | char *agefile; |
134 | char *cache_root; | 143 | char *cache_root; |
@@ -248,5 +257,8 @@ extern const char *cgit_repobasename(const char *reponame); | |||
248 | 257 | ||
249 | extern int cgit_parse_snapshots_mask(const char *str); | 258 | extern int cgit_parse_snapshots_mask(const char *str); |
250 | 259 | ||
260 | extern int cgit_open_filter(struct cgit_filter *filter); | ||
261 | extern int cgit_close_filter(struct cgit_filter *filter); | ||
262 | |||
251 | 263 | ||
252 | #endif /* CGIT_H */ | 264 | #endif /* CGIT_H */ |
diff --git a/shared.c b/shared.c index cce0af4..288cfa2 100644 --- a/shared.c +++ b/shared.c | |||
@@ -355,3 +355,38 @@ int cgit_parse_snapshots_mask(const char *str) | |||
355 | } | 355 | } |
356 | return rv; | 356 | return rv; |
357 | } | 357 | } |
358 | |||
359 | int cgit_open_filter(struct cgit_filter *filter) | ||
360 | { | ||
361 | |||
362 | filter->old_stdout = chk_positive(dup(STDOUT_FILENO), | ||
363 | "Unable to duplicate STDOUT"); | ||
364 | chk_zero(pipe(filter->pipe_fh), "Unable to create pipe to subprocess"); | ||
365 | filter->pid = chk_non_negative(fork(), "Unable to create subprocess"); | ||
366 | if (filter->pid == 0) { | ||
367 | close(filter->pipe_fh[1]); | ||
368 | chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO), | ||
369 | "Unable to use pipe as STDIN"); | ||
370 | execvp(filter->cmd, filter->argv); | ||
371 | die("Unable to exec subprocess %s: %s (%d)", filter->cmd, | ||
372 | strerror(errno), errno); | ||
373 | } | ||
374 | close(filter->pipe_fh[0]); | ||
375 | chk_non_negative(dup2(filter->pipe_fh[1], STDOUT_FILENO), | ||
376 | "Unable to use pipe as STDOUT"); | ||
377 | close(filter->pipe_fh[1]); | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | int cgit_close_filter(struct cgit_filter *filter) | ||
382 | { | ||
383 | chk_non_negative(dup2(filter->old_stdout, STDOUT_FILENO), | ||
384 | "Unable to restore STDOUT"); | ||
385 | close(filter->old_stdout); | ||
386 | if (filter->pid < 0) | ||
387 | return 0; | ||
388 | waitpid(filter->pid, &filter->exitstatus, 0); | ||
389 | if (WIFEXITED(filter->exitstatus) && !WEXITSTATUS(filter->exitstatus)) | ||
390 | return 0; | ||
391 | die("Subprocess %s exited abnormally", filter->cmd); | ||
392 | } | ||