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 | } | ||
