1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3*0Sstevel@tonic-gate  * Use is subject to license terms.
4*0Sstevel@tonic-gate  *
5*0Sstevel@tonic-gate  *	Copyright (c) 1983, 1984, 1986, 1986, 1987, 1988, 1989 AT&T
6*0Sstevel@tonic-gate  *	  All Rights Reserved
7*0Sstevel@tonic-gate  */
8*0Sstevel@tonic-gate 
9*0Sstevel@tonic-gate /*
10*0Sstevel@tonic-gate  *  Vacation
11*0Sstevel@tonic-gate  *  Copyright (c) 1983  Eric P. Allman
12*0Sstevel@tonic-gate  *  Berkeley, California
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  *  Copyright (c) 1983 Regents of the University of California.
15*0Sstevel@tonic-gate  *  All rights reserved.  The Berkeley software License Agreement
16*0Sstevel@tonic-gate  *  specifies the terms and conditions for redistribution.
17*0Sstevel@tonic-gate  */
18*0Sstevel@tonic-gate 
19*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
20*0Sstevel@tonic-gate 
21*0Sstevel@tonic-gate #include <pwd.h>
22*0Sstevel@tonic-gate #include <stdio.h>
23*0Sstevel@tonic-gate #include <stdarg.h>
24*0Sstevel@tonic-gate #include <stdlib.h>
25*0Sstevel@tonic-gate #include <unistd.h>
26*0Sstevel@tonic-gate #include <sysexits.h>
27*0Sstevel@tonic-gate #include <string.h>
28*0Sstevel@tonic-gate #include <ctype.h>
29*0Sstevel@tonic-gate #include "conf.h"
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate /*
32*0Sstevel@tonic-gate  *  MAILCOMPAT -- Deliver mail to a user's mailbox with the "From's" stuffed.
33*0Sstevel@tonic-gate  */
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate typedef int bool;
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #define	FALSE	0
38*0Sstevel@tonic-gate #define	TRUE	1
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate bool	Debug = FALSE;
41*0Sstevel@tonic-gate char	*myname;		/* person who is to have their mail filtered */
42*0Sstevel@tonic-gate char	*homedir;		/* home directory of said person */
43*0Sstevel@tonic-gate char	*AliasList[MAXLINE];	/* list of aliases to allow */
44*0Sstevel@tonic-gate char    *fromp;
45*0Sstevel@tonic-gate char    *fromuser;
46*0Sstevel@tonic-gate int	AliasCount = 0;
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate static char *newstr();
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate int	ask(char *);
51*0Sstevel@tonic-gate int	sendmessage(char *);
52*0Sstevel@tonic-gate void	AutoInstall(void);
53*0Sstevel@tonic-gate void	usrerr(const char *, ...);
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate int
56*0Sstevel@tonic-gate main(argc, argv)
57*0Sstevel@tonic-gate 	int argc;
58*0Sstevel@tonic-gate 	char **argv;
59*0Sstevel@tonic-gate {
60*0Sstevel@tonic-gate 	register char *p;
61*0Sstevel@tonic-gate 	struct passwd *pw;
62*0Sstevel@tonic-gate 	extern char *getfrom();
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate 	/* process arguments */
65*0Sstevel@tonic-gate 	while (--argc > 0 && (p = *++argv) != NULL && *p == '-')
66*0Sstevel@tonic-gate 	{
67*0Sstevel@tonic-gate 		switch (*++p)
68*0Sstevel@tonic-gate 		{
69*0Sstevel@tonic-gate 		    case 'd':	/* debug */
70*0Sstevel@tonic-gate 			Debug = TRUE;
71*0Sstevel@tonic-gate 			break;
72*0Sstevel@tonic-gate 		    default:
73*0Sstevel@tonic-gate 			usrerr("Unknown flag -%s", p);
74*0Sstevel@tonic-gate 			exit(EX_USAGE);
75*0Sstevel@tonic-gate 		}
76*0Sstevel@tonic-gate 	}
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate 	/* verify recipient argument */
79*0Sstevel@tonic-gate 	if (argc != 1)
80*0Sstevel@tonic-gate 	{
81*0Sstevel@tonic-gate 		if (argc == 0)
82*0Sstevel@tonic-gate 			AutoInstall();
83*0Sstevel@tonic-gate 		else
84*0Sstevel@tonic-gate 			usrerr("Usage: mailcompat username (or) mailcompat -r");
85*0Sstevel@tonic-gate 		exit(EX_USAGE);
86*0Sstevel@tonic-gate 	}
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate 	myname = p;
89*0Sstevel@tonic-gate 	/* find user's home directory */
90*0Sstevel@tonic-gate 	pw = getpwnam(myname);
91*0Sstevel@tonic-gate 	if (pw == NULL)
92*0Sstevel@tonic-gate 	{
93*0Sstevel@tonic-gate 		usrerr("user: %s look up failed, name services outage ?", myname);
94*0Sstevel@tonic-gate 		exit(EX_TEMPFAIL);
95*0Sstevel@tonic-gate 	}
96*0Sstevel@tonic-gate 	homedir = newstr(pw->pw_dir);
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate 	/* read message from standard input (just from line) */
99*0Sstevel@tonic-gate 	fromuser = getfrom(&fromp);
100*0Sstevel@tonic-gate 	return (sendmessage(fromuser));
101*0Sstevel@tonic-gate }
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate /*
104*0Sstevel@tonic-gate **  sendmessage -- read message from standard input do the from stuffing
105*0Sstevel@tonic-gate **             and forward to /bin/mail, Being sure to delete any
106*0Sstevel@tonic-gate **             content-length headers (/bin/mail recalculates them).
107*0Sstevel@tonic-gate **
108*0Sstevel@tonic-gate **
109*0Sstevel@tonic-gate **	Parameters:
110*0Sstevel@tonic-gate **		none.
111*0Sstevel@tonic-gate **
112*0Sstevel@tonic-gate **
113*0Sstevel@tonic-gate **	Side Effects:
114*0Sstevel@tonic-gate **		Reads first line from standard input.
115*0Sstevel@tonic-gate */
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate #define	L_HEADER	"Content-Length:"
118*0Sstevel@tonic-gate #define	LL_HEADER	15
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate int
121*0Sstevel@tonic-gate sendmessage(from)
122*0Sstevel@tonic-gate char *from;
123*0Sstevel@tonic-gate {
124*0Sstevel@tonic-gate 	static char line[MAXLINE];
125*0Sstevel@tonic-gate 	static char command[MAXLINE];
126*0Sstevel@tonic-gate 	bool in_body = FALSE;
127*0Sstevel@tonic-gate 	FILE *mail_fp;
128*0Sstevel@tonic-gate 	static char user_name[L_cuserid];
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 	if (from == NULL)
131*0Sstevel@tonic-gate 		from = cuserid(user_name);
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 	snprintf(command, sizeof (command), "/bin/mail -f %s -d %s", from,
134*0Sstevel@tonic-gate 	    myname);
135*0Sstevel@tonic-gate 	mail_fp = popen(command, "w");
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 	/* read the  line */
138*0Sstevel@tonic-gate 	while (fgets(line, sizeof line, stdin) != NULL)
139*0Sstevel@tonic-gate 	{
140*0Sstevel@tonic-gate 		if (line[0] == (char)'\n')  /* end of mail headers */
141*0Sstevel@tonic-gate 			in_body = TRUE;
142*0Sstevel@tonic-gate 		if (in_body && (strncmp(line, "From ", 5) == 0))
143*0Sstevel@tonic-gate 			fprintf(mail_fp, ">");
144*0Sstevel@tonic-gate 		if (in_body || (strncasecmp(line, L_HEADER, LL_HEADER) != 0))
145*0Sstevel@tonic-gate 			fputs(line, mail_fp);
146*0Sstevel@tonic-gate 	}
147*0Sstevel@tonic-gate 	return (pclose(mail_fp));
148*0Sstevel@tonic-gate }
149*0Sstevel@tonic-gate 
150*0Sstevel@tonic-gate char *
151*0Sstevel@tonic-gate getfrom(shortp)
152*0Sstevel@tonic-gate char **shortp;
153*0Sstevel@tonic-gate {
154*0Sstevel@tonic-gate 	static char line[MAXLINE];
155*0Sstevel@tonic-gate 	register char *p, *start, *at, *bang;
156*0Sstevel@tonic-gate 	char saveat;
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate 	/* read the from line */
159*0Sstevel@tonic-gate 	if (fgets(line, sizeof line, stdin) == NULL ||
160*0Sstevel@tonic-gate 	    strncmp(line, "From ", 5) != NULL)
161*0Sstevel@tonic-gate 	{
162*0Sstevel@tonic-gate 		usrerr("No initial From line");
163*0Sstevel@tonic-gate 		exit(EX_USAGE);
164*0Sstevel@tonic-gate 	}
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 	/* find the end of the sender address and terminate it */
167*0Sstevel@tonic-gate 	start = &line[5];
168*0Sstevel@tonic-gate 	p = strchr(start, ' ');
169*0Sstevel@tonic-gate 	if (p == NULL)
170*0Sstevel@tonic-gate 	{
171*0Sstevel@tonic-gate 		usrerr("Funny From line '%s'", line);
172*0Sstevel@tonic-gate 		exit(EX_USAGE);
173*0Sstevel@tonic-gate 	}
174*0Sstevel@tonic-gate 	*p = '\0';
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 	/*
177*0Sstevel@tonic-gate 	 * Strip all but the rightmost UUCP host
178*0Sstevel@tonic-gate 	 * to prevent loops due to forwarding.
179*0Sstevel@tonic-gate 	 * Start searching leftward from the leftmost '@'.
180*0Sstevel@tonic-gate 	 *	a!b!c!d yields a short name of c!d
181*0Sstevel@tonic-gate 	 *	a!b!c!d@e yields a short name of c!d@e
182*0Sstevel@tonic-gate 	 *	e@a!b!c yields the same short name
183*0Sstevel@tonic-gate 	 */
184*0Sstevel@tonic-gate #ifdef VDEBUG
185*0Sstevel@tonic-gate printf("start='%s'\n", start);
186*0Sstevel@tonic-gate #endif /* VDEBUG */
187*0Sstevel@tonic-gate 	*shortp = start;			/* assume whole addr */
188*0Sstevel@tonic-gate 	if ((at = strchr(start, '@')) == NULL)	/* leftmost '@' */
189*0Sstevel@tonic-gate 		at = p;				/* if none, use end of addr */
190*0Sstevel@tonic-gate 	saveat = *at;
191*0Sstevel@tonic-gate 	*at = '\0';
192*0Sstevel@tonic-gate 	if ((bang = strrchr(start, '!')) != NULL) {	/* rightmost '!' */
193*0Sstevel@tonic-gate 		char *bang2;
194*0Sstevel@tonic-gate 		*bang = '\0';
195*0Sstevel@tonic-gate 		if ((bang2 = strrchr(start, '!')) != NULL) /* 2nd rightmost '!' */
196*0Sstevel@tonic-gate 			*shortp = bang2 + 1;		/* move past ! */
197*0Sstevel@tonic-gate 		*bang = '!';
198*0Sstevel@tonic-gate 	}
199*0Sstevel@tonic-gate 	*at = saveat;
200*0Sstevel@tonic-gate #ifdef VDEBUG
201*0Sstevel@tonic-gate printf("place='%s'\n", *shortp);
202*0Sstevel@tonic-gate #endif /* VDEBUG */
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate 	/* return the sender address */
205*0Sstevel@tonic-gate 	return newstr(start);
206*0Sstevel@tonic-gate }
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate /*
209*0Sstevel@tonic-gate **  USRERR -- print user error
210*0Sstevel@tonic-gate **
211*0Sstevel@tonic-gate **	Parameters:
212*0Sstevel@tonic-gate **		f -- format.
213*0Sstevel@tonic-gate **
214*0Sstevel@tonic-gate **	Returns:
215*0Sstevel@tonic-gate **		none.
216*0Sstevel@tonic-gate **
217*0Sstevel@tonic-gate **	Side Effects:
218*0Sstevel@tonic-gate **		none.
219*0Sstevel@tonic-gate */
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate void
222*0Sstevel@tonic-gate usrerr(const char *f, ...)
223*0Sstevel@tonic-gate {
224*0Sstevel@tonic-gate 	va_list alist;
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate 	va_start(alist, f);
227*0Sstevel@tonic-gate 	(void) fprintf(stderr, "mailcompat: ");
228*0Sstevel@tonic-gate 	(void) vfprintf(stderr, f, alist);
229*0Sstevel@tonic-gate 	(void) fprintf(stderr, "\n");
230*0Sstevel@tonic-gate 	va_end(alist);
231*0Sstevel@tonic-gate }
232*0Sstevel@tonic-gate 
233*0Sstevel@tonic-gate /*
234*0Sstevel@tonic-gate **  NEWSTR -- copy a string
235*0Sstevel@tonic-gate **
236*0Sstevel@tonic-gate **	Parameters:
237*0Sstevel@tonic-gate **		s -- the string to copy.
238*0Sstevel@tonic-gate **
239*0Sstevel@tonic-gate **	Returns:
240*0Sstevel@tonic-gate **		A copy of the string.
241*0Sstevel@tonic-gate **
242*0Sstevel@tonic-gate **	Side Effects:
243*0Sstevel@tonic-gate **		none.
244*0Sstevel@tonic-gate */
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate char *
247*0Sstevel@tonic-gate newstr(s)
248*0Sstevel@tonic-gate 	char *s;
249*0Sstevel@tonic-gate {
250*0Sstevel@tonic-gate 	char *p;
251*0Sstevel@tonic-gate 	size_t psize = strlen(s) + 1;
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 	p = malloc(psize);
254*0Sstevel@tonic-gate 	if (p == NULL)
255*0Sstevel@tonic-gate 	{
256*0Sstevel@tonic-gate 		usrerr("newstr: cannot alloc memory");
257*0Sstevel@tonic-gate 		exit(EX_OSERR);
258*0Sstevel@tonic-gate 	}
259*0Sstevel@tonic-gate 	strlcpy(p, s, psize);
260*0Sstevel@tonic-gate 	return (p);
261*0Sstevel@tonic-gate }
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate /*
264*0Sstevel@tonic-gate  * When invoked with no arguments, we fall into an automatic installation
265*0Sstevel@tonic-gate  * mode, stepping the user through a default installation.
266*0Sstevel@tonic-gate  */
267*0Sstevel@tonic-gate void
268*0Sstevel@tonic-gate AutoInstall()
269*0Sstevel@tonic-gate {
270*0Sstevel@tonic-gate 	char forward[MAXLINE];
271*0Sstevel@tonic-gate 	char line[MAXLINE];
272*0Sstevel@tonic-gate 	static char user_name[L_cuserid];
273*0Sstevel@tonic-gate 	FILE *f;
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate 	myname = cuserid(user_name);
276*0Sstevel@tonic-gate 	homedir = getenv("HOME");
277*0Sstevel@tonic-gate 	if (homedir == NULL) {
278*0Sstevel@tonic-gate 		usrerr("Home directory unknown");
279*0Sstevel@tonic-gate 		exit(EX_CONFIG);
280*0Sstevel@tonic-gate 	}
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	printf("This program can be used to store your mail in a format\n");
283*0Sstevel@tonic-gate 	printf("that you can read with SunOS 4.X based mail readers\n");
284*0Sstevel@tonic-gate 	(void) strlcpy(forward, homedir, sizeof (forward));
285*0Sstevel@tonic-gate 	(void) strlcat(forward, "/.forward", sizeof (forward));
286*0Sstevel@tonic-gate 	f = fopen(forward, "r");
287*0Sstevel@tonic-gate 	if (f) {
288*0Sstevel@tonic-gate 		printf("You have a .forward file in your home directory");
289*0Sstevel@tonic-gate 		printf("  containing:\n");
290*0Sstevel@tonic-gate 		while (fgets(line, MAXLINE, f))
291*0Sstevel@tonic-gate 			printf("    %s", line);
292*0Sstevel@tonic-gate 		fclose(f);
293*0Sstevel@tonic-gate 		if (!ask("Would you like to remove it and disable the mailcompat feature"))
294*0Sstevel@tonic-gate 			exit(0);
295*0Sstevel@tonic-gate 		if (unlink(forward))
296*0Sstevel@tonic-gate 			perror("Error removing .forward file:");
297*0Sstevel@tonic-gate 		else
298*0Sstevel@tonic-gate 			printf("Back to normal reception of mail.\n");
299*0Sstevel@tonic-gate 		exit(0);
300*0Sstevel@tonic-gate 	}
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate 	printf("To enable the mailcompat feature a \".forward\" ");
303*0Sstevel@tonic-gate 	printf("file is created.\n");
304*0Sstevel@tonic-gate 	if (!ask("Would you like to enable the mailcompat feature")) {
305*0Sstevel@tonic-gate 		printf("OK, mailcompat feature NOT enabled.\n");
306*0Sstevel@tonic-gate 		exit(0);
307*0Sstevel@tonic-gate 	}
308*0Sstevel@tonic-gate 	f = fopen(forward, "w");
309*0Sstevel@tonic-gate 	if (f == NULL) {
310*0Sstevel@tonic-gate 		perror("Error opening .forward file");
311*0Sstevel@tonic-gate 		exit(EX_USAGE);
312*0Sstevel@tonic-gate 	}
313*0Sstevel@tonic-gate 	fprintf(f, "\"|/usr/bin/mailcompat %s\"\n", myname);
314*0Sstevel@tonic-gate 	fclose(f);
315*0Sstevel@tonic-gate 	printf("Mailcompat feature ENABLED.");
316*0Sstevel@tonic-gate 	printf("Run mailcompat with no arguments to remove it\n");
317*0Sstevel@tonic-gate }
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate /*
321*0Sstevel@tonic-gate  * Ask the user a question until we get a reasonable answer
322*0Sstevel@tonic-gate  */
323*0Sstevel@tonic-gate int
324*0Sstevel@tonic-gate ask(prompt)
325*0Sstevel@tonic-gate 	char *prompt;
326*0Sstevel@tonic-gate {
327*0Sstevel@tonic-gate 	char line[MAXLINE];
328*0Sstevel@tonic-gate 
329*0Sstevel@tonic-gate 	for (;;) {
330*0Sstevel@tonic-gate 		printf("%s? ", prompt);
331*0Sstevel@tonic-gate 		fflush(stdout);
332*0Sstevel@tonic-gate 		fgets(line, sizeof (line), stdin);
333*0Sstevel@tonic-gate 		if (line[0] == 'y' || line[0] == 'Y')
334*0Sstevel@tonic-gate 			return (TRUE);
335*0Sstevel@tonic-gate 		if (line[0] == 'n' || line[0] == 'N')
336*0Sstevel@tonic-gate 			return (FALSE);
337*0Sstevel@tonic-gate 		printf("Please reply \"yes\" or \"no\" (\'y\' or \'n\')\n");
338*0Sstevel@tonic-gate 	}
339*0Sstevel@tonic-gate 	/* NOTREACHED */
340*0Sstevel@tonic-gate }
341