1N/A/*
1N/A * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
1N/A *
1N/A * Copyright (c) 1983, 1984, 1986, 1986, 1987, 1988, 1989 AT&T
1N/A * All Rights Reserved
1N/A */
1N/A
1N/A/*
1N/A * Vacation
1N/A * Copyright (c) 1983 Eric P. Allman
1N/A * Berkeley, California
1N/A *
1N/A * Copyright (c) 1983 Regents of the University of California.
1N/A * All rights reserved. The Berkeley software License Agreement
1N/A * specifies the terms and conditions for redistribution.
1N/A */
1N/A
1N/A#include <pwd.h>
1N/A#include <stdio.h>
1N/A#include <stdarg.h>
1N/A#include <stdlib.h>
1N/A#include <unistd.h>
1N/A#include <sysexits.h>
1N/A#include <string.h>
1N/A#include <ctype.h>
1N/A#include <sm/bitops.h>
1N/A#include "conf.h"
1N/A
1N/A/*
1N/A * MAILCOMPAT -- Deliver mail to a user's mailbox with the "From's" stuffed.
1N/A */
1N/A
1N/Atypedef int bool;
1N/A
1N/A#define FALSE 0
1N/A#define TRUE 1
1N/A
1N/Abool Debug = FALSE;
1N/Achar *myname; /* person who is to have their mail filtered */
1N/Achar *homedir; /* home directory of said person */
1N/Achar *fromp;
1N/Achar *fromuser;
1N/A
1N/Astatic char *newstr();
1N/A
1N/Aint ask(char *);
1N/Aint sendmessage(char *);
1N/Avoid AutoInstall(void);
1N/Avoid usrerr(const char *, ...);
1N/A
1N/Aint
1N/Amain(argc, argv)
1N/A int argc;
1N/A char **argv;
1N/A{
1N/A register char *p;
1N/A struct passwd *pw;
1N/A extern char *getfrom();
1N/A
1N/A /* process arguments */
1N/A while (--argc > 0 && (p = *++argv) != NULL && *p == '-')
1N/A {
1N/A switch (*++p)
1N/A {
1N/A case 'd': /* debug */
1N/A Debug = TRUE;
1N/A break;
1N/A default:
1N/A usrerr("Unknown flag -%s", p);
1N/A exit(EX_USAGE);
1N/A }
1N/A }
1N/A
1N/A /* verify recipient argument */
1N/A if (argc != 1)
1N/A {
1N/A if (argc == 0)
1N/A AutoInstall();
1N/A else
1N/A usrerr("Usage: mailcompat username (or) mailcompat -r");
1N/A exit(EX_USAGE);
1N/A }
1N/A
1N/A myname = p;
1N/A /* find user's home directory */
1N/A pw = getpwnam(myname);
1N/A if (pw == NULL)
1N/A {
1N/A usrerr("user: %s look up failed, name services outage ?", myname);
1N/A exit(EX_TEMPFAIL);
1N/A }
1N/A homedir = newstr(pw->pw_dir);
1N/A
1N/A /* read message from standard input (just from line) */
1N/A fromuser = getfrom(&fromp);
1N/A return (sendmessage(fromuser));
1N/A}
1N/A
1N/A/*
1N/A** sendmessage -- read message from standard input do the from stuffing
1N/A** and forward to /bin/mail, Being sure to delete any
1N/A** content-length headers (/bin/mail recalculates them).
1N/A**
1N/A**
1N/A** Parameters:
1N/A** none.
1N/A**
1N/A**
1N/A** Side Effects:
1N/A** Reads first line from standard input.
1N/A*/
1N/A
1N/A#define L_HEADER "Content-Length:"
1N/A#define LL_HEADER 15
1N/A
1N/Aint
1N/Asendmessage(from)
1N/Achar *from;
1N/A{
1N/A static char line[MAXLINE];
1N/A static char command[MAXLINE];
1N/A bool in_body = FALSE;
1N/A FILE *mail_fp;
1N/A static char user_name[L_cuserid];
1N/A
1N/A if (from == NULL)
1N/A from = cuserid(user_name);
1N/A
1N/A snprintf(command, sizeof (command), "/bin/mail -f %s -d %s", from,
1N/A myname);
1N/A mail_fp = popen(command, "w");
1N/A
1N/A /* read the line */
1N/A while (fgets(line, sizeof line, stdin) != NULL)
1N/A {
1N/A if (line[0] == (char)'\n') /* end of mail headers */
1N/A in_body = TRUE;
1N/A if (in_body && (strncmp(line, "From ", 5) == 0))
1N/A fprintf(mail_fp, ">");
1N/A if (in_body || (strncasecmp(line, L_HEADER, LL_HEADER) != 0))
1N/A fputs(line, mail_fp);
1N/A }
1N/A return (pclose(mail_fp));
1N/A}
1N/A
1N/Achar *
1N/Agetfrom(shortp)
1N/Achar **shortp;
1N/A{
1N/A static char line[MAXLINE];
1N/A register char *p, *start, *at, *bang;
1N/A char saveat;
1N/A
1N/A /* read the from line */
1N/A if (fgets(line, sizeof line, stdin) == NULL ||
1N/A strncmp(line, "From ", 5) != NULL)
1N/A {
1N/A usrerr("No initial From line");
1N/A exit(EX_USAGE);
1N/A }
1N/A
1N/A /* find the end of the sender address and terminate it */
1N/A start = &line[5];
1N/A p = strchr(start, ' ');
1N/A if (p == NULL)
1N/A {
1N/A usrerr("Funny From line '%s'", line);
1N/A exit(EX_USAGE);
1N/A }
1N/A *p = '\0';
1N/A
1N/A /*
1N/A * Strip all but the rightmost UUCP host
1N/A * to prevent loops due to forwarding.
1N/A * Start searching leftward from the leftmost '@'.
1N/A * a!b!c!d yields a short name of c!d
1N/A * a!b!c!d@e yields a short name of c!d@e
1N/A * e@a!b!c yields the same short name
1N/A */
1N/A#ifdef VDEBUG
1N/Aprintf("start='%s'\n", start);
1N/A#endif /* VDEBUG */
1N/A *shortp = start; /* assume whole addr */
1N/A if ((at = strchr(start, '@')) == NULL) /* leftmost '@' */
1N/A at = p; /* if none, use end of addr */
1N/A saveat = *at;
1N/A *at = '\0';
1N/A if ((bang = strrchr(start, '!')) != NULL) { /* rightmost '!' */
1N/A char *bang2;
1N/A *bang = '\0';
1N/A if ((bang2 = strrchr(start, '!')) != NULL) /* 2nd rightmost '!' */
1N/A *shortp = bang2 + 1; /* move past ! */
1N/A *bang = '!';
1N/A }
1N/A *at = saveat;
1N/A#ifdef VDEBUG
1N/Aprintf("place='%s'\n", *shortp);
1N/A#endif /* VDEBUG */
1N/A
1N/A /* return the sender address */
1N/A return newstr(start);
1N/A}
1N/A
1N/A/*
1N/A** USRERR -- print user error
1N/A**
1N/A** Parameters:
1N/A** f -- format.
1N/A**
1N/A** Returns:
1N/A** none.
1N/A**
1N/A** Side Effects:
1N/A** none.
1N/A*/
1N/A
1N/Avoid
1N/Ausrerr(const char *f, ...)
1N/A{
1N/A va_list alist;
1N/A
1N/A va_start(alist, f);
1N/A (void) fprintf(stderr, "mailcompat: ");
1N/A (void) vfprintf(stderr, f, alist);
1N/A (void) fprintf(stderr, "\n");
1N/A va_end(alist);
1N/A}
1N/A
1N/A/*
1N/A** NEWSTR -- copy a string
1N/A**
1N/A** Parameters:
1N/A** s -- the string to copy.
1N/A**
1N/A** Returns:
1N/A** A copy of the string.
1N/A**
1N/A** Side Effects:
1N/A** none.
1N/A*/
1N/A
1N/Achar *
1N/Anewstr(s)
1N/A char *s;
1N/A{
1N/A char *p;
1N/A size_t psize = strlen(s) + 1;
1N/A
1N/A p = malloc(psize);
1N/A if (p == NULL)
1N/A {
1N/A usrerr("newstr: cannot alloc memory");
1N/A exit(EX_OSERR);
1N/A }
1N/A strlcpy(p, s, psize);
1N/A return (p);
1N/A}
1N/A
1N/A/*
1N/A * When invoked with no arguments, we fall into an automatic installation
1N/A * mode, stepping the user through a default installation.
1N/A */
1N/Avoid
1N/AAutoInstall()
1N/A{
1N/A char forward[MAXLINE];
1N/A char line[MAXLINE];
1N/A static char user_name[L_cuserid];
1N/A FILE *f;
1N/A
1N/A myname = cuserid(user_name);
1N/A homedir = getenv("HOME");
1N/A if (homedir == NULL) {
1N/A usrerr("Home directory unknown");
1N/A exit(EX_CONFIG);
1N/A }
1N/A
1N/A printf("This program can be used to store your mail in a format\n");
1N/A printf("that you can read with SunOS 4.X based mail readers\n");
1N/A (void) strlcpy(forward, homedir, sizeof (forward));
1N/A (void) strlcat(forward, "/.forward", sizeof (forward));
1N/A f = fopen(forward, "r");
1N/A if (f) {
1N/A printf("You have a .forward file in your home directory");
1N/A printf(" containing:\n");
1N/A while (fgets(line, MAXLINE, f))
1N/A printf(" %s", line);
1N/A fclose(f);
1N/A if (!ask("Would you like to remove it and disable the mailcompat feature"))
1N/A exit(0);
1N/A if (unlink(forward))
1N/A perror("Error removing .forward file:");
1N/A else
1N/A printf("Back to normal reception of mail.\n");
1N/A exit(0);
1N/A }
1N/A
1N/A printf("To enable the mailcompat feature a \".forward\" ");
1N/A printf("file is created.\n");
1N/A if (!ask("Would you like to enable the mailcompat feature")) {
1N/A printf("OK, mailcompat feature NOT enabled.\n");
1N/A exit(0);
1N/A }
1N/A f = fopen(forward, "w");
1N/A if (f == NULL) {
1N/A perror("Error opening .forward file");
1N/A exit(EX_USAGE);
1N/A }
1N/A fprintf(f, "\"|/usr/bin/mailcompat %s\"\n", myname);
1N/A fclose(f);
1N/A printf("Mailcompat feature ENABLED.");
1N/A printf("Run mailcompat with no arguments to remove it\n");
1N/A}
1N/A
1N/A
1N/A/*
1N/A * Ask the user a question until we get a reasonable answer
1N/A */
1N/Aint
1N/Aask(prompt)
1N/A char *prompt;
1N/A{
1N/A char line[MAXLINE];
1N/A
1N/A for (;;) {
1N/A printf("%s? ", prompt);
1N/A fflush(stdout);
1N/A fgets(line, sizeof (line), stdin);
1N/A if (line[0] == 'y' || line[0] == 'Y')
1N/A return (TRUE);
1N/A if (line[0] == 'n' || line[0] == 'N')
1N/A return (FALSE);
1N/A printf("Please reply \"yes\" or \"no\" (\'y\' or \'n\')\n");
1N/A }
1N/A /* NOTREACHED */
1N/A}