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
3854816Speter#include <err.h>
3954816Speter#include <stdio.h>
4054816Speter#include <string.h>
41159326Sdelphij#include <unistd.h>
4254816Speter#include <stdlib.h>
4355228Speter#include <libutil.h>
44159326Sdelphij#include <sysexits.h>
4555705Simp#include <syslog.h>
4654816Speter
4755228Speter#include "pathnames.h"
4854816Speter
4954816Speterstruct arglist {
5054816Speter	size_t argc, maxc;
5154816Speter	char **argv;
5254816Speter};
5354816Speter
5499800Salfredint main(int, char *[], char *[]);
5554816Speter
5699800Salfredstatic void initarg(struct arglist *);
57159326Sdelphijstatic void addarg(struct arglist *, const char *);
5854816Speter
5954816Speterstatic void
60159326Sdelphijinitarg(struct arglist *al)
6154816Speter{
6254816Speter	al->argc = 0;
6354816Speter	al->maxc = 10;
64205938Sdelphij	if ((al->argv = calloc(al->maxc, sizeof(char *))) == NULL)
65205938Sdelphij		err(EX_TEMPFAIL, "calloc");
6654816Speter}
6754816Speter
6854816Speterstatic void
69159326Sdelphijaddarg(struct arglist *al, const char *arg)
7054816Speter{
7155705Simp
7254816Speter	if (al->argc == al->maxc) {
7355705Simp		al->maxc <<= 1;
74159326Sdelphij		al->argv = realloc(al->argv, al->maxc * sizeof(char *));
75159326Sdelphij		if (al->argv == NULL)
76159326Sdelphij			err(EX_TEMPFAIL, "realloc");
7754816Speter	}
78159326Sdelphij	if (arg == NULL)
79159326Sdelphij		al->argv[al->argc++] = NULL;
80159326Sdelphij	else if ((al->argv[al->argc++] = strdup(arg)) == NULL)
81159326Sdelphij		err(EX_TEMPFAIL, "strdup");
8254816Speter}
8354816Speter
8454816Speterint
85159326Sdelphijmain(int argc, char *argv[], char *envp[])
8654816Speter{
8754816Speter	FILE *config;
8854816Speter	char *line, *cp, *from, *to, *ap;
89159326Sdelphij	const char *progname;
9054816Speter	size_t len, lineno = 0;
91159326Sdelphij	int i;
9254816Speter	struct arglist al;
9354816Speter
94159326Sdelphij	/* change __progname to mailwrapper so we get sensible error messages */
95159326Sdelphij	progname = getprogname();
96159326Sdelphij	setprogname("mailwrapper");
97159326Sdelphij
9854816Speter	initarg(&al);
99159326Sdelphij	addarg(&al, argv[0]);
10054816Speter
10155705Simp	if ((config = fopen(_PATH_MAILERCONF, "r")) == NULL) {
102159326Sdelphij		addarg(&al, NULL);
103159326Sdelphij		openlog(getprogname(), LOG_PID, LOG_MAIL);
104159326Sdelphij		syslog(LOG_INFO, "cannot open %s, using %s as default MTA",
10555705Simp		    _PATH_MAILERCONF, _PATH_DEFAULTMTA);
10655705Simp		closelog();
10755705Simp		execve(_PATH_DEFAULTMTA, al.argv, envp);
108159326Sdelphij		err(EX_OSERR, "cannot exec %s", _PATH_DEFAULTMTA);
10955705Simp		/*NOTREACHED*/
11055705Simp	}
11154816Speter
11254816Speter	for (;;) {
11354816Speter		if ((line = fparseln(config, &len, &lineno, NULL, 0)) == NULL) {
11454816Speter			if (feof(config))
115159326Sdelphij				errx(EX_CONFIG, "no mapping in %s", _PATH_MAILERCONF);
116159326Sdelphij			err(EX_CONFIG, "cannot parse line %lu", (u_long)lineno);
11754816Speter		}
11854816Speter
11954816Speter#define	WS	" \t\n"
12054816Speter		cp = line;
12154816Speter
12254816Speter		cp += strspn(cp, WS);
12354816Speter		if (cp[0] == '\0') {
12454816Speter			/* empty line */
12554816Speter			free(line);
12654816Speter			continue;
12754816Speter		}
12854816Speter
129205938Sdelphij		if ((from = strsep(&cp, WS)) == NULL || cp == NULL)
13054816Speter			goto parse_error;
13154816Speter
13254816Speter		cp += strspn(cp, WS);
13354816Speter
13454816Speter		if ((to = strsep(&cp, WS)) == NULL)
13554816Speter			goto parse_error;
13654816Speter
137159326Sdelphij		if (strcmp(from, progname) == 0) {
138159326Sdelphij			for (ap = strsep(&cp, WS); ap != NULL;
139159326Sdelphij			     ap = strsep(&cp, WS)) {
140159326Sdelphij				if (*ap)
141159326Sdelphij				    addarg(&al, ap);
142159326Sdelphij			}
14354816Speter			break;
14454816Speter		}
14554816Speter
14654816Speter		free(line);
14754816Speter	}
14854816Speter
14954816Speter	(void)fclose(config);
15054816Speter
151159326Sdelphij	for (i = 1; i < argc; i++)
152159326Sdelphij		addarg(&al, argv[i]);
153159326Sdelphij
154159326Sdelphij	addarg(&al, NULL);
15554816Speter	execve(to, al.argv, envp);
156159326Sdelphij	err(EX_OSERR, "cannot exec %s", to);
15754816Speter	/*NOTREACHED*/
15854816Speterparse_error:
159159326Sdelphij	errx(EX_CONFIG, "parse error in %s at line %lu",
16054816Speter	    _PATH_MAILERCONF, (u_long)lineno);
16154816Speter	/*NOTREACHED*/
16254816Speter}
163