17c478bd9Sstevel@tonic-gate /*
2e9af4bc0SJohn Beck  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  *	Copyright (c) 1983, 1984, 1986, 1986, 1987, 1988, 1989 AT&T
67c478bd9Sstevel@tonic-gate  *	  All Rights Reserved
77c478bd9Sstevel@tonic-gate  */
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate  *  Vacation
117c478bd9Sstevel@tonic-gate  *  Copyright (c) 1983  Eric P. Allman
127c478bd9Sstevel@tonic-gate  *  Berkeley, California
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  *  Copyright (c) 1983 Regents of the University of California.
157c478bd9Sstevel@tonic-gate  *  All rights reserved.  The Berkeley software License Agreement
167c478bd9Sstevel@tonic-gate  *  specifies the terms and conditions for redistribution.
177c478bd9Sstevel@tonic-gate  */
187c478bd9Sstevel@tonic-gate 
197c478bd9Sstevel@tonic-gate #include <pwd.h>
207c478bd9Sstevel@tonic-gate #include <stdio.h>
217c478bd9Sstevel@tonic-gate #include <stdarg.h>
227c478bd9Sstevel@tonic-gate #include <stdlib.h>
237c478bd9Sstevel@tonic-gate #include <unistd.h>
247c478bd9Sstevel@tonic-gate #include <sysexits.h>
257c478bd9Sstevel@tonic-gate #include <string.h>
267c478bd9Sstevel@tonic-gate #include <ctype.h>
27e9af4bc0SJohn Beck #include <sm/bitops.h>
287c478bd9Sstevel@tonic-gate #include "conf.h"
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  *  MAILCOMPAT -- Deliver mail to a user's mailbox with the "From's" stuffed.
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate typedef int bool;
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #define	FALSE	0
377c478bd9Sstevel@tonic-gate #define	TRUE	1
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate bool	Debug = FALSE;
407c478bd9Sstevel@tonic-gate char	*myname;		/* person who is to have their mail filtered */
417c478bd9Sstevel@tonic-gate char	*homedir;		/* home directory of said person */
427c478bd9Sstevel@tonic-gate char	*AliasList[MAXLINE];	/* list of aliases to allow */
437c478bd9Sstevel@tonic-gate char    *fromp;
447c478bd9Sstevel@tonic-gate char    *fromuser;
457c478bd9Sstevel@tonic-gate int	AliasCount = 0;
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate static char *newstr();
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate int	ask(char *);
507c478bd9Sstevel@tonic-gate int	sendmessage(char *);
517c478bd9Sstevel@tonic-gate void	AutoInstall(void);
527c478bd9Sstevel@tonic-gate void	usrerr(const char *, ...);
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate int
main(argc,argv)557c478bd9Sstevel@tonic-gate main(argc, argv)
567c478bd9Sstevel@tonic-gate 	int argc;
577c478bd9Sstevel@tonic-gate 	char **argv;
587c478bd9Sstevel@tonic-gate {
597c478bd9Sstevel@tonic-gate 	register char *p;
607c478bd9Sstevel@tonic-gate 	struct passwd *pw;
617c478bd9Sstevel@tonic-gate 	extern char *getfrom();
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 	/* process arguments */
647c478bd9Sstevel@tonic-gate 	while (--argc > 0 && (p = *++argv) != NULL && *p == '-')
657c478bd9Sstevel@tonic-gate 	{
667c478bd9Sstevel@tonic-gate 		switch (*++p)
677c478bd9Sstevel@tonic-gate 		{
687c478bd9Sstevel@tonic-gate 		    case 'd':	/* debug */
697c478bd9Sstevel@tonic-gate 			Debug = TRUE;
707c478bd9Sstevel@tonic-gate 			break;
717c478bd9Sstevel@tonic-gate 		    default:
727c478bd9Sstevel@tonic-gate 			usrerr("Unknown flag -%s", p);
737c478bd9Sstevel@tonic-gate 			exit(EX_USAGE);
747c478bd9Sstevel@tonic-gate 		}
757c478bd9Sstevel@tonic-gate 	}
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	/* verify recipient argument */
787c478bd9Sstevel@tonic-gate 	if (argc != 1)
797c478bd9Sstevel@tonic-gate 	{
807c478bd9Sstevel@tonic-gate 		if (argc == 0)
817c478bd9Sstevel@tonic-gate 			AutoInstall();
827c478bd9Sstevel@tonic-gate 		else
837c478bd9Sstevel@tonic-gate 			usrerr("Usage: mailcompat username (or) mailcompat -r");
847c478bd9Sstevel@tonic-gate 		exit(EX_USAGE);
857c478bd9Sstevel@tonic-gate 	}
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	myname = p;
887c478bd9Sstevel@tonic-gate 	/* find user's home directory */
897c478bd9Sstevel@tonic-gate 	pw = getpwnam(myname);
907c478bd9Sstevel@tonic-gate 	if (pw == NULL)
917c478bd9Sstevel@tonic-gate 	{
927c478bd9Sstevel@tonic-gate 		usrerr("user: %s look up failed, name services outage ?", myname);
937c478bd9Sstevel@tonic-gate 		exit(EX_TEMPFAIL);
947c478bd9Sstevel@tonic-gate 	}
957c478bd9Sstevel@tonic-gate 	homedir = newstr(pw->pw_dir);
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 	/* read message from standard input (just from line) */
987c478bd9Sstevel@tonic-gate 	fromuser = getfrom(&fromp);
997c478bd9Sstevel@tonic-gate 	return (sendmessage(fromuser));
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate /*
1037c478bd9Sstevel@tonic-gate **  sendmessage -- read message from standard input do the from stuffing
1047c478bd9Sstevel@tonic-gate **             and forward to /bin/mail, Being sure to delete any
1057c478bd9Sstevel@tonic-gate **             content-length headers (/bin/mail recalculates them).
1067c478bd9Sstevel@tonic-gate **
1077c478bd9Sstevel@tonic-gate **
1087c478bd9Sstevel@tonic-gate **	Parameters:
1097c478bd9Sstevel@tonic-gate **		none.
1107c478bd9Sstevel@tonic-gate **
1117c478bd9Sstevel@tonic-gate **
1127c478bd9Sstevel@tonic-gate **	Side Effects:
1137c478bd9Sstevel@tonic-gate **		Reads first line from standard input.
1147c478bd9Sstevel@tonic-gate */
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate #define	L_HEADER	"Content-Length:"
1177c478bd9Sstevel@tonic-gate #define	LL_HEADER	15
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate int
sendmessage(from)1207c478bd9Sstevel@tonic-gate sendmessage(from)
1217c478bd9Sstevel@tonic-gate char *from;
1227c478bd9Sstevel@tonic-gate {
1237c478bd9Sstevel@tonic-gate 	static char line[MAXLINE];
1247c478bd9Sstevel@tonic-gate 	static char command[MAXLINE];
1257c478bd9Sstevel@tonic-gate 	bool in_body = FALSE;
1267c478bd9Sstevel@tonic-gate 	FILE *mail_fp;
1277c478bd9Sstevel@tonic-gate 	static char user_name[L_cuserid];
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	if (from == NULL)
1307c478bd9Sstevel@tonic-gate 		from = cuserid(user_name);
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	snprintf(command, sizeof (command), "/bin/mail -f %s -d %s", from,
1337c478bd9Sstevel@tonic-gate 	    myname);
1347c478bd9Sstevel@tonic-gate 	mail_fp = popen(command, "w");
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	/* read the  line */
1377c478bd9Sstevel@tonic-gate 	while (fgets(line, sizeof line, stdin) != NULL)
1387c478bd9Sstevel@tonic-gate 	{
1397c478bd9Sstevel@tonic-gate 		if (line[0] == (char)'\n')  /* end of mail headers */
1407c478bd9Sstevel@tonic-gate 			in_body = TRUE;
1417c478bd9Sstevel@tonic-gate 		if (in_body && (strncmp(line, "From ", 5) == 0))
1427c478bd9Sstevel@tonic-gate 			fprintf(mail_fp, ">");
1437c478bd9Sstevel@tonic-gate 		if (in_body || (strncasecmp(line, L_HEADER, LL_HEADER) != 0))
1447c478bd9Sstevel@tonic-gate 			fputs(line, mail_fp);
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate 	return (pclose(mail_fp));
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate char *
getfrom(shortp)1507c478bd9Sstevel@tonic-gate getfrom(shortp)
1517c478bd9Sstevel@tonic-gate char **shortp;
1527c478bd9Sstevel@tonic-gate {
1537c478bd9Sstevel@tonic-gate 	static char line[MAXLINE];
1547c478bd9Sstevel@tonic-gate 	register char *p, *start, *at, *bang;
1557c478bd9Sstevel@tonic-gate 	char saveat;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	/* read the from line */
1587c478bd9Sstevel@tonic-gate 	if (fgets(line, sizeof line, stdin) == NULL ||
159*fad16a7eSToomas Soome 	    strncmp(line, "From ", 5) != 0)
1607c478bd9Sstevel@tonic-gate 	{
1617c478bd9Sstevel@tonic-gate 		usrerr("No initial From line");
1627c478bd9Sstevel@tonic-gate 		exit(EX_USAGE);
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	/* find the end of the sender address and terminate it */
1667c478bd9Sstevel@tonic-gate 	start = &line[5];
1677c478bd9Sstevel@tonic-gate 	p = strchr(start, ' ');
1687c478bd9Sstevel@tonic-gate 	if (p == NULL)
1697c478bd9Sstevel@tonic-gate 	{
1707c478bd9Sstevel@tonic-gate 		usrerr("Funny From line '%s'", line);
1717c478bd9Sstevel@tonic-gate 		exit(EX_USAGE);
1727c478bd9Sstevel@tonic-gate 	}
1737c478bd9Sstevel@tonic-gate 	*p = '\0';
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	/*
1767c478bd9Sstevel@tonic-gate 	 * Strip all but the rightmost UUCP host
1777c478bd9Sstevel@tonic-gate 	 * to prevent loops due to forwarding.
1787c478bd9Sstevel@tonic-gate 	 * Start searching leftward from the leftmost '@'.
1797c478bd9Sstevel@tonic-gate 	 *	a!b!c!d yields a short name of c!d
1807c478bd9Sstevel@tonic-gate 	 *	a!b!c!d@e yields a short name of c!d@e
1817c478bd9Sstevel@tonic-gate 	 *	e@a!b!c yields the same short name
1827c478bd9Sstevel@tonic-gate 	 */
1837c478bd9Sstevel@tonic-gate #ifdef VDEBUG
1847c478bd9Sstevel@tonic-gate printf("start='%s'\n", start);
1857c478bd9Sstevel@tonic-gate #endif /* VDEBUG */
1867c478bd9Sstevel@tonic-gate 	*shortp = start;			/* assume whole addr */
1877c478bd9Sstevel@tonic-gate 	if ((at = strchr(start, '@')) == NULL)	/* leftmost '@' */
1887c478bd9Sstevel@tonic-gate 		at = p;				/* if none, use end of addr */
1897c478bd9Sstevel@tonic-gate 	saveat = *at;
1907c478bd9Sstevel@tonic-gate 	*at = '\0';
1917c478bd9Sstevel@tonic-gate 	if ((bang = strrchr(start, '!')) != NULL) {	/* rightmost '!' */
1927c478bd9Sstevel@tonic-gate 		char *bang2;
1937c478bd9Sstevel@tonic-gate 		*bang = '\0';
1947c478bd9Sstevel@tonic-gate 		if ((bang2 = strrchr(start, '!')) != NULL) /* 2nd rightmost '!' */
1957c478bd9Sstevel@tonic-gate 			*shortp = bang2 + 1;		/* move past ! */
1967c478bd9Sstevel@tonic-gate 		*bang = '!';
1977c478bd9Sstevel@tonic-gate 	}
1987c478bd9Sstevel@tonic-gate 	*at = saveat;
1997c478bd9Sstevel@tonic-gate #ifdef VDEBUG
2007c478bd9Sstevel@tonic-gate printf("place='%s'\n", *shortp);
2017c478bd9Sstevel@tonic-gate #endif /* VDEBUG */
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	/* return the sender address */
2047c478bd9Sstevel@tonic-gate 	return newstr(start);
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate **  USRERR -- print user error
2097c478bd9Sstevel@tonic-gate **
2107c478bd9Sstevel@tonic-gate **	Parameters:
2117c478bd9Sstevel@tonic-gate **		f -- format.
2127c478bd9Sstevel@tonic-gate **
2137c478bd9Sstevel@tonic-gate **	Returns:
2147c478bd9Sstevel@tonic-gate **		none.
2157c478bd9Sstevel@tonic-gate **
2167c478bd9Sstevel@tonic-gate **	Side Effects:
2177c478bd9Sstevel@tonic-gate **		none.
2187c478bd9Sstevel@tonic-gate */
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate void
usrerr(const char * f,...)2217c478bd9Sstevel@tonic-gate usrerr(const char *f, ...)
2227c478bd9Sstevel@tonic-gate {
2237c478bd9Sstevel@tonic-gate 	va_list alist;
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	va_start(alist, f);
2267c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "mailcompat: ");
2277c478bd9Sstevel@tonic-gate 	(void) vfprintf(stderr, f, alist);
2287c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\n");
2297c478bd9Sstevel@tonic-gate 	va_end(alist);
2307c478bd9Sstevel@tonic-gate }
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate /*
2337c478bd9Sstevel@tonic-gate **  NEWSTR -- copy a string
2347c478bd9Sstevel@tonic-gate **
2357c478bd9Sstevel@tonic-gate **	Parameters:
2367c478bd9Sstevel@tonic-gate **		s -- the string to copy.
2377c478bd9Sstevel@tonic-gate **
2387c478bd9Sstevel@tonic-gate **	Returns:
2397c478bd9Sstevel@tonic-gate **		A copy of the string.
2407c478bd9Sstevel@tonic-gate **
2417c478bd9Sstevel@tonic-gate **	Side Effects:
2427c478bd9Sstevel@tonic-gate **		none.
2437c478bd9Sstevel@tonic-gate */
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate char *
newstr(s)2467c478bd9Sstevel@tonic-gate newstr(s)
2477c478bd9Sstevel@tonic-gate 	char *s;
2487c478bd9Sstevel@tonic-gate {
2497c478bd9Sstevel@tonic-gate 	char *p;
2507c478bd9Sstevel@tonic-gate 	size_t psize = strlen(s) + 1;
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	p = malloc(psize);
2537c478bd9Sstevel@tonic-gate 	if (p == NULL)
2547c478bd9Sstevel@tonic-gate 	{
2557c478bd9Sstevel@tonic-gate 		usrerr("newstr: cannot alloc memory");
2567c478bd9Sstevel@tonic-gate 		exit(EX_OSERR);
2577c478bd9Sstevel@tonic-gate 	}
2587c478bd9Sstevel@tonic-gate 	strlcpy(p, s, psize);
2597c478bd9Sstevel@tonic-gate 	return (p);
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate /*
2637c478bd9Sstevel@tonic-gate  * When invoked with no arguments, we fall into an automatic installation
2647c478bd9Sstevel@tonic-gate  * mode, stepping the user through a default installation.
2657c478bd9Sstevel@tonic-gate  */
2667c478bd9Sstevel@tonic-gate void
AutoInstall()2677c478bd9Sstevel@tonic-gate AutoInstall()
2687c478bd9Sstevel@tonic-gate {
2697c478bd9Sstevel@tonic-gate 	char forward[MAXLINE];
2707c478bd9Sstevel@tonic-gate 	char line[MAXLINE];
2717c478bd9Sstevel@tonic-gate 	static char user_name[L_cuserid];
2727c478bd9Sstevel@tonic-gate 	FILE *f;
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	myname = cuserid(user_name);
2757c478bd9Sstevel@tonic-gate 	homedir = getenv("HOME");
2767c478bd9Sstevel@tonic-gate 	if (homedir == NULL) {
2777c478bd9Sstevel@tonic-gate 		usrerr("Home directory unknown");
2787c478bd9Sstevel@tonic-gate 		exit(EX_CONFIG);
2797c478bd9Sstevel@tonic-gate 	}
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	printf("This program can be used to store your mail in a format\n");
2827c478bd9Sstevel@tonic-gate 	printf("that you can read with SunOS 4.X based mail readers\n");
2837c478bd9Sstevel@tonic-gate 	(void) strlcpy(forward, homedir, sizeof (forward));
2847c478bd9Sstevel@tonic-gate 	(void) strlcat(forward, "/.forward", sizeof (forward));
2857c478bd9Sstevel@tonic-gate 	f = fopen(forward, "r");
2867c478bd9Sstevel@tonic-gate 	if (f) {
2877c478bd9Sstevel@tonic-gate 		printf("You have a .forward file in your home directory");
2887c478bd9Sstevel@tonic-gate 		printf("  containing:\n");
2897c478bd9Sstevel@tonic-gate 		while (fgets(line, MAXLINE, f))
2907c478bd9Sstevel@tonic-gate 			printf("    %s", line);
2917c478bd9Sstevel@tonic-gate 		fclose(f);
2927c478bd9Sstevel@tonic-gate 		if (!ask("Would you like to remove it and disable the mailcompat feature"))
2937c478bd9Sstevel@tonic-gate 			exit(0);
2947c478bd9Sstevel@tonic-gate 		if (unlink(forward))
2957c478bd9Sstevel@tonic-gate 			perror("Error removing .forward file:");
2967c478bd9Sstevel@tonic-gate 		else
2977c478bd9Sstevel@tonic-gate 			printf("Back to normal reception of mail.\n");
2987c478bd9Sstevel@tonic-gate 		exit(0);
2997c478bd9Sstevel@tonic-gate 	}
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	printf("To enable the mailcompat feature a \".forward\" ");
3027c478bd9Sstevel@tonic-gate 	printf("file is created.\n");
3037c478bd9Sstevel@tonic-gate 	if (!ask("Would you like to enable the mailcompat feature")) {
3047c478bd9Sstevel@tonic-gate 		printf("OK, mailcompat feature NOT enabled.\n");
3057c478bd9Sstevel@tonic-gate 		exit(0);
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate 	f = fopen(forward, "w");
3087c478bd9Sstevel@tonic-gate 	if (f == NULL) {
3097c478bd9Sstevel@tonic-gate 		perror("Error opening .forward file");
3107c478bd9Sstevel@tonic-gate 		exit(EX_USAGE);
3117c478bd9Sstevel@tonic-gate 	}
3127c478bd9Sstevel@tonic-gate 	fprintf(f, "\"|/usr/bin/mailcompat %s\"\n", myname);
3137c478bd9Sstevel@tonic-gate 	fclose(f);
3147c478bd9Sstevel@tonic-gate 	printf("Mailcompat feature ENABLED.");
3157c478bd9Sstevel@tonic-gate 	printf("Run mailcompat with no arguments to remove it\n");
3167c478bd9Sstevel@tonic-gate }
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate /*
3207c478bd9Sstevel@tonic-gate  * Ask the user a question until we get a reasonable answer
3217c478bd9Sstevel@tonic-gate  */
3227c478bd9Sstevel@tonic-gate int
ask(prompt)3237c478bd9Sstevel@tonic-gate ask(prompt)
3247c478bd9Sstevel@tonic-gate 	char *prompt;
3257c478bd9Sstevel@tonic-gate {
3267c478bd9Sstevel@tonic-gate 	char line[MAXLINE];
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	for (;;) {
3297c478bd9Sstevel@tonic-gate 		printf("%s? ", prompt);
3307c478bd9Sstevel@tonic-gate 		fflush(stdout);
3317c478bd9Sstevel@tonic-gate 		fgets(line, sizeof (line), stdin);
3327c478bd9Sstevel@tonic-gate 		if (line[0] == 'y' || line[0] == 'Y')
3337c478bd9Sstevel@tonic-gate 			return (TRUE);
3347c478bd9Sstevel@tonic-gate 		if (line[0] == 'n' || line[0] == 'N')
3357c478bd9Sstevel@tonic-gate 			return (FALSE);
3367c478bd9Sstevel@tonic-gate 		printf("Please reply \"yes\" or \"no\" (\'y\' or \'n\')\n");
3377c478bd9Sstevel@tonic-gate 	}
3387c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
3397c478bd9Sstevel@tonic-gate }
340