Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!swrinde!zaphod.mps.ohio-state.edu!sdd.hp.com!elroy.jpl.nasa.gov!jpl-devvax!lwall From: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Newsgroups: comp.lang.perl Subject: Re: Perly mail filters (?) Message-ID: <9416@jpl-devvax.JPL.NASA.GOV> Date: 6 Sep 90 19:01:33 GMT References: <90Sep5.070222edt.18759@me.utoronto.ca> <1990Sep5.161205.26295@iwarp.intel.com> Reply-To: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Distribution: comp Organization: Jet Propulsion Laboratory, Pasadena, CA Lines: 421 Here's my mailagent. The mailpatch stuff should be in Perl, but I'm lazy. Note that this mailagent is BSD specific in several ways, such as how to lock mail files and where to find them. Hmm. Maybe this should go in the book... Larry #!/bin/sh : make a subdirectory, cd to it, and run this through sh. echo 'If this kit is complete, "End of kit" will echo at the end' echo Extracting mailagent sed >mailagent <<'!STUFFY!FUNK!' -e 's/X//' X#!/usr/bin/perl X X# You'll need to set up a .forward file that feeds your mail to this script. X# Mine looks like this: X# "| /u/sfoc/lwall/bin/mailagent /u/sfoc/lwall lwall Larry >>/u/sfoc/lwall/.maillog 2>&1" X X($HOME, $USER, $NAME) = @ARGV; X X$ENV{'PATH'}="$HOME/bin:/bin:/usr/bin:/usr/ucb"; X$ENV{'IFS'} = '' if $ENV{'IFS'}; X X$LOCK_SH = 1; X$LOCK_EX = 2; X$LOCK_NB = 4; X$LOCK_UN = 8; X X$hostname = `hostname`; X Xif ($hostname !~ /vax/) { X $rsh = 'rsh basvax' if $hostname =~ /mhr/; X open(MAILER,"| $rsh /bin/mail $USER@basvax"); X while () { X print MAILER; X } X exit 0; X} X Xopen(MBOX, ">>/usr/spool/mail/$USER") || die "Can't open mailbox ($< $>): $!"; X Xopen(MBAK,">>$HOME/mailbackup"); X Xopen(PUBOX,">>$HOME/pu"); X Xif (!$NAME || !(chdir $HOME)) { X do lock(); X while () { X $pu = 1 if /^From perl-users/; X print MBAK; X print MBOX; X print PUBOX if $pu; X } X print MBAK "\n\n"; X print MBOX "\n\n"; X print PUBOX "\n\n" if $pu; X exit 0; X} X Xchop($HOME=`pwd`); X$ENV{'HOME'} = $HOME; X$ENV{'USER'} = $USER; X$ENV{'NAME'} = $NAME; X Xumask(022); X X$dest = $USER; X$cmd = ''; Xline: while () { X if (1 .. /^\s*$/) { X $pu = 1 if /^From perl-users/; X s/^From: ([^<]*)\s+<(.*)>$/From: $2 ($1)/; X s/^(From: .*Mailer-Daemon@)([^(]*)\(/$1$2($2/i; X $header .= $_; X chop; X if (/^\s*$/) { X foreach $key (keys(header)) { X eval "\$H$key = \$header{'$key'}"; X } X } X else { X /^From ([^ ]*).*$/ && ($dest = $1, next); X if (s/^([-\w]+):\s*//) { X ($headline = $1) =~ y/A-Z-/a-z_/; X $header{$headline} .= "\n" if $header{$headline} ne ''; X } X else { X s/^\s+/ /; X } X $header{$headline} .= $_; X } X } X else { X $body .= $_; X /^@RR/ && ($ack = 1); X s/^ @SH/@SH/; X if (/^@SH/) { X if (!($gotcmds++) && open(CMD,"$HOME/.commands")) { X while ($foo = ) { X chop($foo); X $command{$foo} = 1; X } X close(CMD); X } X s/\\!/!/g; X if (/[=$^&*([{}`\\|;>?]/) { X s/^@SH/bad cmd:/; X $bad .= $_; X next line; X } X s/ PATH/ $dest/; X s/SH mailpath/SH mailpatch/; X s/SH mailpatch (\w)@(\w)\s/SH mailpatch $2!$1 /; X s/@SH\s*//; X ($first) = split; X $command{'mailpatch'} = 1; X if (!$command{$first}) { X s/^/unk cmd "$first":/; X $bad .= $_; X next line; X } X $cmd .= $_; X } X } X} X X$all = $header . $body; X Xif (open(TWITS,'.twitlist')) { X while () { X chop; X ++$suppress{$_}; X } X close TWITS; X} X X$suppress = 1 if X# $Hto =~ /admin/ || X# $Happarently_to =~ /admin/ || X# $Hcc =~ /admin/ || X $body =~ /I got your message, whatever it was/; X Xif ($cmd) { X $body =~ s/\n\s*@SH.*//g; # delete @SH lines X $body =~ s/\n[ \t]*-[^\0]*//; # delete signature. X $body =~ s/\n\s*thank(s| ?you|s in advance)[,.]?\s*//i; X $body =~ s/\n\s*atdhvaannkcse[,.]?\s*//i; X $body =~ s/\n\s*Thank[^.!,]*.//; X $body =~ s/"[^"]*"//g; # don't count quotes. X $body =~ s/ / /g; # so the next thing works right X $normwords = ($body =~ s/ [a-z]+ //g); # count normal words X $justcmds = 1 if $normwords < 3; # Probably is a signature. X} X X$suppress = 1 if $justcmds; X$suppress = 1 if $suppress{$dest}; X X$suppress = "[suppress]\n" if $suppress; X X$local = ($dest =~ /^[a-zA-Z_0-9@]+$/); # disallow "." and "!", primarily X X$Hto =~ s/.*(<.*>).*/$1/; X$mailinglist = ($Hto =~ /\S+\s+\S+/ || $Hto !~ /lwall/); X Xif ($dest ne $USER) { X X if ($cmd ne '' && ($justcmds || $Hsubject =~ /^command$/i)) { X open(CMD,">/tmp/mess.cmd$$"); X print CMD "set -x\n",$cmd; X close CMD; X $tmp = `sh -x /tmp/mess.cmd$$ 2>&1`; X if ($?) { X open(MAILER,"|/bin/mail $dest $USER"); X print MAILER X"Subject: the following returned a non-zero status XTo: $dest X X$tmp X Xmailagent speaking for $USER X"; X close MAILER; X $all .= "[Command failed]\n"; X $suppress = ''; X } X unlink "/tmp/mess.cmd$$"; X } X X $ack = 0 if $dest =~ /DAEMON/; X if ($ack) { X open(MAILER,"|/bin/mail $dest $USER"); X print MAILER X"Subject: $Hsubject XTo: $dest X XHere is the receipt you requested. X Xmailagent speaking for $USER X"; X close MAILER; X $all .= "[Acked]\n"; X } X X if ($bad) { X open(MAILER,"|/bin/mail $dest $USER"); X print MAILER X"Subject: the following commands were not executed XTo: $dest X X$bad X XIf $NAME can figure out what you wanted he may do it anyway. X Xmailagent speaking for $USER X"; X close MAILER; X $all .= "[Bad Command]\n"; X $suppress = ''; X } X X if (!$ack && !$local && !$mailinglist && $Hsubject !~ /^Forwarded:/) { X if ($cmd eq '') { # not a command X if ($dest !~ /mailer-daemon|postmaster/i) { X open(VACATION,"|vacation lwall"); X print VACATION $all; X close VACATION; X $all .= "[Vacation]\n"; X } X } X } X X# if ($local) { X# $all =~ s/From: (.*)\(/From: $1(#/; X# } X} Xif ($all =~ /^From willie@sm.unisys.com/) { X $all =~ s/^.*Unsent message follows -*\n//i && X $all =~ s/Subject: /Subject: (W) /; X} X X$all =~ s/Subject: /Subject: (S) / if $suppress; X Xdo lock(); Xprint MBOX $all,$suppress,"\n\n"; Xprint MBAK $all,"\n\n"; Xprint PUBOX $all,"\n\n" if $pu; Xdo unlock(); X Xsub lock { X eval 'flock(MBOX,$LOCK_EX);'; X seek(MBOX, 0, 2); # in case some appended while we were waiting X seek(MBAK, 0, 2); # one lock covers both files X} X Xsub unlock { X eval 'flock(MBOX,$LOCK_UN);'; X seek(MBOX, 0, 2); # in case some appended while we were waiting X seek(MBAK, 0, 2); # one lock covers both files X} !STUFFY!FUNK! echo Extracting mailpatch sed >mailpatch <<'!STUFFY!FUNK!' -e 's/X//' X#!/bin/sh X X# You'll have to customize this to know about your own packages. Also, copy X# rangeargs to your private bin directory, or change invocations below. X Xcmd=`date`" $@ " Xcd $HOME X Xdest=$1 Xshift Xsystem=$1 Xshift Xversion=$1 Xshift Xcase "$system" in Xdist|DIST) X cd /u/sfoc/lwall/src/dist/bugs X maxnum=`/bin/sed -n -e 's/^[^0-9]*\([1-9][0-9]*\).*$/\1/p' ../patchlevel.h` X curversion='2.0' X ;; Xperl|PERL) X cd /usr/spool/ftp/pub/perl.3.0/patches X maxnum=`/bin/sed -n -e 's/^[^0-9]*\([1-9][0-9]*\).*$/\1/p' ../patchlevel.h` X curversion='3.0' X ;; Xrn|RN) X cd /u/sfoc/lwall/src/rn/bugs X maxnum=`/bin/sed -n -e 's/^[^0-9]*\([1-9][0-9]*\).*$/\1/p' ../patchlevel` X curversion='4.3' X ;; Xpatch|PATCH) X cd /u/sfoc/lwall/src/patch/bugs X maxnum=`/bin/sed -n -e 's/^[^0-9]*\([1-9][0-9]*\).*$/\1/p' ../patchlevel.h` X curversion='2.0' X ;; Xwarp|WARP) X cd /u/sfoc/lwall/src/warp/bugs X maxnum=`/bin/sed -n -e 's/^[^0-9]*\([1-9][0-9]*\).*$/\1/p' ../patchlevel.h` X curversion='7.0' X ;; Xcdiff|cdiff) X cd /u/sfoc/lwall/src/cdiff/bugs X maxnum=`/bin/sed -n -e 's/^[^0-9]*\([1-9][0-9]*\).*$/\1/p' ../patchlevel.h` X curversion='1.1' X ;; X*) X /bin/mail $dest $USER <> $HOME/.patchlog X exit 1 X ;; Xesac X Xcase "$version" in X$curversion) ;; X*) X /bin/mail $dest $USER <> $HOME/.patchlog X exit 1 X ;; Xesac X Xargs="$*" X Xset X `$HOME/bin/rangeargs -m "$maxnum" $*` Xshift X Xcase $# in X0) set X `$HOME/bin/rangeargs -m 100 $args` X shift X set $1 X ;; Xesac X Xfor num do X /bin/cat </tmp/mp$$ XTo: $dest XSubject: $system version $version patch #$num X X[The latest patch for $system version $version is #$maxnum.] X Xmailpatch speaking for $USER X XEOM X if test -f patch$num; then X /bin/cat >/tmp/mp$$ X /bin/echo "### End of Patch $num ###" >>/tmp/mp$$ X fi X /usr/lib/sendmail -odq -t > $HOME/.patchlog !STUFFY!FUNK! echo Extracting rangeargs.c sed >rangeargs.c <<'!STUFFY!FUNK!' -e 's/X//' X#include X#include Xmain(argc,argv) Xint argc; Xchar **argv; X{ X register int i; X register int min, max; X int maxspec = 0; X register char *s; X X for (argc--,argv++; argc; argc--,argv++) { X if (strcmp(argv[0],"-m")==0) { X argc--,argv++; X maxspec=atoi(argv[0]); X continue; X } X s = argv[0]; X while (*s) { X min=atoi(s); X while (*s && !isdigit(*s)) X s++; X while (isdigit(*s)) X s++; X if (*s == ',') { X max = min; X s++; X } X else if (*s == '-') { X max = atoi(s+1); X if (max == 0 && maxspec) X max=maxspec; X while (*s && *s != ',') X s++; X if (*s) X s++; X } X else max=min; X for (i=min; i<=max; i++) { X printf("%d",i); X if (i != max || argc || *s) X putchar(' '); X } X } X } X putchar('\n'); X} !STUFFY!FUNK! echo "" echo "End of kit" : I do not append .signature, but someone might mail this. exit