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