1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate * 5*7c478bd9Sstevel@tonic-gate * Copyright (c) 1983, 1984, 1986, 1986, 1987, 1988, 1989 AT&T 6*7c478bd9Sstevel@tonic-gate * All Rights Reserved 7*7c478bd9Sstevel@tonic-gate */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Vacation 11*7c478bd9Sstevel@tonic-gate * Copyright (c) 1983 Eric P. Allman 12*7c478bd9Sstevel@tonic-gate * Berkeley, California 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * Copyright (c) 1983 Regents of the University of California. 15*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 16*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 17*7c478bd9Sstevel@tonic-gate */ 18*7c478bd9Sstevel@tonic-gate 19*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 20*7c478bd9Sstevel@tonic-gate 21*7c478bd9Sstevel@tonic-gate #include <pwd.h> 22*7c478bd9Sstevel@tonic-gate #include <stdio.h> 23*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 24*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 25*7c478bd9Sstevel@tonic-gate #include <unistd.h> 26*7c478bd9Sstevel@tonic-gate #include <sysexits.h> 27*7c478bd9Sstevel@tonic-gate #include <string.h> 28*7c478bd9Sstevel@tonic-gate #include <ctype.h> 29*7c478bd9Sstevel@tonic-gate #include "conf.h" 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate /* 32*7c478bd9Sstevel@tonic-gate * MAILCOMPAT -- Deliver mail to a user's mailbox with the "From's" stuffed. 33*7c478bd9Sstevel@tonic-gate */ 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate typedef int bool; 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #define FALSE 0 38*7c478bd9Sstevel@tonic-gate #define TRUE 1 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate bool Debug = FALSE; 41*7c478bd9Sstevel@tonic-gate char *myname; /* person who is to have their mail filtered */ 42*7c478bd9Sstevel@tonic-gate char *homedir; /* home directory of said person */ 43*7c478bd9Sstevel@tonic-gate char *AliasList[MAXLINE]; /* list of aliases to allow */ 44*7c478bd9Sstevel@tonic-gate char *fromp; 45*7c478bd9Sstevel@tonic-gate char *fromuser; 46*7c478bd9Sstevel@tonic-gate int AliasCount = 0; 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate static char *newstr(); 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate int ask(char *); 51*7c478bd9Sstevel@tonic-gate int sendmessage(char *); 52*7c478bd9Sstevel@tonic-gate void AutoInstall(void); 53*7c478bd9Sstevel@tonic-gate void usrerr(const char *, ...); 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate int 56*7c478bd9Sstevel@tonic-gate main(argc, argv) 57*7c478bd9Sstevel@tonic-gate int argc; 58*7c478bd9Sstevel@tonic-gate char **argv; 59*7c478bd9Sstevel@tonic-gate { 60*7c478bd9Sstevel@tonic-gate register char *p; 61*7c478bd9Sstevel@tonic-gate struct passwd *pw; 62*7c478bd9Sstevel@tonic-gate extern char *getfrom(); 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate /* process arguments */ 65*7c478bd9Sstevel@tonic-gate while (--argc > 0 && (p = *++argv) != NULL && *p == '-') 66*7c478bd9Sstevel@tonic-gate { 67*7c478bd9Sstevel@tonic-gate switch (*++p) 68*7c478bd9Sstevel@tonic-gate { 69*7c478bd9Sstevel@tonic-gate case 'd': /* debug */ 70*7c478bd9Sstevel@tonic-gate Debug = TRUE; 71*7c478bd9Sstevel@tonic-gate break; 72*7c478bd9Sstevel@tonic-gate default: 73*7c478bd9Sstevel@tonic-gate usrerr("Unknown flag -%s", p); 74*7c478bd9Sstevel@tonic-gate exit(EX_USAGE); 75*7c478bd9Sstevel@tonic-gate } 76*7c478bd9Sstevel@tonic-gate } 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /* verify recipient argument */ 79*7c478bd9Sstevel@tonic-gate if (argc != 1) 80*7c478bd9Sstevel@tonic-gate { 81*7c478bd9Sstevel@tonic-gate if (argc == 0) 82*7c478bd9Sstevel@tonic-gate AutoInstall(); 83*7c478bd9Sstevel@tonic-gate else 84*7c478bd9Sstevel@tonic-gate usrerr("Usage: mailcompat username (or) mailcompat -r"); 85*7c478bd9Sstevel@tonic-gate exit(EX_USAGE); 86*7c478bd9Sstevel@tonic-gate } 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate myname = p; 89*7c478bd9Sstevel@tonic-gate /* find user's home directory */ 90*7c478bd9Sstevel@tonic-gate pw = getpwnam(myname); 91*7c478bd9Sstevel@tonic-gate if (pw == NULL) 92*7c478bd9Sstevel@tonic-gate { 93*7c478bd9Sstevel@tonic-gate usrerr("user: %s look up failed, name services outage ?", myname); 94*7c478bd9Sstevel@tonic-gate exit(EX_TEMPFAIL); 95*7c478bd9Sstevel@tonic-gate } 96*7c478bd9Sstevel@tonic-gate homedir = newstr(pw->pw_dir); 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate /* read message from standard input (just from line) */ 99*7c478bd9Sstevel@tonic-gate fromuser = getfrom(&fromp); 100*7c478bd9Sstevel@tonic-gate return (sendmessage(fromuser)); 101*7c478bd9Sstevel@tonic-gate } 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate /* 104*7c478bd9Sstevel@tonic-gate ** sendmessage -- read message from standard input do the from stuffing 105*7c478bd9Sstevel@tonic-gate ** and forward to /bin/mail, Being sure to delete any 106*7c478bd9Sstevel@tonic-gate ** content-length headers (/bin/mail recalculates them). 107*7c478bd9Sstevel@tonic-gate ** 108*7c478bd9Sstevel@tonic-gate ** 109*7c478bd9Sstevel@tonic-gate ** Parameters: 110*7c478bd9Sstevel@tonic-gate ** none. 111*7c478bd9Sstevel@tonic-gate ** 112*7c478bd9Sstevel@tonic-gate ** 113*7c478bd9Sstevel@tonic-gate ** Side Effects: 114*7c478bd9Sstevel@tonic-gate ** Reads first line from standard input. 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate #define L_HEADER "Content-Length:" 118*7c478bd9Sstevel@tonic-gate #define LL_HEADER 15 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate int 121*7c478bd9Sstevel@tonic-gate sendmessage(from) 122*7c478bd9Sstevel@tonic-gate char *from; 123*7c478bd9Sstevel@tonic-gate { 124*7c478bd9Sstevel@tonic-gate static char line[MAXLINE]; 125*7c478bd9Sstevel@tonic-gate static char command[MAXLINE]; 126*7c478bd9Sstevel@tonic-gate bool in_body = FALSE; 127*7c478bd9Sstevel@tonic-gate FILE *mail_fp; 128*7c478bd9Sstevel@tonic-gate static char user_name[L_cuserid]; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate if (from == NULL) 131*7c478bd9Sstevel@tonic-gate from = cuserid(user_name); 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate snprintf(command, sizeof (command), "/bin/mail -f %s -d %s", from, 134*7c478bd9Sstevel@tonic-gate myname); 135*7c478bd9Sstevel@tonic-gate mail_fp = popen(command, "w"); 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate /* read the line */ 138*7c478bd9Sstevel@tonic-gate while (fgets(line, sizeof line, stdin) != NULL) 139*7c478bd9Sstevel@tonic-gate { 140*7c478bd9Sstevel@tonic-gate if (line[0] == (char)'\n') /* end of mail headers */ 141*7c478bd9Sstevel@tonic-gate in_body = TRUE; 142*7c478bd9Sstevel@tonic-gate if (in_body && (strncmp(line, "From ", 5) == 0)) 143*7c478bd9Sstevel@tonic-gate fprintf(mail_fp, ">"); 144*7c478bd9Sstevel@tonic-gate if (in_body || (strncasecmp(line, L_HEADER, LL_HEADER) != 0)) 145*7c478bd9Sstevel@tonic-gate fputs(line, mail_fp); 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate return (pclose(mail_fp)); 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate char * 151*7c478bd9Sstevel@tonic-gate getfrom(shortp) 152*7c478bd9Sstevel@tonic-gate char **shortp; 153*7c478bd9Sstevel@tonic-gate { 154*7c478bd9Sstevel@tonic-gate static char line[MAXLINE]; 155*7c478bd9Sstevel@tonic-gate register char *p, *start, *at, *bang; 156*7c478bd9Sstevel@tonic-gate char saveat; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate /* read the from line */ 159*7c478bd9Sstevel@tonic-gate if (fgets(line, sizeof line, stdin) == NULL || 160*7c478bd9Sstevel@tonic-gate strncmp(line, "From ", 5) != NULL) 161*7c478bd9Sstevel@tonic-gate { 162*7c478bd9Sstevel@tonic-gate usrerr("No initial From line"); 163*7c478bd9Sstevel@tonic-gate exit(EX_USAGE); 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /* find the end of the sender address and terminate it */ 167*7c478bd9Sstevel@tonic-gate start = &line[5]; 168*7c478bd9Sstevel@tonic-gate p = strchr(start, ' '); 169*7c478bd9Sstevel@tonic-gate if (p == NULL) 170*7c478bd9Sstevel@tonic-gate { 171*7c478bd9Sstevel@tonic-gate usrerr("Funny From line '%s'", line); 172*7c478bd9Sstevel@tonic-gate exit(EX_USAGE); 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate *p = '\0'; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate /* 177*7c478bd9Sstevel@tonic-gate * Strip all but the rightmost UUCP host 178*7c478bd9Sstevel@tonic-gate * to prevent loops due to forwarding. 179*7c478bd9Sstevel@tonic-gate * Start searching leftward from the leftmost '@'. 180*7c478bd9Sstevel@tonic-gate * a!b!c!d yields a short name of c!d 181*7c478bd9Sstevel@tonic-gate * a!b!c!d@e yields a short name of c!d@e 182*7c478bd9Sstevel@tonic-gate * e@a!b!c yields the same short name 183*7c478bd9Sstevel@tonic-gate */ 184*7c478bd9Sstevel@tonic-gate #ifdef VDEBUG 185*7c478bd9Sstevel@tonic-gate printf("start='%s'\n", start); 186*7c478bd9Sstevel@tonic-gate #endif /* VDEBUG */ 187*7c478bd9Sstevel@tonic-gate *shortp = start; /* assume whole addr */ 188*7c478bd9Sstevel@tonic-gate if ((at = strchr(start, '@')) == NULL) /* leftmost '@' */ 189*7c478bd9Sstevel@tonic-gate at = p; /* if none, use end of addr */ 190*7c478bd9Sstevel@tonic-gate saveat = *at; 191*7c478bd9Sstevel@tonic-gate *at = '\0'; 192*7c478bd9Sstevel@tonic-gate if ((bang = strrchr(start, '!')) != NULL) { /* rightmost '!' */ 193*7c478bd9Sstevel@tonic-gate char *bang2; 194*7c478bd9Sstevel@tonic-gate *bang = '\0'; 195*7c478bd9Sstevel@tonic-gate if ((bang2 = strrchr(start, '!')) != NULL) /* 2nd rightmost '!' */ 196*7c478bd9Sstevel@tonic-gate *shortp = bang2 + 1; /* move past ! */ 197*7c478bd9Sstevel@tonic-gate *bang = '!'; 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate *at = saveat; 200*7c478bd9Sstevel@tonic-gate #ifdef VDEBUG 201*7c478bd9Sstevel@tonic-gate printf("place='%s'\n", *shortp); 202*7c478bd9Sstevel@tonic-gate #endif /* VDEBUG */ 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate /* return the sender address */ 205*7c478bd9Sstevel@tonic-gate return newstr(start); 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate /* 209*7c478bd9Sstevel@tonic-gate ** USRERR -- print user error 210*7c478bd9Sstevel@tonic-gate ** 211*7c478bd9Sstevel@tonic-gate ** Parameters: 212*7c478bd9Sstevel@tonic-gate ** f -- format. 213*7c478bd9Sstevel@tonic-gate ** 214*7c478bd9Sstevel@tonic-gate ** Returns: 215*7c478bd9Sstevel@tonic-gate ** none. 216*7c478bd9Sstevel@tonic-gate ** 217*7c478bd9Sstevel@tonic-gate ** Side Effects: 218*7c478bd9Sstevel@tonic-gate ** none. 219*7c478bd9Sstevel@tonic-gate */ 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate void 222*7c478bd9Sstevel@tonic-gate usrerr(const char *f, ...) 223*7c478bd9Sstevel@tonic-gate { 224*7c478bd9Sstevel@tonic-gate va_list alist; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate va_start(alist, f); 227*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "mailcompat: "); 228*7c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, f, alist); 229*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 230*7c478bd9Sstevel@tonic-gate va_end(alist); 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate /* 234*7c478bd9Sstevel@tonic-gate ** NEWSTR -- copy a string 235*7c478bd9Sstevel@tonic-gate ** 236*7c478bd9Sstevel@tonic-gate ** Parameters: 237*7c478bd9Sstevel@tonic-gate ** s -- the string to copy. 238*7c478bd9Sstevel@tonic-gate ** 239*7c478bd9Sstevel@tonic-gate ** Returns: 240*7c478bd9Sstevel@tonic-gate ** A copy of the string. 241*7c478bd9Sstevel@tonic-gate ** 242*7c478bd9Sstevel@tonic-gate ** Side Effects: 243*7c478bd9Sstevel@tonic-gate ** none. 244*7c478bd9Sstevel@tonic-gate */ 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate char * 247*7c478bd9Sstevel@tonic-gate newstr(s) 248*7c478bd9Sstevel@tonic-gate char *s; 249*7c478bd9Sstevel@tonic-gate { 250*7c478bd9Sstevel@tonic-gate char *p; 251*7c478bd9Sstevel@tonic-gate size_t psize = strlen(s) + 1; 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate p = malloc(psize); 254*7c478bd9Sstevel@tonic-gate if (p == NULL) 255*7c478bd9Sstevel@tonic-gate { 256*7c478bd9Sstevel@tonic-gate usrerr("newstr: cannot alloc memory"); 257*7c478bd9Sstevel@tonic-gate exit(EX_OSERR); 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate strlcpy(p, s, psize); 260*7c478bd9Sstevel@tonic-gate return (p); 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate /* 264*7c478bd9Sstevel@tonic-gate * When invoked with no arguments, we fall into an automatic installation 265*7c478bd9Sstevel@tonic-gate * mode, stepping the user through a default installation. 266*7c478bd9Sstevel@tonic-gate */ 267*7c478bd9Sstevel@tonic-gate void 268*7c478bd9Sstevel@tonic-gate AutoInstall() 269*7c478bd9Sstevel@tonic-gate { 270*7c478bd9Sstevel@tonic-gate char forward[MAXLINE]; 271*7c478bd9Sstevel@tonic-gate char line[MAXLINE]; 272*7c478bd9Sstevel@tonic-gate static char user_name[L_cuserid]; 273*7c478bd9Sstevel@tonic-gate FILE *f; 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate myname = cuserid(user_name); 276*7c478bd9Sstevel@tonic-gate homedir = getenv("HOME"); 277*7c478bd9Sstevel@tonic-gate if (homedir == NULL) { 278*7c478bd9Sstevel@tonic-gate usrerr("Home directory unknown"); 279*7c478bd9Sstevel@tonic-gate exit(EX_CONFIG); 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate printf("This program can be used to store your mail in a format\n"); 283*7c478bd9Sstevel@tonic-gate printf("that you can read with SunOS 4.X based mail readers\n"); 284*7c478bd9Sstevel@tonic-gate (void) strlcpy(forward, homedir, sizeof (forward)); 285*7c478bd9Sstevel@tonic-gate (void) strlcat(forward, "/.forward", sizeof (forward)); 286*7c478bd9Sstevel@tonic-gate f = fopen(forward, "r"); 287*7c478bd9Sstevel@tonic-gate if (f) { 288*7c478bd9Sstevel@tonic-gate printf("You have a .forward file in your home directory"); 289*7c478bd9Sstevel@tonic-gate printf(" containing:\n"); 290*7c478bd9Sstevel@tonic-gate while (fgets(line, MAXLINE, f)) 291*7c478bd9Sstevel@tonic-gate printf(" %s", line); 292*7c478bd9Sstevel@tonic-gate fclose(f); 293*7c478bd9Sstevel@tonic-gate if (!ask("Would you like to remove it and disable the mailcompat feature")) 294*7c478bd9Sstevel@tonic-gate exit(0); 295*7c478bd9Sstevel@tonic-gate if (unlink(forward)) 296*7c478bd9Sstevel@tonic-gate perror("Error removing .forward file:"); 297*7c478bd9Sstevel@tonic-gate else 298*7c478bd9Sstevel@tonic-gate printf("Back to normal reception of mail.\n"); 299*7c478bd9Sstevel@tonic-gate exit(0); 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate printf("To enable the mailcompat feature a \".forward\" "); 303*7c478bd9Sstevel@tonic-gate printf("file is created.\n"); 304*7c478bd9Sstevel@tonic-gate if (!ask("Would you like to enable the mailcompat feature")) { 305*7c478bd9Sstevel@tonic-gate printf("OK, mailcompat feature NOT enabled.\n"); 306*7c478bd9Sstevel@tonic-gate exit(0); 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate f = fopen(forward, "w"); 309*7c478bd9Sstevel@tonic-gate if (f == NULL) { 310*7c478bd9Sstevel@tonic-gate perror("Error opening .forward file"); 311*7c478bd9Sstevel@tonic-gate exit(EX_USAGE); 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate fprintf(f, "\"|/usr/bin/mailcompat %s\"\n", myname); 314*7c478bd9Sstevel@tonic-gate fclose(f); 315*7c478bd9Sstevel@tonic-gate printf("Mailcompat feature ENABLED."); 316*7c478bd9Sstevel@tonic-gate printf("Run mailcompat with no arguments to remove it\n"); 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate /* 321*7c478bd9Sstevel@tonic-gate * Ask the user a question until we get a reasonable answer 322*7c478bd9Sstevel@tonic-gate */ 323*7c478bd9Sstevel@tonic-gate int 324*7c478bd9Sstevel@tonic-gate ask(prompt) 325*7c478bd9Sstevel@tonic-gate char *prompt; 326*7c478bd9Sstevel@tonic-gate { 327*7c478bd9Sstevel@tonic-gate char line[MAXLINE]; 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate for (;;) { 330*7c478bd9Sstevel@tonic-gate printf("%s? ", prompt); 331*7c478bd9Sstevel@tonic-gate fflush(stdout); 332*7c478bd9Sstevel@tonic-gate fgets(line, sizeof (line), stdin); 333*7c478bd9Sstevel@tonic-gate if (line[0] == 'y' || line[0] == 'Y') 334*7c478bd9Sstevel@tonic-gate return (TRUE); 335*7c478bd9Sstevel@tonic-gate if (line[0] == 'n' || line[0] == 'N') 336*7c478bd9Sstevel@tonic-gate return (FALSE); 337*7c478bd9Sstevel@tonic-gate printf("Please reply \"yes\" or \"no\" (\'y\' or \'n\')\n"); 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 340*7c478bd9Sstevel@tonic-gate } 341