all repos — cgit @ 632efb25c07c1b014a4e8cfbbea759f517c2aaf6

a hyperfast web frontend for git written in c

filter.c (view raw)

  1/* filter.c: filter framework functions
  2 *
  3 * Copyright (C) 2006-2014 cgit Development Team <cgit@lists.zx2c4.com>
  4 *
  5 * Licensed under GNU General Public License v2
  6 *   (see COPYING for full license text)
  7 */
  8
  9#include "cgit.h"
 10#include <sys/types.h>
 11#include <sys/wait.h>
 12#include <unistd.h>
 13#include <string.h>
 14#include <stdlib.h>
 15
 16int cgit_open_filter(struct cgit_filter *filter, ...)
 17{
 18	int i;
 19	va_list ap;
 20
 21	va_start(ap, filter);
 22	for (i = 0; i < filter->extra_args; i++)
 23		filter->argv[i+1] = va_arg(ap, char *);
 24	va_end(ap);
 25
 26	filter->old_stdout = chk_positive(dup(STDOUT_FILENO),
 27		"Unable to duplicate STDOUT");
 28	chk_zero(pipe(filter->pipe_fh), "Unable to create pipe to subprocess");
 29	filter->pid = chk_non_negative(fork(), "Unable to create subprocess");
 30	if (filter->pid == 0) {
 31		close(filter->pipe_fh[1]);
 32		chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO),
 33			"Unable to use pipe as STDIN");
 34		execvp(filter->cmd, filter->argv);
 35		die_errno("Unable to exec subprocess %s", filter->cmd);
 36	}
 37	close(filter->pipe_fh[0]);
 38	chk_non_negative(dup2(filter->pipe_fh[1], STDOUT_FILENO),
 39		"Unable to use pipe as STDOUT");
 40	close(filter->pipe_fh[1]);
 41	return 0;
 42}
 43
 44
 45int cgit_close_filter(struct cgit_filter *filter)
 46{
 47	int i, exit_status;
 48
 49	chk_non_negative(dup2(filter->old_stdout, STDOUT_FILENO),
 50		"Unable to restore STDOUT");
 51	close(filter->old_stdout);
 52	if (filter->pid < 0)
 53		goto done;
 54	waitpid(filter->pid, &exit_status, 0);
 55	if (WIFEXITED(exit_status) && !WEXITSTATUS(exit_status))
 56		goto done;
 57	die("Subprocess %s exited abnormally", filter->cmd);
 58
 59done:
 60	for (i = 0; i < filter->extra_args; i++)
 61		filter->argv[i+1] = NULL;
 62	return 0;
 63
 64}
 65
 66void cgit_fprintf_filter(struct cgit_filter *filter, FILE *f, const char *prefix)
 67{
 68	fprintf(f, "%s%s\n", prefix, filter->cmd);
 69}
 70
 71struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype)
 72{
 73	struct cgit_filter *f;
 74	int args_size = 0;
 75
 76	if (!cmd || !cmd[0])
 77		return NULL;
 78
 79	f = xmalloc(sizeof(struct cgit_filter));
 80	memset(f, 0, sizeof(struct cgit_filter));
 81
 82	switch (filtertype) {
 83		case SOURCE:
 84		case ABOUT:
 85			f->extra_args = 1;
 86			break;
 87
 88		case COMMIT:
 89		default:
 90			f->extra_args = 0;
 91			break;
 92	}
 93
 94	f->cmd = xstrdup(cmd);
 95	args_size = (2 + f->extra_args) * sizeof(char *);
 96	f->argv = xmalloc(args_size);
 97	memset(f->argv, 0, args_size);
 98	f->argv[0] = f->cmd;
 99	return f;
100}