From de4d1f2e1bc6dc96dbec938c16475e4a19ec4681 Mon Sep 17 00:00:00 2001 From: Keith Bostic Date: Sat, 26 Dec 1987 23:27:46 -0800 Subject: [PATCH] remove vacation.ignore stuff; first cut at checking To: and Cc: lines for mention of user's login or aliases; remove messages to stderr. SCCS-vsn: usr.bin/vacation/vacation.c 5.7 --- usr/src/usr.bin/vacation/vacation.c | 416 ++++++++++++---------------- 1 file changed, 173 insertions(+), 243 deletions(-) diff --git a/usr/src/usr.bin/vacation/vacation.c b/usr/src/usr.bin/vacation/vacation.c index c766a037f2..4103420031 100644 --- a/usr/src/usr.bin/vacation/vacation.c +++ b/usr/src/usr.bin/vacation/vacation.c @@ -1,17 +1,31 @@ +/* + * Copyright (c) 1983, 1987 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of California at Berkeley. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. This software + * is provided ``as is'' without express or implied warranty. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1983, 1987 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)vacation.c 5.7 (Berkeley) %G%"; +#endif /* not lint */ + /* ** Vacation ** Copyright (c) 1983 Eric P. Allman ** Berkeley, California -** -** Copyright (c) 1983, 1987 Regents of the University of California. -** All rights reserved. The Berkeley software License Agreement -** specifies the terms and conditions for redistribution. */ -#ifndef lint -static char SccsId[] = "@(#)vacation.c 5.6 (Berkeley) %G%"; -#endif not lint - #include #include #include @@ -29,181 +43,161 @@ static char SccsId[] = "@(#)vacation.c 5.6 (Berkeley) %G%"; ** prevent "I am on vacation" loops. */ -#define NO 0 /* no/false */ -#define YES 1 /* yes/true */ -#define EOS '\0' /* end of string */ #define MAXLINE 500 /* max line from mail header */ #define PERIOD (60L*60L*24L*7L) /* week between notifications */ +#define VMSG ".vacation.msg" /* vacation message */ #define VACAT ".vacation" /* dbm's database prefix */ #define VDIR ".vacation.dir" /* dbm's DB prefix, part 1 */ -#define VIGN ".vacation.ignore" /* addresses never replied to */ -#define VLOG ".vacation.log" /* log action and errors */ -#define VMSG ".vacation.msg" /* vacation message */ #define VPAG ".vacation.pag" /* dbm's DB prefix, part 2 */ -typedef struct { - char *dptr; - int dsize; -} DATUM; - -typedef struct { - time_t sentdate; -} DBREC; +typedef struct alias { + struct alias *next; + char *name; +} ALIAS; +ALIAS *names; -static int debug; /* debugging flag */ +static char from[MAXLINE]; /* sender's address */ main(argc, argv) - int argc; - char **argv; + int argc; + char **argv; { - extern int optind; - struct passwd *pw; - int ch, iflag = NO; - char *from, - *getfrom(); - uid_t getuid(); - - while ((ch = getopt(argc, argv, "Idi")) != EOF) + extern int optind; + extern char *optarg; + struct passwd *pw; + ALIAS *cur; + int ch, iflag; + char *malloc(); + uid_t getuid(); + + iflag = 0; + while ((ch = getopt(argc, argv, "a:Ii")) != EOF) switch((char)ch) { + case 'a': /* alias */ + if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS)))) + break; + cur->name = optarg; + cur->next = names; + names = cur; + break; case 'i': /* init the database */ case 'I': /* backward compatible */ - iflag = YES; - break; - case 'd': /* debugging */ - debug = YES; + iflag = 1; break; case '?': default: - usage(); + goto usage; } - argv += optind; argc -= optind; + argv += optind; - /* find and move to user's home directory */ if (argc != 1) { - if (!iflag) - usage(); - if (!(pw = getpwuid(getuid())) || chdir(pw->pw_dir)) { - fprintf(stderr, "vacation: no such user uid %u.\n", getuid()); + if (!iflag) { +usage: syslog(LOG_ERR, "uid %u: usage: vacation [-i] [-a alias] login\n", getuid()); + exit(EX_USAGE); + } + if (!(pw = getpwuid(getuid()))) { syslog(LOG_ERR, "vacation: no such user uid %u.\n", getuid()); exit(EX_USAGE); } - *argv = pw->pw_name; } - else if (!(pw = getpwnam(*argv)) || chdir(pw->pw_dir)) { - fprintf(stderr, "vacation: no such user %s.\n", *argv); + else if (!(pw = getpwnam(*argv))) { syslog(LOG_ERR, "vacation: no such user %s.\n", *argv); exit(EX_USAGE); } + if (chdir(pw->pw_dir)) { + syslog(LOG_ERR, "vacation: no such directory %s.\n", pw->pw_dir); + exit(EX_USAGE); + } - /* iflag cleans out the database */ if (iflag) { initialize(); exit(EX_OK); } - if (debug) { - time_t now, - time(); - char *ctime(); + if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS)))) + exit(EX_SOFTWARE); + cur->name = pw->pw_name; + cur->next = names; + names = cur; - if (!freopen(VLOG, "a", stderr)) { - fprintf(stderr, "vacation: can't append ~%s/%s\n", *argv, VLOG); - syslog(LOG_ERR, "vacation: can't append ~%s/%s\n", *argv, VLOG); - exit(EX_CANTCREAT); - } - (void)time(&now); - fprintf(stderr, "===== %s", ctime(&now)); - } + readheaders(); - /* - * if database missing, we create it and do a dbminit; - * otherwise, just do the dbminit. - */ if (access(VDIR, F_OK)) initialize(); else dbminit(VACAT); - /* find out who sent us mail */ - from = getfrom(&shortfrom); -#ifdef VDEBUG - printf("from='%s'\nshortfrom='%s'\n", from, shortfrom); - exit(0); -#endif - - setknows(shortfrom); - - /* - * ignore if recently replied to this address, - * else note the time and send a reply - */ - if (!knows(from)) { - setknows(from, NO); - sendmessage(from, *argv); + if (!recent()) { + setreply(); + sendmessage(pw->pw_name); } exit(EX_OK); } /* - * getfrom -- - * read mail "From" line and return sender's address + * readheaders -- + * read mail headers */ -static char * getfrom(shortp) char **shortp; { - register char *p; - char buf[MAXLINE], - *malloc(), *strcpy(); - - /* read the from line */ - if (!gets(buf) || strncmp(buf, "From ", 5)) { - fputs("vacation: no initial From line.\n", stderr); - exit(EX_DATAERR); - } - - /* find the end of the sender address and terminate it */ - for (p = &buf[5]; *p && *p != ' '; ++p); - if (!*p) { - fprintf(stderr, "vacation: address terminated From line '%s'\n", buf); + register ALIAS *cur; + register char *p; + int tome, cont; + char buf[MAXLINE], *strcpy(), *index(); + + cont = tome = 0; + while (fgets(buf, sizeof(buf), stdin) && *buf != '\n') + switch(*buf) { + case 'F': /* "From " */ + cont = 0; + if (!strncmp(buf, "From ", 5)) { + for (p = buf + 5; *p && *p != ' '; ++p); + *p = '\0'; + (void)strcpy(from, buf + 5); + if (junkmail()) + exit(EX_OK); + } + break; + case 'P': /* "Precedence:" */ + cont = 0; + if (strncasecmp(buf, "Precedence", 10) || buf[10] != ':' && buf[10] != ' ' && buf[10] != '\t') + break; + if (!(p = index(buf, ':'))) + break; + while (*++p && isspace(*p)); + if (!*p) + break; + if (!strncasecmp(p, "junk", 4) || !strncasecmp(p, "bulk", 4)) + exit(EX_OK); + break; + case 'C': /* "Cc:" */ + if (!strncmp(buf, "Cc:", 3)) + break; + cont = 1; + goto findme; + case 'T': /* "To:" */ + if (strncmp(buf, "To:", 3)) + break; + cont = 1; + goto findme; + default: + if (!isspace(*buf) || !cont || tome) { + cont = 0; + break; + } +findme: for (cur = names; !tome && cur; cur = cur->next) + tome += nsearch(cur->name, buf); + } + if (!tome) + exit(EX_OK); + if (!*from) { + syslog(LOG_ERR, "vacation: no initial \"From\" line.\n"); exit(EX_DATAERR); } - *p = EOS; - if (!(p = malloc((u_int)(strlen(&buf[5]) + 1)))) { - fputs("vacation: out of space.\n", stderr); - exit(EX_OSERR); - } - /* - * Strip all but the rightmost UUCP host - * to prevent loops due to forwarding. - * Start searching leftward from the leftmost '@'. - * a!b!c!d yields a short name of c!d - * a!b!c!d@e yields a short name of c!d@e - * e@a!b!c yields the same short name - */ -#ifdef VDEBUG -printf("start='%s'\n", start); -#endif - *shortp = start; /* assume whole addr */ - if ((at = index(start, '@')) == NULL) /* leftmost '@' */ - at = p; /* if none, use end of addr */ - saveat = *at; - *at = '\0'; - if ((bang = rindex(start, '!')) != NULL) { /* rightmost '!' */ - char *bang2; - - *bang = '\0'; - if ((bang2 = rindex(start, '!')) != NULL) /* 2nd rightmost '!' */ - *shortp = bang2 + 1; /* move past ! */ - *bang = '!'; - } - *at = saveat; -#ifdef VDEBUG -printf("place='%s'\n", *shortp); -#endif +} - /* return the sender address */ return start; } @@ -212,87 +206,64 @@ printf("place='%s'\n", *shortp); * read the header and return if automagic/junk/bulk mail */ static -junkmail(from) - char *from; +junkmail() { static struct ignore { char *name; int len; } ignore[] = { - "-REQUEST", 8, "Postmaster", 10, - "uucp", 4, "MAILER-DAEMON", 13, - "MAILER", 6, NULL, NULL, + "-REQUEST", 8, "Postmaster", 10, + "uucp", 4, "MAILER-DAEMON", 13, + "MAILER", 6, NULL, NULL, }; - register struct ignore *I; - register int len; - register char *p; - char buf[MAXLINE], - *index(), *rindex(); + register struct ignore *cur; + register int len; + register char *p; + char *index(), *rindex(); /* - * This is mildly amusing, and I'm not positive it's right; what - * we're trying to do is find the "real" name of the sender. I'm - * assuming that addresses will be some variant of: - * - * From SENDER - * From SENDER@seismo.css.gov - * From SENDER%site.BITNET@seismo.css.gov - * From site1!site2!SENDER@seismo.css.gov + * This is mildly amusing, and I'm not positive it's right; trying + * to find the "real" name of the sender, assuming that addresses + * will be some variant of: * - * Therefore, the following search order: + * From site!site!SENDER%site.domain%site.domain@site.domain */ if (!(p = index(from, '%'))) if (!(p = index(from, '@'))) { if (p = rindex(from, '!')) ++p; - for (p = from; *p; ++p); + else + p = from; + for (; *p; ++p); } len = p - from; - for (I = ignore; I->name; ++I) - if (len >= I->len && !strncasecmp(I->name, p - I->len, I->len)) { - if (debug) - fprintf(stderr, "not sending to %s {%s}\n", from, I->name); - return(YES); - } - - /* read the header looking for a "Precedence:" line */ - while (gets(buf) && *buf) { - if (strncasecmp(buf, "Precedence", 10) || - buf[10] != ':' && buf[10] != ' ' && buf[10] != '\t') - continue; + for (cur = ignore; cur->name; ++cur) + if (len >= cur->len && !strncasecmp(cur->name, p - cur->len, cur->len)) + return(1); + return(0); +} - /* find the value of this field */ - if (!(p = index(buf, ':'))) - continue; - while (*++p && isspace(*p)); - if (!*p) - continue; +typedef struct { + char *dptr; + int dsize; +} DATUM; - /* see if it is "junk" or "bulk" */ - if (!strncasecmp(p, "junk", 4) || !strncasecmp(p, "bulk", 4)) { - if (debug) - fprintf(stderr, "not sending to %s {junk/bulk}\n", from); - return(YES); - } - } - return(NO); -} +typedef struct { + time_t sentdate; +} DBREC; /* - * knows -- + * recent -- * find out if user has gotten a vacation message recently. */ static -knows(user) char *user; { - DATUM k, d, - fetch(); - time_t now, then, - time(); + DATUM k, d, fetch(); + time_t now, then, time(); - k.dptr = user; - k.dsize = strlen(user) + 1; + k.dptr = from; + k.dsize = strlen(from) + 1; d = fetch(k); if (d.dptr == NULL) return FALSE; @@ -311,25 +282,19 @@ register unsigned size; #endif /* - * setknows -- + * setreply -- * store that this user knows about the vacation. */ static -setknows(user, forever) - char *user; - int forever; +setreply() { - DBREC xrec; - DATUM k, d; - time_t time(); + DBREC xrec; + DATUM k, d; + time_t time(); - k.dptr = user; - k.dsize = strlen(user) + 1; - if (forever) - /* zero is the flag value meaning *never* reply */ - xrec.sentdate = 0; - else - (void)time(&xrec.sentdate); + k.dptr = from; + k.dsize = strlen(from) + 1; + (void)time(&xrec.sentdate); d.dptr = (char *)&xrec; d.dsize = sizeof(xrec); store(k, d); @@ -337,76 +302,41 @@ setknows(user, forever) /* * sendmessage -- - * exec sendmail to send the vacation file to "user". + * exec sendmail to send the vacation file to sender */ static -sendmessage(user, myname) - char *user, *myname; +sendmessage(myname) + char *myname; { - if (debug) { - fprintf(stderr, "sending {%s} to {%s}\n", VMSG, user); - return; - } if (!freopen(VMSG, "r", stdin)) { - fprintf(stderr, "vacation: no ~%s/%s file.\n", myname, VMSG); syslog(LOG_ERR, "vacation: no ~%s/%s file.\n", myname, VMSG); exit(EX_NOINPUT); } - execl("/usr/lib/sendmail", "sendmail", "-f", myname, user, NULL); - fprintf(stderr, "vacation: can't exec /usr/lib/sendmail.\n"); + execl("/usr/lib/sendmail", "sendmail", "-f", myname, from, NULL); syslog(LOG_ERR, "vacation: can't exec /usr/lib/sendmail.\n"); exit(EX_OSERR); } /* * initialize -- - * initialize the database + * initialize the dbm database */ static initialize() { - extern int errno; - extern char *sys_errlist[]; - FILE *fp; - int fd; + extern int errno; + extern char *sys_errlist[]; + int fd; if ((fd = open(VDIR, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) { - fprintf(stderr, "vacation: %s: %s\n", VDIR, sys_errlist[errno]); syslog(LOG_ERR, "vacation: %s: %s\n", VDIR, sys_errlist[errno]); exit(EX_OSERR); } (void)close(fd); if ((fd = open(VPAG, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) { - fprintf(stderr, "vacation: %s: %s\n", VPAG, sys_errlist[errno]); syslog(LOG_ERR, "vacation: %s: %s\n", VPAG, sys_errlist[errno]); exit(EX_OSERR); } (void)close(fd); dbminit(VACAT); - if (fp = fopen(VIGN, "r")) { - char buf[MAXLINE], - *index(); - -/* VARARGS 1 */ - while (fgets(buf, sizeof(buf), fp)) { - *(index(buf, '\n')) = EOS; - setknows(buf, YES); - } - (void)fclose(fp); - } - return p; -} - -/* - * usage -- - * print out a usage message and die - */ -static -usage() -{ - uid_t getuid(); - - fputs("usage: vacation [-i] login\n", stderr); - syslog(LOG_ERR, "uid %u: usage: vacation [-i] login\n", getuid()); - exit(EX_USAGE); } -- 2.20.1