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