xref: /netbsd-src/usr.sbin/mailwrapper/mailwrapper.c (revision 421949a31fb0942d3d87278998c2d7d432d8b3cb)
1*421949a3Ssevan /*	$NetBSD: mailwrapper.c,v 1.11 2018/01/23 21:06:25 sevan Exp $	*/
2180c29c3Sperry 
3180c29c3Sperry /*
4180c29c3Sperry  * Copyright (c) 1998
5180c29c3Sperry  * 	Perry E. Metzger.  All rights reserved.
6180c29c3Sperry  *
7180c29c3Sperry  * Redistribution and use in source and binary forms, with or without
8180c29c3Sperry  * modification, are permitted provided that the following conditions
9180c29c3Sperry  * are met:
10180c29c3Sperry  * 1. Redistributions of source code must retain the above copyright
11180c29c3Sperry  *    notice, this list of conditions and the following disclaimer.
12180c29c3Sperry  * 2. Redistributions in binary form must reproduce the above copyright
13180c29c3Sperry  *    notice, this list of conditions and the following disclaimer in the
14180c29c3Sperry  *    documentation and/or other materials provided with the distribution.
15180c29c3Sperry  * 3. All advertising materials mentioning features or use of this software
16180c29c3Sperry  *    must display the following acknowledgment:
17180c29c3Sperry  *	This product includes software developed for the NetBSD Project
18180c29c3Sperry  *	by Perry E. Metzger.
19180c29c3Sperry  * 4. The name of the author may not be used to endorse or promote products
20180c29c3Sperry  *    derived from this software without specific prior written permission.
21180c29c3Sperry  *
22180c29c3Sperry  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23180c29c3Sperry  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24180c29c3Sperry  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25180c29c3Sperry  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26180c29c3Sperry  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27180c29c3Sperry  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28180c29c3Sperry  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29180c29c3Sperry  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30180c29c3Sperry  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31180c29c3Sperry  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32180c29c3Sperry  */
33180c29c3Sperry 
34180c29c3Sperry #include <err.h>
35180c29c3Sperry #include <stdio.h>
36180c29c3Sperry #include <string.h>
370d7a8dcbSthorpej #include <stdlib.h>
38180c29c3Sperry #include <unistd.h>
39180c29c3Sperry 
40180c29c3Sperry #define _PATH_MAILERCONF	"/etc/mailer.conf"
41180c29c3Sperry 
42854002abSchristos struct arglist {
43854002abSchristos 	size_t argc, maxc;
4443e54b3aSlukem 	const char **argv;
45854002abSchristos };
46854002abSchristos 
47*421949a3Ssevan static void initarg(struct arglist *);
48*421949a3Ssevan static void addarg(struct arglist *, const char *, int);
49854002abSchristos 
50854002abSchristos static void
initarg(struct arglist * al)51*421949a3Ssevan initarg(struct arglist *al)
52854002abSchristos {
53854002abSchristos 	al->argc = 0;
54854002abSchristos 	al->maxc = 10;
55854002abSchristos 	if ((al->argv = malloc(al->maxc * sizeof(char *))) == NULL)
56b0d37030Smjl 		/*
57b0d37030Smjl 		 * This (using err("mailwrapper")) is intentional.
58b0d37030Smjl 		 * Mailwrapper plays ugly games with argv[0] and thus it
59b0d37030Smjl 		 * is often difficult for people to know that the error
60b0d37030Smjl 		 * isn't from "mailq" or "sendmail" but from mailwrapper
61b0d37030Smjl 		 * -- having mailwrapper add an indication that it was really
62b0d37030Smjl 		 * mailwrapper running was a requested feature.
63b0d37030Smjl 		 */
64b0d37030Smjl 		err(1, "mailwrapper");
65854002abSchristos }
66854002abSchristos 
67854002abSchristos static void
addarg(struct arglist * al,const char * arg,int copy)68*421949a3Ssevan addarg(struct arglist *al, const char *arg, int copy)
69854002abSchristos {
70854002abSchristos 	if (al->argc == al->maxc) {
71854002abSchristos 	    al->maxc <<= 1;
72854002abSchristos 	    if ((al->argv = realloc(al->argv,
73854002abSchristos 		al->maxc * sizeof(char *))) == NULL)
74b0d37030Smjl 		    err(1, "mailwrapper");
75854002abSchristos 	}
76854002abSchristos 	if (copy) {
77854002abSchristos 		if ((al->argv[al->argc++] = strdup(arg)) == NULL)
78b0d37030Smjl 			err(1, "mailwrapper:");
79854002abSchristos 	} else
8043e54b3aSlukem 		al->argv[al->argc++] = arg;
81854002abSchristos }
82854002abSchristos 
83180c29c3Sperry int
main(int argc,char * argv[],char * envp[])84*421949a3Ssevan main(int argc, char *argv[], char *envp[])
85180c29c3Sperry {
86180c29c3Sperry 	FILE *config;
87854002abSchristos 	char *line, *cp, *from, *to, *ap;
880d7a8dcbSthorpej 	size_t len, lineno = 0;
89ca86df3fSis 	int i;
90854002abSchristos 	struct arglist al;
91854002abSchristos 
92854002abSchristos 	initarg(&al);
93ca86df3fSis 	addarg(&al, argv[0], 0);
94180c29c3Sperry 
95180c29c3Sperry 	if ((config = fopen(_PATH_MAILERCONF, "r")) == NULL)
96b0d37030Smjl 		err(1, "mailwrapper: can't open %s", _PATH_MAILERCONF);
97180c29c3Sperry 
980d7a8dcbSthorpej 	for (;;) {
990d7a8dcbSthorpej 		if ((line = fparseln(config, &len, &lineno, NULL, 0)) == NULL) {
1000d7a8dcbSthorpej 			if (feof(config))
101b0d37030Smjl 				errx(1, "mailwrapper: no mapping in %s",
102b0d37030Smjl 				    _PATH_MAILERCONF);
103b0d37030Smjl 			err(1, "mailwrapper");
1040d7a8dcbSthorpej 		}
105180c29c3Sperry 
106854002abSchristos #define	WS	" \t\n"
1070d7a8dcbSthorpej 		cp = line;
108180c29c3Sperry 
109854002abSchristos 		cp += strspn(cp, WS);
1100d7a8dcbSthorpej 		if (cp[0] == '\0') {
1110d7a8dcbSthorpej 			/* empty line */
1120d7a8dcbSthorpej 			free(line);
113180c29c3Sperry 			continue;
1140d7a8dcbSthorpej 		}
115180c29c3Sperry 
116854002abSchristos 		if ((from = strsep(&cp, WS)) == NULL)
117854002abSchristos 			goto parse_error;
118180c29c3Sperry 
119854002abSchristos 		cp += strspn(cp, WS);
1200d7a8dcbSthorpej 
121854002abSchristos 		if ((to = strsep(&cp, WS)) == NULL)
122854002abSchristos 			goto parse_error;
1230d7a8dcbSthorpej 
12425bdbb66Scgd 		if (strcmp(from, getprogname()) == 0) {
125854002abSchristos 			for (ap = strsep(&cp, WS); ap != NULL;
126854002abSchristos 			    ap = strsep(&cp, WS))
127854002abSchristos 			    if (*ap)
128854002abSchristos 				    addarg(&al, ap, 0);
129180c29c3Sperry 			break;
130854002abSchristos 		}
1310d7a8dcbSthorpej 
1320d7a8dcbSthorpej 		free(line);
133180c29c3Sperry 	}
134180c29c3Sperry 
135854002abSchristos 	(void)fclose(config);
136180c29c3Sperry 
137ca86df3fSis 	for (i = 1; i < argc; i++)
138ca86df3fSis 		addarg(&al, argv[i], 0);
139ca86df3fSis 
140c1fd8f00Smsaitoh 	addarg(&al, NULL, 0);
14143e54b3aSlukem 	execve(to, __UNCONST(al.argv), envp);
142b0d37030Smjl 	err(1, "mailwrapper: execing %s", to);
143854002abSchristos 	/*NOTREACHED*/
144854002abSchristos parse_error:
145b0d37030Smjl 	errx(1, "mailwrapper: parse error in %s at line %lu",
146854002abSchristos 	    _PATH_MAILERCONF, (u_long)lineno);
147854002abSchristos 	/*NOTREACHED*/
148180c29c3Sperry }
149