17c478bd9Sstevel@tonic-gate /*
24c031281Sjbeck * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
37c478bd9Sstevel@tonic-gate * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate *
57c478bd9Sstevel@tonic-gate * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
67c478bd9Sstevel@tonic-gate * All Rights Reserved
77c478bd9Sstevel@tonic-gate */
87c478bd9Sstevel@tonic-gate
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate * Vacation
117c478bd9Sstevel@tonic-gate * Copyright (c) 1983 Eric P. Allman
127c478bd9Sstevel@tonic-gate * Berkeley, California
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * Copyright (c) 1983 Regents of the University of California.
157c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement
167c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
177c478bd9Sstevel@tonic-gate */
187c478bd9Sstevel@tonic-gate
197c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
207c478bd9Sstevel@tonic-gate
217c478bd9Sstevel@tonic-gate #ifndef lint
227c478bd9Sstevel@tonic-gate static char SccsId[] = "%W% %E% SMI";
237c478bd9Sstevel@tonic-gate #endif /* not lint */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate #include <stdio.h>
267c478bd9Sstevel@tonic-gate #include <stdarg.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <unistd.h>
297c478bd9Sstevel@tonic-gate #include <sysexits.h>
307c478bd9Sstevel@tonic-gate #include <pwd.h>
317c478bd9Sstevel@tonic-gate #include <ndbm.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
337c478bd9Sstevel@tonic-gate #include <ctype.h>
347c478bd9Sstevel@tonic-gate #include <fcntl.h>
357c478bd9Sstevel@tonic-gate #include <strings.h>
367c478bd9Sstevel@tonic-gate #include <errno.h>
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate * VACATION -- return a message to the sender when on vacation.
407c478bd9Sstevel@tonic-gate *
417c478bd9Sstevel@tonic-gate * This program could be invoked as a message receiver
427c478bd9Sstevel@tonic-gate * when someone is on vacation. It returns a message
437c478bd9Sstevel@tonic-gate * specified by the user to whoever sent the mail, taking
447c478bd9Sstevel@tonic-gate * care not to return a message too often to prevent
457c478bd9Sstevel@tonic-gate * "I am on vacation" loops.
467c478bd9Sstevel@tonic-gate *
477c478bd9Sstevel@tonic-gate * For best operation, this program should run setuid to
487c478bd9Sstevel@tonic-gate * root or uucp or someone else that sendmail will believe
497c478bd9Sstevel@tonic-gate * a -f flag from. Otherwise, the user must be careful
507c478bd9Sstevel@tonic-gate * to include a header on his .vacation.msg file.
517c478bd9Sstevel@tonic-gate *
527c478bd9Sstevel@tonic-gate * Positional Parameters:
537c478bd9Sstevel@tonic-gate * the user to collect the vacation message from.
547c478bd9Sstevel@tonic-gate *
557c478bd9Sstevel@tonic-gate * Flag Parameters:
567c478bd9Sstevel@tonic-gate * -I initialize the database.
577c478bd9Sstevel@tonic-gate * -d turn on debugging.
587c478bd9Sstevel@tonic-gate * -tT set the timeout to T. messages arriving more
597c478bd9Sstevel@tonic-gate * often than T will be ignored to avoid loops.
607c478bd9Sstevel@tonic-gate *
617c478bd9Sstevel@tonic-gate * Side Effects:
627c478bd9Sstevel@tonic-gate * A message is sent back to the sender.
637c478bd9Sstevel@tonic-gate *
647c478bd9Sstevel@tonic-gate * Author:
657c478bd9Sstevel@tonic-gate * Eric Allman
667c478bd9Sstevel@tonic-gate * UCB/INGRES
677c478bd9Sstevel@tonic-gate */
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate #define MAXLINE 256 /* max size of a line */
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate #define ONEWEEK (60L*60L*24L*7L)
727c478bd9Sstevel@tonic-gate #define MsgFile "/.vacation.msg"
737c478bd9Sstevel@tonic-gate #define FilterFile "/.vacation.filter"
747c478bd9Sstevel@tonic-gate #define DbFileBase "/.vacation"
757c478bd9Sstevel@tonic-gate #define _PATH_TMP "/tmp/vacation.XXXXXX"
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate typedef int bool;
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate #define FALSE 0
807c478bd9Sstevel@tonic-gate #define TRUE 1
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate static time_t Timeout = ONEWEEK; /* timeout between notices per user */
837c478bd9Sstevel@tonic-gate static DBM *db;
847c478bd9Sstevel@tonic-gate static bool Debug = FALSE;
85*91c7793eSjbeck static bool ListMode = FALSE;
867c478bd9Sstevel@tonic-gate static bool AnswerAll = FALSE; /* default: answer if in To:/Cc: only */
877c478bd9Sstevel@tonic-gate static char *Subject = NULL; /* subject in message header */
887c478bd9Sstevel@tonic-gate static char *EncodedSubject = NULL; /* subject in message header */
897c478bd9Sstevel@tonic-gate static char Charset[MAXLINE]; /* for use in reply message */
907c478bd9Sstevel@tonic-gate static char *AliasList[MAXLINE]; /* list of aliases to allow */
917c478bd9Sstevel@tonic-gate static int AliasCount = 0;
927c478bd9Sstevel@tonic-gate static char *myname; /* name of person "on vacation" */
937c478bd9Sstevel@tonic-gate static char *homedir; /* home directory of said person */
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate extern time_t convtime(char *, char);
967c478bd9Sstevel@tonic-gate extern bool decode_rfc2047(char *, char *, char *);
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate static bool ask(char *);
997c478bd9Sstevel@tonic-gate static bool junkmail(char *);
1007c478bd9Sstevel@tonic-gate static bool filter_ok(char *, char *);
1017c478bd9Sstevel@tonic-gate static bool knows(char *);
1027c478bd9Sstevel@tonic-gate static bool sameword(char *, char *);
1037c478bd9Sstevel@tonic-gate static char *getfrom(char **);
1047c478bd9Sstevel@tonic-gate static char *newstr(char *);
1057c478bd9Sstevel@tonic-gate static void AutoInstall();
1067c478bd9Sstevel@tonic-gate static void initialize(char *);
1077c478bd9Sstevel@tonic-gate static void sendmessage(char *, char *, char *);
1087c478bd9Sstevel@tonic-gate static void setknows(char *);
109*91c7793eSjbeck static void dumplist();
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate void usrerr(const char *, ...);
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate int
main(argc,argv)1147c478bd9Sstevel@tonic-gate main(argc, argv)
1157c478bd9Sstevel@tonic-gate int argc;
1167c478bd9Sstevel@tonic-gate char **argv;
1177c478bd9Sstevel@tonic-gate {
1187c478bd9Sstevel@tonic-gate char *from;
1197c478bd9Sstevel@tonic-gate char *p, *at, *c;
1207c478bd9Sstevel@tonic-gate struct passwd *pw;
1217c478bd9Sstevel@tonic-gate char *shortfrom;
1227c478bd9Sstevel@tonic-gate char buf[MAXLINE];
1237c478bd9Sstevel@tonic-gate char *message_file = MsgFile;
1247c478bd9Sstevel@tonic-gate char *db_file_base = DbFileBase;
1257c478bd9Sstevel@tonic-gate char *filter_file = FilterFile;
1267c478bd9Sstevel@tonic-gate char *sender;
1277c478bd9Sstevel@tonic-gate bool sender_oob = FALSE;
1287c478bd9Sstevel@tonic-gate bool initialize_only = FALSE;
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate /* process arguments */
1317c478bd9Sstevel@tonic-gate while (--argc > 0 && (p = *++argv) != NULL && *p == '-')
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate switch (*++p)
1347c478bd9Sstevel@tonic-gate {
1357c478bd9Sstevel@tonic-gate case 'a': /* add this to list of acceptable aliases */
1367c478bd9Sstevel@tonic-gate AliasList[AliasCount++] = argv[1];
1377c478bd9Sstevel@tonic-gate if (argc > 0) {
1387c478bd9Sstevel@tonic-gate argc--; argv++;
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate break;
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate case 'd': /* debug */
1437c478bd9Sstevel@tonic-gate Debug = TRUE;
1447c478bd9Sstevel@tonic-gate break;
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate case 'e': /* alternate filter file */
1477c478bd9Sstevel@tonic-gate filter_file = argv[1];
1487c478bd9Sstevel@tonic-gate if (argc > 0) {
1497c478bd9Sstevel@tonic-gate argc--; argv++;
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate break;
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate case 'f': /* alternate database file name base */
1547c478bd9Sstevel@tonic-gate db_file_base = argv[1];
1557c478bd9Sstevel@tonic-gate if (argc > 0) {
1567c478bd9Sstevel@tonic-gate argc--; argv++;
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate break;
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate case 'I': /* initialize */
1617c478bd9Sstevel@tonic-gate initialize_only = TRUE;
1627c478bd9Sstevel@tonic-gate break;
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate case 'j': /* answer all mail, even if not in To/Cc */
1657c478bd9Sstevel@tonic-gate AnswerAll = TRUE;
1667c478bd9Sstevel@tonic-gate break;
1677c478bd9Sstevel@tonic-gate
168*91c7793eSjbeck case 'l': /* list all respondees */
169*91c7793eSjbeck ListMode = TRUE;
170*91c7793eSjbeck break;
171*91c7793eSjbeck
1727c478bd9Sstevel@tonic-gate case 'm': /* alternate message file */
1737c478bd9Sstevel@tonic-gate message_file = argv[1];
1747c478bd9Sstevel@tonic-gate if (argc > 0) {
1757c478bd9Sstevel@tonic-gate argc--; argv++;
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate break;
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate case 's': /* sender: use this instead of getfrom() */
1807c478bd9Sstevel@tonic-gate sender = argv[1];
1817c478bd9Sstevel@tonic-gate sender_oob = TRUE;
1827c478bd9Sstevel@tonic-gate if (argc > 0) {
1837c478bd9Sstevel@tonic-gate argc--; argv++;
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate break;
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate case 't': /* set timeout */
1887c478bd9Sstevel@tonic-gate Timeout = convtime(++p, 'w');
1897c478bd9Sstevel@tonic-gate break;
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate default:
1927c478bd9Sstevel@tonic-gate usrerr("Unknown flag -%s", p);
1937c478bd9Sstevel@tonic-gate exit(EX_USAGE);
1947c478bd9Sstevel@tonic-gate }
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate if (initialize_only)
1987c478bd9Sstevel@tonic-gate {
1997c478bd9Sstevel@tonic-gate initialize(db_file_base);
2007c478bd9Sstevel@tonic-gate exit(EX_OK);
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate /* verify recipient argument */
204*91c7793eSjbeck if (argc == 0 && !ListMode)
2057c478bd9Sstevel@tonic-gate AutoInstall();
2067c478bd9Sstevel@tonic-gate
207*91c7793eSjbeck if (argc != 1 && !ListMode)
2087c478bd9Sstevel@tonic-gate {
209*91c7793eSjbeck usrerr("Usage:\tvacation username\n\tvacation -I\n"
210*91c7793eSjbeck "\tvacation -l");
2117c478bd9Sstevel@tonic-gate exit(EX_USAGE);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate myname = p;
2157c478bd9Sstevel@tonic-gate Charset[0] = '\0';
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate /* find user's home directory */
218*91c7793eSjbeck if (ListMode)
219*91c7793eSjbeck pw = getpwuid(getuid());
220*91c7793eSjbeck else
2217c478bd9Sstevel@tonic-gate pw = getpwnam(myname);
2227c478bd9Sstevel@tonic-gate if (pw == NULL)
2237c478bd9Sstevel@tonic-gate {
2247c478bd9Sstevel@tonic-gate usrerr("user %s look up failed, name services outage ?",
2257c478bd9Sstevel@tonic-gate myname);
2267c478bd9Sstevel@tonic-gate exit(EX_TEMPFAIL);
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate homedir = newstr(pw->pw_dir);
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s%s%s", homedir,
2317c478bd9Sstevel@tonic-gate (db_file_base[0] == '/') ? "" : "/", db_file_base);
2327c478bd9Sstevel@tonic-gate if (!(db = dbm_open(buf, O_RDWR, 0))) {
2337c478bd9Sstevel@tonic-gate usrerr("%s: %s\n", buf, strerror(errno));
2347c478bd9Sstevel@tonic-gate exit(EX_DATAERR);
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate
237*91c7793eSjbeck if (ListMode) {
238*91c7793eSjbeck dumplist();
239*91c7793eSjbeck exit(EX_OK);
240*91c7793eSjbeck }
241*91c7793eSjbeck
2427c478bd9Sstevel@tonic-gate if (sender_oob)
2437c478bd9Sstevel@tonic-gate {
2447c478bd9Sstevel@tonic-gate at = strchr(sender, '@');
2457c478bd9Sstevel@tonic-gate if (at != NULL)
2467c478bd9Sstevel@tonic-gate for (c = at + 1; *c; c++)
2477c478bd9Sstevel@tonic-gate *c = (char)tolower((char)*c);
2487c478bd9Sstevel@tonic-gate from = sender;
2497c478bd9Sstevel@tonic-gate shortfrom = sender;
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate else
2527c478bd9Sstevel@tonic-gate /* read message from standard input (just from line) */
2537c478bd9Sstevel@tonic-gate from = getfrom(&shortfrom);
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate /* check if junk mail or this person is already informed */
2567c478bd9Sstevel@tonic-gate if (!junkmail(shortfrom) && filter_ok(shortfrom, filter_file) &&
2577c478bd9Sstevel@tonic-gate !knows(shortfrom))
2587c478bd9Sstevel@tonic-gate {
2597c478bd9Sstevel@tonic-gate /* mark this person as knowing */
2607c478bd9Sstevel@tonic-gate setknows(shortfrom);
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate /* send the message back */
2637c478bd9Sstevel@tonic-gate (void) strlcpy(buf, homedir, sizeof (buf));
2647c478bd9Sstevel@tonic-gate if (message_file[0] != '/')
2657c478bd9Sstevel@tonic-gate (void) strlcat(buf, "/", sizeof (buf));
2667c478bd9Sstevel@tonic-gate (void) strlcat(buf, message_file, sizeof (buf));
2677c478bd9Sstevel@tonic-gate if (Debug)
2687c478bd9Sstevel@tonic-gate printf("Sending %s to %s\n", buf, from);
2697c478bd9Sstevel@tonic-gate else
2707c478bd9Sstevel@tonic-gate {
2717c478bd9Sstevel@tonic-gate sendmessage(buf, from, myname);
2727c478bd9Sstevel@tonic-gate /*NOTREACHED*/
2737c478bd9Sstevel@tonic-gate }
2747c478bd9Sstevel@tonic-gate }
2754c031281Sjbeck while (fgets(buf, MAXLINE, stdin) != NULL)
2764c031281Sjbeck continue; /* drain input */
2777c478bd9Sstevel@tonic-gate return (EX_OK);
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate
280*91c7793eSjbeck struct entry {
281*91c7793eSjbeck time_t when;
282*91c7793eSjbeck long when_size;
283*91c7793eSjbeck char *who;
284*91c7793eSjbeck long who_size;
285*91c7793eSjbeck struct entry *next;
286*91c7793eSjbeck struct entry *prev;
287*91c7793eSjbeck };
288*91c7793eSjbeck
289*91c7793eSjbeck static void
dump_content(key_size,key_ptr,content_size,content_ptr)290*91c7793eSjbeck dump_content(key_size, key_ptr, content_size, content_ptr)
291*91c7793eSjbeck long key_size, content_size;
292*91c7793eSjbeck char *key_ptr, *content_ptr;
293*91c7793eSjbeck {
294*91c7793eSjbeck time_t then;
295*91c7793eSjbeck
296*91c7793eSjbeck if (content_size == sizeof (then)) {
297*91c7793eSjbeck bcopy(content_ptr, (char *)&then, sizeof (then));
298*91c7793eSjbeck (void) printf("%-53.40*s: %s", (int)key_size, key_ptr,
299*91c7793eSjbeck ctime(&then));
300*91c7793eSjbeck } else {
301*91c7793eSjbeck (void) fprintf(stderr, "content size error: %d\n",
302*91c7793eSjbeck (int)content_size);
303*91c7793eSjbeck }
304*91c7793eSjbeck }
305*91c7793eSjbeck
306*91c7793eSjbeck static void
dump_all_content(first)307*91c7793eSjbeck dump_all_content(first)
308*91c7793eSjbeck struct entry *first;
309*91c7793eSjbeck {
310*91c7793eSjbeck struct entry *which;
311*91c7793eSjbeck
312*91c7793eSjbeck for (which = first; which != NULL; which = which->next) {
313*91c7793eSjbeck dump_content(which->who_size, which->who, which->when_size,
314*91c7793eSjbeck (char *)&(which->when));
315*91c7793eSjbeck }
316*91c7793eSjbeck }
317*91c7793eSjbeck
318*91c7793eSjbeck static void
dumplist()319*91c7793eSjbeck dumplist()
320*91c7793eSjbeck {
321*91c7793eSjbeck datum content, key;
322*91c7793eSjbeck struct entry *first = NULL, *last = NULL, *new_entry, *curr;
323*91c7793eSjbeck
324*91c7793eSjbeck for (key = dbm_firstkey(db); key.dptr != NULL; key = dbm_nextkey(db)) {
325*91c7793eSjbeck content = dbm_fetch(db, key);
326*91c7793eSjbeck new_entry = (struct entry *)malloc(sizeof (struct entry));
327*91c7793eSjbeck if (new_entry == NULL)
328*91c7793eSjbeck perror("out of memory");
329*91c7793eSjbeck new_entry->next = NULL;
330*91c7793eSjbeck new_entry->who = (char *)malloc(key.dsize);
331*91c7793eSjbeck if (new_entry->who == NULL)
332*91c7793eSjbeck perror("out of memory");
333*91c7793eSjbeck new_entry->who_size = key.dsize;
334*91c7793eSjbeck (void) strlcpy(new_entry->who, key.dptr, key.dsize);
335*91c7793eSjbeck bcopy(content.dptr, (char *)&(new_entry->when),
336*91c7793eSjbeck sizeof (new_entry->when));
337*91c7793eSjbeck new_entry->when_size = content.dsize;
338*91c7793eSjbeck if (first == NULL) { /* => so is last */
339*91c7793eSjbeck new_entry->prev = NULL;
340*91c7793eSjbeck new_entry->next = NULL;
341*91c7793eSjbeck first = new_entry;
342*91c7793eSjbeck last = new_entry;
343*91c7793eSjbeck } else {
344*91c7793eSjbeck for (curr = first; curr != NULL &&
345*91c7793eSjbeck new_entry->when > curr->when; curr = curr->next)
346*91c7793eSjbeck ;
347*91c7793eSjbeck if (curr == NULL) {
348*91c7793eSjbeck last->next = new_entry;
349*91c7793eSjbeck new_entry->prev = last;
350*91c7793eSjbeck new_entry->next = NULL;
351*91c7793eSjbeck last = new_entry;
352*91c7793eSjbeck } else {
353*91c7793eSjbeck new_entry->next = curr;
354*91c7793eSjbeck new_entry->prev = curr->prev;
355*91c7793eSjbeck if (curr->prev == NULL)
356*91c7793eSjbeck first = new_entry;
357*91c7793eSjbeck else
358*91c7793eSjbeck curr->prev->next = new_entry;
359*91c7793eSjbeck curr->prev = new_entry;
360*91c7793eSjbeck }
361*91c7793eSjbeck }
362*91c7793eSjbeck }
363*91c7793eSjbeck dump_all_content(first);
364*91c7793eSjbeck dbm_close(db);
365*91c7793eSjbeck }
366*91c7793eSjbeck
3677c478bd9Sstevel@tonic-gate /*
3687c478bd9Sstevel@tonic-gate * GETFROM -- read message from standard input and return sender
3697c478bd9Sstevel@tonic-gate *
3707c478bd9Sstevel@tonic-gate * Parameters:
3717c478bd9Sstevel@tonic-gate * none.
3727c478bd9Sstevel@tonic-gate *
3737c478bd9Sstevel@tonic-gate * Returns:
3747c478bd9Sstevel@tonic-gate * pointer to the sender address.
3757c478bd9Sstevel@tonic-gate *
3767c478bd9Sstevel@tonic-gate * Side Effects:
3777c478bd9Sstevel@tonic-gate * Reads first line from standard input.
3787c478bd9Sstevel@tonic-gate */
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate static char *
getfrom(shortp)3817c478bd9Sstevel@tonic-gate getfrom(shortp)
3827c478bd9Sstevel@tonic-gate char **shortp;
3837c478bd9Sstevel@tonic-gate {
3847c478bd9Sstevel@tonic-gate static char line[MAXLINE];
3857c478bd9Sstevel@tonic-gate char *p, *start, *at, *bang, *c;
3867c478bd9Sstevel@tonic-gate char saveat;
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate /* read the from line */
3897c478bd9Sstevel@tonic-gate if (fgets(line, sizeof (line), stdin) == NULL ||
3907c478bd9Sstevel@tonic-gate strncmp(line, "From ", 5) != NULL)
3917c478bd9Sstevel@tonic-gate {
3927c478bd9Sstevel@tonic-gate usrerr("No initial From line");
3937c478bd9Sstevel@tonic-gate exit(EX_PROTOCOL);
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate /* find the end of the sender address and terminate it */
3977c478bd9Sstevel@tonic-gate start = &line[5];
3987c478bd9Sstevel@tonic-gate p = strchr(start, ' ');
3997c478bd9Sstevel@tonic-gate if (p == NULL)
4007c478bd9Sstevel@tonic-gate {
4017c478bd9Sstevel@tonic-gate usrerr("Funny From line '%s'", line);
4027c478bd9Sstevel@tonic-gate exit(EX_PROTOCOL);
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate *p = '\0';
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate /*
4077c478bd9Sstevel@tonic-gate * Strip all but the rightmost UUCP host
4087c478bd9Sstevel@tonic-gate * to prevent loops due to forwarding.
4097c478bd9Sstevel@tonic-gate * Start searching leftward from the leftmost '@'.
4107c478bd9Sstevel@tonic-gate * a!b!c!d yields a short name of c!d
4117c478bd9Sstevel@tonic-gate * a!b!c!d@e yields a short name of c!d@e
4127c478bd9Sstevel@tonic-gate * e@a!b!c yields the same short name
4137c478bd9Sstevel@tonic-gate */
4147c478bd9Sstevel@tonic-gate #ifdef VDEBUG
4157c478bd9Sstevel@tonic-gate printf("start='%s'\n", start);
4167c478bd9Sstevel@tonic-gate #endif /* VDEBUG */
4177c478bd9Sstevel@tonic-gate *shortp = start; /* assume whole addr */
4187c478bd9Sstevel@tonic-gate if ((at = strchr(start, '@')) == NULL) /* leftmost '@' */
4197c478bd9Sstevel@tonic-gate at = p; /* if none, use end of addr */
4207c478bd9Sstevel@tonic-gate saveat = *at;
4217c478bd9Sstevel@tonic-gate *at = '\0';
4227c478bd9Sstevel@tonic-gate if ((bang = strrchr(start, '!')) != NULL) { /* rightmost '!' */
4237c478bd9Sstevel@tonic-gate char *bang2;
4247c478bd9Sstevel@tonic-gate *bang = '\0';
4257c478bd9Sstevel@tonic-gate /* 2nd rightmost '!' */
4267c478bd9Sstevel@tonic-gate if ((bang2 = strrchr(start, '!')) != NULL)
4277c478bd9Sstevel@tonic-gate *shortp = bang2 + 1; /* move past ! */
4287c478bd9Sstevel@tonic-gate *bang = '!';
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate *at = saveat;
4317c478bd9Sstevel@tonic-gate #ifdef VDEBUG
4327c478bd9Sstevel@tonic-gate printf("place='%s'\n", *shortp);
4337c478bd9Sstevel@tonic-gate #endif /* VDEBUG */
4347c478bd9Sstevel@tonic-gate for (c = at + 1; *c; c++)
4357c478bd9Sstevel@tonic-gate *c = (char)tolower((char)*c);
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate /* return the sender address */
4387c478bd9Sstevel@tonic-gate return (start);
4397c478bd9Sstevel@tonic-gate }
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate /*
4427c478bd9Sstevel@tonic-gate * JUNKMAIL -- read the header and tell us if this is junk/bulk mail.
4437c478bd9Sstevel@tonic-gate *
4447c478bd9Sstevel@tonic-gate * Parameters:
4457c478bd9Sstevel@tonic-gate * from -- the Return-Path of the sender. We assume that
4467c478bd9Sstevel@tonic-gate * anything from "*-REQUEST@*" is bulk mail.
4477c478bd9Sstevel@tonic-gate *
4487c478bd9Sstevel@tonic-gate * Returns:
4497c478bd9Sstevel@tonic-gate * TRUE -- if this is junk or bulk mail (that is, if the
4507c478bd9Sstevel@tonic-gate * sender shouldn't receive a response).
4517c478bd9Sstevel@tonic-gate * FALSE -- if the sender deserves a response.
4527c478bd9Sstevel@tonic-gate *
4537c478bd9Sstevel@tonic-gate * Side Effects:
4547c478bd9Sstevel@tonic-gate * May read the header from standard input. When this
4557c478bd9Sstevel@tonic-gate * returns the position on stdin is undefined.
4567c478bd9Sstevel@tonic-gate */
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate static bool
junkmail(from)4597c478bd9Sstevel@tonic-gate junkmail(from)
4607c478bd9Sstevel@tonic-gate char *from;
4617c478bd9Sstevel@tonic-gate {
4627c478bd9Sstevel@tonic-gate register char *p;
4637c478bd9Sstevel@tonic-gate char buf[MAXLINE+1];
4647c478bd9Sstevel@tonic-gate bool inside, onlist;
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate /* test for inhuman sender */
4677c478bd9Sstevel@tonic-gate p = strrchr(from, '@');
4687c478bd9Sstevel@tonic-gate if (p != NULL)
4697c478bd9Sstevel@tonic-gate {
4707c478bd9Sstevel@tonic-gate *p = '\0';
4717c478bd9Sstevel@tonic-gate if (sameword(&p[-8], "-REQUEST") ||
4727c478bd9Sstevel@tonic-gate sameword(&p[-10], "Postmaster") ||
4737c478bd9Sstevel@tonic-gate sameword(&p[-13], "MAILER-DAEMON"))
4747c478bd9Sstevel@tonic-gate {
4757c478bd9Sstevel@tonic-gate *p = '@';
4767c478bd9Sstevel@tonic-gate return (TRUE);
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate *p = '@';
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate
4817c478bd9Sstevel@tonic-gate #define Delims " \n\t:,:;()<>@!"
4827c478bd9Sstevel@tonic-gate
4837c478bd9Sstevel@tonic-gate /* read the header looking for "interesting" lines */
4847c478bd9Sstevel@tonic-gate inside = FALSE;
4857c478bd9Sstevel@tonic-gate onlist = FALSE;
4867c478bd9Sstevel@tonic-gate while (fgets(buf, MAXLINE, stdin) != NULL && buf[0] != '\n')
4877c478bd9Sstevel@tonic-gate {
4887c478bd9Sstevel@tonic-gate if (buf[0] != ' ' && buf[0] != '\t' && strchr(buf, ':') == NULL)
4897c478bd9Sstevel@tonic-gate return (FALSE); /* no header found */
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate p = strtok(buf, Delims);
4927c478bd9Sstevel@tonic-gate if (p == NULL)
4937c478bd9Sstevel@tonic-gate continue;
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate if (sameword(p, "To") || sameword(p, "Cc"))
4967c478bd9Sstevel@tonic-gate {
4977c478bd9Sstevel@tonic-gate inside = TRUE;
4987c478bd9Sstevel@tonic-gate p = strtok((char *)NULL, Delims);
4997c478bd9Sstevel@tonic-gate if (p == NULL)
5007c478bd9Sstevel@tonic-gate continue;
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate } else /* continuation line? */
5037c478bd9Sstevel@tonic-gate if (inside)
5047c478bd9Sstevel@tonic-gate inside = (buf[0] == ' ' || buf[0] == '\t');
5057c478bd9Sstevel@tonic-gate
5067c478bd9Sstevel@tonic-gate if (inside) {
5077c478bd9Sstevel@tonic-gate int i;
5087c478bd9Sstevel@tonic-gate
5097c478bd9Sstevel@tonic-gate do {
5107c478bd9Sstevel@tonic-gate if (sameword(p, myname))
5117c478bd9Sstevel@tonic-gate onlist = TRUE; /* I am on the list */
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate for (i = 0; i < AliasCount; i++)
5147c478bd9Sstevel@tonic-gate if (sameword(p, AliasList[i]))
5157c478bd9Sstevel@tonic-gate onlist = TRUE; /* alias on list */
5167c478bd9Sstevel@tonic-gate
5177c478bd9Sstevel@tonic-gate } while (p = strtok((char *)NULL, Delims));
5187c478bd9Sstevel@tonic-gate continue;
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate if (sameword(p, "Precedence"))
5227c478bd9Sstevel@tonic-gate {
5237c478bd9Sstevel@tonic-gate /* find the value of this field */
5247c478bd9Sstevel@tonic-gate p = strtok((char *)NULL, Delims);
5257c478bd9Sstevel@tonic-gate if (p == NULL)
5267c478bd9Sstevel@tonic-gate continue;
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate /* see if it is "junk" or "bulk" */
5297c478bd9Sstevel@tonic-gate p[4] = '\0';
5307c478bd9Sstevel@tonic-gate if (sameword(p, "junk") || sameword(p, "bulk"))
5317c478bd9Sstevel@tonic-gate return (TRUE);
5327c478bd9Sstevel@tonic-gate }
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate if (sameword(p, "Subject"))
5357c478bd9Sstevel@tonic-gate {
5367c478bd9Sstevel@tonic-gate char *decoded_subject;
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate Subject = newstr(buf+9);
5397c478bd9Sstevel@tonic-gate if (p = strrchr(Subject, '\n'))
5407c478bd9Sstevel@tonic-gate *p = '\0';
5417c478bd9Sstevel@tonic-gate EncodedSubject = newstr(Subject);
5427c478bd9Sstevel@tonic-gate decoded_subject = newstr(Subject);
5437c478bd9Sstevel@tonic-gate if (decode_rfc2047(Subject, decoded_subject, Charset))
5447c478bd9Sstevel@tonic-gate Subject = decoded_subject;
5457c478bd9Sstevel@tonic-gate else
5467c478bd9Sstevel@tonic-gate Charset[0] = '\0';
5477c478bd9Sstevel@tonic-gate if (Debug)
5487c478bd9Sstevel@tonic-gate printf("Subject=%s\n", Subject);
5497c478bd9Sstevel@tonic-gate }
5507c478bd9Sstevel@tonic-gate }
5517c478bd9Sstevel@tonic-gate if (AnswerAll)
5527c478bd9Sstevel@tonic-gate return (FALSE);
5537c478bd9Sstevel@tonic-gate else
5547c478bd9Sstevel@tonic-gate return (!onlist);
5557c478bd9Sstevel@tonic-gate }
5567c478bd9Sstevel@tonic-gate
5577c478bd9Sstevel@tonic-gate /*
5587c478bd9Sstevel@tonic-gate * FILTER_OK -- see if the Return-Path is in the filter file.
5597c478bd9Sstevel@tonic-gate * Note that a non-existent filter file means everything
5607c478bd9Sstevel@tonic-gate * is OK, but an empty file means nothing is OK.
5617c478bd9Sstevel@tonic-gate *
5627c478bd9Sstevel@tonic-gate * Parameters:
5637c478bd9Sstevel@tonic-gate * from -- the Return-Path of the sender.
5647c478bd9Sstevel@tonic-gate *
5657c478bd9Sstevel@tonic-gate * Returns:
5667c478bd9Sstevel@tonic-gate * TRUE -- if this is in the filter file
5677c478bd9Sstevel@tonic-gate * (sender should receive a response).
5687c478bd9Sstevel@tonic-gate * FALSE -- if the sender does not deserve a response.
5697c478bd9Sstevel@tonic-gate */
5707c478bd9Sstevel@tonic-gate
5717c478bd9Sstevel@tonic-gate static bool
filter_ok(from,filter_file)5727c478bd9Sstevel@tonic-gate filter_ok(from, filter_file)
5737c478bd9Sstevel@tonic-gate char *from;
5747c478bd9Sstevel@tonic-gate char *filter_file;
5757c478bd9Sstevel@tonic-gate {
5767c478bd9Sstevel@tonic-gate char file[MAXLINE];
5777c478bd9Sstevel@tonic-gate char line[MAXLINE];
578d5e7c3fcSgww char *match_start;
5797c478bd9Sstevel@tonic-gate size_t line_len, from_len;
5807c478bd9Sstevel@tonic-gate bool result = FALSE;
581d5e7c3fcSgww bool negated = FALSE;
5827c478bd9Sstevel@tonic-gate FILE *f;
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate from_len = strlen(from);
5857c478bd9Sstevel@tonic-gate (void) strlcpy(file, homedir, sizeof (file));
5867c478bd9Sstevel@tonic-gate if (filter_file[0] != '/')
5877c478bd9Sstevel@tonic-gate (void) strlcat(file, "/", sizeof (file));
5887c478bd9Sstevel@tonic-gate (void) strlcat(file, filter_file, sizeof (file));
5897c478bd9Sstevel@tonic-gate f = fopen(file, "r");
5907c478bd9Sstevel@tonic-gate if (f == NULL) {
5917c478bd9Sstevel@tonic-gate /*
5927c478bd9Sstevel@tonic-gate * If the file does not exist, then there is no filter to
5937c478bd9Sstevel@tonic-gate * apply, so we simply return TRUE.
5947c478bd9Sstevel@tonic-gate */
5957c478bd9Sstevel@tonic-gate if (Debug)
5967c478bd9Sstevel@tonic-gate (void) printf("%s does not exist, filter ok.\n",
5977c478bd9Sstevel@tonic-gate file);
5987c478bd9Sstevel@tonic-gate return (TRUE);
5997c478bd9Sstevel@tonic-gate }
6007c478bd9Sstevel@tonic-gate while (fgets(line, MAXLINE, f)) {
6017c478bd9Sstevel@tonic-gate line_len = strlen(line);
6027c478bd9Sstevel@tonic-gate /* zero out trailing newline */
6037c478bd9Sstevel@tonic-gate if (line[line_len - 1] == '\n')
6047c478bd9Sstevel@tonic-gate line[--line_len] = '\0';
6057c478bd9Sstevel@tonic-gate /* skip blank lines */
6067c478bd9Sstevel@tonic-gate if (line_len == 0)
6077c478bd9Sstevel@tonic-gate continue;
6087c478bd9Sstevel@tonic-gate /* skip comment lines */
6097c478bd9Sstevel@tonic-gate if (line[0] == '#')
6107c478bd9Sstevel@tonic-gate continue;
611d5e7c3fcSgww if (line[0] == '!') {
612d5e7c3fcSgww negated = TRUE;
613d5e7c3fcSgww match_start = &line[1];
614d5e7c3fcSgww line_len--;
615d5e7c3fcSgww } else {
616d5e7c3fcSgww negated = FALSE;
617d5e7c3fcSgww match_start = &line[0];
618d5e7c3fcSgww }
6197c478bd9Sstevel@tonic-gate if (strchr(line, '@') != NULL) {
6207c478bd9Sstevel@tonic-gate /* @ => full address */
621d5e7c3fcSgww if (strcasecmp(match_start, from) == 0) {
6227c478bd9Sstevel@tonic-gate result = TRUE;
6237c478bd9Sstevel@tonic-gate if (Debug)
6247c478bd9Sstevel@tonic-gate (void) printf("filter match on %s\n",
6257c478bd9Sstevel@tonic-gate line);
6267c478bd9Sstevel@tonic-gate break;
6277c478bd9Sstevel@tonic-gate }
6287c478bd9Sstevel@tonic-gate } else {
6297c478bd9Sstevel@tonic-gate /* no @ => domain */
6307c478bd9Sstevel@tonic-gate if (from_len <= line_len)
6317c478bd9Sstevel@tonic-gate continue;
6327c478bd9Sstevel@tonic-gate /*
6337c478bd9Sstevel@tonic-gate * Make sure the last part of from is the domain line
6347c478bd9Sstevel@tonic-gate * and that the character immediately preceding is an
6357c478bd9Sstevel@tonic-gate * '@' or a '.', otherwise we could get false positives
6367c478bd9Sstevel@tonic-gate * from e.g. twinsun.com for sun.com .
6377c478bd9Sstevel@tonic-gate */
638d5e7c3fcSgww if (strncasecmp(&from[from_len - line_len],
639d5e7c3fcSgww match_start, line_len) == 0 &&
6407c478bd9Sstevel@tonic-gate (from[from_len - line_len -1] == '@' ||
6417c478bd9Sstevel@tonic-gate from[from_len - line_len -1] == '.')) {
6427c478bd9Sstevel@tonic-gate result = TRUE;
6437c478bd9Sstevel@tonic-gate if (Debug)
6447c478bd9Sstevel@tonic-gate (void) printf("filter match on %s\n",
6457c478bd9Sstevel@tonic-gate line);
6467c478bd9Sstevel@tonic-gate break;
6477c478bd9Sstevel@tonic-gate }
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate }
6507c478bd9Sstevel@tonic-gate (void) fclose(f);
6517c478bd9Sstevel@tonic-gate if (Debug && !result)
6527c478bd9Sstevel@tonic-gate (void) printf("no filter match\n");
653d5e7c3fcSgww return (!negated && result);
6547c478bd9Sstevel@tonic-gate }
6557c478bd9Sstevel@tonic-gate
6567c478bd9Sstevel@tonic-gate /*
6577c478bd9Sstevel@tonic-gate * KNOWS -- predicate telling if user has already been informed.
6587c478bd9Sstevel@tonic-gate *
6597c478bd9Sstevel@tonic-gate * Parameters:
6607c478bd9Sstevel@tonic-gate * user -- the user who sent this message.
6617c478bd9Sstevel@tonic-gate *
6627c478bd9Sstevel@tonic-gate * Returns:
6637c478bd9Sstevel@tonic-gate * TRUE if 'user' has already been informed that the
6647c478bd9Sstevel@tonic-gate * recipient is on vacation.
6657c478bd9Sstevel@tonic-gate * FALSE otherwise.
6667c478bd9Sstevel@tonic-gate *
6677c478bd9Sstevel@tonic-gate * Side Effects:
6687c478bd9Sstevel@tonic-gate * none.
6697c478bd9Sstevel@tonic-gate */
6707c478bd9Sstevel@tonic-gate
6717c478bd9Sstevel@tonic-gate static bool
knows(user)6727c478bd9Sstevel@tonic-gate knows(user)
6737c478bd9Sstevel@tonic-gate char *user;
6747c478bd9Sstevel@tonic-gate {
6757c478bd9Sstevel@tonic-gate datum key, data;
6767c478bd9Sstevel@tonic-gate time_t now, then;
6777c478bd9Sstevel@tonic-gate
6787c478bd9Sstevel@tonic-gate (void) time(&now);
6797c478bd9Sstevel@tonic-gate key.dptr = user;
6807c478bd9Sstevel@tonic-gate key.dsize = strlen(user) + 1;
6817c478bd9Sstevel@tonic-gate data = dbm_fetch(db, key);
6827c478bd9Sstevel@tonic-gate if (data.dptr == NULL)
6837c478bd9Sstevel@tonic-gate return (FALSE);
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate bcopy(data.dptr, (char *)&then, sizeof (then));
6867c478bd9Sstevel@tonic-gate if (then + Timeout < now)
6877c478bd9Sstevel@tonic-gate return (FALSE);
6887c478bd9Sstevel@tonic-gate if (Debug)
6897c478bd9Sstevel@tonic-gate printf("User %s already knows\n", user);
6907c478bd9Sstevel@tonic-gate return (TRUE);
6917c478bd9Sstevel@tonic-gate }
6927c478bd9Sstevel@tonic-gate
6937c478bd9Sstevel@tonic-gate /*
6947c478bd9Sstevel@tonic-gate * SETKNOWS -- set that this user knows about the vacation.
6957c478bd9Sstevel@tonic-gate *
6967c478bd9Sstevel@tonic-gate * Parameters:
6977c478bd9Sstevel@tonic-gate * user -- the user who should be marked.
6987c478bd9Sstevel@tonic-gate *
6997c478bd9Sstevel@tonic-gate * Returns:
7007c478bd9Sstevel@tonic-gate * none.
7017c478bd9Sstevel@tonic-gate *
7027c478bd9Sstevel@tonic-gate * Side Effects:
7037c478bd9Sstevel@tonic-gate * The dbm file is updated as appropriate.
7047c478bd9Sstevel@tonic-gate */
7057c478bd9Sstevel@tonic-gate
7067c478bd9Sstevel@tonic-gate static void
setknows(user)7077c478bd9Sstevel@tonic-gate setknows(user)
7087c478bd9Sstevel@tonic-gate char *user;
7097c478bd9Sstevel@tonic-gate {
7107c478bd9Sstevel@tonic-gate datum key, data;
7117c478bd9Sstevel@tonic-gate time_t now;
7127c478bd9Sstevel@tonic-gate
7137c478bd9Sstevel@tonic-gate key.dptr = user;
7147c478bd9Sstevel@tonic-gate key.dsize = strlen(user) + 1;
7157c478bd9Sstevel@tonic-gate (void) time(&now);
7167c478bd9Sstevel@tonic-gate data.dptr = (char *)&now;
7177c478bd9Sstevel@tonic-gate data.dsize = sizeof (now);
7187c478bd9Sstevel@tonic-gate dbm_store(db, key, data, DBM_REPLACE);
7197c478bd9Sstevel@tonic-gate }
7207c478bd9Sstevel@tonic-gate
7217c478bd9Sstevel@tonic-gate static bool
any8bitchars(line)7227c478bd9Sstevel@tonic-gate any8bitchars(line)
7237c478bd9Sstevel@tonic-gate char *line;
7247c478bd9Sstevel@tonic-gate {
7257c478bd9Sstevel@tonic-gate char *c;
7267c478bd9Sstevel@tonic-gate
7277c478bd9Sstevel@tonic-gate for (c = line; *c; c++)
7287c478bd9Sstevel@tonic-gate if (*c & 0x80)
7297c478bd9Sstevel@tonic-gate return (TRUE);
7307c478bd9Sstevel@tonic-gate return (FALSE);
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate
7337c478bd9Sstevel@tonic-gate /*
7347c478bd9Sstevel@tonic-gate * SENDMESSAGE -- send a message to a particular user.
7357c478bd9Sstevel@tonic-gate *
7367c478bd9Sstevel@tonic-gate * Parameters:
7377c478bd9Sstevel@tonic-gate * msgf -- filename containing the message.
7387c478bd9Sstevel@tonic-gate * user -- user who should receive it.
7397c478bd9Sstevel@tonic-gate *
7407c478bd9Sstevel@tonic-gate * Returns:
7417c478bd9Sstevel@tonic-gate * none.
7427c478bd9Sstevel@tonic-gate *
7437c478bd9Sstevel@tonic-gate * Side Effects:
7447c478bd9Sstevel@tonic-gate * sends mail to 'user' using /usr/lib/sendmail.
7457c478bd9Sstevel@tonic-gate */
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate static void
sendmessage(msgf,user,myname)7487c478bd9Sstevel@tonic-gate sendmessage(msgf, user, myname)
7497c478bd9Sstevel@tonic-gate char *msgf;
7507c478bd9Sstevel@tonic-gate char *user;
7517c478bd9Sstevel@tonic-gate char *myname;
7527c478bd9Sstevel@tonic-gate {
7537c478bd9Sstevel@tonic-gate FILE *f, *fpipe, *tmpf;
7547c478bd9Sstevel@tonic-gate char line[MAXLINE];
7557c478bd9Sstevel@tonic-gate char *p, *tmpf_name;
7567c478bd9Sstevel@tonic-gate int i, pipefd[2], tmpfd;
7577c478bd9Sstevel@tonic-gate bool seen8bitchars = FALSE;
7587c478bd9Sstevel@tonic-gate bool in_header = TRUE;
7597c478bd9Sstevel@tonic-gate
7607c478bd9Sstevel@tonic-gate /* find the message to send */
7617c478bd9Sstevel@tonic-gate f = fopen(msgf, "r");
7627c478bd9Sstevel@tonic-gate if (f == NULL)
7637c478bd9Sstevel@tonic-gate {
7647c478bd9Sstevel@tonic-gate f = fopen("/etc/mail/vacation.def", "r");
7657c478bd9Sstevel@tonic-gate if (f == NULL)
7667c478bd9Sstevel@tonic-gate usrerr("No message to send");
7677c478bd9Sstevel@tonic-gate exit(EX_OSFILE);
7687c478bd9Sstevel@tonic-gate }
7697c478bd9Sstevel@tonic-gate
7707c478bd9Sstevel@tonic-gate if (pipe(pipefd) < 0) {
7717c478bd9Sstevel@tonic-gate usrerr("pipe() failed");
7727c478bd9Sstevel@tonic-gate exit(EX_OSERR);
7737c478bd9Sstevel@tonic-gate }
7747c478bd9Sstevel@tonic-gate i = fork();
7757c478bd9Sstevel@tonic-gate if (i < 0) {
7767c478bd9Sstevel@tonic-gate usrerr("fork() failed");
7777c478bd9Sstevel@tonic-gate exit(EX_OSERR);
7787c478bd9Sstevel@tonic-gate }
7797c478bd9Sstevel@tonic-gate if (i == 0) {
7807c478bd9Sstevel@tonic-gate dup2(pipefd[0], 0);
7817c478bd9Sstevel@tonic-gate close(pipefd[0]);
7827c478bd9Sstevel@tonic-gate close(pipefd[1]);
7837c478bd9Sstevel@tonic-gate fclose(f);
7847c478bd9Sstevel@tonic-gate execl("/usr/lib/sendmail", "sendmail", "-eq", "-f", myname,
7857c478bd9Sstevel@tonic-gate "--", user, NULL);
7867c478bd9Sstevel@tonic-gate usrerr("can't exec /usr/lib/sendmail");
7877c478bd9Sstevel@tonic-gate exit(EX_OSERR);
7887c478bd9Sstevel@tonic-gate }
7897c478bd9Sstevel@tonic-gate close(pipefd[0]);
7907c478bd9Sstevel@tonic-gate fpipe = fdopen(pipefd[1], "w");
7917c478bd9Sstevel@tonic-gate if (fpipe == NULL) {
7927c478bd9Sstevel@tonic-gate usrerr("fdopen() failed");
7937c478bd9Sstevel@tonic-gate exit(EX_OSERR);
7947c478bd9Sstevel@tonic-gate }
7957c478bd9Sstevel@tonic-gate fprintf(fpipe, "To: %s\n", user);
7967c478bd9Sstevel@tonic-gate fputs("Auto-Submitted: auto-replied\n", fpipe);
7977c478bd9Sstevel@tonic-gate fputs("X-Mailer: vacation %I%\n", fpipe);
7987c478bd9Sstevel@tonic-gate
7997c478bd9Sstevel@tonic-gate /*
8007c478bd9Sstevel@tonic-gate * We used to write directly to the pipe. But now we need to know
8017c478bd9Sstevel@tonic-gate * what character set to use, and we need to examine the entire
8027c478bd9Sstevel@tonic-gate * message to determine this. So write to a temp file first.
8037c478bd9Sstevel@tonic-gate */
8047c478bd9Sstevel@tonic-gate tmpf_name = strdup(_PATH_TMP);
8057c478bd9Sstevel@tonic-gate if (tmpf_name == NULL) {
8067c478bd9Sstevel@tonic-gate usrerr("newstr: cannot alloc memory");
8077c478bd9Sstevel@tonic-gate exit(EX_OSERR);
8087c478bd9Sstevel@tonic-gate }
8097c478bd9Sstevel@tonic-gate tmpfd = -1;
8107c478bd9Sstevel@tonic-gate tmpfd = mkstemp(tmpf_name);
8117c478bd9Sstevel@tonic-gate if (tmpfd == -1) {
8127c478bd9Sstevel@tonic-gate usrerr("can't open temp file %s", tmpf_name);
8137c478bd9Sstevel@tonic-gate exit(EX_OSERR);
8147c478bd9Sstevel@tonic-gate }
8157c478bd9Sstevel@tonic-gate tmpf = fdopen(tmpfd, "w");
8167c478bd9Sstevel@tonic-gate if (tmpf == NULL) {
8177c478bd9Sstevel@tonic-gate usrerr("can't open temp file %s", tmpf_name);
8187c478bd9Sstevel@tonic-gate exit(EX_OSERR);
8197c478bd9Sstevel@tonic-gate }
8207c478bd9Sstevel@tonic-gate while (fgets(line, MAXLINE, f)) {
8217c478bd9Sstevel@tonic-gate /*
8227c478bd9Sstevel@tonic-gate * Check for a line with no ':' character. If it's just \n,
8237c478bd9Sstevel@tonic-gate * we're at the end of the headers and all is fine. Or if
8247c478bd9Sstevel@tonic-gate * it starts with white-space, then it's a continuation header.
8257c478bd9Sstevel@tonic-gate * Otherwise, it's the start of the body, which means the
8267c478bd9Sstevel@tonic-gate * header/body separator was skipped. So output it.
8277c478bd9Sstevel@tonic-gate */
8287c478bd9Sstevel@tonic-gate if (in_header && line[0] != '\0' && strchr(line, ':') == NULL) {
8297c478bd9Sstevel@tonic-gate if (line[0] == '\n')
8307c478bd9Sstevel@tonic-gate in_header = FALSE;
8317c478bd9Sstevel@tonic-gate else if (!isspace(line[0])) {
8327c478bd9Sstevel@tonic-gate in_header = FALSE;
8337c478bd9Sstevel@tonic-gate fputs("\n", tmpf);
8347c478bd9Sstevel@tonic-gate }
8357c478bd9Sstevel@tonic-gate }
8367c478bd9Sstevel@tonic-gate p = strchr(line, '$');
8377c478bd9Sstevel@tonic-gate if (p && strncmp(p, "$SUBJECT", 8) == 0) {
8387c478bd9Sstevel@tonic-gate *p = '\0';
8397c478bd9Sstevel@tonic-gate seen8bitchars |= any8bitchars(line);
8407c478bd9Sstevel@tonic-gate fputs(line, tmpf);
8417c478bd9Sstevel@tonic-gate if (Subject) {
8427c478bd9Sstevel@tonic-gate if (in_header)
8437c478bd9Sstevel@tonic-gate fputs(EncodedSubject, tmpf);
8447c478bd9Sstevel@tonic-gate else {
8457c478bd9Sstevel@tonic-gate seen8bitchars |= any8bitchars(Subject);
8467c478bd9Sstevel@tonic-gate fputs(Subject, tmpf);
8477c478bd9Sstevel@tonic-gate }
8487c478bd9Sstevel@tonic-gate }
8497c478bd9Sstevel@tonic-gate seen8bitchars |= any8bitchars(p+8);
8507c478bd9Sstevel@tonic-gate fputs(p+8, tmpf);
8517c478bd9Sstevel@tonic-gate continue;
8527c478bd9Sstevel@tonic-gate }
8537c478bd9Sstevel@tonic-gate seen8bitchars |= any8bitchars(line);
8547c478bd9Sstevel@tonic-gate fputs(line, tmpf);
8557c478bd9Sstevel@tonic-gate }
8567c478bd9Sstevel@tonic-gate fclose(f);
8577c478bd9Sstevel@tonic-gate fclose(tmpf);
8587c478bd9Sstevel@tonic-gate
8597c478bd9Sstevel@tonic-gate /*
8607c478bd9Sstevel@tonic-gate * If we haven't seen a funky Subject with Charset, use the default.
8617c478bd9Sstevel@tonic-gate * If we have and it's us-ascii, 8-bit chars in the message file will
8627c478bd9Sstevel@tonic-gate * still result in iso-8859-1.
8637c478bd9Sstevel@tonic-gate */
8647c478bd9Sstevel@tonic-gate if (Charset[0] == '\0')
8657c478bd9Sstevel@tonic-gate (void) strlcpy(Charset, (seen8bitchars) ? "iso-8859-1" :
8667c478bd9Sstevel@tonic-gate "us-ascii", sizeof (Charset));
8677c478bd9Sstevel@tonic-gate else if ((strcasecmp(Charset, "us-ascii") == 0) && seen8bitchars)
8687c478bd9Sstevel@tonic-gate (void) strlcpy(Charset, "iso-8859-1", sizeof (Charset));
8697c478bd9Sstevel@tonic-gate if (Debug)
8707c478bd9Sstevel@tonic-gate printf("Charset is %s\n", Charset);
8717c478bd9Sstevel@tonic-gate fprintf(fpipe, "Content-Type: text/plain; charset=%s\n", Charset);
8727c478bd9Sstevel@tonic-gate fputs("Mime-Version: 1.0\n", fpipe);
8737c478bd9Sstevel@tonic-gate
8747c478bd9Sstevel@tonic-gate /*
8757c478bd9Sstevel@tonic-gate * Now read back in from the temp file and write to the pipe.
8767c478bd9Sstevel@tonic-gate */
8777c478bd9Sstevel@tonic-gate tmpf = fopen(tmpf_name, "r");
8787c478bd9Sstevel@tonic-gate if (tmpf == NULL) {
8797c478bd9Sstevel@tonic-gate usrerr("can't open temp file %s", tmpf_name);
8807c478bd9Sstevel@tonic-gate exit(EX_OSERR);
8817c478bd9Sstevel@tonic-gate }
8827c478bd9Sstevel@tonic-gate while (fgets(line, MAXLINE, tmpf))
8837c478bd9Sstevel@tonic-gate fputs(line, fpipe);
8847c478bd9Sstevel@tonic-gate fclose(fpipe);
8857c478bd9Sstevel@tonic-gate fclose(tmpf);
8867c478bd9Sstevel@tonic-gate (void) unlink(tmpf_name);
8877c478bd9Sstevel@tonic-gate free(tmpf_name);
8887c478bd9Sstevel@tonic-gate }
8897c478bd9Sstevel@tonic-gate
8907c478bd9Sstevel@tonic-gate /*
8917c478bd9Sstevel@tonic-gate * INITIALIZE -- initialize the database before leaving for vacation
8927c478bd9Sstevel@tonic-gate *
8937c478bd9Sstevel@tonic-gate * Parameters:
8947c478bd9Sstevel@tonic-gate * none.
8957c478bd9Sstevel@tonic-gate *
8967c478bd9Sstevel@tonic-gate * Returns:
8977c478bd9Sstevel@tonic-gate * none.
8987c478bd9Sstevel@tonic-gate *
8997c478bd9Sstevel@tonic-gate * Side Effects:
9007c478bd9Sstevel@tonic-gate * Initializes the files .vacation.{pag,dir} in the
9017c478bd9Sstevel@tonic-gate * caller's home directory.
9027c478bd9Sstevel@tonic-gate */
9037c478bd9Sstevel@tonic-gate
9047c478bd9Sstevel@tonic-gate static void
initialize(db_file_base)9057c478bd9Sstevel@tonic-gate initialize(db_file_base)
9067c478bd9Sstevel@tonic-gate char *db_file_base;
9077c478bd9Sstevel@tonic-gate {
9087c478bd9Sstevel@tonic-gate char *homedir;
9097c478bd9Sstevel@tonic-gate char buf[MAXLINE];
9107c478bd9Sstevel@tonic-gate DBM *db;
9117c478bd9Sstevel@tonic-gate
9127c478bd9Sstevel@tonic-gate setgid(getgid());
9137c478bd9Sstevel@tonic-gate setuid(getuid());
9147c478bd9Sstevel@tonic-gate homedir = getenv("HOME");
9157c478bd9Sstevel@tonic-gate if (homedir == NULL) {
9167c478bd9Sstevel@tonic-gate usrerr("No home!");
9177c478bd9Sstevel@tonic-gate exit(EX_NOUSER);
9187c478bd9Sstevel@tonic-gate }
9197c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s%s%s", homedir,
9207c478bd9Sstevel@tonic-gate (db_file_base[0] == '/') ? "" : "/", db_file_base);
9217c478bd9Sstevel@tonic-gate
9227c478bd9Sstevel@tonic-gate if (!(db = dbm_open(buf, O_WRONLY|O_CREAT|O_TRUNC, 0644))) {
9237c478bd9Sstevel@tonic-gate usrerr("%s: %s\n", buf, strerror(errno));
9247c478bd9Sstevel@tonic-gate exit(EX_DATAERR);
9257c478bd9Sstevel@tonic-gate }
9267c478bd9Sstevel@tonic-gate dbm_close(db);
9277c478bd9Sstevel@tonic-gate }
9287c478bd9Sstevel@tonic-gate
9297c478bd9Sstevel@tonic-gate /*
9307c478bd9Sstevel@tonic-gate * USRERR -- print user error
9317c478bd9Sstevel@tonic-gate *
9327c478bd9Sstevel@tonic-gate * Parameters:
9337c478bd9Sstevel@tonic-gate * f -- format.
9347c478bd9Sstevel@tonic-gate *
9357c478bd9Sstevel@tonic-gate * Returns:
9367c478bd9Sstevel@tonic-gate * none.
9377c478bd9Sstevel@tonic-gate *
9387c478bd9Sstevel@tonic-gate * Side Effects:
9397c478bd9Sstevel@tonic-gate * none.
9407c478bd9Sstevel@tonic-gate */
9417c478bd9Sstevel@tonic-gate
9427c478bd9Sstevel@tonic-gate /* PRINTFLIKE1 */
9437c478bd9Sstevel@tonic-gate void
usrerr(const char * f,...)9447c478bd9Sstevel@tonic-gate usrerr(const char *f, ...)
9457c478bd9Sstevel@tonic-gate {
9467c478bd9Sstevel@tonic-gate va_list alist;
9477c478bd9Sstevel@tonic-gate
9487c478bd9Sstevel@tonic-gate va_start(alist, f);
9497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "vacation: ");
9507c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, f, alist);
9517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n");
9527c478bd9Sstevel@tonic-gate va_end(alist);
9537c478bd9Sstevel@tonic-gate }
9547c478bd9Sstevel@tonic-gate
9557c478bd9Sstevel@tonic-gate /*
9567c478bd9Sstevel@tonic-gate * NEWSTR -- copy a string
9577c478bd9Sstevel@tonic-gate *
9587c478bd9Sstevel@tonic-gate * Parameters:
9597c478bd9Sstevel@tonic-gate * s -- the string to copy.
9607c478bd9Sstevel@tonic-gate *
9617c478bd9Sstevel@tonic-gate * Returns:
9627c478bd9Sstevel@tonic-gate * A copy of the string.
9637c478bd9Sstevel@tonic-gate *
9647c478bd9Sstevel@tonic-gate * Side Effects:
9657c478bd9Sstevel@tonic-gate * none.
9667c478bd9Sstevel@tonic-gate */
9677c478bd9Sstevel@tonic-gate
9687c478bd9Sstevel@tonic-gate static char *
newstr(s)9697c478bd9Sstevel@tonic-gate newstr(s)
9707c478bd9Sstevel@tonic-gate char *s;
9717c478bd9Sstevel@tonic-gate {
9727c478bd9Sstevel@tonic-gate char *p;
9737c478bd9Sstevel@tonic-gate size_t s_sz = strlen(s);
9747c478bd9Sstevel@tonic-gate
9757c478bd9Sstevel@tonic-gate p = malloc(s_sz + 1);
9767c478bd9Sstevel@tonic-gate if (p == NULL)
9777c478bd9Sstevel@tonic-gate {
9787c478bd9Sstevel@tonic-gate usrerr("newstr: cannot alloc memory");
9797c478bd9Sstevel@tonic-gate exit(EX_OSERR);
9807c478bd9Sstevel@tonic-gate }
9817c478bd9Sstevel@tonic-gate (void) strlcpy(p, s, s_sz + 1);
9827c478bd9Sstevel@tonic-gate return (p);
9837c478bd9Sstevel@tonic-gate }
9847c478bd9Sstevel@tonic-gate
9857c478bd9Sstevel@tonic-gate /*
9867c478bd9Sstevel@tonic-gate * SAMEWORD -- return TRUE if the words are the same
9877c478bd9Sstevel@tonic-gate *
9887c478bd9Sstevel@tonic-gate * Ignores case.
9897c478bd9Sstevel@tonic-gate *
9907c478bd9Sstevel@tonic-gate * Parameters:
9917c478bd9Sstevel@tonic-gate * a, b -- the words to compare.
9927c478bd9Sstevel@tonic-gate *
9937c478bd9Sstevel@tonic-gate * Returns:
9947c478bd9Sstevel@tonic-gate * TRUE if a & b match exactly (modulo case)
9957c478bd9Sstevel@tonic-gate * FALSE otherwise.
9967c478bd9Sstevel@tonic-gate *
9977c478bd9Sstevel@tonic-gate * Side Effects:
9987c478bd9Sstevel@tonic-gate * none.
9997c478bd9Sstevel@tonic-gate */
10007c478bd9Sstevel@tonic-gate
10017c478bd9Sstevel@tonic-gate static bool
sameword(a,b)10027c478bd9Sstevel@tonic-gate sameword(a, b)
10037c478bd9Sstevel@tonic-gate register char *a, *b;
10047c478bd9Sstevel@tonic-gate {
10057c478bd9Sstevel@tonic-gate char ca, cb;
10067c478bd9Sstevel@tonic-gate
10077c478bd9Sstevel@tonic-gate do
10087c478bd9Sstevel@tonic-gate {
10097c478bd9Sstevel@tonic-gate ca = *a++;
10107c478bd9Sstevel@tonic-gate cb = *b++;
10117c478bd9Sstevel@tonic-gate if (isascii(ca) && isupper(ca))
10127c478bd9Sstevel@tonic-gate ca = ca - 'A' + 'a';
10137c478bd9Sstevel@tonic-gate if (isascii(cb) && isupper(cb))
10147c478bd9Sstevel@tonic-gate cb = cb - 'A' + 'a';
10157c478bd9Sstevel@tonic-gate } while (ca != '\0' && ca == cb);
10167c478bd9Sstevel@tonic-gate return (ca == cb);
10177c478bd9Sstevel@tonic-gate }
10187c478bd9Sstevel@tonic-gate
10197c478bd9Sstevel@tonic-gate /*
10207c478bd9Sstevel@tonic-gate * When invoked with no arguments, we fall into an automatic installation
10217c478bd9Sstevel@tonic-gate * mode, stepping the user through a default installation.
10227c478bd9Sstevel@tonic-gate */
10237c478bd9Sstevel@tonic-gate
10247c478bd9Sstevel@tonic-gate static void
AutoInstall()10257c478bd9Sstevel@tonic-gate AutoInstall()
10267c478bd9Sstevel@tonic-gate {
10277c478bd9Sstevel@tonic-gate char file[MAXLINE];
10287c478bd9Sstevel@tonic-gate char forward[MAXLINE];
10297c478bd9Sstevel@tonic-gate char cmd[MAXLINE];
10307c478bd9Sstevel@tonic-gate char line[MAXLINE];
10317c478bd9Sstevel@tonic-gate char *editor;
10327c478bd9Sstevel@tonic-gate FILE *f;
10337c478bd9Sstevel@tonic-gate struct passwd *pw;
10347c478bd9Sstevel@tonic-gate extern mode_t umask(mode_t cmask);
10357c478bd9Sstevel@tonic-gate
10367c478bd9Sstevel@tonic-gate umask(022);
10377c478bd9Sstevel@tonic-gate pw = getpwuid(getuid());
10387c478bd9Sstevel@tonic-gate if (pw == NULL) {
10397c478bd9Sstevel@tonic-gate usrerr("User ID unknown");
10407c478bd9Sstevel@tonic-gate exit(EX_NOUSER);
10417c478bd9Sstevel@tonic-gate }
10427c478bd9Sstevel@tonic-gate myname = strdup(pw->pw_name);
10437c478bd9Sstevel@tonic-gate if (myname == NULL) {
10447c478bd9Sstevel@tonic-gate usrerr("Out of memory");
10457c478bd9Sstevel@tonic-gate exit(EX_OSERR);
10467c478bd9Sstevel@tonic-gate }
10477c478bd9Sstevel@tonic-gate homedir = getenv("HOME");
10487c478bd9Sstevel@tonic-gate if (homedir == NULL) {
10497c478bd9Sstevel@tonic-gate usrerr("Home directory unknown");
10507c478bd9Sstevel@tonic-gate exit(EX_NOUSER);
10517c478bd9Sstevel@tonic-gate }
10527c478bd9Sstevel@tonic-gate
10537c478bd9Sstevel@tonic-gate printf("This program can be used to answer your mail automatically\n");
10547c478bd9Sstevel@tonic-gate printf("when you go away on vacation.\n");
10557c478bd9Sstevel@tonic-gate (void) strlcpy(file, homedir, sizeof (file));
10567c478bd9Sstevel@tonic-gate (void) strlcat(file, MsgFile, sizeof (file));
10577c478bd9Sstevel@tonic-gate do {
10587c478bd9Sstevel@tonic-gate f = fopen(file, "r");
10597c478bd9Sstevel@tonic-gate if (f) {
10607c478bd9Sstevel@tonic-gate printf("You have a message file in %s.\n", file);
10617c478bd9Sstevel@tonic-gate if (ask("Would you like to see it")) {
10627c478bd9Sstevel@tonic-gate (void) snprintf(cmd, sizeof (cmd),
10637c478bd9Sstevel@tonic-gate "/usr/bin/more %s", file);
10647c478bd9Sstevel@tonic-gate system(cmd);
10657c478bd9Sstevel@tonic-gate }
10667c478bd9Sstevel@tonic-gate if (ask("Would you like to edit it"))
10677c478bd9Sstevel@tonic-gate f = NULL;
10687c478bd9Sstevel@tonic-gate } else {
10697c478bd9Sstevel@tonic-gate printf("You need to create a message file"
10707c478bd9Sstevel@tonic-gate " in %s first.\n", file);
10717c478bd9Sstevel@tonic-gate f = fopen(file, "w");
10727c478bd9Sstevel@tonic-gate if (f == NULL) {
10737c478bd9Sstevel@tonic-gate usrerr("Cannot open %s", file);
10747c478bd9Sstevel@tonic-gate exit(EX_CANTCREAT);
10757c478bd9Sstevel@tonic-gate }
10767c478bd9Sstevel@tonic-gate fprintf(f, "Subject: away from my mail\n");
10777c478bd9Sstevel@tonic-gate fprintf(f, "\nI will not be reading my mail"
10787c478bd9Sstevel@tonic-gate " for a while.\n");
10797c478bd9Sstevel@tonic-gate fprintf(f, "Your mail regarding \"$SUBJECT\" will"
10807c478bd9Sstevel@tonic-gate " be read when I return.\n");
10817c478bd9Sstevel@tonic-gate fclose(f);
10827c478bd9Sstevel@tonic-gate f = NULL;
10837c478bd9Sstevel@tonic-gate }
10847c478bd9Sstevel@tonic-gate if (f == NULL) {
10857c478bd9Sstevel@tonic-gate editor = getenv("VISUAL");
10867c478bd9Sstevel@tonic-gate if (editor == NULL)
10877c478bd9Sstevel@tonic-gate editor = getenv("EDITOR");
10887c478bd9Sstevel@tonic-gate if (editor == NULL)
10897c478bd9Sstevel@tonic-gate editor = "/usr/bin/vi";
10907c478bd9Sstevel@tonic-gate (void) snprintf(cmd, sizeof (cmd), "%s %s", editor,
10917c478bd9Sstevel@tonic-gate file);
10927c478bd9Sstevel@tonic-gate printf("Please use your editor (%s)"
10937c478bd9Sstevel@tonic-gate " to edit this file.\n", editor);
10947c478bd9Sstevel@tonic-gate system(cmd);
10957c478bd9Sstevel@tonic-gate }
10967c478bd9Sstevel@tonic-gate } while (f == NULL);
10977c478bd9Sstevel@tonic-gate fclose(f);
10987c478bd9Sstevel@tonic-gate (void) strlcpy(forward, homedir, sizeof (forward));
10997c478bd9Sstevel@tonic-gate (void) strlcat(forward, "/.forward", sizeof (forward));
11007c478bd9Sstevel@tonic-gate f = fopen(forward, "r");
11017c478bd9Sstevel@tonic-gate if (f) {
11027c478bd9Sstevel@tonic-gate printf("You have a .forward file"
11037c478bd9Sstevel@tonic-gate " in your home directory containing:\n");
11047c478bd9Sstevel@tonic-gate while (fgets(line, MAXLINE, f))
11057c478bd9Sstevel@tonic-gate printf(" %s", line);
11067c478bd9Sstevel@tonic-gate fclose(f);
11077c478bd9Sstevel@tonic-gate if (!ask("Would you like to remove it and"
11087c478bd9Sstevel@tonic-gate " disable the vacation feature"))
11097c478bd9Sstevel@tonic-gate exit(EX_OK);
11107c478bd9Sstevel@tonic-gate if (unlink(forward))
11117c478bd9Sstevel@tonic-gate perror("Error removing .forward file:");
11127c478bd9Sstevel@tonic-gate else
11137c478bd9Sstevel@tonic-gate printf("Back to normal reception of mail.\n");
11147c478bd9Sstevel@tonic-gate exit(EX_OK);
11157c478bd9Sstevel@tonic-gate }
11167c478bd9Sstevel@tonic-gate
11177c478bd9Sstevel@tonic-gate printf("To enable the vacation feature"
11187c478bd9Sstevel@tonic-gate " a \".forward\" file is created.\n");
11197c478bd9Sstevel@tonic-gate if (!ask("Would you like to enable the vacation feature")) {
11207c478bd9Sstevel@tonic-gate printf("OK, vacation feature NOT enabled.\n");
11217c478bd9Sstevel@tonic-gate exit(EX_OK);
11227c478bd9Sstevel@tonic-gate }
11237c478bd9Sstevel@tonic-gate f = fopen(forward, "w");
11247c478bd9Sstevel@tonic-gate if (f == NULL) {
11257c478bd9Sstevel@tonic-gate perror("Error opening .forward file");
11267c478bd9Sstevel@tonic-gate exit(EX_CANTCREAT);
11277c478bd9Sstevel@tonic-gate }
11287c478bd9Sstevel@tonic-gate fprintf(f, "\\%s, \"|/usr/bin/vacation %s\"\n", myname, myname);
11297c478bd9Sstevel@tonic-gate fclose(f);
11307c478bd9Sstevel@tonic-gate printf("Vacation feature ENABLED."
11317c478bd9Sstevel@tonic-gate " Please remember to turn it off when\n");
11327c478bd9Sstevel@tonic-gate printf("you get back from vacation. Bon voyage.\n");
11337c478bd9Sstevel@tonic-gate
11347c478bd9Sstevel@tonic-gate initialize(DbFileBase);
11357c478bd9Sstevel@tonic-gate exit(EX_OK);
11367c478bd9Sstevel@tonic-gate }
11377c478bd9Sstevel@tonic-gate
11387c478bd9Sstevel@tonic-gate
11397c478bd9Sstevel@tonic-gate /*
11407c478bd9Sstevel@tonic-gate * Ask the user a question until we get a reasonable answer
11417c478bd9Sstevel@tonic-gate */
11427c478bd9Sstevel@tonic-gate
11437c478bd9Sstevel@tonic-gate static bool
ask(prompt)11447c478bd9Sstevel@tonic-gate ask(prompt)
11457c478bd9Sstevel@tonic-gate char *prompt;
11467c478bd9Sstevel@tonic-gate {
11477c478bd9Sstevel@tonic-gate char line[MAXLINE];
11487c478bd9Sstevel@tonic-gate char *res;
11497c478bd9Sstevel@tonic-gate
11507c478bd9Sstevel@tonic-gate for (;;) {
11517c478bd9Sstevel@tonic-gate printf("%s? ", prompt);
11527c478bd9Sstevel@tonic-gate fflush(stdout);
11537c478bd9Sstevel@tonic-gate res = fgets(line, sizeof (line), stdin);
11547c478bd9Sstevel@tonic-gate if (res == NULL)
11557c478bd9Sstevel@tonic-gate return (FALSE);
11567c478bd9Sstevel@tonic-gate if (res[0] == 'y' || res[0] == 'Y')
11577c478bd9Sstevel@tonic-gate return (TRUE);
11587c478bd9Sstevel@tonic-gate if (res[0] == 'n' || res[0] == 'N')
11597c478bd9Sstevel@tonic-gate return (FALSE);
11607c478bd9Sstevel@tonic-gate printf("Please reply \"yes\" or \"no\" (\'y\' or \'n\')\n");
11617c478bd9Sstevel@tonic-gate }
11627c478bd9Sstevel@tonic-gate }
1163