aboutsummaryrefslogtreecommitdiffstats
path: root/pipe.c
blob: ec647697eeea21bee97a58521077790f46093299 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2019 Daniel Borkmann <daniel@iogearbox.net> */

#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <libgen.h>

#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>

#include "l2md.h"

enum {
	FORK_ERROR = -1,
	FORK_CHILD =  0,
};

static void pipe_new_mail(struct config_repo *repo, uint32_t which,
			  const char *oid, const void *raw, size_t len)
{
	char tmp[PATH_MAX];
	int fd[2];

	xpipe(fd);
	switch(fork()) {
	case FORK_ERROR:
		panic("Cannot fork: %s\n", strerror(errno));
	case FORK_CHILD:
		close(fd[1]);
		dup2(fd[0], STDIN_FILENO);
		close(fd[0]);
		strcpy(tmp, repo->out);
		execl(repo->out, basename(tmp), NULL);
		break;
	default:
		close(fd[0]);
		xwrite(fd[1], raw, len);
		close(fd[1]);
		wait(NULL);
		break;
	}
}

static void pipe_bootstrap(struct config *cfg)
{
	struct config_repo *repo;
	struct stat sb;
	uint32_t i;

	repo_for_each(cfg, repo, i) {
		if (stat(repo->out, &sb) != 0)
			panic("Cannot stat %s: %s\n", repo->out,
			      strerror(errno));
		if (!(sb.st_mode & S_IXUSR))
			panic("%s is not an executable!\n", repo->out);
	}
}

static void pipe_set_defaults(struct config *cfg)
{
}

const struct mail_ops ops_pipe = {
	.name		= "pipe",
	.bootstrap	= pipe_bootstrap,
	.new_mail	= pipe_new_mail,
	.set_defaults	= pipe_set_defaults,
};