c766a037f22fbf96cd71b74ee0c929a7c631dc51
** Copyright (c) 1983 Eric P. Allman
** 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.
static char SccsId
[] = "@(#)vacation.c 5.6 (Berkeley) %G%";
** 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.
#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 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 */
static int debug
; /* debugging flag */
while ((ch
= getopt(argc
, argv
, "Idi")) != EOF
)
case 'i': /* init the database */
case 'I': /* backward compatible */
case 'd': /* debugging */
/* find and move to user's home directory */
if (!(pw
= getpwuid(getuid())) || chdir(pw
->pw_dir
)) {
fprintf(stderr
, "vacation: no such user uid %u.\n", getuid());
syslog(LOG_ERR
, "vacation: no such user uid %u.\n", getuid());
else if (!(pw
= getpwnam(*argv
)) || chdir(pw
->pw_dir
)) {
fprintf(stderr
, "vacation: no such user %s.\n", *argv
);
syslog(LOG_ERR
, "vacation: no such user %s.\n", *argv
);
/* iflag cleans out the database */
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
);
fprintf(stderr
, "===== %s", ctime(&now
));
* if database missing, we create it and do a dbminit;
* otherwise, just do the dbminit.
/* find out who sent us mail */
from
= getfrom(&shortfrom
);
printf("from='%s'\nshortfrom='%s'\n", from
, shortfrom
);
* ignore if recently replied to this address,
* else note the time and send a reply
sendmessage(from
, *argv
);
* read mail "From" line and return sender's address
if (!gets(buf
) || strncmp(buf
, "From ", 5)) {
fputs("vacation: no initial From line.\n", stderr
);
/* find the end of the sender address and terminate it */
for (p
= &buf
[5]; *p
&& *p
!= ' '; ++p
);
fprintf(stderr
, "vacation: address terminated From line '%s'\n", buf
);
if (!(p
= malloc((u_int
)(strlen(&buf
[5]) + 1)))) {
fputs("vacation: out of space.\n", stderr
);
* 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
printf("start='%s'\n", start
);
*shortp
= start
; /* assume whole addr */
if ((at
= index(start
, '@')) == NULL
) /* leftmost '@' */
at
= p
; /* if none, use end of addr */
if ((bang
= rindex(start
, '!')) != NULL
) { /* rightmost '!' */
if ((bang2
= rindex(start
, '!')) != NULL
) /* 2nd rightmost '!' */
*shortp
= bang2
+ 1; /* move past ! */
printf("place='%s'\n", *shortp
);
/* return the sender address */
* read the header and return if automagic/junk/bulk mail
"-REQUEST", 8, "Postmaster", 10,
"uucp", 4, "MAILER-DAEMON", 13,
register struct ignore
*I
;
* 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@seismo.css.gov
* From SENDER%site.BITNET@seismo.css.gov
* From site1!site2!SENDER@seismo.css.gov
* Therefore, the following search order:
if (!(p
= index(from
, '%')))
if (!(p
= index(from
, '@'))) {
if (p
= rindex(from
, '!'))
for (I
= ignore
; I
->name
; ++I
)
if (len
>= I
->len
&& !strncasecmp(I
->name
, p
- I
->len
, I
->len
)) {
fprintf(stderr
, "not sending to %s {%s}\n", from
, I
->name
);
/* read the header looking for a "Precedence:" line */
while (gets(buf
) && *buf
) {
if (strncasecmp(buf
, "Precedence", 10) ||
buf
[10] != ':' && buf
[10] != ' ' && buf
[10] != '\t')
/* find the value of this field */
if (!(p
= index(buf
, ':')))
while (*++p
&& isspace(*p
));
/* see if it is "junk" or "bulk" */
if (!strncasecmp(p
, "junk", 4) || !strncasecmp(p
, "bulk", 4)) {
fprintf(stderr
, "not sending to %s {junk/bulk}\n", from
);
* find out if user has gotten a vacation message recently.
k
.dsize
= strlen(user
) + 1;
bcopy(d
.dptr
, (char *)&ldbrec
, sizeof ldbrec
); /* realign data */
return ldbrec
.sentdate
+ Timeout
>= time((time_t *)0);
register char *to
, *from
;
* store that this user knows about the vacation.
k
.dsize
= strlen(user
) + 1;
/* zero is the flag value meaning *never* reply */
(void)time(&xrec
.sentdate
);
* exec sendmail to send the vacation file to "user".
sendmessage(user
, myname
)
fprintf(stderr
, "sending {%s} to {%s}\n", VMSG
, user
);
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
);
execl("/usr/lib/sendmail", "sendmail", "-f", myname
, user
, NULL
);
fprintf(stderr
, "vacation: can't exec /usr/lib/sendmail.\n");
syslog(LOG_ERR
, "vacation: can't exec /usr/lib/sendmail.\n");
* initialize the database
extern char *sys_errlist
[];
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
]);
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
]);
if (fp
= fopen(VIGN
, "r")) {
while (fgets(buf
, sizeof(buf
), fp
)) {
*(index(buf
, '\n')) = EOS
;
* print out a usage message and die
fputs("usage: vacation [-i] login\n", stderr
);
syslog(LOG_ERR
, "uid %u: usage: vacation [-i] login\n", getuid());