1205938Sdelphij/*	$OpenBSD: mailwrapper.c,v 1.18 2007/11/06 14:39:19 otto Exp $	*/
2161038Sdelphij/*	$NetBSD: mailwrapper.c,v 1.9 2003/03/09 08:10:43 mjl Exp $	*/
354816Speter
454816Speter/*
554816Speter * Copyright (c) 1998
654816Speter * 	Perry E. Metzger.  All rights reserved.
754816Speter *
854816Speter * Redistribution and use in source and binary forms, with or without
954816Speter * modification, are permitted provided that the following conditions
1054816Speter * are met:
1154816Speter * 1. Redistributions of source code must retain the above copyright
1254816Speter *    notice, this list of conditions and the following disclaimer.
1354816Speter * 2. Redistributions in binary form must reproduce the above copyright
1454816Speter *    notice, this list of conditions and the following disclaimer in the
1554816Speter *    documentation and/or other materials provided with the distribution.
1654816Speter * 3. All advertising materials mentioning features or use of this software
1754816Speter *    must display the following acknowledgment:
1854816Speter *	This product includes software developed for the NetBSD Project
1954816Speter *	by Perry E. Metzger.
2054816Speter * 4. The name of the author may not be used to endorse or promote products
2154816Speter *    derived from this software without specific prior written permission.
2254816Speter *
2354816Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2454816Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2554816Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2654816Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2754816Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2854816Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2954816Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3054816Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3154816Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3254816Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3354816Speter */
3454816Speter
35117280Scharnier#include <sys/cdefs.h>
36117280Scharnier__FBSDID("$FreeBSD$");
37117280Scharnier
38293242Sbdrewery#include <sys/param.h>
39293242Sbdrewery
4054816Speter#include <err.h>
4154816Speter#include <stdio.h>
4254816Speter#include <string.h>
43159326Sdelphij#include <unistd.h>
4454816Speter#include <stdlib.h>
4555228Speter#include <libutil.h>
46159326Sdelphij#include <sysexits.h>
4755705Simp#include <syslog.h>
4854816Speter
4955228Speter#include "pathnames.h"
5054816Speter
5154816Speterstruct arglist {
5254816Speter	size_t argc, maxc;
5354816Speter	char **argv;
5454816Speter};
5554816Speter
5699800Salfredint main(int, char *[], char *[]);
5754816Speter
5899800Salfredstatic void initarg(struct arglist *);
59159326Sdelphijstatic void addarg(struct arglist *, const char *);
6054816Speter
6154816Speterstatic void
62159326Sdelphijinitarg(struct arglist *al)
6354816Speter{
6454816Speter	al->argc = 0;
6554816Speter	al->maxc = 10;
66205938Sdelphij	if ((al->argv = calloc(al->maxc, sizeof(char *))) == NULL)
67205938Sdelphij		err(EX_TEMPFAIL, "calloc");
6854816Speter}
6954816Speter
7054816Speterstatic void
71159326Sdelphijaddarg(struct arglist *al, const char *arg)
7254816Speter{
7355705Simp
7454816Speter	if (al->argc == al->maxc) {
7555705Simp		al->maxc <<= 1;
76159326Sdelphij		al->argv = realloc(al->argv, al->maxc * sizeof(char *));
77159326Sdelphij		if (al->argv == NULL)
78159326Sdelphij			err(EX_TEMPFAIL, "realloc");
7954816Speter	}
80159326Sdelphij	if (arg == NULL)
81159326Sdelphij		al->argv[al->argc++] = NULL;
82159326Sdelphij	else if ((al->argv[al->argc++] = strdup(arg)) == NULL)
83159326Sdelphij		err(EX_TEMPFAIL, "strdup");
8454816Speter}
8554816Speter
8654816Speterint
87159326Sdelphijmain(int argc, char *argv[], char *envp[])
8854816Speter{
8954816Speter	FILE *config;
9054816Speter	char *line, *cp, *from, *to, *ap;
91159326Sdelphij	const char *progname;
92293242Sbdrewery	char localmailerconf[MAXPATHLEN];
93293242Sbdrewery	const char *mailerconf;
9454816Speter	size_t len, lineno = 0;
95159326Sdelphij	int i;
9654816Speter	struct arglist al;
9754816Speter
98159326Sdelphij	/* change __progname to mailwrapper so we get sensible error messages */
99159326Sdelphij	progname = getprogname();
100159326Sdelphij	setprogname("mailwrapper");
101159326Sdelphij
10254816Speter	initarg(&al);
103159326Sdelphij	addarg(&al, argv[0]);
10454816Speter
105293242Sbdrewery	snprintf(localmailerconf, MAXPATHLEN, "%s/etc/mail/mailer.conf",
106293242Sbdrewery	    getenv("LOCALBASE") ? getenv("LOCALBASE") : "/usr/local");
107293242Sbdrewery
108293242Sbdrewery	mailerconf = localmailerconf;
109293242Sbdrewery	if ((config = fopen(localmailerconf, "r")) == NULL)
110293242Sbdrewery		mailerconf = _PATH_MAILERCONF;
111293242Sbdrewery
112293242Sbdrewery	if (config == NULL && ((config = fopen(mailerconf, "r")) == NULL)) {
113159326Sdelphij		addarg(&al, NULL);
114159326Sdelphij		openlog(getprogname(), LOG_PID, LOG_MAIL);
115159326Sdelphij		syslog(LOG_INFO, "cannot open %s, using %s as default MTA",
116293242Sbdrewery		    mailerconf, _PATH_DEFAULTMTA);
11755705Simp		closelog();
11855705Simp		execve(_PATH_DEFAULTMTA, al.argv, envp);
119159326Sdelphij		err(EX_OSERR, "cannot exec %s", _PATH_DEFAULTMTA);
12055705Simp		/*NOTREACHED*/
12155705Simp	}
12254816Speter
12354816Speter	for (;;) {
12454816Speter		if ((line = fparseln(config, &len, &lineno, NULL, 0)) == NULL) {
12554816Speter			if (feof(config))
126293242Sbdrewery				errx(EX_CONFIG, "no mapping in %s", mailerconf);
127159326Sdelphij			err(EX_CONFIG, "cannot parse line %lu", (u_long)lineno);
12854816Speter		}
12954816Speter
13054816Speter#define	WS	" \t\n"
13154816Speter		cp = line;
13254816Speter
13354816Speter		cp += strspn(cp, WS);
13454816Speter		if (cp[0] == '\0') {
13554816Speter			/* empty line */
13654816Speter			free(line);
13754816Speter			continue;
13854816Speter		}
13954816Speter
140205938Sdelphij		if ((from = strsep(&cp, WS)) == NULL || cp == NULL)
14154816Speter			goto parse_error;
14254816Speter
14354816Speter		cp += strspn(cp, WS);
14454816Speter
14554816Speter		if ((to = strsep(&cp, WS)) == NULL)
14654816Speter			goto parse_error;
14754816Speter
148159326Sdelphij		if (strcmp(from, progname) == 0) {
149159326Sdelphij			for (ap = strsep(&cp, WS); ap != NULL;
150159326Sdelphij			     ap = strsep(&cp, WS)) {
151159326Sdelphij				if (*ap)
152159326Sdelphij				    addarg(&al, ap);
153159326Sdelphij			}
15454816Speter			break;
15554816Speter		}
15654816Speter
15754816Speter		free(line);
15854816Speter	}
15954816Speter
16054816Speter	(void)fclose(config);
16154816Speter
162159326Sdelphij	for (i = 1; i < argc; i++)
163159326Sdelphij		addarg(&al, argv[i]);
164159326Sdelphij
165159326Sdelphij	addarg(&al, NULL);
16654816Speter	execve(to, al.argv, envp);
167159326Sdelphij	err(EX_OSERR, "cannot exec %s", to);
16854816Speter	/*NOTREACHED*/
16954816Speterparse_error:
170159326Sdelphij	errx(EX_CONFIG, "parse error in %s at line %lu",
171293242Sbdrewery	    mailerconf, (u_long)lineno);
17254816Speter	/*NOTREACHED*/
17354816Speter}
174