diff options
-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
@@ -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")) |
@@ -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 */ |
@@ -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 | } | ||