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 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 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 * 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 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 * 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 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 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