17c478bd9Sstevel@tonic-gate /*
2*e9af4bc0SJohn 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>
27*e9af4bc0SJohn 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 ||
1597c478bd9Sstevel@tonic-gate strncmp(line, "From ", 5) != NULL)
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