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
main(argc,argv)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
sendmessage(from)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 *
getfrom(shortp)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
usrerr(const char * f,...)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 *
newstr(s)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
AutoInstall()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
ask(prompt)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