home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-11-20 | 54.6 KB | 1,850 lines |
- Newsgroups: comp.sources.misc
- From: ram@eiffel.com (Raphael Manfredi)
- Subject: v33i106: mailagent - Rule Based Mail Filtering, Part14/17
- Message-ID: <1992Nov20.230841.27156@sparky.imd.sterling.com>
- X-Md4-Signature: 112247dbfb2ef1c4f43313c9a26fabf6
- Date: Fri, 20 Nov 1992 23:08:41 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: ram@eiffel.com (Raphael Manfredi)
- Posting-number: Volume 33, Issue 106
- Archive-name: mailagent/part14
- Environment: Perl, Sendmail, UNIX
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: agent/files/Makefile.SH agent/files/mailagent.cf
- # agent/filter/lock.c agent/filter/sysexits.h agent/mhook.SH
- # agent/pl/builtins.pl agent/pl/context.pl agent/pl/distribs.pl
- # agent/pl/mbox.pl agent/pl/plsave.pl agent/pl/pqueue.pl
- # agent/test/Makefile.SH agent/test/README agent/test/rules
- # install.SH
- # Wrapped by kent@sparky on Wed Nov 18 22:42:31 1992
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 14 (of 17)."'
- if test -f 'agent/files/Makefile.SH' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agent/files/Makefile.SH'\"
- else
- echo shar: Extracting \"'agent/files/Makefile.SH'\" \(3518 characters\)
- sed "s/^X//" >'agent/files/Makefile.SH' <<'END_OF_FILE'
- X: Makefile.SH generated from Jmake.tmpl and Jmakefile [jmake 2.8 PL13]
- X: $X-Id: Jmake.tmpl,v 2.8.1.2 91/11/18 13:22:54 ram Exp $
- X
- Xcase $CONFIG in
- X'')
- X if test ! -f config.sh; then
- X ln ../config.sh . || \
- X ln ../../config.sh . || \
- X ln ../../../config.sh . || \
- X (echo "Can't find config.sh."; exit 1)
- X fi 2>/dev/null
- X . ./config.sh
- X ;;
- Xesac
- Xcase "$0" in
- X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
- Xesac
- XCURRENT=agent/files
- XDIR=`echo $CURRENT/ | sed -e 's/\.\///g'`
- Xecho "Extracting ${DIR}Makefile (with variable substitutions)"
- XDATE=`date`
- X$spitshell >Makefile <<!GROK!THIS!
- X########################################################################
- X# Makefile generated from Makefile.SH on $DATE
- X
- XSHELL = /bin/sh
- XJMAKE = jmake
- XTOP = ../..
- XCURRENT = $CURRENT
- XDIR = $DIR
- XINSTALL = ../../install
- X
- X########################################################################
- X# Parameters set by Configure -- edit config.sh if changes are needed
- X
- XCTAGS = ctags
- XMAKE = make
- XMV = $mv
- XPRIVLIB = $privlib
- XRM = $rm -f
- X
- X!GROK!THIS!
- X$spitshell >>Makefile <<'!NO!SUBS!'
- X
- X########################################################################
- X# Jmake rules for building libraries, programs, scripts, and data files
- X# $X-Id: Jmake.rules,v 2.8.1.4 91/11/18 13:19:07 ram Exp $
- X
- X########################################################################
- X# Start of Jmakefile
- X
- X# $X-Id: Jmakefile,v 2.9 92/07/14 16:47:32 ram Exp $
- X#
- X# Copyright (c) 1991, Raphael Manfredi
- X#
- X# You may redistribute only under the terms of the GNU General Public
- X# Licence as specified in the README file that comes with dist.
- X#
- X# $X-Log: Jmakefile,v $
- X# Revision 2.9 92/07/14 16:47:32 ram
- X# 3.0 beta baseline.
- X#
- X
- XFILES = agenthelp commands distribs filter.sh mailagent.cf proglist \
- X chkagent.sh
- X
- Xall::
- X
- Xinstall::
- X @for dir in $(PRIVLIB) $(PRIVLIB)/mailagent; do \
- X case '${MFLAGS}' in *[i]*) set +e;; esac; \
- X (set -x; $(INSTALL) -d $$dir); \
- X done
- X
- Xdeinstall::
- X $(RM) -r $(PRIVLIB) $(PRIVLIB)/mailagent
- X
- Xinstall:: $(FILES)
- X @case '${MFLAGS}' in *[i]*) set +e;; esac; \
- X for i in $(FILES); do \
- X (set -x; $(INSTALL) -c -m 444 $$i $(PRIVLIB)/mailagent); \
- X done
- X
- Xdeinstall::
- X @case '${MFLAGS}' in *[i]*) set +e;; esac; \
- X for i in $(FILES); do \
- X (set -x; $(RM) $(PRIVLIB)/mailagent/$$i); \
- X done
- X
- X########################################################################
- X# Common rules for all Makefiles -- do not edit
- X
- Xemptyrule::
- X
- Xclean: local_clean
- Xrealclean: local_realclean
- Xclobber: local_clobber
- X
- Xlocal_clean::
- X $(RM) core *~ *.o
- X
- Xlocal_realclean:: local_clean
- X
- Xlocal_clobber:: local_realclean
- X $(RM) Makefile config.sh
- X
- XMakefile.SH: Jmakefile
- X -@if test -f $(TOP)/.package; then \
- X if test -f Makefile.SH; then \
- X echo " $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~"; \
- X $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~; \
- X fi; \
- X echo " $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT)" ; \
- X $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT) ; \
- X else touch $@; exit 0; fi
- X
- XMakefile: Makefile.SH
- X /bin/sh Makefile.SH
- X
- Xtags::
- X $(CTAGS) -w *.[ch]
- X $(CTAGS) -xw *.[ch] > tags
- X
- Xlocal_clobber::
- X $(RM) tags
- X
- X########################################################################
- X# Empty rules for directories with no sub-directories -- do not edit
- X
- Xinstall::
- X @echo "install in $(CURRENT) done."
- X
- Xdeinstall::
- X @echo "deinstall in $(CURRENT) done."
- X
- Xinstall.man::
- X @echo "install.man in $(CURRENT) done."
- X
- Xdeinstall.man::
- X @echo "deinstall.man in $(CURRENT) done."
- X
- XMakefiles::
- X
- XMakefiles.SH::
- X
- X!NO!SUBS!
- Xchmod 644 Makefile
- X$eunicefix Makefile
- X
- END_OF_FILE
- if test 3518 -ne `wc -c <'agent/files/Makefile.SH'`; then
- echo shar: \"'agent/files/Makefile.SH'\" unpacked with wrong size!
- fi
- chmod +x 'agent/files/Makefile.SH'
- # end of 'agent/files/Makefile.SH'
- fi
- if test -f 'agent/files/mailagent.cf' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agent/files/mailagent.cf'\"
- else
- echo shar: Extracting \"'agent/files/mailagent.cf'\" \(2518 characters\)
- sed "s/^X//" >'agent/files/mailagent.cf' <<'END_OF_FILE'
- X#
- X# Configuration file for mailagent
- X#
- X
- X# $Id: mailagent.cf,v 2.9.1.1 92/08/02 15:52:42 ram Exp $
- X#
- X# Copyright (c) 1991, Raphael Manfredi
- X#
- X# You may redistribute only under the terms of the GNU General Public
- X# Licence as specified in the README file that comes with dist.
- X#
- X# $Log: mailagent.cf,v $
- X# Revision 2.9.1.1 92/08/02 15:52:42 ram
- X# patch2: new configuration parameter to specify mailbox file
- X#
- X# Revision 2.9 92/07/14 16:47:51 ram
- X# 3.0 beta baseline.
- X#
- X
- X#
- X# Configuration section
- X#
- X
- X# Paramters likely to change
- Xhome : /lyon/ram # Home directory (must be correctly set)
- Xlevel : 9 # Logging level
- Xtmpdir : /tmp # Temporary directory to be used
- Xemergdir : ~/tmp/lost+mail # Emergency directory (for dumps)
- Xtrack : OFF # Track matches on stdout (on/off)
- X
- X# Minimum path to ensure and path depending on the machine
- Xpath : /bin:/usr/bin:/usr/ucb
- Xp_york : ~/bin:~/bin/rs2030
- Xp_lyon : ~/bin:~/bin/rs2030
- Xp_rome : ~/bin:~/bin/sun4:/base/common/GENERAL/sun4/bin
- X
- X# User who runs mailagent
- Xuser : ram
- Xname : Raphael
- X
- X# Vacation mode (on/off), vacation file and period
- Xvacation : OFF # Vacation mode on/off
- Xvacfile : ~/.vacation # File to be sent back
- Xvacperiod: 1d # Period between two vacation messages
- X
- X
- X#
- X# Parameters which should not change very often
- X#
- X
- X# Define main configuration parameters
- Xspool : ~/var/mailagent # Spool directory
- Xqueue : $spool/queue # Queue directory (must exist)
- Xlogdir : ~/var/log # Where logfile is stored
- Xcontext : $spool/context # Mailagent's context file
- Xlog : agentlog # Log file is in $logdir
- Xseq : .seq # Seq file is in $spool
- Xtimezone : PST8PDT # Time zone location
- Xstatfile : $spool/mailagent.st # Statistics file
- Xrules : ~/.rules # Filter's rules location (optional)
- Xmaildrop : /usr/mail # System mail drop directory (optional)
- Xmailbox : $user # Mailbox file name (optional)
- X
- X# Database hashing directory (in $spool) and other controls
- Xhash : dbr # Hashing directory
- Xcleanlaps: 1M # Laps between cleanings
- Xautoclean: ON # Turn periodic cleaning on/off
- Xagemax : 1y # Maximum lifetime for entries
- X
- X
- X#
- X# Parameters for PROCESS
- X#
- X
- Xcomfile : $spool/commands # Valid commands
- Xdistlist : $spool/distribs # Distribution list
- Xproglist : $spool/proglist # Program description list
- Xmaxsize : 150000 # Maximum size before kiting
- Xplsave : $spool/plsave # Where patchlevels are saved
- Xauthfile : $spool/auth # Remote sending authorizations
- END_OF_FILE
- if test 2518 -ne `wc -c <'agent/files/mailagent.cf'`; then
- echo shar: \"'agent/files/mailagent.cf'\" unpacked with wrong size!
- fi
- # end of 'agent/files/mailagent.cf'
- fi
- if test -f 'agent/filter/lock.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agent/filter/lock.c'\"
- else
- echo shar: Extracting \"'agent/filter/lock.c'\" \(2525 characters\)
- sed "s/^X//" >'agent/filter/lock.c' <<'END_OF_FILE'
- X/*
- X
- X # #### #### # # ####
- X # # # # # # # # #
- X # # # # #### #
- X # # # # # # ### #
- X # # # # # # # ### # #
- X ###### #### #### # # ### ####
- X
- X Lock file handling.
- X*/
- X
- X#include "config.h"
- X#include "portable.h"
- X#include <errno.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- X#ifdef I_FCNTL
- X#include <fcntl.h>
- X#else
- X#include <sys/fcntl.h>
- X#endif
- X#ifdef I_SYSFILE
- X#include <sys/file.h>
- X#endif
- X
- X#define MAX_STRING 2048 /* Max string length */
- X#define MAX_TIME 3600 /* One hour */
- X
- Xprivate char lockfile[MAX_STRING]; /* Location of lock file */
- Xprivate int locked = 0; /* Did we lock successfully? */
- X
- Xprivate void check_lock(); /* Make sure lockfile is not too old */
- X
- Xextern int errno; /* System error status */
- Xextern Time_t time(); /* Current time */
- X
- Xpublic int filter_lock(dir)
- Xchar *dir; /* Where lockfile should be written */
- X{
- X /* Note: this locking is not completly safe w.r.t. race conditions, but the
- X * mailagent will do its own locking checks in a rather safe way.
- X * Return 0 if locking succeeds, -1 otherwise.
- X */
- X
- X int fd;
- X
- X sprintf(lockfile, "%s/filter.lock", dir);
- X check_lock(lockfile);
- X if (-1 == (fd = open(lockfile, O_CREAT | O_EXCL, 0))) {
- X if (errno != EEXIST)
- X add_log(1, "SYSERR open: %m (%e)");
- X return -1;
- X }
- X locked = 1; /* We did lock successfully */
- X close(fd); /* Close dummy file descriptor */
- X
- X return 0;
- X}
- X
- Xpublic void release_lock()
- X{
- X if (locked && -1 == unlink(lockfile)) {
- X add_log(1, "SYSERR unlink: %m (%e)");
- X add_log(4, "WARNING could not remove lockfile %s", lockfile);
- X }
- X locked = 0;
- X}
- X
- Xpublic int is_locked()
- X{
- X return locked; /* Do we have a lock file active or not? */
- X}
- X
- Xprivate void check_lock(file)
- Xchar *file;
- X{
- X /* Make sure the lock file is not older than MAX_TIME seconds, otherwise
- X * unlink it (something must have gone wrong).
- X */
- X
- X struct stat buf;
- X
- X if (-1 == stat(file, &buf)) { /* Stat failed */
- X if (errno == ENOENT) /* File does not exist */
- X return;
- X add_log(1, "SYSERR stat: %m (%e)");
- X add_log(2, "could not check lockfile %s", file);
- X return;
- X }
- X
- X if ((buf.st_mtime - time((Time_t *) 0)) > MAX_TIME) {
- X if (-1 == unlink(lockfile)) {
- X add_log(1, "SYSERR unlink: %m (%e)");
- X add_log(4, "WARNING could not remove old lock %s", lockfile);
- X } else
- X add_log(6, "UNLOCKED filter (lock older than 1 hour)");
- X } else
- X add_log(16, "lockfile for filter is recent");
- X}
- X
- END_OF_FILE
- if test 2525 -ne `wc -c <'agent/filter/lock.c'`; then
- echo shar: \"'agent/filter/lock.c'\" unpacked with wrong size!
- fi
- # end of 'agent/filter/lock.c'
- fi
- if test -f 'agent/filter/sysexits.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agent/filter/sysexits.h'\"
- else
- echo shar: Extracting \"'agent/filter/sysexits.h'\" \(1166 characters\)
- sed "s/^X//" >'agent/filter/sysexits.h' <<'END_OF_FILE'
- X/*
- X
- X #### # # #### ###### # # # ##### #### # #
- X # # # # # # # # # # # #
- X #### # #### ##### ## # # #### ######
- X # # # # ## # # # ### # #
- X # # # # # # # # # # # # ### # #
- X #### # #### ###### # # # # #### ### # #
- X
- X Standard exit codes for sendmail and friends.
- X Original list maintained by Eric Allman <eric@berkeley.edu>.
- X*/
- X
- X/*
- X * $Id: sysexits.h,v 2.9 92/07/14 16:48:43 ram Exp $
- X *
- X * Copyright (c) 1992, Raphael Manfredi
- X *
- X * You may redistribute only under the terms of the GNU General Public
- X * Licence as specified in the README file that comes with dist.
- X *
- X * $Log: sysexits.h,v $
- X * Revision 2.9 92/07/14 16:48:43 ram
- X * 3.0 beta baseline.
- X *
- X */
- X
- X#ifndef _sysexits_h_
- X#define _sysexits_h_
- X
- X#define EX_OK 0
- X#define EX_USAGE 64
- X#define EX_UNAVAILABLE 69
- X#define EX_OSERR 71
- X#define EX_OSFILE 72
- X#define EX_CANTCREAT 73
- X#define EX_IOERR 74
- X#define EX_TEMPFAIL 75
- X
- X#endif
- END_OF_FILE
- if test 1166 -ne `wc -c <'agent/filter/sysexits.h'`; then
- echo shar: \"'agent/filter/sysexits.h'\" unpacked with wrong size!
- fi
- # end of 'agent/filter/sysexits.h'
- fi
- if test -f 'agent/mhook.SH' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agent/mhook.SH'\"
- else
- echo shar: Extracting \"'agent/mhook.SH'\" \(3834 characters\)
- sed "s/^X//" >'agent/mhook.SH' <<'END_OF_FILE'
- Xcase $CONFIG in
- X'')
- X if test ! -f config.sh; then
- X ln ../config.sh . || \
- X ln ../../config.sh . || \
- X ln ../../../config.sh . || \
- X (echo "Can't find config.sh."; exit 1)
- X fi 2>/dev/null
- X . config.sh
- X ;;
- Xesac
- Xcase "$0" in
- X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
- Xesac
- Xecho "Extracting agent/mhook (with variable substitutions)"
- X$spitshell >mhook <<!GROK!THIS!
- X# feed this into perl
- X eval 'exec perl -S \$0 "\$@"'
- X if \$running_under_some_shell;
- X
- X# You'll need to set up a .forward file that feeds your mail to this script,
- X# via the filter. Mine looks like this:
- X# "|exec /users/ram/mail/filter >>/users/ram/.bak 2>&1"
- X
- X# $Id: mhook.SH,v 2.9.1.1 92/08/26 12:44:48 ram Exp $
- X#
- X# Copyright (c) 1991, 1992, Raphael Manfredi
- X#
- X# You may redistribute only under the terms of the GNU General Public
- X# Licence as specified in the README file that comes with dist.
- X#
- X# $Log: mhook.SH,v $
- X# Revision 2.9.1.1 92/08/26 12:44:48 ram
- X# patch8: created
- X#
- X
- X# Perload ON
- X
- X# The following were determined by Configure
- X\$mversion = '$VERSION'; # Current version number
- X\$patchlevel = '$PATCHLEVEL'; # And patchlevel from patchlevel.h
- X!GROK!THIS!
- X
- X$spitshell >>mhook <<'!NO!SUBS!'
- X
- X$prog_name = $0; # Who I am
- X$prog_name =~ s|^.*/(.*)|$1|; # Keep only base name
- X$has_option = 0; # True if invoked with options
- X$config_file = '~/.mailagent'; # Default configuration file
- X
- X# Parse options
- Xwhile ($ARGV[0] =~ /^-/) {
- X $_ = shift;
- X last if /--/;
- X if ($_ eq '-h') {
- X &usage;
- X }
- X elsif ($_ eq '-V') { # Version number
- X print STDERR "$prog_name $mversion PL$patchlevel\n";
- X exit 0;
- X }
- X else {
- X print STDERR "$prog_name: unknown option: $_\n";
- X &usage;
- X }
- X}
- X
- X$hook_name = shift; # Where mailhook folder is located
- X&usage unless $hook_name; # Hook file is a mandatory argument
- X$file_name = shift; # File name to be processed (null if stdin)
- X
- X$ENV{'IFS'}='' if $ENV{'IFS'}; # Shell separation field
- X&read_config($config_file); # Read configuration file and set cf package
- X
- X$ENV{'HOME'} = $cf'home;
- X$ENV{'USER'} = $cf'user;
- X$ENV{'NAME'} = $cf'name;
- X
- Xumask(077); # Files we create are private ones
- X$jobnum = &jobnum; # Compute a job number
- X&init_all; # Start-up initializations
- X
- X$hook_type = &hook_type($hook_name); # Determine kind of hook
- X&hooking($file_name, $hook_name, $hook_type); # Print log message
- Xchdir($cf'home); # Hook called in home directory
- X&$hook_type($file_name, $hook_name); # Invoke hooking function
- X
- X# End of mailhook processing
- X&add_log("mailhook exits") if $loglvl > 17;
- Xexit 0;
- X
- X# Print usage and exit
- Xsub usage {
- X print STDERR <<EOF;
- XUsage: $prog_name [-hV] hook [mail]
- X -h : print this help message and exits.
- X -V : print version number and exits.
- XEOF
- X exit 1;
- X}
- X
- X# Start-up initializations
- Xsub init_all {
- X &init_signals; # Trap common signals
- X &init_constants; # Constants definitions
- X}
- X
- X# Protect ourselves (trap common signals)
- Xsub init_signals {
- X $SIG{'HUP'} = 'emergency';
- X $SIG{'INT'} = 'emergency';
- X $SIG{'QUIT'} = 'emergency';
- X $SIG{'PIPE'} = 'emergency';
- X $SIG{'IO'} = 'emergency';
- X $SIG{'BUS'} = 'emergency';
- X $SIG{'ILL'} = 'emergency';
- X $SIG{'SEGV'} = 'emergency';
- X $SIG{'ALRM'} = 'emergency';
- X $SIG{'TERM'} = 'emergency';
- X}
- X
- X# Constants definitions
- Xsub init_constants {
- X &init_hooks; # Init hooks constants
- X}
- X
- X!NO!SUBS!
- X$grep -v '^;#' pl/jobnum.pl >>mhook
- X$grep -v '^;#' pl/read_conf.pl >>mhook
- X$grep -v '^;#' pl/acs_rqst.pl >>mhook
- X$grep -v '^;#' pl/free_file.pl >>mhook
- X$grep -v '^;#' pl/add_log.pl >>mhook
- X$grep -v '^;#' pl/checklock.pl >>mhook
- X$grep -v '^;#' pl/hook.pl >>mhook
- X$grep -v '^;#' pl/mailhook.pl >>mhook
- X$grep -v '^;#' pl/dbr.pl >>mhook
- X$grep -v '^;#' pl/fatal.pl >>mhook
- X$grep -v '^;#' pl/parse.pl >>mhook
- X$grep -v '^;#' pl/header.pl >>mhook
- X$grep -v '^;#' pl/rfc822.pl >>mhook
- X$grep -v '^;#' pl/extern.pl >>mhook
- Xchmod 755 mhook
- X$eunicefix mhook
- END_OF_FILE
- if test 3834 -ne `wc -c <'agent/mhook.SH'`; then
- echo shar: \"'agent/mhook.SH'\" unpacked with wrong size!
- fi
- # end of 'agent/mhook.SH'
- fi
- if test -f 'agent/pl/builtins.pl' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agent/pl/builtins.pl'\"
- else
- echo shar: Extracting \"'agent/pl/builtins.pl'\" \(3389 characters\)
- sed "s/^X//" >'agent/pl/builtins.pl' <<'END_OF_FILE'
- X;# $Id: builtins.pl,v 2.9 92/07/14 16:49:38 ram Exp $
- X;#
- X;# Copyright (c) 1992, Raphael Manfredi
- X;#
- X;# You may redistribute only under the terms of the GNU General Public
- X;# Licence as specified in the README file that comes with dist.
- X;#
- X;# $Log: builtins.pl,v $
- X;# Revision 2.9 92/07/14 16:49:38 ram
- X;# 3.0 beta baseline.
- X;#
- X;#
- X#
- X# Executing builtin commands
- X#
- X
- X# Send a receipt
- Xsub send_receipt {
- X local($subj) = $Header{'Subject'};
- X local($msg_id) = $Header{'Message-Id'};
- X local($from) = $Header{'From'};
- X local($sender) = $Header{'Reply-To'};
- X local($to) = $Header{'To'};
- X local($ack_dest) = @_; # Were to send receipt
- X local($dest); # Return path to be used (derived from mail)
- X
- X # If no @PATH directive was found, use $sender as a return path
- X $dest = $Userpath; # Set by an @PATH
- X $dest = $sender unless $dest;
- X # Remove the <> if any (e.g. path derived from Return-Path)
- X $dest =~ /<(.*)>/ && ($dest = $1);
- X
- X # Derive a correct return path for receipt
- X $ack_dest = 'PATH' if $ack_dest eq '-';
- X $ack_dest = "" if $ack_dest =~ /[=\$^&*([{}`\\|;><?]/;
- X $ack_dest = $dest if ($ack_dest eq '' || $ack_dest =~ /PATH/);
- X
- X # Compute host name (fully qualified, i.e. with domain name)
- X chop($hostname = `$phostname`);
- X $hostname .= $mydomain if $hostname =~ /^\w+$/;
- X
- X chop($date = `date`);
- X open(MAILER,"|/usr/lib/sendmail -odq -t");
- X print MAILER
- X"To: $ack_dest
- XSubject: Re: $subj (receipt)
- XX-Mailer: mailagent [version $mversion PL$patchlevel]
- X";
- X if ($msg_id ne '') {
- X print MAILER "\nYour message $msg_id,\n";
- X } else {
- X print MAILER "\nYour message ";
- X }
- X print MAILER "addressed to $to,\n" if $to ne '';
- X print MAILER "whose subject was \"$subj\",\n" if $subj ne '';
- X print MAILER
- X"has been received by $hostname on $date
- X
- X-- mailagent speaking for $cf'user
- X";
- X close MAILER;
- X if ($?) {
- X do add_log("ERROR couldn't send receipt to $ack_dest") if $loglvl > 0;
- X } else {
- X do add_log("SENT receipt to $ack_dest") if $loglvl > 2;
- X }
- X}
- X
- X#
- X# Deal with builtins
- X#
- X
- X# Built-in commands are listed herein. Those commands being built-in are always
- X# dealt with during mail parsing and are taken care of at the beginning of the
- X# rules analysis. The code to be executed for each builtin is stored in the
- X# Builtcode array by those routines.
- Xsub init_builtins {
- X %Builtin = (
- X 'RR', 'builtin_rr',
- X 'PATH', 'builtin_path'
- X );
- X undef @Builtcode;
- X}
- X
- X# Whenever a builtin command is recognized (on the fly) while parsing the mail
- X# body, the corresponding builtin function is called with the remaining of the
- X# line given as argument (leading spaces removed).
- X
- X# The @RR command asks for a receipt
- Xsub builtin_rr {
- X local($_) = @_;
- X do add_log("found an @RR request to $_") if $loglvl > 18;
- X # @RR request honored only if not from special user and directed to us
- X unless (&special_user) {
- X push(@Builtcode, "do send_receipt('$_')");
- X } else {
- X &add_log("ignoring @RR request to $_") if $loglvl > 4;
- X }
- X}
- X
- X# The @PATH command sets a valid return path (recorded in $Userpath)
- Xsub builtin_path {
- X local($_) = @_;
- X return if /[=\$^&*([{}`\\|;><?]/; # Invalid character found
- X $Userpath = $_;
- X do add_log("found an @PATH request to $_") if $loglvl > 18;
- X}
- X
- X# Execute stacked builtins
- Xsub run_builtins {
- X return if $#Builtcode < 0; # No recorded builtins
- X foreach (@Builtcode) {
- X eval($_); # Execute stacked builtin
- X }
- X @Builtcode = (); # Reset builtcode array
- X}
- X
- END_OF_FILE
- if test 3389 -ne `wc -c <'agent/pl/builtins.pl'`; then
- echo shar: \"'agent/pl/builtins.pl'\" unpacked with wrong size!
- fi
- # end of 'agent/pl/builtins.pl'
- fi
- if test -f 'agent/pl/context.pl' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agent/pl/context.pl'\"
- else
- echo shar: Extracting \"'agent/pl/context.pl'\" \(3363 characters\)
- sed "s/^X//" >'agent/pl/context.pl' <<'END_OF_FILE'
- X;# $Id: context.pl,v 2.9 92/07/14 16:49:43 ram Exp $
- X;#
- X;# Copyright (c) 1992, Raphael Manfredi
- X;#
- X;# You may redistribute only under the terms of the GNU General Public
- X;# Licence as specified in the README file that comes with dist.
- X;#
- X;# $Log: context.pl,v $
- X;# Revision 2.9 92/07/14 16:49:43 ram
- X;# 3.0 beta baseline.
- X;#
- X;#
- X;# Keep track of the mailagent's context, in particular all the actions which
- X;# may be performed in a batched way and need to save some contextual data.
- X;#
- Xpackage context;
- X
- X#
- X# General handling
- X#
- X
- X# Initialize context from context file
- Xsub init {
- X &default; # Load a default context
- X return unless -f $cf'context; # Finished if no saved context
- X &load; # Load context, overwriting default context
- X &clean; # Remove uneeded entries from context
- X}
- X
- X# Provide a default context
- Xsub default {
- X %Context = (
- X 'last-clean', '0', # Last cleaning of hash files
- X );
- X}
- X
- X# Load the context entries
- Xsub load {
- X unless(open(CONTEXT, "$cf'context")) {
- X &'add_log("WARNING unable to open context file: $!") if $'loglvl > 5;
- X return;
- X }
- X &'add_log("loading mailagent context") if $'loglvl > 15;
- X local($_, $.);
- X while (<CONTEXT>) {
- X next if /^\s*#/;
- X if (/^([\w\-]+)\s*:\s*(\S+)/) {
- X $Context{$1} = $2;
- X next;
- X }
- X &'add_log("WARNING context file corrupted, line $.") if $'loglvl > 5;
- X last;
- X }
- X close CONTEXT;
- X}
- X
- X# Clean context, removing useless entries
- Xsub clean {
- X delete $Context{'last-clean'} unless $cf'autoclean =~ /^on/i;
- X}
- X
- X# Save a new context file
- Xsub save {
- X require 'ctime.pl';
- X local($existed) = -f $cf'context;
- X &'acs_rqst($cf'context) if $existed; # Lock existing file
- X unless (open(CONTEXT, ">$cf'context")) {
- X &'add_log("ERROR cannot overwrite context file: $!") if $'loglvl > 1;
- X return;
- X }
- X &'add_log("saving context file $cf'context") if $'loglvl > 17;
- X local($key, $value, $item);
- X print CONTEXT "# Mailagent context, last updated " . &'ctime(time);
- X while (($key, $value) = each %Context) {
- X next unless $value;
- X $item++;
- X print CONTEXT $key, ': ', $value, "\n";
- X }
- X close CONTEXT;
- X unlink "$cf'context" unless $item; # Do not leave empty context
- X &'add_log("deleted empty context") if $'loglvl > 17 && !$item;
- X &'free_file($cf'context) if $existed;
- X}
- X
- X#
- X# Context-dependant actions
- X#
- X
- X# Remove entries in dbr hash files which are old enough. For this operation
- X# to be performed, the autoclean variable must be set to ON in ~/.mailagent,
- X# the cleanlaps indicates the period for those automatic cleanings, and agemax
- X# specifies the maximum allowed time within the database.
- Xsub autoclean {
- X return unless $cf'autoclean =~ /^on/i;
- X local($period) = &'seconds_in_period($cf'cleanlaps);
- X return if ($Context{'last-clean'} + $period) > time;
- X # Retry time reached -- start auto cleaning
- X &'add_log("autocleaning of dbr files") if $'loglvl > 8;
- X $period = &'seconds_in_period($cf'agemax);
- X &dbr'clean($period);
- X $Context{'last-clean'} = time; # Update last cleaning time
- X}
- X
- X#
- X# Perform all contextual actions
- X#
- X
- X# Run all the contextual actions, each action returning if not needed or if
- X# the retry time was not reached. This routine is the main entry point in
- X# the package, and is the only one called from the outside world.
- Xsub main'contextual_operations {
- X &init; # Initialize context
- X &autoclean; # Clean dbr hash files
- X &save; # Save new context
- X}
- X
- Xpackage main;
- X
- END_OF_FILE
- if test 3363 -ne `wc -c <'agent/pl/context.pl'`; then
- echo shar: \"'agent/pl/context.pl'\" unpacked with wrong size!
- fi
- # end of 'agent/pl/context.pl'
- fi
- if test -f 'agent/pl/distribs.pl' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agent/pl/distribs.pl'\"
- else
- echo shar: Extracting \"'agent/pl/distribs.pl'\" \(3155 characters\)
- sed "s/^X//" >'agent/pl/distribs.pl' <<'END_OF_FILE'
- X;# $Id: distribs.pl,v 2.9 92/07/14 16:49:48 ram Exp $
- X;#
- X;# Copyright (c) 1991, Raphael Manfredi
- X;#
- X;# You may redistribute only under the terms of the GNU General Public
- X;# Licence as specified in the README file that comes with dist.
- X;#
- X;# $Log: distribs.pl,v $
- X;# Revision 2.9 92/07/14 16:49:48 ram
- X;# 3.0 beta baseline.
- X;#
- X;#
- X;# This file relies on the following external conditions:
- X;# - operation do fatal() available for fatal errors
- X;# - the configuration variables are properly set
- X;# - logging is done via do add_log()
- X;#
- X# Read a distribution file and fill in data structures for
- X# the query functions. All the data are stored in associative
- X# arrays, indexed by the system's name and version number.
- X# Associative arrays are:
- X#
- X# name indexed by information
- X#
- X# %Program name + version have we seen that line ?
- X# %System name is name a valid system ?
- X# %Version name latest version for system
- X# %Location name + version location of the distribution
- X# %Archived name + version is distribution archived ?
- X# %Compressed name + version is archive compressed ?
- X# %Patch_only name + version true if only patches delivered
- X# %Maintained name + version true if distribution is maintained
- X# %Patches name + version true if official patches available
- X#
- X# For systems with a version of '---' in the file, the version
- X# for accessing the data has to be a null string.
- X#
- X# Expected format for the distribution file:
- X# system version location archive compress patches
- X#
- X# The `archive', `compress' and `patches' fields can take one
- X# of the following states: "yes" and "no". An additional state
- X# for `patches' is "old", which means that only patches are
- X# available for the version, and not the distribution. Another is
- X# "patch" which means that official patches are available.
- X# All these states can be abbreviated with the first letter.
- X#
- Xsub read_dist {
- X local($fullname);
- X open(DIST, "$cf'distlist") ||
- X do fatal("cannot open distribution file");
- X while (<DIST>) {
- X next if /^\s*#/; # skip comments
- X next if /^\s*$/; # skip empty lines
- X next unless s/^\s*(\w+)\s+([.\-0-9]+)//;
- X $fullname = $1 . "|" . ($2 eq '---'? "0" : $2);
- X if (defined($Program{$fullname})) {
- X do add_log("WARNING duplicate distlist entry $1 $2 ignored")
- X if ($loglvl > 5);
- X next;
- X }
- X $Program{$fullname}++;
- X $Version{$1} = ($2 eq '---' ? "0" : $2) unless
- X defined($System{$1}) && $Version{$1} > ($2 eq '---' ? "0":$2);
- X $System{$1}++;
- X unless (/^\s*(\S+)\s+(\w+)\s+(\w+)\s+(\w+)/) {
- X do add_log("WARNING bad system description line $.")
- X if ($loglvl > 5);
- X next; # Ignore, but it may corrupt further processing
- X }
- X local($location) = $1;
- X local($archive) = $2;
- X local($compress) = $3;
- X local($patch) = $4;
- X $location =~ s/~\//$cf'home\//; # ~ expansion
- X $Location{$fullname} = $location;
- X $Archived{$fullname}++ if $archive =~ /^y/;
- X $Compressed{$fullname}++ if $compress =~ /^y/;
- X $Patch_only{$fullname}++ if $patch =~ /^o/;
- X $Maintained{$fullname}++ if $patch =~ /^y|o/;
- X $Patches{$fullname}++ if $patch =~ /^p/;
- X }
- X close DIST;
- X}
- X
- END_OF_FILE
- if test 3155 -ne `wc -c <'agent/pl/distribs.pl'`; then
- echo shar: \"'agent/pl/distribs.pl'\" unpacked with wrong size!
- fi
- # end of 'agent/pl/distribs.pl'
- fi
- if test -f 'agent/pl/mbox.pl' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agent/pl/mbox.pl'\"
- else
- echo shar: Extracting \"'agent/pl/mbox.pl'\" \(2744 characters\)
- sed "s/^X//" >'agent/pl/mbox.pl' <<'END_OF_FILE'
- X;# $Id: mbox.pl,v 2.9 92/07/14 16:50:22 ram Exp $
- X;#
- X;# Copyright (c) 1992, Raphael Manfredi
- X;#
- X;# You may redistribute only under the terms of the GNU General Public
- X;# Licence as specified in the README file that comes with dist.
- X;#
- X;# $Log: mbox.pl,v $
- X;# Revision 2.9 92/07/14 16:50:22 ram
- X;# 3.0 beta baseline.
- X;#
- X;#
- X;# This package enables the mailagent to incorporate mail from a UNIX-style
- X;# mailbox (i.e. those produced by standard mail utilities with a leading From
- X;# line stating sender and date) into the mailagent's queue. This will be
- X;# especially useful on those sites where users are not allowed to have a
- X;# .forward file. By using the -f option on the mailbox in /usr/spool/mail,
- X;# mail will be queued and filtered as if it had come from filter via .forward.
- Xpackage mbox;
- X
- X# Get mail from UNIX mailbox and queue each item
- Xsub main'mbox_mail {
- X local($mbox) = @_; # Where mail is stored
- X unless (open(MBOX, "$mbox")) {
- X &'add_log("ERROR cannot open $mbox: $!") if $'loglvl > 1;
- X return -1; # Failed
- X }
- X local(@buffer); # Buffer used for look-ahead
- X local(@blanks); # Trailing blank lines are ignored
- X local(@mail); # Where mail is stored
- X while (<MBOX>) {
- X chop;
- X if (/^\s*$/ && 0 == @buffer) {
- X push(@blanks, $_);
- X next; # Remove empty lines before end of mail
- X }
- X if (/^From\s/) {
- X push(@buffer, $_);
- X next;
- X }
- X if (@buffer > 0) {
- X if (/^$/) {
- X &flush(1); # End of header
- X push(@mail, $_);
- X next;
- X }
- X if (/^[\w\-]+:/) {
- X $last_was_header = 1;
- X push(@buffer, $_);
- X next;
- X }
- X if (/^\s/ && $last_was_header) {
- X push(@buffer, $_);
- X next;
- X }
- X &flush(0); # Not a header
- X push(@mail, $_);
- X next;
- X }
- X &flush_blanks;
- X push(@mail, $_);
- X }
- X close MBOX;
- X &flush(1); # Flush mail buffer at end of file
- X &flush_buffer; # Maybe header was incomplete?
- X &'add_log("WARNING incomplete last mail discarded")
- X if $'loglvl > 5 && @mail > 0;
- X 0; # Ok (but there might have been some queue problems)
- X}
- X
- X# Flush blanks into @mail
- Xsub flush_blanks {
- X return unless @blanks;
- X foreach $blank (@blanks) {
- X push(@mail, $blank);
- X }
- X @blanks = ();
- X}
- X
- X# Flush look-ahead buffer into @mail
- Xsub flush_buffer {
- X return unless @buffer;
- X foreach $buffer (@buffer) {
- X push(@mail, $buffer);
- X }
- X @buffer = ();
- X}
- X
- X# Flush mail buffer onto queue
- Xsub flush {
- X local($was_header) = @_; # Did we reach a new header
- X # NB: we don't have to worry if the very first mail does not have a From
- X # line, as qmail will add a faked one if necessary.
- X if ($was_header && @mail > 0) {
- X &main'qmail(*mail);
- X @mail = (); # Reset mail buffer
- X }
- X &flush_buffer; # Fill @mail with what we got so far in @buffer
- X @blanks = (); # Discard trailing blanks
- X}
- X
- Xpackage main;
- X
- END_OF_FILE
- if test 2744 -ne `wc -c <'agent/pl/mbox.pl'`; then
- echo shar: \"'agent/pl/mbox.pl'\" unpacked with wrong size!
- fi
- # end of 'agent/pl/mbox.pl'
- fi
- if test -f 'agent/pl/plsave.pl' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agent/pl/plsave.pl'\"
- else
- echo shar: Extracting \"'agent/pl/plsave.pl'\" \(3784 characters\)
- sed "s/^X//" >'agent/pl/plsave.pl' <<'END_OF_FILE'
- X;# $Id: plsave.pl,v 2.9 92/07/14 16:50:29 ram Exp $
- X;#
- X;# Copyright (c) 1991, Raphael Manfredi
- X;#
- X;# You may redistribute only under the terms of the GNU General Public
- X;# Licence as specified in the README file that comes with dist.
- X;#
- X;# $Log: plsave.pl,v $
- X;# Revision 2.9 92/07/14 16:50:29 ram
- X;# 3.0 beta baseline.
- X;#
- X;#
- X;# This file relies on the following external conditions:
- X;# - operation do fatal() available for fatal errors
- X;# - the configuration variables are properly set
- X;# - logging is done via do add_log()
- X;# - routines for locking files are available
- X;#
- X# Read stored informations for archived systems. The format of
- X# the file is the following:
- X# system version patchlevel mtime
- X# where:
- X# - system is the name of the system
- X# - version is the version number or --- if none
- X# - patchlevel is the current patchlevel, or -2 if no PL
- X# - mtime is the modification time of the archive
- X#
- X# The function builds the following associative array, indexed
- X# by the system's name and version number (which has to be a null
- X# string for systems with no version number, marked '---'):
- X#
- X# name indexed by information
- X#
- X# %PSystem name + version true if line seen
- X# %Patch_level name + version current patch level
- X# %Mtime name + version last modification time
- X#
- X# If the 'plsave' file is not found, a new empty one is created
- X#
- Xsub read_plsave {
- X local($fullname);
- X if (!open(PATLIST, "$cf'plsave")) {
- X do add_log("creating new patlist file") if ($loglvl > 8);
- X system 'cp', '/dev/null', $cf'plsave;
- X open(PATLIST, "$cf'plsave") ||
- X do fatal("cannot open patlist file");
- X }
- X while (<PATLIST>) {
- X next if /^\s*#/; # skip comments
- X next if /^\s*$/; # skip empty lines
- X next unless s/^\s*(\w+)\s+([\w\.]+)//;
- X $fullname = $1 . "|" . ($2 eq '---'? "0" : $2);
- X if (defined($PSystem{$fullname})) {
- X do add_log("WARNING duplicate patlist entry $1 $2 ignored")
- X if ($loglvl > 5);
- X next;
- X }
- X $PSystem{$fullname}++;
- X unless (/^\s*([\-\d]+)\s+(\d+)/) {
- X do add_log("WARNING bad patlist description line $.")
- X if ($loglvl > 5);
- X next; # Ignore, but it may corrupt further processing
- X }
- X $Patch_level{$fullname} = $1;
- X $Mtime{$fullname} = $2;
- X }
- X close PATLIST;
- X}
- X
- X# Write the new 'plsave', but only if the distributions are found
- X# in the %Program array (I assume read_dist() has been called).
- X# The 'plsave' file is locked during the updating process, so that
- X# no conflicting access occurs. There is a small chance that the
- X# file we write is not correct, in case the distribution file changed
- X# while we were processing a mail. However, it isn't a big problem.
- Xsub write_plsave {
- X local($lockext) = ".lock"; # Needed by checklock
- X local($system);
- X local($version);
- X do checklock($cf'plsave); # Make sure no old lock lasts
- X if (0 != &acs_rqst($cf'plsave)) {
- X do add_log("WARNING updating unlocked patlist file")
- X if ($loglvl > 5);
- X }
- X if (!open(PATLIST, ">$cf'plsave")) {
- X do add_log("ERROR unable to update $cf'plsave") if ($loglvl > 0);
- X return;
- X }
- X print PATLIST
- X"# This file was automatically generated by $prog_name.
- X# It records the archived distributions, their patch level if any, and
- X# the modification time of the archive, so that these informations can
- X# be updated when necessary. Do not edit this file.
- X
- X";
- X foreach $pname (keys %PSystem) {
- X if ($Archived{$pname}) {
- X ($system, $version) = $pname =~ /^(\w+)\|([\w\.]+)*$/;
- X $version = '---' if $version eq '0';
- X print PATLIST "$system $version ";
- X print PATLIST "$Patch_level{$pname} $Mtime{$pname}\n";
- X do add_log("updated patlist for $system $version")
- X if ($log_lvl > 18);
- X } else {
- X do add_log("$system $version removed from patlist")
- X if ($log_lvl > 18);
- X }
- X }
- X close PATLIST;
- X do free_file($cf'plsave);
- X}
- X
- END_OF_FILE
- if test 3784 -ne `wc -c <'agent/pl/plsave.pl'`; then
- echo shar: \"'agent/pl/plsave.pl'\" unpacked with wrong size!
- fi
- # end of 'agent/pl/plsave.pl'
- fi
- if test -f 'agent/pl/pqueue.pl' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agent/pl/pqueue.pl'\"
- else
- echo shar: Extracting \"'agent/pl/pqueue.pl'\" \(2659 characters\)
- sed "s/^X//" >'agent/pl/pqueue.pl' <<'END_OF_FILE'
- X;# $Id: pqueue.pl,v 2.9 92/07/14 16:50:32 ram Exp $
- X;#
- X;# Copyright (c) 1992, Raphael Manfredi
- X;#
- X;# You may redistribute only under the terms of the GNU General Public
- X;# Licence as specified in the README file that comes with dist.
- X;#
- X;# $Log: pqueue.pl,v $
- X;# Revision 2.9 92/07/14 16:50:32 ram
- X;# 3.0 beta baseline.
- X;#
- X;#
- X# Process the queue
- Xsub pqueue {
- X local($length); # Length of message, in bytes
- X undef %waiting; # Reset waiting array
- X local(@files) = <$cf'queue/fm*>;
- X # The qm files are put there by the filter and left in case of error
- X # Only files older than 30 minutes are re-parsed (because otherwise it
- X # might have just been queued by the filter).
- X local(@filter_files) = <$cf'queue/qm*>;
- X foreach $file (@filter_files) {
- X ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
- X $atime,$mtime,$ctime,$blksize,$blocks) = stat($file);
- X if ((time - $mtime) > 1800) {
- X # More than 30 minutes -- there must have been a failure
- X push(@files, $file); # Add file to the to-be-parsed list
- X }
- X }
- X # In $agent_wait are stored the names of the mails outside the queue
- X # directory, waiting to be processed.
- X if (-f "$cf'queue/$agent_wait") {
- X if (open(WAITING, "$cf'queue/$agent_wait")) {
- X while (<WAITING>) {
- X chop;
- X push(@files, $_); # Process this file too
- X $waiting{$_} = 1; # Record it comes from waiting file
- X }
- X close WAITING;
- X } else {
- X &add_log("ERROR cannot open $cf'queue/$agent_wait: $!") if $loglvl;
- X }
- X }
- X return 0 unless $#files >= 0;
- X do add_log("processing the whole queue") if $loglvl > 11;
- X $processed = 0;
- X foreach $file (@files) {
- X do add_log("dealing with $file") if $loglvl > 19;
- X $file_name = $file;
- X if ($waiting{$file} && ! -f "$file") {
- X # We may have already processed this file without having resynced
- X # agent_wait or the file has been removed.
- X do add_log ("WARNING could not find $file") if $loglvl > 4;
- X $waiting{$file} = 0; # Mark it as processed
- X next; # And skip it
- X }
- X if (0 == &analyze_mail($file_name)) {
- X unlink $file;
- X ++$processed;
- X $waiting{$file} = 0 if $waiting{$file};
- X $file =~ s|.*/(.*)|$1|; # Keep only basename
- X $length = $Header{'Length'};
- X do add_log("FILTERED [$file] $length bytes") if $loglvl > 4;
- X } else {
- X $file =~ s|.*/(.*)|$1|; # Keep only basename
- X do add_log("ERROR leaving [$file] in queue") if $loglvl > 0;
- X unlink $lockfile;
- X do resync(); # Resynchronize waiting file
- X exit 0; # Do not continue now
- X }
- X }
- X if ($processed == 0) {
- X do add_log("was unable to process queue") if ($loglvl > 5);
- X }
- X do resync(); # Resynchronize waiting file
- X $processed; # Return the number of files processed
- X}
- X
- END_OF_FILE
- if test 2659 -ne `wc -c <'agent/pl/pqueue.pl'`; then
- echo shar: \"'agent/pl/pqueue.pl'\" unpacked with wrong size!
- fi
- # end of 'agent/pl/pqueue.pl'
- fi
- if test -f 'agent/test/Makefile.SH' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agent/test/Makefile.SH'\"
- else
- echo shar: Extracting \"'agent/test/Makefile.SH'\" \(3462 characters\)
- sed "s/^X//" >'agent/test/Makefile.SH' <<'END_OF_FILE'
- X: Makefile.SH generated from Jmake.tmpl and Jmakefile [jmake 2.8 PL13]
- X: $X-Id: Jmake.tmpl,v 2.8.1.2 91/11/18 13:22:54 ram Exp $
- X
- Xcase $CONFIG in
- X'')
- X if test ! -f config.sh; then
- X ln ../config.sh . || \
- X ln ../../config.sh . || \
- X ln ../../../config.sh . || \
- X (echo "Can't find config.sh."; exit 1)
- X fi 2>/dev/null
- X . ./config.sh
- X ;;
- Xesac
- Xcase "$0" in
- X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
- Xesac
- XCURRENT=agent/test
- XDIR=`echo $CURRENT/ | sed -e 's/\.\///g'`
- Xecho "Extracting ${DIR}Makefile (with variable substitutions)"
- XDATE=`date`
- X$spitshell >Makefile <<!GROK!THIS!
- X########################################################################
- X# Makefile generated from Makefile.SH on $DATE
- X
- XSHELL = /bin/sh
- XJMAKE = jmake
- XTOP = ../..
- XCURRENT = $CURRENT
- XDIR = $DIR
- X
- X########################################################################
- X# Parameters set by Configure -- edit config.sh if changes are needed
- X
- XCTAGS = ctags
- XMAKE = make
- XMV = $mv
- XRM = $rm -f
- X
- X!GROK!THIS!
- X$spitshell >>Makefile <<'!NO!SUBS!'
- X
- X########################################################################
- X# Jmake rules for building libraries, programs, scripts, and data files
- X# $X-Id: Jmake.rules,v 2.8.1.4 91/11/18 13:19:07 ram Exp $
- X
- X########################################################################
- X# Start of Jmakefile
- X
- X# $X-Id: Jmakefile,v 2.9 92/07/14 16:50:57 ram Exp $
- X#
- X# Copyright (c) 1991, Raphael Manfredi
- X#
- X# You may redistribute only under the terms of the GNU General Public
- X# Licence as specified in the README file that comes with dist.
- X#
- X# $X-Log: Jmakefile,v $
- X# Revision 2.9 92/07/14 16:50:57 ram
- X# 3.0 beta baseline.
- X#
- X#
- X
- Xall::
- X @echo "The following may take a while..."
- X @echo "Don't panic if any of these tests fails and do not stop make."; \
- X ./TEST
- X @if test -f OK; then \
- X echo "Failure detected, retrying one more time, just in case..."; \
- X echo "Successful tests will not be rerun but flagged as 'done'."; \
- X sleep 2; \
- X ./TEST; \
- X if test -f OK; then \
- X echo "Hmm... Still failed... There might be a real problem."; \
- X echo "I shall be using the plain (non dataloaded) version."; \
- X sleep 2;\
- X ./TEST -n; \
- X fi \
- X fi
- X
- Xtest:
- X ./TEST -i
- X
- Xlocal_clean::
- X $(RM) -r out
- X $(RM) OK
- X
- X########################################################################
- X# Common rules for all Makefiles -- do not edit
- X
- Xemptyrule::
- X
- Xclean: local_clean
- Xrealclean: local_realclean
- Xclobber: local_clobber
- X
- Xlocal_clean::
- X $(RM) core *~ *.o
- X
- Xlocal_realclean:: local_clean
- X
- Xlocal_clobber:: local_realclean
- X $(RM) Makefile config.sh
- X
- XMakefile.SH: Jmakefile
- X -@if test -f $(TOP)/.package; then \
- X if test -f Makefile.SH; then \
- X echo " $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~"; \
- X $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~; \
- X fi; \
- X echo " $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT)" ; \
- X $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT) ; \
- X else touch $@; exit 0; fi
- X
- XMakefile: Makefile.SH
- X /bin/sh Makefile.SH
- X
- Xtags::
- X $(CTAGS) -w *.[ch]
- X $(CTAGS) -xw *.[ch] > tags
- X
- Xlocal_clobber::
- X $(RM) tags
- X
- X########################################################################
- X# Empty rules for directories with no sub-directories -- do not edit
- X
- Xinstall::
- X @echo "install in $(CURRENT) done."
- X
- Xdeinstall::
- X @echo "deinstall in $(CURRENT) done."
- X
- Xinstall.man::
- X @echo "install.man in $(CURRENT) done."
- X
- Xdeinstall.man::
- X @echo "deinstall.man in $(CURRENT) done."
- X
- XMakefiles::
- X
- XMakefiles.SH::
- X
- X!NO!SUBS!
- Xchmod 644 Makefile
- X$eunicefix Makefile
- X
- END_OF_FILE
- if test 3462 -ne `wc -c <'agent/test/Makefile.SH'`; then
- echo shar: \"'agent/test/Makefile.SH'\" unpacked with wrong size!
- fi
- # end of 'agent/test/Makefile.SH'
- fi
- if test -f 'agent/test/README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agent/test/README'\"
- else
- echo shar: Extracting \"'agent/test/README'\" \(3329 characters\)
- sed "s/^X//" >'agent/test/README' <<'END_OF_FILE'
- XThis is the root directory for the regression test suite.
- X
- XThe single TEST executable will run the test suite and report any failure.
- XAlthough not every feature of the mailagent is tested, having it pass
- Xthe whole test suite is a Good Thing. Some commands like PROCESS or POST
- Xare not easy to test automatically, but if you can design good tests
- Xfor them, I will be glad to include them.
- X
- XThis set of programs were written quickly, as effeciency or maintainability
- Xwas not the main issue, obviously. I believe they are reasonably well
- Xwritten, making it possible for someone to be able to understand and modify
- Xthem.
- X
- XRunning the whole test suite takes a long time. On my machine with 40 Mb of
- Xmain memory, it requires 12 minutes to complete. It may take a lot longer
- Xif you do not have at least 16 Mb of RAM.
- X
- XThe option -i turns the incremental mode on. This proved really nice to
- Xme when I was writing this suite, as I was able to skip all the successful
- Xtests and focus only on those which failed or the new ones. The -s option will
- Xcause the test suite to stop at the first error. Normally, only failed basic
- Xtests abort the process. The -o option will not restart the tests from scratch,
- Xeven if the mailagent or filter is newer than the current OK file. Option -n
- Xwill test the non-dataloaded version of the mailagent (because of some bugs
- Xwith eval() which cause the dataloaded version to dump core via a segmentation
- Xviolation).
- X
- XI don't know why I spent some time documenting all this, as I don't expect
- Xanybody to have any chance working on this suite. Anyway, it might be nice
- Xknowing that all the successful tests are recorded in an OK file, along
- Xwith the time stamp of the test, so we may re-run those which were updated
- Xsince last run. In the event the mailagent or the filter are modified, the
- Xtests are re-run throughoutfully.
- X
- XThe file 'level' is optional. If present, it gives the default logging level
- Xto be applied when most of the tests are run (i.e. for those who do not require
- Xany special logging level). If absent, no logging will be done (except for
- Xthose tests who do require... etc...). All the tests are performed in the
- X'out' subdirectory, with the user name set to 'nobody'. That may help a lot
- Xwhen testing commands like RUN, as they have the nasty habbit to mail you, the
- Xuser, their output when they fail for whatever reason.
- X
- XThe generic mail used by the test is an automatic answer I got from the
- Xcomp.compilers newsgroup moderator the day I posted my first article to that
- Xgroup. It has no special value, appart from having some constants relative
- Xto it hardwired within the tests themselves. Don't touch it, even to remove
- Xa white space or some tests may fail (particularily GIVE and PIPE, which have
- Xthe output of 'wc' hardwired). On my machine, here is the output of 'wc mail':
- X
- X 34 227 1620 mail
- X
- XIn the event some of the tests do not pass, there is no reason to panic, and
- Xit doesn't necesseratily mean the mailagent has a bug. It is more likely a
- Xcombinaison of perl + dataloading + bugs + memory + moon's position. Try
- Xto run the test suite again, and then one more time. It sometimes helps.
- XAlso try changing the logging level via 'level' to see if it doesn't make
- Xany difference. This is not really rational, but empirical law :-).
- X
- XI think that's all there is to say.
- END_OF_FILE
- if test 3329 -ne `wc -c <'agent/test/README'`; then
- echo shar: \"'agent/test/README'\" unpacked with wrong size!
- fi
- # end of 'agent/test/README'
- fi
- if test -f 'agent/test/rules' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agent/test/rules'\"
- else
- echo shar: Extracting \"'agent/test/rules'\" \(2993 characters\)
- sed "s/^X//" >'agent/test/rules' <<'END_OF_FILE'
- Xmaildir = ~;
- Xmailfilter = ~;
- X
- XSubject: /test/ { DELETE };
- X
- X# filter/default
- XX-Tag: /default #1/ { DELETE };
- XX-Tag: /default #2/ { NOP };
- XX-Tag: /unknown/ { UNKNOWN };
- X
- X# filter/loop
- XX-Tag: /loop #1/ { BEGIN LOOP; RESTART };
- XX-Tag: /loop #2/ { DELETE };
- X
- X# filter/multiple
- XX-None Subject To X-Tag: /multiple #1/ { SAVE %u.1 };
- XX-None X-Tag: /multiple #2/, X-Other: /another/,
- XTo Cc: root, Cc To: ram { SAVE %u.3; REJECT MULTIPLE };
- X<MULTIPLE> X-Non-Existent: * { SAVE %u.2 };
- XX-Tag: /multiple #2/, X-Other: /multiple #2/ { SAVE %u.2 };
- X
- X# filter/list
- XX-Tag: /list/ { BEGIN LIST; REJECT };
- X<LIST> To: ram { SAVE %u.1 };
- X<LIST> To: max { SAVE %u.2 };
- X<LIST> To: /^root@eiffel.com$/ { SAVE %u.3 };
- X<LIST> To: /^riot@eiffel.co$/ { DELETE };
- X<LIST> To: /^riot@eiffel.com$/ { SAVE %u.4 };
- X<LIST> To: /^riot/ { SAVE %u.5 };
- X<LIST> To: /riot/ { SAVE %u.6 };
- X<LIST> Newsgroups: news.lists { SAVE %u.7 };
- X<LIST> To: !ram { SAVE %u.8 };
- X
- X# filter/pattern
- XX-T.*: "pattern-list" { BEGIN PAT; REJECT };
- X<PAT> .*Re[^\-]*$: *, ^Sub*: * { RUN /bin/echo '%&' > macro; DELETE };
- X
- X# filter/backref
- XX-Tag: /^back(.*) #1/,
- XSubject: /Re:\s+(\w+)\s+ice\s+(\w+)/,
- XFrom: /(.*)compilers/,
- XFrom: /com(.*)rs/,
- XTo: /^(\w+)@(\S+)/ { RUN /bin/echo '%1,%4,%5@%6,%2 %3' > output; DELETE };
- X
- XX-Tag: /^back.* #2/,
- XNewsgroups:
- X /(comp.lang.perl)/,
- X /(comp.unix.wizards)/,
- X /(comp.mail.mh)/ { SAVE %1 };
- X
- X# filter/escape
- XX-Tag: /escape/ { RUN /bin/echo '\;,\\\;,\\,\w' > output; DELETE };
- X
- X# filter/not
- XX-Tag: /not #1/ { BEGIN NOT; REJECT };
- X<NOT> To: !ram { SAVE never };
- X<NOT> To: !/ram@eiffel/ { SAVE never };
- X<NOT> To: !/^ram/i { SAVE never };
- X<NOT> To: /^ram/i { SAVE always; REJECT };
- X<NOT> To: !/^root/i { SAVE always.2; REJECT };
- X<NOT> X-Tag: !"pattern-list" { SAVE always.3 };
- X
- XX-Tag: /not #2/,
- X!To: !ram,
- XTo: !compilers,
- X!From: root { SAVE always };
- X
- X# filter/group
- XX-Tag: /group/ { BEGIN GROUP; REJECT };
- X<GROUP> !To !From: ram { SAVE never };
- X<GROUP> To !From: !ram { SAVE never };
- X<GROUP> !To !From: ram,
- X !Subject !From: ram { SAVE never };
- X<GROUP> !To: root, ram { SAVE never };
- X<GROUP> !F.*: /compiler/ { SAVE never };
- X<GROUP> !From: ram, !To: ram { SAVE always; REJECT };
- X<GROUP> From: ram, To: ram { SAVE never };
- X<GROUP> From: /compiler/,
- X !From: ram, !From: !/compiler/ { SAVE always.2; REJECT };
- X<GROUP> From !Cc !To: /compiler/,
- X From !Cc !To: ram,
- X !From To Cc: /eiffel/,
- X !From To Cc: !/ice/ { SAVE always.3 };
- X
- X# filter/case
- XX-Tag: case, Cc: root { STRIP Cc; SAVE always };
- X
- X# filter/status
- XX-Tag: /status/ { REJECT -t STATUS };
- X<STATUS> { RUN ../no/such/file; REJECT -t; SAVE always; REJECT -t; SAVE never };
- X<STATUS> { RUN ../this/does/not/exist; REJECT -f; SAVE never };
- X<STATUS> { RUN ../nor/does/this; REJECT -t; REJECT -t; REJECT -f; SAVE never };
- X<STATUS> { SAVE always.2; REJECT -f; BEGIN INITIAL; REJECT -t };
- X<INITIAL> X-Tag: /status/ { SAVE always.3 };
- X
- X# filter/hook
- XX-Tag: /hook #(\d)/ { SAVE hook.%1; ABORT -t; SAVE never };
- X
- END_OF_FILE
- if test 2993 -ne `wc -c <'agent/test/rules'`; then
- echo shar: \"'agent/test/rules'\" unpacked with wrong size!
- fi
- # end of 'agent/test/rules'
- fi
- if test -f 'install.SH' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'install.SH'\"
- else
- echo shar: Extracting \"'install.SH'\" \(3632 characters\)
- sed "s/^X//" >'install.SH' <<'END_OF_FILE'
- Xcase $CONFIG in
- X'')
- X if test ! -f config.sh; then
- X ln ../config.sh . || \
- X ln ../../config.sh . || \
- X ln ../../../config.sh . || \
- X (echo "Can't find config.sh."; exit 1)
- X fi 2>/dev/null
- X . config.sh
- X ;;
- Xesac
- Xcase "$0" in
- X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
- Xesac
- Xecho "Extracting install (with variable substitutions)"
- X$spitshell >install <<!GROK!THIS!
- X$startsh
- X# @(#) Installing script accepting bsd-style arguments
- X
- X# $Id: install.SH,v 2.9 92/07/14 16:53:45 ram Exp $
- X#
- X# Copyright (c) 1991, Raphael Manfredi
- X#
- X# You may redistribute only under the terms of the GNU General Public
- X# Licence as specified in the README file that comes with dist.
- X#
- X# $Log: install.SH,v $
- X# Revision 2.9 92/07/14 16:53:45 ram
- X# 3.0 beta baseline.
- X#
- X
- Xchown='$chown'
- Xchmod='$chmod'
- Xchgrp='$chgrp'
- Xrm='$rm'
- Xmv='$mv'
- Xtest='$test'
- Xsed='$sed'
- X!GROK!THIS!
- X$spitshell >>install <<'!NO!SUBS!'
- X
- Xmode=""
- Xdst=""
- Xsrc=""
- Xdostrip=""
- Xnewdir=""
- Xuid=""
- Xgid=""
- X
- X# simulates mkdir -p
- Xmkdir_p='
- Xname=$1;
- Xcreate="";
- Xwhile $test $name; do
- X if $test ! -d "$name"; then
- X create="$name $create";
- X name=`echo $name | $sed -e "s|^[^/]*$||"`;
- X name=`echo $name | $sed -e "s|\(.*\)/.*|\1|"`;
- X else
- X name="";
- X fi;
- Xdone;
- Xfor file in $create; do
- X mkdir $file && $test $verbose &&
- X echo "install: created directory $file" >&2;
- Xdone
- X'
- X
- Xverbose=''
- X
- Xwhile $test x$1 != x
- Xdo
- X case $1 in
- X -c) shift
- X continue
- X ;;
- X -m) mode="$2 "
- X shift
- X shift
- X continue
- X ;;
- X -o) uid="$2 "
- X shift
- X shift
- X continue
- X ;;
- X -g) gid="$2 "
- X shift
- X shift
- X continue
- X ;;
- X -s) dostrip="strip"
- X shift
- X continue
- X ;;
- X -d) newdir="$newdir$2 "
- X shift
- X shift
- X continue
- X ;;
- X -v) verbose='true'
- X shift
- X ;;
- X *) if $test x$src = x
- X then
- X src=$1
- X else
- X dst=$1
- X fi
- X shift
- X continue
- X ;;
- X esac
- Xdone
- X
- X# if -d option is used, we have to create the path given
- Xif $test ! x$newdir = x
- Xthen
- X for i in $newdir
- X do
- X set x $i
- X shift
- X eval $mkdir_p
- X done
- X exit 0 # -d is the only action
- Xfi
- X
- Xif $test x$src = x
- Xthen
- X echo "install: no input file specified" >&2
- X exit 1
- Xfi
- X
- Xif $test x$dst = x
- Xthen
- X echo "install: no destination specified" >&2
- X exit 1
- Xfi
- X
- Xsrcbase=`basename $src`
- Xdstbase=`basename $dst`
- X
- X# If the destination is a directory, the target name is srcbase...
- Xif $test -d $dst; then
- X dstbase=$srcbase
- Xelse
- X dst="`echo $dst | sed 's,^\(.*\)/.*$,\1,'`"
- X if $test ! -d $dst; then
- X dstbase=$dst
- X dst="."
- X fi
- Xfi
- X
- X# If the src has a directory, extract the dir name...
- Xif $test "$src" != "$srcbase" -a "$src" != "./$srcbase"; then
- X src="`echo $src | sed 's,^\(.*\)/.*$,\1,'`"
- Xelse
- X src="."
- Xfi
- X
- X# dst is the destination directory and dstbase the base name.
- X# srcbase is the base name of source and src the source dir.
- X
- Xsrcpth=`(cd $src; pwd)`/$srcbase
- Xdestpth=`(cd $dst; pwd)`/$dstbase
- Xif $test x$srcpth = x$destpth; then
- X $test $verbose && \
- X echo "install: destination and source are identical"
- X exit 0
- Xfi
- X
- X# Do the install
- X(
- X cd $src
- X
- X if $test -f $dst/$dstbase; then
- X $rm -f $dst/$dstbase && $test $verbose &&
- X echo "install: $dst/$dstbase removed"
- X fi
- X if $test -f $dst/$dstbase; then
- X $mv $dst/$dstbase $dst/OLD$dstbase && $test $verbose &&
- X echo "install: $dst/$dstbase renamed as OLD$dstbase"
- X fi
- X
- X cp $srcbase $dst/$dstbase && $test $verbose &&
- X echo "install: $srcbase installed as $dst/$dstbase"
- X
- X if $test ! x$dostrip = x; then
- X strip $dst/$dstbase 2>/dev/null && $test $verbose &&
- X echo "install: stripped $dst/$dstbase"
- X fi
- X
- X if $test ! x$uid = x; then
- X $chown $uid $dst/$dstbase
- X fi
- X if $test ! x$gid = x; then
- X $chgrp $gid $dst/$dstbase
- X fi
- X if $test ! x$mode = x
- X then
- X $chmod $mode $dst/$dstbase
- X fi
- X)
- X
- Xexit 0
- X!NO!SUBS!
- Xchmod 755 install
- X$eunicefix install
- END_OF_FILE
- if test 3632 -ne `wc -c <'install.SH'`; then
- echo shar: \"'install.SH'\" unpacked with wrong size!
- fi
- chmod +x 'install.SH'
- # end of 'install.SH'
- fi
- echo shar: End of archive 14 \(of 17\).
- cp /dev/null ark14isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 17 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-