1955eb5e1SGarrett D'Amore /*
2955eb5e1SGarrett D'Amore * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3955eb5e1SGarrett D'Amore * Use is subject to license terms.
4955eb5e1SGarrett D'Amore *
5955eb5e1SGarrett D'Amore * Copyright (c) 1983, 1984, 1986, 1986, 1987, 1988, 1989 AT&T
6955eb5e1SGarrett D'Amore * All Rights Reserved
7955eb5e1SGarrett D'Amore */
8955eb5e1SGarrett D'Amore
9955eb5e1SGarrett D'Amore /*
10955eb5e1SGarrett D'Amore * Vacation
11955eb5e1SGarrett D'Amore * Copyright (c) 1983 Eric P. Allman
12955eb5e1SGarrett D'Amore * Berkeley, California
13955eb5e1SGarrett D'Amore *
14955eb5e1SGarrett D'Amore * Copyright (c) 1983 Regents of the University of California.
15955eb5e1SGarrett D'Amore * All rights reserved. The Berkeley software License Agreement
16955eb5e1SGarrett D'Amore * specifies the terms and conditions for redistribution.
17955eb5e1SGarrett D'Amore */
18955eb5e1SGarrett D'Amore
19955eb5e1SGarrett D'Amore #include <pwd.h>
20955eb5e1SGarrett D'Amore #include <stdio.h>
21955eb5e1SGarrett D'Amore #include <stdarg.h>
22955eb5e1SGarrett D'Amore #include <stdlib.h>
23955eb5e1SGarrett D'Amore #include <unistd.h>
24955eb5e1SGarrett D'Amore #include <sysexits.h>
25955eb5e1SGarrett D'Amore #include <string.h>
26955eb5e1SGarrett D'Amore #include <ctype.h>
27955eb5e1SGarrett D'Amore #include <sm/bitops.h>
28955eb5e1SGarrett D'Amore #include "conf.h"
29955eb5e1SGarrett D'Amore
30955eb5e1SGarrett D'Amore /*
31955eb5e1SGarrett D'Amore * MAILCOMPAT -- Deliver mail to a user's mailbox with the "From's" stuffed.
32955eb5e1SGarrett D'Amore */
33955eb5e1SGarrett D'Amore
34955eb5e1SGarrett D'Amore typedef int bool;
35955eb5e1SGarrett D'Amore
36955eb5e1SGarrett D'Amore #define FALSE 0
37955eb5e1SGarrett D'Amore #define TRUE 1
38955eb5e1SGarrett D'Amore
39955eb5e1SGarrett D'Amore bool Debug = FALSE;
40955eb5e1SGarrett D'Amore char *myname; /* person who is to have their mail filtered */
41955eb5e1SGarrett D'Amore char *homedir; /* home directory of said person */
42955eb5e1SGarrett D'Amore char *AliasList[MAXLINE]; /* list of aliases to allow */
43955eb5e1SGarrett D'Amore char *fromp;
44955eb5e1SGarrett D'Amore char *fromuser;
45955eb5e1SGarrett D'Amore int AliasCount = 0;
46955eb5e1SGarrett D'Amore
47955eb5e1SGarrett D'Amore static char *newstr();
48955eb5e1SGarrett D'Amore
49955eb5e1SGarrett D'Amore int ask(char *);
50955eb5e1SGarrett D'Amore int sendmessage(char *);
51955eb5e1SGarrett D'Amore void AutoInstall(void);
52955eb5e1SGarrett D'Amore void usrerr(const char *, ...);
53955eb5e1SGarrett D'Amore
54955eb5e1SGarrett D'Amore int
main(argc,argv)55955eb5e1SGarrett D'Amore main(argc, argv)
56955eb5e1SGarrett D'Amore int argc;
57955eb5e1SGarrett D'Amore char **argv;
58955eb5e1SGarrett D'Amore {
59955eb5e1SGarrett D'Amore register char *p;
60955eb5e1SGarrett D'Amore struct passwd *pw;
61955eb5e1SGarrett D'Amore extern char *getfrom();
62955eb5e1SGarrett D'Amore
63955eb5e1SGarrett D'Amore /* process arguments */
64955eb5e1SGarrett D'Amore while (--argc > 0 && (p = *++argv) != NULL && *p == '-')
65955eb5e1SGarrett D'Amore {
66955eb5e1SGarrett D'Amore switch (*++p)
67955eb5e1SGarrett D'Amore {
68955eb5e1SGarrett D'Amore case 'd': /* debug */
69955eb5e1SGarrett D'Amore Debug = TRUE;
70955eb5e1SGarrett D'Amore break;
71955eb5e1SGarrett D'Amore default:
72955eb5e1SGarrett D'Amore usrerr("Unknown flag -%s", p);
73955eb5e1SGarrett D'Amore exit(EX_USAGE);
74955eb5e1SGarrett D'Amore }
75955eb5e1SGarrett D'Amore }
76955eb5e1SGarrett D'Amore
77955eb5e1SGarrett D'Amore /* verify recipient argument */
78955eb5e1SGarrett D'Amore if (argc != 1)
79955eb5e1SGarrett D'Amore {
80955eb5e1SGarrett D'Amore if (argc == 0)
81955eb5e1SGarrett D'Amore AutoInstall();
82955eb5e1SGarrett D'Amore else
83955eb5e1SGarrett D'Amore usrerr("Usage: mailcompat username (or) mailcompat -r");
84955eb5e1SGarrett D'Amore exit(EX_USAGE);
85955eb5e1SGarrett D'Amore }
86955eb5e1SGarrett D'Amore
87955eb5e1SGarrett D'Amore myname = p;
88955eb5e1SGarrett D'Amore /* find user's home directory */
89955eb5e1SGarrett D'Amore pw = getpwnam(myname);
90955eb5e1SGarrett D'Amore if (pw == NULL)
91955eb5e1SGarrett D'Amore {
92955eb5e1SGarrett D'Amore usrerr("user: %s look up failed, name services outage ?", myname);
93955eb5e1SGarrett D'Amore exit(EX_TEMPFAIL);
94955eb5e1SGarrett D'Amore }
95955eb5e1SGarrett D'Amore homedir = newstr(pw->pw_dir);
96955eb5e1SGarrett D'Amore
97955eb5e1SGarrett D'Amore /* read message from standard input (just from line) */
98955eb5e1SGarrett D'Amore fromuser = getfrom(&fromp);
99955eb5e1SGarrett D'Amore return (sendmessage(fromuser));
100955eb5e1SGarrett D'Amore }
101955eb5e1SGarrett D'Amore
102955eb5e1SGarrett D'Amore /*
103955eb5e1SGarrett D'Amore ** sendmessage -- read message from standard input do the from stuffing
104955eb5e1SGarrett D'Amore ** and forward to /bin/mail, Being sure to delete any
105955eb5e1SGarrett D'Amore ** content-length headers (/bin/mail recalculates them).
106955eb5e1SGarrett D'Amore **
107955eb5e1SGarrett D'Amore **
108955eb5e1SGarrett D'Amore ** Parameters:
109955eb5e1SGarrett D'Amore ** none.
110955eb5e1SGarrett D'Amore **
111955eb5e1SGarrett D'Amore **
112955eb5e1SGarrett D'Amore ** Side Effects:
113955eb5e1SGarrett D'Amore ** Reads first line from standard input.
114955eb5e1SGarrett D'Amore */
115955eb5e1SGarrett D'Amore
116955eb5e1SGarrett D'Amore #define L_HEADER "Content-Length:"
117955eb5e1SGarrett D'Amore #define LL_HEADER 15
118955eb5e1SGarrett D'Amore
119955eb5e1SGarrett D'Amore int
sendmessage(from)120955eb5e1SGarrett D'Amore sendmessage(from)
121955eb5e1SGarrett D'Amore char *from;
122955eb5e1SGarrett D'Amore {
123955eb5e1SGarrett D'Amore static char line[MAXLINE];
124955eb5e1SGarrett D'Amore static char command[MAXLINE];
125955eb5e1SGarrett D'Amore bool in_body = FALSE;
126955eb5e1SGarrett D'Amore FILE *mail_fp;
127955eb5e1SGarrett D'Amore static char user_name[L_cuserid];
128955eb5e1SGarrett D'Amore
129955eb5e1SGarrett D'Amore if (from == NULL)
130955eb5e1SGarrett D'Amore from = cuserid(user_name);
131955eb5e1SGarrett D'Amore
132955eb5e1SGarrett D'Amore snprintf(command, sizeof (command), "/bin/mail -f %s -d %s", from,
133955eb5e1SGarrett D'Amore myname);
134955eb5e1SGarrett D'Amore mail_fp = popen(command, "w");
135955eb5e1SGarrett D'Amore
136955eb5e1SGarrett D'Amore /* read the line */
137955eb5e1SGarrett D'Amore while (fgets(line, sizeof line, stdin) != NULL)
138955eb5e1SGarrett D'Amore {
139955eb5e1SGarrett D'Amore if (line[0] == (char)'\n') /* end of mail headers */
140955eb5e1SGarrett D'Amore in_body = TRUE;
141955eb5e1SGarrett D'Amore if (in_body && (strncmp(line, "From ", 5) == 0))
142955eb5e1SGarrett D'Amore fprintf(mail_fp, ">");
143955eb5e1SGarrett D'Amore if (in_body || (strncasecmp(line, L_HEADER, LL_HEADER) != 0))
144955eb5e1SGarrett D'Amore fputs(line, mail_fp);
145955eb5e1SGarrett D'Amore }
146955eb5e1SGarrett D'Amore return (pclose(mail_fp));
147955eb5e1SGarrett D'Amore }
148955eb5e1SGarrett D'Amore
149955eb5e1SGarrett D'Amore char *
getfrom(shortp)150955eb5e1SGarrett D'Amore getfrom(shortp)
151955eb5e1SGarrett D'Amore char **shortp;
152955eb5e1SGarrett D'Amore {
153955eb5e1SGarrett D'Amore static char line[MAXLINE];
154955eb5e1SGarrett D'Amore register char *p, *start, *at, *bang;
155955eb5e1SGarrett D'Amore char saveat;
156955eb5e1SGarrett D'Amore
157955eb5e1SGarrett D'Amore /* read the from line */
158955eb5e1SGarrett D'Amore if (fgets(line, sizeof line, stdin) == NULL ||
159*fad16a7eSToomas Soome strncmp(line, "From ", 5) != 0)
160955eb5e1SGarrett D'Amore {
161955eb5e1SGarrett D'Amore usrerr("No initial From line");
162955eb5e1SGarrett D'Amore exit(EX_USAGE);
163955eb5e1SGarrett D'Amore }
164955eb5e1SGarrett D'Amore
165955eb5e1SGarrett D'Amore /* find the end of the sender address and terminate it */
166955eb5e1SGarrett D'Amore start = &line[5];
167955eb5e1SGarrett D'Amore p = strchr(start, ' ');
168955eb5e1SGarrett D'Amore if (p == NULL)
169955eb5e1SGarrett D'Amore {
170955eb5e1SGarrett D'Amore usrerr("Funny From line '%s'", line);
171955eb5e1SGarrett D'Amore exit(EX_USAGE);
172955eb5e1SGarrett D'Amore }
173955eb5e1SGarrett D'Amore *p = '\0';
174955eb5e1SGarrett D'Amore
175955eb5e1SGarrett D'Amore /*
176955eb5e1SGarrett D'Amore * Strip all but the rightmost UUCP host
177955eb5e1SGarrett D'Amore * to prevent loops due to forwarding.
178955eb5e1SGarrett D'Amore * Start searching leftward from the leftmost '@'.
179955eb5e1SGarrett D'Amore * a!b!c!d yields a short name of c!d
180955eb5e1SGarrett D'Amore * a!b!c!d@e yields a short name of c!d@e
181955eb5e1SGarrett D'Amore * e@a!b!c yields the same short name
182955eb5e1SGarrett D'Amore */
183955eb5e1SGarrett D'Amore #ifdef VDEBUG
184955eb5e1SGarrett D'Amore printf("start='%s'\n", start);
185955eb5e1SGarrett D'Amore #endif /* VDEBUG */
186955eb5e1SGarrett D'Amore *shortp = start; /* assume whole addr */
187955eb5e1SGarrett D'Amore if ((at = strchr(start, '@')) == NULL) /* leftmost '@' */
188955eb5e1SGarrett D'Amore at = p; /* if none, use end of addr */
189955eb5e1SGarrett D'Amore saveat = *at;
190955eb5e1SGarrett D'Amore *at = '\0';
191955eb5e1SGarrett D'Amore if ((bang = strrchr(start, '!')) != NULL) { /* rightmost '!' */
192955eb5e1SGarrett D'Amore char *bang2;
193955eb5e1SGarrett D'Amore *bang = '\0';
194955eb5e1SGarrett D'Amore if ((bang2 = strrchr(start, '!')) != NULL) /* 2nd rightmost '!' */
195955eb5e1SGarrett D'Amore *shortp = bang2 + 1; /* move past ! */
196955eb5e1SGarrett D'Amore *bang = '!';
197955eb5e1SGarrett D'Amore }
198955eb5e1SGarrett D'Amore *at = saveat;
199955eb5e1SGarrett D'Amore #ifdef VDEBUG
200955eb5e1SGarrett D'Amore printf("place='%s'\n", *shortp);
201955eb5e1SGarrett D'Amore #endif /* VDEBUG */
202955eb5e1SGarrett D'Amore
203955eb5e1SGarrett D'Amore /* return the sender address */
204955eb5e1SGarrett D'Amore return newstr(start);
205955eb5e1SGarrett D'Amore }
206955eb5e1SGarrett D'Amore
207955eb5e1SGarrett D'Amore /*
208955eb5e1SGarrett D'Amore ** USRERR -- print user error
209955eb5e1SGarrett D'Amore **
210955eb5e1SGarrett D'Amore ** Parameters:
211955eb5e1SGarrett D'Amore ** f -- format.
212955eb5e1SGarrett D'Amore **
213955eb5e1SGarrett D'Amore ** Returns:
214955eb5e1SGarrett D'Amore ** none.
215955eb5e1SGarrett D'Amore **
216955eb5e1SGarrett D'Amore ** Side Effects:
217955eb5e1SGarrett D'Amore ** none.
218955eb5e1SGarrett D'Amore */
219955eb5e1SGarrett D'Amore
220955eb5e1SGarrett D'Amore void
usrerr(const char * f,...)221955eb5e1SGarrett D'Amore usrerr(const char *f, ...)
222955eb5e1SGarrett D'Amore {
223955eb5e1SGarrett D'Amore va_list alist;
224955eb5e1SGarrett D'Amore
225955eb5e1SGarrett D'Amore va_start(alist, f);
226955eb5e1SGarrett D'Amore (void) fprintf(stderr, "mailcompat: ");
227955eb5e1SGarrett D'Amore (void) vfprintf(stderr, f, alist);
228955eb5e1SGarrett D'Amore (void) fprintf(stderr, "\n");
229955eb5e1SGarrett D'Amore va_end(alist);
230955eb5e1SGarrett D'Amore }
231955eb5e1SGarrett D'Amore
232955eb5e1SGarrett D'Amore /*
233955eb5e1SGarrett D'Amore ** NEWSTR -- copy a string
234955eb5e1SGarrett D'Amore **
235955eb5e1SGarrett D'Amore ** Parameters:
236955eb5e1SGarrett D'Amore ** s -- the string to copy.
237955eb5e1SGarrett D'Amore **
238955eb5e1SGarrett D'Amore ** Returns:
239955eb5e1SGarrett D'Amore ** A copy of the string.
240955eb5e1SGarrett D'Amore **
241955eb5e1SGarrett D'Amore ** Side Effects:
242955eb5e1SGarrett D'Amore ** none.
243955eb5e1SGarrett D'Amore */
244955eb5e1SGarrett D'Amore
245955eb5e1SGarrett D'Amore char *
newstr(s)246955eb5e1SGarrett D'Amore newstr(s)
247955eb5e1SGarrett D'Amore char *s;
248955eb5e1SGarrett D'Amore {
249955eb5e1SGarrett D'Amore char *p;
250955eb5e1SGarrett D'Amore size_t psize = strlen(s) + 1;
251955eb5e1SGarrett D'Amore
252955eb5e1SGarrett D'Amore p = malloc(psize);
253955eb5e1SGarrett D'Amore if (p == NULL)
254955eb5e1SGarrett D'Amore {
255955eb5e1SGarrett D'Amore usrerr("newstr: cannot alloc memory");
256955eb5e1SGarrett D'Amore exit(EX_OSERR);
257955eb5e1SGarrett D'Amore }
258955eb5e1SGarrett D'Amore strlcpy(p, s, psize);
259955eb5e1SGarrett D'Amore return (p);
260955eb5e1SGarrett D'Amore }
261955eb5e1SGarrett D'Amore
262955eb5e1SGarrett D'Amore /*
263955eb5e1SGarrett D'Amore * When invoked with no arguments, we fall into an automatic installation
264955eb5e1SGarrett D'Amore * mode, stepping the user through a default installation.
265955eb5e1SGarrett D'Amore */
266955eb5e1SGarrett D'Amore void
AutoInstall()267955eb5e1SGarrett D'Amore AutoInstall()
268955eb5e1SGarrett D'Amore {
269955eb5e1SGarrett D'Amore char forward[MAXLINE];
270955eb5e1SGarrett D'Amore char line[MAXLINE];
271955eb5e1SGarrett D'Amore static char user_name[L_cuserid];
272955eb5e1SGarrett D'Amore FILE *f;
273955eb5e1SGarrett D'Amore
274955eb5e1SGarrett D'Amore myname = cuserid(user_name);
275955eb5e1SGarrett D'Amore homedir = getenv("HOME");
276955eb5e1SGarrett D'Amore if (homedir == NULL) {
277955eb5e1SGarrett D'Amore usrerr("Home directory unknown");
278955eb5e1SGarrett D'Amore exit(EX_CONFIG);
279955eb5e1SGarrett D'Amore }
280955eb5e1SGarrett D'Amore
281955eb5e1SGarrett D'Amore printf("This program can be used to store your mail in a format\n");
282955eb5e1SGarrett D'Amore printf("that you can read with SunOS 4.X based mail readers\n");
283955eb5e1SGarrett D'Amore (void) strlcpy(forward, homedir, sizeof (forward));
284955eb5e1SGarrett D'Amore (void) strlcat(forward, "/.forward", sizeof (forward));
285955eb5e1SGarrett D'Amore f = fopen(forward, "r");
286955eb5e1SGarrett D'Amore if (f) {
287955eb5e1SGarrett D'Amore printf("You have a .forward file in your home directory");
288955eb5e1SGarrett D'Amore printf(" containing:\n");
289955eb5e1SGarrett D'Amore while (fgets(line, MAXLINE, f))
290955eb5e1SGarrett D'Amore printf(" %s", line);
291955eb5e1SGarrett D'Amore fclose(f);
292955eb5e1SGarrett D'Amore if (!ask("Would you like to remove it and disable the mailcompat feature"))
293955eb5e1SGarrett D'Amore exit(0);
294955eb5e1SGarrett D'Amore if (unlink(forward))
295955eb5e1SGarrett D'Amore perror("Error removing .forward file:");
296955eb5e1SGarrett D'Amore else
297955eb5e1SGarrett D'Amore printf("Back to normal reception of mail.\n");
298955eb5e1SGarrett D'Amore exit(0);
299955eb5e1SGarrett D'Amore }
300955eb5e1SGarrett D'Amore
301955eb5e1SGarrett D'Amore printf("To enable the mailcompat feature a \".forward\" ");
302955eb5e1SGarrett D'Amore printf("file is created.\n");
303955eb5e1SGarrett D'Amore if (!ask("Would you like to enable the mailcompat feature")) {
304955eb5e1SGarrett D'Amore printf("OK, mailcompat feature NOT enabled.\n");
305955eb5e1SGarrett D'Amore exit(0);
306955eb5e1SGarrett D'Amore }
307955eb5e1SGarrett D'Amore f = fopen(forward, "w");
308955eb5e1SGarrett D'Amore if (f == NULL) {
309955eb5e1SGarrett D'Amore perror("Error opening .forward file");
310955eb5e1SGarrett D'Amore exit(EX_USAGE);
311955eb5e1SGarrett D'Amore }
312955eb5e1SGarrett D'Amore fprintf(f, "\"|/usr/bin/mailcompat %s\"\n", myname);
313955eb5e1SGarrett D'Amore fclose(f);
314955eb5e1SGarrett D'Amore printf("Mailcompat feature ENABLED.");
315955eb5e1SGarrett D'Amore printf("Run mailcompat with no arguments to remove it\n");
316955eb5e1SGarrett D'Amore }
317955eb5e1SGarrett D'Amore
318955eb5e1SGarrett D'Amore
319955eb5e1SGarrett D'Amore /*
320955eb5e1SGarrett D'Amore * Ask the user a question until we get a reasonable answer
321955eb5e1SGarrett D'Amore */
322955eb5e1SGarrett D'Amore int
ask(prompt)323955eb5e1SGarrett D'Amore ask(prompt)
324955eb5e1SGarrett D'Amore char *prompt;
325955eb5e1SGarrett D'Amore {
326955eb5e1SGarrett D'Amore char line[MAXLINE];
327955eb5e1SGarrett D'Amore
328955eb5e1SGarrett D'Amore for (;;) {
329955eb5e1SGarrett D'Amore printf("%s? ", prompt);
330955eb5e1SGarrett D'Amore fflush(stdout);
331955eb5e1SGarrett D'Amore fgets(line, sizeof (line), stdin);
332955eb5e1SGarrett D'Amore if (line[0] == 'y' || line[0] == 'Y')
333955eb5e1SGarrett D'Amore return (TRUE);
334955eb5e1SGarrett D'Amore if (line[0] == 'n' || line[0] == 'N')
335955eb5e1SGarrett D'Amore return (FALSE);
336955eb5e1SGarrett D'Amore printf("Please reply \"yes\" or \"no\" (\'y\' or \'n\')\n");
337955eb5e1SGarrett D'Amore }
338955eb5e1SGarrett D'Amore /* NOTREACHED */
339955eb5e1SGarrett D'Amore }
340