diff options
| author | Lars Hjemli <hjemli@gmail.com> | 2009-07-31 17:38:38 +0200 | 
|---|---|---|
| committer | Lars Hjemli <hjemli@gmail.com> | 2009-07-31 17:39:51 +0200 | 
| commit | d6f6072560c963065b13c704fa1fa6f8950e4bac (patch) | |
| tree | 096a542cd404d4a174f2f4a1da44ab0df99aa7c3 | |
| parent | 286a905842dc0bec6d21a614ec4a97c5f19d5bc4 (diff) | |
| download | cgit-d6f6072560c963065b13c704fa1fa6f8950e4bac.tar.gz cgit-d6f6072560c963065b13c704fa1fa6f8950e4bac.tar.bz2 cgit-d6f6072560c963065b13c704fa1fa6f8950e4bac.zip | |
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>
| -rw-r--r-- | cgit.c | 15 | ||||
| -rw-r--r-- | cgit.h | 12 | ||||
| -rw-r--r-- | shared.c | 35 | 
3 files changed, 62 insertions, 0 deletions
| @@ -17,6 +17,21 @@  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")) @@ -129,6 +129,15 @@ struct cgit_query {  	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; @@ -248,5 +257,8 @@ extern const char *cgit_repobasename(const char *reponame);  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 */ @@ -355,3 +355,38 @@ int cgit_parse_snapshots_mask(const char *str)  	}  	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); +} | 
