remove DATUM, DBREC -- should simply be able to bcopy buffer onto the time_t,
shouldn't need all that struct stuff
SCCS-vsn: usr.bin/vacation/vacation.1 6.7
SCCS-vsn: usr.bin/vacation/vacation.c 5.12
.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.\" @(#)vacation.1 6.6 (Berkeley) %G%
+.\" @(#)vacation.1 6.7 (Berkeley) %G%
.\"
.TH VACATION 1 ""
.UC 6
.\"
.TH VACATION 1 ""
.UC 6
.SH SYNOPSIS
.B vacation
.B -i
.SH SYNOPSIS
.B vacation
.B -i
.br
.B vacation
[
.B -a
alias ] login
.SH DESCRIPTION
.br
.B vacation
[
.B -a
alias ] login
.SH DESCRIPTION
-\fIVacation\fP returns a message to the sender of a message telling
-them that you are currently not reading your mail. The intended use
-is in a \fI.forward\fP file. For example, your \fI.forward\fP file
-might have:
+.I Vacation
+returns a message to the sender of a message telling them that you
+are currently not reading your mail. The intended use is in a
+.I .forward
+file. For example, your
+.I .forward
+file might have:
.PP
.ti +5
\eeric, "|/usr/ucb/vacation -a allman eric"
.PP
.ti +5
\eeric, "|/usr/ucb/vacation -a allman eric"
which would send messages to you (assuming your login name was eric) and
reply to any messages for ``eric'' or ``allman''.
.PP
which would send messages to you (assuming your login name was eric) and
reply to any messages for ``eric'' or ``allman''.
.PP
-No message will be sent unless \fIlogin\fP or an \fIalias\fP supplied
-using the \fB-a\fP option is a substring of either the ``To:'' or ``Cc:''
-headers of the mail. No messages from ``???-REQUEST'', ``Postmaster'',
-``UUCP'', ``MAILER'', or ``MAILER-DAEMON'' will be replied to, nor is a
-notification sent if a ``Precedence: bulk'' or ``Precedence: junk'' line
-is included in the mail headers. Only one message per week will be sent
-to each unique sender. The people who have sent you messages are
-maintained as an \fIndbm\fP(3) database in the files \fI.vacation.pag\fP
-and \fI.vacation.dir\fP in your home directory.
+No message will be sent unless
+.I login
+(or an
+.I alias
+supplied using the
+.B -a
+option) is part of either the ``To:'' or ``Cc:'' headers of the mail.
+No messages from ``???-REQUEST'', ``Postmaster'', ``UUCP'', ``MAILER'',
+or ``MAILER-DAEMON'' will be replied to (where these strings are
+case insensitive) nor is a notification sent if a ``Precedence: bulk''
+or ``Precedence: junk'' line is included in the mail headers.
+The people who have sent you messages are maintained as an
+.IR ndbm (3)
+database in the files
+.I .vacation.pag
+and
+.I .vacation.dir
+in your home directory.
+.PP
+The
+.B -i
+flag initializes the vacation database files. It should be used
+before you modify your
+.I .forward
+file.
-The \fB-i\fP flag initializes the vacation database files. It should be
-used before you modify your \fI.forward\fP file.
+The
+.B -r
+flag sets the reply interval to
+.I interval
+days. The default is one week. An interval of ``0'' means that
+a reply is sent to each message, and an interval of ``infinite''
+(actually, any non-numeric character) will never send more than
+one reply. It should be noted that intervals of ``0'' are quite
+dangerous, as it allows mailers to get into ``I am on vacation''
+loops.
-\fIVacation\fP expects a file \fI.vacation.msg\fP, in your home directory,
-containing a message to be sent back to each sender. It should be an entire
-message (including headers). For example, it might say:
+.I Vacation
+expects a file
+.IR .vacation.msg ,
+in your home directory, containing a message to be sent back to each
+sender. It should be an entire message (including headers). For
+example, it might contain:
-\fIVacation\fP reads the first line from the standard input for
-a \s-1UNIX\s0-style ``From'' line to determine the sender.
-\fISendmail\fP(8) includes this ``From'' line automatically.
+.I Vacation
+reads the first line from the standard input for a \s-1UNIX\s0-style
+``From'' line to determine the sender.
+.IR Sendmail (8)
+includes this ``From'' line automatically.
-Fatal errors, such as calling \fIvacation\fP with incorrect arguments,
-or with non-existent \fIlogin\fPs, are logged in the system log file,
-using \fIsyslog\fP(8).
+Fatal errors, such as calling
+.I vacation
+with incorrect arguments, or with non-existent
+.IR login s,
+are logged in the system log file, using
+.IR syslog (8).
.SH FILES
.nf
.ta \w'~/.vacation.msg 'u
.SH FILES
.nf
.ta \w'~/.vacation.msg 'u
#endif /* not lint */
#ifndef lint
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)vacation.c 5.11 (Berkeley) %G%";
+static char sccsid[] = "@(#)vacation.c 5.12 (Berkeley) %G%";
#include <sys/param.h>
#include <sys/file.h>
#include <pwd.h>
#include <sys/param.h>
#include <sys/file.h>
#include <pwd.h>
+#include <ndbm.h>
+#include <syslog.h>
+#include <tzfile.h>
#include <stdio.h>
#include <ctype.h>
#include <stdio.h>
#include <ctype.h>
-** VACATION -- return a message to the sender when on vacation.
-**
-** This program could be invoked as a message receiver when someone is
-** on vacation. It returns a message specified by the user to whoever
-** sent the mail, taking care not to return a message too often to
-** prevent "I am on vacation" loops.
-*/
+ * VACATION -- return a message to the sender when on vacation.
+ *
+ * This program is invoked as a message receiver. It returns a
+ * message specified by the user to whomever sent the mail, taking
+ * care not to return a message too often to prevent "I am on
+ * vacation" loops.
+ */
#define MAXLINE 500 /* max line from mail header */
#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 VMSG ".vacation.msg" /* vacation message */
#define VACAT ".vacation" /* dbm's database prefix */
#define VDIR ".vacation.dir" /* dbm's DB prefix, part 1 */
typedef struct alias {
struct alias *next;
typedef struct alias {
struct alias *next;
-static char from[MAXLINE]; /* sender's address */
+static DBM *db;
+
+extern int errno;
+
+#define VIT "__VACATION__INTERVAL__TIMER__"
+static char from[MAXLINE];
main(argc, argv)
int argc;
char **argv;
{
main(argc, argv)
int argc;
char **argv;
{
+ extern int optind, opterr;
extern char *optarg;
struct passwd *pw;
ALIAS *cur;
extern char *optarg;
struct passwd *pw;
ALIAS *cur;
int ch, iflag;
char *malloc();
uid_t getuid();
int ch, iflag;
char *malloc();
uid_t getuid();
- iflag = 0;
- while ((ch = getopt(argc, argv, "a:Ii")) != EOF)
+ opterr = iflag = 0;
+ interval = -1;
+ while ((ch = getopt(argc, argv, "a:Iir:")) != EOF)
switch((char)ch) {
case 'a': /* alias */
if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))))
switch((char)ch) {
case 'a': /* alias */
if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))))
cur->next = names;
names = cur;
break;
cur->next = names;
names = cur;
break;
- case 'i': /* init the database */
case 'I': /* backward compatible */
case 'I': /* backward compatible */
+ case 'i': /* init the database */
+ case 'r':
+ if (isdigit(*optarg)) {
+ interval = atol(optarg) * SECS_PER_DAY;
+ if (interval < 0)
+ goto usage;
+ }
+ else
+ interval = LONG_MAX;
+ break;
case '?':
default:
goto usage;
case '?':
default:
goto usage;
if (argc != 1) {
if (!iflag) {
if (argc != 1) {
if (!iflag) {
-usage: syslog(LOG_ERR, "uid %u: usage: vacation [-i] [-a alias] login\n", getuid());
- exit(1);
+usage: syslog(LOG_NOTICE, "uid %u: usage: vacation [-i] [-a alias] login\n", getuid());
+ myexit(1);
}
if (!(pw = getpwuid(getuid()))) {
syslog(LOG_ERR, "vacation: no such user uid %u.\n", getuid());
}
if (!(pw = getpwuid(getuid()))) {
syslog(LOG_ERR, "vacation: no such user uid %u.\n", getuid());
}
}
else if (!(pw = getpwnam(*argv))) {
syslog(LOG_ERR, "vacation: no such user %s.\n", *argv);
}
}
else if (!(pw = getpwnam(*argv))) {
syslog(LOG_ERR, "vacation: no such user %s.\n", *argv);
}
if (chdir(pw->pw_dir)) {
}
if (chdir(pw->pw_dir)) {
- syslog(LOG_ERR, "vacation: no such directory %s.\n", pw->pw_dir);
- exit(1);
+ syslog(LOG_NOTICE, "vacation: no such directory %s.\n", pw->pw_dir);
+ myexit(1);
+ if (iflag || access(VDIR, F_OK))
+ if (!(db = dbm_open(VACAT, O_RDWR, 0))) {
+ syslog(LOG_NOTICE, "vacation: %s: %s\n", VACAT,
+ strerror(errno));
+ myexit(1);
+ if (interval != -1)
+ setinterval(interval);
+ if (iflag)
+ myexit(0);
+
if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))))
if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))))
cur->name = pw->pw_name;
cur->next = names;
names = cur;
readheaders();
cur->name = pw->pw_name;
cur->next = names;
names = cur;
readheaders();
- if (access(VDIR, F_OK))
- initialize();
- else
- dbminit(VACAT);
-
if (!recent()) {
setreply();
sendmessage(pw->pw_name);
}
if (!recent()) {
setreply();
sendmessage(pw->pw_name);
}
+ myexit(0);
+ /* NOTREACHED */
for (p = buf + 5; *p && *p != ' '; ++p);
*p = '\0';
(void)strcpy(from, buf + 5);
for (p = buf + 5; *p && *p != ' '; ++p);
*p = '\0';
(void)strcpy(from, buf + 5);
+ if (p = index(from, '\n'))
+ *p = '\0';
}
break;
case 'P': /* "Precedence:" */
}
break;
case 'P': /* "Precedence:" */
if (!*p)
break;
if (!strncasecmp(p, "junk", 4) || !strncasecmp(p, "bulk", 4))
if (!*p)
break;
if (!strncasecmp(p, "junk", 4) || !strncasecmp(p, "bulk", 4))
break;
case 'C': /* "Cc:" */
if (strncmp(buf, "Cc:", 3))
break;
case 'C': /* "Cc:" */
if (strncmp(buf, "Cc:", 3))
tome += nsearch(cur->name, buf);
}
if (!tome)
tome += nsearch(cur->name, buf);
}
if (!tome)
- syslog(LOG_ERR, "vacation: no initial \"From\" line.\n");
- exit(1);
+ syslog(LOG_NOTICE, "vacation: no initial \"From\" line.\n");
+ myexit(1);
* junkmail --
* read the header and return if automagic/junk/bulk mail
*/
* junkmail --
* read the header and return if automagic/junk/bulk mail
*/
junkmail()
{
static struct ignore {
junkmail()
{
static struct ignore {
-typedef struct {
- char *dptr;
- int dsize;
-} DATUM;
-
-typedef struct {
- time_t sentdate;
-} DBREC;
-
/*
* recent --
* find out if user has gotten a vacation message recently.
/*
* recent --
* find out if user has gotten a vacation message recently.
+ * use bcopy for machines with alignment restrictions
- DATUM k, d, fetch();
- time_t now, then, time();
+ datum key, data;
+ time_t then, next, time();
- k.dptr = from;
- k.dsize = strlen(from) + 1;
- d = fetch(k);
if (d.dptr == NULL)
return FALSE;
bcopy(d.dptr, (char *)&ldbrec, sizeof ldbrec); /* realign data */
if (d.dptr == NULL)
return FALSE;
bcopy(d.dptr, (char *)&ldbrec, sizeof ldbrec); /* realign data */
+/*
+ * setinterval --
+ * store the reply interval
+ */
+setinterval(interval)
+ time_t interval;
+{
+ datum key, data;
+
+ key.dptr = VIT;
+ key.dsize = sizeof(VIT) - 1;
+ data.dptr = (char *)&interval;
+ data.dsize = sizeof(interval);
+ dbm_store(db, key, data, DBM_REPLACE);
+}
+
/*
* setreply --
* store that this user knows about the vacation.
*/
/*
* setreply --
* store that this user knows about the vacation.
*/
- DBREC xrec;
- DATUM k, d;
- time_t time();
-
- k.dptr = from;
- k.dsize = strlen(from) + 1;
- (void)time(&xrec.sentdate);
- d.dptr = (char *)&xrec;
- d.dsize = sizeof(xrec);
- store(k, d);
+ datum key, data;
+ time_t now, time();
+
+ key.dptr = from;
+ key.dsize = strlen(from);
+ (void)time(&now);
+ data.dptr = (char *)&now;
+ data.dsize = sizeof(now);
+ dbm_store(db, key, data, DBM_REPLACE);
}
/*
* sendmessage --
* exec sendmail to send the vacation file to sender
*/
}
/*
* sendmessage --
* exec sendmail to send the vacation file to sender
*/
sendmessage(myname)
char *myname;
{
if (!freopen(VMSG, "r", stdin)) {
sendmessage(myname)
char *myname;
{
if (!freopen(VMSG, "r", stdin)) {
- syslog(LOG_ERR, "vacation: no ~%s/%s file.\n", myname, VMSG);
- exit(1);
+ syslog(LOG_NOTICE, "vacation: no ~%s/%s file.\n", myname, VMSG);
+ myexit(1);
}
execl("/usr/lib/sendmail", "sendmail", "-f", myname, from, NULL);
syslog(LOG_ERR, "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");
}
/*
* initialize --
* initialize the dbm database
*/
}
/*
* initialize --
* initialize the dbm database
*/
- extern int errno;
- extern char *sys_errlist[];
int fd;
if ((fd = open(VDIR, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
int fd;
if ((fd = open(VDIR, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
- syslog(LOG_ERR, "vacation: %s: %s\n", VDIR, sys_errlist[errno]);
+ syslog(LOG_NOTICE, "vacation: %s: %s\n", VDIR, strerror(errno));
exit(1);
}
(void)close(fd);
if ((fd = open(VPAG, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
exit(1);
}
(void)close(fd);
if ((fd = open(VPAG, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
- syslog(LOG_ERR, "vacation: %s: %s\n", VPAG, sys_errlist[errno]);
+ syslog(LOG_NOTICE, "vacation: %s: %s\n", VPAG, strerror(errno));
exit(1);
}
(void)close(fd);
exit(1);
}
(void)close(fd);
+}
+
+/*
+ * myexit --
+ * we're outta here...
+ */
+myexit(eval)
+ int eval;
+{
+ if (db)
+ dbm_close(db);
+ exit(eval);