diff --git a/cgit.h b/cgit.h index 9b4be26..92e8c55 100644 --- a/cgit.h +++ b/cgit.h @@ -57,6 +57,13 @@ typedef enum { } filter_type; struct cgit_filter { + int (*open)(struct cgit_filter *, va_list ap); + int (*close)(struct cgit_filter *); + void (*fprintf)(struct cgit_filter *, FILE *, const char *prefix); +}; + +struct cgit_exec_filter { + struct cgit_filter base; char *cmd; char **argv; int extra_args; @@ -346,6 +353,7 @@ 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); extern void cgit_fprintf_filter(struct cgit_filter *filter, FILE *f, const char *prefix); +extern void cgit_exec_filter_init(struct cgit_exec_filter *filter, char *cmd, char **argv); extern struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype); extern void cgit_prepare_repo_env(struct cgit_repo * repo); diff --git a/filter.c b/filter.c index 80cf689..0f3edb0 100644 --- a/filter.c +++ b/filter.c @@ -13,15 +13,13 @@ #include #include -int cgit_open_filter(struct cgit_filter *filter, ...) +static int open_exec_filter(struct cgit_filter *base, va_list ap) { + struct cgit_exec_filter *filter = (struct cgit_exec_filter *) base; int i; - va_list ap; - va_start(ap, filter); for (i = 0; i < filter->extra_args; i++) filter->argv[i+1] = va_arg(ap, char *); - va_end(ap); filter->old_stdout = chk_positive(dup(STDOUT_FILENO), "Unable to duplicate STDOUT"); @@ -41,9 +39,9 @@ int cgit_open_filter(struct cgit_filter *filter, ...) return 0; } - -int cgit_close_filter(struct cgit_filter *filter) +static int close_exec_filter(struct cgit_filter *base) { + struct cgit_exec_filter *filter = (struct cgit_exec_filter *) base; int i, exit_status; chk_non_negative(dup2(filter->old_stdout, STDOUT_FILENO), @@ -63,21 +61,50 @@ done: } -void cgit_fprintf_filter(struct cgit_filter *filter, FILE *f, const char *prefix) +static void fprintf_exec_filter(struct cgit_filter *base, FILE *f, const char *prefix) { + struct cgit_exec_filter *filter = (struct cgit_exec_filter *) base; fprintf(f, "%s%s\n", prefix, filter->cmd); } -struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype) +int cgit_open_filter(struct cgit_filter *filter, ...) { - struct cgit_filter *f; - int args_size = 0; + int result; + va_list ap; + va_start(ap, filter); + result = filter->open(filter, ap); + va_end(ap); + return result; +} - if (!cmd || !cmd[0]) - return NULL; +int cgit_close_filter(struct cgit_filter *filter) +{ + return filter->close(filter); +} + +void cgit_fprintf_filter(struct cgit_filter *filter, FILE *f, const char *prefix) +{ + filter->fprintf(filter, f, prefix); +} + +void cgit_exec_filter_init(struct cgit_exec_filter *filter, char *cmd, char **argv) +{ + memset(filter, 0, sizeof(*filter)); + filter->base.open = open_exec_filter; + filter->base.close = close_exec_filter; + filter->base.fprintf = fprintf_exec_filter; + filter->cmd = cmd; + filter->argv = argv; +} + +static struct cgit_filter *new_exec_filter(const char *cmd, filter_type filtertype) +{ + struct cgit_exec_filter *f; + int args_size = 0; - f = xmalloc(sizeof(struct cgit_filter)); - memset(f, 0, sizeof(struct cgit_filter)); + f = xmalloc(sizeof(*f)); + /* We leave argv for now and assign it below. */ + cgit_exec_filter_init(f, xstrdup(cmd), NULL); switch (filtertype) { case SOURCE: @@ -91,10 +118,17 @@ struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype) break; } - f->cmd = xstrdup(cmd); args_size = (2 + f->extra_args) * sizeof(char *); f->argv = xmalloc(args_size); memset(f->argv, 0, args_size); f->argv[0] = f->cmd; - return f; + return &f->base; +} + +struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype) +{ + if (!cmd || !cmd[0]) + return NULL; + + return new_exec_filter(cmd, filtertype); } diff --git a/ui-snapshot.c b/ui-snapshot.c index 5136c49..7115ec4 100644 --- a/ui-snapshot.c +++ b/ui-snapshot.c @@ -58,13 +58,12 @@ static int write_compressed_tar_archive(const char *hex, char *filter_argv[]) { int rv; - struct cgit_filter f = { - .cmd = filter_argv[0], - .argv = filter_argv, - }; - cgit_open_filter(&f); + struct cgit_exec_filter f; + cgit_exec_filter_init(&f, filter_argv[0], filter_argv); + + cgit_open_filter(&f.base); rv = write_tar_archive(hex, prefix); - cgit_close_filter(&f); + cgit_close_filter(&f.base); return rv; }