File vacation-1.2.6.2.dif of Package vacation
--- Makefile
+++ Makefile 2006-08-25 15:36:57.000000000 +0200
@@ -8,18 +8,9 @@
#
SHELL = /bin/sh
CC = gcc
-ARCH = $(shell uname -m)
-#
-ifeq "$(ARCH)" "alpha"
- CFLAGS = $(RPM_OPT_FLAGS) -Wall
-else
-ifeq "$(ARCH)" "ppc"
- CFLAGS = $(RPM_OPT_FLAGS) -fsigned-char -Wall
-else
- CFLAGS = $(RPM_OPT_FLAGS) -m486 -Wall
-endif
-endif
-LFLAGS = -Xlinker -warn-common
+ARCH = $(shell uname -m)
+CFLAGS = $(RPM_OPT_FLAGS) -Wall
+LFLAGS = -Xlinker -warn-common
LIBS = -lgdbm
LINT = lint -abchuvx
@@ -29,7 +20,7 @@ LLIBS =
BINDIR = /usr/bin
VACATION = $(BINDIR)/vacation
VACLOOK = $(BINDIR)/vaclook
-MANDIR = /usr/man/man
+MANDIR = /usr/share/man/man
MANEXT1 = 1
VERSION = 1
--- vacation.c
+++ vacation.c 2007-01-09 12:27:03.000000000 +0000
@@ -69,6 +69,7 @@ static char rcsid[] __attribute__ ((unus
#include <sys/param.h>
#include <sys/stat.h>
+#include <sys/vfs.h>
#include <fcntl.h>
#include <pwd.h>
#include <gdbm.h>
@@ -84,6 +85,13 @@ static char rcsid[] __attribute__ ((unus
#include "tzfile.h"
#include "vacation.h"
+static void eatmsg (void);
+#define EXITIT(excode) { eatmsg(); if (db) gdbm_close(db); exit(excode); }
+#define EXITM(excode) { if (!iflag && !lflag) eatmsg(); if (db) gdbm_close(db); exit(excode); }
+#ifndef NFS_SUPER_MAGIC
+# define NFS_SUPER_MAGIC 0x6969
+#endif
+
/*
* VACATION -- return a message to the sender when on vacation.
*
@@ -100,13 +108,14 @@ int main(int argc, char **argv)
struct passwd *pw;
ALIAS *cur;
time_t interval;
- int ch, iflag, nflag;
+ int ch, iflag, nflag, mfail, lflag, fflag, flags;
char *vacation;
char *vdomain;
char *vusername;
openlog ("vacation", LOG_PID, LOG_MAIL);
- opterr = iflag = nflag = rflag = 0;
+ db = (GDBM_FILE)0;
+ opterr = iflag = nflag = rflag = mfail = lflag = fflag = 0;
interval = -1;
vdomain = NULL;
#ifdef _PATH_VACATION
@@ -114,14 +123,14 @@ int main(int argc, char **argv)
#else
vacation = argv[0];
#endif
- if (argc == 1)
+ if (argc == 1 || (argc == 2 && (strcmp(argv[1], "-F") == 0)))
nflag = 1;
- while ((ch = getopt(argc, argv, "a:h:It:jr")) != EOF)
+ while ((ch = getopt(argc, argv, "a:h:Iit:jrlF")) != EOF)
switch((char)ch) {
case 'a': /* alias */
if (!(cur = (ALIAS *)malloc((u_int)sizeof(ALIAS)))) {
- perror ("malloc");
- exit (-1);
+ mfail++;
+ break;
}
cur->name = optarg;
cur->next = names;
@@ -131,23 +140,30 @@ int main(int argc, char **argv)
vdomain = optarg;
break;
case 'I': /* init the database */
+ case 'i': /* init the database */
iflag = 1;
break;
case 't':
if (isdigit(*optarg)) {
- interval = atol(optarg) * SECSPERDAY; /* unit is `days' */
+ interval = atol(optarg) * SECSPERDAY; /* unit is `days' */
if (interval < 0)
usage();
}
else
interval = LONG_MAX;
break;
- case 'j': /* don't check To: and Cc: fields */
+ case 'j': /* don't check To: and Cc: fields */
jflag = 1;
break;
- case 'r': /* "Reply-To:" overrides "From:" */
+ case 'r': /* "Reply-To:" overrides "From:" */
rflag = 1;
break;
+ case 'l': /* List ~/vacation.db */
+ lflag = 1;
+ break;
+ case 'F': /* Force creation of ~/vacation.db on NFS HOME */
+ fflag = 1;
+ break;
case '?':
default:
usage();
@@ -155,38 +171,120 @@ int main(int argc, char **argv)
}
argc -= optind;
argv += optind;
-
+
+ if (mfail) {
+ syslog(LOG_NOTICE,
+ "vacation: can't allocate memory for alias.\n");
+ closelog();
+ EXITM(-1);
+ }
if (argc != 1) {
- if (!iflag && !nflag)
+ if (!iflag && !nflag && !lflag)
usage();
if (!(pw = getpwuid(getuid()))) {
syslog(LOG_ERR,
"vacation: no such user uid %u.\n", getuid());
- exit(1);
+ closelog();
+ EXITM(1);
}
}
else if (!(pw = getpwnam(*argv))) {
syslog(LOG_ERR, "vacation: no such user %s.\n", *argv);
- exit(1);
+ closelog();
+ EXITM(1);
}
if (chdir(pw->pw_dir)) {
syslog(LOG_NOTICE,
"vacation: no such directory %s.\n", pw->pw_dir);
- exit(1);
+ closelog();
+ EXITM(1);
}
+ if (iflag || nflag) {
+ struct statfs fs;
+ flags = GDBM_NEWDB;
+ if (fflag == 0) {
+ if (statfs(pw->pw_dir, &fs) < 0) {
+ syslog(LOG_ERR, "vacation: can not stat %s %s.\n", pw->pw_dir, strerror(errno));
+ closelog();
+ EXITM(1);
+ }
+ if (fs.f_type == NFS_SUPER_MAGIC) {
+ fprintf(stderr, "vacation: Warning %s is mounted via NFS which may cause\n"
+ " a corrupted ~/.vacation.db data base file!\n\n"
+ ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n"
+ " Please run vacation on the mail delivering server, which is\n"
+ " normal the NFS server, or retry with the added option -F to\n"
+ " force the creation of ~/.vacation.db\n\n"
+ ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n",
+ pw->pw_dir);
+ syslog(LOG_NOTICE, "vacation: no data base on NFS file system created\n");
+ closelog();
+ EXITM(1);
+ }
+ }
+ } else if (lflag)
+ flags = GDBM_READER|GDBM_NOLOCK;
+ else
+ flags = GDBM_WRITER;
+
do
{
- db = gdbm_open(VDB, 128, ((iflag || nflag) ? GDBM_NEWDB : GDBM_WRITER),
- 0644, NULL);
+ db = gdbm_open(VDB, 128, flags, 0644, NULL);
if (!db && errno == EAGAIN)
sleep((rand() & 7) + 1);
}
while (!db && errno == EAGAIN);
if (!db) {
- syslog(LOG_NOTICE, "vacation: %s: %s\n", VDB, strerror(errno));
- exit(1);
+ char *errm;
+ if (errno == 0)
+ errm = gdbm_strerror(gdbm_errno);
+ else
+ errm = strerror(errno);
+ if (lflag || iflag || nflag) {
+ fprintf(stderr, "vacation: %s: %s\n", VDB, errm);
+ close(0);
+ }
+ syslog(LOG_NOTICE, "vacation: %s: %s\n", VDB, errm);
+ closelog();
+ EXITM(1);
+ }
+
+ if (lflag) {
+ datum key, next = gdbm_firstkey (db);
+
+ while (next.dptr) {
+ key = next;
+ next = gdbm_nextkey(db, key);
+
+ if (key.dptr) {
+ datum data = gdbm_fetch(db, key);
+
+ if (data.dptr) {
+ time_t was;
+
+ if (data.dsize == (sizeof(was) >> 1)) {
+ /* We read on 64bit system 32bit time_t input */
+ int32_t in;
+
+ bzero(&was, sizeof(was));
+ bcopy(data.dptr, &in, sizeof(in));
+ was = (time_t)in;
+ } else
+ bcopy(data.dptr, &was, sizeof(was));
+
+ printf("%-36.*s %.36s", key.dsize, key.dptr, ctime(&was));
+ free (data.dptr);
+ }
+
+ free (key.dptr);
+ }
+
+ }
+
+ (void) gdbm_close(db);
+ exit(0);
}
if (interval != -1)
@@ -196,15 +294,19 @@ int main(int argc, char **argv)
(void) gdbm_close(db);
exit(0);
}
-
+
if (nflag) {
(void) gdbm_close(db);
initialize(vacation, pw->pw_name);
exit(0);
}
- if (!(cur = malloc((u_int)sizeof(ALIAS))))
- exit(1);
+ if (!(cur = malloc((u_int)sizeof(ALIAS)))) {
+ syslog(LOG_NOTICE,
+ "vacation: can't allocate memory for username.\n");
+ closelog();
+ EXITM(-1);
+ }
cur->name = pw->pw_name;
cur->next = names;
names = cur;
@@ -218,8 +320,10 @@ int main(int argc, char **argv)
(void) gdbm_close(db);
if( vdomain){ /* add virtual domain to username */
if( !(vusername = (char *)malloc(MAXLINE))) {
- perror ("malloc");
- exit (-1);
+ syslog(LOG_NOTICE,
+ "vacation: can't allocate memory for virtual domain.\n");
+ closelog();
+ EXITM(-1);
}
(void) strcpy( vusername, pw->pw_name);
strcat( vusername, "@");
@@ -231,10 +335,17 @@ int main(int argc, char **argv)
}
} else
(void) gdbm_close(db);
+ closelog();
exit(0);
/* NOTREACHED */
}
+static void eatmsg()
+{
+ while (getc(stdin) != EOF)
+ continue;
+}
+
/*
* readheaders --
* read mail headers
@@ -246,8 +357,6 @@ void readheaders(void)
int tome, cont;
char buf[MAXLINE];
char uucpfrom[MAXLINE];
-// char sender[MAXLINE];
-// char domain[MAXLINE];
cont = tome = 0;
while (fgets(buf, sizeof(buf), stdin) && *buf != '\n')
@@ -292,7 +401,7 @@ void readheaders(void)
*p = '\0';
}
else
- exit (1); /* this should not occur */
+ EXITIT (1); /* this should not occur */
if ((p = rindex(uucpfrom, '!')))
strcat(from, p+1);
else
@@ -303,7 +412,7 @@ void readheaders(void)
printd (logline);
#endif
if (junkmail())
- exit(0);
+ EXITIT(0);
break;
case 'R': /* "Reply-To: " */
cont = 0;
@@ -318,7 +427,7 @@ void readheaders(void)
printd (logline);
#endif
if (junkmail())
- exit(0);
+ EXITIT(0);
}
break;
case 'S': /* "Subject" */
@@ -332,7 +441,7 @@ void readheaders(void)
printd (logline);
#endif
if (junkmail())
- exit(0);
+ EXITIT(0);
}
break;
case 'P': /* "Precedence:" */
@@ -348,7 +457,12 @@ void readheaders(void)
if (!strncasecmp(p, "junk", 4) ||
!strncasecmp(p, "list", 4) ||
!strncasecmp(p, "bulk", 4))
- exit(0);
+ EXITIT(0);
+ break;
+ case 'X': /* "To:" */
+ cont = 0;
+ if (strncasecmp(buf, "X-Spam-Flag: YES", 16) == 0)
+ EXITIT(0);
break;
case 'C': /* "Cc:" */
if (strncasecmp(buf, "Cc:", 3))
@@ -368,12 +482,15 @@ void readheaders(void)
findme:
for (cur = names; !tome && cur; cur = cur->next)
tome += nsearch(cur->name, buf);
- }
+
+ } /* switch(toupper(*buf)) */
+
if (!jflag && !tome)
- exit(0);
+ EXITIT(0);
if (!*from) {
syslog(LOG_NOTICE, "vacation: no \"From:\" line.\n");
- exit(2);
+ closelog();
+ EXITIT(2);
}
if (rflag && (*replyto != 0x0))
strcpy (from, replyto);
@@ -418,7 +535,9 @@ int junkmail(void)
{"List-Owner", 10}, {"List-Archive", 12},
{"-request", 8}, {"postmaster", 10}, {"uucp", 4},
{"mailer-daemon", 13}, {"mailer", 6}, {"-relay", 6},
- {"-activists", 10}, {"-programmers", 12}, {NULL, 0},
+ {"-activists", 10}, {"-programmers", 12}, {"bugzilla-daemon", 15},
+ {"noreply", 7}, {"board", 5}, {"info", 4},
+ {NULL, 0}
};
register struct ignore *cur;
register int len;
@@ -515,6 +634,7 @@ void setreply(void)
/*
* sendmessage --
* exec sendmail to send the vacation file to sender
+ * A "Precedence: bulk" header is automatically added to the message.
*/
void
sendmessage(char *myname, char *myrealname)
@@ -526,12 +646,16 @@ sendmessage(char *myname, char *myrealna
char buf[MAXLINE];
char line[MAXLINE];
- if ((p = index(myrealname, ','))) { /* realname with , ? */
+ if ((p = index(myrealname, ','))) { /* realname with , ? */
*p = '\0'; /* let string end here */
}
- while(( p = index(myrealname,' '))){
+ /* realname beginning with - or ` ' ? */
+ while (myrealname && (*myrealname == '-' || *myrealname == ' ')) {
+ myrealname++; /* skip `-' */
+ }
+ while((p = index(myrealname,' '))) {
*p = '_'; /* replace all blanks to underlines */
- }
+ }
if (index(myrealname, '(') || index(myrealname, ')')){
*buf='\"'; /* put " around realnames with () */
(void) strcpy(buf+1, myrealname);
@@ -547,15 +671,18 @@ sendmessage(char *myname, char *myrealna
mfp = fopen(VMSG, "r");
if (mfp == NULL) {
syslog(LOG_NOTICE, "vacation: no ~%s/%s file.\n", myname, VMSG);
+ closelog();
exit(1);
}
if (pipe(pvect) < 0) {
syslog(LOG_ERR, "vacation: pipe: %s", strerror(errno));
+ closelog();
exit(1);
}
i = fork();
if (i < 0) {
syslog(LOG_ERR, "vacation: fork: %s", strerror(errno));
+ closelog();
exit(1);
}
if (i == 0) {
@@ -563,14 +690,15 @@ sendmessage(char *myname, char *myrealna
close(pvect[0]);
close(pvect[1]);
fclose(mfp);
- execl(_PATH_SENDMAIL, "sendmail", "-f", myname, "-F", buf, "--", from, NULL);
+ execl(_PATH_SENDMAIL, "sendmail", "-f", myname, "-F", buf, "--", from, NULL);
syslog(LOG_ERR, "vacation: can't exec %s: %s",
_PATH_SENDMAIL, strerror(errno));
+ closelog();
exit(1);
}
close(pvect[0]);
sfp = fdopen(pvect[1], "w");
- fprintf(sfp,"User-Agent: Vacation/1.2.6 http://vacation.sourceforge.net\n");
+ fprintf(sfp,"User-Agent: Vacation/1.2.6.2 http://vacation.sourceforge.net\n");
fprintf(sfp,"Precedence: bulk\n");
fprintf(sfp, "To: %s\n", from);
while (fgets(buf, sizeof buf, mfp)) {
@@ -606,7 +734,7 @@ sendmessage(char *myname, char *myrealna
void usage(void)
{
- puts ("usage: vacation [ -I ]");
+ puts ("usage: vacation [ -I | -i | -l ] [ -F ]");
puts ("or: vacation [ -j ] [ -a alias ] [ -h hostname ] [ -tN ] [ -r ] login");
exit(1);
}
@@ -616,7 +744,7 @@ void initialize (char *path, char *mynam
{
char *editor;
char ebuf[PATH_MAX];
- char c;
+ int c;
FILE *message;
FILE *oldmessage;
FILE *forward;
--- vacation.man
+++ vacation.man 2007-01-09 12:38:34.000000000 +0000
@@ -25,7 +25,9 @@ vacation \- reply to mail automatically
.SH SYNOPSIS
.B vacation
[
-.B \-I | \-i
+.B \-I | \-i | \-l
+] [
+.B \-F
]
.br
.B vacation
@@ -45,6 +47,7 @@ vacation \- reply to mail automatically
.B \-?
]
.I username
+.br
.SH DESCRIPTION
.IX vacation "" "\fLvacation\fR \(em automatic mail replies"
.LP
@@ -155,13 +158,45 @@ senders is made case-independant.
.SH OPTIONS
.TP
.B \-I
-Initialize the
+Or
+.B \-i
+initialize the
.B \&.vacation.db
file and start
.BR vacation .
+This should only be used on the command line, not
+in the
+.B \&.forward
+file.
+.TP
+.B \-F
+Force creation of
+.B \&.vacation.db
+even if the
+.B $\s-1HOME
+directory is identified as a NFS file system.
+Please note that the used data base is not portable
+between 32bit and 64bit architectures and also not
+portable between little and big endianess architectures
+even same bit-wide is used for. Therefore the
+initial creation of the
+.B \&.vacation.db
+should always happen on the server used for receiving
+mails for the specific user.
+.TP
+.B \-l
+List the content of the vacation database file
+including the address and the associated time of
+the last auto-response to that address.
+This should only be used on the command line, not
+in the
+.B \&.forward
+file.
.LP
If the
-.B \-I
+.BR \-I ,\ \-i
+or
+.B \-l
flag is not specified, and a
.I user
argument is given,
--- vaclook
+++ vaclook 2006-08-25 15:36:57.000000000 +0200
@@ -1,14 +1,4 @@
-#!/usr/bin/perl
+#!/bin/sh
#
-# $Id: vaclook,v 1.1 2000/05/12 23:31:46 thecivvie Exp $
-require 5; # This script requires Perl v5.
-use GDBM_File; # Format that 'vacation' uses.
-
-# Associate the file with local hash.
-tie (%vacdb, GDBM_File, "$ENV{'HOME'}/.vacation.db", 0, undef);
-
-# Dump the contents (with converted time-stamps).
-map {
- printf ("%-36s %.36s\n", "$_:", scalar (localtime (unpack ('i', $vacdb{$_}))))
- } sort keys %vacdb;
+exec /usr/bin/vacation -lF