]> git.cameronkatri.com Git - cgit.git/commitdiff
Add generic filter/plugin infrastructure
authorLars Hjemli <hjemli@gmail.com>
Fri, 31 Jul 2009 15:38:38 +0000 (17:38 +0200)
committerLars Hjemli <hjemli@gmail.com>
Fri, 31 Jul 2009 15:39:51 +0000 (17:39 +0200)
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>
cgit.c
cgit.h
shared.c

diff --git a/cgit.c b/cgit.c
index 2039ab1de53699b6d29a23f1409461386589a227..779a4643abb87e84aef93dc40239c26a4a17d63b 100644 (file)
--- a/cgit.c
+++ b/cgit.c
 
 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)
 {
        if (!strcmp(name, "root-title"))
 void config_cb(const char *name, const char *value)
 {
        if (!strcmp(name, "root-title"))
diff --git a/cgit.h b/cgit.h
index 8c64efeaa6e7f5698751e202b64765280e3985cf..d0fff1f7f8cd5a0af073afce2d8ea23301811154 100644 (file)
--- a/cgit.h
+++ b/cgit.h
@@ -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 {
        char *agefile;
        char *cache_root;
 struct cgit_config {
        char *agefile;
        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 */
index cce0af40db29b77527fe1f6a7a897b4076c9621b..288cfa22b4888ee8b773188089d2ecc496714f94 100644 (file)
--- a/shared.c
+++ b/shared.c
@@ -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);
+}