#/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;
}