#/usr/local/bin/perl
#
# vacation program
# Larry Wall <
[email protected]>
#
# updates by Tom Christiansen <
[email protected]>
$vacation = $0;
$vacation = '/usr/local/bin/nvacation' unless $vacation =~ m#^/#;
$user = $ENV{'USER'} || $ENV{'LOGNAME'} || getlogin || (getpwuid($>))[0];
$editor = $ENV{'VISUAL'} || $ENV{'EDITOR'} || 'vi';
$pager = $ENV{'PAGER'} || 'more';
$default_msg = <<'EOF';
I will not be reading my mail for a while.
Your mail regarding "$SUBJECT" will be read when I return.
EOF
if (!@ARGV) { # interactive use, a la Sun
&interactive();
die "not reached";
}
@ignores = (
'daemon',
'postmaster',
'mailer-daemon',
'mailer',
'root',
);
# set-up time scale suffix ratios
%scale = (
's', 1,
'm', 60,
'h', 60 * 60,
'd', 24 * 60 * 60,
'w', 7 * 24 * 60 * 60,
);
while ($ARGV[0] =~ /^-/) {
$_ = shift;
if (/^-I/i) { # eric allman's source has both cases
chdir;
&initialize;
exit;
} elsif (/^-j/) {
$opt_j++;
} elsif (/^-f(.*)/) {
&save_file($1 ? $1 : shift);
} elsif (/^-a(.*)/) {
&save_alias($1 ? $1 : shift);
} elsif (/^-t([\d.]*)([smhdw])/) {
$timeout = $1;
$timeout *= $scale{$2} if $2;
} else {
die "Unrecognized switch: $_\n";
}
}
if (!@ARGV) {
&interactive();
die "not reached";
}
$user = shift;
push(@ignores, $user);
push(@aliases, $user);
die "Usage: vacation username\n" if $user eq '' || @ARGV;
$home = (getpwnam($user))[7];
die "No home directory for user $user\n" unless $home;
chdir $home || die "Can't chdir to $home: $!\n";
$timeout = 7 * 24 * 60 * 60 unless $timeout;
dbmopen(VAC, ".vacation", 0666) || die "Can't open vacation dbm files: $!\n";
$/ = ''; # paragraph mode
$header = <>;
$header =~ s/\n\s+/ /g; # fix continuation lines
$* = 1;
exit if $header =~ /^Precedence:\s*(bulk|junk)/i;
exit if $header =~ /^From.*-REQUEST@/i;
for (@ignores) {
exit if $header =~ /^From.*\b$_\b/i;
}
($from) = ($header =~ /^From\s+(\S+)/); # that's the Unix-style From line
die "No \"From\" line!!!!\n" if $from eq "";
($subject) = ($header =~ /Subject:\s+(.*)/);
$subject = "(No subject)" unless $subject;
$subject =~ s/\s+$//;
($to) = ($header =~ /To:\s+(.*)/);
($cc) = ($header =~ /Cc:(\s+.*)/);
$to .= ', '.$cc if $cc;
if (open(MSG,'.vacation.msg')) {
undef $/;
$msg = <MSG>;
close MSG;
} else {
$msg = $default_msg;
}
$msg =~ s/\$SUBJECT/$subject/g; # Sun's vacation does this
unless ($opt_j) {
foreach $name (@aliases) {
$ok++ if $to =~ /\b$name\b/;
}
exit unless $ok;
}
$lastdate = $VAC{$from};
$now = time;
if ($lastdate ne '') {
($lastdate) = unpack("L",$lastdate);
exit unless $lastdate;
exit if $now < $lastdate + $timeout;
}
$VAC{$from} = pack("L", $now);
dbmclose(VAC);
open(MAIL, "|/usr/lib/sendmail -oi -t $from") || die "Can't run sendmail: $!\n";
print MAIL <<EOF;
To: $from
#Subject: This is a recording... [Re: $subject]
Precedence: junk
EOF
print MAIL $msg;
close MAIL;
exit;
sub yorn {
local($answer);
for (;;) {
print $_[0];
$answer = <STDIN>;
last if $answer =~ /^[yn]/i;
print "Please answer \"yes\" or \"no\" ('y' or 'n')\n";
}
$answer =~ /^y/i;
}
sub interactive {
chdir;
chop($cwd = `pwd`);
&disable if -f '.forward';
print <<EOF;
This program can be used to answer your mail automatically
when you go away on vacation.
EOF
for (;;) {
if (-f '.vacation.msg') {
print "\nYou already have a message file in $cwd/.vacation.msg.\n";
$see = &yorn("Would you like to see it? ");
system $pager, '.vacation.msg' if $see;
$edit = &yorn("Would you like to edit it? ");
}
else {
&make_default;
print <<EOF;
I've created a default vacation message in ~/.vacation.msg. This
message will be automatically returned to anyone sending you mail while
you're out.
Press return when ready to continue, and you will enter your favorite
editor ($editor) to edit the messasge to your own tastes.
EOF
$| = 1;
print "Press return to continue: ";
<STDIN>;
$edit = 1;
}
last unless $edit;
system $editor, '.vacation.msg';
last;
}
print "\nTo enable the vacation feature a \".forward\" file is created.\n";
if (&yorn("Would you like to enable the vacation feature now? ")) {
&initialize;
print <<EOF;
Ok, vacation feature ENABLED. Please remember to turn it off when
you get back from vacation. Bon voyage!
EOF
}
else {
print "Ok, vacation feature NOT enabled.\n";
}
exit;
}
sub initialize {
&zero('.vacation.pag');
&zero('.vacation.dir');
open(FOR, ">.forward") || die "Can't create .forward: $!\n";
print FOR "\\$user, \"|$vacation $user\"\n";
close FOR;
&make_default;
}
sub zero {
local($FILE) = @_;
open (FILE, ">$FILE") || die "can't creat $FILE: $!";
close FILE;
}
sub save_file {
local($FILE) = @_;
local($_);
open FILE || die "can't open $FILE: $!";
while (<FILE>) {
push(@ignores, split);
}
close FILE;
}
sub disable {
print "\nYou have a .forward file in your home directory containing: ",
"\n",
`cat .forward`,
"\n";
if (&yorn(
"Would you like to remove it and disable the vacation feature? ")) {
unlink('.forward') || die "Can't unlink .forward: $!\n";
dbmopen(VAC, '.vacation', 0444) || die "no .vacation dbmfile\n";
sub byvalue { $VAC{$a} <=> $VAC{$b}; }
if (@keys = sort byvalue keys %VAC) {
require 'ctime.pl';
open (PAGER, "|$pager") || die "can't open $pager: $!";
print PAGER <<EOF;
While you were away, mail was sent to the following addresses:
EOF
for $key (@keys) {
($when) = unpack("L", $VAC{$key});
printf PAGER "%-20s %s", $key, &ctime($when);
}
close PAGER;
}
print "Back to normal reception of mail.\n";
exit;
} else {
print "Ok, vacation feature NOT disabled.\n";
}
}
sub make_default {
return if $edit;
open(MSG, ">.vacation.msg") || die "Can't create .vacation.msg: $!\n";
print MSG $default_msg;
close MSG;
}