1*3882aa95Santon /* $OpenBSD: mailwrapper.c,v 1.23 2017/06/14 16:32:11 anton Exp $ */
2a53d1a28Sjakob /* $NetBSD: mailwrapper.c,v 1.2 1999/02/20 22:10:07 thorpej Exp $ */
3a53d1a28Sjakob
4a53d1a28Sjakob /*
5a53d1a28Sjakob * Copyright (c) 1998
6a53d1a28Sjakob * Perry E. Metzger. All rights reserved.
7a53d1a28Sjakob *
8a53d1a28Sjakob * Redistribution and use in source and binary forms, with or without
9a53d1a28Sjakob * modification, are permitted provided that the following conditions
10a53d1a28Sjakob * are met:
11a53d1a28Sjakob * 1. Redistributions of source code must retain the above copyright
12a53d1a28Sjakob * notice, this list of conditions and the following disclaimer.
13a53d1a28Sjakob * 2. Redistributions in binary form must reproduce the above copyright
14a53d1a28Sjakob * notice, this list of conditions and the following disclaimer in the
15a53d1a28Sjakob * documentation and/or other materials provided with the distribution.
16a53d1a28Sjakob * 3. All advertising materials mentioning features or use of this software
17a53d1a28Sjakob * must display the following acknowledgment:
18a53d1a28Sjakob * This product includes software developed for the NetBSD Project
19a53d1a28Sjakob * by Perry E. Metzger.
20a53d1a28Sjakob * 4. The name of the author may not be used to endorse or promote products
21a53d1a28Sjakob * derived from this software without specific prior written permission.
22a53d1a28Sjakob *
23a53d1a28Sjakob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24a53d1a28Sjakob * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25a53d1a28Sjakob * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26a53d1a28Sjakob * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27a53d1a28Sjakob * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28a53d1a28Sjakob * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29a53d1a28Sjakob * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30a53d1a28Sjakob * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31a53d1a28Sjakob * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32a53d1a28Sjakob * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33a53d1a28Sjakob */
34a53d1a28Sjakob
35a53d1a28Sjakob #include <err.h>
36a53d1a28Sjakob #include <stdio.h>
37a53d1a28Sjakob #include <string.h>
38a53d1a28Sjakob #include <stdlib.h>
3976d33112Sjakob #include <syslog.h>
40a53d1a28Sjakob #include <unistd.h>
41a53d1a28Sjakob #include <util.h>
42a53d1a28Sjakob
43a53d1a28Sjakob #define _PATH_MAILERCONF "/etc/mailer.conf"
4460e6d519Ssunil #define _PATH_DEFAULTMTA "/usr/sbin/smtpctl"
45a53d1a28Sjakob
46a53d1a28Sjakob struct arglist {
47a53d1a28Sjakob size_t argc, maxc;
48a53d1a28Sjakob char **argv;
49a53d1a28Sjakob };
50a53d1a28Sjakob
51c72b5b24Smillert static void initarg(struct arglist *);
523a1ce664Sjung static void addarg(struct arglist *, const char *);
53a53d1a28Sjakob
54a53d1a28Sjakob extern const char *__progname; /* from crt0.o */
55a53d1a28Sjakob
56a53d1a28Sjakob static void
initarg(struct arglist * al)5755ef04e3Sderaadt initarg(struct arglist *al)
58a53d1a28Sjakob {
59a53d1a28Sjakob al->argc = 0;
60a53d1a28Sjakob al->maxc = 10;
611ed98fdfSderaadt if ((al->argv = calloc(al->maxc, sizeof(char *))) == NULL)
620f09aad0Sderaadt err(1, "malloc");
63a53d1a28Sjakob }
64a53d1a28Sjakob
65a53d1a28Sjakob static void
addarg(struct arglist * al,const char * arg)663a1ce664Sjung addarg(struct arglist *al, const char *arg)
67a53d1a28Sjakob {
68a53d1a28Sjakob if (al->argc == al->maxc) {
69a53d1a28Sjakob al->maxc <<= 1;
70779af70dSderaadt al->argv = reallocarray(al->argv, al->maxc, sizeof(char *));
719c4bd211Smillert if (al->argv == NULL)
720f09aad0Sderaadt err(1, "realloc");
73a53d1a28Sjakob }
743a1ce664Sjung
75a53d1a28Sjakob al->argv[al->argc++] = (char *)arg;
76a53d1a28Sjakob }
77a53d1a28Sjakob
78a53d1a28Sjakob int
main(int argc,char * argv[])79*3882aa95Santon main(int argc, char *argv[])
80a53d1a28Sjakob {
81a53d1a28Sjakob FILE *config;
82a53d1a28Sjakob char *line, *cp, *from, *to, *ap;
83366cf49cSmillert const char *progname;
84a53d1a28Sjakob size_t len, lineno = 0;
85a53d1a28Sjakob struct arglist al;
86a53d1a28Sjakob
870b6ac1ffSderaadt if (pledge("stdio rpath exec", NULL) == -1)
880b6ac1ffSderaadt err(1, "pledge");
890b6ac1ffSderaadt
90366cf49cSmillert /* change __progname to mailwrapper so we get sensible error messages */
91366cf49cSmillert progname = __progname;
92366cf49cSmillert __progname = "mailwrapper";
93366cf49cSmillert
94a53d1a28Sjakob initarg(&al);
95a53d1a28Sjakob for (len = 0; len < argc; len++)
963a1ce664Sjung addarg(&al, argv[len]);
97a53d1a28Sjakob
980b6ac1ffSderaadt config = fopen(_PATH_MAILERCONF, "r");
990b6ac1ffSderaadt
1000b6ac1ffSderaadt if (pledge("stdio exec", NULL) == -1)
1010b6ac1ffSderaadt err(1, "pledge");
1020b6ac1ffSderaadt
1030b6ac1ffSderaadt if (config == NULL) {
1043a1ce664Sjung addarg(&al, NULL);
105366cf49cSmillert openlog(__progname, LOG_PID, LOG_MAIL);
1060f09aad0Sderaadt syslog(LOG_INFO, "cannot open %s, using %s as default MTA",
10776d33112Sjakob _PATH_MAILERCONF, _PATH_DEFAULTMTA);
10876d33112Sjakob closelog();
109*3882aa95Santon execv(_PATH_DEFAULTMTA, al.argv);
1100731caacSmillert err(1, "cannot exec %s", _PATH_DEFAULTMTA);
11176d33112Sjakob /*NOTREACHED*/
11276d33112Sjakob }
113a53d1a28Sjakob
114a53d1a28Sjakob for (;;) {
115a53d1a28Sjakob if ((line = fparseln(config, &len, &lineno, NULL, 0)) == NULL) {
116a53d1a28Sjakob if (feof(config))
1170f09aad0Sderaadt errx(1, "no mapping in %s", _PATH_MAILERCONF);
1180f09aad0Sderaadt err(1, "fparseln");
119a53d1a28Sjakob }
120a53d1a28Sjakob
121a53d1a28Sjakob #define WS " \t\n"
122a53d1a28Sjakob cp = line;
123a53d1a28Sjakob
124a53d1a28Sjakob cp += strspn(cp, WS);
125a53d1a28Sjakob if (cp[0] == '\0') {
126a53d1a28Sjakob /* empty line */
127a53d1a28Sjakob free(line);
128a53d1a28Sjakob continue;
129a53d1a28Sjakob }
130a53d1a28Sjakob
131bf3eb731Sotto if ((from = strsep(&cp, WS)) == NULL || cp == NULL)
132a53d1a28Sjakob goto parse_error;
133a53d1a28Sjakob
134a53d1a28Sjakob cp += strspn(cp, WS);
135a53d1a28Sjakob
136a53d1a28Sjakob if ((to = strsep(&cp, WS)) == NULL)
137a53d1a28Sjakob goto parse_error;
138a53d1a28Sjakob
139366cf49cSmillert if (strcmp(from, progname) == 0) {
140a53d1a28Sjakob for (ap = strsep(&cp, WS); ap != NULL;
141a53d1a28Sjakob ap = strsep(&cp, WS))
142a53d1a28Sjakob if (*ap)
1433a1ce664Sjung addarg(&al, ap);
144a53d1a28Sjakob break;
145a53d1a28Sjakob }
146a53d1a28Sjakob
147a53d1a28Sjakob free(line);
148a53d1a28Sjakob }
149a53d1a28Sjakob
150a53d1a28Sjakob (void)fclose(config);
151a53d1a28Sjakob
1523a1ce664Sjung addarg(&al, NULL);
1534ddf7c6bSimp
154*3882aa95Santon execv(to, al.argv);
1550731caacSmillert err(1, "cannot exec %s", to);
156a53d1a28Sjakob /*NOTREACHED*/
157a53d1a28Sjakob parse_error:
1580f09aad0Sderaadt errx(1, "parse error in %s at line %lu",
159a53d1a28Sjakob _PATH_MAILERCONF, (u_long)lineno);
160a53d1a28Sjakob /*NOTREACHED*/
161a53d1a28Sjakob }
162