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