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