xref: /freebsd/usr.sbin/mailwrapper/mailwrapper.c (revision d89167b4ea3fc14eaa1fb11a9d08b3381653f36e)
1ff4d7851SWarner Losh /*	$OpenBSD: mailwrapper.c,v 1.6 1999/12/17 05:06:28 mickey Exp $	*/
23ae92913SPeter Wemm /*	$NetBSD: mailwrapper.c,v 1.3 1999/05/29 18:18:15 christos Exp $	*/
3521cb9d2SPeter Wemm /* $FreeBSD$ */
43ae92913SPeter Wemm 
53ae92913SPeter Wemm /*
63ae92913SPeter Wemm  * Copyright (c) 1998
73ae92913SPeter Wemm  * 	Perry E. Metzger.  All rights reserved.
83ae92913SPeter Wemm  *
93ae92913SPeter Wemm  * Redistribution and use in source and binary forms, with or without
103ae92913SPeter Wemm  * modification, are permitted provided that the following conditions
113ae92913SPeter Wemm  * are met:
123ae92913SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
133ae92913SPeter Wemm  *    notice, this list of conditions and the following disclaimer.
143ae92913SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
153ae92913SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
163ae92913SPeter Wemm  *    documentation and/or other materials provided with the distribution.
173ae92913SPeter Wemm  * 3. All advertising materials mentioning features or use of this software
183ae92913SPeter Wemm  *    must display the following acknowledgment:
193ae92913SPeter Wemm  *	This product includes software developed for the NetBSD Project
203ae92913SPeter Wemm  *	by Perry E. Metzger.
213ae92913SPeter Wemm  * 4. The name of the author may not be used to endorse or promote products
223ae92913SPeter Wemm  *    derived from this software without specific prior written permission.
233ae92913SPeter Wemm  *
243ae92913SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
253ae92913SPeter Wemm  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
263ae92913SPeter Wemm  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
273ae92913SPeter Wemm  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
283ae92913SPeter Wemm  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
293ae92913SPeter Wemm  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
303ae92913SPeter Wemm  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
313ae92913SPeter Wemm  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
323ae92913SPeter Wemm  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
333ae92913SPeter Wemm  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
343ae92913SPeter Wemm  */
353ae92913SPeter Wemm 
363ae92913SPeter Wemm #include <err.h>
373ae92913SPeter Wemm #include <stdio.h>
383ae92913SPeter Wemm #include <string.h>
393ae92913SPeter Wemm #include <stdlib.h>
403ae92913SPeter Wemm #include <unistd.h>
41521cb9d2SPeter Wemm #include <libutil.h>
42ff4d7851SWarner Losh #include <syslog.h>
43ff4d7851SWarner Losh #include <stdarg.h>
443ae92913SPeter Wemm 
45521cb9d2SPeter Wemm #include "pathnames.h"
463ae92913SPeter Wemm 
473ae92913SPeter Wemm struct arglist {
483ae92913SPeter Wemm 	size_t argc, maxc;
493ae92913SPeter Wemm 	char **argv;
503ae92913SPeter Wemm };
513ae92913SPeter Wemm 
52d89167b4SAlfred Perlstein int main(int, char *[], char *[]);
533ae92913SPeter Wemm 
54d89167b4SAlfred Perlstein static void initarg(struct arglist *);
55d89167b4SAlfred Perlstein static void addarg(struct arglist *, const char *, int);
56d89167b4SAlfred Perlstein static void freearg(struct arglist *, int);
573ae92913SPeter Wemm 
583ae92913SPeter Wemm extern const char *__progname;	/* from crt0.o */
593ae92913SPeter Wemm 
603ae92913SPeter Wemm static void
613ae92913SPeter Wemm initarg(al)
623ae92913SPeter Wemm 	struct arglist *al;
633ae92913SPeter Wemm {
643ae92913SPeter Wemm 	al->argc = 0;
653ae92913SPeter Wemm 	al->maxc = 10;
663ae92913SPeter Wemm 	if ((al->argv = malloc(al->maxc * sizeof(char *))) == NULL)
6739e80db3SPhilippe Charnier 		err(1, NULL);
683ae92913SPeter Wemm }
693ae92913SPeter Wemm 
703ae92913SPeter Wemm static void
713ae92913SPeter Wemm addarg(al, arg, copy)
723ae92913SPeter Wemm 	struct arglist *al;
733ae92913SPeter Wemm 	const char *arg;
743ae92913SPeter Wemm 	int copy;
753ae92913SPeter Wemm {
76ff4d7851SWarner Losh 	char **argv2;
77ff4d7851SWarner Losh 
783ae92913SPeter Wemm 	if (al->argc == al->maxc) {
793ae92913SPeter Wemm 		al->maxc <<= 1;
80ff4d7851SWarner Losh 
81ff4d7851SWarner Losh 		if ((argv2 = realloc(al->argv,
82ff4d7851SWarner Losh 		    al->maxc * sizeof(char *))) == NULL) {
83ff4d7851SWarner Losh 			if (al->argv)
84ff4d7851SWarner Losh 				free(al->argv);
85ff4d7851SWarner Losh 			al->argv = NULL;
8639e80db3SPhilippe Charnier 			err(1, NULL);
87ff4d7851SWarner Losh 		} else {
88ff4d7851SWarner Losh 			al->argv = argv2;
89ff4d7851SWarner Losh 		}
903ae92913SPeter Wemm 	}
913ae92913SPeter Wemm 	if (copy) {
923ae92913SPeter Wemm 		if ((al->argv[al->argc++] = strdup(arg)) == NULL)
9339e80db3SPhilippe Charnier 			err(1, NULL);
943ae92913SPeter Wemm 	} else
953ae92913SPeter Wemm 		al->argv[al->argc++] = (char *)arg;
963ae92913SPeter Wemm }
973ae92913SPeter Wemm 
983ae92913SPeter Wemm static void
993ae92913SPeter Wemm freearg(al, copy)
1003ae92913SPeter Wemm 	struct arglist *al;
1013ae92913SPeter Wemm 	int copy;
1023ae92913SPeter Wemm {
1033ae92913SPeter Wemm 	size_t i;
1043ae92913SPeter Wemm 	if (copy)
1053ae92913SPeter Wemm 		for (i = 0; i < al->argc; i++)
1063ae92913SPeter Wemm 			free(al->argv[i]);
1073ae92913SPeter Wemm 	free(al->argv);
1083ae92913SPeter Wemm }
1093ae92913SPeter Wemm 
1103ae92913SPeter Wemm int
1113ae92913SPeter Wemm main(argc, argv, envp)
1123ae92913SPeter Wemm 	int argc;
1133ae92913SPeter Wemm 	char *argv[];
1143ae92913SPeter Wemm 	char *envp[];
1153ae92913SPeter Wemm {
1163ae92913SPeter Wemm 	FILE *config;
1173ae92913SPeter Wemm 	char *line, *cp, *from, *to, *ap;
1183ae92913SPeter Wemm 	size_t len, lineno = 0;
1193ae92913SPeter Wemm 	struct arglist al;
1203ae92913SPeter Wemm 
1213ae92913SPeter Wemm 	initarg(&al);
1223ae92913SPeter Wemm 	for (len = 0; len < argc; len++)
1233ae92913SPeter Wemm 		addarg(&al, argv[len], 0);
1243ae92913SPeter Wemm 
125ff4d7851SWarner Losh 	if ((config = fopen(_PATH_MAILERCONF, "r")) == NULL) {
126ff4d7851SWarner Losh 		addarg(&al, NULL, 0);
127ff4d7851SWarner Losh 		openlog("mailwrapper", LOG_PID, LOG_MAIL);
128ff4d7851SWarner Losh 		syslog(LOG_INFO, "can't open %s, using %s as default MTA",
129ff4d7851SWarner Losh 		    _PATH_MAILERCONF, _PATH_DEFAULTMTA);
130ff4d7851SWarner Losh 		closelog();
131ff4d7851SWarner Losh 		execve(_PATH_DEFAULTMTA, al.argv, envp);
132ff4d7851SWarner Losh 		freearg(&al, 0);
13339e80db3SPhilippe Charnier 		err(1, "execing %s", _PATH_DEFAULTMTA);
134ff4d7851SWarner Losh 		/*NOTREACHED*/
135ff4d7851SWarner Losh 	}
1363ae92913SPeter Wemm 
1373ae92913SPeter Wemm 	for (;;) {
1383ae92913SPeter Wemm 		if ((line = fparseln(config, &len, &lineno, NULL, 0)) == NULL) {
1393ae92913SPeter Wemm 			if (feof(config))
14039e80db3SPhilippe Charnier 				errx(1, "no mapping in %s", _PATH_MAILERCONF);
14139e80db3SPhilippe Charnier 			err(1, "can't parse line %lu", (u_long)lineno);
1423ae92913SPeter Wemm 		}
1433ae92913SPeter Wemm 
1443ae92913SPeter Wemm #define	WS	" \t\n"
1453ae92913SPeter Wemm 		cp = line;
1463ae92913SPeter Wemm 
1473ae92913SPeter Wemm 		cp += strspn(cp, WS);
1483ae92913SPeter Wemm 		if (cp[0] == '\0') {
1493ae92913SPeter Wemm 			/* empty line */
1503ae92913SPeter Wemm 			free(line);
1513ae92913SPeter Wemm 			continue;
1523ae92913SPeter Wemm 		}
1533ae92913SPeter Wemm 
1543ae92913SPeter Wemm 		if ((from = strsep(&cp, WS)) == NULL)
1553ae92913SPeter Wemm 			goto parse_error;
1563ae92913SPeter Wemm 
1573ae92913SPeter Wemm 		cp += strspn(cp, WS);
1583ae92913SPeter Wemm 
1593ae92913SPeter Wemm 		if ((to = strsep(&cp, WS)) == NULL)
1603ae92913SPeter Wemm 			goto parse_error;
1613ae92913SPeter Wemm 
1623ae92913SPeter Wemm 		if (strcmp(from, __progname) == 0) {
1633ae92913SPeter Wemm 			for (ap = strsep(&cp, WS); ap != NULL;
1643ae92913SPeter Wemm 			    ap = strsep(&cp, WS))
1653ae92913SPeter Wemm 			    if (*ap)
1663ae92913SPeter Wemm 				    addarg(&al, ap, 0);
1673ae92913SPeter Wemm 			break;
1683ae92913SPeter Wemm 		}
1693ae92913SPeter Wemm 
1703ae92913SPeter Wemm 		free(line);
1713ae92913SPeter Wemm 	}
1723ae92913SPeter Wemm 
1733ae92913SPeter Wemm 	(void)fclose(config);
1743ae92913SPeter Wemm 
175ff4d7851SWarner Losh 	addarg(&al, NULL, 0);
1763ae92913SPeter Wemm 	execve(to, al.argv, envp);
1773ae92913SPeter Wemm 	freearg(&al, 0);
17857b6c4a5SPaul Richards 	warn("execing %s", to);
1793ae92913SPeter Wemm 	free(line);
18057b6c4a5SPaul Richards 	exit(1);
1813ae92913SPeter Wemm 	/*NOTREACHED*/
1823ae92913SPeter Wemm parse_error:
1833ae92913SPeter Wemm 	freearg(&al, 0);
1843ae92913SPeter Wemm 	free(line);
18539e80db3SPhilippe Charnier 	errx(1, "parse error in %s at line %lu",
1863ae92913SPeter Wemm 	    _PATH_MAILERCONF, (u_long)lineno);
1873ae92913SPeter Wemm 	/*NOTREACHED*/
1883ae92913SPeter Wemm }
189