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