all repos — cgit @ ed3497b0de6634350cd17b320538fba918d4084c

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
66struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype)
67{
68	struct cgit_filter *f;
69	int args_size = 0;
70
71	if (!cmd || !cmd[0])
72		return NULL;
73
74	f = xmalloc(sizeof(struct cgit_filter));
75	memset(f, 0, sizeof(struct cgit_filter));
76
77	switch (filtertype) {
78		case SOURCE:
79		case ABOUT:
80			f->extra_args = 1;
81			break;
82
83		case COMMIT:
84		default:
85			f->extra_args = 0;
86			break;
87	}
88
89	f->cmd = xstrdup(cmd);
90	args_size = (2 + f->extra_args) * sizeof(char *);
91	f->argv = xmalloc(args_size);
92	memset(f->argv, 0, args_size);
93	f->argv[0] = f->cmd;
94	return f;
95}