532 lines
13 KiB
Diff
532 lines
13 KiB
Diff
---
|
|
vacation-1.2.7.1/Makefile | 11 --
|
|
vacation-1.2.7.1/vacation-en.man | 38 +++++++
|
|
vacation-1.2.7.1/vacation.c | 195 ++++++++++++++++++++++++++++++++-------
|
|
vacation-1.2.7.1/vaclook | 16 ---
|
|
4 files changed, 199 insertions(+), 61 deletions(-)
|
|
|
|
--- vacation-1.2.7.1/Makefile
|
|
+++ vacation-1.2.7.1/Makefile 2017-02-01 09:10:03.746060561 +0000
|
|
@@ -13,17 +13,8 @@ CFLAGS = $(RPM_OPT_FLAGS) -g -Wall
|
|
ifeq "$(ARCH)" "x86_64"
|
|
# Uncomment below for backwards compatibility of gdbm files.
|
|
# CFLAGS = $(CFLAGS) -m32
|
|
-else
|
|
-ifeq "$(ARCH)" "ppc"
|
|
- CFLAGS = $(CFLAGS) -fsigned-char
|
|
-else
|
|
-ifeq "$(ARCH)" "ppc64"
|
|
- CFLAGS = $(CFLAGS) -fsigned-char
|
|
-endif
|
|
-endif
|
|
endif
|
|
|
|
-LFLAGS = -Xlinker -warn-common
|
|
IFLAGS =
|
|
|
|
LIBS = -lgdbm
|
|
@@ -45,7 +36,7 @@ endif
|
|
BINDIR = $(PREFIX)/bin
|
|
VACATION = $(BINDIR)/vacation
|
|
VACLOOK = $(BINDIR)/vaclook
|
|
-MANDIR = $(PREFIX)/man/man
|
|
+MANDIR = $(PREFIX)/share/man/man
|
|
MANEXT1 = 1
|
|
|
|
VERSION = 1
|
|
--- vacation-1.2.7.1/vacation-en.man
|
|
+++ vacation-1.2.7.1/vacation-en.man 2017-02-01 09:10:03.746060561 +0000
|
|
@@ -25,8 +25,9 @@ vacation \- reply to mail automatically
|
|
.SH SYNOPSIS
|
|
.B vacation
|
|
[
|
|
-.B \-I | \-i
|
|
-]
|
|
+.B \-I | \-i | \-l
|
|
+] [
|
|
+.B \-F
|
|
.br
|
|
.B vacation
|
|
[
|
|
@@ -48,6 +49,7 @@ vacation \- reply to mail automatically
|
|
.B \-?
|
|
]
|
|
.I username
|
|
+.br
|
|
.SH DESCRIPTION
|
|
.IX vacation "" "\fLvacation\fR \(em automatic mail replies"
|
|
.LP
|
|
@@ -162,9 +164,39 @@ 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,
|
|
--- vacation-1.2.7.1/vacation.c
|
|
+++ vacation-1.2.7.1/vacation.c 2017-02-01 09:16:24.158138617 +0000
|
|
@@ -76,6 +76,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>
|
|
@@ -91,6 +92,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
|
|
+
|
|
/* Extern definitions for getopt(3) */
|
|
extern int optind, opterr;
|
|
extern char *optarg;
|
|
@@ -110,14 +118,15 @@ 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;
|
|
char tmpusername[ 1024 ];
|
|
|
|
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
|
|
@@ -125,16 +134,16 @@ 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:Iit:jrv")) != 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;
|
|
@@ -163,6 +172,12 @@ main (int argc, char **argv)
|
|
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 'v': /* Output vacation version number */
|
|
printf ("Linux Vacation %s\n", VACVERS);
|
|
exit (0);
|
|
@@ -175,32 +190,68 @@ 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)))
|
|
{
|
|
snprintf( tmpusername, 1023, "%s", *argv );
|
|
syslog (LOG_ERR, "vacation: no such user %s.\n", tmpusername);
|
|
- 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 database file!\n\n"
|
|
+ ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n"
|
|
+ "Please run vacation on the mail delivering server, which is\n"
|
|
+ "normally 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 database 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 ((char *) VDB, 128, ((iflag || nflag) ? GDBM_NEWDB : GDBM_WRITER),
|
|
- 0644, NULL);
|
|
+ db = gdbm_open ((char *) VDB, 128, flags, 0644, NULL);
|
|
if (!db && errno == ENOENT)
|
|
{
|
|
db = gdbm_open ((char *) VDB, 128, GDBM_NEWDB, 0644, NULL);
|
|
@@ -210,12 +261,56 @@ main (int argc, char **argv)
|
|
}
|
|
while (!db && errno == EAGAIN);
|
|
|
|
- if (!db)
|
|
- {
|
|
- syslog (LOG_NOTICE, "vacation: %s: %s\n", VDB, strerror (errno));
|
|
- exit (1);
|
|
+ if (!db) {
|
|
+ char *errm;
|
|
+ if (errno == 0)
|
|
+ errm = gdbm_strerror(gdbm_errno);
|
|
+ else
|
|
+ errm = gdbm_strerror(errno);
|
|
+ if (lflag || iflag || nflag) {
|
|
+ fprintf(stderr, "vacation: %s: %s\n", (char *) VDB, errm);
|
|
+ close(0);
|
|
+ }
|
|
+ syslog(LOG_NOTICE, "vacation: %s: %s\n", (char *) 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)
|
|
setinterval (interval);
|
|
|
|
@@ -232,8 +327,11 @@ main (int argc, char **argv)
|
|
exit (0);
|
|
}
|
|
|
|
- if (!(cur = (ALIAS *) malloc ((u_int) sizeof (ALIAS))))
|
|
- exit (1);
|
|
+ if (!(cur = (ALIAS *) 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;
|
|
@@ -250,8 +348,9 @@ main (int argc, char **argv)
|
|
{ /* add virtual domain to username */
|
|
if (!(vusername = (char *) malloc (MAXLINE)))
|
|
{
|
|
- perror ("malloc");
|
|
- exit (-1);
|
|
+ syslog(LOG_NOTICE, "vacation: cant' allocation memory for virtual domain.\n");
|
|
+ closelog();
|
|
+ EXITM(-1);
|
|
}
|
|
(void) strlcpy (vusername, pw->pw_name, MAXLINE);
|
|
strlcat (vusername, "@", MAXLINE);
|
|
@@ -266,10 +365,17 @@ 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
|
|
@@ -322,7 +428,7 @@ readheaders (void)
|
|
*p = '\0';
|
|
}
|
|
else
|
|
- exit (1); /* this should not occur */
|
|
+ EXITIT (1); /* this should not occur */
|
|
if ((p = rindex (uucpfrom, '!')))
|
|
strlcat (from, p + 1, MAXLINE);
|
|
else
|
|
@@ -333,7 +439,7 @@ readheaders (void)
|
|
printd (logline);
|
|
#endif
|
|
if (junkmail ())
|
|
- exit (0);
|
|
+ EXITIT (0);
|
|
break;
|
|
case 'R': /* "Reply-To: " */
|
|
cont = 0;
|
|
@@ -345,7 +451,7 @@ readheaders (void)
|
|
printd (logline);
|
|
#endif
|
|
if (junkmail ())
|
|
- exit (0);
|
|
+ EXITIT (0);
|
|
}
|
|
break;
|
|
case 'S': /* "Subject" */
|
|
@@ -360,7 +466,7 @@ readheaders (void)
|
|
printd (logline);
|
|
#endif
|
|
if (junkmail ())
|
|
- exit (0);
|
|
+ EXITIT (0);
|
|
}
|
|
break;
|
|
case 'P': /* "Precedence:" */
|
|
@@ -375,7 +481,7 @@ readheaders (void)
|
|
break;
|
|
if (!strncasecmp (p, "junk", 4) ||
|
|
!strncasecmp (p, "list", 4) || !strncasecmp (p, "bulk", 4))
|
|
- exit (0);
|
|
+ EXITIT (0);
|
|
break;
|
|
case 'A': /* "Auto-Submitted:" */
|
|
cont = 0;
|
|
@@ -388,8 +494,12 @@ readheaders (void)
|
|
if (!*p)
|
|
break;
|
|
if (strncasecmp (p, "no", 2))
|
|
- exit (0);
|
|
+ EXITIT (0);
|
|
break;
|
|
+ case 'X': /* "To:" */
|
|
+ cont = 0;
|
|
+ if (strncasecmp(buf, "X-Spam-Flag: YES", 16) == 0)
|
|
+ EXITIT (0);
|
|
case 'C': /* "Cc:" */
|
|
if (strncasecmp (buf, "Cc:", 3))
|
|
break;
|
|
@@ -400,10 +510,6 @@ readheaders (void)
|
|
break;
|
|
cont = 1;
|
|
goto findme;
|
|
- case 'X': /* Don't reply to email marked as spam by SpamAssassin */
|
|
- if (!strncasecmp (buf, "X-Spam-Status: Yes", 18))
|
|
- exit (0);
|
|
- break;
|
|
default:
|
|
if (!isspace (*buf) || !cont || tome)
|
|
{
|
|
@@ -413,13 +519,15 @@ 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))
|
|
strlcpy (from, replyto, MAXLINE);
|
|
@@ -503,7 +611,19 @@ junkmail (void)
|
|
{
|
|
"-programmers", 12},
|
|
{
|
|
- NULL, 0},};
|
|
+ "bugzilla-daemon", 15},
|
|
+ {
|
|
+ "noreply", 7},
|
|
+ {
|
|
+ "no-reply", 8},
|
|
+ {
|
|
+ "info", 4},
|
|
+ {
|
|
+ "nobody", 6},
|
|
+ {
|
|
+ "keine.Antwort", 13},
|
|
+ {
|
|
+ NULL, 0},};
|
|
register struct ignore *cur;
|
|
register int len;
|
|
register char *p;
|
|
@@ -609,6 +729,7 @@ 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)
|
|
@@ -628,17 +749,20 @@ sendmessage (char *myname, char *myrealn
|
|
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)
|
|
@@ -651,6 +775,7 @@ sendmessage (char *myname, char *myrealn
|
|
NULL);
|
|
syslog (LOG_ERR, "vacation: can't exec %s: %s", _PATH_SENDMAIL,
|
|
strerror (errno));
|
|
+ closelog();
|
|
exit (1);
|
|
}
|
|
close (pvect[0]);
|
|
@@ -699,7 +824,7 @@ sendmessage (char *myname, char *myrealn
|
|
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);
|
|
--- vacation-1.2.7.1/vaclook
|
|
+++ vacation-1.2.7.1/vaclook 2017-02-01 09:10:03.746060561 +0000
|
|
@@ -1,14 +1,4 @@
|
|
-#!/usr/bin/perl
|
|
+#!/bin/sh
|
|
#
|
|
-# $Id$
|
|
-
|
|
-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
|