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>
This commit is contained in:
Lars Hjemli 2009-07-31 17:38:38 +02:00
parent 286a905842
commit d6f6072560
3 changed files with 62 additions and 0 deletions

15
cgit.c
View File

@ -17,6 +17,21 @@
const char *cgit_version = CGIT_VERSION; const char *cgit_version = CGIT_VERSION;
struct cgit_filter *new_filter(const char *cmd, int extra_args)
{
struct cgit_filter *f;
if (!cmd)
return NULL;
f = xmalloc(sizeof(struct cgit_filter));
f->cmd = xstrdup(cmd);
f->argv = xmalloc((2 + extra_args) * sizeof(char *));
f->argv[0] = f->cmd;
f->argv[1] = NULL;
return f;
}
void config_cb(const char *name, const char *value) void config_cb(const char *name, const char *value)
{ {
if (!strcmp(name, "root-title")) if (!strcmp(name, "root-title"))

12
cgit.h
View File

@ -129,6 +129,15 @@ struct cgit_query {
int showmsg; int showmsg;
}; };
struct cgit_filter {
char *cmd;
char **argv;
int old_stdout;
int pipe_fh[2];
int pid;
int exitstatus;
};
struct cgit_config { struct cgit_config {
char *agefile; char *agefile;
char *cache_root; char *cache_root;
@ -248,5 +257,8 @@ extern const char *cgit_repobasename(const char *reponame);
extern int cgit_parse_snapshots_mask(const char *str); extern int cgit_parse_snapshots_mask(const char *str);
extern int cgit_open_filter(struct cgit_filter *filter);
extern int cgit_close_filter(struct cgit_filter *filter);
#endif /* CGIT_H */ #endif /* CGIT_H */

View File

@ -355,3 +355,38 @@ int cgit_parse_snapshots_mask(const char *str)
} }
return rv; return rv;
} }
int cgit_open_filter(struct cgit_filter *filter)
{
filter->old_stdout = chk_positive(dup(STDOUT_FILENO),
"Unable to duplicate STDOUT");
chk_zero(pipe(filter->pipe_fh), "Unable to create pipe to subprocess");
filter->pid = chk_non_negative(fork(), "Unable to create subprocess");
if (filter->pid == 0) {
close(filter->pipe_fh[1]);
chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO),
"Unable to use pipe as STDIN");
execvp(filter->cmd, filter->argv);
die("Unable to exec subprocess %s: %s (%d)", filter->cmd,
strerror(errno), errno);
}
close(filter->pipe_fh[0]);
chk_non_negative(dup2(filter->pipe_fh[1], STDOUT_FILENO),
"Unable to use pipe as STDOUT");
close(filter->pipe_fh[1]);
return 0;
}
int cgit_close_filter(struct cgit_filter *filter)
{
chk_non_negative(dup2(filter->old_stdout, STDOUT_FILENO),
"Unable to restore STDOUT");
close(filter->old_stdout);
if (filter->pid < 0)
return 0;
waitpid(filter->pid, &filter->exitstatus, 0);
if (WIFEXITED(filter->exitstatus) && !WEXITSTATUS(filter->exitstatus))
return 0;
die("Subprocess %s exited abnormally", filter->cmd);
}