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