| // 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, |
| }; |