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