home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume33 / mailagnt / part14 < prev    next >
Encoding:
Text File  |  1992-11-20  |  54.6 KB  |  1,850 lines

  1. Newsgroups: comp.sources.misc
  2. From: ram@eiffel.com (Raphael Manfredi)
  3. Subject:  v33i106:  mailagent - Rule Based Mail Filtering, Part14/17
  4. Message-ID: <1992Nov20.230841.27156@sparky.imd.sterling.com>
  5. X-Md4-Signature: 112247dbfb2ef1c4f43313c9a26fabf6
  6. Date: Fri, 20 Nov 1992 23:08:41 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: ram@eiffel.com (Raphael Manfredi)
  10. Posting-number: Volume 33, Issue 106
  11. Archive-name: mailagent/part14
  12. Environment: Perl, Sendmail, UNIX
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then feed it
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # Contents:  agent/files/Makefile.SH agent/files/mailagent.cf
  19. #   agent/filter/lock.c agent/filter/sysexits.h agent/mhook.SH
  20. #   agent/pl/builtins.pl agent/pl/context.pl agent/pl/distribs.pl
  21. #   agent/pl/mbox.pl agent/pl/plsave.pl agent/pl/pqueue.pl
  22. #   agent/test/Makefile.SH agent/test/README agent/test/rules
  23. #   install.SH
  24. # Wrapped by kent@sparky on Wed Nov 18 22:42:31 1992
  25. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  26. echo If this archive is complete, you will see the following message:
  27. echo '          "shar: End of archive 14 (of 17)."'
  28. if test -f 'agent/files/Makefile.SH' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'agent/files/Makefile.SH'\"
  30. else
  31.   echo shar: Extracting \"'agent/files/Makefile.SH'\" \(3518 characters\)
  32.   sed "s/^X//" >'agent/files/Makefile.SH' <<'END_OF_FILE'
  33. X: Makefile.SH generated from Jmake.tmpl and Jmakefile [jmake 2.8 PL13]
  34. X: $X-Id: Jmake.tmpl,v 2.8.1.2 91/11/18 13:22:54 ram Exp $
  35. X
  36. Xcase $CONFIG in
  37. X'')
  38. X    if test ! -f config.sh; then
  39. X        ln ../config.sh . || \
  40. X        ln ../../config.sh . || \
  41. X        ln ../../../config.sh . || \
  42. X        (echo "Can't find config.sh."; exit 1)
  43. X    fi 2>/dev/null
  44. X    . ./config.sh
  45. X    ;;
  46. Xesac
  47. Xcase "$0" in
  48. X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
  49. Xesac
  50. XCURRENT=agent/files
  51. XDIR=`echo $CURRENT/ | sed -e 's/\.\///g'`
  52. Xecho "Extracting ${DIR}Makefile (with variable substitutions)"
  53. XDATE=`date`
  54. X$spitshell >Makefile <<!GROK!THIS!
  55. X########################################################################
  56. X# Makefile generated from Makefile.SH on $DATE
  57. X
  58. XSHELL = /bin/sh
  59. XJMAKE = jmake
  60. XTOP = ../..
  61. XCURRENT = $CURRENT
  62. XDIR = $DIR
  63. XINSTALL = ../../install
  64. X
  65. X########################################################################
  66. X# Parameters set by Configure -- edit config.sh if changes are needed
  67. X
  68. XCTAGS = ctags
  69. XMAKE = make
  70. XMV = $mv
  71. XPRIVLIB = $privlib
  72. XRM = $rm -f
  73. X
  74. X!GROK!THIS!
  75. X$spitshell >>Makefile <<'!NO!SUBS!'
  76. X
  77. X########################################################################
  78. X# Jmake rules for building libraries, programs, scripts, and data files
  79. X# $X-Id: Jmake.rules,v 2.8.1.4 91/11/18 13:19:07 ram Exp $
  80. X
  81. X########################################################################
  82. X# Start of Jmakefile
  83. X
  84. X# $X-Id: Jmakefile,v 2.9 92/07/14 16:47:32 ram Exp $
  85. X#
  86. X#  Copyright (c) 1991, Raphael Manfredi
  87. X#
  88. X#  You may redistribute only under the terms of the GNU General Public
  89. X#  Licence as specified in the README file that comes with dist.
  90. X#
  91. X# $X-Log:    Jmakefile,v $
  92. X# Revision 2.9  92/07/14  16:47:32  ram
  93. X# 3.0 beta baseline.
  94. X#
  95. X
  96. XFILES = agenthelp commands distribs filter.sh mailagent.cf proglist \
  97. X    chkagent.sh
  98. X
  99. Xall::
  100. X
  101. Xinstall::
  102. X    @for dir in $(PRIVLIB) $(PRIVLIB)/mailagent; do \
  103. X        case '${MFLAGS}' in *[i]*) set +e;; esac; \
  104. X        (set -x; $(INSTALL) -d $$dir); \
  105. X    done
  106. X
  107. Xdeinstall::
  108. X    $(RM) -r $(PRIVLIB) $(PRIVLIB)/mailagent
  109. X
  110. Xinstall:: $(FILES)
  111. X    @case '${MFLAGS}' in *[i]*) set +e;; esac; \
  112. X    for i in $(FILES); do \
  113. X        (set -x; $(INSTALL) -c -m 444 $$i $(PRIVLIB)/mailagent); \
  114. X    done
  115. X
  116. Xdeinstall::
  117. X    @case '${MFLAGS}' in *[i]*) set +e;; esac; \
  118. X    for i in $(FILES); do \
  119. X        (set -x; $(RM) $(PRIVLIB)/mailagent/$$i); \
  120. X    done
  121. X
  122. X########################################################################
  123. X# Common rules for all Makefiles -- do not edit
  124. X
  125. Xemptyrule::
  126. X
  127. Xclean: local_clean
  128. Xrealclean: local_realclean
  129. Xclobber: local_clobber
  130. X
  131. Xlocal_clean::
  132. X    $(RM) core *~ *.o
  133. X
  134. Xlocal_realclean:: local_clean
  135. X
  136. Xlocal_clobber:: local_realclean
  137. X    $(RM) Makefile config.sh
  138. X
  139. XMakefile.SH: Jmakefile
  140. X    -@if test -f $(TOP)/.package; then \
  141. X        if test -f Makefile.SH; then \
  142. X            echo "    $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~"; \
  143. X            $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~; \
  144. X        fi; \
  145. X        echo "    $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT)" ; \
  146. X        $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT) ; \
  147. X    else touch $@; exit 0; fi
  148. X
  149. XMakefile: Makefile.SH
  150. X    /bin/sh Makefile.SH
  151. X
  152. Xtags::
  153. X    $(CTAGS) -w *.[ch]
  154. X    $(CTAGS) -xw *.[ch] > tags
  155. X
  156. Xlocal_clobber::
  157. X    $(RM) tags
  158. X
  159. X########################################################################
  160. X# Empty rules for directories with no sub-directories -- do not edit
  161. X
  162. Xinstall::
  163. X    @echo "install in $(CURRENT) done."
  164. X
  165. Xdeinstall::
  166. X    @echo "deinstall in $(CURRENT) done."
  167. X
  168. Xinstall.man::
  169. X    @echo "install.man in $(CURRENT) done."
  170. X
  171. Xdeinstall.man::
  172. X    @echo "deinstall.man in $(CURRENT) done."
  173. X
  174. XMakefiles::
  175. X
  176. XMakefiles.SH::
  177. X
  178. X!NO!SUBS!
  179. Xchmod 644 Makefile
  180. X$eunicefix Makefile
  181. X
  182. END_OF_FILE
  183.   if test 3518 -ne `wc -c <'agent/files/Makefile.SH'`; then
  184.     echo shar: \"'agent/files/Makefile.SH'\" unpacked with wrong size!
  185.   fi
  186.   chmod +x 'agent/files/Makefile.SH'
  187.   # end of 'agent/files/Makefile.SH'
  188. fi
  189. if test -f 'agent/files/mailagent.cf' -a "${1}" != "-c" ; then 
  190.   echo shar: Will not clobber existing file \"'agent/files/mailagent.cf'\"
  191. else
  192.   echo shar: Extracting \"'agent/files/mailagent.cf'\" \(2518 characters\)
  193.   sed "s/^X//" >'agent/files/mailagent.cf' <<'END_OF_FILE'
  194. X#
  195. X# Configuration file for mailagent
  196. X#
  197. X
  198. X# $Id: mailagent.cf,v 2.9.1.1 92/08/02 15:52:42 ram Exp $
  199. X#
  200. X#  Copyright (c) 1991, Raphael Manfredi
  201. X#
  202. X#  You may redistribute only under the terms of the GNU General Public
  203. X#  Licence as specified in the README file that comes with dist.
  204. X#
  205. X# $Log:    mailagent.cf,v $
  206. X# Revision 2.9.1.1  92/08/02  15:52:42  ram
  207. X# patch2: new configuration parameter to specify mailbox file
  208. X# 
  209. X# Revision 2.9  92/07/14  16:47:51  ram
  210. X# 3.0 beta baseline.
  211. X# 
  212. X
  213. X#
  214. X# Configuration section
  215. X#
  216. X
  217. X# Paramters likely to change
  218. Xhome     : /lyon/ram            # Home directory (must be correctly set)
  219. Xlevel    : 9                    # Logging level
  220. Xtmpdir   : /tmp                    # Temporary directory to be used
  221. Xemergdir : ~/tmp/lost+mail        # Emergency directory (for dumps)
  222. Xtrack    : OFF                    # Track matches on stdout (on/off)
  223. X
  224. X# Minimum path to ensure and path depending on the machine
  225. Xpath     : /bin:/usr/bin:/usr/ucb
  226. Xp_york   : ~/bin:~/bin/rs2030
  227. Xp_lyon   : ~/bin:~/bin/rs2030
  228. Xp_rome   : ~/bin:~/bin/sun4:/base/common/GENERAL/sun4/bin
  229. X
  230. X# User who runs mailagent
  231. Xuser     : ram
  232. Xname     : Raphael
  233. X
  234. X# Vacation mode (on/off), vacation file and period
  235. Xvacation : OFF                    # Vacation mode on/off
  236. Xvacfile  : ~/.vacation            # File to be sent back
  237. Xvacperiod: 1d                    # Period between two vacation messages
  238. X
  239. X
  240. X#
  241. X# Parameters which should not change very often
  242. X#
  243. X
  244. X# Define main configuration parameters
  245. Xspool    : ~/var/mailagent        # Spool directory
  246. Xqueue    : $spool/queue            # Queue directory (must exist)
  247. Xlogdir   : ~/var/log            # Where logfile is stored
  248. Xcontext  : $spool/context        # Mailagent's context file
  249. Xlog      : agentlog                # Log file is in $logdir
  250. Xseq      : .seq                    # Seq file is in $spool
  251. Xtimezone : PST8PDT                # Time zone location
  252. Xstatfile : $spool/mailagent.st    # Statistics file
  253. Xrules    : ~/.rules                # Filter's rules location (optional)
  254. Xmaildrop : /usr/mail            # System mail drop directory (optional)
  255. Xmailbox  : $user                # Mailbox file name (optional)
  256. X
  257. X# Database hashing directory (in $spool) and other controls
  258. Xhash     : dbr                    # Hashing directory
  259. Xcleanlaps: 1M                    # Laps between cleanings
  260. Xautoclean: ON                    # Turn periodic cleaning on/off
  261. Xagemax   : 1y                    # Maximum lifetime for entries
  262. X
  263. X
  264. X#
  265. X# Parameters for PROCESS
  266. X#
  267. X
  268. Xcomfile  : $spool/commands        # Valid commands
  269. Xdistlist : $spool/distribs        # Distribution list
  270. Xproglist : $spool/proglist        # Program description list
  271. Xmaxsize  : 150000                # Maximum size before kiting
  272. Xplsave   : $spool/plsave        # Where patchlevels are saved
  273. Xauthfile : $spool/auth            # Remote sending authorizations
  274. END_OF_FILE
  275.   if test 2518 -ne `wc -c <'agent/files/mailagent.cf'`; then
  276.     echo shar: \"'agent/files/mailagent.cf'\" unpacked with wrong size!
  277.   fi
  278.   # end of 'agent/files/mailagent.cf'
  279. fi
  280. if test -f 'agent/filter/lock.c' -a "${1}" != "-c" ; then 
  281.   echo shar: Will not clobber existing file \"'agent/filter/lock.c'\"
  282. else
  283.   echo shar: Extracting \"'agent/filter/lock.c'\" \(2525 characters\)
  284.   sed "s/^X//" >'agent/filter/lock.c' <<'END_OF_FILE'
  285. X/*
  286. X
  287. X #        ####    ####   #    #           ####
  288. X #       #    #  #    #  #   #           #    #
  289. X #       #    #  #       ####            #
  290. X #       #    #  #       #  #     ###    #
  291. X #       #    #  #    #  #   #    ###    #    #
  292. X ######   ####    ####   #    #   ###     ####
  293. X
  294. X    Lock file handling.
  295. X*/
  296. X
  297. X#include "config.h"
  298. X#include "portable.h"
  299. X#include <errno.h>
  300. X#include <sys/types.h>
  301. X#include <sys/stat.h>
  302. X
  303. X#ifdef I_FCNTL
  304. X#include <fcntl.h>
  305. X#else
  306. X#include <sys/fcntl.h>
  307. X#endif
  308. X#ifdef I_SYSFILE
  309. X#include <sys/file.h>
  310. X#endif
  311. X
  312. X#define MAX_STRING    2048        /* Max string length */
  313. X#define MAX_TIME    3600        /* One hour */
  314. X
  315. Xprivate char lockfile[MAX_STRING];        /* Location of lock file */
  316. Xprivate int locked = 0;                    /* Did we lock successfully? */
  317. X
  318. Xprivate void check_lock();                /* Make sure lockfile is not too old */
  319. X
  320. Xextern int errno;                        /* System error status */
  321. Xextern Time_t time();                    /* Current time */
  322. X
  323. Xpublic int filter_lock(dir)
  324. Xchar *dir;                        /* Where lockfile should be written */
  325. X{
  326. X    /* Note: this locking is not completly safe w.r.t. race conditions, but the
  327. X     * mailagent will do its own locking checks in a rather safe way.
  328. X     * Return 0 if locking succeeds, -1 otherwise.
  329. X     */
  330. X
  331. X    int fd;
  332. X
  333. X    sprintf(lockfile, "%s/filter.lock", dir);
  334. X    check_lock(lockfile);
  335. X    if (-1 == (fd = open(lockfile, O_CREAT | O_EXCL, 0))) {
  336. X        if (errno != EEXIST)
  337. X            add_log(1, "SYSERR open: %m (%e)");
  338. X        return -1;
  339. X    }
  340. X    locked = 1;                    /* We did lock successfully */
  341. X    close(fd);                    /* Close dummy file descriptor */
  342. X
  343. X    return 0;
  344. X}
  345. X
  346. Xpublic void release_lock()
  347. X{
  348. X    if (locked && -1 == unlink(lockfile)) {
  349. X        add_log(1, "SYSERR unlink: %m (%e)");
  350. X        add_log(4, "WARNING could not remove lockfile %s", lockfile);
  351. X    }
  352. X    locked = 0;
  353. X}
  354. X
  355. Xpublic int is_locked()
  356. X{
  357. X    return locked;            /* Do we have a lock file active or not? */
  358. X}
  359. X
  360. Xprivate void check_lock(file)
  361. Xchar *file;
  362. X{
  363. X    /* Make sure the lock file is not older than MAX_TIME seconds, otherwise
  364. X     * unlink it (something must have gone wrong).
  365. X     */
  366. X
  367. X    struct stat buf;
  368. X
  369. X    if (-1 == stat(file, &buf)) {        /* Stat failed */
  370. X        if (errno == ENOENT)            /* File does not exist */
  371. X            return;
  372. X        add_log(1, "SYSERR stat: %m (%e)");
  373. X        add_log(2, "could not check lockfile %s", file);
  374. X        return;
  375. X    }
  376. X
  377. X    if ((buf.st_mtime - time((Time_t *) 0)) > MAX_TIME) {
  378. X        if (-1 == unlink(lockfile)) {
  379. X            add_log(1, "SYSERR unlink: %m (%e)");
  380. X            add_log(4, "WARNING could not remove old lock %s", lockfile);
  381. X        } else
  382. X            add_log(6, "UNLOCKED filter (lock older than 1 hour)");
  383. X    } else
  384. X        add_log(16, "lockfile for filter is recent");
  385. X}
  386. X
  387. END_OF_FILE
  388.   if test 2525 -ne `wc -c <'agent/filter/lock.c'`; then
  389.     echo shar: \"'agent/filter/lock.c'\" unpacked with wrong size!
  390.   fi
  391.   # end of 'agent/filter/lock.c'
  392. fi
  393. if test -f 'agent/filter/sysexits.h' -a "${1}" != "-c" ; then 
  394.   echo shar: Will not clobber existing file \"'agent/filter/sysexits.h'\"
  395. else
  396.   echo shar: Extracting \"'agent/filter/sysexits.h'\" \(1166 characters\)
  397.   sed "s/^X//" >'agent/filter/sysexits.h' <<'END_OF_FILE'
  398. X/*
  399. X
  400. X  ####    #   #   ####   ######  #    #     #     #####   ####           #    #
  401. X #         # #   #       #        #  #      #       #    #               #    #
  402. X  ####      #     ####   #####     ##       #       #     ####           ######
  403. X      #     #         #  #         ##       #       #         #   ###    #    #
  404. X #    #     #    #    #  #        #  #      #       #    #    #   ###    #    #
  405. X  ####      #     ####   ######  #    #     #       #     ####    ###    #    #
  406. X
  407. X    Standard exit codes for sendmail and friends.
  408. X    Original list maintained by Eric Allman <eric@berkeley.edu>.
  409. X*/
  410. X
  411. X/*
  412. X * $Id: sysexits.h,v 2.9 92/07/14 16:48:43 ram Exp $
  413. X *
  414. X *  Copyright (c) 1992, Raphael Manfredi
  415. X *
  416. X *  You may redistribute only under the terms of the GNU General Public
  417. X *  Licence as specified in the README file that comes with dist.
  418. X *
  419. X * $Log:    sysexits.h,v $
  420. X * Revision 2.9  92/07/14  16:48:43  ram
  421. X * 3.0 beta baseline.
  422. X * 
  423. X */
  424. X
  425. X#ifndef _sysexits_h_
  426. X#define _sysexits_h_
  427. X
  428. X#define EX_OK            0
  429. X#define EX_USAGE        64
  430. X#define EX_UNAVAILABLE    69
  431. X#define EX_OSERR        71
  432. X#define EX_OSFILE        72
  433. X#define EX_CANTCREAT    73
  434. X#define EX_IOERR        74
  435. X#define EX_TEMPFAIL        75
  436. X
  437. X#endif
  438. END_OF_FILE
  439.   if test 1166 -ne `wc -c <'agent/filter/sysexits.h'`; then
  440.     echo shar: \"'agent/filter/sysexits.h'\" unpacked with wrong size!
  441.   fi
  442.   # end of 'agent/filter/sysexits.h'
  443. fi
  444. if test -f 'agent/mhook.SH' -a "${1}" != "-c" ; then 
  445.   echo shar: Will not clobber existing file \"'agent/mhook.SH'\"
  446. else
  447.   echo shar: Extracting \"'agent/mhook.SH'\" \(3834 characters\)
  448.   sed "s/^X//" >'agent/mhook.SH' <<'END_OF_FILE'
  449. Xcase $CONFIG in
  450. X'')
  451. X    if test ! -f config.sh; then
  452. X        ln ../config.sh . || \
  453. X        ln ../../config.sh . || \
  454. X        ln ../../../config.sh . || \
  455. X        (echo "Can't find config.sh."; exit 1)
  456. X    fi 2>/dev/null
  457. X    . config.sh
  458. X    ;;
  459. Xesac
  460. Xcase "$0" in
  461. X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
  462. Xesac
  463. Xecho "Extracting agent/mhook (with variable substitutions)"
  464. X$spitshell >mhook <<!GROK!THIS!
  465. X# feed this into perl
  466. X    eval 'exec perl -S \$0 "\$@"'
  467. X        if \$running_under_some_shell;
  468. X
  469. X# You'll need to set up a .forward file that feeds your mail to this script,
  470. X# via the filter. Mine looks like this:
  471. X#   "|exec /users/ram/mail/filter >>/users/ram/.bak 2>&1"
  472. X
  473. X# $Id: mhook.SH,v 2.9.1.1 92/08/26 12:44:48 ram Exp $
  474. X#
  475. X#  Copyright (c) 1991, 1992, Raphael Manfredi
  476. X#
  477. X#  You may redistribute only under the terms of the GNU General Public
  478. X#  Licence as specified in the README file that comes with dist.
  479. X#
  480. X# $Log:    mhook.SH,v $
  481. X# Revision 2.9.1.1  92/08/26  12:44:48  ram
  482. X# patch8: created
  483. X# 
  484. X
  485. X# Perload ON
  486. X
  487. X# The following were determined by Configure
  488. X\$mversion = '$VERSION';            # Current version number
  489. X\$patchlevel = '$PATCHLEVEL';        # And patchlevel from patchlevel.h
  490. X!GROK!THIS!
  491. X
  492. X$spitshell >>mhook <<'!NO!SUBS!'
  493. X
  494. X$prog_name = $0;                # Who I am
  495. X$prog_name =~ s|^.*/(.*)|$1|;    # Keep only base name
  496. X$has_option = 0;                # True if invoked with options
  497. X$config_file = '~/.mailagent';    # Default configuration file
  498. X
  499. X# Parse options
  500. Xwhile ($ARGV[0] =~ /^-/) {
  501. X    $_ = shift;
  502. X    last if /--/;
  503. X    if ($_ eq '-h') {
  504. X        &usage;
  505. X    }
  506. X    elsif ($_ eq '-V') {    # Version number
  507. X        print STDERR "$prog_name $mversion PL$patchlevel\n";
  508. X        exit 0;
  509. X    }
  510. X    else {
  511. X        print STDERR "$prog_name: unknown option: $_\n";
  512. X        &usage;
  513. X    }
  514. X}
  515. X
  516. X$hook_name = shift;                # Where mailhook folder is located
  517. X&usage unless $hook_name;        # Hook file is a mandatory argument
  518. X$file_name = shift;                # File name to be processed (null if stdin)
  519. X
  520. X$ENV{'IFS'}='' if $ENV{'IFS'};    # Shell separation field
  521. X&read_config($config_file);        # Read configuration file and set cf package
  522. X
  523. X$ENV{'HOME'} = $cf'home;
  524. X$ENV{'USER'} = $cf'user;
  525. X$ENV{'NAME'} = $cf'name;
  526. X
  527. Xumask(077);                        # Files we create are private ones
  528. X$jobnum = &jobnum;                # Compute a job number
  529. X&init_all;                        # Start-up initializations
  530. X
  531. X$hook_type = &hook_type($hook_name);            # Determine kind of hook
  532. X&hooking($file_name, $hook_name, $hook_type);    # Print log message
  533. Xchdir($cf'home);                                # Hook called in home directory
  534. X&$hook_type($file_name, $hook_name);            # Invoke hooking function
  535. X
  536. X# End of mailhook processing
  537. X&add_log("mailhook exits") if $loglvl > 17;
  538. Xexit 0;
  539. X
  540. X# Print usage and exit
  541. Xsub usage {
  542. X    print STDERR <<EOF;
  543. XUsage: $prog_name [-hV] hook [mail]
  544. X  -h : print this help message and exits.
  545. X  -V : print version number and exits.
  546. XEOF
  547. X    exit 1;
  548. X}
  549. X
  550. X# Start-up initializations
  551. Xsub init_all {
  552. X    &init_signals;                # Trap common signals
  553. X    &init_constants;            # Constants definitions
  554. X}
  555. X
  556. X# Protect ourselves (trap common signals)
  557. Xsub init_signals {
  558. X    $SIG{'HUP'} = 'emergency';
  559. X    $SIG{'INT'} = 'emergency';
  560. X    $SIG{'QUIT'} = 'emergency';
  561. X    $SIG{'PIPE'} = 'emergency';
  562. X    $SIG{'IO'} = 'emergency';
  563. X    $SIG{'BUS'} = 'emergency';
  564. X    $SIG{'ILL'} = 'emergency';
  565. X    $SIG{'SEGV'} = 'emergency';
  566. X    $SIG{'ALRM'} = 'emergency';
  567. X    $SIG{'TERM'} = 'emergency';
  568. X}
  569. X
  570. X# Constants definitions
  571. Xsub init_constants {
  572. X    &init_hooks;                # Init hooks constants
  573. X}
  574. X
  575. X!NO!SUBS!
  576. X$grep -v '^;#' pl/jobnum.pl >>mhook
  577. X$grep -v '^;#' pl/read_conf.pl >>mhook
  578. X$grep -v '^;#' pl/acs_rqst.pl >>mhook
  579. X$grep -v '^;#' pl/free_file.pl >>mhook
  580. X$grep -v '^;#' pl/add_log.pl >>mhook
  581. X$grep -v '^;#' pl/checklock.pl >>mhook
  582. X$grep -v '^;#' pl/hook.pl >>mhook
  583. X$grep -v '^;#' pl/mailhook.pl >>mhook
  584. X$grep -v '^;#' pl/dbr.pl >>mhook
  585. X$grep -v '^;#' pl/fatal.pl >>mhook
  586. X$grep -v '^;#' pl/parse.pl >>mhook
  587. X$grep -v '^;#' pl/header.pl >>mhook
  588. X$grep -v '^;#' pl/rfc822.pl >>mhook
  589. X$grep -v '^;#' pl/extern.pl >>mhook
  590. Xchmod 755 mhook
  591. X$eunicefix mhook
  592. END_OF_FILE
  593.   if test 3834 -ne `wc -c <'agent/mhook.SH'`; then
  594.     echo shar: \"'agent/mhook.SH'\" unpacked with wrong size!
  595.   fi
  596.   # end of 'agent/mhook.SH'
  597. fi
  598. if test -f 'agent/pl/builtins.pl' -a "${1}" != "-c" ; then 
  599.   echo shar: Will not clobber existing file \"'agent/pl/builtins.pl'\"
  600. else
  601.   echo shar: Extracting \"'agent/pl/builtins.pl'\" \(3389 characters\)
  602.   sed "s/^X//" >'agent/pl/builtins.pl' <<'END_OF_FILE'
  603. X;# $Id: builtins.pl,v 2.9 92/07/14 16:49:38 ram Exp $
  604. X;#
  605. X;#  Copyright (c) 1992, Raphael Manfredi
  606. X;#
  607. X;#  You may redistribute only under the terms of the GNU General Public
  608. X;#  Licence as specified in the README file that comes with dist.
  609. X;#
  610. X;# $Log:    builtins.pl,v $
  611. X;# Revision 2.9  92/07/14  16:49:38  ram
  612. X;# 3.0 beta baseline.
  613. X;# 
  614. X;# 
  615. X#
  616. X# Executing builtin commands
  617. X#
  618. X
  619. X# Send a receipt
  620. Xsub send_receipt {
  621. X    local($subj) =            $Header{'Subject'};
  622. X    local($msg_id) =        $Header{'Message-Id'};
  623. X    local($from) =            $Header{'From'};
  624. X    local($sender) =        $Header{'Reply-To'};
  625. X    local($to) =            $Header{'To'};
  626. X    local($ack_dest) = @_;    # Were to send receipt
  627. X    local($dest);            # Return path to be used (derived from mail)
  628. X
  629. X    # If no @PATH directive was found, use $sender as a return path
  630. X    $dest = $Userpath;                # Set by an @PATH
  631. X    $dest = $sender unless $dest;
  632. X    # Remove the <> if any (e.g. path derived from Return-Path)
  633. X    $dest =~ /<(.*)>/ && ($dest = $1);
  634. X
  635. X    # Derive a correct return path for receipt
  636. X    $ack_dest = 'PATH' if $ack_dest eq '-';
  637. X    $ack_dest = "" if $ack_dest =~ /[=\$^&*([{}`\\|;><?]/;
  638. X    $ack_dest = $dest if ($ack_dest eq '' || $ack_dest =~ /PATH/);
  639. X
  640. X    # Compute host name (fully qualified, i.e. with domain name)
  641. X    chop($hostname = `$phostname`);
  642. X    $hostname .= $mydomain if $hostname =~ /^\w+$/;
  643. X
  644. X    chop($date = `date`);
  645. X    open(MAILER,"|/usr/lib/sendmail -odq -t");
  646. X    print MAILER
  647. X"To: $ack_dest
  648. XSubject: Re: $subj (receipt)
  649. XX-Mailer: mailagent [version $mversion PL$patchlevel]
  650. X";
  651. X    if ($msg_id ne '') {
  652. X        print MAILER "\nYour message $msg_id,\n";
  653. X    } else {
  654. X        print MAILER "\nYour message ";
  655. X    }
  656. X    print MAILER "addressed to $to,\n" if $to ne '';
  657. X    print MAILER "whose subject was \"$subj\",\n" if $subj ne '';
  658. X    print MAILER
  659. X"has been received by $hostname on $date
  660. X
  661. X-- mailagent speaking for $cf'user
  662. X";
  663. X    close MAILER;
  664. X    if ($?) {
  665. X        do add_log("ERROR couldn't send receipt to $ack_dest") if $loglvl > 0;
  666. X    } else {
  667. X        do add_log("SENT receipt to $ack_dest") if $loglvl > 2;
  668. X    }
  669. X}
  670. X
  671. X#
  672. X# Deal with builtins
  673. X#
  674. X
  675. X# Built-in commands are listed herein. Those commands being built-in are always
  676. X# dealt with during mail parsing and are taken care of at the beginning of the
  677. X# rules analysis. The code to be executed for each builtin is stored in the
  678. X# Builtcode array by those routines.
  679. Xsub init_builtins {
  680. X    %Builtin = (
  681. X        'RR', 'builtin_rr',
  682. X        'PATH', 'builtin_path'
  683. X    );
  684. X    undef @Builtcode;
  685. X}
  686. X
  687. X# Whenever a builtin command is recognized (on the fly) while parsing the mail
  688. X# body, the corresponding builtin function is called with the remaining of the
  689. X# line given as argument (leading spaces removed).
  690. X
  691. X# The @RR command asks for a receipt
  692. Xsub builtin_rr {
  693. X    local($_) = @_;
  694. X    do add_log("found an @RR request to $_") if $loglvl > 18;
  695. X    # @RR request honored only if not from special user and directed to us
  696. X    unless (&special_user) {
  697. X        push(@Builtcode, "do send_receipt('$_')");
  698. X    } else {
  699. X        &add_log("ignoring @RR request to $_") if $loglvl > 4;
  700. X    }
  701. X}
  702. X
  703. X# The @PATH command sets a valid return path (recorded in $Userpath)
  704. Xsub builtin_path {
  705. X    local($_) = @_;
  706. X    return if /[=\$^&*([{}`\\|;><?]/;        # Invalid character found
  707. X    $Userpath = $_;
  708. X    do add_log("found an @PATH request to $_") if $loglvl > 18;
  709. X}
  710. X
  711. X# Execute stacked builtins
  712. Xsub run_builtins {
  713. X    return if $#Builtcode < 0;        # No recorded builtins
  714. X    foreach (@Builtcode) {
  715. X        eval($_);                    # Execute stacked builtin
  716. X    }
  717. X    @Builtcode = ();                # Reset builtcode array
  718. X}
  719. X
  720. END_OF_FILE
  721.   if test 3389 -ne `wc -c <'agent/pl/builtins.pl'`; then
  722.     echo shar: \"'agent/pl/builtins.pl'\" unpacked with wrong size!
  723.   fi
  724.   # end of 'agent/pl/builtins.pl'
  725. fi
  726. if test -f 'agent/pl/context.pl' -a "${1}" != "-c" ; then 
  727.   echo shar: Will not clobber existing file \"'agent/pl/context.pl'\"
  728. else
  729.   echo shar: Extracting \"'agent/pl/context.pl'\" \(3363 characters\)
  730.   sed "s/^X//" >'agent/pl/context.pl' <<'END_OF_FILE'
  731. X;# $Id: context.pl,v 2.9 92/07/14 16:49:43 ram Exp $
  732. X;#
  733. X;#  Copyright (c) 1992, Raphael Manfredi
  734. X;#
  735. X;#  You may redistribute only under the terms of the GNU General Public
  736. X;#  Licence as specified in the README file that comes with dist.
  737. X;#
  738. X;# $Log:    context.pl,v $
  739. X;# Revision 2.9  92/07/14  16:49:43  ram
  740. X;# 3.0 beta baseline.
  741. X;# 
  742. X;# 
  743. X;# Keep track of the mailagent's context, in particular all the actions which
  744. X;# may be performed in a batched way and need to save some contextual data.
  745. X;#
  746. Xpackage context;
  747. X
  748. X#
  749. X# General handling
  750. X#
  751. X
  752. X# Initialize context from context file
  753. Xsub init {
  754. X    &default;                        # Load a default context
  755. X    return unless -f $cf'context;    # Finished if no saved context
  756. X    &load;                            # Load context, overwriting default context
  757. X    &clean;                            # Remove uneeded entries from context
  758. X}
  759. X
  760. X# Provide a default context
  761. Xsub default {
  762. X    %Context = (
  763. X        'last-clean', '0',            # Last cleaning of hash files
  764. X    );
  765. X}
  766. X
  767. X# Load the context entries
  768. Xsub load {
  769. X    unless(open(CONTEXT, "$cf'context")) {
  770. X        &'add_log("WARNING unable to open context file: $!") if $'loglvl > 5;
  771. X        return;
  772. X    }
  773. X    &'add_log("loading mailagent context") if $'loglvl > 15;
  774. X    local($_, $.);
  775. X    while (<CONTEXT>) {
  776. X        next if /^\s*#/;
  777. X        if (/^([\w\-]+)\s*:\s*(\S+)/) {
  778. X            $Context{$1} = $2;
  779. X            next;
  780. X        }
  781. X        &'add_log("WARNING context file corrupted, line $.") if $'loglvl > 5;
  782. X        last;
  783. X    }
  784. X    close CONTEXT;
  785. X}
  786. X
  787. X# Clean context, removing useless entries
  788. Xsub clean {
  789. X    delete $Context{'last-clean'} unless $cf'autoclean =~ /^on/i;
  790. X}
  791. X
  792. X# Save a new context file
  793. Xsub save {
  794. X    require 'ctime.pl';
  795. X    local($existed) = -f $cf'context;
  796. X    &'acs_rqst($cf'context) if $existed;    # Lock existing file
  797. X    unless (open(CONTEXT, ">$cf'context")) {
  798. X        &'add_log("ERROR cannot overwrite context file: $!") if $'loglvl > 1;
  799. X        return;
  800. X    }
  801. X    &'add_log("saving context file $cf'context") if $'loglvl > 17;
  802. X    local($key, $value, $item);
  803. X    print CONTEXT "# Mailagent context, last updated " . &'ctime(time);
  804. X    while (($key, $value) = each %Context) {
  805. X        next unless $value;
  806. X        $item++;
  807. X        print CONTEXT $key, ': ', $value, "\n";
  808. X    }
  809. X    close CONTEXT;
  810. X    unlink "$cf'context" unless $item;        # Do not leave empty context
  811. X    &'add_log("deleted empty context") if $'loglvl > 17 && !$item;
  812. X    &'free_file($cf'context) if $existed;
  813. X}
  814. X
  815. X#
  816. X# Context-dependant actions
  817. X#
  818. X
  819. X# Remove entries in dbr hash files which are old enough. For this operation
  820. X# to be performed, the autoclean variable must be set to ON in ~/.mailagent,
  821. X# the cleanlaps indicates the period for those automatic cleanings, and agemax
  822. X# specifies the maximum allowed time within the database.
  823. Xsub autoclean {
  824. X    return unless $cf'autoclean =~ /^on/i;
  825. X    local($period) = &'seconds_in_period($cf'cleanlaps);
  826. X    return if ($Context{'last-clean'} + $period) > time;
  827. X    # Retry time reached -- start auto cleaning
  828. X    &'add_log("autocleaning of dbr files") if $'loglvl > 8;
  829. X    $period = &'seconds_in_period($cf'agemax);
  830. X    &dbr'clean($period);
  831. X    $Context{'last-clean'} = time;            # Update last cleaning time
  832. X}
  833. X
  834. X#
  835. X# Perform all contextual actions
  836. X#
  837. X
  838. X# Run all the contextual actions, each action returning if not needed or if
  839. X# the retry time was not reached. This routine is the main entry point in
  840. X# the package, and is the only one called from the outside world.
  841. Xsub main'contextual_operations {
  842. X    &init;                    # Initialize context
  843. X    &autoclean;                # Clean dbr hash files
  844. X    &save;                    # Save new context
  845. X}
  846. X
  847. Xpackage main;
  848. X
  849. END_OF_FILE
  850.   if test 3363 -ne `wc -c <'agent/pl/context.pl'`; then
  851.     echo shar: \"'agent/pl/context.pl'\" unpacked with wrong size!
  852.   fi
  853.   # end of 'agent/pl/context.pl'
  854. fi
  855. if test -f 'agent/pl/distribs.pl' -a "${1}" != "-c" ; then 
  856.   echo shar: Will not clobber existing file \"'agent/pl/distribs.pl'\"
  857. else
  858.   echo shar: Extracting \"'agent/pl/distribs.pl'\" \(3155 characters\)
  859.   sed "s/^X//" >'agent/pl/distribs.pl' <<'END_OF_FILE'
  860. X;# $Id: distribs.pl,v 2.9 92/07/14 16:49:48 ram Exp $
  861. X;#
  862. X;#  Copyright (c) 1991, Raphael Manfredi
  863. X;#
  864. X;#  You may redistribute only under the terms of the GNU General Public
  865. X;#  Licence as specified in the README file that comes with dist.
  866. X;#
  867. X;# $Log:    distribs.pl,v $
  868. X;# Revision 2.9  92/07/14  16:49:48  ram
  869. X;# 3.0 beta baseline.
  870. X;# 
  871. X;#
  872. X;# This file relies on the following external conditions:
  873. X;#    - operation do fatal() available for fatal errors
  874. X;#    - the configuration variables are properly set
  875. X;#    - logging is done via do add_log()
  876. X;#
  877. X# Read a distribution file and fill in data structures for
  878. X# the query functions. All the data are stored in associative
  879. X# arrays, indexed by the system's name and version number.
  880. X# Associative arrays are:
  881. X#
  882. X# name          indexed by       information
  883. X#
  884. X# %Program      name + version   have we seen that line ?
  885. X# %System       name             is name a valid system ?
  886. X# %Version      name             latest version for system
  887. X# %Location        name + version   location of the distribution
  888. X# %Archived     name + version   is distribution archived ?
  889. X# %Compressed   name + version   is archive compressed ?
  890. X# %Patch_only   name + version   true if only patches delivered
  891. X# %Maintained   name + version   true if distribution is maintained
  892. X# %Patches      name + version   true if official patches available
  893. X#
  894. X# For systems with a version of '---' in the file, the version
  895. X# for accessing the data has to be a null string.
  896. X#
  897. X# Expected format for the distribution file:
  898. X#     system version location archive compress patches
  899. X#
  900. X# The `archive', `compress' and `patches' fields can take one
  901. X# of the following states: "yes" and "no". An additional state
  902. X# for `patches' is "old", which means that only patches are
  903. X# available for the version, and not the distribution. Another is
  904. X# "patch" which means that official patches are available.
  905. X# All these states can be abbreviated with the first letter.
  906. X#
  907. Xsub read_dist {
  908. X    local($fullname);
  909. X    open(DIST, "$cf'distlist") ||
  910. X        do fatal("cannot open distribution file");
  911. X    while (<DIST>) {
  912. X        next if /^\s*#/;    # skip comments
  913. X        next if /^\s*$/;    # skip empty lines
  914. X        next unless s/^\s*(\w+)\s+([.\-0-9]+)//;
  915. X        $fullname = $1 . "|" . ($2 eq '---'? "0" : $2);
  916. X        if (defined($Program{$fullname})) {
  917. X            do add_log("WARNING duplicate distlist entry $1 $2 ignored")
  918. X                if ($loglvl > 5);
  919. X            next;
  920. X        }
  921. X        $Program{$fullname}++;
  922. X        $Version{$1} = ($2 eq '---' ? "0" : $2) unless
  923. X            defined($System{$1}) && $Version{$1} > ($2 eq '---' ? "0":$2);
  924. X        $System{$1}++;
  925. X        unless (/^\s*(\S+)\s+(\w+)\s+(\w+)\s+(\w+)/) {
  926. X            do add_log("WARNING bad system description line $.")
  927. X                if ($loglvl > 5);
  928. X            next;    # Ignore, but it may corrupt further processing
  929. X        }
  930. X        local($location) = $1;
  931. X        local($archive) = $2;
  932. X        local($compress) = $3;
  933. X        local($patch) = $4;
  934. X        $location =~ s/~\//$cf'home\//;        # ~ expansion
  935. X        $Location{$fullname} = $location;
  936. X        $Archived{$fullname}++ if $archive =~ /^y/;
  937. X        $Compressed{$fullname}++ if $compress =~ /^y/;
  938. X        $Patch_only{$fullname}++ if $patch =~ /^o/;
  939. X        $Maintained{$fullname}++ if $patch =~ /^y|o/;
  940. X        $Patches{$fullname}++ if $patch =~ /^p/;
  941. X    }
  942. X    close DIST;
  943. X}
  944. X
  945. END_OF_FILE
  946.   if test 3155 -ne `wc -c <'agent/pl/distribs.pl'`; then
  947.     echo shar: \"'agent/pl/distribs.pl'\" unpacked with wrong size!
  948.   fi
  949.   # end of 'agent/pl/distribs.pl'
  950. fi
  951. if test -f 'agent/pl/mbox.pl' -a "${1}" != "-c" ; then 
  952.   echo shar: Will not clobber existing file \"'agent/pl/mbox.pl'\"
  953. else
  954.   echo shar: Extracting \"'agent/pl/mbox.pl'\" \(2744 characters\)
  955.   sed "s/^X//" >'agent/pl/mbox.pl' <<'END_OF_FILE'
  956. X;# $Id: mbox.pl,v 2.9 92/07/14 16:50:22 ram Exp $
  957. X;#
  958. X;#  Copyright (c) 1992, Raphael Manfredi
  959. X;#
  960. X;#  You may redistribute only under the terms of the GNU General Public
  961. X;#  Licence as specified in the README file that comes with dist.
  962. X;#
  963. X;# $Log:    mbox.pl,v $
  964. X;# Revision 2.9  92/07/14  16:50:22  ram
  965. X;# 3.0 beta baseline.
  966. X;# 
  967. X;# 
  968. X;# This package enables the mailagent to incorporate mail from a UNIX-style
  969. X;# mailbox (i.e. those produced by standard mail utilities with a leading From
  970. X;# line stating sender and date) into the mailagent's queue. This will be
  971. X;# especially useful on those sites where users are not allowed to have a
  972. X;# .forward file. By using the -f option on the mailbox in /usr/spool/mail,
  973. X;# mail will be queued and filtered as if it had come from filter via .forward.
  974. Xpackage mbox;
  975. X
  976. X# Get mail from UNIX mailbox and queue each item
  977. Xsub main'mbox_mail {
  978. X    local($mbox) = @_;            # Where mail is stored
  979. X    unless (open(MBOX, "$mbox")) {
  980. X        &'add_log("ERROR cannot open $mbox: $!") if $'loglvl > 1;
  981. X        return -1;                # Failed
  982. X    }
  983. X    local(@buffer);                # Buffer used for look-ahead
  984. X    local(@blanks);                # Trailing blank lines are ignored
  985. X    local(@mail);                # Where mail is stored
  986. X    while (<MBOX>) {
  987. X        chop;
  988. X        if (/^\s*$/ && 0 == @buffer) {
  989. X            push(@blanks, $_);
  990. X            next;                # Remove empty lines before end of mail
  991. X        }
  992. X        if (/^From\s/) {
  993. X            push(@buffer, $_);
  994. X            next;
  995. X        }
  996. X        if (@buffer > 0) {
  997. X            if (/^$/) {
  998. X                &flush(1);        # End of header
  999. X                push(@mail, $_);
  1000. X                next;
  1001. X            }
  1002. X            if (/^[\w\-]+:/) {
  1003. X                $last_was_header = 1;
  1004. X                push(@buffer, $_);
  1005. X                next;
  1006. X            }
  1007. X            if (/^\s/ && $last_was_header) {
  1008. X                push(@buffer, $_);
  1009. X                next;
  1010. X            }
  1011. X            &flush(0);            # Not a header
  1012. X            push(@mail, $_);
  1013. X            next;
  1014. X        }
  1015. X        &flush_blanks;
  1016. X        push(@mail, $_);
  1017. X    }
  1018. X    close MBOX;
  1019. X    &flush(1);            # Flush mail buffer at end of file
  1020. X    &flush_buffer;        # Maybe header was incomplete?
  1021. X    &'add_log("WARNING incomplete last mail discarded")
  1022. X        if $'loglvl > 5 && @mail > 0;
  1023. X    0;                    # Ok (but there might have been some queue problems)
  1024. X}
  1025. X
  1026. X# Flush blanks into @mail
  1027. Xsub flush_blanks {
  1028. X    return unless @blanks;
  1029. X    foreach $blank (@blanks) {
  1030. X        push(@mail, $blank);
  1031. X    }
  1032. X    @blanks = ();
  1033. X}
  1034. X
  1035. X# Flush look-ahead buffer into @mail
  1036. Xsub flush_buffer {
  1037. X    return unless @buffer;
  1038. X    foreach $buffer (@buffer) {
  1039. X        push(@mail, $buffer);
  1040. X    }
  1041. X    @buffer = ();
  1042. X}
  1043. X
  1044. X# Flush mail buffer onto queue
  1045. Xsub flush {
  1046. X    local($was_header) = @_;    # Did we reach a new header
  1047. X    # NB: we don't have to worry if the very first mail does not have a From
  1048. X    # line, as qmail will add a faked one if necessary.
  1049. X    if ($was_header && @mail > 0) {
  1050. X        &main'qmail(*mail);
  1051. X        @mail = ();                # Reset mail buffer
  1052. X    }
  1053. X    &flush_buffer;                # Fill @mail with what we got so far in @buffer
  1054. X    @blanks = ();                # Discard trailing blanks
  1055. X}
  1056. X
  1057. Xpackage main;
  1058. X
  1059. END_OF_FILE
  1060.   if test 2744 -ne `wc -c <'agent/pl/mbox.pl'`; then
  1061.     echo shar: \"'agent/pl/mbox.pl'\" unpacked with wrong size!
  1062.   fi
  1063.   # end of 'agent/pl/mbox.pl'
  1064. fi
  1065. if test -f 'agent/pl/plsave.pl' -a "${1}" != "-c" ; then 
  1066.   echo shar: Will not clobber existing file \"'agent/pl/plsave.pl'\"
  1067. else
  1068.   echo shar: Extracting \"'agent/pl/plsave.pl'\" \(3784 characters\)
  1069.   sed "s/^X//" >'agent/pl/plsave.pl' <<'END_OF_FILE'
  1070. X;# $Id: plsave.pl,v 2.9 92/07/14 16:50:29 ram Exp $
  1071. X;#
  1072. X;#  Copyright (c) 1991, Raphael Manfredi
  1073. X;#
  1074. X;#  You may redistribute only under the terms of the GNU General Public
  1075. X;#  Licence as specified in the README file that comes with dist.
  1076. X;#
  1077. X;# $Log:    plsave.pl,v $
  1078. X;# Revision 2.9  92/07/14  16:50:29  ram
  1079. X;# 3.0 beta baseline.
  1080. X;# 
  1081. X;#
  1082. X;# This file relies on the following external conditions:
  1083. X;#    - operation do fatal() available for fatal errors
  1084. X;#    - the configuration variables are properly set
  1085. X;#    - logging is done via do add_log()
  1086. X;#    - routines for locking files are available
  1087. X;#
  1088. X# Read stored informations for archived systems. The format of
  1089. X# the file is the following:
  1090. X#    system version patchlevel mtime
  1091. X# where:
  1092. X#    - system is the name of the system
  1093. X#    - version is the version number or --- if none
  1094. X#    - patchlevel is the current patchlevel, or -2 if no PL
  1095. X#    - mtime is the modification time of the archive
  1096. X#
  1097. X# The function builds the following associative array, indexed
  1098. X# by the system's name and version number (which has to be a null
  1099. X# string for systems with no version number, marked '---'):
  1100. X#
  1101. X# name          indexed by       information
  1102. X#
  1103. X# %PSystem      name + version   true if line seen
  1104. X# %Patch_level  name + version   current patch level
  1105. X# %Mtime        name + version   last modification time
  1106. X#
  1107. X# If the 'plsave' file is not found, a new empty one is created
  1108. X#
  1109. Xsub read_plsave {
  1110. X    local($fullname);
  1111. X    if (!open(PATLIST, "$cf'plsave")) {
  1112. X        do add_log("creating new patlist file") if ($loglvl > 8);
  1113. X        system 'cp', '/dev/null', $cf'plsave;
  1114. X        open(PATLIST, "$cf'plsave") ||
  1115. X            do fatal("cannot open patlist file");
  1116. X    }
  1117. X    while (<PATLIST>) {
  1118. X        next if /^\s*#/;    # skip comments
  1119. X        next if /^\s*$/;    # skip empty lines
  1120. X        next unless s/^\s*(\w+)\s+([\w\.]+)//;
  1121. X        $fullname = $1 . "|" . ($2 eq '---'? "0" : $2);
  1122. X        if (defined($PSystem{$fullname})) {
  1123. X            do add_log("WARNING duplicate patlist entry $1 $2 ignored")
  1124. X                if ($loglvl > 5);
  1125. X            next;
  1126. X        }
  1127. X        $PSystem{$fullname}++;
  1128. X        unless (/^\s*([\-\d]+)\s+(\d+)/) {
  1129. X            do add_log("WARNING bad patlist description line $.")
  1130. X                if ($loglvl > 5);
  1131. X            next;    # Ignore, but it may corrupt further processing
  1132. X        }
  1133. X        $Patch_level{$fullname} = $1;
  1134. X        $Mtime{$fullname} = $2;
  1135. X    }
  1136. X    close PATLIST;
  1137. X}
  1138. X
  1139. X# Write the new 'plsave', but only if the distributions are found
  1140. X# in the %Program array (I assume read_dist() has been called).
  1141. X# The 'plsave' file is locked during the updating process, so that
  1142. X# no conflicting access occurs. There is a small chance that the
  1143. X# file we write is not correct, in case the distribution file changed
  1144. X# while we were processing a mail. However, it isn't a big problem.
  1145. Xsub write_plsave {
  1146. X    local($lockext) = ".lock";        # Needed by checklock
  1147. X    local($system);
  1148. X    local($version);
  1149. X    do checklock($cf'plsave);        # Make sure no old lock lasts
  1150. X    if (0 != &acs_rqst($cf'plsave)) {
  1151. X        do add_log("WARNING updating unlocked patlist file")
  1152. X            if ($loglvl > 5);
  1153. X    }
  1154. X    if (!open(PATLIST, ">$cf'plsave")) {
  1155. X        do add_log("ERROR unable to update $cf'plsave") if ($loglvl > 0);
  1156. X        return;
  1157. X    }
  1158. X    print PATLIST
  1159. X"# This file was automatically generated by $prog_name.
  1160. X# It records the archived distributions, their patch level if any, and
  1161. X# the modification time of the archive, so that these informations can
  1162. X# be updated when necessary. Do not edit this file.
  1163. X
  1164. X";
  1165. X    foreach $pname (keys %PSystem) {
  1166. X        if ($Archived{$pname}) {
  1167. X            ($system, $version) = $pname =~ /^(\w+)\|([\w\.]+)*$/;
  1168. X            $version = '---' if $version eq '0';
  1169. X            print PATLIST "$system $version ";
  1170. X            print PATLIST "$Patch_level{$pname} $Mtime{$pname}\n";
  1171. X            do add_log("updated patlist for $system $version")
  1172. X                if ($log_lvl > 18);
  1173. X        } else {
  1174. X            do add_log("$system $version removed from patlist")
  1175. X                if ($log_lvl > 18);
  1176. X        }
  1177. X    }
  1178. X    close PATLIST;
  1179. X    do free_file($cf'plsave);
  1180. X}
  1181. X
  1182. END_OF_FILE
  1183.   if test 3784 -ne `wc -c <'agent/pl/plsave.pl'`; then
  1184.     echo shar: \"'agent/pl/plsave.pl'\" unpacked with wrong size!
  1185.   fi
  1186.   # end of 'agent/pl/plsave.pl'
  1187. fi
  1188. if test -f 'agent/pl/pqueue.pl' -a "${1}" != "-c" ; then 
  1189.   echo shar: Will not clobber existing file \"'agent/pl/pqueue.pl'\"
  1190. else
  1191.   echo shar: Extracting \"'agent/pl/pqueue.pl'\" \(2659 characters\)
  1192.   sed "s/^X//" >'agent/pl/pqueue.pl' <<'END_OF_FILE'
  1193. X;# $Id: pqueue.pl,v 2.9 92/07/14 16:50:32 ram Exp $
  1194. X;#
  1195. X;#  Copyright (c) 1992, Raphael Manfredi
  1196. X;#
  1197. X;#  You may redistribute only under the terms of the GNU General Public
  1198. X;#  Licence as specified in the README file that comes with dist.
  1199. X;#
  1200. X;# $Log:    pqueue.pl,v $
  1201. X;# Revision 2.9  92/07/14  16:50:32  ram
  1202. X;# 3.0 beta baseline.
  1203. X;# 
  1204. X;# 
  1205. X# Process the queue
  1206. Xsub pqueue {
  1207. X    local($length);                        # Length of message, in bytes
  1208. X    undef %waiting;                        # Reset waiting array
  1209. X    local(@files) = <$cf'queue/fm*>;
  1210. X    # The qm files are put there by the filter and left in case of error
  1211. X    # Only files older than 30 minutes are re-parsed (because otherwise it
  1212. X    # might have just been queued by the filter).
  1213. X    local(@filter_files) = <$cf'queue/qm*>;
  1214. X    foreach $file (@filter_files) {
  1215. X        ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
  1216. X            $atime,$mtime,$ctime,$blksize,$blocks) = stat($file);
  1217. X        if ((time - $mtime) > 1800) {
  1218. X            # More than 30 minutes -- there must have been a failure
  1219. X            push(@files, $file);        # Add file to the to-be-parsed list
  1220. X        }
  1221. X    }
  1222. X    # In $agent_wait are stored the names of the mails outside the queue
  1223. X    # directory, waiting to be processed.
  1224. X    if (-f "$cf'queue/$agent_wait") {
  1225. X        if (open(WAITING, "$cf'queue/$agent_wait")) {
  1226. X            while (<WAITING>) {
  1227. X                chop;
  1228. X                push(@files, $_);        # Process this file too
  1229. X                $waiting{$_} = 1;        # Record it comes from waiting file
  1230. X            }
  1231. X            close WAITING;
  1232. X        } else {
  1233. X            &add_log("ERROR cannot open $cf'queue/$agent_wait: $!") if $loglvl;
  1234. X        }
  1235. X    }
  1236. X    return 0 unless $#files >= 0;
  1237. X    do add_log("processing the whole queue") if $loglvl > 11;
  1238. X    $processed = 0;
  1239. X    foreach $file (@files) {
  1240. X        do add_log("dealing with $file") if $loglvl > 19;
  1241. X        $file_name = $file;
  1242. X        if ($waiting{$file} && ! -f "$file") {
  1243. X            # We may have already processed this file without having resynced
  1244. X            # agent_wait or the file has been removed.
  1245. X            do add_log ("WARNING could not find $file") if $loglvl > 4;
  1246. X            $waiting{$file} = 0;    # Mark it as processed
  1247. X            next;                    # And skip it
  1248. X        }
  1249. X        if (0 == &analyze_mail($file_name)) {
  1250. X            unlink $file;
  1251. X            ++$processed;
  1252. X            $waiting{$file} = 0 if $waiting{$file};
  1253. X            $file =~ s|.*/(.*)|$1|;    # Keep only basename
  1254. X            $length = $Header{'Length'};
  1255. X            do add_log("FILTERED [$file] $length bytes") if $loglvl > 4;
  1256. X        } else {
  1257. X            $file =~ s|.*/(.*)|$1|;    # Keep only basename
  1258. X            do add_log("ERROR leaving [$file] in queue") if $loglvl > 0;
  1259. X            unlink $lockfile;
  1260. X            do resync();            # Resynchronize waiting file
  1261. X            exit 0;                    # Do not continue now
  1262. X        }
  1263. X    }
  1264. X    if ($processed == 0) {
  1265. X        do add_log("was unable to process queue") if ($loglvl > 5);
  1266. X    }
  1267. X    do resync();        # Resynchronize waiting file
  1268. X    $processed;            # Return the number of files processed
  1269. X}
  1270. X
  1271. END_OF_FILE
  1272.   if test 2659 -ne `wc -c <'agent/pl/pqueue.pl'`; then
  1273.     echo shar: \"'agent/pl/pqueue.pl'\" unpacked with wrong size!
  1274.   fi
  1275.   # end of 'agent/pl/pqueue.pl'
  1276. fi
  1277. if test -f 'agent/test/Makefile.SH' -a "${1}" != "-c" ; then 
  1278.   echo shar: Will not clobber existing file \"'agent/test/Makefile.SH'\"
  1279. else
  1280.   echo shar: Extracting \"'agent/test/Makefile.SH'\" \(3462 characters\)
  1281.   sed "s/^X//" >'agent/test/Makefile.SH' <<'END_OF_FILE'
  1282. X: Makefile.SH generated from Jmake.tmpl and Jmakefile [jmake 2.8 PL13]
  1283. X: $X-Id: Jmake.tmpl,v 2.8.1.2 91/11/18 13:22:54 ram Exp $
  1284. X
  1285. Xcase $CONFIG in
  1286. X'')
  1287. X    if test ! -f config.sh; then
  1288. X        ln ../config.sh . || \
  1289. X        ln ../../config.sh . || \
  1290. X        ln ../../../config.sh . || \
  1291. X        (echo "Can't find config.sh."; exit 1)
  1292. X    fi 2>/dev/null
  1293. X    . ./config.sh
  1294. X    ;;
  1295. Xesac
  1296. Xcase "$0" in
  1297. X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
  1298. Xesac
  1299. XCURRENT=agent/test
  1300. XDIR=`echo $CURRENT/ | sed -e 's/\.\///g'`
  1301. Xecho "Extracting ${DIR}Makefile (with variable substitutions)"
  1302. XDATE=`date`
  1303. X$spitshell >Makefile <<!GROK!THIS!
  1304. X########################################################################
  1305. X# Makefile generated from Makefile.SH on $DATE
  1306. X
  1307. XSHELL = /bin/sh
  1308. XJMAKE = jmake
  1309. XTOP = ../..
  1310. XCURRENT = $CURRENT
  1311. XDIR = $DIR
  1312. X
  1313. X########################################################################
  1314. X# Parameters set by Configure -- edit config.sh if changes are needed
  1315. X
  1316. XCTAGS = ctags
  1317. XMAKE = make
  1318. XMV = $mv
  1319. XRM = $rm -f
  1320. X
  1321. X!GROK!THIS!
  1322. X$spitshell >>Makefile <<'!NO!SUBS!'
  1323. X
  1324. X########################################################################
  1325. X# Jmake rules for building libraries, programs, scripts, and data files
  1326. X# $X-Id: Jmake.rules,v 2.8.1.4 91/11/18 13:19:07 ram Exp $
  1327. X
  1328. X########################################################################
  1329. X# Start of Jmakefile
  1330. X
  1331. X# $X-Id: Jmakefile,v 2.9 92/07/14 16:50:57 ram Exp $
  1332. X#
  1333. X#  Copyright (c) 1991, Raphael Manfredi
  1334. X#
  1335. X#  You may redistribute only under the terms of the GNU General Public
  1336. X#  Licence as specified in the README file that comes with dist.
  1337. X#
  1338. X# $X-Log:    Jmakefile,v $
  1339. X# Revision 2.9  92/07/14  16:50:57  ram
  1340. X# 3.0 beta baseline.
  1341. X#
  1342. X#
  1343. X
  1344. Xall::
  1345. X    @echo "The following may take a while..."
  1346. X    @echo "Don't panic if any of these tests fails and do not stop make."; \
  1347. X    ./TEST
  1348. X    @if test -f OK; then \
  1349. X        echo "Failure detected, retrying one more time, just in case..."; \
  1350. X        echo "Successful tests will not be rerun but flagged as 'done'."; \
  1351. X        sleep 2; \
  1352. X        ./TEST; \
  1353. X        if test -f OK; then \
  1354. X            echo "Hmm... Still failed... There might be a real problem."; \
  1355. X            echo "I shall be using the plain (non dataloaded) version."; \
  1356. X            sleep 2;\
  1357. X            ./TEST -n; \
  1358. X        fi \
  1359. X    fi
  1360. X
  1361. Xtest:
  1362. X    ./TEST -i
  1363. X
  1364. Xlocal_clean::
  1365. X    $(RM) -r out
  1366. X    $(RM) OK
  1367. X
  1368. X########################################################################
  1369. X# Common rules for all Makefiles -- do not edit
  1370. X
  1371. Xemptyrule::
  1372. X
  1373. Xclean: local_clean
  1374. Xrealclean: local_realclean
  1375. Xclobber: local_clobber
  1376. X
  1377. Xlocal_clean::
  1378. X    $(RM) core *~ *.o
  1379. X
  1380. Xlocal_realclean:: local_clean
  1381. X
  1382. Xlocal_clobber:: local_realclean
  1383. X    $(RM) Makefile config.sh
  1384. X
  1385. XMakefile.SH: Jmakefile
  1386. X    -@if test -f $(TOP)/.package; then \
  1387. X        if test -f Makefile.SH; then \
  1388. X            echo "    $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~"; \
  1389. X            $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~; \
  1390. X        fi; \
  1391. X        echo "    $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT)" ; \
  1392. X        $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT) ; \
  1393. X    else touch $@; exit 0; fi
  1394. X
  1395. XMakefile: Makefile.SH
  1396. X    /bin/sh Makefile.SH
  1397. X
  1398. Xtags::
  1399. X    $(CTAGS) -w *.[ch]
  1400. X    $(CTAGS) -xw *.[ch] > tags
  1401. X
  1402. Xlocal_clobber::
  1403. X    $(RM) tags
  1404. X
  1405. X########################################################################
  1406. X# Empty rules for directories with no sub-directories -- do not edit
  1407. X
  1408. Xinstall::
  1409. X    @echo "install in $(CURRENT) done."
  1410. X
  1411. Xdeinstall::
  1412. X    @echo "deinstall in $(CURRENT) done."
  1413. X
  1414. Xinstall.man::
  1415. X    @echo "install.man in $(CURRENT) done."
  1416. X
  1417. Xdeinstall.man::
  1418. X    @echo "deinstall.man in $(CURRENT) done."
  1419. X
  1420. XMakefiles::
  1421. X
  1422. XMakefiles.SH::
  1423. X
  1424. X!NO!SUBS!
  1425. Xchmod 644 Makefile
  1426. X$eunicefix Makefile
  1427. X
  1428. END_OF_FILE
  1429.   if test 3462 -ne `wc -c <'agent/test/Makefile.SH'`; then
  1430.     echo shar: \"'agent/test/Makefile.SH'\" unpacked with wrong size!
  1431.   fi
  1432.   # end of 'agent/test/Makefile.SH'
  1433. fi
  1434. if test -f 'agent/test/README' -a "${1}" != "-c" ; then 
  1435.   echo shar: Will not clobber existing file \"'agent/test/README'\"
  1436. else
  1437.   echo shar: Extracting \"'agent/test/README'\" \(3329 characters\)
  1438.   sed "s/^X//" >'agent/test/README' <<'END_OF_FILE'
  1439. XThis is the root directory for the regression test suite.
  1440. X
  1441. XThe single TEST executable will run the test suite and report any failure.
  1442. XAlthough not every feature of the mailagent is tested, having it pass
  1443. Xthe whole test suite is a Good Thing. Some commands like PROCESS or POST
  1444. Xare not easy to test automatically, but if you can design good tests
  1445. Xfor them, I will be glad to include them.
  1446. X
  1447. XThis set of programs were written quickly, as effeciency or maintainability
  1448. Xwas not the main issue, obviously. I believe they are reasonably well
  1449. Xwritten, making it possible for someone to be able to understand and modify
  1450. Xthem.
  1451. X
  1452. XRunning the whole test suite takes a long time. On my machine with 40 Mb of
  1453. Xmain memory, it requires 12 minutes to complete. It may take a lot longer
  1454. Xif you do not have at least 16 Mb of RAM.
  1455. X
  1456. XThe option -i turns the incremental mode on. This proved really nice to
  1457. Xme when I was writing this suite, as I was able to skip all the successful
  1458. Xtests and focus only on those which failed or the new ones. The -s option will
  1459. Xcause the test suite to stop at the first error. Normally, only failed basic
  1460. Xtests abort the process. The -o option will not restart the tests from scratch,
  1461. Xeven if the mailagent or filter is newer than the current OK file. Option -n
  1462. Xwill test the non-dataloaded version of the mailagent (because of some bugs
  1463. Xwith eval() which cause the dataloaded version to dump core via a segmentation
  1464. Xviolation).
  1465. X
  1466. XI don't know why I spent some time documenting all this, as I don't expect
  1467. Xanybody to have any chance working on this suite. Anyway, it might be nice
  1468. Xknowing that all the successful tests are recorded in an OK file, along
  1469. Xwith the time stamp of the test, so we may re-run those which were updated
  1470. Xsince last run. In the event the mailagent or the filter are modified, the
  1471. Xtests are re-run throughoutfully.
  1472. X
  1473. XThe file 'level' is optional. If present, it gives the default logging level
  1474. Xto be applied when most of the tests are run (i.e. for those who do not require
  1475. Xany special logging level). If absent, no logging will be done (except for
  1476. Xthose tests who do require... etc...). All the tests are performed in the
  1477. X'out' subdirectory, with the user name set to 'nobody'. That may help a lot
  1478. Xwhen testing commands like RUN, as they have the nasty habbit to mail you, the
  1479. Xuser, their output when they fail for whatever reason.
  1480. X
  1481. XThe generic mail used by the test is an automatic answer I got from the
  1482. Xcomp.compilers newsgroup moderator the day I posted my first article to that
  1483. Xgroup. It has no special value, appart from having some constants relative
  1484. Xto it hardwired within the tests themselves. Don't touch it, even to remove
  1485. Xa white space or some tests may fail (particularily GIVE and PIPE, which have
  1486. Xthe output of 'wc' hardwired). On my machine, here is the output of 'wc mail':
  1487. X
  1488. X     34     227    1620  mail
  1489. X
  1490. XIn the event some of the tests do not pass, there is no reason to panic, and
  1491. Xit doesn't necesseratily mean the mailagent has a bug. It is more likely a
  1492. Xcombinaison of perl + dataloading + bugs + memory + moon's position. Try
  1493. Xto run the test suite again, and then one more time. It sometimes helps.
  1494. XAlso try changing the logging level via 'level' to see if it doesn't make
  1495. Xany difference. This is not really rational, but empirical law :-).
  1496. X
  1497. XI think that's all there is to say.
  1498. END_OF_FILE
  1499.   if test 3329 -ne `wc -c <'agent/test/README'`; then
  1500.     echo shar: \"'agent/test/README'\" unpacked with wrong size!
  1501.   fi
  1502.   # end of 'agent/test/README'
  1503. fi
  1504. if test -f 'agent/test/rules' -a "${1}" != "-c" ; then 
  1505.   echo shar: Will not clobber existing file \"'agent/test/rules'\"
  1506. else
  1507.   echo shar: Extracting \"'agent/test/rules'\" \(2993 characters\)
  1508.   sed "s/^X//" >'agent/test/rules' <<'END_OF_FILE'
  1509. Xmaildir = ~;
  1510. Xmailfilter = ~;
  1511. X
  1512. XSubject: /test/        { DELETE };
  1513. X
  1514. X# filter/default
  1515. XX-Tag: /default #1/ { DELETE };
  1516. XX-Tag: /default #2/ { NOP };
  1517. XX-Tag: /unknown/     { UNKNOWN };
  1518. X
  1519. X# filter/loop
  1520. XX-Tag: /loop #1/            { BEGIN LOOP; RESTART };
  1521. XX-Tag: /loop #2/            { DELETE };
  1522. X
  1523. X# filter/multiple
  1524. XX-None Subject To X-Tag: /multiple #1/            { SAVE %u.1 };
  1525. XX-None X-Tag: /multiple #2/, X-Other: /another/,
  1526. XTo Cc: root, Cc To: ram                            { SAVE %u.3; REJECT MULTIPLE };
  1527. X<MULTIPLE> X-Non-Existent: *                    { SAVE %u.2 };
  1528. XX-Tag: /multiple #2/, X-Other: /multiple #2/    { SAVE %u.2 };
  1529. X
  1530. X# filter/list
  1531. XX-Tag: /list/                    { BEGIN LIST; REJECT };
  1532. X<LIST> To: ram                    { SAVE %u.1 };
  1533. X<LIST> To: max                    { SAVE %u.2 };
  1534. X<LIST> To: /^root@eiffel.com$/    { SAVE %u.3 };
  1535. X<LIST> To: /^riot@eiffel.co$/    { DELETE };
  1536. X<LIST> To: /^riot@eiffel.com$/    { SAVE %u.4 };
  1537. X<LIST> To: /^riot/                { SAVE %u.5 };
  1538. X<LIST> To: /riot/                { SAVE %u.6 };
  1539. X<LIST> Newsgroups: news.lists    { SAVE %u.7 };
  1540. X<LIST> To: !ram                    { SAVE %u.8 };
  1541. X
  1542. X# filter/pattern
  1543. XX-T.*: "pattern-list"            { BEGIN PAT; REJECT };
  1544. X<PAT> .*Re[^\-]*$: *, ^Sub*: *    { RUN /bin/echo '%&' > macro; DELETE };
  1545. X
  1546. X# filter/backref
  1547. XX-Tag: /^back(.*) #1/,
  1548. XSubject: /Re:\s+(\w+)\s+ice\s+(\w+)/,
  1549. XFrom: /(.*)compilers/,
  1550. XFrom: /com(.*)rs/,
  1551. XTo: /^(\w+)@(\S+)/        { RUN /bin/echo '%1,%4,%5@%6,%2 %3' > output; DELETE };
  1552. X
  1553. XX-Tag: /^back.* #2/,
  1554. XNewsgroups:
  1555. X    /(comp.lang.perl)/,
  1556. X    /(comp.unix.wizards)/,
  1557. X    /(comp.mail.mh)/    { SAVE %1 };
  1558. X
  1559. X# filter/escape
  1560. XX-Tag: /escape/            { RUN /bin/echo '\;,\\\;,\\,\w' > output; DELETE };
  1561. X
  1562. X# filter/not
  1563. XX-Tag: /not #1/            { BEGIN NOT; REJECT };
  1564. X<NOT> To: !ram            { SAVE never };
  1565. X<NOT> To: !/ram@eiffel/    { SAVE never };
  1566. X<NOT> To: !/^ram/i        { SAVE never };
  1567. X<NOT> To: /^ram/i                { SAVE always; REJECT };
  1568. X<NOT> To: !/^root/i                { SAVE always.2; REJECT };
  1569. X<NOT> X-Tag: !"pattern-list"    { SAVE always.3 };
  1570. X
  1571. XX-Tag: /not #2/,
  1572. X!To: !ram,
  1573. XTo: !compilers,
  1574. X!From: root                { SAVE always };
  1575. X
  1576. X# filter/group
  1577. XX-Tag: /group/            { BEGIN GROUP; REJECT };
  1578. X<GROUP> !To !From: ram    { SAVE never };
  1579. X<GROUP> To !From: !ram    { SAVE never };
  1580. X<GROUP> !To !From: ram,
  1581. X    !Subject !From: ram        { SAVE never };
  1582. X<GROUP> !To: root, ram        { SAVE never };
  1583. X<GROUP> !F.*: /compiler/    { SAVE never };
  1584. X<GROUP> !From: ram, !To: ram    { SAVE always; REJECT };
  1585. X<GROUP> From: ram, To: ram        { SAVE never };
  1586. X<GROUP> From: /compiler/,
  1587. X    !From: ram, !From: !/compiler/    { SAVE always.2; REJECT };
  1588. X<GROUP> From !Cc !To: /compiler/,
  1589. X    From !Cc !To: ram,
  1590. X    !From To Cc: /eiffel/,
  1591. X    !From To Cc: !/ice/            { SAVE always.3 };
  1592. X
  1593. X# filter/case
  1594. XX-Tag: case, Cc: root    { STRIP Cc; SAVE always };
  1595. X
  1596. X# filter/status
  1597. XX-Tag: /status/    { REJECT -t STATUS };
  1598. X<STATUS> { RUN ../no/such/file; REJECT -t; SAVE always; REJECT -t; SAVE never };
  1599. X<STATUS> { RUN ../this/does/not/exist; REJECT -f; SAVE never };
  1600. X<STATUS> { RUN ../nor/does/this; REJECT -t; REJECT -t; REJECT -f; SAVE never };
  1601. X<STATUS> { SAVE always.2; REJECT -f; BEGIN INITIAL; REJECT -t };
  1602. X<INITIAL> X-Tag: /status/    { SAVE always.3 };
  1603. X
  1604. X# filter/hook
  1605. XX-Tag: /hook #(\d)/        { SAVE hook.%1; ABORT -t; SAVE never };
  1606. X
  1607. END_OF_FILE
  1608.   if test 2993 -ne `wc -c <'agent/test/rules'`; then
  1609.     echo shar: \"'agent/test/rules'\" unpacked with wrong size!
  1610.   fi
  1611.   # end of 'agent/test/rules'
  1612. fi
  1613. if test -f 'install.SH' -a "${1}" != "-c" ; then 
  1614.   echo shar: Will not clobber existing file \"'install.SH'\"
  1615. else
  1616.   echo shar: Extracting \"'install.SH'\" \(3632 characters\)
  1617.   sed "s/^X//" >'install.SH' <<'END_OF_FILE'
  1618. Xcase $CONFIG in
  1619. X'')
  1620. X    if test ! -f config.sh; then
  1621. X        ln ../config.sh . || \
  1622. X        ln ../../config.sh . || \
  1623. X        ln ../../../config.sh . || \
  1624. X        (echo "Can't find config.sh."; exit 1)
  1625. X    fi 2>/dev/null
  1626. X    . config.sh
  1627. X    ;;
  1628. Xesac
  1629. Xcase "$0" in
  1630. X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
  1631. Xesac
  1632. Xecho "Extracting install (with variable substitutions)"
  1633. X$spitshell >install <<!GROK!THIS!
  1634. X$startsh
  1635. X# @(#) Installing script accepting bsd-style arguments
  1636. X
  1637. X# $Id: install.SH,v 2.9 92/07/14 16:53:45 ram Exp $
  1638. X#
  1639. X#  Copyright (c) 1991, Raphael Manfredi
  1640. X#
  1641. X#  You may redistribute only under the terms of the GNU General Public
  1642. X#  Licence as specified in the README file that comes with dist.
  1643. X#
  1644. X# $Log:    install.SH,v $
  1645. X# Revision 2.9  92/07/14  16:53:45  ram
  1646. X# 3.0 beta baseline.
  1647. X# 
  1648. X
  1649. Xchown='$chown'
  1650. Xchmod='$chmod'
  1651. Xchgrp='$chgrp'
  1652. Xrm='$rm'
  1653. Xmv='$mv'
  1654. Xtest='$test'
  1655. Xsed='$sed'
  1656. X!GROK!THIS!
  1657. X$spitshell >>install <<'!NO!SUBS!'
  1658. X
  1659. Xmode=""
  1660. Xdst=""
  1661. Xsrc=""
  1662. Xdostrip=""
  1663. Xnewdir=""
  1664. Xuid=""
  1665. Xgid=""
  1666. X
  1667. X# simulates mkdir -p
  1668. Xmkdir_p='
  1669. Xname=$1;
  1670. Xcreate="";
  1671. Xwhile $test $name; do
  1672. X    if $test ! -d "$name"; then
  1673. X        create="$name $create";
  1674. X        name=`echo $name | $sed -e "s|^[^/]*$||"`;
  1675. X        name=`echo $name | $sed -e "s|\(.*\)/.*|\1|"`;
  1676. X    else
  1677. X        name="";
  1678. X    fi;
  1679. Xdone;
  1680. Xfor file in $create; do
  1681. X    mkdir $file && $test $verbose &&
  1682. X    echo "install: created directory $file" >&2;
  1683. Xdone
  1684. X'
  1685. X
  1686. Xverbose=''
  1687. X
  1688. Xwhile $test x$1 != x
  1689. Xdo
  1690. X    case $1 in 
  1691. X    -c) shift
  1692. X        continue
  1693. X        ;;
  1694. X    -m) mode="$2 "
  1695. X        shift
  1696. X        shift
  1697. X        continue
  1698. X        ;;
  1699. X    -o) uid="$2 "
  1700. X        shift
  1701. X        shift
  1702. X        continue
  1703. X        ;;
  1704. X    -g) gid="$2 "
  1705. X        shift
  1706. X        shift
  1707. X        continue
  1708. X        ;;
  1709. X    -s) dostrip="strip"
  1710. X        shift
  1711. X        continue
  1712. X        ;;
  1713. X    -d) newdir="$newdir$2 "
  1714. X        shift
  1715. X        shift
  1716. X        continue
  1717. X        ;;
  1718. X    -v) verbose='true'
  1719. X        shift
  1720. X        ;;
  1721. X    *) if $test x$src = x
  1722. X        then
  1723. X            src=$1
  1724. X        else
  1725. X            dst=$1
  1726. X        fi
  1727. X        shift
  1728. X        continue
  1729. X        ;;
  1730. X    esac
  1731. Xdone
  1732. X
  1733. X# if -d option is used, we have to create the path given
  1734. Xif $test ! x$newdir = x
  1735. Xthen
  1736. X    for i in $newdir
  1737. X    do
  1738. X        set x $i
  1739. X        shift
  1740. X        eval $mkdir_p
  1741. X    done
  1742. X    exit 0        # -d is the only action
  1743. Xfi
  1744. X
  1745. Xif $test x$src = x
  1746. Xthen
  1747. X    echo "install: no input file specified" >&2
  1748. X    exit 1
  1749. Xfi
  1750. X
  1751. Xif $test x$dst = x
  1752. Xthen
  1753. X    echo "install: no destination specified" >&2
  1754. X    exit 1
  1755. Xfi
  1756. X
  1757. Xsrcbase=`basename $src`
  1758. Xdstbase=`basename $dst`
  1759. X
  1760. X# If the destination is a directory, the target name is srcbase...
  1761. Xif $test -d $dst; then
  1762. X    dstbase=$srcbase
  1763. Xelse
  1764. X    dst="`echo $dst | sed 's,^\(.*\)/.*$,\1,'`"
  1765. X    if $test ! -d $dst; then
  1766. X        dstbase=$dst
  1767. X        dst="."
  1768. X    fi
  1769. Xfi
  1770. X
  1771. X# If the src has a directory, extract the dir name...
  1772. Xif $test "$src" != "$srcbase" -a "$src" != "./$srcbase"; then
  1773. X    src="`echo $src | sed 's,^\(.*\)/.*$,\1,'`"
  1774. Xelse
  1775. X    src="."
  1776. Xfi
  1777. X
  1778. X# dst is the destination directory and dstbase the base name.
  1779. X# srcbase is the base name of source and src the source dir.
  1780. X
  1781. Xsrcpth=`(cd $src; pwd)`/$srcbase
  1782. Xdestpth=`(cd $dst; pwd)`/$dstbase
  1783. Xif $test x$srcpth = x$destpth; then
  1784. X    $test $verbose && \
  1785. X    echo "install: destination and source are identical"
  1786. X    exit 0
  1787. Xfi
  1788. X
  1789. X# Do the install
  1790. X(
  1791. X    cd $src
  1792. X
  1793. X    if $test -f $dst/$dstbase; then
  1794. X        $rm -f $dst/$dstbase && $test $verbose &&
  1795. X        echo "install: $dst/$dstbase removed"
  1796. X    fi
  1797. X    if $test -f $dst/$dstbase; then
  1798. X        $mv $dst/$dstbase $dst/OLD$dstbase && $test $verbose &&
  1799. X        echo "install: $dst/$dstbase renamed as OLD$dstbase"
  1800. X    fi
  1801. X
  1802. X    cp $srcbase $dst/$dstbase && $test $verbose &&
  1803. X    echo "install: $srcbase installed as $dst/$dstbase"
  1804. X
  1805. X    if $test ! x$dostrip = x; then
  1806. X        strip $dst/$dstbase 2>/dev/null && $test $verbose &&
  1807. X        echo "install: stripped $dst/$dstbase"
  1808. X    fi
  1809. X
  1810. X    if $test ! x$uid = x; then
  1811. X        $chown $uid $dst/$dstbase
  1812. X    fi
  1813. X    if $test ! x$gid = x; then
  1814. X        $chgrp $gid $dst/$dstbase
  1815. X    fi
  1816. X    if $test ! x$mode = x
  1817. X    then
  1818. X        $chmod $mode $dst/$dstbase
  1819. X    fi
  1820. X)
  1821. X
  1822. Xexit 0
  1823. X!NO!SUBS!
  1824. Xchmod 755 install
  1825. X$eunicefix install
  1826. END_OF_FILE
  1827.   if test 3632 -ne `wc -c <'install.SH'`; then
  1828.     echo shar: \"'install.SH'\" unpacked with wrong size!
  1829.   fi
  1830.   chmod +x 'install.SH'
  1831.   # end of 'install.SH'
  1832. fi
  1833. echo shar: End of archive 14 \(of 17\).
  1834. cp /dev/null ark14isdone
  1835. MISSING=""
  1836. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ; do
  1837.     if test ! -f ark${I}isdone ; then
  1838.     MISSING="${MISSING} ${I}"
  1839.     fi
  1840. done
  1841. if test "${MISSING}" = "" ; then
  1842.     echo You have unpacked all 17 archives.
  1843.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1844. else
  1845.     echo You still must unpack the following archives:
  1846.     echo "        " ${MISSING}
  1847. fi
  1848. exit 0
  1849. exit 0 # Just in case...
  1850.