home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume35 / mailagnt / patch18 < prev    next >
Encoding:
Text File  |  1993-02-04  |  37.7 KB  |  1,226 lines

  1. Newsgroups: comp.sources.misc
  2. From: ram@eiffel.com (Raphael Manfredi)
  3. Subject: v35i034:  mailagent - Rule Based Mail Filtering, Patch18
  4. Message-ID: <1993Feb5.030658.776@sparky.imd.sterling.com>
  5. X-Md4-Signature: 7729d8fc0da3d870ee48c336c0756978
  6. Date: Fri, 5 Feb 1993 03:06:58 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: ram@eiffel.com (Raphael Manfredi)
  10. Posting-number: Volume 35, Issue 34
  11. Archive-name: mailagent/patch18
  12. Environment: Perl, Sendmail, UNIX
  13. Patch-To: mailagent: Volume 33, Issue 93-109
  14.  
  15. [The latest patch for mailagent version 2.9 is #19.]
  16.  
  17. System: mailagent version 2.9
  18. Patch #: 18
  19. Priority: MEDIUM
  20. Subject: patch #17, continued
  21. Date: Mon Feb  1 10:45:58 PST 1993
  22. From: Raphael Manfredi <ram@eiffel.com>
  23.  
  24. Description:
  25.     See patch #17.
  26.  
  27.  
  28. Fix:    From rn, say "| patch -p -N -d DIR", where DIR is your mailagent source
  29.     directory.  Outside of rn, say "cd DIR; patch -p -N <thisarticle".
  30.     If you don't have the patch program, apply the following by hand,
  31.     or get patch (version 2.0, latest patchlevel).
  32.  
  33.     After patching:
  34.         Configure -d
  35.         make depend
  36.         make
  37.         make install
  38.         make install.man
  39.  
  40.     If patch indicates that patchlevel is the wrong version, you may need
  41.     to apply one or more previous patches, or the patch may already
  42.     have been applied.  See the patchlevel.h file to find out what has or
  43.     has not been applied.  In any event, don't continue with the patch.
  44.  
  45.     If you are missing previous patches they can be obtained from me:
  46.  
  47.         Raphael Manfredi <ram@eiffel.com>
  48.  
  49.     If you send a mail message of the following form it will greatly speed
  50.     processing:
  51.  
  52.         Subject: Command
  53.         @SH mailpatch PATH mailagent 2.9 LIST
  54.                ^ note the c
  55.  
  56.     where PATH is a return path FROM ME TO YOU either in Internet notation,
  57.     or in bang notation from some well-known host, and LIST is the number
  58.     of one or more patches you need, separated by spaces, commas, and/or
  59.     hyphens.  Saying 35- says everything from 35 to the end.
  60.  
  61.     To get some more detailed instructions, send me the following mail:
  62.  
  63.         Subject: Command
  64.         @SH mailhelp PATH
  65.  
  66.  
  67. Index: patchlevel.h
  68. Prereq: 17
  69. 4c4
  70. < #define PATCHLEVEL 17
  71. ---
  72. > #define PATCHLEVEL 18
  73.  
  74. Index: agent/pl/newcmd.pl
  75. *** agent/pl/newcmd.pl.old    Mon Feb  1 10:24:39 1993
  76. --- agent/pl/newcmd.pl    Mon Feb  1 10:24:39 1993
  77. ***************
  78. *** 0 ****
  79. --- 1,210 ----
  80. + ;# $Id: newcmd.pl,v 2.9.1.1 93/02/01 10:17:40 ram Exp $
  81. + ;#
  82. + ;#  Copyright (c) 1993, Raphael Manfredi
  83. + ;#
  84. + ;#  You may redistribute only under the terms of the GNU General Public
  85. + ;#  Licence as specified in the README file that comes with dist.
  86. + ;#
  87. + ;# $Log:    newcmd.pl,v $
  88. + ;# Revision 2.9.1.1  93/02/01  10:17:40  ram
  89. + ;# patch17: created
  90. + ;# 
  91. + ;# 
  92. + ;# This package handles the dynamic loading of a perl script in memory,
  93. + ;# providing a dynamic way of enhancing the command set of the mailagent.
  94. + ;#
  95. + ;# New commands are specified in the newcmd file specified in the config file.
  96. + ;# The syntax of this file is the following:
  97. + ;#
  98. + ;#   <cmd_name> <path> <function> [<status_flag> [<seen_flag>]]
  99. + ;#
  100. + ;# cmd_name: this is the command name, eg. RETURN_SENDER
  101. + ;# path: this is the path to the perl script implementing the command.
  102. + ;# function: the perl function within the script which implements the command
  103. + ;# status_flag: states whether the command modifies the execution status
  104. + ;# seen_flag: states whether the command is allowed in _SEEN_ mode
  105. + ;# 
  106. + ;# The last two booleans are optional, and may be specified as either 'yes'
  107. + ;# and 'no' or 'true' and 'false'. Their default value is respectively true
  108. + ;# and false.
  109. + ;#
  110. + ;# New commands are loaded as they are used and put in a special newcmd
  111. + ;# package, so that the names of the routines do not conflict with the
  112. + ;# mailagent's one. They are free to use whatever function the mailagent
  113. + ;# implements by prefixing the routine name with its package: normally, the
  114. + ;# execution of the command is done from within the newcmd package.
  115. + ;#
  116. + ;# Commands are given a single argument: the string forming the command name.
  117. + ;# Therefore, the command may implement the syntax it wishes. However, for
  118. + ;# the user convenience, the special array @newcmd'argv is preset with a
  119. + ;# shell-style parsed version. The mailagent also initializes the same
  120. + ;# special variables as the one set for PERL commands, only does it put them
  121. + ;# in the newcmd package instead of mailhook.
  122. + ;#
  123. + ;# Several data structures are maintained by this package:
  124. + ;#   %Usercmd, maps a command name to a file
  125. + ;#   %Loaded, records whether a file has been loaded or not
  126. + ;#   %Run, maps a command name to a perl function
  127. + ;#
  128. + package newcmd;
  129. + #
  130. + # User-defined commands
  131. + #
  132. + # Parse the newcmd file and record all new commands in the mailagent data
  133. + # structures.
  134. + sub load {
  135. +     return unless -s $cf'newcmd;    # Empty or non-existent file
  136. +     local($ST_MODE) =  2 + $[;        # Field st_mode from inode structure
  137. +     local($S_IWOTH) = 02;            # Writable by world (no .ph files here)
  138. +     local($unsecure) = 0;            # Is command file unsecure?
  139. +     # Security checks. We cannot extend the mailagent commands if the file
  140. +     # describing those new commands is not owned by the user or ir world
  141. +     # writable. Indeed, someone could redefine default commands like LEAVE
  142. +     # and use that to break into the user account.
  143. +     unless (-O "$cf'newcmd") {
  144. +         &'add_log("WARNING you do not own new command file $cf'newcmd")
  145. +             if $'loglvl > 5;
  146. +         $unsecure++;
  147. +     }
  148. +     local($st_mode) = (stat($cf'newcmd))[$ST_MODE];
  149. +     if ($st_mode & $S_IWOTH) {
  150. +         &'add_log("WARNING new command file $cf'newcmd is world writable!")
  151. +             if $'loglvl > 5;
  152. +         $unsecure++;
  153. +     }
  154. +     if ($unsecure) {
  155. +         &'add_log("NOTICE ignoring new commands for security reasons")
  156. +             if $'loglvl > 6;
  157. +         return;
  158. +     }
  159. +     unless (open(NEWCMD, $cf'newcmd)) {
  160. +         &'add_log("ERROR cannot open $cf'newcmd: $!") if $'loglvl;
  161. +         &'add_log("WARNING new commands not loaded") if $'loglvl > 5;
  162. +         return;
  163. +     }
  164. +     local($_);
  165. +     local($cmd, $path, $function, $status, $seen);
  166. +     while (<NEWCMD>) {
  167. +         next if /^\s*#/;            # Skip comments
  168. +         next if /^\s*$/;            # Skip blank lines
  169. +         ($cmd, $path, $function, $status, $seen) = split(' ');
  170. +         $cmd =~ tr/a-z/A-Z/;        # Cannonicalize to upper-case
  171. +         $path =~ s/~/$cf'home/;        # Perform ~ substitution
  172. +         unless (-f $path && -r $path) {
  173. +             $path =~ s/^$cf'home/~/;
  174. +             &'add_log("ERROR command '$cmd' bound to unreadable file $path")
  175. +                 if $'loglvl;
  176. +             next;                    # Skip invalid command
  177. +         }
  178. +         # Load command into data structures by setting internal tables
  179. +         $'Filter{$cmd} = "newcmd'run";        # Main dispatcher for new commands
  180. +         $Usercmd{$cmd} = $path;                # Record command path
  181. +         $Loaded{$path} = 0;                    # File not loaded yet
  182. +         $Run{$cmd} = $function;                # Perl function to call
  183. +         $'Nostatus{$cmd} = 1 if status =~ /^f|n/i;
  184. +         $'Rfilter{$cmd} = 1 unless $seen =~ /^t|y/i;
  185. +         &interface'add($cmd);                # Add interface for perl hooks
  186. +         $path =~ s/^$cf'home/~/;
  187. +         &'add_log("new command $cmd in $path (&$function)")
  188. +             if $'loglvl > 18;
  189. +     }
  190. +     close NEWCMD;
  191. + }
  192. + # This is the main dispatcher for user-defined command.
  193. + # Our caller 'run_command' has set up some special variables, like $mfile
  194. + # and $cmd_name, which are used here. Someday, I'll have to encapsulate that
  195. + # in a better way--RAM.
  196. + sub run {
  197. +     # Make global variables visible in this package. Variables which should
  198. +     # not be changed are marked 'read only'.
  199. +     local($cmd) = $'cmd;                    # Full command line (read only)
  200. +     local($cmd_name) = $'cmd_name;            # Command name (read only)
  201. +     local($mfile) = $'mfile;                # File name (read only)
  202. +     local($ever_saved) = $'ever_saved;        # Saving already occurred?
  203. +     local($cont) = $'cont;                    # Continuation status
  204. +     local($vacation) = $'vacation;            # Vacation message allowed?
  205. +     local($lastcmd) = $'lastcmd;            # Last failure status stored
  206. +     local($wmode) = $'wmode;                # Filter mode
  207. +     &'add_log("user-defined command $cmd_name") if $'loglvl > 15;
  208. +     # Let's see if we already have loaded the perl script which is responsible
  209. +     # for implementing this command.
  210. +     local($path) = $Usercmd{$cmd_name};
  211. +     unless ($path) {
  212. +         &'add_log("ERROR unknown user-defined command $cmd_name") if $'loglvl;
  213. +         return 1;                    # Command failed (should not happen)
  214. +     }
  215. +     local($function) = $Run{$cmd_name};
  216. +     if (!$Loaded{$path}) {            # If implementation not loaded yet
  217. +         unless (open(PERL, $path)) {
  218. +             &'add_log("SYSERR open: $!") if $'loglvl;
  219. +             &'add_log("ERROR cannot load code for user-defined $cmd_name")
  220. +                 if $'loglvl;
  221. +             return 1;                # Command failed
  222. +         }
  223. +         local($/) = undef;
  224. +         local($body) = ' ' x (-s PERL);
  225. +         $body = <PERL>;                # Slurp whole file into pre-extended var
  226. +         close(PERL);
  227. +         local(@saved) = @INC;        # Save perl INC path (might be changed)
  228. +         unshift(@INC, $'privlib);    # Files first searched for in private lib
  229. +         eval $body;                    # Load code into memory
  230. +         @INC = @saved;                # Restore original require search path
  231. +         $Loaded{$path} = 1;            # Mark script as loaded
  232. +         if (chop($@)) {                # Script has an error
  233. +             &'add_log("ERROR in $path: $@") if $'loglvl;
  234. +             &'add_log("ERROR script for $cmd_name had an error") if $'loglvl;
  235. +             return 1;                # Command failed
  236. +         }
  237. +         # Make sure the script we just loaded defines the function we want
  238. +         local($defined) = 0;
  239. +         eval('$defined = 1 if defined &' . $function);
  240. +         unless ($defined) {
  241. +             &'add_log("ERROR script $path did not provide &$function")
  242. +                 if $'loglvl;
  243. +             return 1;                # Command failed
  244. +         }
  245. +     }
  246. +     # At this point, we know we have some code to call in order to run the
  247. +     # user-defined command. Prepare the special array @ARGV and initialize
  248. +     # the mailhook variable in the current package.
  249. +     &hook'initvar('newcmd');        # Initialize convenience variables
  250. +     local(@ARGV);                    # Argument vector for command
  251. +     require 'shellwords.pl';
  252. +     eval '@ARGV = &shellwords($cmd)';
  253. +     # We don't need to protect the following execution within an eval, since
  254. +     # we are currently inside one, via run_command.
  255. +     local($failed) = &$function($cmd);        # Call user-defined function
  256. +     # Propagate changes into global variables
  257. +     $'ever_saved = $ever_saved;
  258. +     $'cont = $cont;
  259. +     $'vacation = $vacation;
  260. +     $'lastcmd = $lastcmd;
  261. +     $'wmode = $wmode;
  262. +     # Log our action
  263. +     local($msg) = $failed ? "and failed" : "successfully";
  264. +     &'add_log("ran $cmd_name [$mfile] $msg") if $'loglvl > 6;
  265. +     $failed;            # Propagate failure status
  266. + }
  267. + package main;
  268.  
  269. Index: agent/pl/mailhook.pl
  270. Prereq: 2.9.1.1
  271. *** agent/pl/mailhook.pl.old    Mon Feb  1 10:24:37 1993
  272. --- agent/pl/mailhook.pl    Mon Feb  1 10:24:37 1993
  273. ***************
  274. *** 1,4 ****
  275. ! ;# $Id: mailhook.pl,v 2.9.1.1 92/08/26 13:16:58 ram Exp $
  276.   ;#
  277.   ;#  Copyright (c) 1992, Raphael Manfredi
  278.   ;#
  279. --- 1,4 ----
  280. ! ;# $Id: mailhook.pl,v 2.9.1.2 93/02/01 10:17:30 ram Exp $
  281.   ;#
  282.   ;#  Copyright (c) 1992, Raphael Manfredi
  283.   ;#
  284. ***************
  285. *** 6,11 ****
  286. --- 6,15 ----
  287.   ;#  Licence as specified in the README file that comes with dist.
  288.   ;#
  289.   ;# $Log:    mailhook.pl,v $
  290. + ;# Revision 2.9.1.2  93/02/01  10:17:30  ram
  291. + ;# patch17: special variables may now be initialized within various packages
  292. + ;# patch17: do not abort with fatal but with die (provision for new mailhooks)
  293. + ;# 
  294.   ;# Revision 2.9.1.1  92/08/26  13:16:58  ram
  295.   ;# patch8: created
  296.   ;# 
  297. ***************
  298. *** 21,41 ****
  299.   # does not have (usually) to do any parsing on the mail. Headers of the mail
  300.   # are available via the %header array and some special variables are set as
  301.   # conveniences.
  302. ! sub hook'initialize {
  303. !     *header = *main'Header;        # User may fetch headers via %header
  304. !     $sender = $header{'Sender'};
  305. !     $subject = $header{'Subject'};
  306. !     $precedence = $header{'Precedence'};
  307. !     $from = $header{'From'};
  308. !     $to = $header{'To'};
  309. !     $cc = $header{'Cc'};
  310. !     ($address, $friendly) = &'parse_address($from);
  311. !     $login = &'login_name($from);
  312. !     @to = split(/,/, $to);
  313. !     @cc = split(/,/, $to);
  314. !     # Leave only the address part in @to and @cc
  315. !     grep(($_ = (&'parse_address($_))[0], 0), @to);
  316. !     grep(($_ = (&'parse_address($_))[0], 0), @cc);
  317.   }
  318.   
  319.   # Load hook script and run it
  320. --- 25,52 ----
  321.   # does not have (usually) to do any parsing on the mail. Headers of the mail
  322.   # are available via the %header array and some special variables are set as
  323.   # conveniences.
  324. ! sub hook'initvar {
  325. !     local($package) = @_;        # Package into which variables should be set
  326. !     local($init) = &'q(<<'EOP');
  327. ! :    *header = *main'Header;        # User may fetch headers via %header
  328. ! :    $sender = $header{'Sender'};
  329. ! :    $subject = $header{'Subject'};
  330. ! :    $precedence = $header{'Precedence'};
  331. ! :    $from = $header{'From'};
  332. ! :    $to = $header{'To'};
  333. ! :    $cc = $header{'Cc'};
  334. ! :    ($address, $friendly) = &'parse_address($from);
  335. ! :    $login = &'login_name($from);
  336. ! :    @to = split(/,/, $to);
  337. ! :    @cc = split(/,/, $to);
  338. ! :    # Leave only the address part in @to and @cc
  339. ! :    grep(($_ = (&'parse_address($_))[0], 0), @to);
  340. ! :    grep(($_ = (&'parse_address($_))[0], 0), @cc);
  341. ! EOP
  342. !     eval(<<EOP);                # Initialize variables inside package
  343. !     package $package;
  344. !     $init
  345. ! EOP
  346.   }
  347.   
  348.   # Load hook script and run it
  349. ***************
  350. *** 50,56 ****
  351.       if (chop($@)) {
  352.           $@ =~ s/ in file \(eval\)//;
  353.           &'add_log("ERROR $@") if $'loglvl;
  354. !         &'fatal("$hook aborted");
  355.       }
  356.   }
  357.   
  358. --- 61,67 ----
  359.       if (chop($@)) {
  360.           $@ =~ s/ in file \(eval\)//;
  361.           &'add_log("ERROR $@") if $'loglvl;
  362. !         die("$hook aborted");
  363.       }
  364.   }
  365.   
  366.  
  367. Index: agent/test/misc/newcmd.t
  368. *** agent/test/misc/newcmd.t.old    Mon Feb  1 10:24:59 1993
  369. --- agent/test/misc/newcmd.t    Mon Feb  1 10:24:59 1993
  370. ***************
  371. *** 0 ****
  372. --- 1,68 ----
  373. + # Test user-defined commands
  374. + do '../pl/misc.pl';
  375. + unlink "$user", 'always', 'test';
  376. + &add_option("-o 'newcmd: ~/.newcmd'");
  377. + open(NEWCMD, '>.newcmd') || print "1\n";
  378. + print NEWCMD <<EOF || print "2\n";
  379. + FIRST_CMD ~/commands first
  380. + SECOND_CMD ~/commands second
  381. + THIRD_CMD ~/commands third
  382. + EOF
  383. + close NEWCMD || print "3\n";
  384. + open(COM, '>commands') || print "4\n";
  385. + print COM <<'EOC' || print "5\n";
  386. + sub first {
  387. +     &mailhook'third_cmd('test');    # Make sure interface function is there
  388. +     open(OUT, '>output1');
  389. +     print OUT join(' ', @ARGV), "\n";
  390. +     print OUT "$to\n";
  391. +     close OUT;
  392. +     0;
  393. + }
  394. + sub second {
  395. +     &main'add_log('second user-defined command ran ok');
  396. +     open(OUT, '>output2');
  397. +     print OUT "$from\n";
  398. +     print OUT "$header{'Date'}\n";
  399. +     close OUT;
  400. +     0;
  401. + }
  402. + sub third {
  403. +     local($cmd) = @_;
  404. +     local(@cmd) = split(' ', $cmd);
  405. +     open(TEST, ">$cmd[1]");
  406. +     print TEST "$cmd\n";
  407. +     close TEST;
  408. +     0;
  409. + }
  410. + EOC
  411. + close COM || print "6\n";
  412. + &add_header('X-Tag: newcmd');
  413. + `$cmd`;
  414. + $? == 0 || print "7\n";
  415. + -f "$user" && print "8\n";        # Haa defaulted to LEAVE -> something's wrong
  416. + -f 'output1' || print "9\n";
  417. + -f 'output2' || print "10\n";
  418. + -f 'test' || print "11\n";
  419. + chop($test = `cat test 2>/dev/null`);
  420. + $test eq 'third_cmd test' || print "12\n";
  421. + chop(@test = `cat output1 2>/dev/null`);
  422. + $test[0] eq 'FIRST_CMD arg1 arg2' || print "13\n";
  423. + $test[1] eq 'ram@eiffel.com' || print "14\n";
  424. + chop(@test = `cat output2 2>/dev/null`);
  425. + $test[0] eq 'compilers-request@iecc.cambridge.ma.us' || print "15\n";
  426. + $test[1] eq '3 Jul 92 00:43:22 EDT (Fri)' || print "16\n";
  427. + &get_log(17);
  428. + &check_log('second user-defined command ran ok', 18) == 1 || print "19\n";
  429. + unlink "$user", 'mail', 'test', 'output1', 'output2', 'commands', '.newcmd';
  430. + print "0\n";
  431.  
  432. Index: MANIFEST
  433. *** MANIFEST.old    Mon Feb  1 10:25:04 1993
  434. --- MANIFEST    Mon Feb  1 10:25:04 1993
  435. ***************
  436. *** 100,105 ****
  437. --- 100,106 ----
  438.   agent/pl/matching.pl       Matching routines used by filter
  439.   agent/pl/mbox.pl           Getting mails from a mailbox file
  440.   agent/pl/mmdf.pl           MMDF-style mailbox handling
  441. + agent/pl/newcmd.pl         Filter command extension driver
  442.   agent/pl/once.pl           Dealing with once commands
  443.   agent/pl/parse.pl          Perl library to parse a mail message
  444.   agent/pl/period.pl         Perl library to compute periods
  445. ***************
  446. *** 106,111 ****
  447. --- 107,113 ----
  448.   agent/pl/plsave.pl         Perl library to handle the plsave cache file
  449.   agent/pl/plural.pl         Perl library to pluralize words
  450.   agent/pl/pqueue.pl         Processing the queued mails
  451. + agent/pl/q.pl              Quote removal function
  452.   agent/pl/queue_mail.pl     Queuing mails
  453.   agent/pl/rangeargs.pl      Perl library to expand a list of patches
  454.   agent/pl/read_conf.pl      Perl library to read configuration file
  455. ***************
  456. *** 182,187 ****
  457. --- 184,190 ----
  458.   agent/test/mail                The mail used by testing routines
  459.   agent/test/misc/compress.t     Folder compression checks
  460.   agent/test/misc/mmdf.t         MMDF-style mailbox checks
  461. + agent/test/misc/newcmd.t       Filter command extension tests
  462.   agent/test/option/             Tests the options to the mailagent program
  463.   agent/test/option/L.t          Test -L option
  464.   agent/test/option/V.t          Test -V option
  465. ***************
  466. *** 204,209 ****
  467. --- 207,213 ----
  468.   agent/test/pl/init.pl          Variable initializations
  469.   agent/test/pl/logfile.pl       Logging file checking
  470.   agent/test/pl/mail.pl          Modifies mail components
  471. + agent/test/pl/misc.pl          Set up for miscellaneous tests
  472.   agent/test/rules               Rules used by filtering tests
  473.   bin/perload                The dataloading/autoloading perl translator
  474.   config.h.SH                Produces config.h
  475.  
  476. Index: agent/pl/filter.pl
  477. Prereq: 2.9.1.6
  478. *** agent/pl/filter.pl.old    Mon Feb  1 10:24:26 1993
  479. --- agent/pl/filter.pl    Mon Feb  1 10:24:27 1993
  480. ***************
  481. *** 1,4 ****
  482. ! ;# $Id: filter.pl,v 2.9.1.6 93/01/12 13:13:12 ram Exp $
  483.   ;#
  484.   ;#  Copyright (c) 1992, Raphael Manfredi
  485.   ;#
  486. --- 1,4 ----
  487. ! ;# $Id: filter.pl,v 2.9.1.7 93/02/01 10:10:24 ram Exp $
  488.   ;#
  489.   ;#  Copyright (c) 1992, Raphael Manfredi
  490.   ;#
  491. ***************
  492. *** 6,11 ****
  493. --- 6,15 ----
  494.   ;#  Licence as specified in the README file that comes with dist.
  495.   ;#
  496.   ;# $Log:    filter.pl,v $
  497. + ;# Revision 2.9.1.7  93/02/01  10:10:24  ram
  498. + ;# patch17: NOTIFY now accepts a list of addresses instead of just one
  499. + ;# patch17: file inclusion to load addresses now available with NOTIFY
  500. + ;# 
  501.   ;# Revision 2.9.1.6  93/01/12  13:13:12  ram
  502.   ;# patch15: undocumented feature commented (WRITE may allow hooks)
  503.   ;# 
  504. ***************
  505. *** 151,162 ****
  506.   
  507.   # Run the NOTIFY command
  508.   sub run_notify {
  509. !     local($address, $msg) = $cmd =~ m|^\w+\s+(\S+)\s+(\S+)|;
  510.       $msg =~ s/~/$cf'home/g;                    # ~ substitution
  511. !     local($failed) = do notify($msg, $address);
  512.       unless ($failed) {
  513.           $msg =~ s|^$cf'home|~|;                # Replace the home directory by ~
  514. !         do add_log("NOTIFIED $msg for [$mfile]") if $loglvl > 2;
  515.       }
  516.       $failed;
  517.   }
  518. --- 155,169 ----
  519.   
  520.   # Run the NOTIFY command
  521.   sub run_notify {
  522. !     local($args) = $cmd =~ m|^\w+\s+(.*)|;
  523. !     local(@args) = split(' ', $args);
  524. !     local($msg) = pop(@args);                # Last argument is message text
  525.       $msg =~ s/~/$cf'home/g;                    # ~ substitution
  526. !     local($address) = join(' ', @args);        # Address list
  527. !     local($failed) = ¬ify($msg, $address);
  528.       unless ($failed) {
  529.           $msg =~ s|^$cf'home|~|;                # Replace the home directory by ~
  530. !         &add_log("NOTIFIED $msg [$mfile] to $addresses") if $loglvl > 2;
  531.       }
  532.       $failed;
  533.   }
  534.  
  535. Index: agent/pl/analyze.pl
  536. Prereq: 2.9.1.5
  537. *** agent/pl/analyze.pl.old    Mon Feb  1 10:24:22 1993
  538. --- agent/pl/analyze.pl    Mon Feb  1 10:24:23 1993
  539. ***************
  540. *** 1,4 ****
  541. ! ;# $Id: analyze.pl,v 2.9.1.5 92/12/01 09:18:49 ram Exp $
  542.   ;#
  543.   ;#  Copyright (c) 1992, Raphael Manfredi
  544.   ;#
  545. --- 1,4 ----
  546. ! ;# $Id: analyze.pl,v 2.9.1.6 93/02/01 10:09:21 ram Exp $
  547.   ;#
  548.   ;#  Copyright (c) 1992, Raphael Manfredi
  549.   ;#
  550. ***************
  551. *** 6,11 ****
  552. --- 6,15 ----
  553.   ;#  Licence as specified in the README file that comes with dist.
  554.   ;#
  555.   ;# $Log:    analyze.pl,v $
  556. + ;# Revision 2.9.1.6  93/02/01  10:09:21  ram
  557. + ;# patch17: now recognizes 'mailer-agent' as a special address
  558. + ;# patch17: logging of sender now focuses only on address part
  559. + ;# 
  560.   ;# Revision 2.9.1.5  92/12/01  09:18:49  ram
  561.   ;# patch13: fixed mode selection pattern (no brace allowed)
  562.   ;# 
  563. ***************
  564. *** 42,47 ****
  565. --- 46,52 ----
  566.           'newsmaster', 1,        # My convention for news administrator--RAM
  567.           'usenet', 1,            # Aka newsmaster
  568.           'mailer-daemon', 1,        # Sendmail
  569. +         'mailer-agent', 1,        # NeXT mailer
  570.           'nobody', 1                # Nobody we've heard of
  571.       );
  572.   }
  573. ***************
  574. *** 332,339 ****
  575.       local($sender) = $Header{'Sender'};
  576.       local($from) = $Header{'From'};
  577.       &add_log("FROM $from");
  578. !     &add_log("VIA $sender")
  579. !         if $sender ne '' && $sender ne (&parse_address($from))[0];
  580.       if ($subject ne '') {
  581.           if ($subject =~ s/^Re:\s*//) {
  582.               &add_log("REPLY $subject");
  583. --- 337,344 ----
  584.       local($sender) = $Header{'Sender'};
  585.       local($from) = $Header{'From'};
  586.       &add_log("FROM $from");
  587. !     &add_log("VIA $sender") if $sender ne '' &&
  588. !         (&parse_address($sender))[0] ne (&parse_address($from))[0];
  589.       if ($subject ne '') {
  590.           if ($subject =~ s/^Re:\s*//) {
  591.               &add_log("REPLY $subject");
  592.  
  593. Index: agent/files/mailagent.cf
  594. Prereq: 2.9.1.2
  595. *** agent/files/mailagent.cf.old    Mon Feb  1 10:23:54 1993
  596. --- agent/files/mailagent.cf    Mon Feb  1 10:23:54 1993
  597. ***************
  598. *** 2,8 ****
  599.   # Configuration file for mailagent
  600.   #
  601.   
  602. ! # $Id: mailagent.cf,v 2.9.1.2 93/01/12 12:07:32 ram Exp $
  603.   #
  604.   #  Copyright (c) 1991, Raphael Manfredi
  605.   #
  606. --- 2,8 ----
  607.   # Configuration file for mailagent
  608.   #
  609.   
  610. ! # $Id: mailagent.cf,v 2.9.1.3 93/02/01 09:53:44 ram Exp $
  611.   #
  612.   #  Copyright (c) 1991, Raphael Manfredi
  613.   #
  614. ***************
  615. *** 10,15 ****
  616. --- 10,19 ----
  617.   #  Licence as specified in the README file that comes with dist.
  618.   #
  619.   # $Log:    mailagent.cf,v $
  620. + # Revision 2.9.1.3  93/02/01  09:53:44  ram
  621. + # patch17: new optional parameter 'newcmd'
  622. + # patch17: both 'compress' and 'newcmd' under same "optional" section
  623. + # 
  624.   # Revision 2.9.1.2  93/01/12  12:07:32  ram
  625.   # patch15: new parameters: nfslock, mmdf, mmdfbox and compress
  626.   # 
  627. ***************
  628. *** 68,74 ****
  629.   mailbox  : $user                # Mailbox file name (optional)
  630.   mmdf     : OFF                    # Allow MMDF-style mailbox delivery
  631.   mmdfbox  : OFF                    # Force new folders to MMDF format
  632. ! compress : ~/.compress            # Folder compression list (optional)
  633.   
  634.   # Database hashing directory (in $spool) and other controls
  635.   hash     : dbr                    # Hashing directory
  636. --- 72,81 ----
  637.   mailbox  : $user                # Mailbox file name (optional)
  638.   mmdf     : OFF                    # Allow MMDF-style mailbox delivery
  639.   mmdfbox  : OFF                    # Force new folders to MMDF format
  640. ! # Optional parameters (for experts...)
  641. ! #compress : ~/.compress            # Folder compression list
  642. ! #newcmd   : $spool/newcmd        # Definition of new filtering commands
  643.   
  644.   # Database hashing directory (in $spool) and other controls
  645.   hash     : dbr                    # Hashing directory
  646.  
  647. Index: agent/pl/hook.pl
  648. Prereq: 2.9.1.1
  649. *** agent/pl/hook.pl.old    Mon Feb  1 10:24:32 1993
  650. --- agent/pl/hook.pl    Mon Feb  1 10:24:32 1993
  651. ***************
  652. *** 1,4 ****
  653. ! ;# $Id: hook.pl,v 2.9.1.1 92/08/26 13:14:05 ram Exp $
  654.   ;#
  655.   ;#  Copyright (c) 1992, Raphael Manfredi
  656.   ;#
  657. --- 1,4 ----
  658. ! ;# $Id: hook.pl,v 2.9.1.2 93/02/01 10:15:59 ram Exp $
  659.   ;#
  660.   ;#  Copyright (c) 1992, Raphael Manfredi
  661.   ;#
  662. ***************
  663. *** 6,11 ****
  664. --- 6,14 ----
  665.   ;#  Licence as specified in the README file that comes with dist.
  666.   ;#
  667.   ;# $Log:    hook.pl,v $
  668. + ;# Revision 2.9.1.2  93/02/01  10:15:59  ram
  669. + ;# patch17: special variables are now initialized by &initvar
  670. + ;# 
  671.   ;# Revision 2.9.1.1  92/08/26  13:14:05  ram
  672.   ;# patch8: created
  673.   ;# 
  674. ***************
  675. *** 131,137 ****
  676.       local($mail, $hook) = @_;
  677.       &'add_log("hook is an audit script") if $'loglvl > 17;
  678.       &'parse_mail($mail);        # Fill in %Header
  679. !     &initialize;                # Initialize special variables
  680.       &run($hook);                # Load hook and run it
  681.   }
  682.   
  683. --- 134,140 ----
  684.       local($mail, $hook) = @_;
  685.       &'add_log("hook is an audit script") if $'loglvl > 17;
  686.       &'parse_mail($mail);        # Fill in %Header
  687. !     &initvar('mailhook');        # Initialize special variables
  688.       &run($hook);                # Load hook and run it
  689.   }
  690.   
  691. ***************
  692. *** 151,157 ****
  693.           &'fatal("cannot deliver to hook");
  694.       }
  695.       if (0 == $pid) {            # Child process
  696. !         &initialize;            # Initialize special variables
  697.           &run($hook);            # Load hook and run it
  698.           exit 0;                    # Everything went well
  699.       }
  700. --- 154,160 ----
  701.           &'fatal("cannot deliver to hook");
  702.       }
  703.       if (0 == $pid) {            # Child process
  704. !         &initvar('mailhook');    # Initialize special variables
  705.           &run($hook);            # Load hook and run it
  706.           exit 0;                    # Everything went well
  707.       }
  708.  
  709. Index: agent/test/misc/compress.t
  710. *** agent/test/misc/compress.t.old    Mon Feb  1 10:24:54 1993
  711. --- agent/test/misc/compress.t    Mon Feb  1 10:24:55 1993
  712. ***************
  713. *** 0 ****
  714. --- 1,45 ----
  715. + # Test compression feature
  716. + do '../pl/misc.pl';
  717. + unlink "$user.Z", 'always';
  718. + # Look whether compress is available. If not, do not perform this test.
  719. + `compress mail`;
  720. + `uncompress mail` if $? == 0 && -f mail.Z;
  721. + if ($? != 0) {        # No compress available in path, sorry
  722. +     print "-1\n";    # Do not perform any tests
  723. +     exit 0;
  724. + }
  725. + &add_option("-o 'compress: ~/.compress'");
  726. + open(COMPRESS, '>.compress') || print "1\n";
  727. + print COMPRESS <<EOF || print "2\n";
  728. + a[lm]*
  729. + $user
  730. + EOF
  731. + close COMPRESS || print "3\n";
  732. + &add_header('X-Tag: compress');
  733. + `$cmd`;
  734. + $? == 0 || print "4\n";
  735. + -f "$user" && print "5\n";        # Should be compressed
  736. + -f "$user.Z" || print "6\n";
  737. + -f 'always' && print "7\n";        # Should also be compressed
  738. + -f 'always.Z' || print "8\n";
  739. + -f 'another' || print "9\n";    # This one is not compressed
  740. + -f 'another.Z' && print "10\n";
  741. + $msize = -s "$user.Z";
  742. + `cp $user.Z $user >/dev/null 2>&1`;
  743. + `$cmd`;
  744. + $? == 0 || print "11\n";
  745. + -f "$user" || print "12\n";        # Should be not be recompressed
  746. + -f "$user.Z" || print "13\n";    # Should still be there
  747. + -f 'always' && print "14\n";    # Should also be compressed
  748. + -f 'always.Z' || print "15\n";
  749. + -f 'another' || print "16\n";    # This one is not compressed
  750. + -f 'another.Z' && print "17\n";
  751. + (-s $user != $msize) || print "18\n";        # Mail saved there
  752. + (-s "$user.Z" == $msize) || print "19\n";    # This one left undisturbed
  753. + unlink "$user", "$user.Z", 'always', 'always.Z', 'another', 'mail', '.compress';
  754. + print "0\n";
  755.  
  756. Index: agent/filter/parser.c
  757. Prereq: 2.9.1.3
  758. *** agent/filter/parser.c.old    Mon Feb  1 10:23:57 1993
  759. --- agent/filter/parser.c    Mon Feb  1 10:23:58 1993
  760. ***************
  761. *** 11,17 ****
  762.   */
  763.   
  764.   /*
  765. !  * $Id: parser.c,v 2.9.1.3 92/12/01 09:13:21 ram Exp $
  766.    *
  767.    *  Copyright (c) 1992, Raphael Manfredi
  768.    *
  769. --- 11,17 ----
  770.   */
  771.   
  772.   /*
  773. !  * $Id: parser.c,v 2.9.1.4 93/02/01 09:54:21 ram Exp $
  774.    *
  775.    *  Copyright (c) 1992, Raphael Manfredi
  776.    *
  777. ***************
  778. *** 19,24 ****
  779. --- 19,27 ----
  780.    *  Licence as specified in the README file that comes with dist.
  781.    *
  782.    * $Log:    parser.c,v $
  783. +  * Revision 2.9.1.4  93/02/01  09:54:21  ram
  784. +  * patch17: configuration variables may now have '-' in them
  785. +  * 
  786.    * Revision 2.9.1.3  92/12/01  09:13:21  ram
  787.    * patch13: removed spurious inclusion of <sys/types.h>
  788.    * 
  789. ***************
  790. *** 395,402 ****
  791.           return;                            /* Ignore it */
  792.   
  793.       while (*nptr++ = *path) {            /* Copy everything until non alphanum */
  794. !         if (*path == '_') {                /* '_' is valid in variable names */
  795. !             path++;                        /* But is not an alphanumeric char */
  796.               continue;
  797.           } else if (!isalnum(*path++))    /* Reached a non-alphanumeric char */
  798.               break;                        /* We got variable name */
  799. --- 398,406 ----
  800.           return;                            /* Ignore it */
  801.   
  802.       while (*nptr++ = *path) {            /* Copy everything until non alphanum */
  803. !         if (*path == '_' || *path == '-') {
  804. !             /* Valid variable characters, although not 'isalnum' */
  805. !             path++;
  806.               continue;
  807.           } else if (!isalnum(*path++))    /* Reached a non-alphanumeric char */
  808.               break;                        /* We got variable name */
  809.  
  810. Index: agent/pl/history.pl
  811. Prereq: 2.9.1.2
  812. *** agent/pl/history.pl.old    Mon Feb  1 10:24:29 1993
  813. --- agent/pl/history.pl    Mon Feb  1 10:24:30 1993
  814. ***************
  815. *** 1,4 ****
  816. ! ;# $Id: history.pl,v 2.9.1.2 92/11/01 15:50:23 ram Exp $
  817.   ;#
  818.   ;#  Copyright (c) 1992, Raphael Manfredi
  819.   ;#
  820. --- 1,4 ----
  821. ! ;# $Id: history.pl,v 2.9.1.3 93/02/01 10:15:29 ram Exp $
  822.   ;#
  823.   ;#  Copyright (c) 1992, Raphael Manfredi
  824.   ;#
  825. ***************
  826. *** 6,11 ****
  827. --- 6,14 ----
  828.   ;#  Licence as specified in the README file that comes with dist.
  829.   ;#
  830.   ;# $Log:    history.pl,v $
  831. + ;# Revision 2.9.1.3  93/02/01  10:15:29  ram
  832. + ;# patch17: updated comment
  833. + ;# 
  834.   ;# Revision 2.9.1.2  92/11/01  15:50:23  ram
  835.   ;# patch11: now recognizes '(a)' for '@' in a message ID (X-400 gateways)
  836.   ;# 
  837. ***************
  838. *** 20,26 ****
  839.   ;# Each message-id tag is stored in a file, along with a time-stamp (to enable
  840.   ;# its removal after a given period.
  841.   ;#
  842. ! # Record message whose message ID is given as argument and return 0 if the
  843.   # message was recorded for the first time or if there is no valid message ID.
  844.   # Return 1 if the message was already recorded, and hence was already seen.
  845.   sub history_record {
  846. --- 23,29 ----
  847.   ;# Each message-id tag is stored in a file, along with a time-stamp (to enable
  848.   ;# its removal after a given period.
  849.   ;#
  850. ! # Record the message ID of the current message and return 0 if the
  851.   # message was recorded for the first time or if there is no valid message ID.
  852.   # Return 1 if the message was already recorded, and hence was already seen.
  853.   sub history_record {
  854.  
  855. Index: agent/pl/interface.pl
  856. Prereq: 2.9.1.3
  857. *** agent/pl/interface.pl.old    Mon Feb  1 10:24:34 1993
  858. --- agent/pl/interface.pl    Mon Feb  1 10:24:35 1993
  859. ***************
  860. *** 1,4 ****
  861. ! ;# $Id: interface.pl,v 2.9.1.3 92/11/10 10:14:02 ram Exp $
  862.   ;#
  863.   ;#  Copyright (c) 1992, Raphael Manfredi
  864.   ;#
  865. --- 1,4 ----
  866. ! ;# $Id: interface.pl,v 2.9.1.4 93/02/01 10:16:29 ram Exp $
  867.   ;#
  868.   ;#  Copyright (c) 1992, Raphael Manfredi
  869.   ;#
  870. ***************
  871. *** 6,11 ****
  872. --- 6,14 ----
  873.   ;#  Licence as specified in the README file that comes with dist.
  874.   ;#
  875.   ;# $Log:    interface.pl,v $
  876. + ;# Revision 2.9.1.4  93/02/01  10:16:29  ram
  877. + ;# patch17: new &add routine to dynamically build a perl interface
  878. + ;# 
  879.   ;# Revision 2.9.1.3  92/11/10  10:14:02  ram
  880.   ;# patch12: perl command interface changed to return boolean success
  881.   ;# 
  882. ***************
  883. *** 144,149 ****
  884.       return 1 unless $'Filter{$fun};
  885.       0;
  886.   }
  887. !     
  888.   package main;
  889.   
  890. --- 147,166 ----
  891.       return 1 unless $'Filter{$fun};
  892.       0;
  893.   }
  894. ! # Add a new interface function for user-defined commands
  895. ! sub add {
  896. !     local($cmd) = @_;            # Command name
  897. !     $cmd =~ tr/A-Z/a-z/;        # Cannonicalize to lower case
  898. !     eval &'q(<<EOP);            # Compile new mailhook perl interface function
  899. ! :    sub mailhook'$cmd { &interface'dispatch; }
  900. ! EOP
  901. !     if (chop($@)) {
  902. !         &'add_log("ERROR while adding 'sub $cmd': $@") if $'loglvl;
  903. !         &'add_log("WARNING cannot use '&$cmd' in perl hooks")
  904. !             if $'loglvl > 5;
  905. !     }
  906. ! }
  907.   package main;
  908.   
  909.  
  910. Index: agent/pl/rfc822.pl
  911. Prereq: 2.9.1.2
  912. *** agent/pl/rfc822.pl.old    Mon Feb  1 10:24:46 1993
  913. --- agent/pl/rfc822.pl    Mon Feb  1 10:24:46 1993
  914. ***************
  915. *** 1,4 ****
  916. ! ;# $Id: rfc822.pl,v 2.9.1.2 92/12/01 09:27:19 ram Exp $
  917.   ;#
  918.   ;#  Copyright (c) 1992, Raphael Manfredi
  919.   ;#
  920. --- 1,4 ----
  921. ! ;# $Id: rfc822.pl,v 2.9.1.3 93/01/19 17:44:03 ram Exp $
  922.   ;#
  923.   ;#  Copyright (c) 1992, Raphael Manfredi
  924.   ;#
  925. ***************
  926. *** 6,11 ****
  927. --- 6,14 ----
  928.   ;#  Licence as specified in the README file that comes with dist.
  929.   ;#
  930.   ;# $Log:    rfc822.pl,v $
  931. + ;# Revision 2.9.1.3  93/01/19  17:44:03  ram
  932. + ;# patch17: now recognizes bogus addresses like '<address> (comment)'
  933. + ;# 
  934.   ;# Revision 2.9.1.2  92/12/01  09:27:19  ram
  935.   ;# patch13: added internet info extraction out of e-mail address
  936.   ;# 
  937. ***************
  938. *** 28,34 ****
  939.       local($comment);
  940.       local($internet);
  941.       if (/^\s*(\S+)\s+\((.*)\)/) {        # address (comment) 
  942. !         ($1, $2);
  943.       } elsif (/^\s*(.*)\s+<(\S+)>/) {    # comment <address>
  944.           $comment = $1;
  945.           $internet = $2;
  946. --- 31,40 ----
  947.       local($comment);
  948.       local($internet);
  949.       if (/^\s*(\S+)\s+\((.*)\)/) {        # address (comment) 
  950. !         $comment = $2;
  951. !         $internet = $1;
  952. !         $internet =~ s/^<(\S+)>/$1/;    # was <address> (comment)
  953. !         ($internet, $comment);
  954.       } elsif (/^\s*(.*)\s+<(\S+)>/) {    # comment <address>
  955.           $comment = $1;
  956.           $internet = $2;
  957.  
  958. Index: agent/examples/rules
  959. *** agent/examples/rules.old    Mon Feb  1 10:23:51 1993
  960. --- agent/examples/rules    Mon Feb  1 10:23:52 1993
  961. ***************
  962. *** 143,148 ****
  963. --- 143,174 ----
  964.       system,
  965.       unknown-user    { SAVE admin };
  966.   
  967. + # Mail about the mailagent (sometimes called mail filter, hence the double
  968. + # pattern) is handled specially. I have a special pattern file held in
  969. + # ~/mail/auto-msg/agent.key. Every message which is NOT a reply and has one
  970. + # of those patterns in its body will be automatically replied to, once a week,
  971. + # by sending the message held in ~/mail/auto-msg/agent.msg. In order for me
  972. + # to know that this message has been already "replied-to", I annotate it.
  973. + # Ultimately, the message is dropped in a dedicated folder.
  974. + Subject:
  975. +     /mail\s*agent/i,
  976. +     /mail\s*filter/i        { BEGIN AGENT; REJECT };
  977. + <AGENT>
  978. +     Subject: !/^Re:/,
  979. +     Body: "~/mail/auto-msg/agent.key"
  980. +         {
  981. +             ONCE (%r, agent, 1w) REJECT AGENT_MSG;
  982. +             SAVE agent;
  983. +         };
  984. + <AGENT_MSG>
  985. +         {
  986. +             MESSAGE ~/mail/auto-msg/agent.msg;
  987. +             ANNOTATE Auto-Replied: %r;
  988. +             SAVE agent;
  989. +         };
  990. + <AGENT> { SAVE agent };
  991.   # Here, I am detecting mails sent by someone at ISE, i.e. mails with the
  992.   # domain name ``eiffel.com'' appended or simply mails with no domain name.
  993.   # I also turn off vacation messages, for when I am away, people at ISE usually
  994.  
  995. Index: agent/mhook.SH
  996. Prereq: 2.9.1.2
  997. *** agent/mhook.SH.old    Mon Feb  1 10:24:14 1993
  998. --- agent/mhook.SH    Mon Feb  1 10:24:14 1993
  999. ***************
  1000. *** 22,28 ****
  1001.   # via the filter. Mine looks like this:
  1002.   #   "|exec /users/ram/mail/filter >>/users/ram/.bak 2>&1"
  1003.   
  1004. ! # $Id: mhook.SH,v 2.9.1.2 93/01/12 12:09:20 ram Exp $
  1005.   #
  1006.   #  Copyright (c) 1991, 1992, Raphael Manfredi
  1007.   #
  1008. --- 22,28 ----
  1009.   # via the filter. Mine looks like this:
  1010.   #   "|exec /users/ram/mail/filter >>/users/ram/.bak 2>&1"
  1011.   
  1012. ! # $Id: mhook.SH,v 2.9.1.3 93/02/01 10:05:35 ram Exp $
  1013.   #
  1014.   #  Copyright (c) 1991, 1992, Raphael Manfredi
  1015.   #
  1016. ***************
  1017. *** 30,35 ****
  1018. --- 30,38 ----
  1019.   #  Licence as specified in the README file that comes with dist.
  1020.   #
  1021.   # $Log:    mhook.SH,v $
  1022. + # Revision 2.9.1.3  93/02/01  10:05:35  ram
  1023. + # patch17: added new file pl/q.pl for quotations
  1024. + # 
  1025.   # Revision 2.9.1.2  93/01/12  12:09:20  ram
  1026.   # patch15: leading perl start up is now configured
  1027.   # 
  1028. ***************
  1029. *** 142,146 ****
  1030. --- 145,150 ----
  1031.   $grep -v '^;#' pl/header.pl >>mhook
  1032.   $grep -v '^;#' pl/rfc822.pl >>mhook
  1033.   $grep -v '^;#' pl/extern.pl >>mhook
  1034. + $grep -v '^;#' pl/q.pl >>mhook
  1035.   chmod 755 mhook
  1036.   $eunicefix mhook
  1037.  
  1038. Index: agent/test/misc/mmdf.t
  1039. *** agent/test/misc/mmdf.t.old    Mon Feb  1 10:24:56 1993
  1040. --- agent/test/misc/mmdf.t    Mon Feb  1 10:24:57 1993
  1041. ***************
  1042. *** 0 ****
  1043. --- 1,37 ----
  1044. + # Test MMDF-style mailboxes
  1045. + do '../pl/misc.pl';
  1046. + unlink "$user", 'always';
  1047. + &add_option("-o 'mmdf: ON' -o 'mmdfbox: OFF'");
  1048. + &add_header('X-Tag: mmdf');
  1049. + `$cmd`;
  1050. + $? == 0 || print "1\n";
  1051. + -f "$user" || print "2\n";
  1052. + -f 'always' || print "3\n";
  1053. + sub has_ctrl {
  1054. +     local($file) = @_;
  1055. +     open(FILE, $file) || return 0;
  1056. +     local($count) = 0;
  1057. +     local($_);
  1058. +     while (<FILE>) {
  1059. +         $count++ if /^\01\01\01\01$/;
  1060. +     }
  1061. +     $count;
  1062. + }
  1063. + &has_ctrl($user) == 0 || print "4\n";
  1064. + &has_ctrl('always') == 0 || print "5\n";
  1065. + $cmd =~ s/mmdfbox: OFF/mmdfbox: ON/ || print "6\n";
  1066. + unlink 'always';
  1067. + `$cmd`;
  1068. + $? == 0 || print "7\n";
  1069. + -f "$user" || print "8\n";
  1070. + -f 'always' || print "9\n";
  1071. + &has_ctrl($user) == 0 || print "10\n";
  1072. + &has_ctrl('always') == 4 || print "11\n";
  1073. + unlink $user, 'always', 'mail';
  1074. + print "0\n";
  1075.  
  1076. Index: agent/pl/q.pl
  1077. *** agent/pl/q.pl.old    Mon Feb  1 10:24:43 1993
  1078. --- agent/pl/q.pl    Mon Feb  1 10:24:44 1993
  1079. ***************
  1080. *** 0 ****
  1081. --- 1,22 ----
  1082. + ;# $Id: q.pl,v 2.9.1.1 93/02/01 10:21:44 ram Exp $
  1083. + ;#
  1084. + ;#  Copyright (c) 1993, Raphael Manfredi
  1085. + ;#
  1086. + ;#  You may redistribute only under the terms of the GNU General Public
  1087. + ;#  Licence as specified in the README file that comes with dist.
  1088. + ;#
  1089. + ;# $Log:    q.pl,v $
  1090. + ;# Revision 2.9.1.1  93/02/01  10:21:44  ram
  1091. + ;# patch17: created
  1092. + ;# 
  1093. + ;# Revision 2.9  92/07/14  16:50:18  ram
  1094. + ;# 3.0 beta baseline.
  1095. + ;# 
  1096. + # Quotation removal routine
  1097. + sub q {
  1098. +     local($_) = @_;
  1099. +     local($*) = 1;
  1100. +     s/^://g;
  1101. +     $_;
  1102. + }
  1103.  
  1104. Index: README
  1105. *** README.old    Mon Feb  1 10:23:49 1993
  1106. --- README    Mon Feb  1 10:23:49 1993
  1107. ***************
  1108. *** 1,6 ****
  1109.                              mailagent 2.9
  1110.   
  1111. !               Copyright (c) 1990-1992, Raphael Manfredi
  1112.   
  1113.   ------------------------------------------------------------------------
  1114.       This program is free software; you can redistribute it and/or modify
  1115. --- 1,6 ----
  1116.                              mailagent 2.9
  1117.   
  1118. !               Copyright (c) 1990-1993, Raphael Manfredi
  1119.   
  1120.   ------------------------------------------------------------------------
  1121.       This program is free software; you can redistribute it and/or modify
  1122.  
  1123. Index: agent/test/TEST
  1124. *** agent/test/TEST.old    Mon Feb  1 10:24:49 1993
  1125. --- agent/test/TEST    Mon Feb  1 10:24:49 1993
  1126. ***************
  1127. *** 11,17 ****
  1128.   $ENV{'PWD'} = $pwd;
  1129.   $ENV{'LEVEL'} = 0;            # Default loglvl for filter and cmd tests
  1130.   
  1131. ! @tests = ('basic', 'option', 'filter', 'cmd');
  1132.   $failed = 0;
  1133.   $how_many = 0;
  1134.   
  1135. --- 11,17 ----
  1136.   $ENV{'PWD'} = $pwd;
  1137.   $ENV{'LEVEL'} = 0;            # Default loglvl for filter and cmd tests
  1138.   
  1139. ! @tests = ('basic', 'option', 'filter', 'cmd', 'misc');
  1140.   $failed = 0;
  1141.   $how_many = 0;
  1142.   
  1143.  
  1144. Index: agent/test/actions
  1145. *** agent/test/actions.old    Mon Feb  1 10:24:52 1993
  1146. --- agent/test/actions    Mon Feb  1 10:24:52 1993
  1147. ***************
  1148. *** 210,212 ****
  1149. --- 210,215 ----
  1150.   X-Tag: /write #1/    { WRITE mbox };
  1151.   X-Tag: /write #2/    { WRITE path/another/third/mbox };
  1152.   
  1153. + X-Tag: /compress/    { LEAVE; SAVE always; SAVE another };
  1154. + X-Tag: /mmdf/        { LEAVE; SAVE always; SAVE always };
  1155. + X-Tag: /newcmd/        { FIRST_CMD arg1 arg2; SECOND_CMD; DELETE };
  1156.  
  1157. Index: agent/test/pl/misc.pl
  1158. *** agent/test/pl/misc.pl.old    Mon Feb  1 10:25:01 1993
  1159. --- agent/test/pl/misc.pl    Mon Feb  1 10:25:01 1993
  1160. ***************
  1161. *** 0 ****
  1162. --- 1,10 ----
  1163. + # Common actions at the top of each misc test
  1164. + do '../pl/cmd.pl';
  1165. + # Add option to command string held in $cmd
  1166. + sub add_option {
  1167. +     local($opt) = @_;
  1168. +     local(@cmd) = split(' ', $cmd);
  1169. +     $cmd = join(' ', $cmd[0], $opt, @cmd[1..$#cmd]);
  1170. + }
  1171.  
  1172. *** End of Patch 18 ***
  1173.  
  1174. exit 0 # Just in case...
  1175.