home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume41 / mailagnt / part19 < prev    next >
Encoding:
Text File  |  1993-12-03  |  55.0 KB  |  1,859 lines

  1. Newsgroups: comp.sources.misc
  2. From: Raphael Manfredi <ram@acri.fr>
  3. Subject: v41i019:  mailagent - Flexible mail filtering and processing package, v3.0, Part19/26
  4. Message-ID: <1993Dec3.213411.22706@sparky.sterling.com>
  5. X-Md4-Signature: 0fcb416ae11bbd7464c06ca92a7fdd14
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Advanced Computer Research Institute, Lyon, France.
  8. Date: Fri, 3 Dec 1993 21:34:11 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: Raphael Manfredi <ram@acri.fr>
  12. Posting-number: Volume 41, Issue 19
  13. Archive-name: mailagent/part19
  14. Environment: UNIX, Perl
  15. Supersedes: mailagent: Volume 33, Issue 93-109
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  22. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  23. # Contents:  agent/files/help/Makefile.SH agent/files/mailagent.cf
  24. #   agent/filter/main.c agent/man/Makefile.SH agent/pl/builtins.pl
  25. #   agent/pl/mmdf.pl agent/pl/read_conf.pl agent/pl/rfc822.pl
  26. #   agent/test/TEST agent/test/level agent/test/rules install.SH
  27. # Wrapped by ram@soft208 on Mon Nov 29 16:49:57 1993
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. echo If this archive is complete, you will see the following message:
  30. echo '          "shar: End of archive 19 (of 26)."'
  31. if test -f 'agent/files/help/Makefile.SH' -a "${1}" != "-c" ; then 
  32.   echo shar: Will not clobber existing file \"'agent/files/help/Makefile.SH'\"
  33. else
  34.   echo shar: Extracting \"'agent/files/help/Makefile.SH'\" \(4413 characters\)
  35.   sed "s/^X//" >'agent/files/help/Makefile.SH' <<'END_OF_FILE'
  36. X: Makefile.SH generated from Jmake.tmpl and Jmakefile [jmake 3.0 PL14]
  37. X: $X-Id: Jmake.tmpl,v 3.0.1.1 1993/08/20 07:36:36 ram Exp ram $
  38. X
  39. Xcase $CONFIG in
  40. X'')
  41. X    if test -f config.sh; then TOP=.;
  42. X    elif test -f ../config.sh; then TOP=..;
  43. X    elif test -f ../../config.sh; then TOP=../..;
  44. X    elif test -f ../../../config.sh; then TOP=../../..;
  45. X    elif test -f ../../../../config.sh; then TOP=../../../..;
  46. X    else
  47. X        echo "Can't find config.sh."; exit 1
  48. X    fi
  49. X    . $TOP/config.sh
  50. X    ;;
  51. Xesac
  52. Xcase "$0" in
  53. X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
  54. Xesac
  55. XCURRENT=agent/files/help
  56. XDIR=`echo $CURRENT/ | sed -e 's/\.\///g'`
  57. Xecho "Extracting ${DIR}Makefile (with variable substitutions)"
  58. XDATE=`date`
  59. X$spitshell >Makefile <<!GROK!THIS!
  60. X########################################################################
  61. X# Makefile generated from Makefile.SH on $DATE
  62. X
  63. XSHELL = /bin/sh
  64. XJMAKE = jmake
  65. XTOP = ../../..
  66. XCURRENT = $CURRENT
  67. XDIR = $DIR
  68. XINSTALL = ../../../install
  69. X
  70. X########################################################################
  71. X# Parameters set by Configure -- edit config.sh if changes are needed
  72. X
  73. XCTAGS = ctags
  74. XMAKE = make
  75. XMV = $mv
  76. XPRIVLIB = $installprivlib
  77. XRM = $rm -f
  78. X
  79. X!GROK!THIS!
  80. X$spitshell >>Makefile <<'!NO!SUBS!'
  81. X########################################################################
  82. X# Jmake rules for building libraries, programs, scripts, and data files
  83. X# $X-Id: Jmake.rules,v 3.0 1993/08/18 12:04:14 ram Exp ram $
  84. X
  85. X########################################################################
  86. X# Start of Jmakefile
  87. X
  88. X# $X-Id: Jmakefile,v 2.9 92/07/14 16:47:32 ram Exp $
  89. X#
  90. X#  Copyright (c) 1990-1993, Raphael Manfredi
  91. X#  
  92. X#  You may redistribute only under the terms of the Artistic License,
  93. X#  as specified in the README file that comes with the distribution.
  94. X#  You may reuse parts of this distribution only within the terms of
  95. X#  that same Artistic License; a copy of which may be found at the root
  96. X#  of the source tree for mailagent 3.0.
  97. X#
  98. X# $X-Log$
  99. X
  100. XFILES = addauth approve delpower end getauth help newpower \
  101. X    passwd password power release remauth set setauth user
  102. X
  103. Xall::
  104. X
  105. Xall:: $(FILES)
  106. X
  107. Xlocal_realclean::
  108. X    $(RM) $(FILES)
  109. X
  110. Xaddauth: addauth.SH
  111. X    /bin/sh addauth.SH
  112. X
  113. Xapprove: approve.SH
  114. X    /bin/sh approve.SH
  115. X
  116. Xdelpower: delpower.SH
  117. X    /bin/sh delpower.SH
  118. X
  119. Xend: end.SH
  120. X    /bin/sh end.SH
  121. X
  122. Xgetauth: getauth.SH
  123. X    /bin/sh getauth.SH
  124. X
  125. Xhelp: help.SH
  126. X    /bin/sh help.SH
  127. X
  128. Xnewpower: newpower.SH
  129. X    /bin/sh newpower.SH
  130. X
  131. Xpasswd: passwd.SH
  132. X    /bin/sh passwd.SH
  133. X
  134. Xpassword: password.SH
  135. X    /bin/sh password.SH
  136. X
  137. Xpower: power.SH
  138. X    /bin/sh power.SH
  139. X
  140. Xrelease: release.SH
  141. X    /bin/sh release.SH
  142. X
  143. Xremauth: remauth.SH
  144. X    /bin/sh remauth.SH
  145. X
  146. Xset: set.SH
  147. X    /bin/sh set.SH
  148. X
  149. Xsetauth: setauth.SH
  150. X    /bin/sh setauth.SH
  151. X
  152. Xuser: user.SH
  153. X    /bin/sh user.SH
  154. X
  155. X
  156. Xinstall::
  157. X    @for dir in $(PRIVLIB) $(PRIVLIB)/help; do \
  158. X        case '${MFLAGS}' in *[i]*) set +e;; esac; \
  159. X        (set -x; $(INSTALL) -d $$dir); \
  160. X    done
  161. X
  162. Xdeinstall::
  163. X    $(RM) -r $(PRIVLIB) $(PRIVLIB)/help
  164. X
  165. Xinstall:: $(FILES)
  166. X    @case '${MFLAGS}' in *[i]*) set +e;; esac; \
  167. X    for i in $(FILES); do \
  168. X        (set -x; $(INSTALL) -c -m 444 $$i $(PRIVLIB)/help); \
  169. X    done
  170. X
  171. Xdeinstall::
  172. X    @case '${MFLAGS}' in *[i]*) set +e;; esac; \
  173. X    for i in $(FILES); do \
  174. X        (set -x; $(RM) $(PRIVLIB)/help/$$i); \
  175. X    done
  176. X
  177. X########################################################################
  178. X# Common rules for all Makefiles -- do not edit
  179. X
  180. Xemptyrule::
  181. X
  182. Xclean: local_clean
  183. Xrealclean: local_realclean
  184. Xclobber: local_clobber
  185. X
  186. Xlocal_clean::
  187. X    $(RM) core *~ *.o
  188. X
  189. Xlocal_realclean:: local_clean
  190. X
  191. Xlocal_clobber:: local_realclean
  192. X    $(RM) Makefile config.sh
  193. X
  194. XMakefile.SH: Jmakefile
  195. X    -@if test -f $(TOP)/.package; then \
  196. X        if test -f Makefile.SH; then \
  197. X            echo "    $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~"; \
  198. X            $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~; \
  199. X        fi; \
  200. X        echo "    $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT)" ; \
  201. X        $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT) ; \
  202. X    else touch $@; exit 0; fi
  203. X
  204. XMakefile: Makefile.SH
  205. X    /bin/sh Makefile.SH
  206. X
  207. Xtags::
  208. X    $(CTAGS) -w *.[ch]
  209. X    $(CTAGS) -xw *.[ch] > tags
  210. X
  211. Xlocal_clobber::
  212. X    $(RM) tags
  213. X
  214. X########################################################################
  215. X# Empty rules for directories with no sub-directories -- do not edit
  216. X
  217. Xinstall::
  218. X    @echo "install in $(CURRENT) done."
  219. X
  220. Xdeinstall::
  221. X    @echo "deinstall in $(CURRENT) done."
  222. X
  223. Xinstall.man::
  224. X    @echo "install.man in $(CURRENT) done."
  225. X
  226. Xdeinstall.man::
  227. X    @echo "deinstall.man in $(CURRENT) done."
  228. X
  229. XMakefiles::
  230. X
  231. XMakefiles.SH::
  232. X
  233. X!NO!SUBS!
  234. Xchmod 644 Makefile
  235. X$eunicefix Makefile
  236. X
  237. END_OF_FILE
  238.   if test 4413 -ne `wc -c <'agent/files/help/Makefile.SH'`; then
  239.     echo shar: \"'agent/files/help/Makefile.SH'\" unpacked with wrong size!
  240.   fi
  241.   # end of 'agent/files/help/Makefile.SH'
  242. fi
  243. if test -f 'agent/files/mailagent.cf' -a "${1}" != "-c" ; then 
  244.   echo shar: Will not clobber existing file \"'agent/files/mailagent.cf'\"
  245. else
  246.   echo shar: Extracting \"'agent/files/mailagent.cf'\" \(4439 characters\)
  247.   sed "s/^X//" >'agent/files/mailagent.cf' <<'END_OF_FILE'
  248. X#
  249. X# Configuration file for mailagent
  250. X#
  251. X
  252. X# $Id: mailagent.cf,v 3.0 1993/11/29 13:48:02 ram Exp ram $
  253. X#
  254. X#  Copyright (c) 1990-1993, Raphael Manfredi
  255. X#  
  256. X#  You may redistribute only under the terms of the Artistic License,
  257. X#  as specified in the README file that comes with the distribution.
  258. X#  You may reuse parts of this distribution only within the terms of
  259. X#  that same Artistic License; a copy of which may be found at the root
  260. X#  of the source tree for mailagent 3.0.
  261. X#
  262. X# $Log: mailagent.cf,v $
  263. X# Revision 3.0  1993/11/29  13:48:02  ram
  264. X# Baseline for mailagent 3.0 netwide release.
  265. X#
  266. X
  267. X#
  268. X# Configuration section
  269. X#
  270. X
  271. X# Paramters likely to change
  272. Xhome     : /lyon/ram            # Home directory (must be correctly set)
  273. Xlevel    : 9                    # Logging level
  274. Xtmpdir   : /tmp                    # Temporary directory to be used
  275. Xemergdir : ~/tmp/lost+mail        # Emergency directory (for dumps)
  276. Xtrack    : OFF                    # Track matches on stdout (on/off)
  277. X
  278. X# Minimum path to ensure and path depending on the machine
  279. Xpath     : /bin:/usr/bin:/usr/ucb
  280. Xp_york   : ~/bin:~/bin/rs2030
  281. Xp_lyon   : ~/bin:~/bin/rs2030
  282. Xp_rome   : ~/bin:~/bin/sun4:/base/common/GENERAL/sun4/bin
  283. X
  284. X# User who runs mailagent
  285. Xuser     : ram
  286. Xname     : Raphael
  287. X
  288. X# Vacation mode (on/off), vacation file and period
  289. Xvacation : OFF                    # Vacation mode on/off
  290. Xvacfile  : ~/.vacation            # File to be sent back
  291. Xvacperiod: 1d                    # Period between two vacation messages
  292. X
  293. X# Mail and news transport agents
  294. X# By default, values for sendmail and sendnews are determined at configuration
  295. X# time. The default mailopt is -odq when sendmail is used. The -h option is
  296. X# always added to the sendnews program to indicate headers are already present.
  297. Xsendmail : /usr/lib/sendmail
  298. Xsendnews : /usr/lib/news/inews
  299. Xmailopt  : -odq
  300. Xnewsopt  :
  301. X
  302. X
  303. X#
  304. X# Parameters which should not change very often
  305. X#
  306. X
  307. X# Define main configuration parameters
  308. Xspool    : ~/var/mailagent        # Spool directory
  309. Xqueue    : $spool/queue            # Queue directory (must exist)
  310. Xlogdir   : ~/var/log            # Where logfile is stored
  311. Xcontext  : $spool/context        # Mailagent's context file
  312. Xlog      : agentlog                # Log file is in $logdir
  313. Xseq      : .seq                    # Seq file is in $spool
  314. Xtimezone : PST8PDT                # Time zone location
  315. Xstatfile : $spool/mailagent.st    # Statistics file
  316. Xrules    : ~/.rules                # Filter's rules location (optional)
  317. Xrulecache: $spool/rulecache        # Cache for compiled rules (optional)
  318. Xnfslock  : OFF                    # NFS-secure locking (optional)
  319. Xsecure   : ON                    # Make extended checks on sensitive files
  320. X
  321. X# Mailbox parameters
  322. Xmaildrop : /usr/mail            # System mail drop directory (optional)
  323. Xmailbox  : $user                # Mailbox file name (optional)
  324. Xmmdf     : OFF                    # Allow MMDF-style mailbox delivery
  325. Xmmdfbox  : OFF                    # Force new folders to MMDF format
  326. X
  327. X# MH-style folders
  328. Xmhprofile: ~/.mh_profile        # Name of the MH profile file (optional)
  329. Xmsgprefix: .msg_prefix            # File containing message name prefix
  330. X
  331. X# Optional parameters (for experts...)
  332. X#compress : ~/.compress            # Folder compression list
  333. X#newcmd   : $spool/newcmd        # Definition of new filtering commands
  334. X#perlib   : pl                    # Extended perl library search path
  335. X
  336. X# Database hashing directory (in $spool) and other controls
  337. Xhash     : dbr                    # Hashing directory
  338. Xcleanlaps: 1M                    # Laps between cleanings
  339. Xautoclean: ON                    # Turn periodic cleaning on/off
  340. Xagemax   : 1y                    # Maximum lifetime for entries
  341. X
  342. X#
  343. X# Parameters for SERVER
  344. X#
  345. X
  346. Xcomserver: $spool/server        # Valid server commands
  347. Xservdir  : $spool/cmds            # Default path for perl server commands
  348. Xmaxerrors: 10                    # Allow at most ten errors before flushing
  349. Xmaxcmds  : 10                    # Allow maximum of ten commands in one request
  350. Xscriptcc : ON                    # Send copy of sesssion transcripts to user?
  351. Xbqueue   : $spool/batch            # Batch queue (not implemented yet)
  352. Xpowers   : $spool/powers        # Directory for power administration
  353. Xpowerlog : $logdir/powerlog        # Log requests for new powers
  354. Xpowerlist: $powers/aliases        # Mapping of powers to filename in powerdir
  355. Xpowerdir : $powers/clearance    # Directory listing user clearances for powers
  356. Xpasswd   : $powers/passwd        # Power passwords
  357. Xhelpdir  : $spool/help            # Help directory for server commands
  358. X
  359. X#
  360. X# Parameters for PROCESS
  361. X#
  362. X
  363. Xcomfile  : $spool/commands        # Valid commands
  364. Xdistlist : $spool/distribs        # Distribution list
  365. Xproglist : $spool/proglist        # Program description list
  366. Xmaxsize  : 150000                # Maximum size before kiting
  367. Xplsave   : $spool/plsave        # Where patchlevels are saved
  368. Xauthfile : $spool/auth            # Remote sending authorizations (not yet)
  369. END_OF_FILE
  370.   if test 4439 -ne `wc -c <'agent/files/mailagent.cf'`; then
  371.     echo shar: \"'agent/files/mailagent.cf'\" unpacked with wrong size!
  372.   fi
  373.   # end of 'agent/files/mailagent.cf'
  374. fi
  375. if test -f 'agent/filter/main.c' -a "${1}" != "-c" ; then 
  376.   echo shar: Will not clobber existing file \"'agent/filter/main.c'\"
  377. else
  378.   echo shar: Extracting \"'agent/filter/main.c'\" \(4488 characters\)
  379.   sed "s/^X//" >'agent/filter/main.c' <<'END_OF_FILE'
  380. X/*
  381. X
  382. X #    #    ##       #    #    #           ####
  383. X ##  ##   #  #      #    ##   #          #    #
  384. X # ## #  #    #     #    # #  #          #
  385. X #    #  ######     #    #  # #   ###    #
  386. X #    #  #    #     #    #   ##   ###    #    #
  387. X #    #  #    #     #    #    #   ###     ####
  388. X
  389. X    The main entry point.
  390. X*/
  391. X
  392. X/*
  393. X * $Id: main.c,v 3.0 1993/11/29 13:48:15 ram Exp ram $
  394. X *
  395. X *  Copyright (c) 1990-1993, Raphael Manfredi
  396. X *  
  397. X *  You may redistribute only under the terms of the Artistic License,
  398. X *  as specified in the README file that comes with the distribution.
  399. X *  You may reuse parts of this distribution only within the terms of
  400. X *  that same Artistic License; a copy of which may be found at the root
  401. X *  of the source tree for mailagent 3.0.
  402. X *
  403. X * $Log: main.c,v $
  404. X * Revision 3.0  1993/11/29  13:48:15  ram
  405. X * Baseline for mailagent 3.0 netwide release.
  406. X *
  407. X */
  408. X
  409. X#include "config.h"
  410. X#include "portable.h"
  411. X
  412. X#ifdef I_STRING
  413. X#include <string.h>
  414. X#else
  415. X#include <strings.h>
  416. X#endif
  417. X
  418. X#include <stdio.h>
  419. X#include <signal.h>
  420. X#include <sys/types.h>
  421. X#include "logfile.h"
  422. X#include "io.h"
  423. X#include "hash.h"
  424. X#include "msg.h"
  425. X#include "parser.h"
  426. X#include "sysexits.h"
  427. X#include "lock.h"
  428. X#include "confmagic.h"
  429. X
  430. X#define MAX_STRING    2048    /* Maximum string length */
  431. X
  432. Xprivate Signal_t handler();    /* Signal handler */
  433. Xprivate void set_signal();    /* Set up the signal handler */
  434. X
  435. Xextern void env_home();        /* Only for tests */
  436. X
  437. Xpublic void main(argc, argv, envp)
  438. Xint argc;
  439. Xchar **argv;
  440. Xchar **envp;
  441. X{
  442. X    /* This is the main entry point for the mail filter */
  443. X
  444. X    char *value;                        /* Symbol value */
  445. X    int euid, uid;                        /* Current effective and real uid */
  446. X    int egid, gid;                        /* Effective and real gid */
  447. X
  448. X    /* Compute program name, removing any leading path to keep only the name
  449. X     * of the executable file.
  450. X     */
  451. X    progname = rindex(argv[0], '/');    /* Only last name if '/' found */
  452. X    if (progname++ == (char *) 0)        /* There were no '/' */
  453. X        progname = argv[0];                /* This must be the filename then */
  454. X    progpid = getpid();                    /* Program's PID */
  455. X
  456. X    /* Security precautions. Look who we are and who we pretend to be */
  457. X    uid = getuid();
  458. X    gid = getgid();
  459. X    euid = geteuid();
  460. X    egid = getegid();
  461. X
  462. X    /* The '-t' option means we are in test mode: set the home directory by
  463. X     * using the environment HOME variable, so that we may provide our own
  464. X     * configuration file elsewhere. Of course, this cannot be used if the
  465. X     * filter is setuid and invoked by an uid different than the owner of the
  466. X     * filter program.
  467. X     */
  468. X    if (argc > 1 && 0 == strcmp(argv[1], "-t")) {
  469. X        if (uid != euid || gid != egid) {
  470. X            fprintf(stderr, "filter: no option allowed when set%s\n",
  471. X                uid != euid ? "uid" : "gid");
  472. X            exit(EX_USAGE);
  473. X        }
  474. X        env_home();                        /* Get HOME form environment */
  475. X    }
  476. X
  477. X    set_signal();                        /* Set up signal handler */
  478. X    read_conf(".mailagent");            /* Read configuration file */
  479. X
  480. X    add_log(19, "starting processing");
  481. X
  482. X    /* We'll be invoking a perl script with the -S switch, and perl will not
  483. X     * allow us to do that if it detects "setuidness". Some sendmail programs
  484. X     * are broken and do not reset the uid/gid correctly when they process
  485. X     * their queue. This is why it is important to set the setuid and setgid
  486. X     * bits on the filter program.
  487. X     */
  488. X
  489. X    /* Make sure our gid matches the effective gid */
  490. X    if (egid != gid && -1 == setgid(egid)) {
  491. X        add_log(1, "SYSERR setgid: %m (%e)");
  492. X        add_log(4, "WARNING cannot set GID to %d, continuing as %d", egid, gid);
  493. X    } else if (egid != gid)
  494. X        add_log(6, "NOTICE reset GID from %d to %d", gid, egid);
  495. X
  496. X    /* Make sure our uid matches the effective uid */
  497. X    if (euid != uid && -1 == setuid(euid)) {
  498. X        add_log(1, "SYSERR setuid: %m (%e)");
  499. X        add_log(4, "WARNING cannot set UID to %d, continuing as %d", euid, uid);
  500. X    } else if (euid != uid)
  501. X        add_log(6, "NOTICE reset UID from %d to %d", uid, euid);
  502. X
  503. X    value = ht_value(&symtab, "queue");        /* Fetch queue location */
  504. X    if (value == (char *) 0)
  505. X        fatal("queue directory not defined");
  506. X
  507. X    set_env_vars(envp);                        /* Set environment variables */
  508. X    process();                                /* Process mail */
  509. X
  510. X    exit(EX_OK);        /* We did it */
  511. X}
  512. X
  513. Xprivate void set_signal()
  514. X{
  515. X    /* Set up the signal handler */
  516. X
  517. X#ifdef SIGHUP
  518. X    signal(SIGHUP, handler);
  519. X#endif
  520. X#ifdef SIGINT
  521. X    signal(SIGINT, handler);
  522. X#endif
  523. X#ifdef SIGQUIT
  524. X    signal(SIGQUIT, handler);
  525. X#endif
  526. X#ifdef SIGTERM
  527. X    signal(SIGTERM, handler);
  528. X#endif
  529. X}
  530. X
  531. Xprivate Signal_t handler(sig)
  532. Xint sig;
  533. X{
  534. X    /* A signal was caught */
  535. X
  536. X    release_lock();                    /* Release lock file if necessary */
  537. X    fatal("caught signal #%d", sig);
  538. X}
  539. X
  540. END_OF_FILE
  541.   if test 4488 -ne `wc -c <'agent/filter/main.c'`; then
  542.     echo shar: \"'agent/filter/main.c'\" unpacked with wrong size!
  543.   fi
  544.   # end of 'agent/filter/main.c'
  545. fi
  546. if test -f 'agent/man/Makefile.SH' -a "${1}" != "-c" ; then 
  547.   echo shar: Will not clobber existing file \"'agent/man/Makefile.SH'\"
  548. else
  549.   echo shar: Extracting \"'agent/man/Makefile.SH'\" \(4062 characters\)
  550.   sed "s/^X//" >'agent/man/Makefile.SH' <<'END_OF_FILE'
  551. X: Makefile.SH generated from Jmake.tmpl and Jmakefile [jmake 3.0 PL14]
  552. X: $X-Id: Jmake.tmpl,v 3.0.1.1 1993/08/20 07:36:36 ram Exp ram $
  553. X
  554. Xcase $CONFIG in
  555. X'')
  556. X    if test -f config.sh; then TOP=.;
  557. X    elif test -f ../config.sh; then TOP=..;
  558. X    elif test -f ../../config.sh; then TOP=../..;
  559. X    elif test -f ../../../config.sh; then TOP=../../..;
  560. X    elif test -f ../../../../config.sh; then TOP=../../../..;
  561. X    else
  562. X        echo "Can't find config.sh."; exit 1
  563. X    fi
  564. X    . $TOP/config.sh
  565. X    ;;
  566. Xesac
  567. Xcase "$0" in
  568. X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
  569. Xesac
  570. XCURRENT=agent/man
  571. XDIR=`echo $CURRENT/ | sed -e 's/\.\///g'`
  572. Xecho "Extracting ${DIR}Makefile (with variable substitutions)"
  573. XDATE=`date`
  574. X$spitshell >Makefile <<!GROK!THIS!
  575. X########################################################################
  576. X# Makefile generated from Makefile.SH on $DATE
  577. X
  578. XSHELL = /bin/sh
  579. XJMAKE = jmake
  580. XTOP = ../..
  581. XCURRENT = $CURRENT
  582. XDIR = $DIR
  583. XINSTALL = ../../install
  584. X
  585. X########################################################################
  586. X# Parameters set by Configure -- edit config.sh if changes are needed
  587. X
  588. XCTAGS = ctags
  589. XL = $manext
  590. XMANSRC = $installmansrc
  591. XMAKE = make
  592. XMV = $mv
  593. XRM = $rm -f
  594. X
  595. X########################################################################
  596. X# Automatically generated parameters -- do not edit
  597. X
  598. XMANPAGE =  \$(MPAGES)
  599. X
  600. X########################################################################
  601. X# New suffixes and associated building rules -- edit with care
  602. X
  603. X.SUFFIXES: .SH .$manext
  604. X
  605. X.SH.$manext:
  606. X    /bin/sh \$<
  607. X
  608. X!GROK!THIS!
  609. X$spitshell >>Makefile <<'!NO!SUBS!'
  610. X########################################################################
  611. X# Jmake rules for building libraries, programs, scripts, and data files
  612. X# $X-Id: Jmake.rules,v 3.0 1993/08/18 12:04:14 ram Exp ram $
  613. X
  614. X########################################################################
  615. X# Start of Jmakefile
  616. X
  617. X# $X-Id: Jmakefile,v 2.9 92/07/14 16:49:04 ram Exp $
  618. X#
  619. X#  Copyright (c) 1990-1993, Raphael Manfredi
  620. X#  
  621. X#  You may redistribute only under the terms of the Artistic License,
  622. X#  as specified in the README file that comes with the distribution.
  623. X#  You may reuse parts of this distribution only within the terms of
  624. X#  that same Artistic License; a copy of which may be found at the root
  625. X#  of the source tree for mailagent 3.0.
  626. X#
  627. X# $X-Log$
  628. X
  629. XMPAGES = mailagent.$(L) maildist.$(L) maillist.$(L) mailhelp.$(L) \
  630. X    mailpatch.$(L) package.$(L)
  631. X
  632. Xall:: $(MPAGES)
  633. X
  634. Xlocal_realclean::
  635. X    $(RM) $(MPAGES)
  636. X
  637. Xinstall.man::
  638. X    @if test "$(MANSRC)"; then \
  639. X        case '${MFLAGS}' in *[i]*) set +e;; esac; \
  640. X        for file in $(MPAGES); do \
  641. X            (set -x; $(INSTALL) -c -m 444 $$file $(MANSRC)); \
  642. X        done; \
  643. X    else exit 0; fi
  644. X
  645. Xdeinstall.man::
  646. X    @if test "$(MANSRC)"; then \
  647. X        case '${MFLAGS}' in *[i]*) set +e;; esac; \
  648. X        for file in $(MPAGES); do \
  649. X            (set -x; $(RM) $(MANSRC)/$$file); \
  650. X        done; \
  651. X    else exit 0; fi
  652. X
  653. X########################################################################
  654. X# Common rules for all Makefiles -- do not edit
  655. X
  656. Xemptyrule::
  657. X
  658. Xclean: local_clean
  659. Xrealclean: local_realclean
  660. Xclobber: local_clobber
  661. X
  662. Xlocal_clean::
  663. X    $(RM) core *~ *.o
  664. X
  665. Xlocal_realclean:: local_clean
  666. X
  667. Xlocal_clobber:: local_realclean
  668. X    $(RM) Makefile config.sh
  669. X
  670. XMakefile.SH: Jmakefile
  671. X    -@if test -f $(TOP)/.package; then \
  672. X        if test -f Makefile.SH; then \
  673. X            echo "    $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~"; \
  674. X            $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~; \
  675. X        fi; \
  676. X        echo "    $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT)" ; \
  677. X        $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT) ; \
  678. X    else touch $@; exit 0; fi
  679. X
  680. XMakefile: Makefile.SH
  681. X    /bin/sh Makefile.SH
  682. X
  683. Xtags::
  684. X    $(CTAGS) -w *.[ch]
  685. X    $(CTAGS) -xw *.[ch] > tags
  686. X
  687. Xlocal_clobber::
  688. X    $(RM) tags
  689. X
  690. X########################################################################
  691. X# Empty rules for directories with no sub-directories -- do not edit
  692. X
  693. Xinstall::
  694. X    @echo "install in $(CURRENT) done."
  695. X
  696. Xdeinstall::
  697. X    @echo "deinstall in $(CURRENT) done."
  698. X
  699. Xinstall.man::
  700. X    @echo "install.man in $(CURRENT) done."
  701. X
  702. Xdeinstall.man::
  703. X    @echo "deinstall.man in $(CURRENT) done."
  704. X
  705. XMakefiles::
  706. X
  707. XMakefiles.SH::
  708. X
  709. X!NO!SUBS!
  710. Xchmod 644 Makefile
  711. X$eunicefix Makefile
  712. X
  713. END_OF_FILE
  714.   if test 4062 -ne `wc -c <'agent/man/Makefile.SH'`; then
  715.     echo shar: \"'agent/man/Makefile.SH'\" unpacked with wrong size!
  716.   fi
  717.   chmod +x 'agent/man/Makefile.SH'
  718.   # end of 'agent/man/Makefile.SH'
  719. fi
  720. if test -f 'agent/pl/builtins.pl' -a "${1}" != "-c" ; then 
  721.   echo shar: Will not clobber existing file \"'agent/pl/builtins.pl'\"
  722. else
  723.   echo shar: Extracting \"'agent/pl/builtins.pl'\" \(3583 characters\)
  724.   sed "s/^X//" >'agent/pl/builtins.pl' <<'END_OF_FILE'
  725. X;# $Id: builtins.pl,v 3.0 1993/11/29 13:48:35 ram Exp ram $
  726. X;#
  727. X;#  Copyright (c) 1990-1993, Raphael Manfredi
  728. X;#  
  729. X;#  You may redistribute only under the terms of the Artistic License,
  730. X;#  as specified in the README file that comes with the distribution.
  731. X;#  You may reuse parts of this distribution only within the terms of
  732. X;#  that same Artistic License; a copy of which may be found at the root
  733. X;#  of the source tree for mailagent 3.0.
  734. X;#
  735. X;# $Log: builtins.pl,v $
  736. X;# Revision 3.0  1993/11/29  13:48:35  ram
  737. X;# Baseline for mailagent 3.0 netwide release.
  738. X;#
  739. X;# 
  740. X#
  741. X# Executing builtin commands
  742. X#
  743. X
  744. X# Send a receipt
  745. Xsub send_receipt {
  746. X    local($subj) =            $Header{'Subject'};
  747. X    local($msg_id) =        $Header{'Message-Id'};
  748. X    local($from) =            $Header{'From'};
  749. X    local($sender) =        $Header{'Reply-To'};
  750. X    local($to) =            $Header{'To'};
  751. X    local($ack_dest) = @_;    # Were to send receipt
  752. X    local($dest);            # Return path to be used (derived from mail)
  753. X
  754. X    # If no @PATH directive was found, use $sender as a return path
  755. X    $dest = $Userpath;                # Set by an @PATH
  756. X    $dest = $sender unless $dest;
  757. X    # Remove the <> if any (e.g. path derived from Return-Path)
  758. X    $dest =~ /<(.*)>/ && ($dest = $1);
  759. X
  760. X    # Derive a correct return path for receipt
  761. X    $ack_dest = 'PATH' if $ack_dest eq '-';
  762. X    $ack_dest = "" if $ack_dest =~ /[=\$^&*([{}`\\|;><?]/;
  763. X    $ack_dest = $dest if ($ack_dest eq '' || $ack_dest =~ /PATH/);
  764. X
  765. X    # Compute host name (fully qualified, i.e. with domain name)
  766. X    chop($hostname = `$phostname`);
  767. X    $hostname .= $mydomain if $hostname =~ /^\w+$/;
  768. X
  769. X    chop($date = `date`);
  770. X    open(MAILER,"|$cf'sendmail $cf'mailopt $ack_dest");
  771. X    print MAILER <<EOM;
  772. XTo: $ack_dest
  773. XSubject: Re: $subj (receipt)
  774. X$MAILER
  775. XEOM
  776. X    if ($msg_id ne '') {
  777. X        print MAILER "\nYour message $msg_id,\n";
  778. X    } else {
  779. X        print MAILER "\nYour message ";
  780. X    }
  781. X    print MAILER "addressed to $to,\n" if $to ne '';
  782. X    print MAILER "whose subject was \"$subj\",\n" if $subj ne '';
  783. X    print MAILER <<EOM;
  784. Xhas been received by $hostname on $date
  785. X
  786. X-- mailagent speaking for $cf'user
  787. XEOM
  788. X    close MAILER;
  789. X    if ($?) {
  790. X        &add_log("ERROR couldn't send receipt to $ack_dest") if $loglvl > 0;
  791. X    } else {
  792. X        &add_log("SENT receipt to $ack_dest") if $loglvl > 2;
  793. X    }
  794. X}
  795. X
  796. X#
  797. X# Deal with builtins
  798. X#
  799. X
  800. X# Built-in commands are listed herein. Those commands being built-in are always
  801. X# dealt with during mail parsing and are taken care of at the beginning of the
  802. X# rules analysis. The code to be executed for each builtin is stored in the
  803. X# Builtcode array by those routines.
  804. Xsub init_builtins {
  805. X    %Builtin = (
  806. X        'RR', 'builtin_rr',
  807. X        'PATH', 'builtin_path'
  808. X    );
  809. X    undef @Builtcode;
  810. X}
  811. X
  812. X# Whenever a builtin command is recognized (on the fly) while parsing the mail
  813. X# body, the corresponding builtin function is called with the remaining of the
  814. X# line given as argument (leading spaces removed).
  815. X
  816. X# The @RR command asks for a receipt
  817. Xsub builtin_rr {
  818. X    local($_) = @_;
  819. X    &add_log("found an @RR request to $_") if $loglvl > 18;
  820. X    # @RR request honored only if not from special user and directed to us
  821. X    unless (&special_user) {
  822. X        push(@Builtcode, "&send_receipt('$_')");
  823. X    } else {
  824. X        &add_log("ignoring @RR request to $_") if $loglvl > 4;
  825. X    }
  826. X}
  827. X
  828. X# The @PATH command sets a valid return path (recorded in $Userpath)
  829. Xsub builtin_path {
  830. X    local($_) = @_;
  831. X    return if /[=\$^&*([{}`\\|;><?]/;        # Invalid character found
  832. X    $Userpath = $_;
  833. X    &add_log("found an @PATH request to $_") if $loglvl > 18;
  834. X}
  835. X
  836. X# Execute stacked builtins
  837. Xsub run_builtins {
  838. X    return if $#Builtcode < 0;        # No recorded builtins
  839. X    foreach (@Builtcode) {
  840. X        eval($_);                    # Execute stacked builtin
  841. X    }
  842. X    @Builtcode = ();                # Reset builtcode array
  843. X}
  844. X
  845. END_OF_FILE
  846.   if test 3583 -ne `wc -c <'agent/pl/builtins.pl'`; then
  847.     echo shar: \"'agent/pl/builtins.pl'\" unpacked with wrong size!
  848.   fi
  849.   # end of 'agent/pl/builtins.pl'
  850. fi
  851. if test -f 'agent/pl/mmdf.pl' -a "${1}" != "-c" ; then 
  852.   echo shar: Will not clobber existing file \"'agent/pl/mmdf.pl'\"
  853. else
  854.   echo shar: Extracting \"'agent/pl/mmdf.pl'\" \(4318 characters\)
  855.   sed "s/^X//" >'agent/pl/mmdf.pl' <<'END_OF_FILE'
  856. X;# $Id: mmdf.pl,v 3.0 1993/11/29 13:49:02 ram Exp ram $
  857. X;#
  858. X;#  Copyright (c) 1990-1993, Raphael Manfredi
  859. X;#  
  860. X;#  You may redistribute only under the terms of the Artistic License,
  861. X;#  as specified in the README file that comes with the distribution.
  862. X;#  You may reuse parts of this distribution only within the terms of
  863. X;#  that same Artistic License; a copy of which may be found at the root
  864. X;#  of the source tree for mailagent 3.0.
  865. X;#
  866. X;# $Log: mmdf.pl,v $
  867. X;# Revision 3.0  1993/11/29  13:49:02  ram
  868. X;# Baseline for mailagent 3.0 netwide release.
  869. X;#
  870. X;# 
  871. X;# This set of routine handles MMDF-style mailboxes, which differ from the
  872. X;# traditional Unix-style boxes by encapsulating each message between 2 lines
  873. X;# of 4 ^A, one at the begining and one at the end. The leading From_ line is
  874. X;# consequently not needed and is removed.
  875. X;#
  876. X;# Note: this MMDF-style mailbox is also used by MH packed folders.
  877. X;#
  878. X#
  879. X# MMDF-style saving routines
  880. X#
  881. X
  882. Xpackage mmdf;
  883. X
  884. X# Attempt to save in a possible MMDF mailbox. The routine opens the mailbox
  885. X# and tries to determine what kind of mailbox it is, then selects the
  886. X# appropriate saving routine.
  887. Xsub save {
  888. X    local(*FD, $mailbox) = @_;    # File descriptor and mailbox name
  889. X    if (&is_mmdf($mailbox)) {    # Folder looks like an MMDF mailbox
  890. X        &save_mmdf(*FD, 'MDF');    # Use MMDF format then
  891. X    } else {
  892. X        &save_unix(*FD);        # Be conservative and use standard format
  893. X    }
  894. X}
  895. X    
  896. X# Save to a MMDF-style mailbox and return failure status with message length
  897. X# Can also be used to save MH messages if parameter $mmdf set to 'MH' (in which
  898. X# case the two ^A delimiter lines are ommitted).
  899. Xsub save_mmdf {
  900. X    local(*FD, $mmdf) = @_;        # File descriptor, MH/MDF format
  901. X    local($amount) = 0;            # Amount of bytes saved
  902. X    local($failed);
  903. X    local($from);
  904. X    local(@head) = split(/\n/, $'Header{'Head'});
  905. X    $from = shift(@head);        # The first From_ line has to be skipped
  906. X    unless ($from =~ /^From\s/) {
  907. X        &'add_log("WARNING leading From line absent") if $'loglvl > 5;
  908. X        unshift(@head, $from);    # Put it back if not a From_ line
  909. X    }
  910. X    unless ($mmdf eq 'MH') {
  911. X        (print FD "\01\01\01\01\n") || ($failed = 1);
  912. X        $amount += 5;
  913. X    }
  914. X    foreach $line (@head) {
  915. X        (print FD $line, "\n") || ($failed = 1);
  916. X        $amount += length($line) + 1;
  917. X    }
  918. X    (print FD $'FILTER, "\n\n") || ($failed = 1);
  919. X    (print FD $'Header{'Body'}) || ($failed = 1);
  920. X    &force_flushing(*FD);
  921. X    unless ($mmdf eq 'MH') {
  922. X        (print FD "\01\01\01\01\n") || ($failed = 1);
  923. X        $amount += 5;
  924. X    }
  925. X    $amount +=
  926. X        length($'Header{'Body'}) +    # Message body
  927. X        length($'FILTER) + 2;        # X-Filter line plus two newlines
  928. X    ($failed, $amount);
  929. X}
  930. X
  931. X# Save to a Unix-style mailbox and return failure status with message length
  932. Xsub save_unix {
  933. X    local(*FD) = @_;            # File descriptor
  934. X    local($amount) = 0;            # Amount of bytes saved
  935. X    local($failed);
  936. X    # First print the Header, then add the X-Filter: line, followed by body.
  937. X    (print FD $'Header{'Head'}) || ($failed = 1);
  938. X    (print FD $'FILTER, "\n\n") || ($failed = 1);
  939. X    (print FD $'Header{'Body'}) || ($failed = 1);
  940. X    &force_flushing(*FD);
  941. X    (print FD "\n") || ($failed = 1);        # Allow parsing by other tools
  942. X    $amount +=
  943. X        length($'Header{'Head'}) +    # Message header
  944. X        length($'Header{'Body'}) +    # Message body
  945. X        length($'FILTER) + 2 +        # X-Filter line plus two newlines
  946. X        1;                            # Trailing new-line
  947. X    ($failed, $amount);
  948. X}
  949. X
  950. X# Force flushing on file descriptor, so that after next print, we may rest
  951. X# assured everything as been written on disk. That way, we may stat the file
  952. X# without closing it (since that would release any flock-style lock).
  953. Xsub force_flushing {
  954. X    local(*FD) = @_;            # File descriptor we want to flush
  955. X    select((select(FD), $| = 1)[0]);
  956. X}
  957. X
  958. X# Guess whether the folder we are writing to is MMDF-style or not.
  959. Xsub is_mmdf {
  960. X    local($folder) = @_;        # The folder to be scanned
  961. X    open(FOLDER, "$folder") || return 0;    # Can't open -> not MMDF, say.
  962. X    local($_);                    # First line from folder
  963. X    $_ = <FOLDER>;                # Can be empty
  964. X    close FOLDER;
  965. X    return 0 if /^From\s/;            # Looks like an Unix-style mailbox
  966. X    return 1 if /^\01\01\01\01\n/;    # This must be an MMDF-style mailbox
  967. X    # If we can't decide (most probably because $_ is empty), then choose
  968. X    # according to the 'mmdfbox' parameter.
  969. X    &'add_log("WARNING folder $folder may be corrupted")
  970. X        if $_ ne '' && $'loglvl > 5;
  971. X    $cf'mmdfbox =~ /on/i ? 1 : 0;    # Force MMDF if mmdfbox is ON
  972. X}
  973. X
  974. Xpackage main;
  975. X
  976. END_OF_FILE
  977.   if test 4318 -ne `wc -c <'agent/pl/mmdf.pl'`; then
  978.     echo shar: \"'agent/pl/mmdf.pl'\" unpacked with wrong size!
  979.   fi
  980.   # end of 'agent/pl/mmdf.pl'
  981. fi
  982. if test -f 'agent/pl/read_conf.pl' -a "${1}" != "-c" ; then 
  983.   echo shar: Will not clobber existing file \"'agent/pl/read_conf.pl'\"
  984. else
  985.   echo shar: Extracting \"'agent/pl/read_conf.pl'\" \(4166 characters\)
  986.   sed "s/^X//" >'agent/pl/read_conf.pl' <<'END_OF_FILE'
  987. X;# $Id: read_conf.pl,v 3.0 1993/11/29 13:49:12 ram Exp ram $
  988. X;#
  989. X;#  Copyright (c) 1990-1993, Raphael Manfredi
  990. X;#  
  991. X;#  You may redistribute only under the terms of the Artistic License,
  992. X;#  as specified in the README file that comes with the distribution.
  993. X;#  You may reuse parts of this distribution only within the terms of
  994. X;#  that same Artistic License; a copy of which may be found at the root
  995. X;#  of the source tree for mailagent 3.0.
  996. X;#
  997. X;# $Log: read_conf.pl,v $
  998. X;# Revision 3.0  1993/11/29  13:49:12  ram
  999. X;# Baseline for mailagent 3.0 netwide release.
  1000. X;#
  1001. X;#
  1002. Xpackage cf;
  1003. X
  1004. X# This package is responsible for keeping track of the configuration variables.
  1005. X
  1006. X# Read configuration file (usually in ~/.mailagent)
  1007. Xsub main'read_config {
  1008. X    local($file) = @_;                # where config file is located
  1009. X    local($_);
  1010. X    $file = '~/.mailagent' unless $file;
  1011. X    local($myhome) = $ENV{'HOME'};    # must be correctly set by filter
  1012. X    $file =~ s/~/$myhome/;            # ~ substitution
  1013. X    local($main'config) = $file;    # Save it: could be modified by config
  1014. X    open(CONFIG, "$file") ||
  1015. X        &'fatal("can't open config file $file");
  1016. X    local($config) = ' ' x 2000;    # pre-extend to avoid realloc()
  1017. X    $config = '';
  1018. X    while (<CONFIG>) {
  1019. X        next if /^[ \t]*#/;            # skip comments
  1020. X        next if /^[ \t]*\n/;        # skip empy lines
  1021. X        $config .= $_;
  1022. X    }
  1023. X    &parse($config) || &'fatal('bad configuration');
  1024. X    close CONFIG;
  1025. X
  1026. X    # Security checks, pending of those performed by the C filter. They are
  1027. X    # somewhat necessary, even though the mailagent does not run setuid
  1028. X    # (because anybody may activate the mailagent for any user by sending him
  1029. X    # a mail, and world writable configuration files makes the task too easy
  1030. X    # for a potential hacker). The tests are performed once the configuration
  1031. X    # file has been parsed, so logging of fatal errors may occur.
  1032. X
  1033. X    local($unsecure) = 0;
  1034. X
  1035. X    $unsecure++ unless &'file_secure($'config, 'config');
  1036. X    $unsecure++ unless &'file_secure($rules, 'rule');
  1037. X    &'fatal("unsecure configuration!") if $unsecure;
  1038. X
  1039. X    return unless -f "$rules";        # No rule file
  1040. X}
  1041. X
  1042. X# Parse config file held in variable and return 1 if ok, 0 for errors
  1043. Xsub parse {
  1044. X    local($config) = @_;
  1045. X    local($eval) = ' ' x 1000;        # Pre-extend
  1046. X    local($myhome) = $ENV{'HOME'};    # must be correctly set by filter
  1047. X    local($var, $value);
  1048. X    local($_);
  1049. X    $eval = '';
  1050. X    foreach (split(/\n/, $config)) {
  1051. X        if (/^[ \t]*([^ \t\n:\/]*)[ \t]*:[ \t]*([^#\n]*)/) {
  1052. X            $var = $1;
  1053. X            $value = $2;
  1054. X            $value =~ s/\s*$//;                        # remove trailing spaces
  1055. X            $eval .= "\$$var = \"$value\";\n";
  1056. X            $eval .= "\$$var =~ s|~|$myhome|g;\n";    # ~ substitution
  1057. X        }
  1058. X    }
  1059. X    eval $eval;            # evaluate configuration parameters within package
  1060. X
  1061. X    if ($@ ne '') {                # Parsing error detected
  1062. X        local($error) = $@;        # Logged error
  1063. X        local($*) = 1;
  1064. X        $error = (split(/\n/, $error))[0];        # Keep only first line
  1065. X        # Dump error message on stderr, as well as faulty configuration file.
  1066. X        # The original is restored out of the perl form to avoid surprise.
  1067. X        $eval =~ s/^\$.* =~ s\|~\|.*\n//g;        # Remove added ~ substitutions
  1068. X        $eval =~ s/^\$//g;                        # Remove leading '$'
  1069. X        $eval =~ s/ = "(.*)";/: $1/g;            # Keep only variable value
  1070. X        chop($eval);
  1071. X        print STDERR <<EOM;
  1072. X**** Syntax error in configuration:
  1073. X$error
  1074. X
  1075. X---- Begin of Faulty Configuration
  1076. X$eval
  1077. X---- End of Faulty Configuration
  1078. X
  1079. XEOM
  1080. X        &'add_log("syntax error in configuration: $error") if $'loglvl > 1;
  1081. X        return 0;
  1082. X    }
  1083. X
  1084. X    # Define the mailagent parameters from those in config file
  1085. X    $logfile = $logdir . "/$log";
  1086. X    $seqfile = $spool . "/$seq";
  1087. X    $hashdir = $spool . "/$hash";
  1088. X    $main'loglvl = int($level);        # This one is visible in the main package
  1089. X    $main'track_all = 1 if $track =~ /on/i;        # Option -t set by config
  1090. X    $sendmail = $'mailer if $sendmail eq '';    # No sendmail program specified
  1091. X    $sendnews = $'inews if $sendnews eq '';        # No news posting program
  1092. X    $mailopt = '-odq' if $mailopt eq '' && $sendmail =~ /sendmail/;
  1093. X
  1094. X    # Update @INC perlib search path with the perlib variable. Paths not
  1095. X    # starting by a '/' are supposed to be under the mailagent private lib
  1096. X    # directory.
  1097. X
  1098. X    if (defined $perlib) {
  1099. X        foreach (split(':', $perlib)) {
  1100. X            s/^~/$home/;
  1101. X            $_ = $'privlib . '/' . $_ unless m|^/|;
  1102. X            push(@INC, $_);
  1103. X        }
  1104. X    }
  1105. X
  1106. X    1;        # Ok
  1107. X}
  1108. X
  1109. Xpackage main;
  1110. X
  1111. END_OF_FILE
  1112.   if test 4166 -ne `wc -c <'agent/pl/read_conf.pl'`; then
  1113.     echo shar: \"'agent/pl/read_conf.pl'\" unpacked with wrong size!
  1114.   fi
  1115.   # end of 'agent/pl/read_conf.pl'
  1116. fi
  1117. if test -f 'agent/pl/rfc822.pl' -a "${1}" != "-c" ; then 
  1118.   echo shar: Will not clobber existing file \"'agent/pl/rfc822.pl'\"
  1119. else
  1120.   echo shar: Extracting \"'agent/pl/rfc822.pl'\" \(4527 characters\)
  1121.   sed "s/^X//" >'agent/pl/rfc822.pl' <<'END_OF_FILE'
  1122. X;# $Id: rfc822.pl,v 3.0 1993/11/29 13:49:13 ram Exp ram $
  1123. X;#
  1124. X;#  Copyright (c) 1990-1993, Raphael Manfredi
  1125. X;#  
  1126. X;#  You may redistribute only under the terms of the Artistic License,
  1127. X;#  as specified in the README file that comes with the distribution.
  1128. X;#  You may reuse parts of this distribution only within the terms of
  1129. X;#  that same Artistic License; a copy of which may be found at the root
  1130. X;#  of the source tree for mailagent 3.0.
  1131. X;#
  1132. X;# $Log: rfc822.pl,v $
  1133. X;# Revision 3.0  1993/11/29  13:49:13  ram
  1134. X;# Baseline for mailagent 3.0 netwide release.
  1135. X;#
  1136. X;#
  1137. X;# The following routines do some parsing on RFC822 headers (such as the
  1138. X;# ones provided by sendmail).
  1139. X;#
  1140. X
  1141. X# Parse an address and returns (internet, comment)
  1142. X# Examples:
  1143. X#    ram@eiffel.com (Raphael Manfredi)  -> (ram@eiffel.com, Raphael Manfredi)
  1144. X#    Raphael Manfredi <ram@eiffel.com>  -> (ram@eiffel.com, Raphael Manfredi)
  1145. X# Note that we try to parse malformed RFC822 addresses to the best we can, by
  1146. X# giving priority to anything between <> for correct e-mail address detection.
  1147. X# Common errors include having a '<>' construct as part of the comment attached
  1148. X# to the address as "name <surname> lastname", but this can only be followed
  1149. X# by a <> address and the regexp is built so that it will skip the first <>
  1150. X# and match only the last one on the line.
  1151. Xsub parse_address {
  1152. X    local($_) = shift(@_);        # The address to be parsed
  1153. X    local($comment);
  1154. X    local($internet);
  1155. X    if (/^\s*(.*)\s+<(\S+)>[^()]*$/) {        # comment <address>
  1156. X        $comment = $1;
  1157. X        $internet = $2;
  1158. X        $comment =~ s/^"(.*)"/$1/;            # "comment" -> comment
  1159. X        ($internet, $comment);
  1160. X    } elsif (/^\s*([^()]+)\s+\((.*)\)/) {    # address (comment) 
  1161. X        $comment = $2;
  1162. X        $internet = $1;
  1163. X        # Construct '<address> (comment)' is invalid but... priority to <>
  1164. X        # This will also take care of "comment" <address> (other-comment)
  1165. X        $internet =~ /<(\S+)>/ && ($internet = $1);
  1166. X        ($internet, $comment);
  1167. X    } elsif (/^\s*<(\S+)>\s*(.*)/) {        # <address> ...garbage...
  1168. X        ($1, $2);
  1169. X    } elsif (/^\s*\((.*)\)\s+<?(.*)>?/) {    # (comment) [address or <address>]
  1170. X        ($2, $1);
  1171. X    } else {                                # plain address, grab first word
  1172. X        /^\s*(\S+)\s*(.*)/;
  1173. X        ($1, $2);
  1174. X    }
  1175. X}
  1176. X
  1177. X# Parses an internet address and returns the login name of the sender. When
  1178. X# facing an RFC 822 group addressing (like To: group:;), it returns the group
  1179. X# name.
  1180. Xsub login_name {
  1181. X    local($_) = shift(@_);                # The internet address
  1182. X    if (/^(\S+):;/) {                    # rfc-822-group:;
  1183. X        &last_name($1);
  1184. X    } elsif (s/^"(\S+)"@\S+/$1/) {        # "user@domain"@other
  1185. X        &login_name($_);                # parse user@domain
  1186. X    } elsif (s/^(\S+)@\S+/$1/) {        # user@domain.name
  1187. X        &login_name($_);                # parse user
  1188. X    } elsif (s/^(\S+)%\S+/$1/) {        # user%domain.name
  1189. X        &login_name($_);                # parse user
  1190. X    } elsif (s/^\S+!(\S+)/$1/) {        # ...!backbone!user
  1191. X        &last_name($_);                    # user can only be a simple name
  1192. X    } else {                            # everything else must be a single name
  1193. X        &last_name($_);                    # keep only last name
  1194. X    }
  1195. X}
  1196. X
  1197. X# Extract last name from a login name like First_name.Last_name and put it
  1198. X# in lowercase. Hence, Raphael.Manfredi will become manfredi. Since '_' or '.'
  1199. X# characters could be legitimely used in a login name (or distribution list),
  1200. X# we remove it only when followed by an upper-cased letter.
  1201. Xsub last_name {
  1202. X    local($_) = shift(@_);            # The sender's login name
  1203. X    s/.*\.([A-Z]\w*)/$1/;            # Keep only the last name (. separation)
  1204. X    s/.*_([A-Z]\w*)/$1/;            # Same as above (_ separation)
  1205. X    tr/A-Z/a-z/;                    # And lowercase it
  1206. X    $_;
  1207. X}
  1208. X
  1209. X# Parse an e-mail address and return a three element array:
  1210. X#   ($host, $domain, $country)
  1211. Xsub internet_info {
  1212. X    local($_) = shift(@_);                # The internet address
  1213. X    local($login) = &login_name($_);    # Get the address login name
  1214. X    local($internet);                    # The internet part of the address
  1215. X    # Try with uucp form first, to detect things like eiffel!ram@inria.fr
  1216. X    # We use the login name to anchor the last '!' or the first '@' or '%'
  1217. X    ($internet) = /([^!]*)!$login/i;
  1218. X    ($internet) = /$login[@%]([\w.-]*)/i unless $internet;
  1219. X    $internet =~ tr/A-Z/a-z/;                # Always lower-cased
  1220. X    local(@parts) = split(/\./, $internet);    # Break on dots
  1221. X    if (@parts == 1) {                        # Only a host name
  1222. X        # Maybe this is a local address, maybe this is a uucp name. Assume that
  1223. X        # it is local if there is an '@' sign, as in 'ram@lyon'. Otherwise, it
  1224. X        # is a uucp name, as in 'eiffel!ram'.
  1225. X        push(@parts, 'uucp') if /!$login/;    # UUCP name
  1226. X        push(@parts, split(/\./, $mydomain)) if @parts == 1;
  1227. X    }
  1228. X    unshift(@parts, '') if @parts == 2;        # No host name
  1229. X    @parts[($#parts - 2) .. $#parts];        # ($host, $domain, $country)
  1230. X}
  1231. X
  1232. END_OF_FILE
  1233.   if test 4527 -ne `wc -c <'agent/pl/rfc822.pl'`; then
  1234.     echo shar: \"'agent/pl/rfc822.pl'\" unpacked with wrong size!
  1235.   fi
  1236.   # end of 'agent/pl/rfc822.pl'
  1237. fi
  1238. if test -f 'agent/test/TEST' -a "${1}" != "-c" ; then 
  1239.   echo shar: Will not clobber existing file \"'agent/test/TEST'\"
  1240. else
  1241.   echo shar: Extracting \"'agent/test/TEST'\" \(4682 characters\)
  1242.   sed "s/^X//" >'agent/test/TEST' <<'END_OF_FILE'
  1243. X: # feed this into perl
  1244. X    eval 'exec perl -S $0 "$@"'
  1245. X        if $running_under_some_shell;
  1246. X
  1247. X# $Id: TEST,v 3.0 1993/11/29 13:49:22 ram Exp ram $
  1248. X#
  1249. X#  Copyright (c) 1990-1993, Raphael Manfredi
  1250. X#  
  1251. X#  You may redistribute only under the terms of the Artistic License,
  1252. X#  as specified in the README file that comes with the distribution.
  1253. X#  You may reuse parts of this distribution only within the terms of
  1254. X#  that same Artistic License; a copy of which may be found at the root
  1255. X#  of the source tree for mailagent 3.0.
  1256. X#
  1257. X# $Log: TEST,v $
  1258. X# Revision 3.0  1993/11/29  13:49:22  ram
  1259. X# Baseline for mailagent 3.0 netwide release.
  1260. X#
  1261. X
  1262. Xchop($pwd = `pwd`);
  1263. X$ENV{'HOME'} = "$pwd/out";
  1264. Xchop($host = `(hostname 2>/dev/null || uname -n) 2>/dev/null`);
  1265. X$host =~ s/^([^.]*)\..*/$1/;    # Trim domain name
  1266. X$ENV{'HOST'} = $host;
  1267. X$ENV{'USER'} = 'nobody';    # In case we get mails back from RUN and friends
  1268. X$ENV{'PWD'} = $pwd;
  1269. X$ENV{'LEVEL'} = 0;            # Default loglvl for filter and cmd tests
  1270. X
  1271. X@tests = ('basic', 'option', 'filter', 'cmd', 'misc');
  1272. X$failed = 0;
  1273. X$how_many = 0;
  1274. X
  1275. Xrequire 'getopt.pl';
  1276. X&Getopt;
  1277. X
  1278. X$mailagent = 'mailagent';            # Default program (dataloaded version)
  1279. X$mailagent = 'magent' if $opt_n;    # Use non-dataloaded version
  1280. X$ENV{'MAILAGENT'} = $mailagent;
  1281. X$ENV{'PATH'} = "$pwd/..:" . $ENV{'PATH'};
  1282. X
  1283. X-f "../$mailagent" && -x _ || die "No $mailagent.\n";
  1284. X-f '../filter/filter' && -x _ || die "No filter.\n";
  1285. X$> || die "Cannot run tests as super-user.\n";
  1286. X
  1287. X&load_ok;        # Don't rerun successful tests if up to date
  1288. X
  1289. X# A level file indicates default loglvl
  1290. Xif (-f 'level') {
  1291. X    chop($level = `cat level`);
  1292. X    $ENV{'LEVEL'} = int($level);
  1293. X}
  1294. X
  1295. Xunless (-f 'OK') {
  1296. X    %Ok = ();
  1297. X    `rm -rf out` if -d 'out';
  1298. X}
  1299. X
  1300. Xumask 022;        # Ensure none of the files are world writable
  1301. X
  1302. X`mkdir out` unless -d 'out';
  1303. X
  1304. Xselect(STDOUT);
  1305. X$| = 1;
  1306. Xopen(OK, ">>OK");
  1307. Xselect(OK);
  1308. X$| = 1;        # We may safely interrupt
  1309. Xselect(STDOUT);
  1310. X
  1311. Xforeach $dir (@tests) {
  1312. X    next unless -d $dir;
  1313. X    &run($dir);
  1314. X}
  1315. X
  1316. X# Summarize what happened
  1317. X
  1318. Xclose OK;
  1319. X
  1320. Xif ($failed == 0) {
  1321. X    print "All tests successful.\n";
  1322. X} else {
  1323. X    print "Failed $how_many test", $how_many == 1 ? '' : 's';
  1324. X    print " from $failed file", $failed == 1 ? '' : 's', ".\n";
  1325. X}
  1326. X
  1327. X&clean_up;
  1328. Xexit 0;        # End of tests
  1329. X
  1330. X#
  1331. X# Subroutines
  1332. X#
  1333. X
  1334. Xsub clean_up {
  1335. X    return if $failed || $opt_i;    # -i asks for incrementality
  1336. X    unlink 'OK';
  1337. X    `rm -rf out` if -d 'out';
  1338. X}
  1339. X
  1340. Xsub print {
  1341. X    local($dir, $file) = @_;
  1342. X    $file =~ s/\.t$//;
  1343. X    local($len) = 1 + length($dir) + length($file);
  1344. X    print "$dir/$file", '.' x (17 - $len);
  1345. X}
  1346. X
  1347. Xsub num { $a <=> $b; }
  1348. X
  1349. Xsub result {
  1350. X    local($test, $output) = @_;
  1351. X    local($now) = time;
  1352. X    local(@res) = split(/\n/, $output);    # Failed test numbers
  1353. X    if ($res[0] eq '') {
  1354. X        print "FAILED (no test run)\n";
  1355. X        ++$failed;
  1356. X    } elsif ($res[$#res] == 0 && $#res > 0 && $res[$#res -1] == $#res) {
  1357. X        print "FAILED (all tests)\n";
  1358. X        ++$failed;
  1359. X        $how_many += $#res;
  1360. X    } elsif ($res[0] == 0) {
  1361. X        print "ok\n";
  1362. X        print OK "$test $now\n";
  1363. X    } elsif ($res[0] == -1) {
  1364. X        print "untested\n";
  1365. X    } else {
  1366. X        # Program outputs the number of each test failed, and last must be 0
  1367. X        local($last) = pop(@res);
  1368. X        push(@res, $last) unless $last == 0;
  1369. X        local($n) = @res + 0;
  1370. X        local($s) = $n == 1 ? '' : 's';
  1371. X        print "FAILED ($n test$s:";
  1372. X        @res = sort num @res;
  1373. X        print ' ', join(',', @res);
  1374. X        print " and aborted" unless $last == 0;
  1375. X        print ")\n";
  1376. X        ++$failed;
  1377. X        $how_many += $n;
  1378. X    }
  1379. X    if ($failed && $opt_s) {    # Stop at first error if -s
  1380. X        print "Aborted tests.\n";
  1381. X        exit 0;
  1382. X    }
  1383. X}
  1384. X
  1385. Xsub run {
  1386. X    local($dir) = @_;
  1387. X    chdir $dir || die "Cannot chdir to $dir: $!\n";
  1388. X    local(@files) = <*.t>;
  1389. X    local($test);
  1390. X    local($output);
  1391. X    foreach $file (@files) {
  1392. X        &print($dir, $file);
  1393. X        $test = "$dir/$file";
  1394. X        if ($Ok{$test} >= ((stat($file))[9])) {    # Check time stamp
  1395. X            print "done\n";
  1396. X            next;
  1397. X        }
  1398. X        $output = `perl $file`;
  1399. X        &result($test, $output);
  1400. X        &basic_failed if $dir eq 'basic' && $failed;
  1401. X    }
  1402. X    chdir '..' || die "Cannot chdir back to ..: $!\n";
  1403. X}
  1404. X
  1405. Xsub basic_failed {
  1406. X    print "Failed a basic test, cannot continue.\n";
  1407. X    unlink 'OK';
  1408. X    exit 0;
  1409. X}
  1410. X
  1411. Xsub load_ok {
  1412. X    return unless -f 'OK';
  1413. X
  1414. X    # Make sure the OK file is up to date, unless -o (outdated)
  1415. X    unless ($opt_o) {
  1416. X        local($ok_mtime) = (stat('OK'))[9];
  1417. X        local($ma_mtime) = (stat("../$mailagent"))[9];
  1418. X        local($fi_mtime) = (stat('../filter/filter'))[9];
  1419. X        local($restart) = 0;
  1420. X        if ($ma_mtime > $ok_mtime) {
  1421. X            warn "Mailagent has changed, restarting tests...\n";
  1422. X            ++$restart;
  1423. X        } elsif ($fi_mtime > $ok_mtime) {
  1424. X            warn "Filter has changed, restarting tests...\n";
  1425. X            ++$restart;
  1426. X        }
  1427. X        unlink 'OK' if $restart;
  1428. X    }
  1429. X
  1430. X    return unless -f 'OK';
  1431. X    local($file, $when);
  1432. X    open(OK, 'OK') || return;
  1433. X    while (<OK>) {
  1434. X        chop;
  1435. X        ($file, $when) = /^(\S+)\s+(\d+)/;
  1436. X        $Ok{$file} = $when if $when;
  1437. X    }
  1438. X    close OK;
  1439. X
  1440. X}
  1441. X
  1442. END_OF_FILE
  1443.   if test 4682 -ne `wc -c <'agent/test/TEST'`; then
  1444.     echo shar: \"'agent/test/TEST'\" unpacked with wrong size!
  1445.   fi
  1446.   chmod +x 'agent/test/TEST'
  1447.   # end of 'agent/test/TEST'
  1448. fi
  1449. if test -f 'agent/test/level' -a "${1}" != "-c" ; then 
  1450.   echo shar: Will not clobber existing file \"'agent/test/level'\"
  1451. else
  1452.   echo shar: Extracting \"'agent/test/level'\" \(2 characters\)
  1453.   sed "s/^X//" >'agent/test/level' <<'END_OF_FILE'
  1454. X0
  1455. END_OF_FILE
  1456.   if test 2 -ne `wc -c <'agent/test/level'`; then
  1457.     echo shar: \"'agent/test/level'\" unpacked with wrong size!
  1458.   fi
  1459.   # end of 'agent/test/level'
  1460. fi
  1461. if test -f 'agent/test/rules' -a "${1}" != "-c" ; then 
  1462.   echo shar: Will not clobber existing file \"'agent/test/rules'\"
  1463. else
  1464.   echo shar: Extracting \"'agent/test/rules'\" \(4703 characters\)
  1465.   sed "s/^X//" >'agent/test/rules' <<'END_OF_FILE'
  1466. X#
  1467. X# Mailagent rules for filter regression tests
  1468. X#
  1469. X
  1470. X# $Id: rules,v 3.0 1993/11/29 13:50:27 ram Exp ram $
  1471. X#
  1472. X#  Copyright (c) 1990-1993, Raphael Manfredi
  1473. X#  
  1474. X#  You may redistribute only under the terms of the Artistic License,
  1475. X#  as specified in the README file that comes with the distribution.
  1476. X#  You may reuse parts of this distribution only within the terms of
  1477. X#  that same Artistic License; a copy of which may be found at the root
  1478. X#  of the source tree for mailagent 3.0.
  1479. X#
  1480. X# $Log: rules,v $
  1481. X# Revision 3.0  1993/11/29  13:50:27  ram
  1482. X# Baseline for mailagent 3.0 netwide release.
  1483. X#
  1484. X
  1485. Xmaildir = ~;
  1486. Xmailfilter = ~;
  1487. X
  1488. XSubject: /test/        { DELETE };
  1489. X
  1490. X# filter/default
  1491. XX-Tag: /default #1/ { DELETE };
  1492. XX-Tag: /default #2/ { NOP };
  1493. XX-Tag: /unknown/     { UNKNOWN };
  1494. X
  1495. X# filter/loop
  1496. XX-Tag: /loop #1/            { BEGIN LOOP; RESTART };
  1497. XX-Tag: /loop #2/            { DELETE };
  1498. X
  1499. X# filter/multiple
  1500. XX-None Subject To X-Tag: /multiple #1/            { SAVE %u.1 };
  1501. XX-None X-Tag: /multiple #2/, X-Other: /another/,
  1502. XTo Cc: root, Cc To: ram                            { SAVE %u.3; REJECT MULTIPLE };
  1503. X<MULTIPLE> X-Non-Existent: *                    { SAVE %u.2 };
  1504. XX-Tag: /multiple #2/, X-Other: /multiple #2/    { SAVE %u.2 };
  1505. X
  1506. X# filter/list
  1507. XX-Tag: /list/                    { BEGIN LIST; REJECT };
  1508. X<LIST> To: ram                    { SAVE %u.1 };
  1509. X<LIST> To: max                    { SAVE %u.2 };
  1510. X<LIST> To: /^root@eiffel.com$/    { SAVE %u.3 };
  1511. X<LIST> To: /^riot@eiffel.co$/    { DELETE };
  1512. X<LIST> To: /^riot@eiffel.com$/    { SAVE %u.4 };
  1513. X<LIST> To: /^riot/                { SAVE %u.5 };
  1514. X<LIST> To: /riot/                { SAVE %u.6 };
  1515. X<LIST> Newsgroups: news.lists    { SAVE %u.7 };
  1516. X<LIST> To: !ram                    { SAVE %u.8 };
  1517. X
  1518. X# filter/pattern
  1519. XX-T.*: "pattern-list"            { BEGIN PAT; REJECT };
  1520. X<PAT> .*Re[^\-]*$: *, ^Sub*: *    { RUN /bin/echo '%&' > macro; DELETE };
  1521. X
  1522. X# filter/backref
  1523. XX-Tag: /^back(.*) #1/,
  1524. XSubject: /Re:\s+(\w+)\s+ice\s+(\w+)/,
  1525. XFrom: /(.*)compilers/,
  1526. XFrom: /com(.*)rs/,
  1527. XTo: /^(\w+)@(\S+)/        { RUN /bin/echo '%1,%4,%5@%6,%2 %3' > output; DELETE };
  1528. X
  1529. XX-Tag: /^back.* #2/,
  1530. XNewsgroups:
  1531. X    /(comp.lang.perl)/,
  1532. X    /(comp.unix.wizards)/,
  1533. X    /(comp.mail.mh)/    { SAVE %1 };
  1534. X
  1535. X# filter/escape
  1536. XX-Tag: /escape/            { RUN /bin/echo '\;,\\\;,\\,\w' > output; DELETE };
  1537. X
  1538. X# filter/mode
  1539. XX-Tag: /mode/            { REJECT MODE };
  1540. X<MODE, !INITIAL>        { SAVE always; REJECT };
  1541. X<MODE>                    { SAVE always.2; REJECT };
  1542. X<!NOSUCH,!BADMODE> X-Tag: /mode/    { SAVE always.3; REJECT };
  1543. X<!MODE> X-Tag: /mode/                { SAVE never; REJECT };
  1544. X<MODE>                    { DELETE };
  1545. X
  1546. X# filter/not
  1547. XX-Tag: /not #1/            { BEGIN NOT; REJECT };
  1548. X<NOT> To: !ram            { SAVE never };
  1549. X<NOT> To: !/ram@eiffel/    { SAVE never };
  1550. X<NOT> To: !/^ram/i        { SAVE never };
  1551. X<NOT> To: /^ram/i                { SAVE always; REJECT };
  1552. X<NOT> To: !/^root/i                { SAVE always.2; REJECT };
  1553. X<NOT> X-Tag: !"pattern-list"    { SAVE always.3 };
  1554. X
  1555. XX-Tag: /not #2/,
  1556. X!To: !ram,
  1557. XTo: !compilers,
  1558. X!From: root                { SAVE always };
  1559. X
  1560. X# filter/group
  1561. XX-Tag: /group/            { BEGIN GROUP; REJECT };
  1562. X<GROUP> !To !From: ram    { SAVE never };
  1563. X<GROUP> To !From: !ram    { SAVE never };
  1564. X<GROUP> !To !From: ram,
  1565. X    !Subject !From: ram        { SAVE never };
  1566. X<GROUP> !To: root, ram        { SAVE never };
  1567. X<GROUP> !F.*: /compiler/    { SAVE never };
  1568. X<GROUP> !From: ram, !To: ram    { SAVE always; REJECT };
  1569. X<GROUP> From: ram, To: ram        { SAVE never };
  1570. X<GROUP> From: /compiler/,
  1571. X    !From: ram, !From: !/compiler/    { SAVE always.2; REJECT };
  1572. X<GROUP> From !Cc !To: /compiler/,
  1573. X    From !Cc !To: ram,
  1574. X    !From To Cc: /eiffel/,
  1575. X    !From To Cc: !/ice/            { SAVE always.3 };
  1576. X
  1577. X# filter/case
  1578. XX-Tag: case, Cc: root    { STRIP Cc; SAVE always };
  1579. X
  1580. X# filter/status
  1581. XX-Tag: /status/    { REJECT -t STATUS };
  1582. X<STATUS> { RUN ../no/such/file; REJECT -t; SAVE always; REJECT -t; SAVE never };
  1583. X<STATUS> { RUN ../this/does/not/exist; REJECT -f; SAVE never };
  1584. X<STATUS> { RUN ../nor/does/this; REJECT -t; REJECT -t; REJECT -f; SAVE never };
  1585. X<STATUS> { SAVE always.2; REJECT -f; BEGIN INITIAL; REJECT -t };
  1586. X<INITIAL> X-Tag: /status/    { SAVE always.3 };
  1587. X
  1588. X# filter/hook
  1589. XX-Tag: /hook #(\d)/        { SAVE hook.%1; ABORT -t; SAVE never };
  1590. X
  1591. X# filter/range
  1592. XX-Tag: /range/            { BEGIN RANGE; REJECT };
  1593. X<RANGE> From <2, 4>: /compiler/    { SAVE always; REJECT };
  1594. X<RANGE> To Cc: made                { SAVE always.2; REJECT };
  1595. X<RANGE> To Cc <1, 1>: made        { SAVE never; REJECT };
  1596. X<RANGE> To Cc <1, 2>: must        { SAVE always.3; REJECT };
  1597. X<RANGE> To Cc <3, 1>: ram        { SAVE never.2; REJECT };
  1598. X<RANGE> Body <-, 3>: /SIGPLAN/    { SAVE never.3; REJECT };
  1599. X<RANGE> Body <-, ->: /SIGPLAN/    { SAVE always.4; REJECT };
  1600. X<RANGE> Body <9, 9>: /SIGPLAN/    { SAVE always.5; REJECT };
  1601. X<RANGE> Body <9, 9>: /CD-ROM/        { SAVE never.4; REJECT };
  1602. X<RANGE> Body <13, 14>: /something/    { SAVE always.6; REJECT };
  1603. X<RANGE> Body <-3, ->: /Regards/        { SAVE always.7; REJECT };
  1604. X<RANGE> Cc <-1, ->: made            { SAVE always.8; REJECT };
  1605. X<RANGE> Body <-3, ->: /request/        { SAVE never.5; REJECT };
  1606. X<RANGE> Cc <-1, ->: must            { SAVE never.6 };
  1607. X<RANGE>                             { DELETE };
  1608. X
  1609. END_OF_FILE
  1610.   if test 4703 -ne `wc -c <'agent/test/rules'`; then
  1611.     echo shar: \"'agent/test/rules'\" unpacked with wrong size!
  1612.   fi
  1613.   # end of 'agent/test/rules'
  1614. fi
  1615. if test -f 'install.SH' -a "${1}" != "-c" ; then 
  1616.   echo shar: Will not clobber existing file \"'install.SH'\"
  1617. else
  1618.   echo shar: Extracting \"'install.SH'\" \(3974 characters\)
  1619.   sed "s/^X//" >'install.SH' <<'END_OF_FILE'
  1620. Xcase $CONFIG in
  1621. X'')
  1622. X    if test -f config.sh; then TOP=.;
  1623. X    elif test -f ../config.sh; then TOP=..;
  1624. X    elif test -f ../../config.sh; then TOP=../..;
  1625. X    elif test -f ../../../config.sh; then TOP=../../..;
  1626. X    elif test -f ../../../../config.sh; then TOP=../../../..;
  1627. X    else
  1628. X        echo "Can't find config.sh."; exit 1
  1629. X    fi
  1630. X    . $TOP/config.sh
  1631. X    ;;
  1632. Xesac
  1633. Xcase "$0" in
  1634. X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
  1635. Xesac
  1636. Xecho "Extracting install (with variable substitutions)"
  1637. X$spitshell >install <<!GROK!THIS!
  1638. X$startsh
  1639. X# @(#) Installing script accepting bsd-style arguments
  1640. X
  1641. X# $Id: install.SH,v 3.0 1993/11/29 13:50:29 ram Exp ram $
  1642. X#
  1643. X#  Copyright (c) 1990-1993, Raphael Manfredi
  1644. X#  
  1645. X#  You may redistribute only under the terms of the Artistic License,
  1646. X#  as specified in the README file that comes with the distribution.
  1647. X#  You may reuse parts of this distribution only within the terms of
  1648. X#  that same Artistic License; a copy of which may be found at the root
  1649. X#  of the source tree for mailagent 3.0.
  1650. X#
  1651. X# $Log: install.SH,v $
  1652. X# Revision 3.0  1993/11/29  13:50:29  ram
  1653. X# Baseline for mailagent 3.0 netwide release.
  1654. X#
  1655. X
  1656. Xchown='$chown'
  1657. Xchmod='$chmod'
  1658. Xchgrp='$chgrp'
  1659. Xrm='$rm'
  1660. Xmv='$mv'
  1661. Xtest='$test'
  1662. Xsed='$sed'
  1663. X!GROK!THIS!
  1664. X$spitshell >>install <<'!NO!SUBS!'
  1665. X
  1666. Xmode=""
  1667. Xdst=""
  1668. Xsrc=""
  1669. Xdostrip=""
  1670. Xnewdir=""
  1671. Xuid=""
  1672. Xgid=""
  1673. X
  1674. X# simulates mkdir -p
  1675. Xmkdir_p='
  1676. Xname=$1;
  1677. Xcreate="";
  1678. Xwhile $test $name; do
  1679. X    if $test ! -d "$name"; then
  1680. X        create="$name $create";
  1681. X        name=`echo $name | $sed -e "s|^[^/]*$||"`;
  1682. X        name=`echo $name | $sed -e "s|\(.*\)/.*|\1|"`;
  1683. X    else
  1684. X        name="";
  1685. X    fi;
  1686. Xdone;
  1687. Xfor file in $create; do
  1688. X    mkdir $file && $test $verbose &&
  1689. X    echo "install: created directory $file" >&2;
  1690. Xdone
  1691. X'
  1692. X
  1693. Xverbose=''
  1694. X
  1695. Xwhile $test x$1 != x
  1696. Xdo
  1697. X    case $1 in 
  1698. X    -c) shift
  1699. X        continue
  1700. X        ;;
  1701. X    -m) mode="$2 "
  1702. X        shift
  1703. X        shift
  1704. X        continue
  1705. X        ;;
  1706. X    -o) uid="$2 "
  1707. X        shift
  1708. X        shift
  1709. X        continue
  1710. X        ;;
  1711. X    -g) gid="$2 "
  1712. X        shift
  1713. X        shift
  1714. X        continue
  1715. X        ;;
  1716. X    -s) dostrip="strip"
  1717. X        shift
  1718. X        continue
  1719. X        ;;
  1720. X    -d) newdir="$newdir$2 "
  1721. X        shift
  1722. X        shift
  1723. X        continue
  1724. X        ;;
  1725. X    -v) verbose='true'
  1726. X        shift
  1727. X        ;;
  1728. X    *) if $test x$src = x
  1729. X        then
  1730. X            src=$1
  1731. X        else
  1732. X            dst=$1
  1733. X        fi
  1734. X        shift
  1735. X        continue
  1736. X        ;;
  1737. X    esac
  1738. Xdone
  1739. X
  1740. X# if -d option is used, we have to create the path given
  1741. Xif $test ! x$newdir = x
  1742. Xthen
  1743. X    for i in $newdir
  1744. X    do
  1745. X        set x $i
  1746. X        shift
  1747. X        eval $mkdir_p
  1748. X    done
  1749. X    exit 0        # -d is the only action
  1750. Xfi
  1751. X
  1752. Xif $test x$src = x
  1753. Xthen
  1754. X    echo "install: no input file specified" >&2
  1755. X    exit 1
  1756. Xfi
  1757. X
  1758. Xif $test x$dst = x
  1759. Xthen
  1760. X    echo "install: no destination specified" >&2
  1761. X    exit 1
  1762. Xfi
  1763. X
  1764. Xsrcbase=`basename $src`
  1765. Xdstbase=`basename $dst`
  1766. X
  1767. X# If the destination is a directory, the target name is srcbase...
  1768. Xif $test -d $dst; then
  1769. X    dstbase=$srcbase
  1770. Xelse
  1771. X    dst="`echo $dst | sed 's,^\(.*\)/.*$,\1,'`"
  1772. X    if $test ! -d $dst; then
  1773. X        dstbase=$dst
  1774. X        dst="."
  1775. X    fi
  1776. Xfi
  1777. X
  1778. X# If the src has a directory, extract the dir name...
  1779. Xif $test "$src" != "$srcbase" -a "$src" != "./$srcbase"; then
  1780. X    src="`echo $src | sed 's,^\(.*\)/.*$,\1,'`"
  1781. Xelse
  1782. X    src="."
  1783. Xfi
  1784. X
  1785. X# dst is the destination directory and dstbase the base name.
  1786. X# srcbase is the base name of source and src the source dir.
  1787. X
  1788. Xsrcpth=`(cd $src; pwd)`/$srcbase
  1789. Xdestpth=`(cd $dst; pwd)`/$dstbase
  1790. Xif $test x$srcpth = x$destpth; then
  1791. X    $test $verbose && \
  1792. X    echo "install: destination and source are identical"
  1793. X    exit 0
  1794. Xfi
  1795. X
  1796. X# Do the install
  1797. X(
  1798. X    cd $src
  1799. X
  1800. X    if $test -f $dst/$dstbase; then
  1801. X        $rm -f $dst/$dstbase && $test $verbose &&
  1802. X        echo "install: $dst/$dstbase removed"
  1803. X    fi
  1804. X    if $test -f $dst/$dstbase; then
  1805. X        $mv $dst/$dstbase $dst/OLD$dstbase && $test $verbose &&
  1806. X        echo "install: $dst/$dstbase renamed as OLD$dstbase"
  1807. X    fi
  1808. X
  1809. X    cp $srcbase $dst/$dstbase && $test $verbose &&
  1810. X    echo "install: $srcbase installed as $dst/$dstbase"
  1811. X
  1812. X    if $test ! x$dostrip = x; then
  1813. X        strip $dst/$dstbase 2>/dev/null && $test $verbose &&
  1814. X        echo "install: stripped $dst/$dstbase"
  1815. X    fi
  1816. X
  1817. X    if $test ! x$uid = x; then
  1818. X        $chown $uid $dst/$dstbase
  1819. X    fi
  1820. X    if $test ! x$gid = x; then
  1821. X        $chgrp $gid $dst/$dstbase
  1822. X    fi
  1823. X    if $test ! x$mode = x
  1824. X    then
  1825. X        $chmod $mode $dst/$dstbase
  1826. X    fi
  1827. X)
  1828. X
  1829. Xexit 0
  1830. X!NO!SUBS!
  1831. Xchmod 755 install
  1832. X$eunicefix install
  1833. END_OF_FILE
  1834.   if test 3974 -ne `wc -c <'install.SH'`; then
  1835.     echo shar: \"'install.SH'\" unpacked with wrong size!
  1836.   fi
  1837.   chmod +x 'install.SH'
  1838.   # end of 'install.SH'
  1839. fi
  1840. echo shar: End of archive 19 \(of 26\).
  1841. cp /dev/null ark19isdone
  1842. MISSING=""
  1843. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ; do
  1844.     if test ! -f ark${I}isdone ; then
  1845.     MISSING="${MISSING} ${I}"
  1846.     fi
  1847. done
  1848. if test "${MISSING}" = "" ; then
  1849.     echo You have unpacked all 26 archives.
  1850.     echo "Now run 'sh PACKNOTES', then read README and type Configure.'"
  1851.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1852. else
  1853.     echo You still must unpack the following archives:
  1854.     echo "        " ${MISSING}
  1855. fi
  1856. exit 0
  1857.  
  1858. exit 0 # Just in case...
  1859.