xref: /onnv-gate/usr/src/cmd/sendmail/aux/mailcompat.c (revision 11440:802724e2906a)
10Sstevel@tonic-gate /*
2*11440SJohn.Beck@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  *	Copyright (c) 1983, 1984, 1986, 1986, 1987, 1988, 1989 AT&T
60Sstevel@tonic-gate  *	  All Rights Reserved
70Sstevel@tonic-gate  */
80Sstevel@tonic-gate 
90Sstevel@tonic-gate /*
100Sstevel@tonic-gate  *  Vacation
110Sstevel@tonic-gate  *  Copyright (c) 1983  Eric P. Allman
120Sstevel@tonic-gate  *  Berkeley, California
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  *  Copyright (c) 1983 Regents of the University of California.
150Sstevel@tonic-gate  *  All rights reserved.  The Berkeley software License Agreement
160Sstevel@tonic-gate  *  specifies the terms and conditions for redistribution.
170Sstevel@tonic-gate  */
180Sstevel@tonic-gate 
190Sstevel@tonic-gate #include <pwd.h>
200Sstevel@tonic-gate #include <stdio.h>
210Sstevel@tonic-gate #include <stdarg.h>
220Sstevel@tonic-gate #include <stdlib.h>
230Sstevel@tonic-gate #include <unistd.h>
240Sstevel@tonic-gate #include <sysexits.h>
250Sstevel@tonic-gate #include <string.h>
260Sstevel@tonic-gate #include <ctype.h>
27*11440SJohn.Beck@Sun.COM #include <sm/bitops.h>
280Sstevel@tonic-gate #include "conf.h"
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate  *  MAILCOMPAT -- Deliver mail to a user's mailbox with the "From's" stuffed.
320Sstevel@tonic-gate  */
330Sstevel@tonic-gate 
340Sstevel@tonic-gate typedef int bool;
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #define	FALSE	0
370Sstevel@tonic-gate #define	TRUE	1
380Sstevel@tonic-gate 
390Sstevel@tonic-gate bool	Debug = FALSE;
400Sstevel@tonic-gate char	*myname;		/* person who is to have their mail filtered */
410Sstevel@tonic-gate char	*homedir;		/* home directory of said person */
420Sstevel@tonic-gate char	*AliasList[MAXLINE];	/* list of aliases to allow */
430Sstevel@tonic-gate char    *fromp;
440Sstevel@tonic-gate char    *fromuser;
450Sstevel@tonic-gate int	AliasCount = 0;
460Sstevel@tonic-gate 
470Sstevel@tonic-gate static char *newstr();
480Sstevel@tonic-gate 
490Sstevel@tonic-gate int	ask(char *);
500Sstevel@tonic-gate int	sendmessage(char *);
510Sstevel@tonic-gate void	AutoInstall(void);
520Sstevel@tonic-gate void	usrerr(const char *, ...);
530Sstevel@tonic-gate 
540Sstevel@tonic-gate int
main(argc,argv)550Sstevel@tonic-gate main(argc, argv)
560Sstevel@tonic-gate 	int argc;
570Sstevel@tonic-gate 	char **argv;
580Sstevel@tonic-gate {
590Sstevel@tonic-gate 	register char *p;
600Sstevel@tonic-gate 	struct passwd *pw;
610Sstevel@tonic-gate 	extern char *getfrom();
620Sstevel@tonic-gate 
630Sstevel@tonic-gate 	/* process arguments */
640Sstevel@tonic-gate 	while (--argc > 0 && (p = *++argv) != NULL && *p == '-')
650Sstevel@tonic-gate 	{
660Sstevel@tonic-gate 		switch (*++p)
670Sstevel@tonic-gate 		{
680Sstevel@tonic-gate 		    case 'd':	/* debug */
690Sstevel@tonic-gate 			Debug = TRUE;
700Sstevel@tonic-gate 			break;
710Sstevel@tonic-gate 		    default:
720Sstevel@tonic-gate 			usrerr("Unknown flag -%s", p);
730Sstevel@tonic-gate 			exit(EX_USAGE);
740Sstevel@tonic-gate 		}
750Sstevel@tonic-gate 	}
760Sstevel@tonic-gate 
770Sstevel@tonic-gate 	/* verify recipient argument */
780Sstevel@tonic-gate 	if (argc != 1)
790Sstevel@tonic-gate 	{
800Sstevel@tonic-gate 		if (argc == 0)
810Sstevel@tonic-gate 			AutoInstall();
820Sstevel@tonic-gate 		else
830Sstevel@tonic-gate 			usrerr("Usage: mailcompat username (or) mailcompat -r");
840Sstevel@tonic-gate 		exit(EX_USAGE);
850Sstevel@tonic-gate 	}
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	myname = p;
880Sstevel@tonic-gate 	/* find user's home directory */
890Sstevel@tonic-gate 	pw = getpwnam(myname);
900Sstevel@tonic-gate 	if (pw == NULL)
910Sstevel@tonic-gate 	{
920Sstevel@tonic-gate 		usrerr("user: %s look up failed, name services outage ?", myname);
930Sstevel@tonic-gate 		exit(EX_TEMPFAIL);
940Sstevel@tonic-gate 	}
950Sstevel@tonic-gate 	homedir = newstr(pw->pw_dir);
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	/* read message from standard input (just from line) */
980Sstevel@tonic-gate 	fromuser = getfrom(&fromp);
990Sstevel@tonic-gate 	return (sendmessage(fromuser));
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate /*
1030Sstevel@tonic-gate **  sendmessage -- read message from standard input do the from stuffing
1040Sstevel@tonic-gate **             and forward to /bin/mail, Being sure to delete any
1050Sstevel@tonic-gate **             content-length headers (/bin/mail recalculates them).
1060Sstevel@tonic-gate **
1070Sstevel@tonic-gate **
1080Sstevel@tonic-gate **	Parameters:
1090Sstevel@tonic-gate **		none.
1100Sstevel@tonic-gate **
1110Sstevel@tonic-gate **
1120Sstevel@tonic-gate **	Side Effects:
1130Sstevel@tonic-gate **		Reads first line from standard input.
1140Sstevel@tonic-gate */
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate #define	L_HEADER	"Content-Length:"
1170Sstevel@tonic-gate #define	LL_HEADER	15
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate int
sendmessage(from)1200Sstevel@tonic-gate sendmessage(from)
1210Sstevel@tonic-gate char *from;
1220Sstevel@tonic-gate {
1230Sstevel@tonic-gate 	static char line[MAXLINE];
1240Sstevel@tonic-gate 	static char command[MAXLINE];
1250Sstevel@tonic-gate 	bool in_body = FALSE;
1260Sstevel@tonic-gate 	FILE *mail_fp;
1270Sstevel@tonic-gate 	static char user_name[L_cuserid];
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	if (from == NULL)
1300Sstevel@tonic-gate 		from = cuserid(user_name);
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	snprintf(command, sizeof (command), "/bin/mail -f %s -d %s", from,
1330Sstevel@tonic-gate 	    myname);
1340Sstevel@tonic-gate 	mail_fp = popen(command, "w");
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	/* read the  line */
1370Sstevel@tonic-gate 	while (fgets(line, sizeof line, stdin) != NULL)
1380Sstevel@tonic-gate 	{
1390Sstevel@tonic-gate 		if (line[0] == (char)'\n')  /* end of mail headers */
1400Sstevel@tonic-gate 			in_body = TRUE;
1410Sstevel@tonic-gate 		if (in_body && (strncmp(line, "From ", 5) == 0))
1420Sstevel@tonic-gate 			fprintf(mail_fp, ">");
1430Sstevel@tonic-gate 		if (in_body || (strncasecmp(line, L_HEADER, LL_HEADER) != 0))
1440Sstevel@tonic-gate 			fputs(line, mail_fp);
1450Sstevel@tonic-gate 	}
1460Sstevel@tonic-gate 	return (pclose(mail_fp));
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate char *
getfrom(shortp)1500Sstevel@tonic-gate getfrom(shortp)
1510Sstevel@tonic-gate char **shortp;
1520Sstevel@tonic-gate {
1530Sstevel@tonic-gate 	static char line[MAXLINE];
1540Sstevel@tonic-gate 	register char *p, *start, *at, *bang;
1550Sstevel@tonic-gate 	char saveat;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	/* read the from line */
1580Sstevel@tonic-gate 	if (fgets(line, sizeof line, stdin) == NULL ||
1590Sstevel@tonic-gate 	    strncmp(line, "From ", 5) != NULL)
1600Sstevel@tonic-gate 	{
1610Sstevel@tonic-gate 		usrerr("No initial From line");
1620Sstevel@tonic-gate 		exit(EX_USAGE);
1630Sstevel@tonic-gate 	}
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	/* find the end of the sender address and terminate it */
1660Sstevel@tonic-gate 	start = &line[5];
1670Sstevel@tonic-gate 	p = strchr(start, ' ');
1680Sstevel@tonic-gate 	if (p == NULL)
1690Sstevel@tonic-gate 	{
1700Sstevel@tonic-gate 		usrerr("Funny From line '%s'", line);
1710Sstevel@tonic-gate 		exit(EX_USAGE);
1720Sstevel@tonic-gate 	}
1730Sstevel@tonic-gate 	*p = '\0';
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	/*
1760Sstevel@tonic-gate 	 * Strip all but the rightmost UUCP host
1770Sstevel@tonic-gate 	 * to prevent loops due to forwarding.
1780Sstevel@tonic-gate 	 * Start searching leftward from the leftmost '@'.
1790Sstevel@tonic-gate 	 *	a!b!c!d yields a short name of c!d
1800Sstevel@tonic-gate 	 *	a!b!c!d@e yields a short name of c!d@e
1810Sstevel@tonic-gate 	 *	e@a!b!c yields the same short name
1820Sstevel@tonic-gate 	 */
1830Sstevel@tonic-gate #ifdef VDEBUG
1840Sstevel@tonic-gate printf("start='%s'\n", start);
1850Sstevel@tonic-gate #endif /* VDEBUG */
1860Sstevel@tonic-gate 	*shortp = start;			/* assume whole addr */
1870Sstevel@tonic-gate 	if ((at = strchr(start, '@')) == NULL)	/* leftmost '@' */
1880Sstevel@tonic-gate 		at = p;				/* if none, use end of addr */
1890Sstevel@tonic-gate 	saveat = *at;
1900Sstevel@tonic-gate 	*at = '\0';
1910Sstevel@tonic-gate 	if ((bang = strrchr(start, '!')) != NULL) {	/* rightmost '!' */
1920Sstevel@tonic-gate 		char *bang2;
1930Sstevel@tonic-gate 		*bang = '\0';
1940Sstevel@tonic-gate 		if ((bang2 = strrchr(start, '!')) != NULL) /* 2nd rightmost '!' */
1950Sstevel@tonic-gate 			*shortp = bang2 + 1;		/* move past ! */
1960Sstevel@tonic-gate 		*bang = '!';
1970Sstevel@tonic-gate 	}
1980Sstevel@tonic-gate 	*at = saveat;
1990Sstevel@tonic-gate #ifdef VDEBUG
2000Sstevel@tonic-gate printf("place='%s'\n", *shortp);
2010Sstevel@tonic-gate #endif /* VDEBUG */
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 	/* return the sender address */
2040Sstevel@tonic-gate 	return newstr(start);
2050Sstevel@tonic-gate }
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate /*
2080Sstevel@tonic-gate **  USRERR -- print user error
2090Sstevel@tonic-gate **
2100Sstevel@tonic-gate **	Parameters:
2110Sstevel@tonic-gate **		f -- format.
2120Sstevel@tonic-gate **
2130Sstevel@tonic-gate **	Returns:
2140Sstevel@tonic-gate **		none.
2150Sstevel@tonic-gate **
2160Sstevel@tonic-gate **	Side Effects:
2170Sstevel@tonic-gate **		none.
2180Sstevel@tonic-gate */
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate void
usrerr(const char * f,...)2210Sstevel@tonic-gate usrerr(const char *f, ...)
2220Sstevel@tonic-gate {
2230Sstevel@tonic-gate 	va_list alist;
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	va_start(alist, f);
2260Sstevel@tonic-gate 	(void) fprintf(stderr, "mailcompat: ");
2270Sstevel@tonic-gate 	(void) vfprintf(stderr, f, alist);
2280Sstevel@tonic-gate 	(void) fprintf(stderr, "\n");
2290Sstevel@tonic-gate 	va_end(alist);
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate /*
2330Sstevel@tonic-gate **  NEWSTR -- copy a string
2340Sstevel@tonic-gate **
2350Sstevel@tonic-gate **	Parameters:
2360Sstevel@tonic-gate **		s -- the string to copy.
2370Sstevel@tonic-gate **
2380Sstevel@tonic-gate **	Returns:
2390Sstevel@tonic-gate **		A copy of the string.
2400Sstevel@tonic-gate **
2410Sstevel@tonic-gate **	Side Effects:
2420Sstevel@tonic-gate **		none.
2430Sstevel@tonic-gate */
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate char *
newstr(s)2460Sstevel@tonic-gate newstr(s)
2470Sstevel@tonic-gate 	char *s;
2480Sstevel@tonic-gate {
2490Sstevel@tonic-gate 	char *p;
2500Sstevel@tonic-gate 	size_t psize = strlen(s) + 1;
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	p = malloc(psize);
2530Sstevel@tonic-gate 	if (p == NULL)
2540Sstevel@tonic-gate 	{
2550Sstevel@tonic-gate 		usrerr("newstr: cannot alloc memory");
2560Sstevel@tonic-gate 		exit(EX_OSERR);
2570Sstevel@tonic-gate 	}
2580Sstevel@tonic-gate 	strlcpy(p, s, psize);
2590Sstevel@tonic-gate 	return (p);
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate /*
2630Sstevel@tonic-gate  * When invoked with no arguments, we fall into an automatic installation
2640Sstevel@tonic-gate  * mode, stepping the user through a default installation.
2650Sstevel@tonic-gate  */
2660Sstevel@tonic-gate void
AutoInstall()2670Sstevel@tonic-gate AutoInstall()
2680Sstevel@tonic-gate {
2690Sstevel@tonic-gate 	char forward[MAXLINE];
2700Sstevel@tonic-gate 	char line[MAXLINE];
2710Sstevel@tonic-gate 	static char user_name[L_cuserid];
2720Sstevel@tonic-gate 	FILE *f;
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	myname = cuserid(user_name);
2750Sstevel@tonic-gate 	homedir = getenv("HOME");
2760Sstevel@tonic-gate 	if (homedir == NULL) {
2770Sstevel@tonic-gate 		usrerr("Home directory unknown");
2780Sstevel@tonic-gate 		exit(EX_CONFIG);
2790Sstevel@tonic-gate 	}
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 	printf("This program can be used to store your mail in a format\n");
2820Sstevel@tonic-gate 	printf("that you can read with SunOS 4.X based mail readers\n");
2830Sstevel@tonic-gate 	(void) strlcpy(forward, homedir, sizeof (forward));
2840Sstevel@tonic-gate 	(void) strlcat(forward, "/.forward", sizeof (forward));
2850Sstevel@tonic-gate 	f = fopen(forward, "r");
2860Sstevel@tonic-gate 	if (f) {
2870Sstevel@tonic-gate 		printf("You have a .forward file in your home directory");
2880Sstevel@tonic-gate 		printf("  containing:\n");
2890Sstevel@tonic-gate 		while (fgets(line, MAXLINE, f))
2900Sstevel@tonic-gate 			printf("    %s", line);
2910Sstevel@tonic-gate 		fclose(f);
2920Sstevel@tonic-gate 		if (!ask("Would you like to remove it and disable the mailcompat feature"))
2930Sstevel@tonic-gate 			exit(0);
2940Sstevel@tonic-gate 		if (unlink(forward))
2950Sstevel@tonic-gate 			perror("Error removing .forward file:");
2960Sstevel@tonic-gate 		else
2970Sstevel@tonic-gate 			printf("Back to normal reception of mail.\n");
2980Sstevel@tonic-gate 		exit(0);
2990Sstevel@tonic-gate 	}
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 	printf("To enable the mailcompat feature a \".forward\" ");
3020Sstevel@tonic-gate 	printf("file is created.\n");
3030Sstevel@tonic-gate 	if (!ask("Would you like to enable the mailcompat feature")) {
3040Sstevel@tonic-gate 		printf("OK, mailcompat feature NOT enabled.\n");
3050Sstevel@tonic-gate 		exit(0);
3060Sstevel@tonic-gate 	}
3070Sstevel@tonic-gate 	f = fopen(forward, "w");
3080Sstevel@tonic-gate 	if (f == NULL) {
3090Sstevel@tonic-gate 		perror("Error opening .forward file");
3100Sstevel@tonic-gate 		exit(EX_USAGE);
3110Sstevel@tonic-gate 	}
3120Sstevel@tonic-gate 	fprintf(f, "\"|/usr/bin/mailcompat %s\"\n", myname);
3130Sstevel@tonic-gate 	fclose(f);
3140Sstevel@tonic-gate 	printf("Mailcompat feature ENABLED.");
3150Sstevel@tonic-gate 	printf("Run mailcompat with no arguments to remove it\n");
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate /*
3200Sstevel@tonic-gate  * Ask the user a question until we get a reasonable answer
3210Sstevel@tonic-gate  */
3220Sstevel@tonic-gate int
ask(prompt)3230Sstevel@tonic-gate ask(prompt)
3240Sstevel@tonic-gate 	char *prompt;
3250Sstevel@tonic-gate {
3260Sstevel@tonic-gate 	char line[MAXLINE];
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	for (;;) {
3290Sstevel@tonic-gate 		printf("%s? ", prompt);
3300Sstevel@tonic-gate 		fflush(stdout);
3310Sstevel@tonic-gate 		fgets(line, sizeof (line), stdin);
3320Sstevel@tonic-gate 		if (line[0] == 'y' || line[0] == 'Y')
3330Sstevel@tonic-gate 			return (TRUE);
3340Sstevel@tonic-gate 		if (line[0] == 'n' || line[0] == 'N')
3350Sstevel@tonic-gate 			return (FALSE);
3360Sstevel@tonic-gate 		printf("Please reply \"yes\" or \"no\" (\'y\' or \'n\')\n");
3370Sstevel@tonic-gate 	}
3380Sstevel@tonic-gate 	/* NOTREACHED */
3390Sstevel@tonic-gate }
340