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

  1. Newsgroups: comp.sources.misc
  2. From: ram@eiffel.com (Raphael Manfredi)
  3. Subject:  v33i107:  mailagent - Rule Based Mail Filtering, Part15/17
  4. Message-ID: <1992Nov20.231151.27892@sparky.imd.sterling.com>
  5. X-Md4-Signature: eb42251cefa5883e149313e85289360d
  6. Date: Fri, 20 Nov 1992 23:11:51 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: ram@eiffel.com (Raphael Manfredi)
  10. Posting-number: Volume 33, Issue 107
  11. Archive-name: mailagent/part15
  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/Jmakefile agent/examples/README agent/files/README
  19. #   agent/filter/README agent/filter/hash.h agent/filter/msg.c
  20. #   agent/filter/portable.h agent/filter/user.c agent/mailhelp.SH
  21. #   agent/pl/acs_rqst.pl agent/pl/history.pl agent/pl/mailhook.pl
  22. #   agent/pl/once.pl agent/pl/period.pl agent/pl/rfc822.pl
  23. #   agent/pl/unpack.pl agent/test/basic/config.t
  24. #   agent/test/basic/mailagent.t agent/test/cmd/assign.t
  25. #   agent/test/cmd/once.t agent/test/cmd/record.t
  26. #   agent/test/cmd/unique.t agent/test/cmd/write.t agent/test/mail
  27. #   agent/test/option/s.t
  28. # Wrapped by kent@sparky on Wed Nov 18 22:42:32 1992
  29. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  30. echo If this archive is complete, you will see the following message:
  31. echo '          "shar: End of archive 15 (of 17)."'
  32. if test -f 'agent/Jmakefile' -a "${1}" != "-c" ; then 
  33.   echo shar: Will not clobber existing file \"'agent/Jmakefile'\"
  34. else
  35.   echo shar: Extracting \"'agent/Jmakefile'\" \(1541 characters\)
  36.   sed "s/^X//" >'agent/Jmakefile' <<'END_OF_FILE'
  37. X/*
  38. X * Jmakefile for mailagent
  39. X */
  40. X
  41. X;# $Id: Jmakefile,v 2.9.1.2 92/08/26 12:33:22 ram Exp $
  42. X;#
  43. X;#  Copyright (c) 1991, Raphael Manfredi
  44. X;#
  45. X;#  You may redistribute only under the terms of the GNU General Public
  46. X;#  Licence as specified in the README file that comes with dist.
  47. X;#
  48. X;# $Log:    Jmakefile,v $
  49. X;# Revision 2.9.1.2  92/08/26  12:33:22  ram
  50. X;# patch8: new mailhook target, installed in private library directory
  51. X;# 
  52. X;# Revision 2.9.1.1  92/08/12  21:27:08  ram
  53. X;# patch6: mailagent is now built with offset table (perload -o)
  54. X;# 
  55. X;# Revision 2.9  92/07/14  16:47:06  ram
  56. X;# 3.0 beta baseline.
  57. X;# 
  58. X
  59. XBIN = mailpatch mailhelp maillist maildist
  60. X
  61. XNoManPages()
  62. XShellScriptTarget($(BIN))
  63. XSimpleShellScriptTarget(magent)
  64. XSimpleShellScriptTarget(mhook)
  65. X
  66. X/* The mailagent itself is derived from 'magent' through perload, hence
  67. X * making the program more efficient (the whole script need not be compiled
  68. X * by perl). Idem for mailhook.
  69. X */
  70. X
  71. XAllTarget(mailagent)
  72. Xmailagent: magent
  73. X    $(TOP)/bin/perload -o magent > $@
  74. X    chmod +rx $@
  75. X
  76. XAllTarget(mailhook)
  77. Xmailhook: mhook
  78. X    $(TOP)/bin/perload -o mhook > $@
  79. X    chmod +rx $@
  80. X
  81. X/* The mailagent carries some machine-dependant parts (for file locking)
  82. X * so it is a binary, not a script (viz it may not be shared accross
  83. X * different architectures).
  84. X */
  85. X
  86. X>BINDIR
  87. XInstallScript(mailagent,$(BINDIR))
  88. X
  89. XSetSubdirs(files filter man test)
  90. XDependDirs(filter)
  91. X
  92. X>PRIVLIB    /* Force metaconfig to ask for privlib location */
  93. X
  94. XMakeInstallDirectories($(PRIVLIB))
  95. XInstallMultipleDestFlags(install,mailhook,$(PRIVLIB),-m 555)
  96. END_OF_FILE
  97.   if test 1541 -ne `wc -c <'agent/Jmakefile'`; then
  98.     echo shar: \"'agent/Jmakefile'\" unpacked with wrong size!
  99.   fi
  100.   # end of 'agent/Jmakefile'
  101. fi
  102. if test -f 'agent/examples/README' -a "${1}" != "-c" ; then 
  103.   echo shar: Will not clobber existing file \"'agent/examples/README'\"
  104. else
  105.   echo shar: Extracting \"'agent/examples/README'\" \(1409 characters\)
  106.   sed "s/^X//" >'agent/examples/README' <<'END_OF_FILE'
  107. XThis directory contains examples of rule files for the mailagent and
  108. Xother aspects from my own environment.
  109. X
  110. Xdaemon:
  111. X    A small rule file which basically simulates the behaviour of the
  112. X    vacation program (except that vacation messages are sent every day,
  113. X    not once).
  114. X
  115. Xmailfolders:
  116. X    This file is a copy of my ~/.mailfolders. It lists all the folders or
  117. X    directories where the filter drops its incoming mail (appart from my
  118. X    system mailbox, which is implicetely included). This file is used by
  119. X    my ~/.profile to compute a suitable MAILPATH value (a colon separated
  120. X    list of files ksh should monitor for new mail). It is also used by the
  121. X    mchk script.
  122. X
  123. Xmchk:
  124. X    Check all the folders for new mail.
  125. X
  126. Xmhinc:
  127. X    This script incorporates the filtered mails or news into the
  128. X    corresponding MH folder.
  129. X    
  130. Xnocmds:
  131. X    A copy of my ~/tmp/nocmds file, which will be mailed back to anybody
  132. X    who sends me a Command mail, except when sent by myself.
  133. X
  134. Xprofile:
  135. X    An excerpt from my ~/.profile file where the mail related variables
  136. X    are set. I am using ksh, but some plain sh also handle those variables,
  137. X    which is why it is not in a ~/.kshrc.
  138. X
  139. Xrules:
  140. X    The rule file I am currently using as of today, June 30th 1992. It is
  141. X    a good example of what can be done, although it is far from using all
  142. X    the available features. Heavily commented.
  143. X
  144. Xvacation:
  145. X    A generic vacation message held in ~/.vacation. It shows typical macro
  146. X    substitutions.
  147. X
  148. END_OF_FILE
  149.   if test 1409 -ne `wc -c <'agent/examples/README'`; then
  150.     echo shar: \"'agent/examples/README'\" unpacked with wrong size!
  151.   fi
  152.   # end of 'agent/examples/README'
  153. fi
  154. if test -f 'agent/files/README' -a "${1}" != "-c" ; then 
  155.   echo shar: Will not clobber existing file \"'agent/files/README'\"
  156. else
  157.   echo shar: Extracting \"'agent/files/README'\" \(1362 characters\)
  158.   sed "s/^X//" >'agent/files/README' <<'END_OF_FILE'
  159. XThis directory holds the shell version of the filter, and some other
  160. Xsample files which will be installed in the public mailagent directory.
  161. X
  162. Xagenthelp:
  163. X    The generic help message used by the @SH mailhelp command. You may
  164. X    of course rewrite this completely to fit your taste.
  165. X
  166. Xchkagent.sh:
  167. X    A small script I am using to monitor the whole mailagent installation.
  168. X    This is run by cron every night, and mails me problems logged in the
  169. X    log file, or unusual messages from my ~/.bak, etc...
  170. X    (The name chkagent.sh was chosen to leave room for the RCS ,v extension
  171. X    on some old systems with 14 characters limit in the file names.)
  172. X    Here is my crontab entry:
  173. X
  174. X        # Check the mailagent log file for the current day
  175. X        55 23 * * *        $HOME/etc/checkagent
  176. X
  177. Xcommands:
  178. X    This file holds the allowed commands for @SH hooks.
  179. X
  180. Xdistribs:
  181. X    A description table which states where each program is located,
  182. X    whether it is archived or not, or has patches, etc... This is
  183. X    used by the @SH commands.
  184. X
  185. Xfilter.sh:
  186. X    The shell version of the filter program. Note that this script is
  187. X    not tested by the automatic regression tests and needs some tailoring
  188. X    before it can be used. It is provided only as a guideline for people
  189. X    who cannot use the C version.
  190. X
  191. Xmailagent.cf:
  192. X    A template for your ~/.mailagent.
  193. X
  194. Xproglist:
  195. X    A list of program description which will be used by the 'maillist'
  196. X    command.
  197. X
  198. END_OF_FILE
  199.   if test 1362 -ne `wc -c <'agent/files/README'`; then
  200.     echo shar: \"'agent/files/README'\" unpacked with wrong size!
  201.   fi
  202.   # end of 'agent/files/README'
  203. fi
  204. if test -f 'agent/filter/README' -a "${1}" != "-c" ; then 
  205.   echo shar: Will not clobber existing file \"'agent/filter/README'\"
  206. else
  207.   echo shar: Extracting \"'agent/filter/README'\" \(2156 characters\)
  208.   sed "s/^X//" >'agent/filter/README' <<'END_OF_FILE'
  209. XThis is the root directory for the C filter.
  210. X
  211. XUsing the C version of the filter instead of the shell version is up to you.
  212. XThis is not really a filter in the common sense, because it does not actually
  213. Xfilter anything based on the contents of your mails. It only distills your
  214. Xincoming mail into the mailagent's queue, avoiding the spawning of multiple
  215. Xperl processes which are resource consuming.
  216. X
  217. XI had to write a C version for the filter because I was loosing some mail on
  218. Xmy machine when I used the shell script. This occurred seldom, but still...
  219. XThe reason was due to the delivery mode at our site. We get our mail from a
  220. Xuucp feed. Once in a while, 20 or more mails were delivered at the same time,
  221. Xand the shell script was not fast enough, and sendmail + filter were eating
  222. Xall my system's resources.
  223. X
  224. XThis program was written in two days, in self defense, when I decided I could
  225. Xnot afford seeing my precious mail sweeping into /dev/null any longer. It
  226. Xmight not be as portable as I wanted it too.
  227. X
  228. XIf you have an internet connection and receive only a small amount of mail
  229. Xat a time, or if you have NFS mounted mailboxes, then the shell script filter
  230. Xmay well be the winner.
  231. X
  232. XIn case you are lucky enough to have a uucp connection *and* NFS mounted
  233. Xmailboxes where you may receive mail on multiple machines :-), then you may
  234. Xrun into difficulties while setting up your .forward. The best thing to do is
  235. Xto have the filter executable installed at the same location on all the
  236. Xmachines, say in /usr/local/bin/filter.
  237. X
  238. XIf your sendmail does not always set the uid correctly before invoking the
  239. Xmailer specified in the .forward, then you will have to use the C filter and
  240. Xmake a local copy with the setuid bit set. This is yet another reason for me
  241. Xto use this program on my MIPS workstation, grrr...
  242. X
  243. XThe C filter pays attention to more variables in the ~/.mailagent than the
  244. Xshell script one, mainly to ensure a proper PATH variable. Also note that
  245. Xthe algorithms used by the two programs are completely different. Despite the
  246. Xfact it was written in a hurry, I believe it is a little safer than its shell
  247. Xcounterpart. At least it is *much* faster.
  248. X
  249. END_OF_FILE
  250.   if test 2156 -ne `wc -c <'agent/filter/README'`; then
  251.     echo shar: \"'agent/filter/README'\" unpacked with wrong size!
  252.   fi
  253.   # end of 'agent/filter/README'
  254. fi
  255. if test -f 'agent/filter/hash.h' -a "${1}" != "-c" ; then 
  256.   echo shar: Will not clobber existing file \"'agent/filter/hash.h'\"
  257. else
  258.   echo shar: Extracting \"'agent/filter/hash.h'\" \(1733 characters\)
  259.   sed "s/^X//" >'agent/filter/hash.h' <<'END_OF_FILE'
  260. X/*
  261. X
  262. X #    #    ##     ####   #    #          #    #
  263. X #    #   #  #   #       #    #          #    #
  264. X ######  #    #   ####   ######          ######
  265. X #    #  ######       #  #    #   ###    #    #
  266. X #    #  #    #  #    #  #    #   ###    #    #
  267. X #    #  #    #   ####   #    #   ###    #    #
  268. X
  269. X    Declarations for hash table.
  270. X*/
  271. X
  272. X/*
  273. X * $Id: hash.h,v 2.9 92/07/14 16:48:11 ram Exp $
  274. X *
  275. X *  Copyright (c) 1992, Raphael Manfredi
  276. X *
  277. X *  You may redistribute only under the terms of the GNU General Public
  278. X *  Licence as specified in the README file that comes with dist.
  279. X *
  280. X * $Log:    hash.h,v $
  281. X * Revision 2.9  92/07/14  16:48:11  ram
  282. X * 3.0 beta baseline.
  283. X * 
  284. X */
  285. X
  286. X#ifndef _hash_h
  287. X#define _hash_h
  288. X
  289. X/* Structure which describes the hash table: array of keys and array of
  290. X * values, along with the table's size and the number of recorded elements.
  291. X */
  292. Xstruct htable {
  293. X    int32 h_size;        /* Size of table (prime number) */
  294. X    int32 h_items;        /* Number of items recorded in table */
  295. X    char **h_keys;        /* Array of keys (strings) */
  296. X    int h_pos;            /* Last position in table (iterations) */
  297. X    char **h_values;    /* Array of values (strings) */
  298. X};
  299. X
  300. X/* Function declaration */
  301. Xextern int ht_create();                /* Create H table */
  302. Xextern char *ht_value();            /* Get value given some key */
  303. Xextern char *ht_put();                /* Insert value in H table */
  304. Xextern char *ht_force();            /* Like ht_put, but replace old value */
  305. Xextern int ht_xtend();                /* Extend size of full H table */
  306. Xextern int ht_start();                /* Start iteration over H table */
  307. Xextern int ht_next();                /* Go to next item in H table */
  308. Xextern char *ht_ckey();                /* Fetch current key */
  309. Xextern char *ht_cvalue();            /* Fetch current value */
  310. Xextern int ht_count();                /* Number of items in H table */
  311. X
  312. X#endif
  313. END_OF_FILE
  314.   if test 1733 -ne `wc -c <'agent/filter/hash.h'`; then
  315.     echo shar: \"'agent/filter/hash.h'\" unpacked with wrong size!
  316.   fi
  317.   # end of 'agent/filter/hash.h'
  318. fi
  319. if test -f 'agent/filter/msg.c' -a "${1}" != "-c" ; then 
  320.   echo shar: Will not clobber existing file \"'agent/filter/msg.c'\"
  321. else
  322.   echo shar: Extracting \"'agent/filter/msg.c'\" \(1707 characters\)
  323.   sed "s/^X//" >'agent/filter/msg.c' <<'END_OF_FILE'
  324. X/*
  325. X
  326. X #    #   ####    ####            ####
  327. X ##  ##  #       #    #          #    #
  328. X # ## #   ####   #               #
  329. X #    #       #  #  ###   ###    #
  330. X #    #  #    #  #    #   ###    #    #
  331. X #    #   ####    ####    ###     ####
  332. X
  333. X    Fatal messages.
  334. X*/
  335. X
  336. X/*
  337. X * $Id: msg.c,v 2.9 92/07/14 16:48:32 ram Exp $
  338. X *
  339. X *  Copyright (c) 1992, Raphael Manfredi
  340. X *
  341. X *  You may redistribute only under the terms of the GNU General Public
  342. X *  Licence as specified in the README file that comes with dist.
  343. X *
  344. X * $Log:    msg.c,v $
  345. X * Revision 2.9  92/07/14  16:48:32  ram
  346. X * 3.0 beta baseline.
  347. X * 
  348. X */
  349. X
  350. X#include "config.h"
  351. X#include "portable.h"
  352. X#include <stdio.h>
  353. X#include <sys/types.h>
  354. X#include "sysexits.h"
  355. X#include "logfile.h"
  356. X#include "lock.h"
  357. X#include "io.h"
  358. X
  359. X#define MAX_STRING    1024        /* Maximum length for error string */
  360. X
  361. X/* VARARGS2 */
  362. Xpublic void fatal(reason, arg1, arg2, arg3, arg4, arg5)
  363. Xchar *reason;
  364. Xint arg1, arg2, arg3, arg4, arg5;
  365. X{
  366. X    /* Fatal error -- die with a meaningful error status for sendmail. If the
  367. X     * logfile has been opened, the reason will also be logged there.
  368. X     */
  369. X    char buffer[MAX_STRING];
  370. X    int status;                        /* Status from emergency_save() */
  371. X    
  372. X    status = emergency_save();        /* Attempt emergency saving */
  373. X
  374. X    fprintf(stderr, "%s: ", progname);
  375. X    fprintf(stderr, reason, arg1, arg2, arg3, arg4, arg5);
  376. X    fputc('\n', stderr);
  377. X    sprintf(buffer, "FATAL %s", reason);
  378. X    add_log(1, buffer, arg1, arg2, arg3, arg4, arg5);
  379. X    release_lock();
  380. X
  381. X    if (!was_queued()) {
  382. X        add_log(6, "NOTICE leaving mail in MTA's queue");
  383. X        exit(EX_TEMPFAIL);
  384. X    } else if (status == -1) {
  385. X        add_log(5, "WARNING no saving was ever done");
  386. X        add_log(6, "NOTICE leaving mail in MTA's queue");
  387. X        exit(EX_TEMPFAIL);
  388. X    }
  389. X
  390. X    exit(EX_OK);
  391. X}
  392. X
  393. END_OF_FILE
  394.   if test 1707 -ne `wc -c <'agent/filter/msg.c'`; then
  395.     echo shar: \"'agent/filter/msg.c'\" unpacked with wrong size!
  396.   fi
  397.   # end of 'agent/filter/msg.c'
  398. fi
  399. if test -f 'agent/filter/portable.h' -a "${1}" != "-c" ; then 
  400.   echo shar: Will not clobber existing file \"'agent/filter/portable.h'\"
  401. else
  402.   echo shar: Extracting \"'agent/filter/portable.h'\" \(1377 characters\)
  403.   sed "s/^X//" >'agent/filter/portable.h' <<'END_OF_FILE'
  404. X/*
  405. X
  406. X #####    ####   #####    #####    ##    #####   #       ######          #    #
  407. X #    #  #    #  #    #     #     #  #   #    #  #       #               #    #
  408. X #    #  #    #  #    #     #    #    #  #####   #       #####           ######
  409. X #####   #    #  #####      #    ######  #    #  #       #        ###    #    #
  410. X #       #    #  #   #      #    #    #  #    #  #       #        ###    #    #
  411. X #        ####   #    #     #    #    #  #####   ######  ######   ###    #    #
  412. X
  413. X    Some portable declarations.
  414. X*/
  415. X
  416. X/*
  417. X * $Id: portable.h,v 2.9 92/07/14 16:48:41 ram Exp $
  418. X *
  419. X *  Copyright (c) 1992, Raphael Manfredi
  420. X *
  421. X *  You may redistribute only under the terms of the GNU General Public
  422. X *  Licence as specified in the README file that comes with dist.
  423. X *
  424. X * $Log:    portable.h,v $
  425. X * Revision 2.9  92/07/14  16:48:41  ram
  426. X * 3.0 beta baseline.
  427. X * 
  428. X */
  429. X
  430. X#ifndef _portable_h_
  431. X#define _portable_h_
  432. X
  433. X/*
  434. X * Standard types
  435. X */
  436. X#if INTSIZE < 4
  437. Xtypedef int int16;
  438. Xtypedef long int32;
  439. Xtypedef unsigned int uint16;
  440. Xtypedef unsigned long uint32;
  441. X#else
  442. Xtypedef short int16;
  443. Xtypedef int int32;
  444. Xtypedef unsigned short uint16;
  445. Xtypedef unsigned int uint32;
  446. X#endif
  447. X
  448. X/*
  449. X * Scope control pseudo-keywords
  450. X */
  451. X#define public                /* default C scope */
  452. X#define private static        /* static outside a block means private */
  453. X#define shared                /* data shared between modules, but not public */
  454. X
  455. X#endif
  456. END_OF_FILE
  457.   if test 1377 -ne `wc -c <'agent/filter/portable.h'`; then
  458.     echo shar: \"'agent/filter/portable.h'\" unpacked with wrong size!
  459.   fi
  460.   # end of 'agent/filter/portable.h'
  461. fi
  462. if test -f 'agent/filter/user.c' -a "${1}" != "-c" ; then 
  463.   echo shar: Will not clobber existing file \"'agent/filter/user.c'\"
  464. else
  465.   echo shar: Extracting \"'agent/filter/user.c'\" \(1665 characters\)
  466.   sed "s/^X//" >'agent/filter/user.c' <<'END_OF_FILE'
  467. X/*
  468. X
  469. X #    #   ####   ######  #####            ####
  470. X #    #  #       #       #    #          #    #
  471. X #    #   ####   #####   #    #          #
  472. X #    #       #  #       #####    ###    #
  473. X #    #  #    #  #       #   #    ###    #    #
  474. X  ####    ####   ######  #    #   ###     ####
  475. X
  476. X    Compute user login name.
  477. X*/
  478. X
  479. X/*
  480. X * $Id: user.c,v 2.9 92/07/14 16:48:46 ram Exp $
  481. X *
  482. X *  Copyright (c) 1992, Raphael Manfredi
  483. X *
  484. X *  You may redistribute only under the terms of the GNU General Public
  485. X *  Licence as specified in the README file that comes with dist.
  486. X *
  487. X * $Log:    user.c,v $
  488. X * Revision 2.9  92/07/14  16:48:46  ram
  489. X * 3.0 beta baseline.
  490. X * 
  491. X */
  492. X
  493. X#include "config.h"
  494. X#include "portable.h"
  495. X#include <sys/types.h>                    /* For uid_t */
  496. X#include <pwd.h>
  497. X
  498. X#ifdef I_STRING
  499. X#include <string.h>
  500. X#else
  501. X#include <strings.h>
  502. X#endif
  503. X
  504. X#define LOGIN_LEN    8                    /* Maximum login name length */
  505. X
  506. Xextern struct passwd *getpwuid();        /* Get password entry for UID */
  507. Xextern Uid_t geteuid();                    /* Effective user UID */
  508. X
  509. Xpublic char *logname()
  510. X{
  511. X    /* Return pointer to static data holding the user login name. Note that we
  512. X     * look-up in /etc/passwd. Hence, if the user has duplicate entries in the
  513. X     * file, the first one will be reported. This may or may not bother you.
  514. X     * NB: we use the *effective* user ID, not the real one.
  515. X     */
  516. X    
  517. X    static char login[LOGIN_LEN + 1];    /* Where login name is stored */
  518. X    struct passwd *pw;                    /* Pointer to password entry */
  519. X
  520. X    pw = getpwuid(geteuid());            /* Get first entry matching UID */
  521. X    if (pw == (struct passwd *) 0)
  522. X        return (char *) 0;                /* User not found */
  523. X
  524. X    strncpy(login, pw->pw_name, LOGIN_LEN);
  525. X    login[LOGIN_LEN] = '\0';
  526. X
  527. X    return login;
  528. X}
  529. X
  530. END_OF_FILE
  531.   if test 1665 -ne `wc -c <'agent/filter/user.c'`; then
  532.     echo shar: \"'agent/filter/user.c'\" unpacked with wrong size!
  533.   fi
  534.   # end of 'agent/filter/user.c'
  535. fi
  536. if test -f 'agent/mailhelp.SH' -a "${1}" != "-c" ; then 
  537.   echo shar: Will not clobber existing file \"'agent/mailhelp.SH'\"
  538. else
  539.   echo shar: Extracting \"'agent/mailhelp.SH'\" \(2102 characters\)
  540.   sed "s/^X//" >'agent/mailhelp.SH' <<'END_OF_FILE'
  541. Xcase $CONFIG in
  542. X'')
  543. X    if test ! -f config.sh; then
  544. X        ln ../config.sh . || \
  545. X        ln ../../config.sh . || \
  546. X        ln ../../../config.sh . || \
  547. X        (echo "Can't find config.sh."; exit 1)
  548. X    fi 2>/dev/null
  549. X    . config.sh
  550. X    ;;
  551. Xesac
  552. Xcase "$0" in
  553. X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
  554. Xesac
  555. Xecho "Extracting agent/mailhelp (with variable substitutions)"
  556. X$spitshell >mailhelp <<!GROK!THIS!
  557. X# feed this into perl
  558. X    eval "exec perl -S \$0 \$*"
  559. X        if \$running_under_some_shell;
  560. X
  561. X# $Id: mailhelp.SH,v 2.9 92/07/14 16:48:54 ram Exp $
  562. X#
  563. X#  Copyright (c) 1991, 1992, Raphael Manfredi
  564. X#
  565. X#  You may redistribute only under the terms of the GNU General Public
  566. X#  Licence as specified in the README file that comes with dist.
  567. X#
  568. X# $Log:    mailhelp.SH,v $
  569. X# Revision 2.9  92/07/14  16:48:54  ram
  570. X# 3.0 beta baseline.
  571. X# 
  572. X
  573. X\$mversion = '$VERSION';
  574. X\$patchlevel = '$PATCHLEVEL';
  575. X!GROK!THIS!
  576. X
  577. X$spitshell >>mailhelp <<'!NO!SUBS!'
  578. X
  579. X$prog_name = $0;                # Who I am
  580. X$prog_name =~ s|^.*/(.*)|$1|;    # Keep only base name
  581. X
  582. Xdo read_config();    # First, read configuration file (in ~/.mailagent)
  583. X
  584. X# take job number and command from environment
  585. X# (passed by mailagent)
  586. X$jobnum = $ENV{'jobnum'};
  587. X$fullcmd = $ENV{'fullcmd'};
  588. X
  589. X$dest=shift;                            # Who should the help be sent to
  590. X$dest = $ENV{'path'} if $dest eq '';    # If dest was ommitted
  591. X
  592. X# A single '-' as first argument stands for return path
  593. X$dest = $ENV{'path'} if $dest eq '-';
  594. X
  595. Xopen(HELP, "$cf'spool/agenthelp") || do fatal("no help file!\n");
  596. Xopen(MAILER, "|/usr/lib/sendmail -odq -t");
  597. Xprint MAILER
  598. X"To: $dest
  599. XSubject: How to use my mail agent
  600. XX-Mailer: mailagent [version $mversion PL$patchlevel]
  601. X
  602. X";
  603. Xwhile (<HELP>) {
  604. X    # Replace some tokens by parameters
  605. X    s/=DEST=/$dest/g;
  606. X    s/=MAXSIZE=/$cf'maxsize/g;
  607. X    print MAILER;
  608. X}
  609. Xprint MAILER
  610. X"
  611. X-- $prog_name speaking for $cf'user
  612. X";
  613. Xclose MAILER;
  614. Xif ($?) {
  615. X    do add_log("ERROR couldn't send help to $dest") if $loglvl > 0;
  616. X} else {
  617. X    do add_log("SENT help to $dest") if $loglvl > 2;
  618. X}
  619. Xclose HELP;
  620. X
  621. X!NO!SUBS!
  622. X$grep -v '^;#' pl/fatal.pl >>mailhelp
  623. X$grep -v '^;#' pl/add_log.pl >>mailhelp
  624. X$grep -v '^;#' pl/read_conf.pl >>mailhelp
  625. Xchmod 755 mailhelp
  626. X$eunicefix mailhelp
  627. END_OF_FILE
  628.   if test 2102 -ne `wc -c <'agent/mailhelp.SH'`; then
  629.     echo shar: \"'agent/mailhelp.SH'\" unpacked with wrong size!
  630.   fi
  631.   chmod +x 'agent/mailhelp.SH'
  632.   # end of 'agent/mailhelp.SH'
  633. fi
  634. if test -f 'agent/pl/acs_rqst.pl' -a "${1}" != "-c" ; then 
  635.   echo shar: Will not clobber existing file \"'agent/pl/acs_rqst.pl'\"
  636. else
  637.   echo shar: Extracting \"'agent/pl/acs_rqst.pl'\" \(1490 characters\)
  638.   sed "s/^X//" >'agent/pl/acs_rqst.pl' <<'END_OF_FILE'
  639. X;# $Id: acs_rqst.pl,v 2.9 92/07/14 16:49:28 ram Exp $
  640. X;#
  641. X;#  Copyright (c) 1991, Raphael Manfredi
  642. X;#
  643. X;#  You may redistribute only under the terms of the GNU General Public
  644. X;#  Licence as specified in the README file that comes with dist.
  645. X;#
  646. X;# $Log:    acs_rqst.pl,v $
  647. X;# Revision 2.9  92/07/14  16:49:28  ram
  648. X;# 3.0 beta baseline.
  649. X;# 
  650. X;#
  651. X# Asks for the exclusive access of a file
  652. X# The given parameter (let's say F) is the absolute path
  653. X# of the file we want to access. The routine checks for the
  654. X# presence of F.lock. If it exists, it sleeps 1 second and tries
  655. X# again. After 10 trys, it reports failure by returning -1.
  656. X# Otherwise, file F.lock is created and the pid of the current
  657. X# process is written. It is checked afterwards.
  658. Xsub acs_rqst {
  659. X    local($file) = @_;    # file to be locked
  660. X    local($max) = 10;    # max number of attempts
  661. X    local($mask);        # to save old umask
  662. X    while ($max) {
  663. X        $max--;
  664. X        if (-f "$file.lock") {
  665. X            sleep(2);    # busy: wait
  666. X            next;
  667. X        }
  668. X        # Attempt to create lock
  669. X        $mask = umask(0333);            # no write permission
  670. X        if (open(FILE, ">$file.lock")) {
  671. X            print FILE "$$\n";            # write pid
  672. X            close FILE;
  673. X            umask($mask);                # restore old umask
  674. X            # Check lock
  675. X            open(FILE, "$file.lock");
  676. X            $_ = <FILE>;                # read contents
  677. X            close FILE;
  678. X            last if int($_) == $$;        # lock is ok
  679. X        } else {
  680. X            umask($mask);                # restore old umask
  681. X            sleep(2);                    # busy: wait
  682. X        }
  683. X    }
  684. X    if ($max) {
  685. X        $result = 0;    # ok
  686. X    } else {
  687. X        $result = -1;    # could not lock
  688. X    }
  689. X    $result;            # return status
  690. X}
  691. X
  692. END_OF_FILE
  693.   if test 1490 -ne `wc -c <'agent/pl/acs_rqst.pl'`; then
  694.     echo shar: \"'agent/pl/acs_rqst.pl'\" unpacked with wrong size!
  695.   fi
  696.   # end of 'agent/pl/acs_rqst.pl'
  697. fi
  698. if test -f 'agent/pl/history.pl' -a "${1}" != "-c" ; then 
  699.   echo shar: Will not clobber existing file \"'agent/pl/history.pl'\"
  700. else
  701.   echo shar: Extracting \"'agent/pl/history.pl'\" \(2538 characters\)
  702.   sed "s/^X//" >'agent/pl/history.pl' <<'END_OF_FILE'
  703. X;# $Id: history.pl,v 2.9.1.2 92/11/01 15:50:23 ram Exp $
  704. X;#
  705. X;#  Copyright (c) 1992, Raphael Manfredi
  706. X;#
  707. X;#  You may redistribute only under the terms of the GNU General Public
  708. X;#  Licence as specified in the README file that comes with dist.
  709. X;#
  710. X;# $Log:    history.pl,v $
  711. X;# Revision 2.9.1.2  92/11/01  15:50:23  ram
  712. X;# patch11: now recognizes '(a)' for '@' in a message ID (X-400 gateways)
  713. X;# 
  714. X;# Revision 2.9.1.1  92/08/26  13:13:35  ram
  715. X;# patch8: rewrote computation of message ID when absent from mail
  716. X;# 
  717. X;# Revision 2.9  92/07/14  16:50:08  ram
  718. X;# 3.0 beta baseline.
  719. X;# 
  720. X;# 
  721. X;# Handle the message history mechanism, which is used to reject duplicates.
  722. X;# Each message-id tag is stored in a file, along with a time-stamp (to enable
  723. X;# its removal after a given period.
  724. X;#
  725. X# Record message whose message ID is given as argument and return 0 if the
  726. X# message was recorded for the first time or if there is no valid message ID.
  727. X# Return 1 if the message was already recorded, and hence was already seen.
  728. Xsub history_record {
  729. X    local($msg_id) = $Header{'Message-Id'};        # Message-ID header
  730. X
  731. X    # If there is no message ID, use the concatenation of date + from fields.
  732. X    if ($msg_id) {
  733. X        # Keep only the ID stored within <> brackets
  734. X        ($msg_id) = $msg_id =~ m|^<(.*)>\s*$|;
  735. X    } else {
  736. X        # Use date + from iff there is a date. We cannot use the from field
  737. X        # alone, obviously!! We also have to ensure there is an '@' in the
  738. X        # message id, which is the case unless the address is in uucp form.
  739. X        $msg_id = $Header{'Date'};
  740. X        local($from, $comment) = &parse_address($Header{'From'});
  741. X        $from =~ s/^([\w-.]+)!([\w-.]+)/@$1:$2/;    # host!user -> @host:user
  742. X        $msg_id .= '.' . $from if $msg_id;
  743. X    }
  744. X    $msg_id =~ s/\s+/./g;            # Suppress all spaces
  745. X    $msg_id =~ s/\(a\)/@/;            # X-400 gateways sometimes use (a) for @
  746. X    return 0 unless $msg_id;        # Cannot record message without an ID
  747. X
  748. X    # Hashing of the message ID is done based on the two first letters of
  749. X    # the host name (assuming message ID has the form whatever@host).
  750. X    local($stamp, $host) = $msg_id =~ m|^(.*)@([.\w]+)|;
  751. X    unless ($stamp) {
  752. X        &add_log("WARNING incorrect message ID <$msg_id>") if $loglvl > 5;
  753. X        return 0;                    # Cannot record message if invalid ID
  754. X    }
  755. X
  756. X    local($time, $line) = &dbr'info($host, 'HISTORY', $stamp);
  757. X    return 0 if $time == -1;                # An error occurred
  758. X    if ($time > 0) {                        # Message already recorded
  759. X        &add_log("history duplicate <$msg_id>") if $loglvl > 6;
  760. X        return 1;
  761. X    }
  762. X    &dbr'update($host, 'HISTORY', 0, $stamp);    # Record message (appending)
  763. X    0;            # First time ever seen
  764. X}
  765. X
  766. END_OF_FILE
  767.   if test 2538 -ne `wc -c <'agent/pl/history.pl'`; then
  768.     echo shar: \"'agent/pl/history.pl'\" unpacked with wrong size!
  769.   fi
  770.   # end of 'agent/pl/history.pl'
  771. fi
  772. if test -f 'agent/pl/mailhook.pl' -a "${1}" != "-c" ; then 
  773.   echo shar: Will not clobber existing file \"'agent/pl/mailhook.pl'\"
  774. else
  775.   echo shar: Extracting \"'agent/pl/mailhook.pl'\" \(1687 characters\)
  776.   sed "s/^X//" >'agent/pl/mailhook.pl' <<'END_OF_FILE'
  777. X;# $Id: mailhook.pl,v 2.9.1.1 92/08/26 13:16:58 ram Exp $
  778. X;#
  779. X;#  Copyright (c) 1992, Raphael Manfredi
  780. X;#
  781. X;#  You may redistribute only under the terms of the GNU General Public
  782. X;#  Licence as specified in the README file that comes with dist.
  783. X;#
  784. X;# $Log:    mailhook.pl,v $
  785. X;# Revision 2.9.1.1  92/08/26  13:16:58  ram
  786. X;# patch8: created
  787. X;# 
  788. X;# 
  789. X#
  790. X# Various hook utilities
  791. X# (name in package hook, compiled in package mailhook)
  792. X#
  793. X
  794. Xpackage mailhook;
  795. X
  796. X# Parse mail and initialize special variables. The perl script used as hook
  797. X# does not have (usually) to do any parsing on the mail. Headers of the mail
  798. X# are available via the %header array and some special variables are set as
  799. X# conveniences.
  800. Xsub hook'initialize {
  801. X    *header = *main'Header;        # User may fetch headers via %header
  802. X    $sender = $header{'Sender'};
  803. X    $subject = $header{'Subject'};
  804. X    $precedence = $header{'Precedence'};
  805. X    $from = $header{'From'};
  806. X    $to = $header{'To'};
  807. X    $cc = $header{'Cc'};
  808. X    ($address, $friendly) = &'parse_address($from);
  809. X    $login = &'login_name($from);
  810. X    @to = split(/,/, $to);
  811. X    @cc = split(/,/, $to);
  812. X    # Leave only the address part in @to and @cc
  813. X    grep(($_ = (&'parse_address($_))[0], 0), @to);
  814. X    grep(($_ = (&'parse_address($_))[0], 0), @cc);
  815. X}
  816. X
  817. X# Load hook script and run it
  818. Xsub hook'run {
  819. X    local($hook) = @_;
  820. X    open(HOOK, $hook) || &'fatal("cannot open $hook: $!");
  821. X    local($/) = undef;
  822. X    local($body) = <HOOK>;        # Slurp whole file
  823. X    close(HOOK);
  824. X    unshift(@INC, $'privlib);    # Files first searched for in mailagent's lib
  825. X    eval $body;                    # Load, compile and execute within mailhook
  826. X    if (chop($@)) {
  827. X        $@ =~ s/ in file \(eval\)//;
  828. X        &'add_log("ERROR $@") if $'loglvl;
  829. X        &'fatal("$hook aborted");
  830. X    }
  831. X}
  832. X
  833. Xpackage main;
  834. X
  835. END_OF_FILE
  836.   if test 1687 -ne `wc -c <'agent/pl/mailhook.pl'`; then
  837.     echo shar: \"'agent/pl/mailhook.pl'\" unpacked with wrong size!
  838.   fi
  839.   # end of 'agent/pl/mailhook.pl'
  840. fi
  841. if test -f 'agent/pl/once.pl' -a "${1}" != "-c" ; then 
  842.   echo shar: Will not clobber existing file \"'agent/pl/once.pl'\"
  843. else
  844.   echo shar: Extracting \"'agent/pl/once.pl'\" \(1644 characters\)
  845.   sed "s/^X//" >'agent/pl/once.pl' <<'END_OF_FILE'
  846. X;# $Id: once.pl,v 2.9 92/07/14 16:50:24 ram Exp $
  847. X;#
  848. X;#  Copyright (c) 1992, Raphael Manfredi
  849. X;#
  850. X;#  You may redistribute only under the terms of the GNU General Public
  851. X;#  Licence as specified in the README file that comes with dist.
  852. X;#
  853. X;# $Log:    once.pl,v $
  854. X;# Revision 2.9  92/07/14  16:50:24  ram
  855. X;# 3.0 beta baseline.
  856. X;# 
  857. X;# 
  858. X;# Handling of the "once" directory for ONCE commands. A once command is
  859. X;# tagged with a tuple (name,ruletag). The name is used for hashing, and
  860. X;# the ruletag sepecifies the entry to be used by the command for timestamp
  861. X;# recording. The dbr package is used to maintain the database
  862. X;#
  863. X# Given a tuple (name, tag) and a period, make sure the command may be
  864. X# executed. If it can, update the timestamp and return true. false otherwise.
  865. Xsub once_check {
  866. X    local($hname, $tag, $period) = @_;
  867. X    $hname =~ s/\s//g;                    # There cannot be spaces in the name
  868. X    local($ok) = 1;                        # Is once ok ?
  869. X    local($timestamp) = 0;                # Time stamp attached to entry
  870. X    local($linenum) = 0;                # Line where entry was found
  871. X    if (-f $file) {
  872. X        ($timestamp, $linenum) = &dbr'info($hname, 'ONCE', $tag);
  873. X        return 0 if $timestamp == -1;    # An error occurred
  874. X    }
  875. X    local($now) = time;                    # Number of seconds since The Epoch
  876. X    if (($timestamp + $period) > $now) {
  877. X        &'add_log("we have to wait for ($hname, $tag)") if $'loglvl > 18;
  878. X        return 0;
  879. X    }
  880. X    # Now we know we can execute the command. So update the database entry.
  881. X    # If the timestamp is 0, then an append has to be done, otherwise it's
  882. X    # a single replacement.
  883. X    if ($timestamp > 0) {
  884. X        &dbr'update($hname, 'ONCE', $linenum, $tag);
  885. X    } else {
  886. X        &dbr'update($hname, 'ONCE', 0, $tag);
  887. X    }
  888. X    1;
  889. X}
  890. X
  891. END_OF_FILE
  892.   if test 1644 -ne `wc -c <'agent/pl/once.pl'`; then
  893.     echo shar: \"'agent/pl/once.pl'\" unpacked with wrong size!
  894.   fi
  895.   # end of 'agent/pl/once.pl'
  896. fi
  897. if test -f 'agent/pl/period.pl' -a "${1}" != "-c" ; then 
  898.   echo shar: Will not clobber existing file \"'agent/pl/period.pl'\"
  899. else
  900.   echo shar: Extracting \"'agent/pl/period.pl'\" \(1384 characters\)
  901.   sed "s/^X//" >'agent/pl/period.pl' <<'END_OF_FILE'
  902. X;# $Id: period.pl,v 2.9 92/07/14 16:50:26 ram Exp $
  903. X;#
  904. X;#  Copyright (c) 1992, Raphael Manfredi
  905. X;#
  906. X;#  You may redistribute only under the terms of the GNU General Public
  907. X;#  Licence as specified in the README file that comes with dist.
  908. X;#
  909. X;# $Log:    period.pl,v $
  910. X;# Revision 2.9  92/07/14  16:50:26  ram
  911. X;# 3.0 beta baseline.
  912. X;# 
  913. X;# 
  914. X# Compute the number of seconds in the period. An atomic period is a digit
  915. X# possibly followed by a modifier. The default modifier is 'd'.
  916. X# Here are the available modifiers (case is significant):
  917. X#  m  minute
  918. X#  h  hour
  919. X#  d  day
  920. X#  w  week
  921. X#  M  month (30 days of 24 hours)
  922. X#  y  year
  923. Xsub seconds_in_period {
  924. X    local($_) = @_;                # The string to parse
  925. X    s|^(\d+)||;
  926. X    local ($number) = int($1);    # Number of elementary periods
  927. X    $_ = 'd' unless /^\s*\w$/;    # Period modifier (defaults to day)
  928. X    local($sec);                # Number of seconds in an atomic period
  929. X    if ($_ eq 'm') {
  930. X        $sec = 60;                # One minute = 60 seconds
  931. X    } elsif ($_ eq 'h') {
  932. X        $sec = 3600;            # One hour = 3600 seconds
  933. X    } elsif ($_ eq 'd') {
  934. X        $sec = 86400;            # One day = 24 hours
  935. X    } elsif ($_ eq 'w') {
  936. X        $sec = 604800;            # One week = 7 days
  937. X    } elsif ($_ eq 'M') {
  938. X        $sec = 2592000;            # One month = 30 days
  939. X    } elsif ($_ eq 'y') {
  940. X        $sec = 31536000;        # One year = 365 days
  941. X    } else {
  942. X        $sec = 86400;            # Unrecognized: defaults to one day
  943. X    }
  944. X    $number * $sec;                # Number of seconds in the period
  945. X}
  946. X
  947. END_OF_FILE
  948.   if test 1384 -ne `wc -c <'agent/pl/period.pl'`; then
  949.     echo shar: \"'agent/pl/period.pl'\" unpacked with wrong size!
  950.   fi
  951.   # end of 'agent/pl/period.pl'
  952. fi
  953. if test -f 'agent/pl/rfc822.pl' -a "${1}" != "-c" ; then 
  954.   echo shar: Will not clobber existing file \"'agent/pl/rfc822.pl'\"
  955. else
  956.   echo shar: Extracting \"'agent/pl/rfc822.pl'\" \(2208 characters\)
  957.   sed "s/^X//" >'agent/pl/rfc822.pl' <<'END_OF_FILE'
  958. X;# $Id: rfc822.pl,v 2.9.1.1 92/11/01 15:51:46 ram Exp $
  959. X;#
  960. X;#  Copyright (c) 1992, Raphael Manfredi
  961. X;#
  962. X;#  You may redistribute only under the terms of the GNU General Public
  963. X;#  Licence as specified in the README file that comes with dist.
  964. X;#
  965. X;# $Log:    rfc822.pl,v $
  966. X;# Revision 2.9.1.1  92/11/01  15:51:46  ram
  967. X;# patch11: allows _ as separator in names (as in First_Last)
  968. X;# 
  969. X;# Revision 2.9  92/07/14  16:50:42  ram
  970. X;# 3.0 beta baseline.
  971. X;# 
  972. X;#
  973. X;# The following routines do some parsing on RFC822 headers (such as the
  974. X;# ones provided by sendmail).
  975. X;#
  976. X# Parse an address and returns (internet, comment)
  977. X# Examples:
  978. X#    ram@eiffel.com (Raphael Manfredi)  -> (ram@eiffel.com, Raphael Manfredi)
  979. X#    Raphael Manfredi <ram@eiffel.com>  -> (ram@eiffel.com, Raphael Manfredi)
  980. Xsub parse_address {
  981. X    local($_) = shift(@_);        # The address to be parsed
  982. X    local($comment);
  983. X    local($internet);
  984. X    if (/^\s*(\S+)\s+\((.*)\)/) {        # address (comment) 
  985. X        ($1, $2);
  986. X    } elsif (/^\s*(.*)\s+<(\S+)>/) {    # comment <address>
  987. X        $comment = $1;
  988. X        $internet = $2;
  989. X        $comment =~ s/^"(.*)"/$1/;        # "comment" -> comment
  990. X        ($internet, $comment);
  991. X    } elsif (/^\s*<(\S+)>/) {            # <address>
  992. X        ($1, "");
  993. X    } else {                            # address
  994. X        s/^\s+//;
  995. X        ($_, "");
  996. X    }
  997. X}
  998. X
  999. X# Parses an internet address and returns the login name of the sender
  1000. Xsub login_name {
  1001. X    local($_) = shift(@_);                # The internet address
  1002. X    if (s/^"(\S+)"@\S+/$1/) {            # "user@domain"@other
  1003. X        do login_name($_);                # parse user@domain
  1004. X    } elsif (s/^(\S+)@\S+/$1/) {        # user@domain.name
  1005. X        do login_name($_);                # parse user
  1006. X    } elsif (s/^(\S+)%\S+/$1/) {        # user%domain.name
  1007. X        do login_name($_);                # parse user
  1008. X    } elsif (s/^\S+!(\S+)/$1/) {        # ...!backbone!user
  1009. X        do last_name($_);                # user can only be a simple name
  1010. X    } else {                            # everything else must be a single name
  1011. X        do last_name($_);                # keep only last name
  1012. X    }
  1013. X}
  1014. X
  1015. X# Extract last name from a login name like First_name.Last_name and put it
  1016. X# in lowercase. Hence, Raphael.Manfredi will become manfredi.
  1017. Xsub last_name {
  1018. X    local($_) = shift(@_);            # The sender's login name
  1019. X    s/.*\.(\w+)/$1/;                # Keep only the last name (. separation)
  1020. X    s/.*_(\w+)/$1/;                    # Same as above (_ separation)
  1021. X    tr/A-Z/a-z/;                    # And lowercase it
  1022. X    $_;
  1023. X}
  1024. X
  1025. END_OF_FILE
  1026.   if test 2208 -ne `wc -c <'agent/pl/rfc822.pl'`; then
  1027.     echo shar: \"'agent/pl/rfc822.pl'\" unpacked with wrong size!
  1028.   fi
  1029.   # end of 'agent/pl/rfc822.pl'
  1030. fi
  1031. if test -f 'agent/pl/unpack.pl' -a "${1}" != "-c" ; then 
  1032.   echo shar: Will not clobber existing file \"'agent/pl/unpack.pl'\"
  1033. else
  1034.   echo shar: Extracting \"'agent/pl/unpack.pl'\" \(1883 characters\)
  1035.   sed "s/^X//" >'agent/pl/unpack.pl' <<'END_OF_FILE'
  1036. X;# $Id: unpack.pl,v 2.9 92/07/14 16:50:55 ram Exp $
  1037. X;#
  1038. X;#  Copyright (c) 1991, Raphael Manfredi
  1039. X;#
  1040. X;#  You may redistribute only under the terms of the GNU General Public
  1041. X;#  Licence as specified in the README file that comes with dist.
  1042. X;#
  1043. X;# $Log:    unpack.pl,v $
  1044. X;# Revision 2.9  92/07/14  16:50:55  ram
  1045. X;# 3.0 beta baseline.
  1046. X;# 
  1047. X;#
  1048. X# Expands an archive's name
  1049. Xsub expand {
  1050. X    local($path) = shift;        # The archive
  1051. X    # Look for extension of base path (eg: .cpio.Z)
  1052. X    local(@fullpath) = <${path}.*>;
  1053. X    if (-1 == $#fullpath) {
  1054. X        do clean_tmp();
  1055. X        do fatal("no archive file");
  1056. X    }
  1057. X    $path = $fullpath[0];        # Name with archive extension
  1058. X}
  1059. X
  1060. X# Unpack(path,dir,flag) restores archive `path' into `dir'
  1061. X# and returns the location of the main directory.
  1062. Xsub unpack {
  1063. X    local($path) = shift;        # The archive
  1064. X    local($dir) = shift;        # Storage place
  1065. X    local($compflag) = shift;    # Flag for compression (useful for short names)
  1066. X    local($unpack) = "";        # Will hold the restore command
  1067. X    $path = do expand($path);    # Name with archive extension
  1068. X    do add_log("archive is $path") if $loglvl > 19;
  1069. X    # First determine wether it is compressed
  1070. X    if ($compflag) {
  1071. X        $unpack = "zcat | ";
  1072. X    }
  1073. X    # Cpio or tar ?
  1074. X    if ($path =~ /\.tar/) {
  1075. X        $unpack .= "tar xof -";
  1076. X    } else {
  1077. X        $unpack .= "cpio -icmd";
  1078. X    }
  1079. X    system "< $path (cd $dir; $unpack)";
  1080. X    $path =~ s|.*/(\w+)|$1|;    # Keep only basename
  1081. X    local ($stat) = $?;            # Return status
  1082. X    if ($stat) {
  1083. X        do clean_tmp();
  1084. X        do fatal("unable to unpack $path");
  1085. X    }
  1086. X    do add_log("unpacked $path with \"$unpack\"") if $loglvl > 12;
  1087. X
  1088. X    # The top level directory is the only file in $dir
  1089. X    local(@top) = <${dir}/*>;
  1090. X    if ($#top < 0) {
  1091. X        do clean_tmp();
  1092. X        do fatal("$prog_name: no top-level dir for $path");
  1093. X    }
  1094. X    if ($#top > 0) {
  1095. X        do add_log("WARNING more than one file in $dir") if $loglvl > 4;
  1096. X    }
  1097. X    do add_log("top-level dir for $path is $top[0]") if $loglvl > 19;
  1098. X    $top[0];        # Top-level directory
  1099. X}
  1100. X
  1101. END_OF_FILE
  1102.   if test 1883 -ne `wc -c <'agent/pl/unpack.pl'`; then
  1103.     echo shar: \"'agent/pl/unpack.pl'\" unpacked with wrong size!
  1104.   fi
  1105.   # end of 'agent/pl/unpack.pl'
  1106. fi
  1107. if test -f 'agent/test/basic/config.t' -a "${1}" != "-c" ; then 
  1108.   echo shar: Will not clobber existing file \"'agent/test/basic/config.t'\"
  1109. else
  1110.   echo shar: Extracting \"'agent/test/basic/config.t'\" \(2021 characters\)
  1111.   sed "s/^X//" >'agent/test/basic/config.t' <<'END_OF_FILE'
  1112. X# This MUST be the first test ever run
  1113. Xdo '../pl/init.pl';
  1114. Xdo '../pl/logfile.pl';
  1115. Xchdir '../out' || exit 0;
  1116. Xchop($pwd = `pwd`);
  1117. X$path = $ENV{'PATH'};
  1118. X$host = $ENV{'HOST'};
  1119. X$user = $ENV{'USER'};
  1120. Xopen(CONFIG, ">.mailagent") || print "1\n";
  1121. Xprint CONFIG <<EOF;
  1122. Xhome     : $pwd
  1123. Xlevel    : 21            # Undocumented of course
  1124. Xtmpdir   : /tmp
  1125. Xemergdir : $pwd/emerg
  1126. Xtrack    : OFF
  1127. Xpath     : .
  1128. Xp_$host  : .
  1129. Xuser     : $user
  1130. Xname     : Mailagent Test Suite
  1131. Xvacation : OFF
  1132. Xvacfile  : ~/.vacation
  1133. Xvacperiod: 1d
  1134. Xspool    : ~
  1135. Xqueue    : ~/queue        # This is a good test for comments
  1136. Xlogdir   : ~
  1137. Xcontext  : \$spool/context
  1138. Xlog      : agentlog
  1139. Xseq      : .seq
  1140. Xtimezone : PST8PDT
  1141. Xstatfile : \$spool/mailagent.st
  1142. Xrules    : ~/.rules
  1143. Xmaildrop : $pwd            # Do not LEAVE messages in /usr/spool/mail
  1144. Xmailbox  : \$user        # Use config variable, not current perl $user
  1145. Xhash     : dbr
  1146. Xcleanlaps: 1M
  1147. Xautoclean: OFF
  1148. Xagemax   : 1y
  1149. Xcomfile  : \$spool/commands
  1150. Xdistlist : \$spool/distribs
  1151. Xproglist : \$spool/proglist
  1152. Xmaxsize  : 150000
  1153. Xplsave   : \$spool/plsave
  1154. Xauthfile : \$spool/auth
  1155. XEOF
  1156. Xclose CONFIG;
  1157. X`rm -rf queue emerg`;
  1158. X`mkdir emerg`;
  1159. X$? == 0 || print "2\n";
  1160. X# Use the special undocumented -t option from filter to get HOME directory
  1161. X# via environment instead of /etc/passwd.
  1162. Xopen(FILTER, "|$filter -t >/dev/null 2>&1") || print "3\n";
  1163. Xprint FILTER <<EOF;
  1164. XDummy mail
  1165. XEOF
  1166. Xclose FILTER;
  1167. X$? != 0 || print "4\n";            # No valid queue directory
  1168. X$file = <emerg/*>;
  1169. Xif (-f "$file") {
  1170. X    open(FILE, $file) || print "5\n";
  1171. X    @file = <FILE>;
  1172. X    close FILE;
  1173. X    $file[0] eq "Dummy mail\n" || print "6\n";
  1174. X    unlink "$file";
  1175. X} else {
  1176. X    print "5\n";                # No emergency dump
  1177. X}
  1178. X-s 'agentlog' || print "6\n";    # No logfile or empty
  1179. X&get_log(7);
  1180. X&check_log('FATAL', 8);                # There must be a FATAL
  1181. X&check_log('MTA', 9);                # Filter must think mail is in MTA's queue
  1182. X&check_log('updating PATH', 10);    # Make sure hostname is computed
  1183. X&check_log('unable to queue', 11);    # Filter did not queue mail
  1184. Xunlink 'agentlog';
  1185. X`mkdir queue`;
  1186. X$? == 0 || print "12\n";        # Cannot make queue
  1187. Xprint "0\n";
  1188. END_OF_FILE
  1189.   if test 2021 -ne `wc -c <'agent/test/basic/config.t'`; then
  1190.     echo shar: \"'agent/test/basic/config.t'\" unpacked with wrong size!
  1191.   fi
  1192.   # end of 'agent/test/basic/config.t'
  1193. fi
  1194. if test -f 'agent/test/basic/mailagent.t' -a "${1}" != "-c" ; then 
  1195.   echo shar: Will not clobber existing file \"'agent/test/basic/mailagent.t'\"
  1196. else
  1197.   echo shar: Extracting \"'agent/test/basic/mailagent.t'\" \(2013 characters\)
  1198.   sed "s/^X//" >'agent/test/basic/mailagent.t' <<'END_OF_FILE'
  1199. X# Basic mailagent test: ensure it is correctly invoked by filter.
  1200. Xdo '../pl/init.pl';
  1201. Xdo '../pl/logfile.pl';
  1202. X$user = $ENV{'USER'};
  1203. Xchdir '../out' || exit 0;
  1204. X# Make sure we'll find the mailagent
  1205. Xsystem 'perl', '-i', '-p', '-e', "s|^path.*|path     :.:$up|", '.mailagent';
  1206. X$? == 0 || print "1\n";
  1207. Xopen(RULES, ">.rules") || print "2\n";
  1208. Xprint RULES "{ DELETE };\n";
  1209. Xclose RULES;
  1210. Xopen(FILTER, "|$filter -t >/dev/null 2>&1") || print "3\n";
  1211. Xprint FILTER <<EOF;
  1212. XFrom: test
  1213. X
  1214. XDummy body
  1215. XEOF
  1216. Xclose FILTER;
  1217. X$? == 0 || print "4\n";
  1218. X&get_log(5);
  1219. X&check_log('WARNING.*assuming', 6);        # No To: field
  1220. X&check_log('FILTERED', 7);                # Mail filtered
  1221. X&check_log('DELETED', 8);                # Mail deleted by only rule
  1222. X@files = <queue/qm*>;
  1223. X@files == 0 || print "9\n";                # Queued mail deleted when filtered
  1224. Xunlink 'agentlog', '.rules';
  1225. Xsleep 1 while -f 'perl.lock';            # Let background mailagent die
  1226. X# Check empty rules...
  1227. Xopen(FILTER, "|$filter -t >/dev/null 2>&1") || print "10\n";
  1228. Xprint FILTER <<EOF;
  1229. XFrom: test
  1230. X
  1231. XDummy body
  1232. XEOF
  1233. Xclose FILTER;
  1234. X$? == 0 || print "11\n";
  1235. X&get_log(12);
  1236. X&check_log('FILTERED', 13);                # Mail filtered
  1237. X&check_log('LEFT', 14);                    # Mail left in mbox
  1238. X&check_log('building default', 15);        # Used default rules
  1239. X-s "$user" || print "16\n";                # Maildrop is here, so is mbox
  1240. X@files = <queue/qm*>;
  1241. X@files == 0 || print "17\n";            # Queued mail deleted when filtered
  1242. X-f 'context' && print "18\n";            # Empty context must be deleted
  1243. Xunlink 'agentlog', "$user";
  1244. Xsleep 1 while -f 'perl.lock';            # Let background mailagent die
  1245. X# Make sure file is correctly queued when another mailagent is running
  1246. X`cp /dev/null perl.lock`;
  1247. X$? == 0 || print "19\n";
  1248. Xopen(FILTER, "|$filter -t >/dev/null 2>&1") || print "20\n";
  1249. Xprint FILTER <<EOF;
  1250. XDummy mail
  1251. XEOF
  1252. Xclose FILTER;
  1253. X$? == 0 || print "21\n";    # Must terminate correctly (queued)
  1254. X&get_log(22);
  1255. X&check_log('QUEUED', 23);    # Mail was queued
  1256. X$file = <queue/fm*>;
  1257. X-f "$file" || print "24\n";    # Must have been left in queue as a 'fm' file
  1258. Xunlink "$file", 'agentlog', 'perl.lock';
  1259. Xprint "0\n";
  1260. END_OF_FILE
  1261.   if test 2013 -ne `wc -c <'agent/test/basic/mailagent.t'`; then
  1262.     echo shar: \"'agent/test/basic/mailagent.t'\" unpacked with wrong size!
  1263.   fi
  1264.   # end of 'agent/test/basic/mailagent.t'
  1265. fi
  1266. if test -f 'agent/test/cmd/assign.t' -a "${1}" != "-c" ; then 
  1267.   echo shar: Will not clobber existing file \"'agent/test/cmd/assign.t'\"
  1268. else
  1269.   echo shar: Extracting \"'agent/test/cmd/assign.t'\" \(544 characters\)
  1270.   sed "s/^X//" >'agent/test/cmd/assign.t' <<'END_OF_FILE'
  1271. X# Test ASSIGN command
  1272. Xdo '../pl/cmd.pl';
  1273. Xunlink 'output';
  1274. X
  1275. X&add_header('X-Tag: assign #1');
  1276. X`$cmd`;
  1277. X$? == 0 || print "1\n";
  1278. X-f 'output' || print "2\n";        # Result of various assign commands
  1279. Xchop($output = `cat output 2>/dev/null`);
  1280. X$output eq 'ram,try,try.2' || print "3\n";
  1281. Xunlink 'output';
  1282. X
  1283. X&replace_header('X-Tag: assign #2');
  1284. X`$cmd`;
  1285. X$? == 0 || print "4\n";
  1286. X-f 'output' || print "5\n";        # Result of various assign commands
  1287. Xchop($output = `cat output 2>/dev/null`);
  1288. X$output eq '7,1+2,7' || print "6\n";
  1289. X
  1290. Xunlink 'output', 'mail';
  1291. Xprint "0\n";
  1292. END_OF_FILE
  1293.   if test 544 -ne `wc -c <'agent/test/cmd/assign.t'`; then
  1294.     echo shar: \"'agent/test/cmd/assign.t'\" unpacked with wrong size!
  1295.   fi
  1296.   # end of 'agent/test/cmd/assign.t'
  1297. fi
  1298. if test -f 'agent/test/cmd/once.t' -a "${1}" != "-c" ; then 
  1299.   echo shar: Will not clobber existing file \"'agent/test/cmd/once.t'\"
  1300. else
  1301.   echo shar: Extracting \"'agent/test/cmd/once.t'\" \(1298 characters\)
  1302.   sed "s/^X//" >'agent/test/cmd/once.t' <<'END_OF_FILE'
  1303. X# The ONCE command and autocleaning feature
  1304. Xdo '../pl/cmd.pl';
  1305. Xunlink 'one', 'two', 'three', 'four', "$user";
  1306. X
  1307. X&add_header('X-Tag: once');
  1308. X`rm -rf dbr` if -d 'dbr';
  1309. X`$cmd`;
  1310. X$? == 0 || print "1\n";
  1311. X-f "$user" && print "2\n";
  1312. X-f 'one' || print "3\n";
  1313. X-f 'two' && print "4\n";
  1314. X-f 'three' || print "5\n";
  1315. X-f 'four' || print "6\n";
  1316. X-d 'dbr' || print "7\n";
  1317. X@files = <dbr/*/*>;
  1318. X@files == 3 || print "8\n";
  1319. X
  1320. X# Make sure ONCE dbr database not disturbed by autocleaning, and, along
  1321. X# the way, check that auto cleaning is correctly run.
  1322. X
  1323. X$level = $ENV{'LEVEL'};
  1324. X`$mailagent -L $level -q -o 'autoclean: ON' 2>/dev/null`;
  1325. X$? == 0 || print "9\n";
  1326. X@new_files = <dbr/*/*>;
  1327. X@new_files == @files || print "10\n";
  1328. Xunlink 'one', 'two', 'three', 'four', "$user";
  1329. X-f 'context' || print "11\n";
  1330. X
  1331. X`$cmd`;
  1332. X$? == 0 || print "12\n";
  1333. X-f "$user" && print "13\n";
  1334. X-f 'one' && print "14\n";
  1335. X-f 'two' && print "15\n";
  1336. X-f 'three' && print "16\n";
  1337. X-f 'four' || print "17\n";
  1338. X-d 'dbr' || print "18\n";
  1339. X
  1340. X# Make sure autocleaning leaves things in a coherent state
  1341. X
  1342. X`$mailagent -q -L $level -o 'autoclean: ON' -o 'agemax: 0m' 2>/dev/null`;
  1343. X-d 'dbr' && print "19\n";
  1344. X-f 'context' || print "20\n";
  1345. X
  1346. X`$mailagent -q -L $level 2>/dev/null`;
  1347. X-f 'context' && print "21\n";
  1348. X
  1349. Xunlink 'one', 'two', 'three', 'four', "$user", 'mail';
  1350. Xprint "0\n";
  1351. END_OF_FILE
  1352.   if test 1298 -ne `wc -c <'agent/test/cmd/once.t'`; then
  1353.     echo shar: \"'agent/test/cmd/once.t'\" unpacked with wrong size!
  1354.   fi
  1355.   # end of 'agent/test/cmd/once.t'
  1356. fi
  1357. if test -f 'agent/test/cmd/record.t' -a "${1}" != "-c" ; then 
  1358.   echo shar: Will not clobber existing file \"'agent/test/cmd/record.t'\"
  1359. else
  1360.   echo shar: Extracting \"'agent/test/cmd/record.t'\" \(1302 characters\)
  1361.   sed "s/^X//" >'agent/test/cmd/record.t' <<'END_OF_FILE'
  1362. X# The RECORD command
  1363. Xdo '../pl/cmd.pl';
  1364. Xunlink "$user.1", "$user.2", "$user.3";
  1365. X
  1366. X&add_header('X-Tag: record #1');
  1367. X`rm -rf dbr` if -d 'dbr';
  1368. X`$cmd`;
  1369. X$? == 0 || print "1\n";
  1370. X-f "$user.1" || print "2\n";    # Was saved, first time.
  1371. Xunlink "$user.1";
  1372. X
  1373. X-d 'dbr' || print "3\n";        # Make sure history recording works
  1374. X-f 'dbr/i/e' || print "4\n";    # Hashing done on domain name
  1375. X
  1376. X`$cmd`;
  1377. X$? == 0 || print "5\n";
  1378. X-f "$user.1" && print "6\n";    # We rejected this time, in SEEN mode
  1379. X-f "$user.2" || print "7\n";    # And saved it here
  1380. Xunlink "$user.2";
  1381. X
  1382. X&replace_header('X-Tag: record #2');
  1383. X`$cmd`;
  1384. X$? == 0 || print "8\n";
  1385. X-f "$user.1" && print "9\n";    # We restarted this time
  1386. X-f "$user.3" || print "10\n";    # And caught that rule in RECORD mode
  1387. X-f "$user" && print "11\n";        # Nothing here
  1388. Xunlink "$user.3";
  1389. X
  1390. X&replace_header('X-Tag: record #3');
  1391. X`$cmd`;
  1392. X$? == 0 || print "12\n";
  1393. X-f "$user.1" && print "13\n";    # We aborted
  1394. X-f "$user" || print "14\n";        # Must be there (aborted, no match)
  1395. Xunlink "$user.1", "$user";
  1396. X
  1397. X&replace_header('X-Tag: record #4');
  1398. X`$cmd`;
  1399. X$? == 0 || print "15\n";
  1400. X-f "$user.1" && print "16\n";    # We rejected
  1401. X-f "$user.2" || print "17\n";    # Must be there (saved in mode RECORD)
  1402. X-f "$user" && print "18\n";
  1403. X
  1404. X`rm -rf dbr` if -d 'dbr';
  1405. Xunlink "$user", "$user.1", "$user.2", "$user.3", 'mail';
  1406. Xprint "0\n";
  1407. END_OF_FILE
  1408.   if test 1302 -ne `wc -c <'agent/test/cmd/record.t'`; then
  1409.     echo shar: \"'agent/test/cmd/record.t'\" unpacked with wrong size!
  1410.   fi
  1411.   # end of 'agent/test/cmd/record.t'
  1412. fi
  1413. if test -f 'agent/test/cmd/unique.t' -a "${1}" != "-c" ; then 
  1414.   echo shar: Will not clobber existing file \"'agent/test/cmd/unique.t'\"
  1415. else
  1416.   echo shar: Extracting \"'agent/test/cmd/unique.t'\" \(1293 characters\)
  1417.   sed "s/^X//" >'agent/test/cmd/unique.t' <<'END_OF_FILE'
  1418. X# The UNIQUE command
  1419. Xdo '../pl/cmd.pl';
  1420. Xunlink "$user.1", "$user.2", "$user.3";
  1421. X
  1422. X&add_header('X-Tag: unique #1');
  1423. X`rm -rf dbr` if -d 'dbr';
  1424. X`$cmd`;
  1425. X$? == 0 || print "1\n";
  1426. X-f "$user.1" || print "2\n";    # Was saved, first time.
  1427. Xunlink "$user.1";
  1428. X
  1429. X-d 'dbr' || print "3\n";        # Make sure history recording works
  1430. X-f 'dbr/i/e' || print "4\n";    # Hashing done on domain name
  1431. X
  1432. X`$cmd`;
  1433. X$? == 0 || print "5\n";
  1434. X-f "$user.1" && print "6\n";    # We rejected this time, NOT in SEEN mode
  1435. X-f "$user.2" || print "7\n";    # And saved it here
  1436. Xunlink "$user.2";
  1437. X
  1438. X&replace_header('X-Tag: unique #2');
  1439. X`$cmd`;
  1440. X$? == 0 || print "8\n";
  1441. X-f "$user.1" && print "9\n";    # We restarted this time
  1442. X-f "$user.3" || print "10\n";    # And caught that rule
  1443. X-f "$user" && print "11\n";        # Nothing here
  1444. Xunlink "$user.3";
  1445. X
  1446. X&replace_header('X-Tag: unique #3');
  1447. X`$cmd`;
  1448. X$? == 0 || print "12\n";
  1449. X-f "$user.1" && print "13\n";    # We aborted
  1450. X-f "$user" && print "14\n";        # Must not be there (tagged as saved)
  1451. Xunlink "$user.1", "$user";
  1452. X
  1453. X&replace_header('X-Tag: unique #4');
  1454. X`$cmd`;
  1455. X$? == 0 || print "15\n";
  1456. X-f "$user.1" && print "16\n";    # We rejected
  1457. X-f "$user.2" || print "17\n";    # Must be there (saved in mode UNIQUE)
  1458. X-f "$user" && print "18\n";
  1459. X
  1460. X`rm -rf dbr` if -d 'dbr';
  1461. Xunlink "$user", "$user.1", "$user.2", "$user.3", 'mail';
  1462. Xprint "0\n";
  1463. END_OF_FILE
  1464.   if test 1293 -ne `wc -c <'agent/test/cmd/unique.t'`; then
  1465.     echo shar: \"'agent/test/cmd/unique.t'\" unpacked with wrong size!
  1466.   fi
  1467.   # end of 'agent/test/cmd/unique.t'
  1468. fi
  1469. if test -f 'agent/test/cmd/write.t' -a "${1}" != "-c" ; then 
  1470.   echo shar: Will not clobber existing file \"'agent/test/cmd/write.t'\"
  1471. else
  1472.   echo shar: Extracting \"'agent/test/cmd/write.t'\" \(1299 characters\)
  1473.   sed "s/^X//" >'agent/test/cmd/write.t' <<'END_OF_FILE'
  1474. X# The WRITE command
  1475. Xdo '../pl/cmd.pl';
  1476. X$mbox = 'mbox';
  1477. X
  1478. X&add_header('X-Tag: write #1');
  1479. X`$cmd`;
  1480. X$? == 0 || print "1\n";
  1481. X-f "$mbox" || print "2\n";        # Mail saved here
  1482. X-f "$user" && print "3\n";        # Must not exist (yet)
  1483. X
  1484. X# When mailbox protected against writing...
  1485. Xunlink <emerg/*>;
  1486. X$size = -s "$mbox";
  1487. Xchmod 0444, "$mbox";
  1488. X`$cmd`;
  1489. X$? == 0 || print "4\n";
  1490. X-f "$mbox" || print "5\n";                # Must still be there
  1491. X$size == -s "$mbox" || print "6\n";        # And not altered
  1492. X@emerg = <emerg/*>;
  1493. X@emerg == 1 || print "7\n";                # Emeregency as SAVE failed
  1494. X-f "$user" || print "8\n";                # Not saved -> leave in mbox
  1495. X-s "$user" == -s "$mbox" || print "9\n";
  1496. X
  1497. X# There is no X-Filter mail in the emergency saving
  1498. X`grep -v X-Filter: $mbox > ok`;
  1499. X$? == 0 || print "10\n";
  1500. X-s $emerg[0] eq -s 'ok' || print "11\n";    # Full mail saved, of course
  1501. X
  1502. X# Now verify WRITE actually overwrites the contentes
  1503. Xunlink "$user";
  1504. Xchmod 0644, "$mbox";
  1505. X`$cmd`;
  1506. X$? == 0 || print "12\n";
  1507. X$size == -s "$mbox" || print "13\n";
  1508. X-f "$user" && print "14\n";
  1509. X
  1510. X# Make sure WRITE creates full path when needed
  1511. X&replace_header('X-Tag: write #2');
  1512. X`rm -rf path` if -d 'path';
  1513. X`$cmd`;
  1514. X$? == 0 || print "15\n";
  1515. X-f 'path/another/third/mbox' || print "16\n";
  1516. X`rm -rf path` if -d 'path';
  1517. X
  1518. Xunlink <emerg/*>;
  1519. Xunlink "$mbox", "$user", 'mail', 'ok';
  1520. Xprint "0\n";
  1521. END_OF_FILE
  1522.   if test 1299 -ne `wc -c <'agent/test/cmd/write.t'`; then
  1523.     echo shar: \"'agent/test/cmd/write.t'\" unpacked with wrong size!
  1524.   fi
  1525.   # end of 'agent/test/cmd/write.t'
  1526. fi
  1527. if test -f 'agent/test/mail' -a "${1}" != "-c" ; then 
  1528.   echo shar: Will not clobber existing file \"'agent/test/mail'\"
  1529. else
  1530.   echo shar: Extracting \"'agent/test/mail'\" \(1620 characters\)
  1531.   sed "s/^X//" >'agent/test/mail' <<'END_OF_FILE'
  1532. XFrom compilers-request@iecc.cambridge.ma.us Sun Jul 12 14:45:54 PDT 1992
  1533. XReceived: from eiffel.eiffel.com by lyon.eiffel.com (5.61/1.34)
  1534. X    id AA13012; Thu, 2 Jul 92 22:34:10 -0700
  1535. XReceived: from uunet.UUCP by eiffel.eiffel.com (4.0/SMI-4.0)
  1536. X    id AA09695; Thu, 2 Jul 92 22:31:36 PDT
  1537. XReceived: from ursa-major.spdcc.com by relay2.UU.NET with SMTP 
  1538. X    (5.61/UUNET-internet-primary) id AA21794; Fri, 3 Jul 92 01:17:38 -0400
  1539. XReceived: by ursa-major.spdcc.com with sendmail-5.65/4.7 
  1540. X    id <AA13205@ursa-major.spdcc.com>; Fri, 3 Jul 92 01:17:34 -0400
  1541. XReceived: by iecc.cambridge.ma.us (smail2.5+)
  1542. X    id AA04311; 3 Jul 92 00:43:22 EDT (Fri)
  1543. XTo: ram@eiffel.com
  1544. XFrom: compilers-request@iecc.cambridge.ma.us
  1545. XSubject: Re: melting ice technology?
  1546. XDate: 3 Jul 92 00:43:22 EDT (Fri)
  1547. XMessage-Id: <9207030043.AA04311@iecc.cambridge.ma.us>
  1548. X
  1549. XYour message to the moderated usenet group comp.compilers has been
  1550. Xreceived.  Within a few days, it should either be posted to usenet or, if
  1551. Xfor some reason it's not suitable for posting, returned to you.
  1552. X
  1553. XWhen you send a message to comp.compilers, I understand that to mean that
  1554. Xyou want me to post it to usenet, which means it will be sent to tens of
  1555. Xthousands of potential readers at thousands of computers all around the
  1556. Xworld.  It may also appear in a printed comp.compilers annual and other
  1557. Xbooks, in the ACM SIGPLAN Notices and other magazines, in on-line and
  1558. Xoff-line archives, CD-ROMs, and anywhere else that some reader decides to
  1559. Xuse it.
  1560. X
  1561. XIf you don't want me to post something, please send it instead to
  1562. Xcompilers-request@iecc.cambridge.ma.us.
  1563. X
  1564. XRegards,
  1565. XJohn Levine, comp.compilers moderator
  1566. END_OF_FILE
  1567.   if test 1620 -ne `wc -c <'agent/test/mail'`; then
  1568.     echo shar: \"'agent/test/mail'\" unpacked with wrong size!
  1569.   fi
  1570.   # end of 'agent/test/mail'
  1571. fi
  1572. if test -f 'agent/test/option/s.t' -a "${1}" != "-c" ; then 
  1573.   echo shar: Will not clobber existing file \"'agent/test/option/s.t'\"
  1574. else
  1575.   echo shar: Extracting \"'agent/test/option/s.t'\" \(1803 characters\)
  1576.   sed "s/^X//" >'agent/test/option/s.t' <<'END_OF_FILE'
  1577. X# -s: report gathered statistics (special)
  1578. Xdo '../pl/init.pl';
  1579. Xdo '../pl/logfile.pl';
  1580. Xchdir '../out';
  1581. Xunlink 'mailagent.st';
  1582. X$out = `$mailagent -summary 2>/dev/null`;
  1583. X$? == 0 || print "1\n";
  1584. X`cp /dev/null mailagent.st`;
  1585. X$mail_test = <<'EOM';
  1586. XFrom ram Sat Jul 11 18:51:16 PDT 1992
  1587. XFrom: ram
  1588. XTo: ram
  1589. XSubject: test
  1590. X
  1591. XThis is a test.
  1592. XEOM
  1593. X# First time creates new statistics, second time updates them.
  1594. Xfor ($i = 0; $i < 2; $i++) {
  1595. X    open(MAILAGENT, "|$mailagent -e 'STRIP Nothing; LEAVE' 2>/dev/null") ||
  1596. X    print "2x$i\n";
  1597. X    print MAILAGENT $mail_test;
  1598. X    close MAILAGENT;
  1599. X    $? == 0 || print "3x$i\n";
  1600. X    sleep 1 while -f 'perl.lock';    # Wait for background process to finish
  1601. X}
  1602. X$user = $ENV{'USER'};
  1603. X-s "$user" || print "4\n";
  1604. X$out = `$mailagent -s 2>/dev/null`;
  1605. X$out ne '' || print "5\n";
  1606. X@out = split(/\n/, $out);
  1607. X@leave = grep(/LEAVE/, @out);
  1608. X@strip = grep(/STRIP/, @out);
  1609. X@leave == @strip || print "6\n";
  1610. X@leave == 1 || print "7\n";
  1611. X$out = `$mailagent -sm 2>/dev/null`;
  1612. X@out = split(/\n/, $out);
  1613. X@leave = grep(/LEAVE/, @out);
  1614. X@strip = grep(/STRIP/, @out);
  1615. X@leave == @strip || print "8\n";
  1616. X@leave == 2 || print "9\n";
  1617. X$out = `$mailagent -sr 2>/dev/null`;
  1618. X@out = split(/\n/, $out);
  1619. Xgrep(/STRIP.*LEAVE/, @out) || print "10\n";
  1620. X&get_log(11, 'mailagent.st');
  1621. X&check_log('^---', 12) == 1 || print "13\n";    # Rules did not changed
  1622. X&check_log('^\+\+\+', 14) == 1 || print "15\n";
  1623. X
  1624. X# Now change rules slightly
  1625. Xopen(MAILAGENT, "|$mailagent -e 'STRIP Other; LEAVE' 2>/dev/null") ||
  1626. Xprint "16\n";
  1627. Xprint MAILAGENT $mail_test;
  1628. Xclose MAILAGENT;
  1629. X$? == 0 || print "17\n";
  1630. Xsleep 1 while -f 'perl.lock';        # Wait for background process to finish
  1631. X&get_log(18, 'mailagent.st');
  1632. X&check_log('^---', 19) == 2 || print "20\n";    # Rules did changed
  1633. X&check_log('^\+\+\+', 21) == 2 || print "22\n";
  1634. X
  1635. Xunlink 'mailagent.st', "$user";
  1636. Xprint "0\n";
  1637. END_OF_FILE
  1638.   if test 1803 -ne `wc -c <'agent/test/option/s.t'`; then
  1639.     echo shar: \"'agent/test/option/s.t'\" unpacked with wrong size!
  1640.   fi
  1641.   # end of 'agent/test/option/s.t'
  1642. fi
  1643. echo shar: End of archive 15 \(of 17\).
  1644. cp /dev/null ark15isdone
  1645. MISSING=""
  1646. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ; do
  1647.     if test ! -f ark${I}isdone ; then
  1648.     MISSING="${MISSING} ${I}"
  1649.     fi
  1650. done
  1651. if test "${MISSING}" = "" ; then
  1652.     echo You have unpacked all 17 archives.
  1653.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1654. else
  1655.     echo You still must unpack the following archives:
  1656.     echo "        " ${MISSING}
  1657. fi
  1658. exit 0
  1659. exit 0 # Just in case...
  1660.