1 #include <stdio.h>
2 #include <ctype.h>
3 #include <sysexits.h>
4 #include <paths.h>
5 
6 #define TRUE		1
7 #define FALSE		0
8 typedef char		BOOL;
9 
10 #define CHARNULL	((char *) NULL)
11 #define MAXMAILOPTS	20
12 
13 enum copymode {RETAIN, DISCARD};
14 char *myname;
15 
16 main(argc, argv)
17 	int argc;
18 	char **argv;
19 {
20 	BOOL seen_precedence;
21 	register FILE *mailfp;
22 	enum copymode mode;
23 	register char *p;
24 	char *ml_name;
25 	char *ml_owner;
26 	char *mailer_opts[MAXMAILOPTS+1];
27 	char **next_opt = mailer_opts;
28 	char c;
29 	extern FILE *openmailer();
30 	extern char *readheadertag();
31 	extern void copyheader();
32 	extern void dropheader();
33 	extern void copybody();
34 
35 	myname = argv[0];
36 	argc--, argv++;
37 	while (*argv[0] == '-')
38 	{
39 		if (next_opt >= &mailer_opts[MAXMAILOPTS])
40 		{
41 			fprintf(stderr,
42 			    "%s: too many mailer options\n", myname);
43 			exit(EX_USAGE);
44 		}
45 		*next_opt++ = *argv++;
46 		argc--;
47 	}
48 	*next_opt = NULL;
49 
50 	/* parse arguments */
51 	if (argc < 3)
52 	{
53 		fprintf(stderr,
54 		    "Usage: %s [-mailopts ...] listname ownername member...\n",
55 		    myname);
56 		exit(EX_USAGE);
57 	}
58 
59 	ml_name = *argv++;
60 	ml_owner = *argv++;
61 
62 	/* consume and discard leading "From_" line */
63 	while ((c = fgetc(stdin)) != EOF && c != '\n')
64 		continue;
65 
66 	/* open the connection to the mailer */
67 	mailfp = openmailer(ml_owner, mailer_opts, argv);
68 
69 	/* output the Resent-xxx: fields */
70 	fprintf(mailfp, "Resent-To:	%s\n", ml_name);
71 	fprintf(mailfp, "Resent-From:	%s\n", ml_owner);
72 	fprintf(mailfp, "Sender:	%s\n", ml_owner);
73 
74 	/*
75 	**  Consume header
76 	**
77 	**	Errors-To:	discard
78 	**	Precedence:	retain; mark that it has been seen
79 	**	Received:	discard
80 	**	Resent-*:	discard
81 	**	Return-Path:	discard
82 	**	Via:		discard
83 	**	X-Mailer:	discard
84 	**	others		retain
85 	*/
86 
87 	seen_precedence = FALSE;
88 
89 	while ((p = readheadertag(stdin)) != CHARNULL)
90 	{
91 		extern BOOL sameword();
92 
93 		mode = RETAIN;
94 		switch (p[0])
95 		{
96 		  case 'e':
97 		  case 'E':
98 			if (sameword(p, "errors-to", 10))
99 				mode = DISCARD;
100 			break;
101 
102 		  case 'p':
103 		  case 'P':
104 			if (sameword(p, "precedence", 11))
105 				seen_precedence = TRUE;
106 			break;
107 
108 		  case 'r':
109 		  case 'R':
110 			if (sameword(p, "return-path", 12) ||
111 #ifdef notyet
112 			    sameword(p, "received", 9) ||
113 #endif
114 			    sameword(p, "resent-", 7))
115 				mode = DISCARD;
116 			break;
117 
118 		  case 's':
119 		  case 'S':
120 			if sameword(p, "sender", 7))
121 				mode = DISCARD;
122 			break;
123 
124 		  case 'v':
125 		  case 'V':
126 			if (sameword(p, "via", 4))
127 				mode = DISCARD;
128 			break;
129 
130 		  case 'x':
131 		  case 'X':
132 			if (sameword(p, "x-mailer", 9))
133 				mode = DISCARD;
134 			break;
135 		}
136 
137 		switch (mode)
138 		{
139 		  case RETAIN:
140 			fprintf(mailfp, "%s", p);
141 			copyheader(stdin, mailfp);
142 			break;
143 
144 		  case DISCARD:
145 			dropheader(stdin);
146 			break;
147 		}
148 	}
149 
150 	/* if no precedence was given, make it bulk mail */
151 	if (!seen_precedence)
152 		fprintf(mailfp, "Precedence: bulk\n");
153 
154 	/* copy the body of the message */
155 	copybody(stdin, mailfp);
156 
157 	/* clean up the connection */
158 	exit (pclose(mailfp));
159 }
160 
161 
162 
163 /*
164 **  OPENMAILER -- open a connection to the mailer
165 */
166 
167 FILE *
168 openmailer(from, opt, argv)
169 	char *from;
170 	char **opt, **argv;
171 {
172 	register char *bp;
173 	register FILE *mailfp;
174 	char buf[10000];
175 	extern int strlen();
176 
177 	bp = buf;
178 	(void) sprintf(bp, "%s -f %s -oi", _PATH_SENDMAIL, from);
179 	bp += strlen(bp);
180 
181 	while (*opt != CHARNULL)
182 	{
183 		(void) sprintf(bp, " %s", *opt++);
184 		bp += strlen(bp);
185 		if (bp >= buf + sizeof(buf)) {
186 			fprintf(stderr, "%s: options list too long\n", myname);
187 			exit(EX_SOFTWARE);
188 		}
189 	}
190 	while (*argv != CHARNULL)
191 	{
192 		(void) sprintf(bp, " %s", *argv++);
193 		bp += strlen(bp);
194 		if (bp >= buf + sizeof(buf)) {
195 			fprintf(stderr, "%s: arg list too long\n", myname);
196 			exit(EX_SOFTWARE);
197 		}
198 	}
199 
200 	mailfp = popen(buf, "w");
201 	if (mailfp == NULL)
202 	{
203 		fprintf(stderr, "%s: Unable to popen %s\n", myname,
204 		   _PATH_SENDMAIL);
205 		exit(EX_OSFILE);
206 	}
207 
208 	return (mailfp);
209 }
210 
211 
212 
213 /*
214 **  DROPHEADER -- drop a single header field
215 */
216 
217 void
218 dropheader(infp)
219 	register FILE *infp;
220 {
221 	register int c;
222 
223 	while ((c = fgetc(infp)) != EOF)
224 	{
225 		if (c == '\n')
226 		{
227 			/* look at next character to check for continuation */
228 			c = fgetc(infp);
229 			if (c == ' ' || c == '\t')
230 				continue;
231 			if (c != EOF)
232 				ungetc(c, infp);
233 			break;
234 		}
235 	}
236 }
237 
238 
239 
240 /*
241 **  COPYHEADER -- copy a single header field
242 */
243 
244 void
245 copyheader(infp, outfp)
246 	register FILE *infp;
247 	register FILE *outfp;
248 {
249 	register int c;
250 
251 	while ((c = fgetc(infp)) != EOF)
252 	{
253 		(void) fputc(c, outfp);
254 		if (c == '\n')
255 		{
256 			/* look at next character to check for continuation */
257 			c = fgetc(infp);
258 			if (c == ' ' || c == '\t')
259 			{
260 				(void) fputc(c, outfp);
261 				continue;
262 			}
263 			if (c != EOF)
264 				ungetc(c, infp);
265 			break;
266 		}
267 	}
268 }
269 
270 
271 
272 /*
273 **  READHEADERTAG -- read and return the name of a header field
274 */
275 
276 #define MAXHDRTAG	60
277 
278 char *
279 readheadertag(infp)
280 	register FILE *infp;
281 {
282 	register int c;
283 	register char *bp;
284 	int i;
285 	static char buf[MAXHDRTAG + 1];
286 	extern char *strchr();
287 
288 	c = fgetc(infp);
289 	if (c == EOF)
290 		return (CHARNULL);
291 	if (c == '\n')
292 	{
293 		ungetc(c, infp);
294 		return (CHARNULL);
295 	}
296 
297 	bp = buf;
298 	i = sizeof buf;
299 	do
300 	{
301 		*bp++ = c;
302 		c = fgetc(infp);
303 	} while (--i > 0 && c != EOF && c != '\0' &&
304 		 strchr(" \t\n:", c) == CHARNULL);
305 	if (c != EOF)
306 		ungetc(c, infp);
307 	*bp++ = '\0';
308 	return (buf);
309 }
310 
311 
312 
313 /*
314 **  COPYBODY -- copy the body of a message
315 */
316 
317 void
318 copybody(infp, outfp)
319 	register FILE *infp;
320 	register FILE *outfp;
321 {
322 	register int c;
323 
324 	while ((c = fgetc(infp)) != EOF)
325 		fputc(c, outfp);
326 }
327 
328 
329 
330 /*
331 **  SAMEWORD -- return true if two words are identical.  The first
332 **		word is case insignificant; the second must be lower case.
333 */
334 
335 BOOL
336 sameword(test, pat, len)
337 	register char *test;
338 	register char *pat;
339 	int len;
340 {
341 	for (; --len >= 0; test++, pat++)
342 	{
343 		if (*test == *pat)
344 			continue;
345 		if (isupper(*test) && tolower(*test) == *pat)
346 			continue;
347 		return (FALSE);
348 	}
349 	return (TRUE);
350 }
351