mailagent-3.1-74.orig/0000755000175000017500000000000011675050344012604 5ustar jdgjdgmailagent-3.1-74.orig/patchlevel.h0000644000175000017500000000015411017744444015105 0ustar jdgjdg/* mailagent-3.0 - 1 Dec 1993 */ /* mailagent-3.1 - 2008-05-30 */ #define VERSION 3.1 #define PATCHLEVEL 0 mailagent-3.1-74.orig/FAQ0000644000175000017500000004015710473324174013145 0ustar jdgjdg-- $Id: FAQ,v 3.0.1.4 1995/08/07 16:04:41 ram Exp ram $ -- -- Copyright (c) 1990-2006, Raphael Manfredi -- -- You may redistribute only under the terms of the Artistic License, -- as specified in the README file that comes with the distribution. -- You may reuse parts of this distribution only within the terms of -- that same Artistic License; a copy of which may be found at the root -- of the source tree for mailagent 3.0. -- -- $Log: FAQ,v $ -- Revision 3.0.1.4 1995/08/07 16:04:41 ram -- patch37: updated my e-mail address -- -- Revision 3.0.1.3 1995/02/16 14:19:48 ram -- patch32: now mentions new mailagent option -I for quick setup -- patch32: made some cleanup following Nancy McGough's comments -- -- Revision 3.0.1.2 1995/02/03 17:54:03 ram -- patch30: detab-ed the FAQ file for easier reading on terminals -- patch30: minor changes in wording and added the Star Trek example -- -- Revision 3.0.1.1 1995/01/03 17:53:38 ram -- patch24: created -- [This FAQ written for inclusion in the "Filtering Mail FAQ" posting] Subject: 5.0 Mailagent Mailagent is a powerful mail processing package that can be used to process your mail messages, either at arrival time via a .forward hook or later on while they are already saved in a mail folder. Mailagent is written in Perl and hence has all the advantages of being interpreted, i.e. it is easy to enhance dynamically and to customize. This version of the FAQ describes the basics of setting up mailagent to process incoming mail messages from within a .forward. To find out about the more advanced features of mailagent, please refer to the mailagent(1) manual page. ----------------------------------- Subject: ... 5.1 Setting Up Mailagent 1] First, make sure mailagent is available on your system. The easiest way to do this is to run: mailagent -V which will print the mailagent version if it is available, or the shell will issue an error message "mailagent: not found" or something like it. 2a] Now you need to understand the MTA (Mail Transport Agent, the program that delivers the mail; usually, sendmail) will NOT deliver to mailagent directly, rather to an intermediate (small) filter program. Two versions are available: shell or C -- refer to the mailagent(1) manpage to choose, but I recommend you use the C version first, and move to the shell version if you can't run a binary from your .forward file. 2b] Locate the filter program (it will be filter or filter.sh depending on whether you choose the C or the shell version respectively) under some directory like /usr/local/lib/mailagent. From now on, we'll assume we use the C filter and that it is located under /usr/local/lib/mailagent. 3] Copy the file /usr/local/lib/mailagent/mailagent.cf as ~/.mailagent and edit it to configure your system correctly. You will see two distinct sections in that file and you need to set-up properly the first one, the "Configuration section". If you have a version of mailagent that is recent enough (at least 3.0 PL32) then you can create an initial configuration very easily and quickly by running the following command: mailagent -I which will set-up an almost ready-to-use ~/.mailagent file. All you need to do at this point is go through its configuration section to make sure mailagent made the right choices... The minimal set of variables that MUST be correctly set (i.e. for which you cannot rely on the default set in the file) are (# introduces comment in a shell-like manner, which run up to the end of the line): home: # Your HOME directory, as reported by "echo $HOME", usually. path: # Path to be used to locate mailagent and perl, at least. p_xxx: # Path to be appended to "path" above when running on machine "xxx". user: # Your login name. name: # Your name. level: # Logging level. I recommend you raise it to 20 for testing. The mail folder directory is ~/Mail by default, but it can be changed only from within your rule file by putting maildir = ~/mail; at its top, for instance, to make it ~/mail. The rule file is defined as the "rules" parameter, and is set to ~/.rules by default. 4] Ensure the directories configured in your ~/.mailagent under "logdir" and "spool" and "queue" do exist. If you use the standard setting, this requires the following commands: cd mkdir var cd var mkdir log mailagent cd mailagent mkdir queue 5a] Create a rule file (named ~/.rules by default) for testing: cd vi .rules 5b] Enter the following in ~/.rules Subject: /test/ { SAVE testing }; The meaning of that rule should be pretty obvious: If we receive a mail whose subject line contains the word "test", then we save that mail in a folder named "testing", under the default folder directory (~/Mail). 5c] Create a ~/.forward file as follows: "|exec /usr/local/lib/mailagent/filter >> /export/home/ram/.bak 2>&1" The meaning of that line is the following: every mail should be piped (hence the leading "|" character) onto the filter program, and any output from that program (i.e. errors) are appended to some file in your home directory, with stderr following stdout (2>&1) in traditional sh syntax. == IMPORTANT NOTES == * Your .forward is always processed by sh, regardless of your login shell. * Replace /export/home/ram with your proper login directory full path. That's a part that makes your .forward unique (for zealous optimizing sendmail that are dead wrong about optimizing!) and that can save you a lot of trouble if anything goes wrong! Just look at your ~/.bak! * Replace /usr/local/lib/mailagent/filter with the proper filter path on your machine. 5d] Note that on many systems, you need to ensure your .forward will be readable by everybody, and that your home directory has the "x" bit set for everybody (i.e. can be part of a lookup path) so that sendmail can see and parse your .forward file. To ensure this, type: cd chmod a+r .forward chmod a+x . 6] Send yourself two test messages: one with "test" in the subject, and one without "test" in the subject. 7a] Checkout your ~/.bak file: it should be empty! 7b] Checkout your ~/var/log/agentlog file to see what really happened to your messages. Watch out for any ERROR or WARNING logs. This assumes you have left at least the default logging level (9) in the ~/.mailagent file (the "level" variable). But for testing, that level should be raised to 20 to help you diagnose what's going on. 7c] Look out in ~/Mail/testing. You should find there the message whose Subject line contained the word "test". Then make sure the other message has been delivered to your regular mailbox. (Since no match occurred in your rule file, the mail is left in your mailbox by default). 7d] TROUBLESHOOTING * If your mail was not properly delivered, please make sure your rule file and configuration file are correct by issuing the following command: mailagent -d * If the previous command does not output the single rule you should have put in ~/.rules, then please make sure step 3 and 4 above were correctly performed (those being the crucial steps ensuring a proper configuration). * Check the ~/.bak file for error messages. * Check for typos in any of these files: ~/.forward ~/.mailagent ~/.rules * Check the file and directory permissions of your .forward (set in step 5c above). Type... In order to... ------- -------------- cd Go to your home directory. ls -l .forward Check the permission: it should say -rw-r--r-- ls -ld . Check permission of home dir: it should say drwx?-x?-x The ?'s may be r's or hyphens or one of each (i.e., drwx--x--x, drwxr-xr-x, drwxr-x--x, drwx--xr-x). * If none of the previous hints helped you identify problem, and you can't figure it out from the output in ~/.bak or in the ~/var/log/agentlog file (or whatever file you have configured for logging within your ~/.mailagent file, variables "log" and "logdir"), then make sure your mail is not waiting in the MTA's queue: this might be the case if the agentlog file is empty. If you are using sendmail as MTA, you can run: /usr/lib/sendmail -bp to print out the queue. * As a last resort, please look at the mailagent(1) manual page under the section "Testing Your Installation" for more tips and things to look at. 8] Once you have successfully tested mailagent in steps 6 and 7 above, you're on! Mailagent is ready to process your mail. All you have to do is extend the ~/.rules file to add more rules. For instance: To Cc: www-talk { SAVE www-talk }; To Cc: agent-users { SAVE agent-users }; Those two rules filter the two mailing lists www-talk and agent-users into their respective folders, whether the mailing list address appear in the To OR Cc header. Since rules are not qualified as a pattern match (contrary to our test above), they match on logins in the address, i.e. they will match things like www-talk@chip.com or chip!www-talk, or a plain simple www-talk if this is a local alias. (This implicit matching on logins works only for some selectors like To, Cc or From which are know to contain addresses). If you wish to sort on patterns appearing in the Subject of messages for instance, then you must use a pattern matching syntax, as in: Subject: /star trek/ { SAVE star-trek; }; to save in a folder "star-trek" all the messages whose subject contains the words "star trek". Case matters, but keep on reading... 9] As an advanced topic, since mailagent is written in Perl, you have all the power of Perl's regular expressions at your disposal. Which means you can write things like this: To Cc: agent-users { REJECT AGENT }; Subject: /^\w*subscribe/i { DELETE }; * { UNIQUE -a; SAVE agent }; The second lines makes use of that perl extended regular expression syntax: \w matches an alphanumeric character plus "_", while the trailing "i" option requests a case-insensitive match. You also note you have a real automaton at your disposal. You can enter a special state (AGENT in our example) and continue parsing by only scanning for rules tagged by this mode. The first match stops the automaton, unless you REJECT to continue processing. When not restricted by a mode list, a rule is always taken into account. For example, assuming the automaton is in the state "NEWS", it will not consider rules tagged , as in the above example. The automaton begins in mode "INITIAL". The "UNIQUE -a" action followed by a SAVE ensures only one copy per Message-ID will ever end-up in your agent folder -- no duplicates! Also note you can have more than one action per rule, and that the last one uses '*' to match anything, i.e. its action part between {} will always be executed in AGENT mode, when reached by the automaton. Also, since in Perl regular expression syntax, \b matches a word-boundary and \s any space or tab character, we can write our Star Trek message sorting into a much more robust form: Subject: /\bstar\s+trek\b/i { SAVE star-trek; }; (\s+ matches one or more white spaces, while \s* would match zero or more, see the Perl manual page for a complete description of regular expressions.) which will match on various subject strings like "Last Star Trek season" or "I am addicted to Star trek", but not on "Tristar treks" -- whatever that means :-) All in all, the filtering automaton syntax is pretty much intuitive and easy to read. You have to learn which actions are possible and what they mean, naturally. ----------------------------------- Subject: ... 5.2 Tracking Your Incoming Mail If you are curious about what mailagent does to your mail, you have two options: * Look at your "agentlog" file, with a log level set to 9. * Get a summary of all the actions performed by running: mailagent -summary This last option is only possible if you have initialized the statistics gathering process by creating a ~/var/mailagent/mailagent.st file (under the default setting from ~/.mailagent). You will get a clear picture of your processing, by seeing which rule match, how often, in which state, etc... You will also know how many times you SAVE or DELETE messages for instance. Actually, mailagent statistics are triggered by a simple mailagent -s command, the letters given after in the {u,m,a,r,y} set being options that alter the output given by the command. * Look at the ~/.bak occasionally to make sure no error is pending... ----------------------------------- Subject: ... 5.3 How Safe Mailagent Processing Is? As soon as the filter program has taken a hold on your message, you can rest assured the mail will get filtered one way or the other. If filter can't queue your mail, it will exit with an exit status of 75, that status being recognized by "sendmail" as a "deliver later on" hint, in which case the mail message will safely wait in sendmail's queue. So if filter gets your message, it immediately forks and exits with a 0 status for sendmail, letting it know its work is finished and releasing it to save resources. It then calls mailagent on the queued message (in mailagent's private queue) to actually process the message. Only after successful processing will mailagent delete the queued message. Hence, under an heavily loaded system, the worst that could happen would be a duplicate processing of a message, or a bounce back when sendmail cannot fork and exec the filter program from your .forward. Under catastrophic conditions, filter or mailagent will simply dump the message on stdout, for ~/.bak to catch, preceded by the reason why processing was aborted. ----------------------------------- Subject: ... 5.4 Locking Under Mailagent By default, mailagent proceeds with a fixed locking scheme (.lock extension) plus flock() if asked to do so at Configure time. However, mailagent provides support for NFS-secure locks and also can use non-standard locking procedures, configurable from within ~/.mailagent (variables "nfslock" and "mboxlock"). However, it cannot support locking on a rule basis (yet!). The author is willing to raise the priority of that item if one comes up with a legitimate need for that feature that could not be worked-around by a PERL escape. ;-) ----------------------------------- Subject: ... 5.5 Folder Types Supported Mailagent can deliver mail to plain UNIX folders (also known as "mbox format"), to MMDF folders, to MH folders (with unseen sequence update built-in and using locks, not like rcvstore which does not!) or to directories (ala MH, but without unseen sequence support and with alternate naming possible). It also supports delivery to folders with the "x" bit set, in which case mailagent interprets those as being hooks. It either pipes the message to the "program" or further interprets the hook to do more processing. See the manual page mailagent(1) under the section "MAIL HOOKS" for more details. ----------------------------------- Subject: ... 5.6 Mailagent References Manuals: mailagent(1) - reference manual page (about 47 pages troff'ed). perl(1) - reference manual for Perl sendmail(8) - send mail over the Internet Examples: agent/examples/rules - a commented rule file sample, from the distribution source tree. Newsgroup: comp.mail.misc Mailing List: agent-users@foretune.co.jp Subscribe to the list by sending mail: To: majordomo@foretune.co.jp subscribe agent-users Mailagent archives: FTP://ftp.foretune.co.jp/pub/network/mail/mailagent EMAIL: Send mail to the author's mailagent: To: ram@hptnos02.grenoble.hp.com Subject: Command @SH maildist - mailagent - ----------------------------------- mailagent-3.1-74.orig/Jmakefile0000644000175000017500000000141311017742141014406 0ustar jdgjdg/* * Main Jmakefile for mailagent 2.9 */ ;# $Id: Jmakefile,v 3.0 1993/11/29 13:47:34 ram Exp ram $ ;# ;# Copyright (c) 1990-2006, Raphael Manfredi ;# ;# You may redistribute only under the terms of the Artistic License, ;# as specified in the README file that comes with the distribution. ;# You may reuse parts of this distribution only within the terms of ;# that same Artistic License; a copy of which may be found at the root ;# of the source tree for mailagent 3.0. ;# ;# $Log: Jmakefile,v $ ;# Revision 3.0 1993/11/29 13:47:34 ram ;# Baseline for mailagent 3.0 netwide release. ;# all:: NoManPages() SetSubdirs(agent) AddedByConfigure(install mkdep cppstdin) DependSubdirs() all:: revision.h .FORCE: revision.h: .FORCE $(TOP)/bin/svn-revision $(TOP) $@ mailagent-3.1-74.orig/bin/0000755000175000017500000000000011675050335013354 5ustar jdgjdgmailagent-3.1-74.orig/bin/perload0000755000175000017500000005267511031240252014730 0ustar jdgjdg: # feed this into perl '/bin/true' && eval 'exec perl -S $0 "$@"' if $running_under_some_shell; 'di'; 'ig00'; # # This perl script is its own manual page [generated by wrapman] # # $Id: perload,v 3.0.1.1 1994/09/22 14:41:41 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: perload,v $ # Revision 3.0.1.1 1994/09/22 14:41:41 ram # patch12: added minimal support for perl5 dataloading # # Revision 3.0 1993/11/29 13:50:28 ram # Baseline for mailagent 3.0 netwide release. # # Replace each function definition in a loading section by two stubs and # reject the definition into the DATA part of the script if in a dataload # section or into a FILE if in an autoload section. $in_load = 0; # In a loading section $autoload = ''; # Name of autoloaded file $has_invocation_stub = 0; # True if we detect a #! stub $current_package = 'main'; # Current package $init_emitted = 0; # True when dataloading stamp was emitted $in_function = 0; require 'getopt.pl'; &Getopt; while (<>) { if ($. == 1 && /^(:|#).*perl/) { # Invocation stub $has_invocation_stub = 1; print; next; } if ($. <= 3 && $has_invocation_stub) { print; next; } if (/^\s*$/) { &flush_comment; print unless $in_function; print if $in_function && !$in_load; if ($in_function && $in_load) { push(@Data, "\n") unless $autoload; $Auto{$autoload} .= "\n" if $autoload; } next; } if (/^\s*;?#/) { if (/#\s*perload on/i) { # Enter a loading section print unless /:$/; $in_load = 1; next; } if (/#\s*perload off/i) { # End a loading section print unless /:$/; $in_load = 0; next; } if (/#\s*autoload (\S+)/i) { # Enter autoloading section print unless /:$/; push(@autoload, $autoload); # Directives may be nested $autoload = $1; $in_load += 2; next; } if (/#\s*offload/i) { # End autoloading section print unless /:$/; $autoload = pop(@autoload); # Revert to previously active file $in_load -= 2; next; } &emit_init unless $init_emitted; push(@Comment, $_) unless $in_function; print if $in_function && !$in_load; next unless $in_function; push(@Data, $_) unless $autoload; $Auto{$autoload} .= $_ if $autoload; next; } &emit_init unless $init_emitted; /^package (\S+)\s*;/ && ($current_package = $1); unless ($in_load) { &flush_comment; print; next; } # We are in a loading section if (/^sub\s+([\w']+)\s*\{(.*)/) { die "line $.: function $1 defined within another function.\n" if $in_function; # Silently ignore one-line functions if (/\}/) { &flush_comment; print; next; } $comment = $2; $in_function = 1; $function = $1; ($fn_package, $fn_basename) = $function =~ /^(\w+)'(\w+)/; unless ($fn_package) { $fn_package = $current_package; $fn_basename = $function; } die "line $.: duplicate routine ${fn_package}::$fn_basename\n" if $Seen{"${fn_package}::$fn_basename"}++; # Keep leading function comment foreach (@Comment) { push(@Data, $_) unless $autoload; $Auto{$autoload} .= $_ if $autoload; } @Comment = (); # Change package context for correct compilation: the name is visible # within the original function package while the body of the function # is compiled within the current package. $declaration = "sub $fn_package" . "'load_$fn_basename {$comment\n"; $package_context = "\tpackage $current_package;\n"; if ($autoload) { $Auto{$autoload} .= $declaration . $package_context; } else { push(@Data, $declaration, $package_context); } # Emit stubs print "sub $fn_package", "'$fn_basename"; print " { &auto_$fn_package", "'$fn_basename; }\n"; print "sub auto_$fn_package", "'$fn_basename { "; print '&main\'dataload' unless $autoload; print '&main\'autoload(' . "'$autoload'" . ', @_)' if $autoload; print "; }\n"; next; } unless ($in_function) { &flush_comment; print; next; } # We are in a loading section and inside a function body push(@Data, $_) unless $autoload; $Auto{$autoload} .= $_ if $autoload; $in_function = 0 if /^\}/; if (/^\}/) { push(@Data, "\n") unless $autoload; $Auto{$autoload} .= "\n" if $autoload; } } @auto = keys %Auto; if (@auto > 0) { print &q(<<'EOC'); :# Load the calling function from file and call it. This function is called :# only once per file to be loaded. :sub main'autoload { : local($__file__) = shift(@_); : local($__packname__) = (caller(1))[3]; : $__packname__ =~ s/::/'/; : local($__rpackname__) = $__packname__; : local($__saved__) = $@; : $__rpackname__ =~ s/^auto_//; : &perload'load_from_file($__file__); : $__rpackname__ =~ s/'/'load_/; : $@ = $__saved__; # Restore value $@ had on entrance : &$__rpackname__(@_); # Call newly loaded function :} : :# Load file and compile it, substituing the second stub function with the :# loaded ones. Location of the file uses the @AUTO array. :sub perload'load_from_file { : package perload; : local($file) = @_; # File to be loaded : local($body) = ' ' x 1024; # Pre-extent : local($load) = ' ' x 256; # Loading operations : # Avoid side effects by protecting special variables which will be : # changed by the autoloading operation. : local($., $_, $@); : $body = ''; : $load = ''; : &init_auto unless defined(@'AUTO); # Make sure we have a suitable @AUTO : &locate_file unless -f "$file"; # Locate file if relative path : open(FILE, $file) || : die "Can't load $'__rpackname__ from $file: $!\n"; : while () { : $load .= '*auto_' . $1 . '\'' . $2 . '= *' . $1 . '\'' . "load_$2;\n" : if (/^sub\s+(\w+)'load_(\w+)\s*\{/); : $body .= $_; : } : close FILE; EOC if ($opt_t) { print &q(<<'EOC'); : # Untaint body when running setuid : $body =~ /^([^\0]*)/; : # No need to untaint $load, as it was built using trusted variables : eval $1 . $load; EOC } else { print &q(<<'EOC'); : eval $body . $load; EOC } print &q(<<'EOC'); : chop($@) && die "$@, while parsing code of $file.\n"; :} : :# Initialize the @AUTO array. Attempt defining it by using the AUTOLIB :# environment variable if set, otherwise look in auto/ first, then in the :# current directory. :sub perload'init_auto { : if (defined $ENV{'AUTOLIB'} && $ENV{'AUTOLIB'}) { : @AUTO = split(':', $ENV{'AUTOLIB'}); : } else { : @AUTO = ('auto', '.'); : } :} : :# Locate to-be-loaded file held in $file by looking through the @AUTO array. :# This variable, defined in 'load_from_file', is modified as a side effect. :sub perload'locate_file { : package perload; : local($fullpath); : foreach $dir (@'AUTO) { : $fullpath = $dir . '/' . $file; : last if -f "$fullpath"; : $fullpath = ''; : } : $file = $fullpath if $fullpath; # Update var from 'load_from_file' :} : EOC } if (@Data > 0) { print &q(<<'EOC'); :# Load the calling function from DATA segment and call it. This function is :# called only once per routine to be loaded. :sub main'dataload { : package perload; : local($__packname__) = (caller(1))[3]; : $__packname__ =~ s/::/'/; : local($__rpackname__) = $__packname__; : local($__at__) = $@; : $__rpackname__ =~ s/^auto_//; : eval { load_from_data($__rpackname__, 0) }; : if ($@ eq "RETRY\n") { : undef %Datapos; : load_from_data($__rpackname__, 1); : } else { : die $@ if $@; : } : local($__fun__) = "$__rpackname__"; : $__fun__ =~ s/'/'load_/; : eval "*$__packname__ = *$__fun__;"; # Change symbol table entry : die $@ if $@; # Should not happen : $@ = $__at__; # Restore value $@ had on entrance : &$__fun__; # Call newly loaded function :} : :# Load function name given as argument, fatal error if not existent :sub perload'load_from_data { : package perload; : local ($name, $retried) = @_; : local($pos) = $Datapos{$name}; # Offset within DATA : # Avoid side effects by protecting special variables which will be changed : # by the dataloading operation. : local($., $_); : $pos = &fetch_function_code($name, $retried) unless $pos; : die "Function $name not found in data section.\n" unless $pos; : die "Cannot seek to $pos into data section.\n" : unless seek(main'DATA, $pos, 0); : local($/) = "\n}"; : local($body) = scalar(); : local $loaded = $name; : $loaded =~ s/^(.*?)'(.*)/sub ${1}'load_$2 {/;; : unless ($body =~ /\n\}$/s && substr($body, 0, length $loaded) eq $loaded) { : if ($retried) { : die "End of file found while loading $name.\n" : unless $body =~ /\n\}$/s; : die "Offset table garbled or file changed whilst loading $name.\n"; : } : die "RETRY\n"; : } : local $@; EOC if ($opt_t) { print &q(<<'EOC'); : # Untaint body when running setuid : $body =~ /^([^\0]*)/; : # Now we may safely eval it without getting an insecure dependency : eval $1; # Load function into perl space EOC } else { print &q(<<'EOC'); : eval $body; # Load function into perl space EOC } print &q(<<'EOC'); : chop($@) && die "$@, while parsing code of $_[0].\n"; :} : EOC print &q(<<'EOC') unless $opt_o; :# Parse text after the END token and record defined loadable functions (i.e. :# those whose name starts with load_) into the %Datapos array. Such function :# definitions must be left adjusted. Stop as soon as the function we want :# has been found. :sub perload'fetch_function_code { : package perload; : local($pos) = tell main'DATA; : local($in_function) = 0; : local($func_name); : local($., $_); : while () { : if (/^sub\s+(\w+)'load_(\w+)\s*\{/) { : die "DATA line $.: function $1'$2 defined within $func_name.\n" : if $in_function; : $func_name = $1 . '\'' . $2; : $Datapos{$func_name} = $pos; : $in_function = 1; : next; : } : $in_function = 0 if /^\}/; : next if $in_function; : return $pos if $func_name eq $_[0]; : $pos = tell main'DATA; : } : 0; # Function not found :} : EOC print &q(<<'EOC') if $opt_o; :# This function is called only once, and fills in the %Datapos array with :# the offset of each of the dataloaded routines held in the data section. :sub perload'fetch_function_code { : package perload; : local ($name, $retried) = @_; : local($start) = 0; : local($., $_); : if ($retried) { : my $date = scalar localtime; : warn("$0 probably changed, reloading offset table on $date\n"); : close(main'DATA); : open(main'DATA, $0) || die "Can't open $0 to reload offset table: $!\n"; : my $found = 0; : while () { : if (/^__END__\s$/) { $found++; last } : } : die "Unable to find __END__ token in $0\n" unless $found; : } : while () { # First move to start of offset table : next if /^#/; : last if /^$/ && ++$start > 2; # Skip two blank line after end token : } : $start = tell(main'DATA); # Offsets in table are relative to here : local($key, $value); : while () { # Load the offset table : last if /^$/; # Ends with a single blank line : ($key, $value) = split(' '); : $Datapos{$key} = $value + $start; : } : $Datapos{$name}; # All that pain to get this offset... :} : EOC print &q(<<'EOC'); :# :# The perl compiler stops here. :# : :__END__ : :# :# Beyond this point lie functions we may never compile. :# : EOC # Option -o directs us to optimize the function location by emitting an # offset table, which lists all the position within DATA for each possible # dataloaded routine. if ($opt_o) { print &q(<<'EOC'); :# :# DO NOT CHANGE A IOTA BEYOND THIS COMMENT! :# The following table lists offsets of functions within the data section. :# Should modifications be needed, change original code and rerun perload :# with the -o option to regenerate a proper offset table. :# : EOC $trailing_message = &q(<<'EOC'); : :# :# End of offset table and beginning of dataloading section. :# : EOC $pos = 0; # Offset relative to this point (start of table) foreach (@Data) { $Datapos{"$1\'$2"} = $pos - $now if /^sub\s+(\w+)'load_(\w+)\s*\{/; # } for vi $pos += length; } @poskeys = keys %Datapos; # Array of routine names (fully qualified) # Write out a formatted table, each entry stored on $entry bytes and # formatted with the $format string. ($entry, $format) = &get_format(*poskeys); # The total size occupied by the table is the size of one item times # the number of items plus the final trailing message at the end of # the table. $table_size = $entry * @poskeys + length($trailing_message); # Output formatted table foreach (sort @poskeys) { printf($format, $_, $table_size + $Datapos{$_}); } print $trailing_message; } # Output code for each dataloaded function foreach (@Data) { print; } print &q(<<'EOC'); :# :# End of dataloading section. :# : EOC } if (@auto > 0) { mkdir('auto',0755) unless -d 'auto'; foreach $file (@auto) { unless (open(AUTO, ">auto/$file")) { warn "Can't create auto/$file: $!\n"; next; } print AUTO &q(<<'EOC'); :# This file was generated by perload : EOC print AUTO $Auto{$file}; close AUTO; } } # Compute optimum format for routine offset table, returning both the size of # each entry and the formating string for printf. sub get_format { local(*names) = @_; local($name_len) = 0; local($max_len) = 0; foreach (@names) { $name_len = length; $max_len = $name_len if $name_len > $max_len; } # The size of each entry (preceded by one tab, followed by 12 chars) $name_len = $max_len + 1 + 12; ($name_len, "\t%${max_len}s %10d\n"); } sub emit_init { print &q(<<'EOC'); :# :# This perl program uses dynamic loading [generated by perload] :# : EOC $init_emitted = 1; } sub flush_comment { print @Comment if @Comment > 0; @Comment = (); } sub q { local($_) = @_; s/^://gm; $_; } # # These next few lines are legal in both perl and nroff. # .00; # finish .ig 'di \" finish diversion--previous line must be blank .nr nl 0-1 \" fake up transition to first page again .nr % 0 \" start at page 1 '; __END__ \" the perl compiler stops here ''' ''' From here on it's a standard manual page. ''' .TH PERLOAD 1 "June 20, 1992" .AT 3 .SH NAME perload \- builds up autoloaded and dataloaded perl scripts .SH SYNOPSIS .B perload [ \fB\-ot\fR ] [ \fIfile\fR ] .SH DESCRIPTION .I Perload takes a perl script as argument (or from stdin if no argument is supplied) and prints out on stdout an equivalent script set-up to perform autoloading or dataloading. The translation is directed by special comments within the original script. Using dynamic loading can drastically improve start-up performances, both in time and in memory, as perl does not need to compile the whole script nor store its whole compiled form in memory. .PP .I Autoloading delays compilation of some functions until they are needed. The code for these functions is loaded dynamically at run-time. The atomicity of loading is a file, which means that putting more than one function into a file will cause all these functions to be loaded and compiled as soon as one among them is needed. .PP .I Dataloading is a form of autoloading where no extra file are needed. The script carries all the functions whose compilation is to be delayed in its data segment (in the \fIperl\fR sense, i.e. they are accessible via the DATA filehandle). The scripts parses the data segment and extracts only the code for the needed subroutine, which means granularity is better than with autloading. .PP It is possible for a single script to use both autoloading and dataloading at the same time. However, it should be noted that a script using only dataloading is self contained and can be moved or shared accross different platforms without fear. On the contrary, a script using only autoloading relies on some externally provided files. Sharing this script among different platforms requires sharing of these external files. The script itself cannot be redistributed without also giving the extra files holding the autoloaded functions. .PP The major drawback with dataloading is that the DATA filehandle cannot be used for anything else and may result in code duplication when two scripts could share the same pieces of code. Autoloading appears as the perfect solution in this case since two scripts may freely share the same functions without actually duplicating them on the disk (hence saving some precious disk blocks :-). .SH CRITERIA Functions to be dataloaded or autoloaded must meet the following layout criteria: .TP 5 \- They must not be one-line functions like \fIsub sorter { $a <=> $b }\fR. Those functions are simply output verbatim, as they are already so small that it would not be worth to dynamically load them, .TP \- The first line must be of the form \fIsub routine_name {\fR, with an optional comment allowed after the '{'. .TP \- The function definition must end with a single '}' character left aligned. .TP \- Package directives outside any function must be left aligned. .PP All the above restrictions should not be source of a problem if "standard" writing style is used. There are also some name restrictions: the package name \fIperload\fR is reserved, as is the \fI@AUTO\fR array when autoloading is used. Packages must not start with \fIauto_\fR, as this is prepended to user's package names when building the stubs. Furthermore, the subroutines names \fImain'autoload\fR and \fImain'dataload\fR must not be used by the original script. Again, these should not cause any grief. .SH DIRECTIVES The translation performed by .I Perload is driven by some special comment directives placed directly within the code. Ending those directives with a ':' character will actually prevent them from being output into the produced script. Case is irrelevant for all the directives and the comment need not be left-aligned, although it must be the first non-space item on the line. .PP The following directives are available: .TP 10 # Perload ON Turns on the \fIperload\fR processing. Any function definition which meets the criteria listed in the previous section will be replaced by two stubs and its actual definition will be rejected into the data segment (default) or a file when inside an autoloading section. .TP # Perload OFF Turns off any processing. The script is written as-is on the standard output. .TP # Autoload \fIpath\fR Requests autoloading from file \fIpath\fR, which may be an absolute path or a relative path. The file will be located at run-time using the @AUTO array if a non-absolute path is supplied or if the file does not exist as listed. Autoloading directives may be nested. .TP # Offload \fIpath\fR The argument is not required. The directive ends the previous autoloading directive (the inmost one). This does not turn off the \fIperload\fR processing though. The \fIpath\fR name is optional here (in fact, it has only a comment value). .SH OPTIONS Perload accepts only two options. Using \fB\-o\fR is meaningful only when dataloading is used. It outputs an offset table which lists the relative offset of the dataloaded functions within the data section. This will spare perl the run-time parsing needed to locate the function, and results in an good speed gain. However, it has one major drawback: it prevents people from actually modifying the source beyond the start of the table. But anything before can be freely edited, which is particulary useful when tailoring the script. .PP This option should not be used when editing of functions within the data section is necessary for whatever reason. When \fB\-o\fR is used, any change in the dataloaded function must be committed by re-running perload on the original script. .PP The other option \fB\-t\fR is to be used when producing a script which is going to run setuid. The body of the loaded function is untainted before being fed to eval, which slightly slows down loading (the first time the function is called), but avoids either an insecure dependency report or weird warnings from taintperl stating something is wrong (which is the behaviour with 4.0 PL35). .SH FILES .TP 10 auto the subdirectory where all produced autoloaded files are written. .SH ENVIRONMENT No environment variables are used by \fIperload\fR. However, the autoloaded version of the script pays attention to the \fIAUTOLIB\fR variable as a colon separated set of directories where the to-be-loaded files are to be found when a non-absolute path was specified. If the \fIAUTOLIB\fR variable is not set, the default value 'auto:.' is used (i.e. look first in the auto/ subdirectory, then in the current directory. .SH CAVEAT Special care is required when using an autoloading script, especially when executed by the super-user: it would be very easy for someone to leave a special version of a routine to be loaded, in the hope the super-user (or another suitable target) executes the autoloaded version of the script with some \fIad hoc\fR changes... .PP The directory holding the to-be-loaded files should therefore be protected against unauthorized access, and no file should have write permission on them. The directory itself should not be world-writable either, or someone might substitute his own version. It should also be considered wise to manually set the @AUTO variable to a suitable value within the script itself. .PP The \fB\-o\fR option uses \fIperl\fR's special variable \fI$/\fR with a multi-character value. I suspect this did not work with versions of \fIperl\fR prior to 4.0, so any script using this optimized form of dataloading will not be 100% backward compatible. .SH AUTHOR Raphael Manfredi .SH CREDITS Valuable input came from Wayne H. Scott . He is merely the author of the optimizing offset table (\fB\-o\fR option). .PP .I Perload is based on an article from Tom Christiansen , .I Autoloading in Perl, explaining the concept of dataloading and giving a basic implementation. .SH "SEE ALSO" perl(1). mailagent-3.1-74.orig/bin/svn-revision0000755000175000017500000000225511017742366015752 0ustar jdgjdg#!/bin/sh # # $Id: svn-revision 12303 2006-11-11 08:11:46Z cbiere $ # # Copyright (c) 2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic Licence, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic Licence; a copy of which may be found at the root # of the source tree for dist 4.0. # # Computes SVN current revision number, if possible, emitting it in # the form of a #define for C perusal. # LC_ALL=C export LC_ALL TOP="$1" FILE="$2" if [ "x$FILE" = x ]; then FILE="&1" oldrev='' else oldrev=`grep REVISION "$FILE" 2>/dev/null | head -n1 | cut -d' ' -f3` fi if test -d "$TOP/.svn"; then revnum=`svn info "$TOP" 2>/dev/null | grep '^Revision' | head -n1 | cut -d' ' -f2` else revnum="$oldrev" # keep as is fi if [ "x$revnum" = "x$oldrev" ]; then exit 0 fi { stamp=`date +"%Y-%m-%d %H:%M:%d %z"` cat < "$FILE" mailagent-3.1-74.orig/agent/0000755000175000017500000000000011675050335013702 5ustar jdgjdgmailagent-3.1-74.orig/agent/Jmakefile0000644000175000017500000000401611052504354015507 0ustar jdgjdg/* * Jmakefile for mailagent */ ;# $Id: Jmakefile,v 3.0.1.4 1999/07/12 13:40:32 ram Exp ram $ ;# ;# Copyright (c) 1990-2006, Raphael Manfredi ;# ;# You may redistribute only under the terms of the Artistic License, ;# as specified in the README file that comes with the distribution. ;# You may reuse parts of this distribution only within the terms of ;# that same Artistic License; a copy of which may be found at the root ;# of the source tree for mailagent 3.0. ;# ;# $Log: Jmakefile,v $ ;# Revision 3.0.1.4 1999/07/12 13:40:32 ram ;# patch66: will now install examples as well ;# ;# Revision 3.0.1.3 1994/10/31 11:12:59 ram ;# patch23: file magent.sh now replaces magent.SH to avoid auto-extraction ;# ;# Revision 3.0.1.2 1994/10/29 17:37:48 ram ;# patch20: directory pl added to subdirs and depend lists ;# ;# Revision 3.0.1.1 1994/09/22 13:39:09 ram ;# patch12: new edusers script to edit users file ;# ;# Revision 3.0 1993/11/29 13:47:37 ram ;# Baseline for mailagent 3.0 netwide release. ;# BIN = mailpatch mailhelp maillist maildist package edusers NoManPages() ShellScriptTarget($(BIN)) SimpleShellScriptTargetExt(magent,.sh) /* The mailagent itself is derived from 'magent' through perload, hence * making the program more efficient (the whole script need not be compiled * by perl). */ AllTarget(mailagent) mailagent: magent perl $(TOP)/bin/perload -o magent > $@ chmod +rx $@ /* The mailagent carries some machine-dependant parts (for file locking) * so it is a binary, not a script (viz it may not be shared accross * different architectures). */ InstallScript(mailagent,$(BINDIR)) SetSubdirs(pl filter files man test examples) DependDirs(pl filter) RemoteDependency(pl/utmp,utmp.pl) RemoteDependency(pl/termios,termios.pl) BINSH = \ |expand f!$(BIN)! !f.SH \ -expand magent.sh depend:: ($(SED) '/^# DO NOT DELETE/q' Makefile && \ grep '^\$$grep' $(BINSH) | \ $(SED) -e "s/^.*' \([^ ]*\) >>\(.*\)/\2: \1/" \ ) > Makefile.new cp Makefile Makefile.bak cp Makefile.new Makefile $(RM) Makefile.new mailagent-3.1-74.orig/agent/edusers.SH0000755000175000017500000000721511030765550015615 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; *) TOP=..;; esac revision=`awk '/^#define[ ]*REVISION/ {print $3}' < $TOP/revision.h` case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/edusers (with variable substitutions)" $spitshell >edusers <>edusers <<'!NO!SUBS!' $userlist = "users"; $prog_name = $0; # Who I am $prog_name =~ s|^.*/(.*)|$1|; # Keep only base name $lockext = $long_filenames ? '.lock' : '!'; # Extension used by lock routines *add_log = *stderr_log; # Ensure logs will go to stderr also $EDITOR = $ENV{'EDITOR'} || $ENV{'VISUAL'} || $defeditor; &read_config; # First, read configuration file (in ~/.mailagent) &read_dist; # Read distributions &catch_signals; $system = shift; # Which system do we want $version = shift; # Which version it is # If no system is specified, try locating a '.package', then source it # to get information... if ($system eq '') { die "$prog_name: you must specify a system name\n" unless &read_package; $system = $pkg'package; $version = $pkg'baserev; } # A single '-' or a missing version means "highest available" version. $version = $Version{$system} if $version eq '-' || $version eq ''; # Full name of system for H table access $pname = $system . "|" . $version; die "$prog_name: no program called $system\n" unless $System{$system}; die "$prog_name: no package $system version $version\n" unless $Program{$pname}; # Go to the system directory. chdir "$Location{$pname}" || die "$prog_name: cannot go to $Location{$pname}\n"; -f $userlist || die "$prog_name: no $userlist file yet for $system $version.\n"; # Lock users file. That file should only be edited with the edusers script. die "$prog_name: cannot lock $userlist.\n" if 0 != &acs_rqst($userlist); system "$EDITOR $userlist"; warn "$prog_name: WARNING: edition failed...\n" if $?; &free_file($userlist); exit $?; !NO!SUBS! $grep -v '^;#' pl/fatal.pl >>edusers $grep -v '^;#' pl/add_log.pl >>edusers $grep -v '^;#' pl/read_conf.pl >>edusers $grep -v '^;#' pl/distribs.pl >>edusers $grep -v '^;#' pl/secure.pl >>edusers $grep -v '^;#' pl/cdir.pl >>edusers $grep -v '^;#' pl/acs_rqst.pl >>edusers $grep -v '^;#' pl/free_file.pl >>edusers $grep -v '^;#' pl/checklock.pl >>edusers $grep -v '^;#' pl/signals.pl >>edusers $grep -v '^;#' pl/package.pl >>edusers $grep -v '^;#' pl/hostname.pl >>edusers chmod 755 edusers $eunicefix edusers mailagent-3.1-74.orig/agent/test/0000755000175000017500000000000011675050334014660 5ustar jdgjdgmailagent-3.1-74.orig/agent/test/Jmakefile0000644000175000017500000000224010473324174016471 0ustar jdgjdg/* * Jmakefile for regression test suite. */ ;# $Id: Jmakefile,v 3.0 1993/11/29 13:49:20 ram Exp ram $ ;# ;# Copyright (c) 1990-2006, Raphael Manfredi ;# ;# You may redistribute only under the terms of the Artistic License, ;# as specified in the README file that comes with the distribution. ;# You may reuse parts of this distribution only within the terms of ;# that same Artistic License; a copy of which may be found at the root ;# of the source tree for mailagent 3.0. ;# ;# $Log: Jmakefile,v $ ;# Revision 3.0 1993/11/29 13:49:20 ram ;# Baseline for mailagent 3.0 netwide release. ;# >RM all:: @echo "The following may take a while..." @echo "Don't panic if any of these tests fails and do not stop make."; \ ./TEST @if test -f OK; then \ echo "Failure detected, retrying one more time, just in case..."; \ echo "Successful tests will not be rerun but flagged as 'done'."; \ sleep 2; \ ./TEST; \ if test -f OK; then \ echo "Hmm... Still failed... There might be a real problem."; \ echo "I shall be using the plain (non dataloaded) version."; \ sleep 2;\ ./TEST -n; \ fi \ fi test: ./TEST -i local_clean:: $(RM) -r out $(RM) OK mailagent-3.1-74.orig/agent/test/level0000644000175000017500000000000310473324174015704 0ustar jdgjdg20 mailagent-3.1-74.orig/agent/test/basic/0000755000175000017500000000000011675050333015740 5ustar jdgjdgmailagent-3.1-74.orig/agent/test/basic/filter.t0000644000175000017500000000515110473324174017416 0ustar jdgjdg# Make sure filter queues messages correctly # $Id: filter.t,v 3.0.1.3 1999/01/13 18:16:41 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: filter.t,v $ # Revision 3.0.1.3 1999/01/13 18:16:41 ram # patch64: agent.wait file moved from queue to spool dir # # Revision 3.0.1.2 1995/08/07 16:27:05 ram # patch37: added support for locking on filesystems with short filenames # # Revision 3.0.1.1 1993/12/15 09:05:53 ram # patch3: now make sure that filter.lock has correct timestamp # # Revision 3.0 1993/11/29 13:49:24 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; do '../pl/logfile.pl'; chdir '../out' || exit 0; open(WAIT, ">agent.wait") || print "1\n"; close WAIT; `chmod u-w queue`; $? == 0 || print "2\n"; # Use the special undocumented -t option from filter to get HOME directory # via environment instead of /etc/passwd. open(FILTER, "|$filter -t >/dev/null 2>&1") || print "3\n"; print FILTER <; if (-f "$file") { chop($what = `cat agent.wait`); chop($pwd = `pwd`); $what eq "$pwd/$file" || print "8\n"; unlink "$file"; } else { print "8\n"; } `chmod u+w queue`; unlink 'agent.wait', 'agentlog'; open(FILTER, "|$filter -t >/dev/null 2>&1") || print "9\n"; print FILTER <; -f "$file" || print "13\n"; # Must have been left in queue unlink "$file", 'agentlog'; # Make sure file is correctly queued when another filter is running unlink "filter$lockext"; # In case an old one remains `cp /dev/null filter$lockext`; # Make sure we have a new fresh one $? == 0 || print "14\n"; open(FILTER, "|$filter -t >/dev/null 2>&1") || print "15\n"; print FILTER <; -f "$file" || print "19\n"; # Must have been left in queue as a 'fm' file unlink "$file", 'agentlog', "filter$lockext"; print "0\n"; mailagent-3.1-74.orig/agent/test/basic/config.t0000644000175000017500000000755710473324174017412 0ustar jdgjdg# This MUST be the first test ever run # $Id: config.t,v 3.0.1.8 1999/01/13 18:16:19 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: config.t,v $ # Revision 3.0.1.8 1999/01/13 18:16:19 ram # patch64: test for non-writable agent.wait file # # Revision 3.0.1.7 1997/02/20 11:48:11 ram # patch55: avoid exec-safe checks and group-writable directories # # Revision 3.0.1.6 1997/01/07 18:36:24 ram # patch52: force execsafe to OFF when running tests # # Revision 3.0.1.5 1996/12/24 15:01:24 ram # patch45: added locksafe, set to OFF # # Revision 3.0.1.4 1995/01/25 15:31:46 ram # patch27: now sets a default umask in the configuration # # Revision 3.0.1.3 1995/01/03 18:20:00 ram # patch24: temporary directory is now local, don't clobber /tmp # # Revision 3.0.1.2 1994/09/22 14:40:52 ram # patch12: added callout queue file definition # # Revision 3.0.1.1 1994/04/25 15:24:33 ram # patch7: added commented 'fromesc' new variable # # Revision 3.0 1993/11/29 13:49:23 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; do '../pl/logfile.pl'; chdir '../out' || exit 0; chop($pwd = `pwd`); $path = $ENV{'PATH'}; $host = $ENV{'HOST'}; $host =~ s/-/_/g; # Filter translates '-' into '_' in hostnames $user = $ENV{'USER'}; open(CONFIG, ">.mailagent") || print "1\n"; print CONFIG </dev/null 2>&1") || print "3\n"; print FILTER <; if (-f "$file") { open(FILE, $file) || print "5\n"; @file = ; close FILE; $file[0] eq "Dummy mail\n" || print "6\n"; unlink "$file"; } else { print "5\n"; # No emergency dump } -s 'agentlog' || print "6\n"; # No logfile or empty &get_log(7); &check_log('FATAL', 8); # There must be a FATAL &check_log('MTA', 9); # Filter must think mail is in MTA's queue &check_log('updating PATH', 10); # Make sure hostname is computed &check_log('unable to queue', 11); # Filter did not queue mail unlink 'agentlog'; `mkdir queue`; `chmod u+w agent.wait`; $? == 0 || print "12\n"; # Cannot make queue print "0\n"; mailagent-3.1-74.orig/agent/test/basic/mailagent.t0000644000175000017500000000556711031240252020066 0ustar jdgjdg# Basic mailagent test: ensure it is correctly invoked by filter. # $Id: mailagent.t,v 3.0.1.2 1996/12/24 15:02:07 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: mailagent.t,v $ # Revision 3.0.1.2 1996/12/24 15:02:07 ram # patch45: ensure we quote upper path properly, in case @ is there! # # Revision 3.0.1.1 1995/08/07 16:27:11 ram # patch37: added support for locking on filesystems with short filenames # # Revision 3.0 1993/11/29 13:49:25 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; do '../pl/logfile.pl'; $user = $ENV{'USER'}; chdir '../out' || exit 0; # Make sure we'll find the mailagent system 'perl', '-i', '-p', '-e', "s|^path.*|path :.:\Q$up\E|", '.mailagent'; $? == 0 || print "1\n"; unlink '.cache'; # Make sure no cached rules yet open(RULES, ">.rules") || print "2\n"; print RULES "{ DELETE };\n"; close RULES; unlink ; open(FILTER, "|$filter -t >>.bak 2>&1") || print "3\n"; print FILTER <; @files == 0 || print "9\n"; # Queued mail deleted when filtered unlink 'agentlog', '.rules'; sleep 1 while -f "perl$lockext"; # Let background mailagent die # Check empty rules... open(FILTER, "|$filter -t >>.bak 2>&1") || print "10\n"; print FILTER <; @files == 0 || print "17\n"; # Queued mail deleted when filtered -f 'context' && print "18\n"; # Empty context must be deleted unlink 'agentlog', "$user"; sleep 1 while -f "perl$lockext"; # Let background mailagent die # Make sure file is correctly queued when another mailagent is running `cp /dev/null perl$lockext`; $? == 0 || print "19\n"; open(FILTER, "|$filter -t >>.bak 2>&1") || print "20\n"; print FILTER <; -f "$file" || print "24\n"; # Must have been left in queue as a 'fm' file -s '.cache' || print "25\n"; # Rules are cached in ~/.cache unlink "$file", 'agentlog', "perl$lockext"; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/0000755000175000017500000000000011675050334015423 5ustar jdgjdgmailagent-3.1-74.orig/agent/test/cmd/biff.t0000644000175000017500000000531711032356704016521 0ustar jdgjdg# The BIFF command # $Id: biff.t,v 3.0.1.1 1995/08/07 16:28:37 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: biff.t,v $ # Revision 3.0.1.1 1995/08/07 16:28:37 ram # patch37: created # do '../pl/cmd.pl'; sub cleanup { unlink $user, 'tty0', 'tty1', 'tty3', 'ok'; } &cleanup; &make_tty(0, 0777, 1); # 1 & 2 &make_tty(1, 0666, 3); # 3 & 4 &make_tty(3, 0777, 5); # 5 & 6 sub make_tty { local($n, $mode, $log) = @_; open(TTY, ">tty$n") || print "$log\n"; $log++; close TTY; chmod($mode, "tty$n") || print "$log\n"; } open(BIFF, '>bfmt') || print "7\n"; print BIFF <<'EOM'; Got mail in %f: %-H %-B ##### EOM close BIFF; &add_header('X-Tag: biff 1'); `$cmd`; $? == 0 || print "8\n"; -f $user || print "9\n"; -f 'ok' || print "10\n"; -s 'tty1' && print "11\n"; -s 'tty0' || print "12\n"; -s 'tty3' || print "13\n"; -s('tty0') == -s('tty3') || print "14\n"; $dflt_size = -s 'tty0'; &get_log(15, 'tty0'); &check_log('^\rTo: ram', 16) == 1 || print "17\n"; &check_log('^\r----', 18) == 2 || print "19\n"; ¬_log('^\r####', 20); unlink $user, 'ok'; &replace_header('X-Tag: biff 2'); `$cmd`; $? == 0 || print "21\n"; -f $user || print "22\n"; -f 'ok' || print "23\n"; -s('ok') == -s($user) || print "24\n"; -s 'tty1' && print "25\n"; -s 'tty0' || print "26\n"; -s 'tty3' || print "27\n"; -s('tty0') == -s('tty3') || print "28\n"; -s('tty0') != $dflt_size || print "29\n"; &get_log(30, 'tty0'); &check_log('^\rTo: ram', 31) == 1 || print "32\n"; &check_log('^Got mail in ~/ok', 33) == 1 || print "34\n"; &check_log('^\r####', 35) == 1 || print "36\n"; &check_log('moderated usenet', 37) == 1 || print "38\n"; ¬_log('^\r----', 39); &cleanup; cp_mail("../mime"); &add_header('X-Tag: biff 3'); &make_tty(0, 0777, 40); # 40 & 41 `$cmd`; $? == 0 || print "41\n"; -f 'ok' || print "42\n"; -s 'tty0' || print "43\n"; &get_log(44, 'tty0'); ¬_log('--foo', 45); &check_log('^Got mail in ~/ok', 46) == 1 || print "47\n"; &check_log('successfully decoded', 48) == 1 || print "49\n"; &cleanup; cp_mail("../qp"); my $subject = <list') || print "13\n"; print LIST < comp`; $? == 0 || print "3\n"; `grep -v Subject: mail > ok`; ((-s 'comp') - 1) == -s 'ok' || print "4\n"; # SAVE adds extra final new-line -s 'comp' != -s 'output' || print "5\n"; # Casually check X-Filter was there unlink 'output', 'mail', 'ok', 'comp'; cp_mail("../base64"); add_header('X-Tag: purify 2'); `$cmd`; $? == 0 || print "6\n"; &get_log(7, 'output'); &check_log('successfully', 8); unlink 'output', 'mail'; cp_mail("../qp"); add_header('X-Tag: purify 2'); `$cmd`; $? == 0 || print "9\n"; &get_log(10, 'output'); ¬_log('brok=', 11); # Body must have been recoded ¬_log("char '=3D'!", 12); &check_log("broken", 13); unlink 'output', 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/macro.t0000644000175000017500000000153110473324174016712 0ustar jdgjdg# Test MACRO command # $Id: macro.t,v 3.0 1993/11/29 13:49:34 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: macro.t,v $ # Revision 3.0 1993/11/29 13:49:34 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink 'ok'; &add_header('X-Tag: macro'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Mail not saved -f 'ok' || print "3\n"; # Output of /bin/echo &get_log(4, 'ok'); &check_log('^It seems to work fine.', 5); # It works unlink 'ok', 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/require.t0000644000175000017500000000213010473324174017261 0ustar jdgjdg# Test REQUIRE command # $Id: require.t,v 3.0 1993/11/29 13:49:45 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: require.t,v $ # Revision 3.0 1993/11/29 13:49:45 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink 'perl.1', 'perl.2', 'never', 'ok'; open(PERL, ">perl.1") || print "1\n"; print PERL <<'EOP'; sub perl_1 { local($name) = @_; $name; } EOP close PERL; open(PERL, ">perl.2") || print "2\n"; print PERL <<'EOP'; $var = "perl_2"; sub perl_2 { $var; } EOP close PERL; &add_header('X-Tag: require'); `$cmd`; $? == 0 || print "3\n"; -f "$user" && print "4\n"; -f 'never' && print "5\n"; &get_log(6, 'ok'); &check_log('^We got perl_1 and perl_2 here', 7); unlink 'mail', 'perl.1', 'perl.2', 'never', 'ok'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/tr.t0000644000175000017500000000246010473324174016240 0ustar jdgjdg# The TR command # $Id: tr.t,v 3.0.1.1 2001/03/13 13:16:19 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: tr.t,v $ # Revision 3.0.1.1 2001/03/13 13:16:19 ram # patch71: added test cases for TR on header fields # # Revision 3.0 1993/11/29 13:49:53 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink 'output'; &add_header('X-Tag: tr #1'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; -f 'output' || print "3\n"; chop ($output = `cat output 2>/dev/null`); $output eq 'RAM@EIFFEL.COM,' . 'RE: mEltIng ICE tEChnology?,'. 'RE: mEltIng ICE tEChnology?' || print "4\n"; unlink 'output'; sub cleanup { unlink 'subst', 'always', 'never', 'never2'; } &cleanup; &replace_header('X-Tag: tr #2'); `$cmd`; $? == 0 || print "5\n"; -f 'subst' || print "6\n"; -f 'always' || print "7\n"; -f 'never' && print "8\n"; -f 'never2' && print "9\n"; get_log(10, 'subst'); not_log('^Received: .*[A-Z]', 11); unlink 'mail'; &cleanup; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/perl.t0000644000175000017500000000255310473324174016560 0ustar jdgjdg# Test PERL command # $Id: perl.t,v 3.0.1.1 1994/07/01 15:08:05 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: perl.t,v $ # Revision 3.0.1.1 1994/07/01 15:08:05 ram # patch8: added test for correct exit status propagation # # Revision 3.0 1993/11/29 13:49:38 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink 'perl.1', 'perl.2', 'never', 'always', 'exit_ok'; open(PERL, ">perl.1") || print "1\n"; print PERL <<'EOP'; &save('always') || &save('never'); &reject('-t'); &save('never'); EOP close PERL; open(PERL, ">perl.2") || print "2\n"; print PERL <<'EOP'; unlink 'always' if -d '../out'; &exit(1) if $ARGV[1] ne 'arg 1' || $ARGV[2] ne 'arg 2'; &perl('perl.1'); # Recursion &save('never'); EOP close PERL; &add_header('X-Tag: perl'); `$cmd`; $? == 0 || print "3\n"; -f "$user" && print "4\n"; -f 'never' && print "5\n"; &get_log(6, 'always'); &check_log('^To: ram', 7) == 2 || print "8\n"; -f 'exit_ok' || print "9\n"; unlink 'mail', 'perl.1', 'perl.2', 'never', 'always', 'exit_ok'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/leave.t0000644000175000017500000000416310473324174016711 0ustar jdgjdg# Test LEAVE command # $Id: leave.t,v 3.0.1.1 1994/07/01 15:07:21 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: leave.t,v $ # Revision 3.0.1.1 1994/07/01 15:07:21 ram # patch8: added tests for new fromall config option # # Revision 3.0 1993/11/29 13:49:33 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/misc.pl'; # Need &add_option also &add_header('X-Tag: leave'); `$cmd`; $? == 0 || print "1\n"; -f "$user" || print "2\n"; # Mail saved here by default # When mailbox protected against writing... unlink ; $size = -s "$user"; chmod 0444, "$user"; `$cmd`; $? == 0 || print "3\n"; -f "$user" || print "4\n"; # Must still be there $size == -s "$user" || print "5\n"; # And not altered @emerg = ; @emerg == 1 || print "6\n"; # Emeregency as LEAVE failed # There is no X-Filter mail in the emergency saving `grep -v X-Filter: $user > ok`; $? == 0 || print "7\n"; -s $emerg[0] eq -s 'ok' || print "8\n"; # Full mail saved, of course # Make sure From within body is escaped if preceded by blank line &add_header("\nFrom mailagent"); # In effect adds an EOH &add_body(<<'NEW'); The following introduces a leading From line NOT preceded by a blank line From my point of view, the preceding should be escaped. NEW unlink "$user"; `$cmd`; $? == 0 || print "9\n"; -f "$user" || print "10\n"; # Must still be there &get_log(11, $user); &check_log('^>From', 12) == 2 || print "13\n"; &check_log('^From line', 14) == 1 || print "15\n"; # Make sure all From lines are escaped when fromall is activated. &add_option('-o fromall:ON'); unlink "$user"; `$cmd`; $? == 0 || print "16\n"; -f "$user" || print "17\n"; &get_log(18, $user); &check_log('^>From', 19) == 3 || print "20\n"; ¬_log('^From line', 21); unlink ; unlink "$user", 'mail', 'ok'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/store.t0000644000175000017500000000341410473324174016747 0ustar jdgjdg# The STORE command # $Id: store.t,v 3.0 1993/11/29 13:49:50 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: store.t,v $ # Revision 3.0 1993/11/29 13:49:50 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; $mbox = 'mbox'; &add_header('X-Tag: store #1'); `$cmd`; $? == 0 || print "1\n"; -f "$mbox" || print "2\n"; # Mail saved here -f "$user" || print "3\n"; # Leave copy in mailbox -s "$mbox" == -s "$user" || print "4\n"; # Same content # When mailbox protected against writing... unlink ; unlink "$user"; $size = -s "$mbox"; chmod 0444, "$mbox"; `$cmd`; $? == 0 || print "5\n"; -f "$mbox" || print "6\n"; # Must still be there $size == -s "$mbox" || print "7\n"; # And not altered -f "$user" || print "8\n"; # Left only copy in mailbox $size == -s "$user" || print "9\n"; # Which must also match in size @emerg = ; @emerg == 1 || print "10\n"; # Emeregency as SAVE failed # There is no X-Filter mail in the emergency saving `grep -v X-Filter: $mbox > ok`; $? == 0 || print "11\n"; -s $emerg[0] eq -s 'ok' || print "12\n"; # Full mail saved, of course unlink "$mbox", "$user"; # Make sure STORE creates full path when needed &replace_header('X-Tag: store #2'); `rm -rf path` if -d 'path'; `$cmd`; $? == 0 || print "13\n"; -f 'path/another/third/mbox' || print "14\n"; -f "$user" || print "15\n"; `rm -rf path` if -d 'path'; unlink ; unlink "$mbox", "$user", 'mail', 'ok'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/reject.t0000644000175000017500000000172410473324174017071 0ustar jdgjdg# The REJECT command # $Id: reject.t,v 3.0 1993/11/29 13:49:44 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: reject.t,v $ # Revision 3.0 1993/11/29 13:49:44 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink "$user.1", 'always', 'never'; # Make sure everything after a REJECT is not executed &add_header('X-Tag: reject'); `$cmd`; $? == 0 || print "1\n"; -f "$user" || print "2\n"; # REJECT -> no match -> leave -f "$user.1" && print "3\n"; # This SAVE was after the REJECT -f 'always' || print "4\n"; -f 'never' && print "5\n"; unlink "$user.1", "$user", 'always', 'never', 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/protect.t0000644000175000017500000000256010473324174017274 0ustar jdgjdg# Test PROTECT command # $Id: protect.t,v 3.0.1.1 1995/01/25 15:33:20 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: protect.t,v $ # Revision 3.0.1.1 1995/01/25 15:33:20 ram # patch27: created # do '../pl/cmd.pl'; sub cleanup { unlink $user, 'fold.1', 'fold.2', 'fold.3', 'fold.4', 'fold.5', 'dflt'; } &cleanup; &add_header('X-Tag: protect'); `$cmd`; $? == 0 || print "2\n"; -f $user && print "3\n"; -f 'dflt' || print "4\n"; -f 'fold.1' || print "5\n"; -f 'fold.2' || print "6\n"; -f 'fold.3' || print "7\n"; -f 'fold.4' || print "8\n"; -f 'fold.5' || print "9\n"; ((2 * -s('fold.1')) == -s('dflt')) || print "10\n"; # Two saves in dflt sub st_mode { (stat($_[0]))[2] & 0777; } &st_mode('dflt') == oct("0644") || print "11\n"; # Not altered by PROTECT &st_mode('fold.1') == oct("0444") || print "12\n"; &st_mode('fold.2') == oct("0666") || print "13\n"; &st_mode('fold.3') == oct("0444") || print "14\n"; &st_mode('fold.4') == oct("0444") || print "15\n"; &st_mode('fold.5') == oct("0644") || print "16\n"; &cleanup; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/umask.t0000644000175000017500000000422110473324174016730 0ustar jdgjdg# Test UMASK command # $Id: umask.t,v 3.0.1.3 1996/12/24 15:02:36 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: umask.t,v $ # Revision 3.0.1.3 1996/12/24 15:02:36 ram # patch45: fixed test for perl5 # # Revision 3.0.1.2 1995/02/03 18:05:08 ram # patch30: fixed regexp bug that could lead the test to fail # # Revision 3.0.1.1 1994/07/01 15:08:10 ram # patch8: created # do '../pl/misc.pl'; # Uses &add_option sub cleanup { unlink $user, 'ok.1', 'ok.2', 'ok.3', 'never'; } open(PERL, ">umask_is") || print "1\n"; print PERL <<'EOP'; $mode = $ARGV[1]; $mode = oct($mode) if $mode =~ /^0/; # In perl5 the sub umask declaration in the mailhook package interferes # with the umask built-in. Therefore, we must ensure we call the # right version while running this PERL hook. To avoid an eval, we # simply switch to package main while calling umask! { package main; $mailhook'umask = umask; } &exit($mode == $umask ? 0 : 1); EOP close PERL; &cleanup; &add_header('X-Tag: umask #1'); `$cmd`; $? == 0 || print "2\n"; -f $user && print "3\n"; -f 'never' && print "4\n"; -f 'ok.1' || print "5\n"; -f 'ok.2' || print "6\n"; &cleanup; &replace_header('X-Tag: umask #3'); system '(cat mail; echo " "; cat mail) > mail2 && mv mail2 mail'; print "7\n" if $?; $cmd =~ s/($mailagent.*)\bmail\b/$1-f mail/; # exclude path... &add_option("-o 'umask: 027'"); &replace_header('X-Tag: umask #2'); # At this point, we're going to process two messages in mail. The first # one is tagged 'umask #2' and the second is tagged 'umask #3'. We wish # to make sure that mailagent restores the default umask before processing # a new message. `$cmd`; $? == 0 || print "8\n"; -f $user && print "9\n"; -f 'never' && print "10\n"; -f 'ok.1' || print "11\n"; -f 'ok.2' || print "12\n"; -f 'ok.3' || print "13\n"; &cleanup; unlink 'umask_is'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/run.t0000644000175000017500000000147710473324174016426 0ustar jdgjdg# The RUN command # $Id: run.t,v 3.0 1993/11/29 13:49:47 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: run.t,v $ # Revision 3.0 1993/11/29 13:49:47 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink 'ok'; &add_header('X-Tag: run'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Mail not saved -f 'ok' || print "3\n"; # Output of /bin/echo &get_log(4, 'ok'); &check_log('Works.', 5); # It works unlink 'ok', 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/back.t0000644000175000017500000000211110473324174016504 0ustar jdgjdg# Test BACK command # $Id: back.t,v 3.0 1993/11/29 13:49:28 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: back.t,v $ # Revision 3.0 1993/11/29 13:49:28 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink 'output'; open(PGM, ">pgm") || print "1\n"; print PGM '/bin/echo "RUN /bin/echo it works! > output; SAVE other"', "\n"; close PGM; chmod 0755, 'pgm'; &add_header('X-Tag: back'); `$cmd`; $? == 0 || print "2\n"; -f 'output' || print "3\n"; # Where output is created chop($output = `cat output 2>/dev/null`); $output eq 'it works!' || print "4\n"; -f 'other' || print "5\n"; # Mail also saved -f "$user" && print "6\n"; # So default action does not apply unlink 'pgm', 'output', 'mail', 'other'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/unique.t0000644000175000017500000000547510473324174017132 0ustar jdgjdg# The UNIQUE command # $Id: unique.t,v 3.0.1.1 1994/01/26 09:36:02 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: unique.t,v $ # Revision 3.0.1.1 1994/01/26 09:36:02 ram # patch5: added tests for tag support # # Revision 3.0 1993/11/29 13:49:53 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink "$user.1", "$user.2", "$user.3"; &add_header('X-Tag: unique #1'); `rm -rf dbr` if -d 'dbr'; `$cmd`; $? == 0 || print "1\n"; -f "$user.1" || print "2\n"; # Was saved, first time. unlink "$user.1"; -d 'dbr' || print "3\n"; # Make sure history recording works -f 'dbr/i/e' || print "4\n"; # Hashing done on domain name `$cmd`; $? == 0 || print "5\n"; -f "$user.1" && print "6\n"; # We rejected this time, NOT in SEEN mode -f "$user.2" || print "7\n"; # And saved it here unlink "$user.2"; &replace_header('X-Tag: unique #2'); `$cmd`; $? == 0 || print "8\n"; -f "$user.1" && print "9\n"; # We restarted this time -f "$user.3" || print "10\n"; # And caught that rule -f "$user" && print "11\n"; # Nothing here unlink "$user.3"; &replace_header('X-Tag: unique #3'); `$cmd`; $? == 0 || print "12\n"; -f "$user.1" && print "13\n"; # We aborted -f "$user" && print "14\n"; # Must not be there (tagged as saved) unlink "$user.1", "$user"; &replace_header('X-Tag: unique #4'); `$cmd`; $? == 0 || print "15\n"; -f "$user.1" && print "16\n"; # We rejected -f "$user.2" || print "17\n"; # Must be there (saved in mode UNIQUE) -f "$user" && print "18\n"; unlink "$user.1", "$user.2", $user; &replace_header('X-Tag: unique #5'); `$cmd`; $? == 0 || print "19\n"; -f "$user.1" || print "20\n"; # First time with both tags tag1 and tag2 -f "$user.2" && print "21\n"; # Can't be there (tag2 already recorded) -f "$user.3" && print "22\n"; # Can't be there (already recorded previously) -f "$user" && print "23\n"; &get_log(24, 'dbr/i/e'); &check_log('$', 25) == 1 || print "26\n"; &check_log('$', 27) == 1 || print "28\n"; &check_log('cambridge', 29) == 3 || print "30\n"; unlink "$user.1", "$user.2", "$user.3", $user; &replace_header('X-Tag: unique #6'); `rm -rf dbr` if -d 'dbr'; `$cmd`; $? == 0 || print "31\n"; -f "$user.1" || print "32\n"; # First time with tag 'tag' -f "$user.2" || print "33\n"; # Tag 'other' distinct from 'tag' -f "$user.3" && print "34\n"; # Sorry, already recorded -f "$user" && print "35\n"; &get_log(36, 'dbr/i/e'); &check_log('cambridge', 37) == 2 || print "38\n"; `rm -rf dbr` if -d 'dbr'; unlink "$user", "$user.1", "$user.2", "$user.3", 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/annotate.t0000644000175000017500000000232210473324174017421 0ustar jdgjdg# Test ANNOTATE command # $Id: annotate.t,v 3.0.1.1 1995/01/03 18:20:17 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: annotate.t,v $ # Revision 3.0.1.1 1995/01/03 18:20:17 ram # patch24: added tests for new -u option # # Revision 3.0 1993/11/29 13:49:26 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; sub cleanup { unlink "$user", 'never'; } &cleanup; &add_header('X-Tag: annotate'); `$cmd`; $? == 0 || print "1\n"; -f "$user" || print "2\n"; # No match -> leave &get_log(3, $user); &check_log('^X-Anno-1:', 4) == 2 || print "5\n"; &check_log('^X-Anno-2:', 6) == 2 || print "7\n"; &check_log('^X-Anno-3:', 8) == 1 || print "9\n"; &check_log('^X-Anno-4:', 10) == 2 || print "11\n"; # No RESYNC done ¬_log('^X-Anno-Error:', 12); &check_log('^X-Anno-5:', 13) == 1 || print "14\n"; -f 'never' && print "15\n"; &cleanup; unlink 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/process.t0000644000175000017500000000114310473324174017266 0ustar jdgjdg# The PROCESS command # $Id: process.t,v 3.0 1993/11/29 13:49:40 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: process.t,v $ # Revision 3.0 1993/11/29 13:49:40 ram # Baseline for mailagent 3.0 netwide release. # print "-1\n"; # Automatic testing difficult mailagent-3.1-74.orig/agent/test/cmd/forward.t0000644000175000017500000000341111024562140017242 0ustar jdgjdg# Test FORWARD command # $Id: forward.t,v 3.0 1993/11/29 13:49:31 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: forward.t,v $ # Revision 3.0 1993/11/29 13:49:31 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; do '../pl/mta.pl'; &add_header('X-Tag: forward 1'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Mail not saved &get_log(4, 'send.mail'); &check_log('^Resent-', 5) == 2 || print "6\n"; &check_log('^Resent-To: nobody', 7) == 1 || print "8\n"; &check_log('^To: ram', 9) == 1 || print "10\n"; &check_log('^Recipients: nobody$', 11) == 1 || print "12\n"; open(LIST, '>list') || print "13\n"; print LIST <msend'); print MSEND <<'EOM'; #!/bin/sh exit 1 EOM close MSEND; `$cmd`; $? == 0 || print "25\n"; -f "$user" && print "26\n"; # Mail not saved -f 'ok' || print "27\n"; # Failure caught by "REJECT -f" &clear_mta; unlink 'mail', 'list', 'ok'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/queue.t0000644000175000017500000000161510473324174016740 0ustar jdgjdg# Test QUEUE command # $Id: queue.t,v 3.0 1993/11/29 13:49:41 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: queue.t,v $ # Revision 3.0 1993/11/29 13:49:41 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink ; &add_header('X-Tag: queue'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Mail queued -> saved @queue = ; @queue == 4 || print "3\n"; $size = -s 'mail'; $ok = 1; foreach (@queue) { $ok == 0 if $size != -s $_; } $ok || print "4\n"; unlink ; unlink 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/feed.t0000644000175000017500000000442211030471671016511 0ustar jdgjdg# Test FEED command # $Id: feed.t,v 3.0 1993/11/29 13:49:31 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: feed.t,v $ # Revision 3.0 1993/11/29 13:49:31 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink 'ok', 'resynced'; &add_header('X-Tag: feed 1'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Mail saved... &get_log(3, 'ok'); # ...here &check_log('^$', 4); # EOH present ¬_log('^To:', 5); # Make sure To: disappeared -f 'resynced' || print "6\n"; # Ensure RESYNC was done under the hood unlink 'ok', 'resynced', 'mail'; # PIPE checks base64, FEED checks quoted-printable &cp_mail("../qp"); &add_header('X-Tag: feed 2'); `$cmd`; $? == 0 || print "7\n"; get_log(8, 'output'); check_log('Content-Transfer-Encoding: quoted-printable', 9); not_log('broken', 10); &check_log('^$', 11); # EOH present unlink 'output', "$user"; &replace_header('X-Tag: feed 3'); `$cmd`; $? == 0 || print "12\n"; get_log(13, 'output'); not_log('Content-Transfer-Encoding:', 14); check_log('broken', 15); &check_log('^$', 16); # EOH present get_log(17, $user); check_log('Content-Transfer-Encoding: quoted-printable', 18); not_log('broken', 19); unlink 'output', "$user"; &replace_header('X-Tag: feed 4'); `$cmd`; $? == 0 || print "20\n"; get_log(21, 'output'); not_log('Content-Transfer-Encoding:', 22); check_log('broken', 23); &check_log('^$', 24); # EOH present get_log(25, $user); check_log('Content-Transfer-Encoding: quoted-printable', 26); not_log('broken', 27); unlink 'output', "$user"; # Check that message will be recoded optimally as 7bit &cp_mail("../base64"); &add_header('X-Tag: feed 4'); `$cmd`; $? == 0 || print "28\n"; get_log(29, 'output'); not_log('Content-Transfer-Encoding:', 30); check_log('successfully', 31); check_log('^$', 32); # EOH present get_log(33, $user); check_log('Content-Transfer-Encoding: 7bit', 34); check_log('successfully', 35); unlink 'output', 'mail', "$user"; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/save.t0000644000175000017500000000445110473324174016553 0ustar jdgjdg# The SAVE command # $Id: save.t,v 3.0.1.2 1995/03/21 12:59:28 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: save.t,v $ # Revision 3.0.1.2 1995/03/21 12:59:28 ram # patch35: fixed rename() syntax for perl 4.0 # # Revision 3.0.1.1 1995/02/16 14:38:56 ram # patch32: added checks for new fromfake config variable # # Revision 3.0 1993/11/29 13:49:48 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/misc.pl'; # Need &add_option also $mbox = 'mbox'; &add_header('X-Tag: save #1'); `$cmd`; $? == 0 || print "1\n"; -f "$mbox" || print "2\n"; # Mail saved here -f "$user" && print "3\n"; # Must not exist (yet) # When mailbox protected against writing... unlink ; $size = -s "$mbox"; chmod 0444, "$mbox"; `$cmd`; $? == 0 || print "4\n"; -f "$mbox" || print "5\n"; # Must still be there $size == -s "$mbox" || print "6\n"; # And not altered @emerg = ; @emerg == 1 || print "7\n"; # Emeregency as SAVE failed -f "$user" || print "8\n"; # Not saved -> leave in mbox -s "$user" == -s "$mbox" || print "9\n"; # There is no X-Filter mail in the emergency saving `grep -v X-Filter: $mbox > ok`; $? == 0 || print "10\n"; -s $emerg[0] eq -s 'ok' || print "11\n"; # Full mail saved, of course unlink "$mbox", "$user"; # Make sure SAVE creates full path when needed &replace_header('X-Tag: save #2'); `rm -rf path` if -d 'path'; `$cmd`; $? == 0 || print "12\n"; -f 'path/another/third/mbox' || print "13\n"; `rm -rf path` if -d 'path'; unlink ; unlink 'ok'; # Ensure fromfake works as advertised, i.e. that it creates a valid From: # header when it is missing. `grep -v '^From: ' mail >mail2`; $? == 0 || print "14\n"; rename('mail2', 'mail'); &replace_header('X-Tag: save #3'); `$cmd`; $? == 0 || print "15\n"; -f 'ok' || print "16\n"; $size = -s 'ok'; &add_option('-o fromfake: OFF'); `$cmd`; $? == 0 || print "17\n"; &get_log(18, 'ok'); &check_log('^From: ', 19) == 1 || print "20\n"; unlink "$mbox", "$user", 'mail', 'ok'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/once.t0000644000175000017500000000345510473324174016544 0ustar jdgjdg# The ONCE command and autocleaning feature # $Id: once.t,v 3.0 1993/11/29 13:49:37 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: once.t,v $ # Revision 3.0 1993/11/29 13:49:37 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink 'one', 'two', 'three', 'four', "$user"; &add_header('X-Tag: once'); `rm -rf dbr` if -d 'dbr'; `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; -f 'one' || print "3\n"; -f 'two' && print "4\n"; -f 'three' || print "5\n"; -f 'four' || print "6\n"; -d 'dbr' || print "7\n"; @files = ; @files == 3 || print "8\n"; # Make sure ONCE dbr database not disturbed by autocleaning, and, along # the way, check that auto cleaning is correctly run. $level = $ENV{'LEVEL'}; `$mailagent -L $level -q -o 'autoclean: ON' 2>/dev/null`; $? == 0 || print "9\n"; @new_files = ; @new_files == @files || print "10\n"; unlink 'one', 'two', 'three', 'four', "$user"; -f 'context' || print "11\n"; `$cmd`; $? == 0 || print "12\n"; -f "$user" && print "13\n"; -f 'one' && print "14\n"; -f 'two' && print "15\n"; -f 'three' && print "16\n"; -f 'four' || print "17\n"; -d 'dbr' || print "18\n"; # Make sure autocleaning leaves things in a coherent state `$mailagent -q -L $level -o 'autoclean: ON' -o 'agemax: 0m' 2>/dev/null`; -d 'dbr' && print "19\n"; -f 'context' || print "20\n"; `$mailagent -q -L $level 2>/dev/null`; -f 'context' && print "21\n"; unlink 'one', 'two', 'three', 'four', "$user", 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/delete.t0000644000175000017500000000131710473324174017055 0ustar jdgjdg# Test DELETE command # $Id: delete.t,v 3.0 1993/11/29 13:49:30 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: delete.t,v $ # Revision 3.0 1993/11/29 13:49:30 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; &add_header('X-Tag: delete'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Mail deleted unlink 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/unknown.t0000644000175000017500000000167410473324174017320 0ustar jdgjdg# Ensure unknown command defaults to LEAVE only when no saving was done # $Id: unknown.t,v 3.0 1993/11/29 13:49:54 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: unknown.t,v $ # Revision 3.0 1993/11/29 13:49:54 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink "$user"; &add_header('X-Tag: unknown #1'); `$cmd`; $? == 0 || print "1\n"; -f "$user" || print "2\n"; # Unknown was first unlink "$user"; &replace_header('X-Tag: unknown #2'); `$cmd`; $? == 0 || print "3\n"; -f "$user" && print "4\n"; # Unknown after saving status known unlink "$user", 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/record.t0000644000175000017500000000550610473324174017075 0ustar jdgjdg# The RECORD command # $Id: record.t,v 3.0.1.1 1994/01/26 09:35:57 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: record.t,v $ # Revision 3.0.1.1 1994/01/26 09:35:57 ram # patch5: added tests for tag support # # Revision 3.0 1993/11/29 13:49:42 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink "$user.1", "$user.2", "$user.3"; &add_header('X-Tag: record #1'); `rm -rf dbr` if -d 'dbr'; `$cmd`; $? == 0 || print "1\n"; -f "$user.1" || print "2\n"; # Was saved, first time. unlink "$user.1"; -d 'dbr' || print "3\n"; # Make sure history recording works -f 'dbr/i/e' || print "4\n"; # Hashing done on domain name `$cmd`; $? == 0 || print "5\n"; -f "$user.1" && print "6\n"; # We rejected this time, in SEEN mode -f "$user.2" || print "7\n"; # And saved it here unlink "$user.2"; &replace_header('X-Tag: record #2'); `$cmd`; $? == 0 || print "8\n"; -f "$user.1" && print "9\n"; # We restarted this time -f "$user.3" || print "10\n"; # And caught that rule in RECORD mode -f "$user" && print "11\n"; # Nothing here unlink "$user.3"; &replace_header('X-Tag: record #3'); `$cmd`; $? == 0 || print "12\n"; -f "$user.1" && print "13\n"; # We aborted -f "$user" || print "14\n"; # Must be there (aborted, no match) unlink "$user.1", "$user"; &replace_header('X-Tag: record #4'); `$cmd`; $? == 0 || print "15\n"; -f "$user.1" && print "16\n"; # We rejected -f "$user.2" || print "17\n"; # Must be there (saved in mode RECORD) -f "$user" && print "18\n"; unlink "$user.1", "$user.2", $user; &replace_header('X-Tag: record #5'); `$cmd`; $? == 0 || print "19\n"; -f "$user.1" || print "20\n"; # First time with both tags tag1 and tag2 -f "$user.2" && print "21\n"; # Can't be there (tag2 already recorded) -f "$user.3" && print "22\n"; # Can't be there (already recorded previously) -f "$user" && print "23\n"; &get_log(24, 'dbr/i/e'); &check_log('$', 25) == 1 || print "26\n"; &check_log('$', 27) == 1 || print "28\n"; &check_log('cambridge', 29) == 3 || print "30\n"; unlink "$user.1", "$user.2", "$user.3", $user; &replace_header('X-Tag: record #6'); `rm -rf dbr` if -d 'dbr'; `$cmd`; $? == 0 || print "31\n"; -f "$user.1" || print "32\n"; # First time with tag 'tag' -f "$user.2" || print "33\n"; # Tag 'other' distinct from 'tag' -f "$user.3" && print "34\n"; # Sorry, already recorded -f "$user" && print "35\n"; &get_log(36, 'dbr/i/e'); &check_log('cambridge', 37) == 2 || print "38\n"; `rm -rf dbr` if -d 'dbr'; unlink "$user", "$user.1", "$user.2", "$user.3", 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/after.t0000644000175000017500000000111210473324174016705 0ustar jdgjdg# The AFTER command # $Id: after.t,v 3.0.1.1 1994/09/22 14:40:57 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: after.t,v $ # Revision 3.0.1.1 1994/09/22 14:40:57 ram # patch12: created # print "-1\n"; # Automatic testing difficult mailagent-3.1-74.orig/agent/test/cmd/assign.t0000644000175000017500000000207710473324174017103 0ustar jdgjdg# Test ASSIGN command # $Id: assign.t,v 3.0 1993/11/29 13:49:27 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: assign.t,v $ # Revision 3.0 1993/11/29 13:49:27 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink 'output'; &add_header('X-Tag: assign #1'); `$cmd`; $? == 0 || print "1\n"; -f 'output' || print "2\n"; # Result of various assign commands chop($output = `cat output 2>/dev/null`); $output eq 'ram,try,try.2' || print "3\n"; unlink 'output'; &replace_header('X-Tag: assign #2'); `$cmd`; $? == 0 || print "4\n"; -f 'output' || print "5\n"; # Result of various assign commands chop($output = `cat output 2>/dev/null`); $output eq '7,1+2,7' || print "6\n"; unlink 'output', 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/server.t0000644000175000017500000000114010473324174017113 0ustar jdgjdg# The SERVER command # $Id: server.t,v 3.0 1993/11/29 13:49:49 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: server.t,v $ # Revision 3.0 1993/11/29 13:49:49 ram # Baseline for mailagent 3.0 netwide release. # print "-1\n"; # Automatic testing difficult mailagent-3.1-74.orig/agent/test/cmd/nop.t0000644000175000017500000000135110473324174016405 0ustar jdgjdg# The NOP command # $Id: nop.t,v 3.0 1993/11/29 13:49:35 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: nop.t,v $ # Revision 3.0 1993/11/29 13:49:35 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; # Make sure NOP is recognized (not defaulted to LEAVE) &add_header('X-Tag: nop'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; unlink 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/notify.t0000644000175000017500000000507210473324174017125 0ustar jdgjdg# Test NOTIFY command # $Id: notify.t,v 3.0.1.3 1995/01/25 15:32:47 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: notify.t,v $ # Revision 3.0.1.3 1995/01/25 15:32:47 ram # patch27: ported to perl 5.0 PL0 # # Revision 3.0.1.2 1994/10/10 10:25:55 ram # patch19: added various escapes in strings for perl5 support # # Revision 3.0.1.1 1994/01/26 09:35:34 ram # patch5: ensure header-added recipients looked for in messages # # Revision 3.0 1993/11/29 13:49:36 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; do '../pl/mta.pl'; open(MSG, '>msg') || print "1\n"; print MSG <msg.2') || print "21\n"; print MSG <<'EOM'; Cc: someone@random, %u Organization: Public Domain Software, Earth, Milkway. Message body. EOM close MSG; &add_header('X-Tag: notify 1'); `$cmd`; $? == 0 || print "2\n"; -f "$user" && print "3\n"; # Mail not saved &get_log(4, 'send.mail'); &check_log('^$', 5) == 1 || print "6\n"; &check_log('^Subject: Re: melting', 7) == 1 || print "8\n"; &check_log('^Recipients: nobody$', 9) == 1 || print "10\n"; &check_log('^Sent by compilers-request.$', 11) == 1 || print "12\n"; open(LIST, '>list') || print "13\n"; print LIST <mail"); close MAIL; &make_digest('Not empty digest header'); `cp digest mail`; &add_header('X-Tag: split #5'); `$cmd`; $? == 0 || print "62\n"; -f 'here' || print "63\n"; # Where digest was split... &get_log(64, 'here'); # Slurp folder in @log &check_log('^X-Tag: digest #1', 65) == 1 || print "66\n"; &check_log('^X-Tag: digest #3', 67) == 1 || print "68\n"; ¬_log('^X-Tag: digest #2', 69); # Empty second message ¬_log('Mailagent-Test-Suite', 70); # No trailing garbage &check_log('^X-Filter-Note:', 71) == 2 || print "72\n"; &check_log('^From ', 73) == 4 || print "74\n"; # One built up for last item &check_log('^Message-Id:', 75) == 1 || print "76\n"; &check_log('^>From', 80) == 2 || print "81\n"; &check_log('^From which', 82) == 1 || print "83\n"; unlink 'here', 'mail.lock'; # Sixth time: mail is not in digest format. `cp ../mail .`; $? == 0 || print "77\n"; # Fool guard for myself &add_header('X-Tag: split #5'); `$cmd`; $? == 0 || print "78\n"; -f 'here' || print "79\n"; # Where mail was saved (not in digest format) unlink 'mail', 'here', 'digest'; # Last is 85 print "0\n"; # Build digest out of mail sub make_digest { local($msg) = @_; # Optional, first line in header &get_log(100, 'mail'); # Slurp mail in @log open(DIGEST, ">digest"); print DIGEST < To: postmaster\@eiffel.com Subject: Mail Report - 10/07 $msg ---------------------------------------------- From ram Sun Jul 12 18:20:27 PDT 1992 From: ram Subject: Notice X-Tag: digest #1 Just to tell you there was no digest header... unless $msg set ---- EOH print DIGEST @log; print DIGEST <<'EOM'; ---- From: ram X-Tag: digest #3 From line should be >escaped. Another message with a really minimum set of header!! From which should NOT be From escaped again... ---- EOM if ($msg eq '') { print DIGEST <<'EOM'; This is trailing garbage. I will use the SPLIT command with the '-w' option and this will be saved is a separate mail with the subject taken from that of the whole digest, with the words (trailing garbage) appended to it... This token, "anticonstitutionellement " will make it obvious for grep -- it's the longest word in French, and it means the government is not doing its job, roughly speaking :-). EOM } else { print DIGEST <<'EOM'; End of digest Mailagent-Test-Suite ********************************** EOM } close DIGEST; } mailagent-3.1-74.orig/agent/test/cmd/beep.t0000644000175000017500000000265710473324174016536 0ustar jdgjdg# The BEEP command # $Id: beep.t,v 3.0.1.2 1995/08/07 16:27:31 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: beep.t,v $ # Revision 3.0.1.2 1995/08/07 16:27:31 ram # patch37: added regression testing for BEEP # # Revision 3.0.1.1 1995/01/25 15:32:12 ram # patch27: created # do '../pl/cmd.pl'; sub cleanup { unlink $user, 'tty0'; } &cleanup; &make_tty(0, 0777, 1); # 1 & 2 sub make_tty { local($n, $mode, $log) = @_; open(TTY, ">tty$n") || print "$log\n"; $log++; close TTY; chmod($mode, "tty$n") || print "$log\n"; } open(BIFF, '>bfmt') || print "3\n"; print BIFF <<'EOM'; Got mail in %f:%a #%b EOM close BIFF; &add_header('X-Tag: beep 1'); `$cmd`; $? == 0 || print "4\n"; -f $user || print "5\n"; -s 'tty0' || print "6\n"; &get_log(7, 'tty0'); &check_log('^Got mail.*:\07\07\07\07$', 8); &check_log('^\r#\07$', 9); unlink $user; &replace_header('X-Tag: beep 2'); `$cmd`; $? == 0 || print "10\n"; -f $user || print "11\n"; -s 'tty0' || print "12\n"; &get_log(13, 'tty0'); &check_log('^Got mail.*:$', 14); &check_log('^\r#\07$', 15); unlink $user; &cleanup; unlink 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/strip.t0000644000175000017500000000346710473324174016764 0ustar jdgjdg# Test STRIP command # $Id: strip.t,v 3.0 1993/11/29 13:49:51 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: strip.t,v $ # Revision 3.0 1993/11/29 13:49:51 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink 'ok', 'no_resync'; open(LIST, '>header-list') || print "17\n"; print LIST <.vacation') || print "1\n"; print VACATION <.vacfile') || print "43\n"; print VACATION </dev/null`); $output eq 'ram@eiffel.fr,melting ice technology?,melting ice technology?' || print "4\n"; unlink 'output'; sub cleanup { unlink 'subst', 'always', 'never', 'never2'; } &cleanup; &replace_header('X-Tag: subst #2'); `$cmd`; $? == 0 || print "5\n"; -f 'subst' || print "6\n"; -f 'always' || print "7\n"; -f 'never' && print "8\n"; -f 'never2' && print "9\n"; get_log(10, 'subst'); check_log('^Received: from eiffel\.chram\.org by lyon\.chram\.org', 11) == 1 || print "12\n"; check_log('^Received: .*\.chram\.org ', 13) == 2 || print "14\n"; check_log('AA21794', 15) == 1 || print "16\n"; unlink 'mail'; &cleanup; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/pass.t0000644000175000017500000000365411024437250016560 0ustar jdgjdg# The PASS command # $Id: pass.t,v 3.0.1.2 1994/10/10 10:26:01 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: pass.t,v $ # Revision 3.0.1.2 1994/10/10 10:26:01 ram # patch19: added various escapes in strings for perl5 support # # Revision 3.0.1.1 1994/04/25 15:25:22 ram # patch7: now make sure From line escaping is correctly removed # # Revision 3.0 1993/11/29 13:49:37 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/misc.pl'; unlink 'output'; &add_header('X-Tag: pass 1'); &add_option("-o 'fromesc: OFF'"); open(MAIL, '>>mail'); print MAIL <From test bug reported by Andy Seaborne EOM close MAIL; `$cmd`; $? == 0 || print "1\n"; -f 'output' || print "2\n"; # Where mail is saved `grep -v X-Filter: output > comp`; $? == 0 || print "3\n"; `grep -v and mail > ok`; # SAVE adds extra final new-line, but the leading '>' from From is removed (-s 'comp') == -s 'ok' || print "4\n"; -s 'comp' != -s 'output' || print "5\n"; # Casually check X-Filter was there &get_log(6, 'output'); &check_log('^From test bug', 7) == 1 || print "8\n"; unlink 'output', 'mail', 'ok', 'comp'; cp_mail("../base64"); add_header('X-Tag: pass 2'); `$cmd`; $? == 0 || print "9\n"; &get_log(10, 'output'); ¬_log('successfully', 11); &check_log('base64-encoded', 12); unlink 'output', 'mail'; cp_mail("../qp"); add_header('X-Tag: pass 3'); `$cmd`; $? == 0 || print "13\n"; &get_log(14, 'output'); ¬_log('brok=', 15); # Line was passed decoded, so this was stripped &check_log("char '=3D'!", 16); # Still encoded in quoted-printable unlink 'output', 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/pipe.t0000644000175000017500000000303111030471671016536 0ustar jdgjdg# The PIPE command # $Id: pipe.t,v 3.0 1993/11/29 13:49:39 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: pipe.t,v $ # Revision 3.0 1993/11/29 13:49:39 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink 'output'; &add_header('X-Tag: pipe 1'); `$cmd`; $? == 0 || print "1\n"; -f 'output' || print "2\n"; # Where output is created chop($output = `cat output 2>/dev/null`); @output = split(' ', $output); @valid = (35, 230, 1634); # Output of wc on whole mail with X-Tag field $ok = 1; for ($i = 0; $i < 3; $i++) { $ok = 0 if $valid[$i] != $output[$i]; } $ok || print "3\n"; -f "$user" || print "4\n"; # Default action applies unlink 'output', 'mail', "$user"; # PIPE checks base64, FEED checks quoted-printable &cp_mail("../base64"); &add_header('X-Tag: pipe 2'); `$cmd`; $? == 0 || print "5\n"; get_log(6, 'output'); check_log('Content-Transfer-Encoding: base64', 7); not_log('successfully', 8); check_log('^$', 9); # EOH present unlink 'output', "$user"; &replace_header('X-Tag: pipe 3'); `$cmd`; $? == 0 || print "10\n"; get_log(11, 'output'); not_log('Content-Transfer-Encoding:', 12); check_log('successfully', 13); unlink 'output', 'mail', "$user"; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/begin.t0000644000175000017500000000166210473324174016702 0ustar jdgjdg# Test BEGIN command # $Id: begin.t,v 3.0 1993/11/29 13:49:28 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: begin.t,v $ # Revision 3.0 1993/11/29 13:49:28 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink 'one', 'two', 'three'; &add_header('X-Tag: begin'); `$cmd`; $? == 0 || print "1\n"; -f 'one' && print "2\n"; # Cannot happen in TWO mode -f 'two' || print "3\n"; # Must be saved here -f 'three' || print "4\n"; # And also here by THREE mode -f "$user" && print "5\n"; # So default action did not apply unlink 'one', 'two', 'three', 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/apply.t0000644000175000017500000000400210473324174016732 0ustar jdgjdg# Test APPLY command # $Id: apply.t,v 3.0.1.1 1999/07/12 13:56:51 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: apply.t,v $ # Revision 3.0.1.1 1999/07/12 13:56:51 ram # patch66: added test for variable propagation # # Revision 3.0 1993/11/29 13:49:26 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; sub cleanup { unlink 'apply.1', 'apply.2', 'never', 'always', 'folder'; } &cleanup; open(RULES, ">apply.1") || print "1\n"; print RULES <<'EOR'; # Make sure there is no side effect with calling environment wrt states To: ram { BEGIN OTHER; APPLY apply.2; REJECT -f; BEGIN IMPOSSIBLE }; # This one will be called recursively from apply.2 { ABORT }; { SAVE never }; EOR close RULES; open(RULES, ">apply.2") || print "2\n"; print RULES <<'EOR'; # We are in OTHER mode when called from apply.1 { SAVE always; BEGIN APPLY_2; APPLY apply.1; REJECT -t }; # Called from main 'actions' file. { SAVE always }; { SAVE never }; EOR close RULES; &add_header('X-Tag: apply #1'); `$cmd`; $? == 0 || print "3\n"; -f "$user" && print "4\n"; -f 'never' && print "5\n"; &get_log(6, 'always'); &check_log('^To: ram', 7) == 3 || print "8\n"; &cleanup; open(RULES, ">apply.1") || print "9\n"; print RULES <<'EOR'; # Ensure non-persistent variables are propagated back and forth through APPLY { SAVE %#folder; ASSIGN folder always; }; EOR close RULES; &replace_header('X-Tag: apply #2'); `$cmd`; $? == 0 || print "10\n"; -f "$user" && print "11\n"; -f "never" && print "12\n"; -f "folder" || print "13\n"; -f "always" || print "14\n"; unlink 'mail', 'mbox'; # 'mbox' is the default mailbox if no args to SAVE &cleanup; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/write.t0000644000175000017500000000346010473324174016746 0ustar jdgjdg# The WRITE command # $Id: write.t,v 3.0 1993/11/29 13:49:55 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: write.t,v $ # Revision 3.0 1993/11/29 13:49:55 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; $mbox = 'mbox'; &add_header('X-Tag: write #1'); `$cmd`; $? == 0 || print "1\n"; -f "$mbox" || print "2\n"; # Mail saved here -f "$user" && print "3\n"; # Must not exist (yet) # When mailbox protected against writing... unlink ; $size = -s "$mbox"; chmod 0444, "$mbox"; `$cmd`; $? == 0 || print "4\n"; -f "$mbox" || print "5\n"; # Must still be there $size == -s "$mbox" || print "6\n"; # And not altered @emerg = ; @emerg == 1 || print "7\n"; # Emeregency as SAVE failed -f "$user" || print "8\n"; # Not saved -> leave in mbox -s "$user" == -s "$mbox" || print "9\n"; # There is no X-Filter mail in the emergency saving `grep -v X-Filter: $mbox > ok`; $? == 0 || print "10\n"; -s $emerg[0] eq -s 'ok' || print "11\n"; # Full mail saved, of course # Now verify WRITE actually overwrites the contentes unlink "$user"; chmod 0644, "$mbox"; `$cmd`; $? == 0 || print "12\n"; $size == -s "$mbox" || print "13\n"; -f "$user" && print "14\n"; # Make sure WRITE creates full path when needed &replace_header('X-Tag: write #2'); `rm -rf path` if -d 'path'; `$cmd`; $? == 0 || print "15\n"; -f 'path/another/third/mbox' || print "16\n"; `rm -rf path` if -d 'path'; unlink ; unlink "$mbox", "$user", 'mail', 'ok'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/do.t0000644000175000017500000000244010473324174016213 0ustar jdgjdg# Test DO command # $Id: do.t,v 3.0.1.1 1994/09/22 14:41:01 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: do.t,v $ # Revision 3.0.1.1 1994/09/22 14:41:01 ram # patch12: created # do '../pl/cmd.pl'; sub cleanup { unlink 'perl.1', 'perl.2', 'never', 'always', 'always.2'; } &cleanup; open(PERL, ">perl.1") || print "1\n"; print PERL <<'EOP'; sub perl_1 { local($name) = @_; &mailhook'save($name); } EOP close PERL; open(PERL, ">perl.2") || print "2\n"; print PERL <<'EOP'; sub perl_2 { return if defined &main'perl_1; return unless defined &__test__'perl_1; local($mode) = @_; &mailhook'reject($mode); } sub __foo__'perl_3 { local($name) = @_; return unless defined &perl_2; return if defined $name; &mailhook'abort; } EOP close PERL; &add_header('X-Tag: do'); `$cmd`; $? == 0 || print "3\n"; -f "$user" && print "4\n"; -f 'never' && print "5\n"; -f 'always' || print "6\n"; -f 'always.2' || print "7\n"; unlink 'mail'; &cleanup; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/give.t0000644000175000017500000000270211024437250016535 0ustar jdgjdg# Test GIVE command # $Id: give.t,v 3.0 1993/11/29 13:49:32 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: give.t,v $ # Revision 3.0 1993/11/29 13:49:32 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink 'output'; &add_header('X-Tag: give 1'); `$cmd`; $? == 0 || print "1\n"; -f 'output' || print "2\n"; # Where output is created chop($output = `cat output 2>/dev/null`); @output = split(' ', $output); @valid = (17, 132, 804); # Output of wc on body $ok = 1; for ($i = 0; $i < 3; $i++) { $ok = 0 if $valid[$i] != $output[$i]; } $ok || print "3\n"; -f "$user" || print "4\n"; # Default action applies unlink 'output', 'mail', "$user"; &cp_mail("../base64"); &add_header('X-Tag: give 2'); `$cmd`; $? == 0 || print "5\n"; &get_log(6, 'output'); &check_log('successfully decoded', 7) == 1 || print "8\n"; unlink 'output', 'mail', "$user"; &cp_mail("../qp"); &add_header('X-Tag: give 2'); `$cmd`; $? == 0 || print "9\n"; &get_log(10, 'output'); &check_log('broken', 11) == 1 || print "12\n"; &check_log('Raphaël', 13) == 1 || print "14\n"; unlink 'output', 'mail', "$user"; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/keep.t0000644000175000017500000000344610473324174016544 0ustar jdgjdg# Test KEEP command # $Id: keep.t,v 3.0 1993/11/29 13:49:33 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: keep.t,v $ # Revision 3.0 1993/11/29 13:49:33 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink 'ok', 'no_resync'; open(LIST, '>header-list') || print "17\n"; print LIST < no leave -f 'always' || print "4\n"; unlink "$user", "$user.1", 'always', 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/on.t0000644000175000017500000000152110473324174016224 0ustar jdgjdg# The ON command # $Id: on.t,v 3.0.1.1 1998/03/31 15:29:01 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: on.t,v $ # Revision 3.0.1.1 1998/03/31 15:29:01 ram # patch59: created # do '../pl/cmd.pl'; sub cleanup { unlink 'days', $user; } &cleanup; &add_header('X-Tag: on'); `$cmd`; $? == 0 || print "1\n"; -f $user || print "2\n"; -f 'days' || print "3\n"; -s $user || print "4\n"; -s($user) == -s('days') || print "5\n"; # One save made only into 'days' unlink 'mail'; &cleanup; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/bounce.t0000644000175000017500000000315111024562140017052 0ustar jdgjdg# Test BOUNCE command # $Id: bounce.t,v 3.0 1993/11/29 13:49:29 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: bounce.t,v $ # Revision 3.0 1993/11/29 13:49:29 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; do '../pl/mta.pl'; &add_header('X-Tag: bounce 1'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Mail not saved &get_log(4, 'send.mail'); ¬_log('^Resent-', 5); # Bounce does not add any Resent- headers &check_log('^To: ram', 6) == 1 || print "7\n"; open(LIST, '>list') || print "8\n"; print LIST <msend'); print MSEND <<'EOM'; #!/bin/sh exit 1 EOM close MSEND; `$cmd`; $? == 0 || print "17\n"; -f "$user" && print "18\n"; # Mail not saved -f 'ok' || print "19\n"; # Failure caught by "REJECT -f" &clear_mta; unlink 'mail', 'list', 'ok'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/restart.t0000644000175000017500000000166310473324174017303 0ustar jdgjdg# The RESTART command # $Id: restart.t,v 3.0 1993/11/29 13:49:46 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: restart.t,v $ # Revision 3.0 1993/11/29 13:49:46 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink "$user.1", 'never'; # Make sure everything after a RESTART is not executed &add_header('X-Tag: restart'); `$cmd`; $? == 0 || print "1\n"; -f "$user" || print "2\n"; # RESTART -> no match -> leave -f "$user.1" && print "3\n"; # This SAVE was after the RESTART -f 'never' && print "4\n"; # Idem unlink "$user.1", "$user", 'never', 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/cmd/message.t0000644000175000017500000000442410473324174017241 0ustar jdgjdg# Test MESSAGE command # $Id: message.t,v 3.0.1.3 1995/01/25 15:32:42 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: message.t,v $ # Revision 3.0.1.3 1995/01/25 15:32:42 ram # patch27: ported to perl 5.0 PL0 # # Revision 3.0.1.2 1994/10/10 10:25:49 ram # patch19: added various escapes in strings for perl5 support # # Revision 3.0.1.1 1994/01/26 09:35:22 ram # patch5: ensure header-added recipients looked for in messages # # Revision 3.0 1993/11/29 13:49:34 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; do '../pl/mta.pl'; open(MSG, '>msg') || print "1\n"; print MSG <msg.2') || print "13\n"; print MSG <<'EOM'; Cc: some@random.ctry, %u Organization: Public Domain Software, Earth, Milkway. Body of message. EOM close MSG; &add_header('X-Tag: message 1'); `$cmd`; $? == 0 || print "2\n"; -f "$user" && print "3\n"; # Mail not saved &get_log(4, 'send.mail'); &check_log('^$', 5) == 2 || print "6\n"; &check_log('^Subject: Re: melting', 7) == 1 || print "8\n"; &check_log('^Recipients: compilers-request\@iecc', 9) == 1 || print "10\n"; &check_log('^Sent by compilers-request.$', 11) == 1 || print "12\n"; unlink 'send.mail', $user; &replace_header('X-Tag: message 2'); `$cmd`; $? == 0 || print "14\n"; -f "$user" && print "15\n"; # Mail not saved &get_log(16, 'send.mail'); &check_log('^$', 17) == 1 || print "18\n"; &check_log('^Subject: Re: melting', 19) == 1 || print "20\n"; $recipients = join(' ', sort split(' ', "compilers-request\@iecc.cambridge.ma.us some\@random.ctry $user")); $recipients =~ s/@/\\@/g; # Escape all @ for perl5, grrr... &check_log("^Recipients: $recipients", 21) == 1 || print "22\n"; &check_log('^Cc: some\@random.ctry, ' . $user, 23) == 1 || print "24\n"; &clear_mta; unlink 'mail', 'msg', 'msg.2', $user; # Last is 24 print "0\n"; mailagent-3.1-74.orig/agent/test/base640000644000175000017500000000171211024437250015662 0ustar jdgjdgFrom raphael_manfredi@pobox.com Tue Jun 10 17:44:12 2008 Received: from tours.ram.loc (fetchmail@localhost [127.0.0.1]) by tours.ram.loc (8.14.3/8.13.8/Debian-3) with ESMTP id m5AFiCJq002957 for ; Tue, 10 Jun 2008 17:44:12 +0200 From: "Raphael Manfredi" To: "Raphael Manfredi" Date: Tue, 10 Jun 2008 15:35:21 +0000 Subject: Sample base64 encoding Message-ID: Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 MIME-Version: 1.0 Content-Length: 346 Lines: 6 VGhpcyBtZXNzYWdlIGlzIG9uZSBiaWcgTUlNRSBwYXJ0IHRoYXQgaGFzIGJlZW4gYmFzZTY0LWVu Y29kZWQuDQoNClRoZSBtYWlsYWdlbnQgdGVzdCBzdWl0ZSBpcyBnb2luZyB0byBsb29rIGZvciB0 aGUgZm9sbG93aW5nIGxpbmU6DQoNCiAgICAgICAgKioqIFlFUywgc3VjY2Vzc2Z1bGx5IGRlY29k ZWQgKioqDQoNCmluIHRoZSBkZWNvZGVkIGJvZHkgYXMgcHJvb2YgdGhhdCB0aGUgYmFzZTY0IGRl Y29kaW5nIGxvZ2ljIGlzIHdvcmtpbmcuDQo= mailagent-3.1-74.orig/agent/test/qp0000644000175000017500000000174411024437250015223 0ustar jdgjdgFrom raphael_manfredi@pobox.com Tue Jun 10 17:44:12 2008 Received: from tours.ram.loc (fetchmail@localhost [127.0.0.1]) by tours.ram.loc (8.14.3/8.13.8/Debian-3) with ESMTP id m5AFiCJq002957 for ; Tue, 10 Jun 2008 17:44:12 +0200 From: "Raphael Manfredi" To: "Raphael Manfredi" Date: Tue, 10 Jun 2008 15:35:21 +0000 Subject: Sample quoted-printable encoding Message-ID: Content-Type: text/plain; charset="iso8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Lines: 7 This is a first line of pure ASCII text This second line contains the word 'Rapha=EBl' This third line is much longer than 76 chars and therefore needs to be brok= en up smartly This fourth line contains the naughty char '=3D'! This fifth line is unreadable: =E0=E9=F4=EA=E8=E0=E9=F4=EA=E8=E0=E9=F4=EA= =E8=E0=E9=F4=EA=E8=E0=E9=F4=EA=E8=E0=E9=F4=EA=E8=E0=E9=F4=EA=E8, yeah! mailagent-3.1-74.orig/agent/test/atail0000644000175000017500000000360210473324174015677 0ustar jdgjdg: # feed this into perl eval 'exec perl -S $0 "$@"' if $running_under_some_shell; # $Id: atail,v 3.0.1.1 1994/09/22 14:40:37 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: atail,v $ # Revision 3.0.1.1 1994/09/22 14:40:37 ram # patch12: created # # Active monitoring of out/agentlog. This is going to be a CPU hog, but is # intended to debug stall cases or weird mailagent errors. # Launched automatically with the -m (monitor) option of TEST. # Aborts when parent becomes init after 5 seconds of delay, just in case # the TEST program dies without having a chance to kill us. $LOG = 'out/agentlog'; # Log file $open = 0; # True when file opened $size = 0; # Last file size $SIG{'ALRM'} = 'check_parent'; alarm(5); select STDOUT; $| = 1; for (;;) { &close_file if !-e $LOG && $open; next unless -f _; &new_file unless $open; &check_size if $open; } # Log file disappeared sub close_file { print "** Log removed\n"; close LOG; $open = 0; $size = 0; } # File reappeared sub new_file { print "** New log file\n"; open(LOG, $LOG); $open = 1; } # Print whatever there is in the file after $size bytes sub check_size { $now = -s _; if ($now < $size) { print "** Replaced log file\n"; open(LOG, $LOG); $size = 0; } seek(LOG, $size, 0); sysread(LOG, $buf, $now - $size); $size = $now; print $buf; } # Make sure our parent is not init sub check_parent { die "atail: parent process died, exiting\n" if getppid == 1; # Don't know whether perl re-instantiates handlers when kernel doesn't $SIG{'ALRM'} = 'check_parent'; alarm(5); } mailagent-3.1-74.orig/agent/test/option/0000755000175000017500000000000011675050334016170 5ustar jdgjdgmailagent-3.1-74.orig/agent/test/option/l.t0000644000175000017500000000427310473324174016617 0ustar jdgjdg# -l: list message queue (special) # $Id: l.t,v 3.0.1.1 1994/09/22 14:41:21 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: l.t,v $ # Revision 3.0.1.1 1994/09/22 14:41:21 ram # patch12: now checks that callout messages are properly listed # # Revision 3.0 1993/11/29 13:50:18 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; do '../pl/logfile.pl'; chdir '../out'; unlink ; open(MBOX, ">mbox") || print "1\n"; print MBOX <<'EOM'; From ram Sat Jul 11 17:17:12 PDT 1992 From: ram To: ram Subject: test #1 Body #1 From ram Sat Jul 11 17:17:12 PDT 1992 From: ram To: ram Subject: test #2 Body #2 From ram Sat Jul 11 17:17:12 PDT 1992 From: ram To: ram Subject: test #3 Body #3 EOM close MBOX; `$mailagent -f mbox -e 'QUEUE' 2>/dev/null`; $? == 0 || print "2\n"; @output = split(/\n/, $output = `$mailagent -l 2>/dev/null`); @files = ; @files == 3 || print "3\n"; # Not a -l failure, but that will get our attention foreach $file (@files) { $file =~ s|^queue/||; eval "grep(/$file/, \@output)" || $failed++; } $failed == 0 || print "4\n"; # Invoking mailagent as `mailqueue' lists the queue. unlink 'mailqueue'; `ln $mailagent_path ./mailqueue 2>/dev/null`; $? == 0 || print "5\n"; $output_bis = `./mailqueue 2>/dev/null`; $output eq $output_bis || print "6\n"; # Ensure callout messages are also listed `$mailagent -f mbox -e 'AFTER -a (now + 1 day) DELETE; DELETE' 2>/dev/null`; $? == 0 || print "7\n"; @qfiles = ; @cfiles = ; @qfiles == 3 || print "8\n"; @cfiles == 3 || print "9\n"; # Make sure there are three messages queued and three callouts reported @log = `$mailagent -l 2>/dev/null`; &check_log('Now', 10) == 3 || print "11\n"; &check_log('Skipped', 12) == 3 || print "13\n"; &check_log('Callout', 14) == 3 || print "15\n"; unlink , 'mbox', 'mailqueue', 'context', 'callout'; print "0\n"; mailagent-3.1-74.orig/agent/test/option/what.t0000644000175000017500000000125610473324174017325 0ustar jdgjdg# Make sure invalid option leads to a meaningful exit status # $Id: what.t,v 3.0 1993/11/29 13:50:22 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: what.t,v $ # Revision 3.0 1993/11/29 13:50:22 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; `$mailagent -foo -bar 2>&1`; $? != 0 || print "1\n"; print "0\n"; mailagent-3.1-74.orig/agent/test/option/o.t0000644000175000017500000000137310473324174016620 0ustar jdgjdg# -o: overwrite config file with supplied definition # $Id: o.t,v 3.0 1993/11/29 13:50:18 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: o.t,v $ # Revision 3.0 1993/11/29 13:50:18 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; chdir '../out'; unlink 'mylog'; `$mailagent -d -o 'log: mylog' 2>/dev/null`; $? == 0 || print "1\n"; -s 'mylog' || print "2\n"; unlink 'mylog'; print "0\n"; mailagent-3.1-74.orig/agent/test/option/d.t0000644000175000017500000000237010473324174016603 0ustar jdgjdg# -d: dump filter rules (special) # $Id: d.t,v 3.0 1993/11/29 13:50:15 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: d.t,v $ # Revision 3.0 1993/11/29 13:50:15 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; do '../pl/logfile.pl'; chdir '../out'; unlink '.rules'; # With no rule file, verify it dumps the default rules $output = `$mailagent -d`; $? == 0 || print "1\n"; @log = split(/\n/, $output); # want to use check_log() &check_log('# Rule 1', 2); &check_log('PROCESS', 3); # With an empty rule file, we must also have the default rules open(RULES, ">.rules"); close RULES; $output_bis = `$mailagent -d`; $? == 0 || print "4\n"; $output_bis eq $output || print "5\n"; # Now check with some rules `cp ../rules .rules`; $output = `$mailagent -d`; $? == 0 || print "6\n"; @log = split(/\n/, $output); # want to use check_log() &check_log('# Rule 1', 7); &check_log('DELETE', 8); print "0\n"; mailagent-3.1-74.orig/agent/test/option/c.t0000644000175000017500000000220411017222435016566 0ustar jdgjdg# -c : specify alternate configuration file # $Id: c.t,v 3.0.1.1 1997/09/15 15:18:45 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: c.t,v $ # Revision 3.0.1.1 1997/09/15 15:18:45 ram # patch57: uses an empty file instead of /dev/null # # Revision 3.0 1993/11/29 13:50:13 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; $output = `cat ../mail | $mailagent -c foo 2>&1`; $? != 0 || print "1\n"; # Cannot open config file $output =~ /^\*\*.*not processed/m || print "2\n"; chdir '../out'; $user = $ENV{'USER'}; unlink "$user"; `cp .mailagent alternate`; open(EMPTY, '>empty'); close EMPTY; $output = `$mailagent -c alternate empty 2>/dev/null`; $? == 0 || print "3\n"; $output eq '' || print "4\n"; -s "$user" || print "5\n"; unlink "$user", 'alternate', 'empty'; print "0\n"; mailagent-3.1-74.orig/agent/test/option/r.t0000644000175000017500000000153110473324174016617 0ustar jdgjdg# -r: sepcify alternate rule file # $Id: r.t,v 3.0 1993/11/29 13:50:20 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: r.t,v $ # Revision 3.0 1993/11/29 13:50:20 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; chdir '../out'; `cp ../rules .rules`; $output = `$mailagent -d 2>/dev/null`; $? == 0 || print "1\n"; `cp .rules myrules`; $output_bis = `$mailagent -r myrules -d 2>/dev/null`; $? == 0 || print "2\n"; $output eq $output_bis || print "3\n"; unlink 'myrules'; print "0\n"; mailagent-3.1-74.orig/agent/test/option/L.t0000644000175000017500000000131310473324174016547 0ustar jdgjdg# -L: force logging level # $Id: L.t,v 3.0 1993/11/29 13:50:12 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: L.t,v $ # Revision 3.0 1993/11/29 13:50:12 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; chdir '../out'; unlink 'agentlog'; `$mailagent -L 0 -d 2>/dev/null`; $? == 0 || print "1\n"; -f 'agentlog' && print "2\n"; print "0\n"; mailagent-3.1-74.orig/agent/test/option/F.t0000644000175000017500000000300110473324174016535 0ustar jdgjdg# -F : force processing on seen mail # $Id: F.t,v 3.0.1.1 1994/01/26 09:36:08 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: F.t,v $ # Revision 3.0.1.1 1994/01/26 09:36:08 ram # patch5: created # do '../pl/init.pl'; do '../pl/logfile.pl'; chdir '../out'; $user = $ENV{'USER'}; # Don't want to include ../pl/filter.pl unlink 'folder', 'again', $user; system "$mailagent -e '{SAVE ~/folder}' -f ../mail >/dev/null 2>&1"; $? == 0 || print "1\n"; -f $user && print "2\n"; ($old_size = -s 'folder') || print "3\n"; &get_log(4, 'folder'); &check_log('^X-Filter:', 5) == 1 || print "6\n"; system "$mailagent -e '{SAVE ~/folder}' -f ./folder >/dev/null 2>&1"; $? == 0 || print "7\n"; -f $user || print "8\n"; ($old_size == -s 'folder') || print "9\n"; ($old_size == -s $user) || print "10\n"; &get_log(11, $user); &check_log('^X-Filter:', 12) == 1 || print "13\n"; # Now here comes the -F check, now that we know everything works fine unlink $user; system "$mailagent -F -e '{SAVE ~/again}' -f ./folder >/dev/null 2>&1"; $? == 0 || print "14\n"; -f $user && print "15\n"; -s 'again' || print "16\n"; &get_log(17, 'again'); &check_log('^X-Filter:', 18) == 1 || print "19\n"; print "0\n"; mailagent-3.1-74.orig/agent/test/option/t.t0000644000175000017500000000223110473324174016617 0ustar jdgjdg# -t: track rules on stdout # $Id: t.t,v 3.0 1993/11/29 13:50:21 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: t.t,v $ # Revision 3.0 1993/11/29 13:50:21 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; chdir '../out'; open(MBOX, ">mbox") || print "1\n"; print MBOX <<'EOM'; From ram Sat Jul 11 18:51:16 PDT 1992 From: ram To: ram Subject: test This is a test. EOM close MBOX; $trace = `$mailagent -t -e 'STRIP To; DELETE; LEAVE' mbox 2>/dev/null`; $? == 0 || print "2\n"; @trace = split(/\n/, $trace); grep(/^-+\s+From/, @trace) || print "3\n"; grep(/^>> STRIP/, @trace) || print "4\n"; grep(/^>> DELETE/, @trace) || print "5\n"; grep(/^>> LEAVE/, @trace) || print "6\n"; grep(/match/i, @trace) || print "7\n"; $user = $ENV{'USER'}; -s "$user" || print "8\n"; unlink "$user", 'mbox'; print "0\n"; mailagent-3.1-74.orig/agent/test/option/V.t0000644000175000017500000000131211017744444016561 0ustar jdgjdg# -V: print version number and exits # $Id: V.t,v 3.0 1993/11/29 13:50:12 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: V.t,v $ # Revision 3.0 1993/11/29 13:50:12 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; $version = `$mailagent -V 2>&1`; $? == 0 || print "1\n"; $version =~ /^mailagent \d+\.\d+-\d+/ || print "2\n"; print "0\n"; mailagent-3.1-74.orig/agent/test/option/U.t0000644000175000017500000000364511017272724016570 0ustar jdgjdg# -U : disable reject / abort of first UNIQUE and REJECT. # $Id: U.t 11 2008-05-28 15:10:12Z rmanfredi $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: F.t,v $ # Revision 3.0.1.1 1994/01/26 09:36:08 ram # patch5: created # do '../pl/init.pl'; do '../pl/logfile.pl'; chdir '../out'; $user = $ENV{'USER'}; # Don't want to include ../pl/filter.pl unlink 'folder', 'again', $user; $devnull = ">/dev/null 2>&1"; # Load the dbr database unlink("dbr/i/e"); system "$mailagent -e '{ UNIQUE (a); UNIQUE (b); }' -f ../mail $devnull"; $? == 0 || print "1\n"; -f $user || print "2\n"; unlink $user; system "$mailagent -U -e '{ UNIQUE (a); SAVE ~/again; }' -f ../mail $devnull"; $? == 0 || print "3\n"; -f $user && print "4\n"; -s 'again' || print "5\n"; &get_log(6, 'again'); &check_log('^X-Filter:', 7) == 1 || print "8\n"; unlink $user, 'again'; system "$mailagent -U -e '{ UNIQUE (a); UNIQUE (b); SAVE ~/again; }' -f ../mail" . $devnull; $? == 0 || print "9\n"; -f $user && print "10\n"; -s 'again' || print "11\n"; unlink $user, 'again'; system "$mailagent -U -e '{ RECORD (a); RECORD (b); SAVE ~/again; }' -f ../mail" . $devnull; $? == 0 || print "12\n"; -f $user && print "13\n"; -s 'again' || print "14\n"; unlink $user, 'again'; system "$mailagent -U -e '{ RECORD (a); UNIQUE (a); SAVE ~/again; }' -f ../mail" . $devnull; $? == 0 || print "15\n"; -f $user || print "16\n"; -s 'again' && print "17\n"; unlink $user, 'again'; system "$mailagent -U -e '{ UNIQUE (a); RECORD (a); SAVE ~/again; }' -f ../mail" . $devnull; $? == 0 || print "18\n"; -f $user || print "19\n"; -s 'again' && print "20\n"; print "0\n"; mailagent-3.1-74.orig/agent/test/option/f.t0000644000175000017500000000327410473324174016611 0ustar jdgjdg# -f: get messages from UNIX-style mailbox file # $Id: f.t,v 3.0 1993/11/29 13:50:16 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: f.t,v $ # Revision 3.0 1993/11/29 13:50:16 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; do '../pl/logfile.pl'; chdir '../out'; unlink 'agentlog'; $user = $ENV{'USER'}; unlink "$user"; open(MBOX, ">mbox") || print "1\n"; print MBOX <<'EOM'; From ram Sat Jul 11 17:17:12 PDT 1992 From: ram To: ram Subject: test #1 Body #1 From ram Sat Jul 11 17:17:12 PDT 1992 Previous line is just a dummy From line. From ram Sat Jul 11 17:17:12 PDT 1992 From: ram To: ram Subject: test #2 Body #2 From ram Sat Jul 11 17:17:12 PDT 1992 From: nearly a header!! Previous 2 lines are just dummy lines. From ram Sat Jul 11 17:17:12 PDT 1992 From: ram To: ram Subject: test #3 Body #3 EOM close MBOX; `$mailagent -e 'LEAVE' -f mbox 2>/dev/null`; $? == 0 || print "2\n"; -s "$user" || print "3\n"; &get_log(4); @queued = grep(/QUEUED/, @log); @queued == 3 || print "5\n"; @subject = grep(/ABOUT.*test/, @log); @subject == 3 || print "6\n"; @filtered = grep(/FILTERED/, @log); @filtered == 3 || print "7\n"; @files = ; @files == 0 || print "8\n"; open(MBOX, "$user") || print "9\n"; @mbox = ; close MBOX; @msg = grep(/^X-Filter:/, @mbox); @msg == 3 || print "10\n"; unlink 'agentlog', "$user", 'mbox'; print "0\n"; mailagent-3.1-74.orig/agent/test/option/q.t0000644000175000017500000000263110473324174016620 0ustar jdgjdg# -q: process the queue (special) # $Id: q.t,v 3.0 1993/11/29 13:50:19 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: q.t,v $ # Revision 3.0 1993/11/29 13:50:19 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; chdir '../out'; unlink ; open(MBOX, ">mbox") || print "1\n"; print MBOX <<'EOM'; From ram Sat Jul 11 17:17:12 PDT 1992 From: ram To: ram Subject: test #1 Body #1 From ram Sat Jul 11 17:17:12 PDT 1992 From: ram To: ram Subject: test #2 Body #2 From ram Sat Jul 11 17:17:12 PDT 1992 From: ram To: ram Subject: test #3 Body #3 EOM close MBOX; `$mailagent -f mbox -e 'QUEUE' 2>/dev/null`; $? == 0 || print "2\n"; $user = $ENV{'USER'}; unlink "$user"; `$mailagent -e 'LEAVE' -q 2>/dev/null`; -f "$user" && print "3\n"; @queue = ; @queue == 3 || print "4\n"; # Still deferred for 30 minutes $now = time; $now -= 31 * 60; utime $now, $now, @queue; `$mailagent -e 'LEAVE' -q 2>/dev/null`; -f "$user" || print "5\n"; @queue = ; @queue == 0 || print "6\n"; # Mails have been processed unlink "$user", 'mbox'; print "0\n"; mailagent-3.1-74.orig/agent/test/option/h.t0000644000175000017500000000132611017222435016577 0ustar jdgjdg# -h: print this help message and exits # $Id: h.t,v 3.0 1993/11/29 13:50:17 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: h.t,v $ # Revision 3.0 1993/11/29 13:50:17 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; $output = `$mailagent -h 2>&1`; $? != 0 || print "1\n"; # -h -> exit status 1 $output =~ /-h : print/m || print "2\n"; print "0\n"; mailagent-3.1-74.orig/agent/test/option/s.t0000644000175000017500000000464210473324174016626 0ustar jdgjdg# -s: report gathered statistics (special) # $Id: s.t,v 3.0.1.1 1995/08/07 16:28:45 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: s.t,v $ # Revision 3.0.1.1 1995/08/07 16:28:45 ram # patch37: added support for locking on filesystems with short filenames # # Revision 3.0 1993/11/29 13:50:20 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; do '../pl/logfile.pl'; chdir '../out'; unlink 'mailagent.st'; $out = `$mailagent -summary 2>/dev/null`; $? == 0 || print "1\n"; `cp /dev/null mailagent.st`; $mail_test = <<'EOM'; From ram Sat Jul 11 18:51:16 PDT 1992 From: ram To: ram Subject: test This is a test. EOM # First time creates new statistics, second time updates them. for ($i = 0; $i < 2; $i++) { open(MAILAGENT, "|$mailagent -e 'STRIP Nothing; LEAVE' 2>/dev/null") || print "2x$i\n"; print MAILAGENT $mail_test; close MAILAGENT; $? == 0 || print "3x$i\n"; sleep 1 while -f "perl$lockext"; # Wait for background process to finish } $user = $ENV{'USER'}; -s "$user" || print "4\n"; $out = `$mailagent -s 2>/dev/null`; $out ne '' || print "5\n"; @out = split(/\n/, $out); @leave = grep(/LEAVE/, @out); @strip = grep(/STRIP/, @out); @leave == @strip || print "6\n"; @leave == 1 || print "7\n"; $out = `$mailagent -sm 2>/dev/null`; @out = split(/\n/, $out); @leave = grep(/LEAVE/, @out); @strip = grep(/STRIP/, @out); @leave == @strip || print "8\n"; @leave == 2 || print "9\n"; $out = `$mailagent -sr 2>/dev/null`; @out = split(/\n/, $out); grep(/STRIP.*LEAVE/, @out) || print "10\n"; &get_log(11, 'mailagent.st'); &check_log('^---', 12) == 1 || print "13\n"; # Rules did not changed &check_log('^\+\+\+', 14) == 1 || print "15\n"; # Now change rules slightly open(MAILAGENT, "|$mailagent -e 'STRIP Other; LEAVE' 2>/dev/null") || print "16\n"; print MAILAGENT $mail_test; close MAILAGENT; $? == 0 || print "17\n"; sleep 1 while -f "perl$lockext"; # Wait for background process to finish &get_log(18, 'mailagent.st'); &check_log('^---', 19) == 2 || print "20\n"; # Rules did changed &check_log('^\+\+\+', 21) == 2 || print "22\n"; unlink 'mailagent.st', "$user"; print "0\n"; mailagent-3.1-74.orig/agent/test/option/i.t0000644000175000017500000000165611017222435016606 0ustar jdgjdg# -i: interactive usage -- print log messages on stderr # $Id: i.t,v 3.0 1993/11/29 13:50:17 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: i.t,v $ # Revision 3.0 1993/11/29 13:50:17 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; chdir '../out'; unlink 'agentlog'; $output = `$mailagent -d -i 2>&1 >/dev/null`; $? == 0 || print "1\n"; open(LOG, 'agentlog') || print "2\n"; undef $/; $log = ; close LOG; $output =~ s/^$mailagent_prog://mg; $log =~ s/^.*$mailagent_prog\[.*\]\s*://mg; $output eq $log || print "3\n"; $output ne '' || print "4\n"; print "0\n"; mailagent-3.1-74.orig/agent/test/option/e.t0000644000175000017500000000304610473324174016605 0ustar jdgjdg# -e : enter rules to be applied # $Id: e.t,v 3.0 1993/11/29 13:50:15 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: e.t,v $ # Revision 3.0 1993/11/29 13:50:15 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/init.pl'; do '../pl/logfile.pl'; chdir '../out'; $output = `$mailagent -e '{ OWN_RULE_1 };' -e '{OWN_RULE_2 };' -d`; $? == 0 || print "1\n"; @log = split(/\n/, $output); # want to use check_log() &check_log('OWN_RULE_1', 2); &check_log('OWN_RULE_2', 3); # Single rule may not be specified between {} $output = `$mailagent -e 'SINGLE' -d`; $? == 0 || print "4\n"; $output_bis = `$mailagent -e '{ SINGLE }' -d`; $? == 0 || print "5\n"; $output eq $output_bis || print "6\n"; $output = `$mailagent -e 'SINGLE' -e '{ OTHER }' -d`; $? == 0 || print "7\n"; $output_bis = `$mailagent -e '{ SINGLE };' -e '{ OTHER }' -d`; $? == 0 || print "8\n"; $output ne $output_bis || print "9\n"; @log = split(/\n/, $output); grep(/# Rule 2/, @log) && print "10\n"; # Only one rule grep(/Subject: SINGLE/, @log) || print "11\n"; # No selector -> Subject @log = split(/\n/, $output_bis); grep(/# Rule 2/, @log) || print "12\n"; # Two rules grep(/Subject: \*/, @log) || print "13\n"; # No pattern -> * print "0\n"; mailagent-3.1-74.orig/agent/test/option/I.t0000644000175000017500000001042510473324174016550 0ustar jdgjdg# -I: install configuration and perform sanity checks. # $Id: I.t,v 3.0.1.2 1996/12/24 15:03:36 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: I.t,v $ # Revision 3.0.1.2 1996/12/24 15:03:36 ram # patch45: fixed test for fast CPUs # # Revision 3.0.1.1 1995/02/16 14:39:06 ram # patch32: created # do '../pl/init.pl'; chdir '../out'; unlink 'agentlog'; $SIG{'INT'} = CATCH; # Restore default configuration if interrupted sub CATCH { rename('.mailconfig', '.mailagent') if -f '.mailconfig'; } # Make sure initial mailagent -I creates a ~/.mailagent file rename('.mailagent', '.mailconfig') || print "1\n"; $output = `$mailagent -I`; print "2\n" if $?; -f '.mailagent' || print "3\n"; # Now load the config into memory... &load_config(4); # uses 5 # Make sure the necessary directories and files have been created. # Hopefully, the default test environment does not use the same # configuration than the default mailagent.cf, so we can make some # sanity checks here... -d $cf'spool || print "6\n"; -d $cf'logdir || print "7\n"; -s $cf'comfile || print "8\n"; -d $cf'queue || print "9\n"; `rm -rf var`; # Hardwired name!! # If we run it again, it should NOT modify the existing one ($ino, $size, $mtime, ) = (stat('.mailagent'))[1,7,9]; $output2 = `$mailagent -I`; print "10\n" if $?; -f '.mailagent' || print "11\n"; ($ino2, $size2, $mtime2, ) = (stat('.mailagent'))[1,7,9]; print "12\n" if $ino2 != $ino; print "13\n" if $size2 != $size; print "14\n" if $mtime2 != $mtime; print "15\n" unless defined $ino; # Make sure stat did not fail... # Should have beed recreated -d $cf'spool || print "16\n"; -d $cf'logdir || print "17\n"; -s $cf'comfile || print "18\n"; -d $cf'queue || print "19\n"; $output ne $output2 || print "20\n"; $output =~ /creating/ || print "21\n"; $output2 =~ /merging/ || print "22\n"; # Ensure missing parameters are merged properly... rename('.mailagent', 'config') || print "23\n"; open(OLD, 'config') || print "24\n"; open(NEW, '>.mailagent') || print "25\n"; while () { next if /^#?com/; next if /^#?queue/; next if /^#?logdir/; print NEW; } close OLD; close(NEW) || print "26\n"; unlink 'config'; # Make sure we can undefine the old config properly... $cf'queue ne '' || print "27\n"; eval $cf'undef; $cf'queue eq '' || print "28\n"; # ...and that the queue parameter was indeed undefined above in NEW. &load_config(29); # uses 30 $cf'queue eq '' || print "31\n"; eval $cf'undef; ($ino, $size, $mtime, ) = (stat('.mailagent'))[1,7,9]; $output3 = `$mailagent -I`; print "32\n" if $?; -f '.mailagent' || print "33\n"; ($ino2, $size2, $mtime2, ) = (stat('.mailagent'))[1,7,9]; print "34\n" if $ino2 == $ino; print "35\n" if $size2 == $size; print "36\n" if $mtime2 < $mtime; # May be equal if CPU is fast print "37\n" unless defined $ino; # Make sure stat did not fail... &load_config(38); # uses 39 $cf'queue ne '' || print "40\n"; # is now defined!! $cf'comfile ne '' || print "41\n"; $cf'logdir ne '' || print "42\n"; `rm -rf var`; # Hardwired name!! &CATCH; # Restore default configuration print "0\n"; # May print 2 error numbers starting from $error # Sets $cf'undef so that we may later on undefine the whole config... sub load_config { local($error) = @_; package cf; $undef = "package cf;\n"; $config = ''; open(CONFIG, '.mailagent') || print "$error\n"; while () { next if /^[ \t]*#/; # skip comments next if /^[ \t]*\n/; # skip empy lines s/([^\\](\\\\)*)@/$1\\@/g; # escape all un-escaped @ in string $config .= $_; } close CONFIG; $myhome = $ENV{'HOME'}; # Set by TEST $eval = ''; foreach (split(/\n/, $config)) { if (/^[ \t]*([^ \t\n:\/]*)[ \t]*:[ \t]*([^#\n]*)/) { $var = $1; $value = $2; $value =~ s/\s*$//; # remove trailing spaces $eval .= "\$$var = \"$value\";\n"; $eval .= "\$$var =~ s|~|\$myhome|g;\n"; # ~ substitution $undef .= "undef \$$var;\n"; # to reset config } } eval $eval; # evaluate configuration parameters within package $error++; print "$error\n" if $@ ne ''; } mailagent-3.1-74.orig/agent/test/TEST0000755000175000017500000001550511021010507015352 0ustar jdgjdg: # feed this into perl eval 'exec perl -S $0 "$@"' if $running_under_some_shell; # $Id: TEST,v 3.0.1.4 2001/03/17 18:14:23 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: TEST,v $ # Revision 3.0.1.4 2001/03/17 18:14:23 ram # patch72: try to run tests as nobody when super-user -- from Debian # # Revision 3.0.1.3 1995/08/07 16:26:39 ram # patch37: added support for locking on filesystems with short filenames # # Revision 3.0.1.2 1994/09/22 14:40:10 ram # patch12: new -m option to monitor agentlog changes via atail # # Revision 3.0.1.1 1993/12/15 09:04:45 ram # patch3: now force . into PATH for msend/nsend # # Revision 3.0 1993/11/29 13:49:22 ram # Baseline for mailagent 3.0 netwide release. # if ($> == 0) { print "Oh, you naughty person. You are superuser!\n"; my $uid = (stat('.'))[4]; $uid = (getpwnam('nobody'))[2] unless $uid; $uid || die "Cannot run tests as super-user.[$<,$>]\n"; $> = $uid; $< = $uid; my $whom = (getpwuid($uid))[0]; print "Trying to run as user $whom [$uid]\n"; } chop($pwd = `pwd`); $ENV{'HOME'} = "$pwd/out"; chop($host = `(hostname 2>/dev/null || uname -n) 2>/dev/null`); $host =~ s/^([^.]*)\..*/$1/; # Trim domain name $ENV{'HOST'} = $host; $ENV{'USER'} = 'nobody'; # In case we get mails back from RUN and friends $ENV{'PWD'} = $pwd; $ENV{'LEVEL'} = 0; # Default loglvl for filter and cmd tests delete $ENV{'ENV'}; # For ksh &read_config_sh; # Load configuration into package cfsh $ENV{'LOCKEXT'} = $cfsh'd_flexfnam eq 'define' ? '.lock' : '!'; @tests = ('basic', 'option', 'filter', 'cmd', 'misc'); $failed = 0; $how_many = 0; require 'getopt.pl'; &Getopt; $mailagent = 'mailagent'; # Default program (dataloaded version) $mailagent = 'magent' if $opt_n; # Use non-dataloaded version $ENV{'MAILAGENT'} = $mailagent; $ENV{'PATH'} = "$pwd/..:.:" . $ENV{'PATH'}; -f "../$mailagent" && -x _ || die "No $mailagent.\n"; -f '../filter/filter' && -x _ || die "No filter.\n"; $> || die "Cannot run tests as super-user. [$<,$>]\n"; &load_ok; # Don't rerun successful tests if up to date # A level file indicates default loglvl if (-f 'level') { chop($level = `cat level`); $ENV{'LEVEL'} = int($level); } # Launch atail if -m to monitor the agentlog file if ($opt_m) { $atail_pid = fork; unlink 'out/agentlog'; if (defined $atail_pid && $atail_pid == 0) { # Child process exec 'perl ./atail'; die "TEST: could not launch atail: $!\n"; } } unless (-f 'OK') { %Ok = (); `rm -rf out` if -d 'out'; } umask 022; # Ensure none of the files are world writable `mkdir out` unless -d 'out'; select(STDOUT); $| = 1; # If they specified a list of files, run them and do not update "OK" # nor print any summary status. if (@ARGV) { foreach my $file (@ARGV) { run_file($file); exit(1) if $failed && $opt_s; } exit($failed ? 1 : 0) ; } open(OK, ">>OK"); select(OK); $| = 1; # We may safely interrupt select(STDOUT); foreach $dir (@tests) { next unless -d $dir; &run($dir); } # Summarize what happened close OK; if ($failed == 0) { print "All tests successful.\n"; } else { print "Failed $how_many test", $how_many == 1 ? '' : 's'; print " from $failed file", $failed == 1 ? '' : 's', ".\n"; } &clean_up; &exit(0); # End of tests # # Subroutines # sub exit { local($code) = @_; kill(15, $atail_pid) if $atail_pid; exit $code; } sub clean_up { return if $failed || $opt_i; # -i asks for incrementality unlink 'OK'; `rm -rf out` if -d 'out'; } sub print { local($dir, $file) = @_; $file =~ s/\.t$//; local($len) = 1 + length($dir) + length($file); print "$dir/$file", '.' x (17 - $len); } sub num { $a <=> $b; } sub result { local($test, $output) = @_; local($now) = time; local(@res) = split(/\n/, $output); # Failed test numbers if ($res[0] eq '') { print "FAILED (no test run)\n"; ++$failed; } elsif ($res[$#res] == 0 && $#res > 0 && $res[$#res -1] == $#res) { print "FAILED (all tests)\n"; ++$failed; $how_many += $#res; } elsif ($res[0] == 0) { print "ok\n"; print OK "$test $now\n"; } elsif ($res[0] == -1) { print "untested\n"; } else { # Program outputs the number of each test failed, and last must be 0 local($last) = pop(@res); push(@res, $last) unless $last == 0; local($n) = @res + 0; local($s) = $n == 1 ? '' : 's'; print "FAILED ($n test$s:"; @res = sort num @res; print ' ', join(',', @res); print " and aborted" unless $last == 0; print ")\n"; ++$failed; $how_many += $n; } if ($failed && $opt_s) { # Stop at first error if -s print "Aborted tests.\n"; &exit(0); } } sub run { local($dir) = @_; chdir $dir or die "Cannot chdir to $dir: $!\n"; local(@files) = <*.t>; local($test); local($output); foreach $file (@files) { &print($dir, $file); $test = "$dir/$file"; if ($Ok{$test} >= ((stat($file))[9])) { # Check time stamp print "done\n"; next; } $output = `perl $file`; &result($test, $output); &basic_failed if $dir eq 'basic' && $failed; } chdir '..' or die "Cannot chdir back to ..: $!\n"; } sub run_file { my ($path) = @_; my ($dir, $file) = $path =~ m|^(.*)/(.*)|; my $test = "$dir/$file"; unless (-f $test) { warn "WARNING: ignoring missing $path\n"; return; } &print($dir, $file); chdir $dir or die "Cannot chdir to $dir: $!\n"; $output = `perl $file`; &result($test, $output); chdir $pwd or die "Cannot chdir back to ..: $!\n"; } sub basic_failed { print "Failed a basic test, cannot continue.\n"; unlink 'OK'; &exit(0); } sub load_ok { return unless -f 'OK'; # Make sure the OK file is up to date, unless -o (outdated) unless ($opt_o) { local($ok_mtime) = (stat('OK'))[9]; local($ma_mtime) = (stat("../$mailagent"))[9]; local($fi_mtime) = (stat('../filter/filter'))[9]; local($restart) = 0; if ($ma_mtime > $ok_mtime) { warn "Mailagent has changed, restarting tests...\n"; ++$restart; } elsif ($fi_mtime > $ok_mtime) { warn "Filter has changed, restarting tests...\n"; ++$restart; } unlink 'OK' if $restart; } return unless -f 'OK'; local($file, $when); open(OK, 'OK') || return; while () { chop; ($file, $when) = /^(\S+)\s+(\d+)/; $Ok{$file} = $when if $when; } close OK; } # Read configuration information from config.sh sub read_config_sh { open(CONFIG, '../../config.sh') || die "No config.sh at the toplevel directory! Did you run Configure?\n"; local($_); local($config) = "package cfsh;\n"; local($var, $value); while () { next unless ($var, $value) = /^(\w+)='([^']*)'/; $config .= "\$$var = '$value';\n"; } close CONFIG; eval($config); warn $@ if $@; die "Can't create config from config.sh\n" if $@; } mailagent-3.1-74.orig/agent/test/rules0000644000175000017500000001537711024437250015744 0ustar jdgjdg# # Mailagent rules for filter regression tests # # $Id: rules,v 3.0.1.5 2001/03/17 18:16:21 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: rules,v $ # Revision 3.0.1.5 2001/03/17 18:16:21 ram # patch72: added new filter/address tests # # Revision 3.0.1.4 1999/07/12 13:58:02 ram # patch66: fixed wrong semantics for <2>, and rewrote tests accordingly # # Revision 3.0.1.3 1996/12/24 15:03:48 ram # patch45: added test cases for new Relayed selector # # Revision 3.0.1.2 1994/07/01 15:12:23 ram # patch8: added test rules for macro substitution in patterns # # Revision 3.0.1.1 1994/04/25 15:26:12 ram # patch7: added three more tests in filter/group # # Revision 3.0 1993/11/29 13:50:27 ram # Baseline for mailagent 3.0 netwide release. # maildir = ~; mailfilter = ~; Subject: /test/ { DELETE }; # filter/address X-Tag: /address #1/ { BEGIN ADDR; REJECT }; To: ram { SAVE ok.1; REJECT }; To: ramx { SAVE bad.1; REJECT }; To: am { SAVE bad.2; REJECT }; To: /^ram@/ { SAVE ok.2; REJECT }; To: ram@eiffel.com { SAVE ok.3; REJECT }; To: am@eiffel.com { SAVE bad.3; REJECT }; To: xram@eiffel.com { SAVE bad.4; REJECT }; To: ramx@eiffel.com { SAVE bad.5; REJECT }; To: RAM@eiffel.COM { SAVE ok.4; REJECT }; To: ram@eiffe..com { SAVE bad.6; REJECT }; To: ram@eiffel { SAVE bad.7; REJECT }; To: ram@eif { SAVE bad.8; REJECT }; To: ram* { SAVE ok.5; REJECT }; To: ra* { SAVE ok.6; REJECT }; To: ra*@eif* { SAVE ok.7; REJECT }; { DELETE }; # filter/default X-Tag: /default #1/ { DELETE }; X-Tag: /default #2/ { NOP }; X-Tag: /unknown/ { UNKNOWN }; # filter/loop X-Tag: /loop #1/ { BEGIN LOOP; RESTART }; X-Tag: /loop #2/ { DELETE }; # filter/multiple X-None Subject To X-Tag: /multiple #1/ { SAVE %u.1 }; X-None X-Tag: /multiple #2/, X-Other: /another/, To Cc: root, Cc To: ram { SAVE %u.3; REJECT MULTIPLE }; X-Non-Existent: * { SAVE %u.2 }; X-Tag: /multiple #2/, X-Other: /multiple #2/ { SAVE %u.2 }; # filter/list X-Tag: /list #1/ { BEGIN LIST; REJECT }; To: ram { SAVE %u.1 }; To: max { SAVE %u.2 }; To: /^root@eiffel.com$/ { SAVE %u.3 }; To: /^riot@eiffel.co$/ { DELETE }; To: /^riot@eiffel.com$/ { SAVE %u.4 }; To: /^riot/ { SAVE %u.5 }; To: /riot/ { SAVE %u.6 }; Newsgroups: news.lists { SAVE %u.7 }; To <3>: /^root@local/ { SAVE %u.8 }; To: !ram { SAVE %u.9 }; { DELETE }; X-Tag: /list #2/ { BEGIN LIST; REJECT }; Relayed: ursa-major.spdcc.com { SAVE ok.1; REJECT LIST_OK }; { SAVE never; REJECT }; { REJECT LIST }; Relayed <1>: /ursa-major/ { SAVE ok.2; REJECT LIST_OK }; { SAVE never; REJECT }; { REJECT LIST }; Relayed <-1,->: *eiffel.com { SAVE ok.3 }; { SAVE never }; # filter/pattern X-T.*: "pattern-list" { BEGIN PAT; REJECT }; .*Re[^\-]*$: *, ^Sub*: * { RUN /bin/echo '%&' > macro; DELETE }; # filter/backref X-Tag: /^back(.*) #1/, Subject: /Re:\s+(\w+)\s+ice\s+(\w+)/, From: /(.*)compilers/, From: /com(.*)rs/, To: /^(\w+)@(\S+)/ { RUN /bin/echo '%1,%4,%5@%6,%2 %3' > output; DELETE }; X-Tag: /^back.* #2/, Newsgroups: /(comp.lang.perl)/, /(comp.unix.wizards)/, /(comp.mail.mh)/ { SAVE %1 }; # filter/escape X-Tag: /escape/ { RUN /bin/echo '\;,\\\;,\\,\w' > output; DELETE }; # filter/mode X-Tag: /mode/ { REJECT MODE }; { SAVE always; REJECT }; { SAVE always.2; REJECT }; X-Tag: /mode/ { SAVE always.3; REJECT }; X-Tag: /mode/ { SAVE never; REJECT }; { DELETE }; # filter/not X-Tag: /not #1/ { BEGIN NOT; REJECT }; To: !ram { SAVE never }; To: !/ram@eiffel/ { SAVE never }; To: !/^ram/i { SAVE never }; To: /^ram/i { SAVE always; REJECT }; To: !/^root/i { SAVE always.2; REJECT }; X-Tag: !"pattern-list" { SAVE always.3 }; X-Tag: /not #2/, !To: !ram, To: !compilers, !From: root { SAVE always }; # filter/group X-Tag: /group/ { BEGIN GROUP; REJECT }; !To !From: ram { SAVE never }; To !From: !ram { SAVE never }; !To !From: ram, !Subject !To: ram { SAVE never }; !To: root, ram { SAVE never }; !F.*: /compiler/ { SAVE never }; !From: ram, !To: ram { SAVE always; REJECT }; From: ram, To: ram { SAVE never }; From: /compiler/, !From: ram, !From: !/compiler/ { SAVE always.2; REJECT }; From !Cc !To: /compiler/, From !Cc !To: ram, !From To Cc: /eiffel/, !From To Cc: !/ice/ { SAVE always.3; REJECT }; !To !Cc: guy_3 { SAVE never.2 }; !To Cc: guy_3 { SAVE always.4; REJECT }; !To: unknown, !Subject !From: ram { SAVE always.5 }; # filter/case X-Tag: case, Cc: root { STRIP Cc; SAVE always }; # filter/base64 X-Tag: base64, Body: /successfully/ { SAVE always }; # filter/qp X-Tag: qp, Body: /broken/ { SAVE always }; # filter/status X-Tag: /status/ { REJECT -t STATUS }; { RUN ../no/such/file; REJECT -t; SAVE always; REJECT -t; SAVE never }; { RUN ../this/does/not/exist; REJECT -f; SAVE never }; { RUN ../nor/does/this; REJECT -t; REJECT -t; REJECT -f; SAVE never }; { SAVE always.2; REJECT -f; BEGIN INITIAL; REJECT -t }; X-Tag: /status/ { SAVE always.3 }; # filter/hook X-Tag: /hook #(\d)/ { SAVE hook.%1; ABORT -t; SAVE never }; # filter/range X-Tag: /range/ { BEGIN RANGE; REJECT }; From <2, 4>: /compiler/ { SAVE always; REJECT }; To Cc: made { SAVE always.2; REJECT }; To Cc <1, 1>: made { SAVE never; REJECT }; To Cc <1, 2>: must { SAVE always.3; REJECT }; To Cc <3, 1>: ram { SAVE never.2; REJECT }; Body <-, 3>: /SIGPLAN/ { SAVE never.3; REJECT }; Body <-, ->: /SIGpLAN/i { SAVE always.4; REJECT }; Body <9, 9>: m|SI\w+N| { SAVE always.5; REJECT }; Body <9, 9>: /CD-ROM/ { SAVE never.4; REJECT }; Body <13, 14>: m,something, { SAVE always.6; REJECT }; Body <-3, ->: /Regards/ { SAVE always.7; REJECT }; Cc <-1, ->: made { SAVE always.8; REJECT }; Body <-3, ->: /request/ { SAVE never.5; REJECT }; Cc <-1, ->: must { SAVE never.6 }; { DELETE }; # filter/macros X-Tag: /macros/ { REJECT MACROS }; To: %u { LEAVE }; { DELETE }; mailagent-3.1-74.orig/agent/test/misc/0000755000175000017500000000000011675050333015612 5ustar jdgjdgmailagent-3.1-74.orig/agent/test/misc/newcmd.t0000644000175000017500000000427010473324174017261 0ustar jdgjdg# Test user-defined commands # $Id: newcmd.t,v 3.0 1993/11/29 13:50:10 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: newcmd.t,v $ # Revision 3.0 1993/11/29 13:50:10 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/misc.pl'; unlink "$user", 'always', 'test'; &add_option("-o 'newcmd: ~/.newcmd'"); open(NEWCMD, '>.newcmd') || print "1\n"; print NEWCMD <commands') || print "4\n"; print COM <<'EOC' || print "5\n"; sub first { &mailhook'third_cmd('test'); # Make sure interface function is there open(OUT, '>output1'); print OUT join(' ', @ARGV), "\n"; print OUT "$to\n"; close OUT; 0; } sub second { &main'add_log('second user-defined command ran ok'); open(OUT, '>output2'); print OUT "$from\n"; print OUT "$header{'Date'}\n"; close OUT; 0; } sub third { local($cmd) = @_; local(@cmd) = split(' ', $cmd); open(TEST, ">$cmd[1]"); print TEST "$cmd\n"; close TEST; 0; } EOC close COM || print "6\n"; &add_header('X-Tag: newcmd'); `$cmd`; $? == 0 || print "7\n"; -f "$user" && print "8\n"; # Has defaulted to LEAVE -> something's wrong -f 'output1' || print "9\n"; -f 'output2' || print "10\n"; -f 'test' || print "11\n"; chop($test = `cat test 2>/dev/null`); $test eq 'third_cmd test' || print "12\n"; chop(@test = `cat output1 2>/dev/null`); $test[0] eq 'FIRST_CMD arg1 arg2' || print "13\n"; $test[1] eq 'ram@eiffel.com' || print "14\n"; chop(@test = `cat output2 2>/dev/null`); $test[0] eq 'compilers-request@iecc.cambridge.ma.us' || print "15\n"; $test[1] eq '3 Jul 92 00:43:22 EDT (Fri)' || print "16\n"; &get_log(17); &check_log('second user-defined command ran ok', 18) == 1 || print "19\n"; unlink "$user", 'mail', 'test', 'output1', 'output2', 'commands', '.newcmd'; print "0\n"; mailagent-3.1-74.orig/agent/test/misc/compress.t0000644000175000017500000000417111565542267017647 0ustar jdgjdg# Test compression feature # $Id: compress.t,v 3.0.1.1 1995/01/25 15:33:37 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: compress.t,v $ # Revision 3.0.1.1 1995/01/25 15:33:37 ram # patch27: ported to perl 5.0 PL0 # # Revision 3.0 1993/11/29 13:50:08 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/misc.pl'; sub cleanup { unlink "$user", "$user.gz", 'always', 'always.gz', 'another', '.compress'; } &cleanup; # Look whether compress is available. If not, do not perform this test. unlink 'mail.gz'; `gzip mail`; `gunzip mail` if $? == 0 && -f mail.gz; if ($? != 0) { # No compress available in path, sorry print "-1\n"; # Do not perform any tests exit 0; } &cp_mail; # Get a new fresh mail message, seems required for perl5? &add_option("-o 'compress: ~/.compress'"); open(COMPRESS, '>.compress') || print "1\n"; print COMPRESS </dev/null 2>&1`; `$cmd`; $? == 0 || print "11\n"; -f "$user" || print "12\n"; # Should be not be recompressed -f "$user.gz" || print "13\n"; # Should still be there -f 'always' && print "14\n"; # Should also be compressed -f 'always.gz' || print "15\n"; -f 'another' || print "16\n"; # This one is not compressed -f 'another.gz' && print "17\n"; (-s $user != $msize) || print "18\n"; # Mail saved there (-s "$user.gz" == $msize) || print "19\n"; # This one left undisturbed unlink 'mail'; &cleanup; print "0\n"; mailagent-3.1-74.orig/agent/test/misc/mmdf.t0000644000175000017500000000243210473324174016725 0ustar jdgjdg# Test MMDF-style mailboxes # $Id: mmdf.t,v 3.0 1993/11/29 13:50:09 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: mmdf.t,v $ # Revision 3.0 1993/11/29 13:50:09 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/misc.pl'; unlink "$user", 'always'; &add_option("-o 'mmdf: ON' -o 'mmdfbox: OFF'"); &add_header('X-Tag: mmdf'); `$cmd`; $? == 0 || print "1\n"; -f "$user" || print "2\n"; -f 'always' || print "3\n"; sub has_ctrl { local($file) = @_; open(FILE, $file) || return 0; local($count) = 0; local($_); while () { $count++ if /^\01\01\01\01$/; } $count; } &has_ctrl($user) == 0 || print "4\n"; &has_ctrl('always') == 0 || print "5\n"; $cmd =~ s/mmdfbox: OFF/mmdfbox: ON/ || print "6\n"; unlink 'always'; `$cmd`; $? == 0 || print "7\n"; -f "$user" || print "8\n"; -f 'always' || print "9\n"; &has_ctrl($user) == 0 || print "10\n"; &has_ctrl('always') == 4 || print "11\n"; unlink $user, 'always', 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/misc/mh.t0000644000175000017500000000555710473324174016421 0ustar jdgjdg# Test MH-style folders # $Id: mh.t,v 3.0.1.1 1995/01/25 15:33:59 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: mh.t,v $ # Revision 3.0.1.1 1995/01/25 15:33:59 ram # patch27: added checks for Msg-Protect and PROTECT # # Revision 3.0 1993/11/29 13:50:09 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/misc.pl'; unlink "$user", 'always'; -d 'mh' || mkdir('mh', 0700) || print "1\n"; -d 'mh/tmp' || mkdir('mh/tmp', 0700) || print "2\n"; unlink ; open(MSG, '>mh/tmp/3') || print "3\n"; print MSG <<'EOF'; From: mailagent To: ram Subject: message #3 Message #3 EOF close MSG; open(MSG, '>mh/tmp/7') || print "4\n"; print MSG <<'EOF'; From: mailagent To: ram Subject: message #7 Message #7 EOF close MSG; open(MSG, '>mh/tmp/.mh_sequences') || print "5\n"; print MSG <<'EOF'; cur: 1 pseq: 3 7 unseen: 1 3-4 12 another: 1 3-7 12 hole: 1 3 5 7 9 full: 1-9 last: 3-6 9-12 EOF close MSG; open(MSG, '>mh/tmp/.mh_seqnew') || print "6\n"; print MSG <<'EOF'; cur: 1 pseq: 3 7 unseen: 1 3-4 8 12 another: 1 3-8 12 hole: 1 3 5 7-8 9 full: 1-9 last: 3-6 8-12 new: 8 EOF close MSG; open(MSG, '>.mh_prof') || print "7\n"; print MSG <<'EOF'; Path: mh Unseen-Sequence: unseen, another, hole, full, last, new Msg-Protect: 0647 EOF close MSG; -d 'dir' || mkdir('dir', 0700) || print "8\n"; unlink ; open(MSG, '>dir/.prefix') || print "9\n"; print MSG "msg\nanother\n"; close MSG; open(MSG, '>dir/msg4') || print "10\n"; close MSG; open(MSG, '>dir/other5') || print "11\n"; close MSG; open(MSG, '>dir/5') || print "12\n"; close MSG; `rm -rf mh/new`; -d 'mh/new' && print "13\n"; -d 'simple' || mkdir('simple', 0700) || print "14\n"; open(MSG, '>simple/3') || print "15\n"; close MSG; unlink 'mh/tmp/8', 'dir/msg5', 'simple/4', $user; &add_option("-o 'mhprofile: ~/.mh_prof' -o 'msgprefix: .prefix'"); &add_header('X-Tag: mh'); `$cmd`; $? == 0 || print "16\n"; -f "$user" && print "17\n"; -s 'mh/tmp/8' || print "18\n"; system "cmp -s mh/tmp/.mh_sequences mh/tmp/.mh_seqnew >/dev/null 2>&1"; $? == 0 || print "19\n"; -f 'mh/new/1' || print "20\n"; -s 'mh/new/.mh_sequences' || print "21\n"; -s 'dir/msg5' || print "22\n"; -s 'simple/4' || print "23\n"; sub st_mode { (stat($_[0]))[2] & 0777; } &st_mode('mh/tmp/8') == oct("0647") || print "24\n"; # Default Msg-Protect &st_mode('mh/new/1') == oct("0567") || print "25\n"; # PROTECT command &st_mode('dir/msg5') == oct("0567") || print "26\n"; # idem &st_mode('simple/4') == oct("0644") || print "27\n"; # Default umask system "rm -rf mh dir simple >/dev/null 2>&1"; unlink $user, 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/misc/usrmac.t0000644000175000017500000000520510473324174017275 0ustar jdgjdg# Test user-defined macros at the perl level # NOTE: this test relies on a working PERL command # $Id: usrmac.t,v 3.0 1993/11/29 13:50:11 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: usrmac.t,v $ # Revision 3.0 1993/11/29 13:50:11 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/cmd.pl'; unlink "$user"; open(SCRIPT, '>script') || print "1\n"; print SCRIPT <<'EOC'; sub macfunc { # Used for function macro substitution "macfunc $_[0] string"; } $macval = 'macval string'; # Used for perl expression macro substitution &usrmac'new('m', 'orig-macro-m', 'SCALAR'); &usrmac'push('m', 'this-is-macro-m', 'SCALAR'); &usrmac'new('mac1', "\$mailhook'macval", 'CONST'); &usrmac'new('mac2', "mailhook'macfunc", 'FN'); &substitute(1); &usrmac'new('m', 'this-is-macro-mbis', 'SCALAR'); &usrmac'push('mac1', "\$mailhook'macval", 'EXPR'); &usrmac'push('mac2', '/bin/sh -c "echo macro %%-[%n]"', 'PROG'); $macval = 'macval bis'; &substitute(2); &usrmac'pop('mac1'); &usrmac'pop('mac2'); &usrmac'pop('m'); &substitute(3); sub substitute { local($num) = @_; open(TEXT, 'text'); open(OUT, ">subst.$num"); local($_); while () { print OUT &'macros_subst(*_); } close OUT; close TEXT; } EOC close SCRIPT; open(TEXT, '>text') || print "2\n"; print TEXT <<'EOT'; %%%A%% %N %-m %=vacation %-(mac1) %-(mac2) This %-m is %-(mac1) and %-(mac2). EOT close TEXT; $result1 = <<'EOR'; %cambridge.ma.us% compilers-request this-is-macro-m OFF macval string macfunc mac2 string This this-is-macro-m is macval string and macfunc mac2 string. EOR $result2 = <<'EOR'; %cambridge.ma.us% compilers-request this-is-macro-mbis OFF macval bis macro %-[mac2] This this-is-macro-mbis is macval bis and macro %-[mac2]. EOR $result3 = <<'EOR'; %cambridge.ma.us% compilers-request orig-macro-m OFF macval string macfunc mac2 string This orig-macro-m is macval string and macfunc mac2 string. EOR sub verify { local($file, $result, $error) = @_; local($var); $var = `cat $file 2>&1`; $var eq $result || print "$error\n"; } &add_header('X-Tag: usrmac'); `$cmd`; $? == 0 || print "3\n"; -f "$user" && print "4\n"; # Created only if perl script fails &verify('subst.1', $result1, 5); &verify('subst.2', $result2, 6); &verify('subst.3', $result3, 7); unlink "$user", 'mail', 'script', 'text', 'subst.1', 'subst.2', 'subst.3'; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/0000755000175000017500000000000011675050333016144 5ustar jdgjdgmailagent-3.1-74.orig/agent/test/filter/default.t0000644000175000017500000000257610473324174017771 0ustar jdgjdg# Make sure default actions apply correctly # $Id: default.t,v 3.0 1993/11/29 13:49:58 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: default.t,v $ # Revision 3.0 1993/11/29 13:49:58 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/filter.pl'; &add_header('X-Tag: default #1'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Must have been deleted &replace_header('X-Tag: default #2'); `$cmd`; $? == 0 || print "3\n"; -f "$user" || print "4\n"; # A NOP -> default action leave &get_mbox(5); &replace_header('X-Tag: never matched'); `$cmd`; $? == 0 || print "6\n"; -f "$user" || print "7\n"; # No match -> default action &get_mbox(8); $mbox2 eq $mbox1 || print "9\n"; &replace_header('X-Tag: unknonw'); `$cmd`; $? == 0 || print "10\n"; -f "$user" || print "11\n"; # Unknown action without previous saving &get_mbox(12); $mbox2 eq $mbox1 || print "13\n"; unlink 'mail'; print "0\n"; sub get_mbox { local($num); undef $/; open(MBOX, "$user"); eval "$mbox$num = "; close MBOX; $/ = "\n"; unlink "$user"; } mailagent-3.1-74.orig/agent/test/filter/pattern.t0000644000175000017500000000205310473324174020010 0ustar jdgjdg# Test selectors specified via a pattern # $Id: pattern.t,v 3.0.1.1 1996/12/24 15:03:19 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: pattern.t,v $ # Revision 3.0.1.1 1996/12/24 15:03:19 ram # patch45: added Relayed to the list of returned headers # # Revision 3.0 1993/11/29 13:50:05 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/filter.pl'; unlink 'macro'; &add_header('X-Tag: pattern'); &add_header('Replied: ram@eiffel.com'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Must have been deleted -f 'macro' || print "3\n"; # Created by RUN chop($macro = `cat macro 2>/dev/null`); $macro eq 'Received,Relayed,Replied;Subject;' || print "4\n"; unlink 'macro'; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/mode.t0000644000175000017500000000176710473324174017272 0ustar jdgjdg# Test negated mode # $Id: mode.t,v 3.0 1993/11/29 13:50:02 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: mode.t,v $ # Revision 3.0 1993/11/29 13:50:02 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/filter.pl'; unlink 'never', 'always', 'always.2', 'always.3'; &add_header('X-Tag: mode'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Mail has been deleted -f 'never' && print "3\n"; # Cannot match -f 'always' || print "4\n"; # This one must have matched -f 'always.2' || print "5\n"; # Direct match -f 'always.3' || print "6\n"; # Another implied direct match unlink 'never', 'always', 'always.2', 'always.3'; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/backref.t0000644000175000017500000000227010473324174017731 0ustar jdgjdg# Test backreferences # $Id: backref.t,v 3.0 1993/11/29 13:49:56 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: backref.t,v $ # Revision 3.0 1993/11/29 13:49:56 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/filter.pl'; unlink 'output', 'comp.unix.wizards'; &add_header('X-Tag: backref #1'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Must have been deleted -f 'output' || print "3\n"; # Created by RUN chop($output = `cat output 2>/dev/null`); $output eq 'ref,,ram@eiffel.com,melting technology' || print "4\n"; &replace_header('X-Tag: backref #2'); &add_header('Newsgroups: comp.mail.mh,comp.unix.wizards,talk.bizarre'); `$cmd`; $? == 0 || print "5\n"; -f "$user" && print "6\n"; # Must have been saved -f 'comp.unix.wizards' || print "7\n"; # Created by SAVE unlink 'output', 'comp.unix.wizards'; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/escape.t0000644000175000017500000000160010473324174017570 0ustar jdgjdg# Test escape sequences within rules # $Id: escape.t,v 3.0 1993/11/29 13:49:58 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: escape.t,v $ # Revision 3.0 1993/11/29 13:49:58 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/filter.pl'; unlink 'output'; &add_header('X-Tag: escape'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Must have been deleted -f 'output' || print "3\n"; # Created by RUN chop($output = `cat output 2>/dev/null`); $output eq ';,\\;,\\,\\w' || print "4\n"; unlink 'output'; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/not.t0000644000175000017500000000230210473324174017130 0ustar jdgjdg# Test negation pattern matching with '!' # $Id: not.t,v 3.0 1993/11/29 13:50:04 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: not.t,v $ # Revision 3.0 1993/11/29 13:50:04 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/filter.pl'; unlink 'never', 'always', 'always.2', 'always.3'; &add_header('X-Tag: not #1'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Mail has been deleted -f 'never' && print "3\n"; # Cannot match -f 'always' || print "4\n"; # This one must have matched -f 'always.2' || print "5\n"; # Did not match, but '!' saves us -f 'always.3' || print "6\n"; # No pattern from file matched unlink 'never', 'always', 'always.2', 'always.3'; &replace_header('X-Tag: not #2'); `$cmd`; $? == 0 || print "7\n"; -f "$user" && print "8\n"; # Mail has been saved -f 'always' || print "9\n"; unlink 'always'; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/status.t0000644000175000017500000000171110473324174017656 0ustar jdgjdg# Make sure commands record their exit status # $Id: status.t,v 3.0 1993/11/29 13:50:06 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: status.t,v $ # Revision 3.0 1993/11/29 13:50:06 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/filter.pl'; unlink 'never', 'always', 'always.2', 'always.3'; &add_header('X-Tag: status'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Mail has been saved -f 'never' && print "3\n"; # Cannot match -f 'always' || print "4\n"; -f 'always.2' || print "5\n"; -f 'always.3' || print "6\n"; unlink 'never', 'always', 'always.2', 'always.3'; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/base64.t0000644000175000017500000000160611024437250017413 0ustar jdgjdg# Check base64 body decoding for matching # $Id: base64.t 38 2008-06-13 09:32:24Z rmanfredi $ # # Copyright (c) 2008, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. do '../pl/filter.pl'; do '../pl/logfile.pl'; unlink 'always'; &cp_mail("../base64"); &add_header('x-tag: base64'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # No default action -f 'always' || print "3\n"; # Recognized both X-Tag and Body &get_log(4, 'always'); ¬_log('YES, successfully decoded', 5); # Body NOT decoded &check_log('Y29kaW5nIGxvZ2ljIGlzIHdvcmtpbmcuDQo=', 6); unlink 'always', "$user"; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/case.t0000644000175000017500000000166110473324174017252 0ustar jdgjdg# Check header field case insensitiveness # $Id: case.t,v 3.0 1993/11/29 13:49:57 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: case.t,v $ # Revision 3.0 1993/11/29 13:49:57 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/filter.pl'; do '../pl/logfile.pl'; unlink 'always'; &add_header('x-tag: case'); &add_header('CC: root'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # No default action -f 'always' || print "3\n"; # Recognized both X-Tag and CC &get_log(4, 'always'); ¬_log('CC:', 5); # CC was STRIPed out unlink 'always', "$user"; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/range.t0000644000175000017500000000305210473324174017427 0ustar jdgjdg# Test range selection # $Id: range.t,v 3.0 1993/11/29 13:50:05 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: range.t,v $ # Revision 3.0 1993/11/29 13:50:05 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/filter.pl'; unlink 'never', 'never.2', 'never.3', 'never.4', 'never.5', 'never.6', 'always', 'always.2', 'always.3', 'always.4', 'always.5', 'always.6', 'always.7', 'always.8'; &add_header('Cc: ram@acri.fr, must@yes.com, made@no.com'); &add_header('X-Tag: range'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Mail has been saved correctly -f 'never' && print "3\n"; # Never(s) cannot match -f 'never.2' && print "4\n"; -f 'never.3' && print "5\n"; -f 'never.4' && print "6\n"; -f 'always' || print "7\n"; # Always must match -f 'always.2' || print "8\n"; -f 'always.3' || print "9\n"; -f 'always.4' || print "10\n"; -f 'always.5' || print "11\n"; -f 'always.6' || print "12\n"; -f 'always.7' || print "13\n"; -f 'always.8' || print "14\n"; -f 'never.5' && print "15\n"; -f 'never.6' && print "16\n"; unlink 'never', 'never.2', 'never.3', 'never.4', 'never.5', 'never.6', 'always', 'always.2', 'always.3', 'always.4', 'always.5', 'always.6', 'always.7', 'always.8'; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/list.t0000644000175000017500000000567610473324174017324 0ustar jdgjdg# This tests mathching on list selectors like To or Newsgroups. # $Id: list.t,v 3.0.1.3 2001/03/17 18:16:05 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: list.t,v $ # Revision 3.0.1.3 2001/03/17 18:16:05 ram # patch72: unlink files we expect to be created before running command # # Revision 3.0.1.2 1999/07/12 13:57:15 ram # patch66: added new test cases # # Revision 3.0.1.1 1996/12/24 15:03:03 ram # patch45: added new tests for Relayed processing # # Revision 3.0 1993/11/29 13:50:01 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/filter.pl'; sub cleanup { for ($i = 1; $i <= 9; $i++) { unlink "$user.$i"; } for ($i = 1; $i <= 3; $i++) { unlink "ok.$i"; } unlink 'never'; } &cleanup; &add_header('X-Tag: list #1'); unlink "$user.1"; `$cmd`; $? == 0 || print "1\n"; -f "$user.1" || print "2\n"; unlink "$user.1"; &replace_header('To: uunet!eiffel.com!max, other@max.com'); unlink "$user.2"; `$cmd`; $? == 0 || print "3\n"; -f "$user.2" || print "4\n"; unlink "$user.2"; &replace_header('To: root@eiffel.com (Super User), max '); unlink "$user.3"; `$cmd`; $? == 0 || print "5\n"; -f "$user.3" || print "6\n"; unlink "$user.3"; # Following is illeaal in RFC-822: should be "root@eiffel.com" &replace_header('To: riot@eiffel.com (Riot Manager), root@eiffel.com '); unlink "$user.4"; `$cmd`; $? == 0 || print "7\n"; -f "$user.4" || print "8\n"; unlink "$user.4"; &replace_header('To: other, me, riotintin@eiffel.com, and, so, on'); unlink "$user.5"; `$cmd`; $? == 0 || print "9\n"; -f "$user.5" || print "10\n"; unlink "$user.5"; &replace_header('To: other, me, chariot@eiffel.com, and, so, on'); unlink "$user.6"; `$cmd`; $? == 0 || print "11\n"; -f "$user.6" || print "12\n"; unlink "$user.6"; &replace_header('To: other, me, abricot@eiffel.com, and, so, on'); &add_header('Newsgroups: comp.lang.perl, news.groups, news.lists'); unlink "$user.7"; `$cmd`; $? == 0 || print "13\n"; -f "$user.7" || print "14\n"; unlink "$user.7"; &replace_header('Newsgroups: comp.lang.perl, news.groups, news.answers'); unlink "$user.9"; `$cmd`; $? == 0 || print "15\n"; -f "$user.9" || print "16\n"; unlink "$user.9"; &replace_header('Newsgroups: none'); &replace_header('To: abricot@eiffel.com, rame@hp.com'); &add_header('To: root@localhost'); unlink "$user.8"; `$cmd`; $? == 0 || print "17\n"; -f "$user.1" && print "18\n"; -f "$user.8" || print "19\n"; unlink "$user.8"; &replace_header('X-Tag: list #2'); `$cmd`; $? == 0 || print "20\n"; -f 'ok.1' || print "21\n"; -f 'ok.2' || print "22\n"; -f 'ok.3' || print "23\n"; -f 'never' && print "24\n"; &cleanup; unlink 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/loop.t0000644000175000017500000000164410473324174017311 0ustar jdgjdg# Ensure loops are detected # $Id: loop.t,v 3.0 1993/11/29 13:50:02 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: loop.t,v $ # Revision 3.0 1993/11/29 13:50:02 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/filter.pl'; &add_header('X-Tag: loop #1'); `$cmd`; $? == 0 || print "1\n"; -f "$user" || print "2\n"; # Loop was detected (otherwise never ends) `mv $user mail 2>/dev/null`; &replace_header('X-Tag: loop #2'); `$cmd`; $? == 0 || print "3\n"; -f "$user" || print "4\n"; # Loop was detected (otherwise mail deleted) unlink 'mail', "$user"; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/multiple.t0000644000175000017500000000226310473324174020171 0ustar jdgjdg# Test matches with multiple headers # $Id: multiple.t,v 3.0 1993/11/29 13:50:03 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: multiple.t,v $ # Revision 3.0 1993/11/29 13:50:03 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/filter.pl'; for ($i = 1; $i <= 3; $i++) { unlink "$user.$i"; } &add_header('X-Tag: multiple #1'); `$cmd`; $? == 0 || print "1\n"; -f "$user.1" || print "2\n"; # Selection worked unlink "$user.1"; &replace_header('X-Tag: multiple #2'); &add_header('X-Other: multiple #2'); `$cmd`; $? == 0 || print "3\n"; -f "$user.2" || print "4\n"; # Selection worked unlink "$user.2"; &add_header('X-Other: another'); `$cmd`; $? == 0 || print "5\n"; -f "$user.3" || print "6\n"; # Selection worked -f "$user.2" || print "7\n"; # Selection on non-existent field unlink "$user.2", "$user.3"; unlink 'mail'; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/hook.t0000644000175000017500000000510110473324174017270 0ustar jdgjdg# Test hooking facilities # $Id: hook.t,v 3.0 1993/11/29 13:50:00 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: hook.t,v $ # Revision 3.0 1993/11/29 13:50:00 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/filter.pl'; do '../pl/logfile.pl'; unlink 'never', 'always', 'always.2', 'always.3'; unlink 'hook.1', 'hook.2', 'hook.3', 'hook.4'; open(HOOK, '>hook.1') || print "1\n"; print HOOK <<'EOH'; #! /bin/sh cat > always exit 0 EOH close HOOK; open(HOOK, '>hook.2') || print "2\n"; print HOOK <<'EOH'; #: deliver open(OUT, '>always.2') || exit 1; print OUT "$login\n"; close OUT; print "SAVE ~/always; RUN /bin/echo hi! > always.3"; EOH close HOOK; open(HOOK, '>hook.3') || print "3\n"; print HOOK <<'EOH'; #: rules !To: ram { SAVE never }; { SAVE ~/always; RUN /bin/echo hi! > always.3 }; EOH close HOOK; open(HOOK, '>hook.4') || print "29\n"; print HOOK <<'EOH'; #: perl &save("~/always"); &run("/bin/echo hi! > always.3"); EOH close HOOK; chmod 0544, 'hook.1', 'hook.2', 'hook.3', 'hook.4'; &add_header('X-Tag: hook #1'); `$cmd`; $? == 0 || print "4\n"; -f 'never' && print "5\n"; &get_log(6, 'always'); &check_log('^To: ram', 7) == 1 || print "8\n"; &get_log(9, 'hook.1'); ¬_log('^To: ram', 10); unlink 'never', 'always', 'always.2', 'always.3'; &replace_header('X-Tag: hook #2'); `$cmd`; $? == 0 || print "11\n"; -f 'never' && print "12\n"; &get_log(13, 'always'); &check_log('^To: ram', 14) == 1 || print "15\n"; &get_log(16, 'always.3'); &check_log('^hi!', 17) == 1 || print "18\n"; &get_log(19, 'always.2'); &check_log('^compilers-request$', 20); unlink 'never', 'always', 'always.2', 'always.3'; &replace_header('X-Tag: hook #3'); `$cmd`; $? == 0 || print "21\n"; -f 'never' && print "22\n"; &get_log(23, 'always'); &check_log('^To: ram', 24) == 1 || print "25\n"; &get_log(26, 'always.3'); &check_log('^hi!', 27) == 1 || print "28\n"; unlink 'never', 'always', 'always.2', 'always.3'; &replace_header('X-Tag: hook #4'); `$cmd`; $? == 0 || print "30\n"; -f 'never' && print "31\n"; &get_log(32, 'always'); &check_log('^To: ram', 33) == 1 || print "34\n"; &get_log(35, 'always.3'); &check_log('^hi!', 36) == 1 || print "37\n"; unlink 'hook.1', 'hook.2', 'hook.3', 'hook.4'; unlink 'never', 'always', 'always.2', 'always.3'; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/group.t0000644000175000017500000000244510473324174017474 0ustar jdgjdg# Test grouping of selectors (mixing normal and inverted selections) # $Id: group.t,v 3.0.1.1 1994/04/25 15:25:47 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: group.t,v $ # Revision 3.0.1.1 1994/04/25 15:25:47 ram # patch7: added three additional tests after a bug was found # # Revision 3.0 1993/11/29 13:49:59 ram # Baseline for mailagent 3.0 netwide release. # do '../pl/filter.pl'; sub cleanup { unlink 'never', 'never.2', 'always', 'always.2', 'always.3', 'always.4', 'always.5'; } &add_header('Cc: guy_1@acri.fr, guy_2@eiffel.com, guy_3@inria.fr'); &add_header('X-Tag: group'); &cleanup; `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Mail has been deleted -f 'never' && print "3\n"; # Cannot match -f 'always' || print "4\n"; # This one must have matched -f 'always.2' || print "5\n"; -f 'always.3' || print "6\n"; -f 'never.2' && print "7\n"; -f 'always.4' || print "8\n"; -f 'always.5' || print "9\n"; &cleanup; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/address.t0000644000175000017500000000233610473324174017764 0ustar jdgjdg# Test various match patterns on address fields # $Id: address.t,v 3.0.1.1 2001/03/17 18:15:16 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: address.t,v $ # Revision 3.0.1.1 2001/03/17 18:15:16 ram # patch72: created # do '../pl/filter.pl'; sub cleanup { for $i (1..7) { unlink "ok.$i" } for $i (1..8) { unlink "bad.$i" } } &cleanup; &add_header('X-Tag: address #1'); &replace_header('To: Raphael Manfredi '); `$cmd`; $? == 0 || print "1\n"; -f "ok.1" || print "2\n"; -f "ok.2" || print "3\n"; -f "ok.3" || print "4\n"; -f "ok.4" || print "5\n"; -f "ok.5" || print "6\n"; -f "ok.6" || print "7\n"; -f "ok.7" || print "8\n"; -f "bad.1" && print "9\n"; -f "bad.2" && print "10\n"; -f "bad.3" && print "11\n"; -f "bad.4" && print "12\n"; -f "bad.5" && print "13\n"; -f "bad.6" && print "14\n"; -f "bad.7" && print "15\n"; -f "bad.8" && print "16\n"; &cleanup; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/macros.t0000644000175000017500000000212410473324174017616 0ustar jdgjdg# Test patterns with macros in them # $Id: macros.t,v 3.0.1.2 1994/10/10 10:26:10 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: macros.t,v $ # Revision 3.0.1.2 1994/10/10 10:26:10 ram # patch19: added various escapes in strings for perl5 support # # Revision 3.0.1.1 1994/07/01 15:09:17 ram # patch8: created # do '../pl/filter.pl'; &add_header('X-Tag: macros'); &replace_header("To: $user\@eiffel.com"); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # Must have been deleted unlink $user; # Just in case # Now check that macro susbstitution occurs in pattern when enabled $cmd =~ s/^(\S+)/$1 -o 'rulemac: ON'/; `$cmd`; $? == 0 || print "3\n"; -f "$user" || print "4\n"; # This time, it has been leaved unlink $user; print "0\n"; mailagent-3.1-74.orig/agent/test/filter/qp.t0000644000175000017500000000152211024437250016744 0ustar jdgjdg# Check quoted-printable body decoding for matching # $Id: qp.t 38 2008-06-13 09:32:24Z rmanfredi $ # # Copyright (c) 2008, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. do '../pl/filter.pl'; do '../pl/logfile.pl'; unlink 'always'; &cp_mail("../qp"); &add_header('x-tag: qp'); `$cmd`; $? == 0 || print "1\n"; -f "$user" && print "2\n"; # No default action -f 'always' || print "3\n"; # Recognized both X-Tag and Body &get_log(4, 'always'); ¬_log('broken', 5); # Body NOT decoded &check_log('brok=', 6); unlink 'always', "$user"; print "0\n"; mailagent-3.1-74.orig/agent/test/mime0000644000175000017500000000230311024475423015526 0ustar jdgjdgFrom raphael_manfredi@pobox.com Tue Jun 10 17:44:12 2008 Received: from tours.ram.loc (fetchmail@localhost [127.0.0.1]) by tours.ram.loc (8.14.3/8.13.8/Debian-3) with ESMTP id m5AFiCJq002957 for ; Tue, 10 Jun 2008 17:44:12 +0200 From: "Raphael Manfredi" To: "Raphael Manfredi" Date: Tue, 10 Jun 2008 15:35:21 +0000 Subject: Sample MIME message Message-ID: MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="foo" Status: RO Content-Length: 609 Lines: 22 --foo Content-Type: text/html; charset="iso8859-1" Sample HTML part

Sole paragraph

--foo Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Content-Length: 346 VGhpcyBtZXNzYWdlIGlzIG9uZSBiaWcgTUlNRSBwYXJ0IHRoYXQgaGFzIGJlZW4gYmFzZTY0LWVu Y29kZWQuDQoNClRoZSBtYWlsYWdlbnQgdGVzdCBzdWl0ZSBpcyBnb2luZyB0byBsb29rIGZvciB0 aGUgZm9sbG93aW5nIGxpbmU6DQoNCiAgICAgICAgKioqIFlFUywgc3VjY2Vzc2Z1bGx5IGRlY29k ZWQgKioqDQoNCmluIHRoZSBkZWNvZGVkIGJvZHkgYXMgcHJvb2YgdGhhdCB0aGUgYmFzZTY0IGRl Y29kaW5nIGxvZ2ljIGlzIHdvcmtpbmcuDQo= --foo-- mailagent-3.1-74.orig/agent/test/pl/0000755000175000017500000000000011675050334015273 5ustar jdgjdgmailagent-3.1-74.orig/agent/test/pl/init.pl0000644000175000017500000000245510473324174016602 0ustar jdgjdg# Set up mailagent and filter paths ;# $Id: init.pl 1 2006-08-24 13:24:12Z rmanfredi $ ;# ;# Copyright (c) 1990-2006, Raphael Manfredi ;# ;# You may redistribute only under the terms of the Artistic License, ;# as specified in the README file that comes with the distribution. ;# You may reuse parts of this distribution only within the terms of ;# that same Artistic License; a copy of which may be found at the root ;# of the source tree for mailagent 3.0. ;# ;# $Log: init.pl,v $ ;# Revision 3.0.1.3 1999/01/13 18:16:59 ram ;# patch64: cleanup agent.wait file since now always produced ;# ;# Revision 3.0.1.2 1995/08/07 16:28:52 ram ;# patch37: added support for locking on filesystems with short filenames ;# ;# Revision 3.0.1.1 1994/07/01 15:10:38 ram ;# patch8: fixed RCS leading comment string ;# ;# Revision 3.0 1993/11/29 13:50:24 ram ;# Baseline for mailagent 3.0 netwide release. ;# $pwd = $ENV{'PWD'}; # Where TEST was invoked from $lockext = $ENV{'LOCKEXT'}; # Locking extension ($up) = $pwd =~ m|^(.*)/.*|; $mailagent_prog = $ENV{'MAILAGENT'}; $mailagent_path = "$up/$mailagent_prog"; $mailagent = "$mailagent_path -TEST"; $filter = "$up/filter/filter"; # Make sure no lock were left by previous test unlink "$pwd/out/filter$lockext", "$pwd/out/perl$lockext"; unlink 'agent.wait'; mailagent-3.1-74.orig/agent/test/pl/mta.pl0000644000175000017500000000166510473324174016422 0ustar jdgjdg# Basic MTA/NTA for tests # $Id: mta.pl 1 2006-08-24 13:24:12Z rmanfredi $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: mta.pl,v $ # Revision 3.0 1993/11/29 13:50:26 ram # Baseline for mailagent 3.0 netwide release. # unlink 'send.mail', 'send.news'; # Output from our MTA and NTA open(MSEND, '>msend'); print MSEND <<'EOM'; #!/bin/sh echo "Recipients: $@" >> send.mail exec cat >> send.mail EOM close MSEND; open(NSEND, '>nsend'); print NSEND <<'EOM'; #!/bin/sh exec cat >> send.news EOM close NSEND; chmod 0755, 'msend', 'nsend'; sub clear_mta { unlink 'msend', 'nsend', 'send.mail', 'send.news'; } mailagent-3.1-74.orig/agent/test/pl/cmd.pl0000644000175000017500000000172310473324174016377 0ustar jdgjdg# Common actions at the top of each command test ;# $Id: cmd.pl 1 2006-08-24 13:24:12Z rmanfredi $ ;# ;# Copyright (c) 1990-2006, Raphael Manfredi ;# ;# You may redistribute only under the terms of the Artistic License, ;# as specified in the README file that comes with the distribution. ;# You may reuse parts of this distribution only within the terms of ;# that same Artistic License; a copy of which may be found at the root ;# of the source tree for mailagent 3.0. ;# ;# $Log: cmd.pl,v $ ;# Revision 3.0.1.1 1994/07/01 15:09:44 ram ;# patch8: the cp_mail routine is now located in mail.pl ;# ;# Revision 3.0 1993/11/29 13:50:22 ram ;# Baseline for mailagent 3.0 netwide release. ;# do '../pl/init.pl'; chdir '../out'; do '../pl/mail.pl'; &cp_mail; # From mail.pl $user = $ENV{'USER'}; unlink "$user", 'agentlog', 'send.mail', 'send.news'; $cmd = "$mailagent -L $ENV{'LEVEL'} -r ../actions mail 2>/dev/null"; # We might need this do '../pl/logfile.pl'; mailagent-3.1-74.orig/agent/test/pl/filter.pl0000644000175000017500000000206410473324174017120 0ustar jdgjdg# Common actions at the top of each filtering test ;# $Id: filter.pl 1 2006-08-24 13:24:12Z rmanfredi $ ;# ;# Copyright (c) 1990-2006, Raphael Manfredi ;# ;# You may redistribute only under the terms of the Artistic License, ;# as specified in the README file that comes with the distribution. ;# You may reuse parts of this distribution only within the terms of ;# that same Artistic License; a copy of which may be found at the root ;# of the source tree for mailagent 3.0. ;# ;# $Log: filter.pl,v $ ;# Revision 3.0.1.1 1994/07/01 15:10:19 ram ;# patch8: now uses the cp_mail routine to copy mail ;# ;# Revision 3.0 1993/11/29 13:50:23 ram ;# Baseline for mailagent 3.0 netwide release. ;# do '../pl/init.pl'; chdir '../out'; do '../pl/mail.pl'; &cp_mail; # From mail.pl $user = $ENV{'USER'}; unlink $user, 'agentlog'; $cmd = "$mailagent -L $ENV{'LEVEL'} -r ../rules mail 2>/dev/null"; # Re-create pattern list open(PATTERN, ">pattern-list"); print PATTERN <<'EOP'; no-match-possible another-impossible-match # This will match pattern EOP close PATTERN; mailagent-3.1-74.orig/agent/test/pl/mail.pl0000644000175000017500000000452411024437250016551 0ustar jdgjdg# Utilities to twinkle default mail message ;# $Id: mail.pl 38 2008-06-13 09:32:24Z rmanfredi $ ;# ;# Copyright (c) 1990-2006, Raphael Manfredi ;# ;# You may redistribute only under the terms of the Artistic License, ;# as specified in the README file that comes with the distribution. ;# You may reuse parts of this distribution only within the terms of ;# that same Artistic License; a copy of which may be found at the root ;# of the source tree for mailagent 3.0. ;# ;# $Log: mail.pl,v $ ;# Revision 3.0.1.2 1997/09/15 15:19:30 ram ;# patch57: forgot to unlink mail.lock in cp_mail() ;# ;# Revision 3.0.1.1 1994/07/01 15:11:46 ram ;# patch8: fixed RCS leading comment string ;# patch8: now defines the cp_mail routine ;# patch8: the replace_header routine can now supersede header lines ;# ;# Revision 3.0 1993/11/29 13:50:25 ram ;# Baseline for mailagent 3.0 netwide release. ;# # Add header line within message sub add_header { local($header, $file) = @_; $file = 'mail' unless $file; local($_); open(NEW, ">$file.x"); open(OLD, "$file"); while () { print NEW $header, "\n" if (1../^$/) && /^$/; print NEW; } close NEW; close OLD; rename("$file.x", "$file"); } # Change first matching header with new value. If $supersede is given, then # the it is used instead. This enables: # &replace_header('To:', 'xxx', 'Cc: me') # to replace the whole first To: line by a Cc: header. If this third argument # is not supplied, then the first one is used verbatim, which is the case in # most calls to this routine. sub replace_header { local($header, $file, $supersede) = @_; $supersede = $header unless defined $supersede; $file = 'mail' unless $file; local($field) = $header =~ /^(\S+):/; local($_); open(NEW, ">$file.x"); open(OLD, "$file"); while () { if ((1../^$/) && eval "/^$field:/") { print NEW $supersede, "\n"; next; } print NEW; } close NEW; close OLD; rename("$file.x", "$file"); } # Add line at the end of the mail message sub add_body { local($line, $file) = @_; $file = 'mail' unless $file; open(NEW, ">>$file"); print NEW $line, "\n"; close NEW; } # Copy mail in out/ sub cp_mail { my ($file) = @_; $file = "../mail" unless defined $file; local($_); open(MAIL, $file) || die "Can't open $file: $!"; open(HERE, '>mail'); print HERE while ; close MAIL; close HERE; unlink 'mail.lock'; } mailagent-3.1-74.orig/agent/test/pl/misc.pl0000644000175000017500000000155410473324174016571 0ustar jdgjdg# Common actions at the top of each misc test ;# $Id: misc.pl 1 2006-08-24 13:24:12Z rmanfredi $ ;# ;# Copyright (c) 1990-2006, Raphael Manfredi ;# ;# You may redistribute only under the terms of the Artistic License, ;# as specified in the README file that comes with the distribution. ;# You may reuse parts of this distribution only within the terms of ;# that same Artistic License; a copy of which may be found at the root ;# of the source tree for mailagent 3.0. ;# ;# $Log: misc.pl,v $ ;# Revision 3.0.1.1 1994/07/01 15:11:55 ram ;# patch8: fixed RCS leading comment string ;# ;# Revision 3.0 1993/11/29 13:50:26 ram ;# Baseline for mailagent 3.0 netwide release. ;# do '../pl/cmd.pl'; # Add option to command string held in $cmd sub add_option { local($opt) = @_; local(@cmd) = split(' ', $cmd); $cmd = join(' ', $cmd[0], $opt, @cmd[1..$#cmd]); } mailagent-3.1-74.orig/agent/test/pl/logfile.pl0000644000175000017500000000254310473324174017256 0ustar jdgjdg# Get log file (by default) or any other file into @log ;# $Id: logfile.pl 1 2006-08-24 13:24:12Z rmanfredi $ ;# ;# Copyright (c) 1990-2006, Raphael Manfredi ;# ;# You may redistribute only under the terms of the Artistic License, ;# as specified in the README file that comes with the distribution. ;# You may reuse parts of this distribution only within the terms of ;# that same Artistic License; a copy of which may be found at the root ;# of the source tree for mailagent 3.0. ;# ;# $Log: logfile.pl,v $ ;# Revision 3.0.1.2 1995/08/07 16:29:15 ram ;# patch37: simplified matching by removing spurious eval ;# ;# Revision 3.0.1.1 1994/07/01 15:10:42 ram ;# patch8: fixed RCS leading comment string ;# ;# Revision 3.0 1993/11/29 13:50:24 ram ;# Baseline for mailagent 3.0 netwide release. ;# sub get_log { local($num, $file) = @_; $file = 'agentlog' unless $file; open(LOG, $file) || print "$num\n"; @log = ; close LOG; } # Make sure a pattern is within @log, return number of matches sub check_log { local($pattern, $num) = @_; local(@matches); @matches = grep(/$pattern/, @log); print "$num\n" unless @matches; 0 + @matches; } # Make sure a pattern is NOT within @log, return number of matches sub not_log { local($pattern, $num) = @_; local(@matches); @matches = grep(/$pattern/, @log); print "$num\n" if @matches; 0 + @matches; } mailagent-3.1-74.orig/agent/test/Makefile.SH0000755000175000017500000000775311031240252016632 0ustar jdgjdg: Makefile.SH generated from Jmake.tmpl and Jmakefile [jmake 3.5-25] : $X-Id: Jmake.tmpl 8 2006-08-25 22:27:18Z rmanfredi $ case $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac CURRENT=agent/test DIR=`echo $CURRENT/ | sed -e 's/\.\///g'` echo "Extracting ${DIR}Makefile (with variable substitutions)" DATE=`date` $spitshell >Makefile <>Makefile <<'!NO!SUBS!' ######################################################################## # Jmake rules for building libraries, programs, scripts, and data files # $X-Id: Jmake.rules 18 2006-12-27 10:35:09Z rmanfredi $ ######################################################################## # Start of Jmakefile # $X-Id: Jmakefile,v 3.0 1993/11/29 13:49:20 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $X-Log: Jmakefile,v $ # Revision 3.0 1993/11/29 13:49:20 ram # Baseline for mailagent 3.0 netwide release. # all:: @echo "The following may take a while..." @echo "Don't panic if any of these tests fails and do not stop make."; \ ./TEST @if test -f OK; then \ echo "Failure detected, retrying one more time, just in case..."; \ echo "Successful tests will not be rerun but flagged as 'done'."; \ sleep 2; \ ./TEST; \ if test -f OK; then \ echo "Hmm... Still failed... There might be a real problem."; \ echo "I shall be using the plain (non dataloaded) version."; \ sleep 2;\ ./TEST -n; \ fi \ fi test: ./TEST -i local_clean:: $(RM) -r out $(RM) OK ######################################################################## # Common rules for all Makefiles -- do not edit all:: clean: local_clean realclean: local_realclean clobber: local_clobber local_clean:: if test -f core; then $(RM) core; fi $(RM) *~ *.o local_realclean:: local_clean local_clobber:: local_realclean $(RM) Makefile config.sh install:: local_install install.man:: maybe_install.man deinstall:: local_deinstall deinstall.man:: maybe_deinstall.man install.man-no: deinstall.man-no: maybe_install.man: install.man-no maybe_deinstall.man: deinstall.man-no Makefile.SH: Jmakefile -@if test -f $(TOP)/.package; then \ if test -f Makefile.SH; then \ echo " $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~"; \ $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~; \ fi; \ echo " $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT)" ; \ $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT) ; \ else touch $@; fi Makefile: Makefile.SH /bin/sh Makefile.SH tags:: $(CTAGS) -w *.[ch] $(CTAGS) -xw *.[ch] > tags local_clobber:: $(RM) tags ######################################################################## # Empty rules for directories with no sub-directories -- do not edit local_install:: @echo "install in $(CURRENT) done." local_deinstall:: @echo "deinstall in $(CURRENT) done." local_install.man:: @echo "install.man in $(CURRENT) done." local_deinstall.man:: @echo "deinstall.man in $(CURRENT) done." Makefiles:: Makefiles.SH:: !NO!SUBS! chmod 644 Makefile $eunicefix Makefile mailagent-3.1-74.orig/agent/test/actions0000644000175000017500000003116311030471671016243 0ustar jdgjdg# # Mailagent rules for action regression tests # # $Id: actions,v 3.0.1.15 2001/03/17 18:15:08 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: actions,v $ # Revision 3.0.1.15 2001/03/17 18:15:08 ram # patch72: fixed test rules for UNIQUE, removing spurious REJECT -f # # Revision 3.0.1.14 2001/03/13 13:15:56 ram # patch71: added test cases for SUBST/TR on header fields # # Revision 3.0.1.13 2001/01/10 16:58:28 ram # patch69: fixed dates for the SELECT test to avoid failures past 2001 # # Revision 3.0.1.12 1999/07/12 13:56:28 ram # patch66: added tests for variable propagation in APPLY # # Revision 3.0.1.11 1998/03/31 15:28:55 ram # patch59: added regression tests for new "ON" command # # Revision 3.0.1.10 1995/08/07 16:26:55 ram # patch37: new BIFF regression testing # # Revision 3.0.1.9 1995/02/16 14:37:50 ram # patch32: one more test for SAVE to check new fromfake feature # # Revision 3.0.1.8 1995/01/25 15:31:32 ram # patch27: extended rules for the PROTECT command tests # # Revision 3.0.1.7 1995/01/03 18:19:14 ram # patch24: added new tests for ANNOTATE -u and VACATION -l # # Revision 3.0.1.6 1994/09/22 14:40:32 ram # patch12: added regression tests for DO # # Revision 3.0.1.5 1994/07/01 15:06:56 ram # patch8: added exit status test for PERL command # patch8: added new test for vacation message with tome config variable # patch8: new set of tests for the new UMASK command # # Revision 3.0.1.4 1994/04/25 15:24:12 ram # patch7: check bug reported by Andy Seaborne # # Revision 3.0.1.3 1994/01/26 09:35:08 ram # patch5: added new tests for UNIQUE and RECORD tags # patch5: ensure header-added recipients looked for in messages # # Revision 3.0.1.2 1993/12/17 08:13:20 ram # patch4: one spurious single quote still remained after patch3 # # Revision 3.0.1.1 1993/12/15 09:05:21 ram # patch3: extra closing single quote removed (was there since 2.9 PL0) # # Revision 3.0 1993/11/29 13:49:23 ram # Baseline for mailagent 3.0 netwide release. # maildir = ~; X-Tag: /abort/ { ABORT -f; SAVE always; ABORT; SAVE %u.1; } X-Tag: /annotate/ { ANNOTATE X-Anno-1: first; ANNOTATE X-Anno-2 second; ANNOTATE X-Anno-3; ANNOTATE -d X-Anno-Error; ANNOTATE -d X-Anno-4 fourth; ANNOTATE -du X-Anno-4 fourth; REJECT -f ANNOTATE; ANNOTATE -d -u X-Anno-5 fith; RESYNC; ANNOTATE -d -u X-Anno-5 fith; ANNOTATE -du X-Anno-5 fith; REJECT -t ANNOTATE; }; { SAVE never }; X-Tag: /apply #1/ { APPLY apply.1; REJECT -t APPLY; SAVE never }; { SAVE never; REJECT APPLY }; { APPLY apply.2; REJECT -f; SAVE always }; { SAVE never }; X-Tag: /apply #2/ { ASSIGN folder folder; APPLY apply.1; REJECT -f APPLY; SAVE %#folder; }; { SAVE never }; X-Tag: /assign #1/, To: /^(\w+)@/ { ASSIGN ram %1; ASSIGN other try; ASSIGN final '%#other.2'; ASSIGN :ram 1 + 2; RUN /bin/echo '%#ram,%#other,%#final' > output; } X-Tag: /assign #2/ { ASSIGN :ram %#:ram + 4; ASSIGN other '1+2'; ASSIGN final %#other + 4; RUN /bin/echo '%#:ram,%#other,%#final' > output; } X-Tag: /back/ { BACK RUN ~/pgm; } X-Tag: /beep 1/ { BIFF bfmt; BEEP 4; BEEP -l 3; REJECT BIFF }; { LEAVE }; X-Tag: /beep 2/ { BIFF bfmt; BEEP -l 0; LEAVE }; X-Tag: /begin/ { BEGIN ONE; BEGIN TWO; REJECT; } { SAVE one }; { SAVE two; BEGIN THREE; REJECT }; { SAVE three }; X-Tag: /biff 1/ { BIFF off; LEAVE; BIFF on; SAVE ok }; X-Tag: /biff 2/ { BIFF bfmt; SAVE ok; BIFF -l off; LEAVE }; X-Tag: /biff 3/ { BIFF bfmt; SAVE ok; }; X-Tag: /bounce 1/ { BOUNCE nobody }; X-Tag: /bounce 2/ { BOUNCE "list" }; X-Tag: /bounce 3/ { BOUNCE nobody; REJECT -f; DELETE }; X-Tag: /bounce 3/ { SAVE ok }; X-Tag: /delete/ { DELETE }; X-Tag: /do\b/ { REQUIRE perl.1 __test__; DO __test__'perl_1('always'); DO perl.2:__test__'perl_2("DO"); SAVE never; }; { SAVE always.2; DO __foo__'perl_3; SAVE never; }; X-Tag: /feed 1/ { FEED grep -v To:; SAVE ok; REJECT; } X-Tag: /feed 1/, !To: ram { SAVE resynced }; X-Tag: /feed 2/ { FEED tee output }; X-Tag: /feed 3/ { FEED -b tee output }; X-Tag: /feed 4/ { FEED -be tee output }; X-Tag: /forward 1/ { FORWARD nobody }; X-Tag: /forward 2/ { FORWARD "list" }; X-Tag: /forward 3/ { FORWARD nobody; REJECT -f; DELETE }; X-Tag: /forward 3/ { SAVE ok }; X-Tag: /give 1/ { GIVE wc > output }; X-Tag: /give 2/ { GIVE cat > output }; X-Tag: /keep/ { KEEP From: To Subject X-None X-Long-* U*; KEEP To Subject X-Long-* From X-None U*; KEEP X-Long-*: Unu*-Head* X-None: To: Subject: From:; KEEP "header-list" From; SAVE ok; REJECT; } X-Tag: /keep/, To: ram { SAVE no_resync }; X-Tag: /message 1/ { MESSAGE msg; DELETE }; X-Tag: /message 2/ { MESSAGE msg.2; DELETE }; X-Tag: /macro/ { MACRO first It seems to; MACRO first Another instance; MACRO -p first; MACRO second null; MACRO -r second = ('work fine', EXPR); MACRO third toto; MACRO -d third; RUN /bin/echo %-(first) %-(second)%-(third). > ok; DELETE; } X-Tag: /nop/ { NOP; DELETE }; X-Tag: /notify 1/ { NOTIFY msg nobody; DELETE }; X-Tag: /notify 2/ { NOTIFY msg "list"; DELETE }; X-Tag: /notify 3/ { NOTIFY msg.2 some@random.ctry %u; DELETE }; X-Tag: /^on$/ { ON (Mondays Tuesdays Wednesdays Thursdays Fridays Saturdays Sundays) LEAVE; ON (mon) SAVE days; ON (tue) SAVE days; ON (wed) SAVE days; ON (thu) SAVE days; ON (fri) SAVE days; ON (sat) SAVE days; ON (sun) SAVE days; ON (Mn Ts Wd Th Fr Sa Su) SAVE days; ON (mno tsx wda tuh frd sam sum) SAVE days; } X-Tag: /once/ { ONCE (ram,tag,1w) SAVE one; ONCE (ram,tag,1w) SAVE two; ONCE (mars,tag,1w) SAVE three; ONCE (other,tag,0m) SAVE four; } X-Tag: /pass 1/ { PASS grep -v and; PASS perl -p -e 's/^\>From /From /'; SAVE output; } X-Tag: /pass 2/ { PASS grep -v successfully; STRIP Content-Transfer-Encoding; SAVE output; } X-Tag: /pass 3/ { PASS grep -v broken; SAVE output; } X-Tag: /perl/ { REJECT PERL }; { PERL perl.2 exit_1; REJECT -t; SAVE exit_ok; REJECT }; { PERL perl.1; SAVE never }; { PERL perl.2 'arg 1' "arg 2"; SAVE never }; { PERL perl.1; SAVE never }; { PERL no_such_file; ABORT -f; SAVE never }; X-Tag: /pipe 1/ { PIPE wc > output }; X-Tag: /pipe 2/ { PIPE cat > output }; X-Tag: /pipe 3/ { PIPE -b cat > output }; X-Tag: /post 1/ { POST alt.test comp.others }; X-Tag: /post 2/ { POST -l "list" }; X-Tag: /purify 1/ { PURIFY grep -v Subject:; SAVE output; }; X-Tag: /purify 2/ { PURIFY grep -v Transfer-Encoding:; SAVE output; }; X-Tag: /protect/ { SAVE dflt; PROTECT 0444; SAVE fold.1; SAVE dflt; PROTECT -l 0666; SAVE fold.2; PROTECT -lu; SAVE fold.3; REJECT PROTECT; }; { SAVE fold.4; PROTECT -u; SAVE fold.5; }; X-Tag: /queue/ { QUEUE; QUEUE; QUEUE; QUEUE }; X-Tag: /record #1/ { RECORD; SAVE %u.1 }; X-Tag: /record #1/ { SAVE %u.1 }; <_SEEN_> X-Tag: /record #1/ { SAVE %u.2 }; X-Tag: /record #2/ { SAVE %u.3 }; X-Tag: /record #2/ { RECORD -r RECORD; SAVE %u.1 }; X-Tag: /record #3/ { RECORD -a; SAVE %u.1 }; X-Tag: /record #4/ { RECORD -c; REJECT -f RECORD; SAVE %u.1 }; X-Tag: /record #4/ { SAVE %u.2 }; X-Tag: /record/ { DELETE }; X-Tag: /record #5/ { RECORD (tag1,tag2); SAVE %u.1; REJECT }; X-Tag: /record #5/ { RECORD INITIAL (tag2); SAVE %u.2; REJECT }; X-Tag: /record #5/ { RECORD -r RECORD_CATCH; SAVE %u.3 }; X-Tag: /record #6/ { RECORD (tag); SAVE %u.1; REJECT }; X-Tag: /record #6/ { RECORD (other); SAVE %u.2; REJECT }; X-Tag: /record #6/ { RECORD -r RECORD_CATCH; SAVE %u.3 }; X-Tag: /require/ { REJECT REQUIRE; }; { REQUIRE non_existent; REJECT -f; SAVE never }; { REQUIRE perl.1; REJECT -t; SAVE never }; { REQUIRE perl.1; REJECT -t; SAVE never }; { REQUIRE perl.2 test_pack; REJECT -t; SAVE never }; { MACRO perl_1 = (newcmd'perl_1, FN); MACRO perl_2 = (&test_pack'perl_2, EXPR); RUN /bin/echo We got %-(perl_1) and %-(perl_2) here > ok; DELETE; }; X-Tag: /reject/ { REJECT REJ; SAVE %u.1 }; X-Tag: /reject/ { SAVE always; REJECT -t REJ; SAVE never }; X-Tag: /restart/ { RESTART -t RES; SAVE %u.1; REJECT }; X-Tag: /restart/ { RESTART no_such_mode; SAVE never }; X-Tag: /resync/, To: ram { PURIFY grep -v To:; RESYNC; REJECT; } X-Tag: /resync/, To: ram { SAVE %u.1 }; X-Tag: /resync/ { SAVE output }; X-Tag: /run/ { RUN /bin/echo Works. > ok; DELETE }; X-Tag: /save #1/ { SAVE mbox }; X-Tag: /save #2/ { SAVE path/another/third/mbox }; X-Tag: /save #3/ { SAVE ok }; X-Tag: /select/ { SELECT (Jan 2 1970 .. Dec 31 2037) SAVE one; SELECT (last month .. last minute) SAVE two; SELECT (last minute .. next minute) SAVE three; SELECT (now - 10 seconds .. now + 5 minutes) SAVE four; SELECT (Dec 31 2037 .. Jan 2 1970) SAVE five; } X-Tag: /unknown #1/ { unknown_command; DELETE }; X-Tag: /unknown #2/ { DELETE; unknown_command }; X-Tag: /split #1/ { SPLIT here; SAVE here }; X-Tag: /split #2/ { SPLIT -ida here }; X-Tag: /split #3/ { SPLIT -iew here }; X-Tag: /split #4/ { SPLIT -iew }; X-Tag: /split #5/ { SPLIT -iew here }; X-Tag: /digest/ { SAVE here }; X-Tag: /store #1/ { STORE mbox }; X-Tag: /store #2/ { STORE path/another/third/mbox }; X-Tag: /strip/ { STRIP X-N* Received:; STRIP Received; STRIP X-N* "header-list"; SAVE ok; REJECT; } X-Tag: /strip/, To: ram { SAVE no_resync }; X-Tag: /subst #1/, To: /(.*)/ { SUBST 1 /com/fr/g; ASSIGN subject %[Subject]; ASSIGN :persistent '%#subject'; SUBST #subject /^Re:\s+//; SUBST #:persistent /^Re:\s+//; RUN /bin/echo '%1,%#subject,%#:persistent' >output; DELETE; } X-Tag: /subst #2/ { SUBST to /eiffel\.com/chram.org/; SUBST Subject: /^Re:\s+//i; SUBST Received /eiffel\.com/chram.org/g; SAVE subst; REJECT SUBST; }; To: /^ram@chram\.org$/ { SAVE never; REJECT }; { RESYNC; REJECT }; To: /^ram@chram\.org$/ { SAVE always }; { SAVE never2 }; X-Tag: /tr #1/, To: /(.*)/ { TR 1 /a-z/A-Z/; ASSIGN subject %[Subject]; ASSIGN :persistent '%#subject'; TR #subject /ice/ICE/; TR #:persistent /ice/ICE/; RUN /bin/echo '%1,%#subject,%#:persistent' >output; DELETE; } X-Tag: /tr #2/ { TR To: /a-z/A-Z/; TR received /A-Z/a-z/; SAVE subst; REJECT TR; } To: /^RAM@EIFFEL.COM$/ { SAVE never; REJECT }; { RESYNC; REJECT }; To: /^RAM@EIFFEL.COM$/ { SAVE always }; { SAVE never2 }; X-Tag: /umask #1/ { REJECT UMASK; }; { UMASK -l 0444; PERL umask_is 0444; REJECT -f UMASKF; SAVE ok.1; REJECT; }; { PERL umask_is %=umask; REJECT -f UMASKF; SAVE ok.2; UMASK 0555; REJECT; }; { PERL umask_is 0555; REJECT -f UMASKF; DELETE; }; X-Tag: /umask #2/ { REJECT UMASK; }; { UMASK 0444; PERL umask_is 0444; REJECT -f UMASKF; SAVE ok.1; UMASK -l 0555; PERL umask_is 0555; REJECT -f UMASKF; REJECT; }; { PERL umask_is 0444; REJECT -f UMASKF; SAVE ok.2; }; X-Tag: /umask #3/ { REJECT UMASK; }; { PERL umask_is 0555; REJECT -t UMASKF; PERL umask_is %=umask; REJECT -f UMASKF; SAVE ok.3; }; { SAVE never; }; X-Tag: /unique #1/ { UNIQUE; SAVE %u.1 }; <_SEEN_> X-Tag: /unique #1/ { SAVE %u.1 }; X-Tag: /unique #1/ { SAVE %u.2 }; X-Tag: /unique #2/ { SAVE %u.3 }; X-Tag: /unique #2/ { UNIQUE -r UNIQUE; SAVE %u.1 }; X-Tag: /unique #3/ { UNIQUE -a; SAVE %u.1 }; X-Tag: /unique #4/ { UNIQUE -c; REJECT -f UNIQUE; SAVE %u.1 }; X-Tag: /unique #4/ { SAVE %u.2 }; X-Tag: /unique #5/ { UNIQUE -a (tag1,tag2); SAVE %u.1; REJECT }; X-Tag: /unique #5/ { UNIQUE (tag2); SAVE %u.2; REJECT }; X-Tag: /unique #5/ { UNIQUE -a; SAVE %u.3 }; X-Tag: /unique #6/ { UNIQUE (tag); SAVE %u.1; REJECT }; X-Tag: /unique #6/ { UNIQUE (other); SAVE %u.2; REJECT }; X-Tag: /unique #6/ { UNIQUE -a; SAVE %u.3 }; X-Tag: /vacation #2/ { DELETE }; X-Tag: /vacation #3/ { VACATION -l ~/.vacfile 3w; REJECT }; X-Tag: /vacation #3/ { DELETE }; X-Tag: /vacation #4/ { VACATION ~/.vacfile 3h; REJECT }; X-Tag: /vacation #4/ { DELETE }; X-Tag: /write #1/ { WRITE mbox }; X-Tag: /write #2/ { WRITE path/another/third/mbox }; X-Tag: /compress/ { LEAVE; SAVE always; SAVE another }; X-Tag: /mmdf/ { LEAVE; SAVE always; SAVE always }; X-Tag: /newcmd/ { FIRST_CMD arg1 arg2; SECOND_CMD; DELETE }; X-Tag: /usrmac/ { PERL script; ABORT -f; DELETE }; X-Tag: /mh/ { SAVE +tmp; PROTECT 0567; SAVE +new; SAVE dir; PROTECT -u; SAVE simple; }; mailagent-3.1-74.orig/agent/test/README0000644000175000017500000001015311017272724015537 0ustar jdgjdgThis is the root directory for the regression test suite. A regression test suite is not meant to be a validation suite. Rather, it is used by developpers to make sure nothing breaks between two snapshots or releases. Thoroughness is not a requirement, since it only affects the accuracy of the test. The single TEST executable will run the test suite and report any failure. Although not every feature of the mailagent is tested, having it pass the whole test suite is a Good Thing. Some commands like PROCESS or POST are not easy to test automatically, but if you can design good tests for them, I will be glad to include them. This set of programs were written quickly, as effeciency or maintainability was not the main issue, obviously. I believe they are reasonably well written, making it possible for someone to be able to understand and modify them. Running the whole test suite takes a long time. On my machine with 40 Mb of main memory, it requires 12 minutes to complete (in 1991). It may take a lot longer if you do not have at least 16 Mb of RAM. The following options are available to TEST: -i incremental, rerun only failed tests -m monitor logfile with "atail" -n use the non-dataloaded version -o allow outdated mailagent / filter -s stop at first error The option -i turns the incremental mode on. This proved really nice to me when I was writing this suite, as I was able to skip all the successful tests and focus only on those which failed or the new ones. The -s option will cause the test suite to stop at the first error. Normally, only failed basic tests abort the process. The -o option will not restart the tests from scratch, even if the mailagent or filter is newer than the current OK file. Option -n will test the non-dataloaded version of the mailagent (because of some bugs with eval() which cause the dataloaded version to dump core via a segmentation violation). The -m option is for desperate cases. It launches the atail process in the background (a real CPU hog) to monitor all changes to the out/agentlog file. This may be really convenient when debugging a test suite failure... Specifying a list of files on the command line will only run these tests. For instance: ./TEST options/i.t I don't know why I spent some time documenting all this (in 1992), as I don't expect anybody to have any chance working on this suite. Anyway, it might be nice knowing that all the successful tests are recorded in an OK file, along with the time stamp of the test, so we may re-run those which were updated since last run. In the event the mailagent or the filter are modified, the tests are re-run throughoutfully. NB: in 2008, I'm glad I did document all that. :-) The file 'level' is optional. If present, it gives the default logging level to be applied when most of the tests are run (i.e. for those who do not require any special logging level). If absent, no logging will be done (except for those tests who do require... etc...). All the tests are performed in the 'out' subdirectory, with the user name set to 'nobody'. That may help a lot when testing commands like RUN, as they have the nasty habbit to mail you, the user, their output when they fail for whatever reason. The generic mail used by the test is an automatic answer I got from the comp.compilers newsgroup moderator the day I posted my first article to that group. It has no special value, appart from having some constants relative to it hardwired within the tests themselves. Don't touch it, even to remove a white space or some tests may fail (particularily GIVE and PIPE, which have the output of 'wc' hardwired). On my machine, here is the output of 'wc mail': 34 227 1620 mail In the event some of the tests do not pass, there is no reason to panic, and it doesn't necesseratily mean the mailagent has a bug. It is more likely a combinaison of perl + dataloading + bugs + memory + moon's position. Try to run the test suite again, and then one more time. It sometimes helps. Also try changing the logging level via 'level' to see if it doesn't make any difference. This is not really rational, but empirical law :-). I think that's all there is to say. mailagent-3.1-74.orig/agent/test/mail0000644000175000017500000000312410473324174015526 0ustar jdgjdgFrom compilers-request@iecc.cambridge.ma.us Sun Jul 12 14:45:54 PDT 1992 Received: from eiffel.eiffel.com by lyon.eiffel.com (5.61/1.34) id AA13012; Thu, 2 Jul 92 22:34:10 -0700 Received: from uunet.UUCP by eiffel.eiffel.com (4.0/SMI-4.0) id AA09695; Thu, 2 Jul 92 22:31:36 PDT Received: from ursa-major.spdcc.com by relay2.UU.NET with SMTP (5.61/UUNET-internet-primary) id AA21794; Fri, 3 Jul 92 01:17:38 -0400 Received: by ursa-major.spdcc.com with sendmail-5.65/4.7 id ; Fri, 3 Jul 92 01:17:34 -0400 Received: by iecc.cambridge.ma.us (smail2.5+) id AA04311; 3 Jul 92 00:43:22 EDT (Fri) To: ram@eiffel.com From: compilers-request@iecc.cambridge.ma.us Subject: Re: melting ice technology? Date: 3 Jul 92 00:43:22 EDT (Fri) Message-Id: <9207030043.AA04311@iecc.cambridge.ma.us> Your message to the moderated usenet group comp.compilers has been received. Within a few days, it should either be posted to usenet or, if for some reason it's not suitable for posting, returned to you. When you send a message to comp.compilers, I understand that to mean that you want me to post it to usenet, which means it will be sent to tens of thousands of potential readers at thousands of computers all around the world. It may also appear in a printed comp.compilers annual and other books, in the ACM SIGPLAN Notices and other magazines, in on-line and off-line archives, CD-ROMs, and anywhere else that some reader decides to use it. If you don't want me to post something, please send it instead to compilers-request@iecc.cambridge.ma.us. Regards, John Levine, comp.compilers moderator mailagent-3.1-74.orig/agent/maillist.SH0000755000175000017500000002260111030765550015755 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; *) TOP=..;; esac revision=`awk '/^#define[ ]*REVISION/ {print $3}' < $TOP/revision.h` case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/maillist (with variable substitutions)" $spitshell >maillist <>maillist <<'!NO!SUBS!' $prog_name = $0; # Who I am $prog_name =~ s|^.*/(.*)|$1|; # Keep only base name &read_config; # First, read configuration file (in ~/.mailagent) # take job number and command from environment # (passed by mailagent) $jobnum = $ENV{'jobnum'}; $fullcmd = $ENV{'fullcmd'}; $dest=shift; # Who should the list to be sent to $dest = $ENV{'path'} if $dest eq ''; # If dest was ommitted # A single '-' as first argument stands for return path $dest = $ENV{'path'} if $dest eq '-'; # Silently discard hostile addresses unless (&addr'valid($dest)) { &add_log("FAILED (HOSTILE $dest)") if $loglvl > 1; exit 0; } &read_dist; # Read distributions and descriptions open(INFO, "$cf'proglist") || &fatal("cannot open description file"); @sysinfo = ; close INFO; &read_plsave; # Read patchlevel description file $tmp_mail = "$cf'tmpdir/xml$$"; open(XHEAD, ">$tmp_mail") || &fatal("cannot create $tmp_mail"); print XHEAD "To: $dest Subject: List of available distributions X-Mailer: mailagent [version $mversion-$revision] Here are the different packages available. If you want the whole distribution, send me the following: \@SH maildist $dest system version If you want patches, use: \@SH mailpatch $dest system version LIST where LIST is a list of patches number, separated by spaces, commas, and/or hyphens. Saying 23- means everything from 23 to the end. Detailed instructions can be obtained by: \@SH mailhelp $dest "; foreach $pname (keys %Program) { ($system, $version) = $pname =~ /^([\w-]+)\|([\w\.]+)*$/; $version = '---' if $version eq '0'; $location = $Location{$pname}; &add_log("dealing with $system $version") if $loglvl > 19; $forwarded = ''; # Set to forwarded addresses when .forward found... # Look for highest patchlevel (even if not maintained) $tmp = ""; # Temporary directory created if ($Archived{$pname}) { unless ($PSystem{$pname}) { # Archive not already listed in 'plsave'. Create a new # entry with a modification time of zero. $PSystem{$pname} = 1; $Patch_level{$pname} = -1; # Not a valid patch level $Mtime{$pname} = 0; # Force unpacking of archive } # We need to unarchive the directory only if archive # modification time is newer than the one in patchlist local($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime, $mtime, $ctime,$blksize,$blocks) = stat(&expand($location)); if ($mtime != $Mtime{$pname}) { # Archive was updated $Mtime{$pname} = $mtime; # Update mod time in 'plsave' # Create a temporary directory $tmp = "$cf'tmpdir/dml$$"; mkdir($tmp, 0700) || &fatal("cannot create $tmp"); # Need to unarchive the distribution $location = &unpack($location, $tmp, $Compressed{$pname}); $Patch_level{$pname} = -1; # Force updating } else { &add_log("no changes in $system $version archive") if $loglvl > 15; } } else { # System is not archived $Patch_level{$pname} = -1; # Force computation } if ($Patch_level{$pname} == -1) { # We still don't know wether there is a patchlevel or not... # Go to system directory, and look there. if (!chdir("$location")) { &add_log("ERROR cannot go to $location") if $loglvl; next; } if ($Patch_only{$pname}) { # Only patches available if ($version eq '') { &add_log("ERROR old system $system has no version number") if $loglvl; next; } if (!chdir("bugs-$version")) { &add_log("ERROR no bugs-$version dir for $system") if $loglvl; next; } local($maxnum); # There is no patchlevel to look at -- compute by hand. for ($maxnum = 1; ; $maxnum++) { last unless -f "patch$maxnum" || -f "patch$maxnum.Z"; } $maxnum--; # We've gone too far $Patch_level{$pname} = $maxnum; } elsif (! -f 'patchlevel.h') { &add_log("no patchlevel.h for $system $version") if $loglvl > 17; } elsif (!open(PATCHLEVEL, "patchlevel.h")) { &add_log("cannot open patchlevel.h for $system $version") if $loglvl > 5; } else { while () { if (/.*PATCHLEVEL[ \t]*([\w-]+)/) { # May have letters $Patch_level{$pname} = $1; last; } } close PATCHLEVEL; if ($Patch_level{$pname} == -1) { &add_log("malformed patchlevel.h for $system $version") if $loglvl > 5; } } } if ($Patch_level{$pname} >= 0) { &add_log("patchlevel is #$Patch_level{$pname} for $system $version") if $loglvl > 18; } else { $Patch_level{$pname} = -2; # Signals: no patchlevel &add_log("no patchlevel for $system $version") if $loglvl > 18; } # If a .forward file is present, maintenance activity is now remotely # handled, and all command mails like mailpath and maildist will be # forwarded according to that file. if (-f '.forward') { $forwarded = join(", ", &forward_list); } &clean_dir; # Remove tmp directory, if necessary # Now look for a description of the package... $describe = ""; $found = 0; foreach (@sysinfo) { next if /^\s*#/; # Skip comments next if /^\s*$/; # Skip blank lines next if /^\*\s+$system/ && ($found = 1); last if $found && /^---|^\*/; # Reached end of description $describe .= "X" . $_ if $found; } $* = 1; $describe =~ s/^X/\t/g; # Indent description $* = 0; print XHEAD "System: $system"; print XHEAD " version $version" if $version !~ /---/; print XHEAD "\nStatus: "; print XHEAD $Maintained{$pname} ? "maintained" : "not maintained"; print XHEAD " (patches only)" if $Patch_only{$pname}; print XHEAD " (official patches available)" if $Patches{$pname}; print XHEAD "\n"; if ($forwarded) { print XHEAD $Maintained{$pname} ? "Maintained-by: " : "Contact: "; print XHEAD "$forwarded\n"; } if ($Maintained{$pname}) { if ($Patch_level{$pname} > 0) { print XHEAD "Highest patch: #$Patch_level{$pname}\n"; } else { print XHEAD "No patches yet\n"; } } else { print XHEAD "Patch level: #$Patch_level{$pname}\n" if $Patch_level{$pname} > 0; } print XHEAD "\n"; print XHEAD "$describe\n" if $describe ne ''; print XHEAD "\n"; } print XHEAD "-- $prog_name speaking for $cf'user\n"; close XHEAD; open(XHEAD, "$tmp_mail") || &fatal("cannot open mail file"); open(MAILER, "|$cf'sendmail $cf'mailopt $dest") || &nofork; while () { print MAILER; } close MAILER; if ($?) { &add_log("ERROR couldn't send list to $dest") if $loglvl > 0; } else { &add_log("SENT list to $dest") if $loglvl > 2; } close XHEAD; &write_plsave; # Write new patchlist file &clean_tmp; # Remove temporary dirs/files exit 0; # All OK sub clean_dir { chdir $cf'home; # Leave [to be removed directory] first if ($tmp ne '') { system '/bin/rm', '-rf', $tmp if -d "$tmp"; &add_log("directory $tmp removed") if $loglvl > 19; $tmp = ""; } } sub clean_tmp { &clean_dir; unlink "$tmp_mail" if -f "$tmp_mail"; } # Report error while forking a sendmail process sub nofork { &add_log("SYSERR fork: $!") if $loglvl; &add_log("ERROR cannot launch $cf'sendmail") if $loglvl; } !NO!SUBS! $grep -v '^;#' pl/fatal.pl >>maillist $grep -v '^;#' pl/acs_rqst.pl >>maillist $grep -v '^;#' pl/free_file.pl >>maillist $grep -v '^;#' pl/add_log.pl >>maillist $grep -v '^;#' pl/read_conf.pl >>maillist $grep -v '^;#' pl/unpack.pl >>maillist $grep -v '^;#' pl/distribs.pl >>maillist $grep -v '^;#' pl/checklock.pl >>maillist $grep -v '^;#' pl/plsave.pl >>maillist $grep -v '^;#' pl/secure.pl >>maillist $grep -v '^;#' pl/cdir.pl >>maillist $grep -v '^;#' pl/hostname.pl >>maillist $grep -v '^;#' pl/addr.pl >>maillist $grep -v '^;#' pl/forward.pl >>maillist chmod 755 maillist $eunicefix maillist mailagent-3.1-74.orig/agent/maildist.SH0000755000175000017500000002723411030765550015754 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; *) TOP=..;; esac revision=`awk '/^#define[ ]*REVISION/ {print $3}' < $TOP/revision.h` case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/maildist (with variable substitutions)" $spitshell >maildist <>maildist <<'!NO!SUBS!' $prog_name = $0; # Who I am $prog_name =~ s|^.*/(.*)|$1|; # Keep only base name &read_config; # First, read configuration file (in ~/.mailagent) # take job number and command from environment # (passed by mailagent) $jobnum = $ENV{'jobnum'}; $fullcmd = $ENV{'fullcmd'}; $pack = $ENV{'pack'}; $path = $ENV{'path'}; &read_dist; # Read distributions $dest = shift; # Who should the system be sent to $system = shift; # Which system $version = shift; # Which version it is # A single '-' as first argument stands for return path $dest = $path if $dest eq '-'; # A single '-' for version means "highest available" version $version = $Version{$system} if $version eq '-' || $version eq ''; # Full program's name for H table access $pname = $system . "|" . $version; $maillist = "To obtain a list of what is available, send me the following mail: Subject: Command \@SH maillist $path ^ note the l"; # Silently discard hostile addresses unless (&addr'valid($dest)) { &add_log("FAILED (HOSTILE $dest)") if $loglvl > 1; exit 0; } if (!$System{$system}) { open(MAILER, "|$cf'sendmail $cf'mailopt $path $cf'email") || &nofork; print MAILER "To: $path Subject: No program called $system X-Mailer: mailagent [version $mversion-$revision] I don't know how to send a program called \"$system\". Sorry. $maillist If $cf'name can figure out what you meant, you'll get the program anyway. -- $prog_name speaking for $cf'user "; close MAILER; if ($?) { &add_log("ERROR cannot report system $system is unknown") if $loglvl; } else { &add_log("MSG system $system is unknown") if $loglvl > 6; } &add_log("FAILED (UNKNOWN SYSTEM)") if $loglvl > 1; exit 0; } if (!$Program{$pname}) { open(MAILER, "|$cf'sendmail $cf'mailopt $path $cf'email") || &nofork; print MAILER "To: $path Subject: No version $version for $system X-Mailer: mailagent [version $mversion-$revision] I don't know how to send version $version of $system. Sorry. $maillist If $cf'name can figure out what you meant, you'll get the program anyway. -- $prog_name speaking for $cf'user "; close MAILER; if ($?) { &add_log("ERROR cannot report system $system $version is unknown") if $loglvl; } else { &add_log("MSG system $system version $version is unknown") if $loglvl > 6; } &add_log("FAILED (BAD VERSION NUMBER)") if $loglvl > 1; exit 0; } # Has the user made a request for an old version (patch only) ? if ($Patch_only{$pname}) { # It is required that patch only systems have a version number &abort("old system has no version number") if $version eq ''; open(MAILER, "|$cf'sendmail $cf'mailopt $path $cf'email") || &nofork; print MAILER "To: $path Subject: System $system $version is obsolete X-Mailer: mailagent [version $mversion-$revision] I can't send you version $version of $system. Sorry. This version appears to be an old one, and only patches are available. The up-to-date version for $system is $Version{$system}. $maillist If $cf'name can figure out what you meant, he may send you the latest version. -- $prog_name speaking for $cf'user "; close MAILER; if ($?) { &add_log("ERROR cannot report system $system $version is obsolete") if $loglvl; } else { &add_log("MSG system $system $version is obsolete") if $loglvl > 6; } &add_log("FAILED (PATCH ONLY VERSION)") if $loglvl > 1; exit 0; } # If the request is not the most recent version, warn the user. if ($version < $Version{$system}) { open(MAILER, "|$cf'sendmail $cf'mailopt $path $cf'email") || &nofork; print MAILER "To: $path Subject: Version $version of $system is an old one X-Mailer: mailagent [version $mversion-$revision] You asked for version $version of $system. This version appears to be an old one, but it is sill available, and I am currently processing your request. However, I wanted to let you know that the up-to-date version for $system is $Version{$system}. $maillist Unless you receive an error message telling you otherwise, I am sending you version $version of $system. You may also request for the new version right now if you wish. -- $prog_name speaking for $cf'user "; close MAILER; if ($?) { &add_log("ERROR cannot report $system $version is old") if $loglvl; } else { &add_log("MSG system $system $version is old") if $loglvl > 6; } } # Create a temporary directory $tmp = "$cf'tmpdir/dmd$$"; mkdir($tmp, 0700); # Need to unarchive the distribution if ($Archived{$pname}) { # Create a temporary directory for distribution $tmp_loc = "$cf'tmpdir/dmdl$$"; mkdir($tmp_loc, 0700); $location = &unpack($Location{$pname}, $tmp_loc, $Compressed{$pname}); } else { $location = $Location{$pname}; } # Go to the package root directory and check for possible forwarding... chdir($location) || &abort("cannot chdir to $location: $!"); &check_forward; # Returns only if command is not forwarded # We are now in the place. Look for a MANIFEST file. If none, we will # send *everything* held, RCS sub-directories and executable/object files # excepted. $manifest = ''; $tmp_list = ''; if (-f 'MANIFEST') { $manifest = "$location/MANIFEST"; } else { $tmp_list = "$cf'tmpdir/mdlist$$"; open(FIND, "find . -type f -print | sort |") || &abort("cannot run find"); open(LIST, ">$tmp_list") || &abort("cannot create $tmp_list"); while () { chop; s|\./||; next if (m|^U/| && -f '.package'); # Skip units if meta-configured next if m|^RCS/|; # Skip RCS files next if m|/RCS/|; next if m|,v$|; next if m|bugs/|; # Skip bugs files (patches and al.) next if m|^\.#|; # Skip [marked for deletion] files next if m|/\.#|; next if m|\.o$|; # Skip object files next if m|core$|; # Skip core files next if (-x $_ && -B $_); # Skip binaries print LIST $_,"\n"; # Keep that file } close FIND; close LIST; $manifest = $tmp_list; } &add_log("manifest is in $manifest") if $loglvl > 19; # If distribution is maintained by dist 3.0 (at least), there is a .package # file in there and we can invoke makedist. Otherwise, we have to do it by # hand... if (-f '.package') { system "makedist -c $tmp -f $manifest"; &abort("cannot run makedist -c $tmp") if $?; } else { &makedist; } $subject = "$system"; $subject .= " $version" if $version ne '0'; $subject .= " package"; &sendfile($dest, $tmp, $pack, $subject); &clean_tmp; exit 0; # Ok # Now for each file in manifest, look if there is an # RCS file associated with it. If so, check out either # the 'lastpat' version or the highest version on the # default branch, provided that the file does not exists # in checked-out form. Otherwise, only run co if 'lastpat' # is defined. sub makedist { chdir $tmp || &abort("cannot chdir to $tmp"); open(MANI, $manifest) || &abort("cannot open $manifest"); while () { next if /^--/; s|^\s*||; # Remove leading spaces ($file,$foo) = split; # Save filename, discard comments next if (-d "$location/$file"); # Skip directories next if ($file =~ /^\s*$/); # Skip blank lines # Extract dirname and basename ($dir, $base) = ('', $file) unless ($dir, $base) = ($file =~ m|(.*/)(.*)|); $logmsg = ''; # String to add to log message $rcsfile = 'blurfl'; $rcsfile = "$location/$file,v" if (-f "$location/$file,v"); $rcsfile = "$location/${dir}RCS/$base,v" if (-f "$location/${dir}RCS/$base,v"); next unless -f "$location/$file" || -f "$rcsfile"; # Skip unexisting files &makedir($dir) unless $dir eq ''; open(COPY, ">$file") || &abort("cannot create $file"); if ($rcsfile ne '') { $rlog = `rlog $rcsfile 2>&1`; ($revs) = ($rlog =~ /lastpat: (\d+)/); if (!$revs) { # Symbol 'lastpat' is not defined # If file exists, open it. Otherwise, run co if (-f "$location/$file") { $logmsg = " (lastpat undefined)"; $origfile = "$location/$file"; open(FILE, $origfile) || &abort("cannot open $origfile"); } else { $logmsg = " (co but no lastpat)"; $origfile = $rcsfile; open(FILE, "co -q -p $rcsfile |") || &abort("cannot run co on $rcsfile"); } } else { # Symbol 'lastpat' is defined $logmsg = " (co lastpat)"; $origfile = $rcsfile; open(FILE, "co -q -p -rlastpat $rcsfile |") || &abort("cannot run co on $rcsfile"); } } else { $origfile = "$location/$file"; open(FILE, "$location/$file") || &abort("cannot open $location/$file"); } while () { # Use Lock[e]r, not Locker, since we might apply this on # ourself one day and get corrupted... s|Lock[e]r:.*\$|\$|; # Remove locker mark (print COPY) || &abort("copy error: $!"); } close(FILE) || &abort("copy error: $!"); close COPY; &add_log("copied $file$logmsg") if $loglvl > 19; # If file is executable, change its permissions if (-x $origfile) { chmod 0755, $file; } else { chmod 0644, $file; } } } sub clean_tmp { # Do not stay in the directories we are removing... chdir $cf'home; if ($tmp ne '') { system '/bin/rm', '-rf', $tmp; &add_log("removed dir $tmp") if $loglvl > 19; } if ($Archived{$pname}) { system '/bin/rm', '-rf', $tmp_loc; &add_log("removed dir $tmp_loc") if $loglvl > 19; } unlink $tmp_list if $tmp_list ne ''; } # Emergency exit with clean-up sub abort { local($reason) = shift(@_); # Why we are exiting &clean_tmp; &fatal($reason); } # Report error while forking a sendmail process sub nofork { &add_log("SYSERR fork: $!") if $loglvl; &add_log("ERROR cannot launch $cf'sendmail") if $loglvl; } !NO!SUBS! $grep -v '^;#' pl/makedir.pl >>maildist $grep -v '^;#' pl/fatal.pl >>maildist $grep -v '^;#' pl/add_log.pl >>maildist $grep -v '^;#' pl/read_conf.pl >>maildist $grep -v '^;#' pl/unpack.pl >>maildist $grep -v '^;#' pl/sendfile.pl >>maildist $grep -v '^;#' pl/distribs.pl >>maildist $grep -v '^;#' pl/secure.pl >>maildist $grep -v '^;#' pl/cdir.pl >>maildist $grep -v '^;#' pl/addr.pl >>maildist $grep -v '^;#' pl/forward.pl >>maildist chmod 755 maildist $eunicefix maildist mailagent-3.1-74.orig/agent/files/0000755000175000017500000000000011675050334015003 5ustar jdgjdgmailagent-3.1-74.orig/agent/files/Jmakefile0000644000175000017500000000214610473324174016621 0ustar jdgjdg/* * Jmakefile for mailagent's files */ ;# $Id: Jmakefile,v 3.0.1.2 1995/09/15 13:36:23 ram Exp ram $ ;# ;# Copyright (c) 1990-2006, Raphael Manfredi ;# ;# You may redistribute only under the terms of the Artistic License, ;# as specified in the README file that comes with the distribution. ;# You may reuse parts of this distribution only within the terms of ;# that same Artistic License; a copy of which may be found at the root ;# of the source tree for mailagent 3.0. ;# ;# $Log: Jmakefile,v $ ;# Revision 3.0.1.2 1995/09/15 13:36:23 ram ;# patch43: new compressors file installed in the private library ;# ;# Revision 3.0.1.1 1995/02/16 14:06:56 ram ;# patch32: added new file setup.cf for initial configuration setup ;# ;# Revision 3.0 1993/11/29 13:47:46 ram ;# Baseline for mailagent 3.0 netwide release. ;# FILES = agenthelp commands distribs filter.sh mailagent.cf proglist \ chkagent.sh setup.cf compressors >PRIVLIB /* Force metaconfig to ask for privlib location */ all:: MakeInstallDirectories($(PRIVLIB)) InstallMultipleDestFlags(install,$(FILES),$(PRIVLIB),-m 444) SetSubdirs(help) mailagent-3.1-74.orig/agent/files/commands0000644000175000017500000000005510473324174016530 0ustar jdgjdgmailpatch mailhelp maillist maildist package mailagent-3.1-74.orig/agent/files/setup.cf0000644000175000017500000000635710473324174016471 0ustar jdgjdg# # Setup file for mailagent # # $Id: setup.cf,v 3.0.1.5 2001/03/17 18:04:04 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: setup.cf,v $ # Revision 3.0.1.5 2001/03/17 18:04:04 ram # patch72: added two variables: domain and hidenet # # Revision 3.0.1.4 1998/07/28 16:56:55 ram # patch62: added setup information for the "hash" config variable # # Revision 3.0.1.3 1996/12/24 13:49:42 ram # patch45: can now say that a file is expected under some directory # patch45: applied that to mailbox, which is a file expected under maildrop # # Revision 3.0.1.2 1995/09/15 13:40:37 ram # patch43: maildrop now defaults to the configured value at first install # patch43: new compspecs optional file in configuration # # Revision 3.0.1.1 1995/02/16 14:26:30 ram # patch32: created # # Perl expressions for computing default values to some parameters when # initializing ~/.mailagent from the mailagent.cf template. # Expressions will be evaluated from within the cfset package. home : &main'tilda_expand('~') path : &default_path user : (getpwuid($<))[0] name : $main'ENV{'NAME'} || (getpwuid($<))[6] email : &main'email_addr domain : &main'domain_addr hidenet : $main'hiddennet eq '' ? OFF : ON sendmail : $main'mailer sendnews : $main'inews mailopt : $main'mailer =~ /\bsendmail$/ ? '-odq' : '' maildrop : $main'maildir timezone : $main'ENV{'TZ'} || 'MET' # Types of various configuration parameters. A lowercase f/d indicates an # optional file/directory, or one that will be created on demand. An uppercase # F/D means a mandatory file/directory that should exist. # # It is possible to further specify an underlying directory for the file # or directory by following the type with a value between parenthesis, as in: # # mailbox = f ($maildrop) # # to say for instance that the mailbox setting in the config file really # indicates a file lying under the maildrop setting. A variable name is # interpreted in the cf package, NOT in the cfset, since it is assummed to # be a configuration variable. It can be fully qualified if it is not. # It is also possible to put a plain string here, since the value will # be interpolated in "" context. # # By default, files are anchored under the home directory unless they start # with a /. # # When using 'mailagent -I', a mandatory directory will be created, while a # mandatory file will be copied from a template lying in the privlib directory # when specified; otherwise, it is created with a null size. spool = D queue = D logdir = D hash = D ($spool) context = f callout = f log = f seq = f statfile = f rules = f rulecache = f maildrop = d mailbox = f ($maildrop) compress = f compspecs = f biffmsg = f mhprofile = f newcmd = f comserver = F servdir = d powers = d powerlog = f powerlist = f powerdir = d passwd = f helpdir = d comfile = F commands distlist = F proglist = F plsave = f mailagent-3.1-74.orig/agent/files/filter.sh0000755000175000017500000002154211017736360016633 0ustar jdgjdg#!/bin/sh # $Id: filter.sh,v 3.0.1.4 1999/01/13 18:03:19 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: filter.sh,v $ # Revision 3.0.1.4 1999/01/13 18:03:19 ram # patch64: agent.wait is now stored in the spool rather than in queue # # Revision 3.0.1.3 1995/08/07 16:06:52 ram # patch37: avoid forking of a new mailagent if one is sitting in background # # Revision 3.0.1.2 1994/10/29 17:39:23 ram # patch20: made it behave more like the C filter # # Revision 3.0.1.1 1994/09/22 13:41:43 ram # patch12: filter.sh now honours queuewait when defined # # Revision 3.0 1993/11/29 13:47:51 ram # Baseline for mailagent 3.0 netwide release. # # You'll have to delete comments by yourself if your shell doesn't grok them # You should install a .forward in your home directory to activate the # process (sendmail must be used as a MTA). Mine looks like this: # "|exec /users/ram/mail/filter >>/users/ram/.bak 2>&1" # Variable HOME *must* correctly be set to your home directory # This should compute it correctly, if not, hardwire it user=`(logname || whoami) 2>/dev/null` HOME=`grep ^$user: /etc/passwd | cut -d':' -f 6` export HOME # The PATH variable must also correctly be set. This variable will be # used by all the mailagent-related programs. If you have chosen to put # the mailagent scripts in a dedicated directory (e.g. $HOME/mailagent), # be sure to put that directory in the PATH variable. # The mailagent scripts could also have been stored in a directory like # /usr/local/scripts by your system administrator, because each user does # not need to have a private copy of theese scrips. PATH="/bin:/usr/bin:/usr/ucb:$HOME/bin/mailagent:$HOME/bin" # The following will set the right path for some architecture-specific # directories. For instance, if you have your home directory viewed on # some different machines (e.g. it is NFS-mounted), then you must be # sure the mailagent will be invoked with the right executables. HOST=`(uname -n || hostname) 2>/dev/null` case "$HOST" in york) PATH="$HOME/bin/rs2030:$PATH" ;; eiffel) PATH="/base/common/sun4/bin:$PATH" ;; *) ;; esac export PATH # The TZ may not correctly be set when sendmail is invoking the filter, hence # funny date could appear in the log message (from GMT zone usually). TZ='PST8PDT' export TZ ##### You should not have to edit below this line ##### # This variable, when eval'ed, adds a log message at the end of the log file # if any. Assumes the ~/.mailagent file was successfully parsed. addlog='umask 077; if test -f $logdir/$log; then /bin/echo "`date \"+%y/%m/%d %H:%M:%S\"` filter[$$]: $1" >> $logdir/$log; else echo "`date \"+%y/%m/%d %H:%M:%S\"` filter[$$]: $1"; fi; umask 277 ' # This variable, when eval'ed, dumps the message on stdout. For this # reason, error messages should be redirected into a file. emergency='echo "*** Could not process the following ($1) ***"; cat $temp; echo "----------- `date` -----------"; set "FATAL $1"; eval $addlog; rm -f $spool/filter.lock $torm ' # This is for safety reasons (mailagent may abort suddenly). Save the # whole mail in a temporary file, which has very restrictive permissions # (prevents unwanted removal). This will be eventually moved to the # mailagent's queue if we can locate it. umask 277 temp=/tmp/Fml$$ torm="$temp" # The magic number '74' is EX_IOERR as understood by sendmail and means that # an I/O error occurred. The mail is left in sendmail's queue. I expect "cat" # to give a meaningful exit code. cat > $temp || exit 74 # The following is done in a subshell put in background, so that this # process can exit with a zero status immediately, which will make # sendmail think that the delivery was successful. Hopefully we can # do our own error recovery now. ( # Script used to save the processed mail in an emergency situation saver='umask 077; if (cat $temp; echo ""; echo "") >> $HOME/mbox.filter; then set "DUMPED in ~/mbox.filter"; eval $addlog; rm -f $torm; else set "unable to dump in ~/mbox.filter"; eval $emergency; fi' # Set a trap in case of interruption. Mail will be dumped in ~/mbox.filter trap 'eval $saver; exit 0' 1 2 3 15 # Look for the ~/.mailagent file, exit if none found if test ! -f $HOME/.mailagent; then set 'FATAL no ~/.mailagent' eval $addlog eval $saver exit 0 fi # Parse ~/.mailagent to get the queue location set X `<$HOME/.mailagent sed -n \ -e '/^[ ]*#/d' \ -e 's/[ ]*#/#/' \ -e 's/^[ ]*\([^ :\/]*\)[ ]*:[ ]*\([^#]*\).*/\1="\2";/p'` shift # Deal with possible white spaces in variables cmd='' for line in $*; do cmd="$cmd$line" done cmd=`echo $cmd | sed -e "s|~|$HOME|g"` eval $cmd # It would be too hazardous to continue without a valid queue directory if test ! -d "$queue"; then set 'FATAL no valid queue directory' eval $addlog eval $saver exit 0 fi # If there is already a filter.lock file, then we set busy to true. Otherwise, # we create the lock file. Note that this scheme is a little lousy (race # conditions may occur), but that's not really important because the mailagent # will do its own tests with the perl.lock file.The motivation here is to avoid # a myriad of filter+perl processes spawned when a lot of mail is delivered # via SMTP (for instance after a uucp connection). # # There is also a chance there be a perl.lock file (indicating mailagent is # processing messages or waiting in the background for a new batch) but no # filter.lock (because the main filter has exited a while ago). That's likely # to happen when mailagent processes maildist commands, and is the reason why # we also test for perl.lock below. busy='' if test -f $spool/filter.lock; then busy='true' elif test -f $spool/perl.lock; then set "NOTICE mailagent seems to be active in background" eval $addlog busy='true' else # Race condition may (and will) occur, but the permissions are kept by 'cp', # so the following will not raise any error message. cp /dev/null $spool/filter.lock >/dev/null 2>&1 || busy='true' fi # Copy tmp file to the queue directory and call the mailagent. If the file # already exists (very unlikely, but...), we append a 'b' for bis. When busy, # create a 'fm' mail message instead, to allow mailagent to process it as soon # as possible, mailagent being the one spawned by the main filter. case "$busy" in true) bq=fm;; *) bq=qm;; esac qbase=${bq}$$ while test -f "$queue/$qbase"; do # Race condition still possible since file is not created yet qbase=${qbase}b done qtemp=$queue/$qbase tqtemp=$queue/T$qbase # Set a proper waiting time. If queuewait is not defined in the config file, # let it default to 60 seconds. test "$queuewait" || queuewait=60 # Do not write in a queue file directly, or the mailagent might start # its processing on an incomplete file. if cp $temp $tqtemp; then mv $tqtemp $qtemp base=`echo $qtemp | sed -e 's/.*\/\(.*\)/\1/'` size=`perl -e 'print 0 + -s("'$qtemp'"), "\n";'` set "QUEUED [$base] $size bytes" eval $addlog if test x = "x$busy"; then sleep $queuewait if perl -S mailagent $qtemp; then rm -f $temp $qtemp $spool/filter.lock exit 0 fi else # Mail queued in a 'fm' file, will be processed by the main mailagent # invoked by the filter process which got its lock... rm -f $temp exit 0 fi else set 'ERROR unable to queue mail before processing' eval $addlog if test x = "x$busy"; then sleep $queuewait if perl -S mailagent $temp; then rm -f $temp $spool/filter.lock exit 0 fi fi fi # We come here only if the mailagent failed its processing. The unprocessed # mail either left in the queue or is given a meaningful name. # Mail was queued correctly, leave it there if cmp $temp $qtemp >/dev/null 2>&1; then rm -f $temp $spool/filter.lock set "ERROR mailagent failed, [$base] left in queue" eval $addlog exit 0 fi # Change the name of the temporary file. tmpdir=`echo $temp | sed -e 's/\(.*\)\/.*/\1/'` mv $temp $tmpdir/$user.$$ temp="$tmpdir/$user.$$" if test x = "x$busy"; then set "ERROR mailagent failed, mail left in $temp" rm -f $spool/filter.lock else set "WARNING filter busy, mail left in $temp" fi eval $addlog # Give the mailagent a clue as to where the mail has been stored. As this # should be very very unlikely, no test is done to see whether a mailagent # is already updating the agent.wait file. The worse that could result from # this shallowness would be having an unprocessed mail. umask 077 set "WARNING mailagent ignores mail was left in $temp" if /bin/echo "$temp" >> $spool/agent.wait; then if grep "$temp" $spool/agent.wait >/dev/null 2>&1; then set "NOTICE $temp memorized into agent.wait" fi fi eval $addlog rm -f $qtemp # Attempt an emergency saving eval $saver exit 0 ) & # Delivery was ok -- for sendmail exit 0 mailagent-3.1-74.orig/agent/files/proglist0000644000175000017500000000401410473324174016571 0ustar jdgjdg# Small descriptions for programs * cshar The useful shell-archive maker. I modified the original slightly to add a Configure script. --- * kit A simple binary tarmailer. This is used by the mail agent when mailing big sets of files. You presently need cshar (from Rich Salz) to use kit. --- * dist Larry Wall's dist package, modified. It contains: - metaconfig, a Configure script generator - a patch generator - a distribution maker It comes from version Larry's dist 2.0 PL 2 package, but has quite a few extensions (I worked especially on the patch generating tools and metaconfig itself). The units used by metaconfig have been manually ripped off from some recently posted Configure scripts (elm 2.3, perl 3.0). --- * matrix An object-oriented matrix library. It is a beta-test release. --- * file The file(1) command with lots of /etc/magic entries. Useful when you work with NFS on different architectures as you can have your own magic file. --- * rcs GNU Revision Control System. You need RCS to use Larry's dist package (patch generating tools). --- * cops Security analysis tools. May be useful to find holes in your system. --- * xfmt Simple text formatter. You need flex to compile it. It looks like SUN-OS fmt program. --- * less The pager that is more than more(1). --- * flex Fast lex. Needed for the xfmt package, because lex is not powerful enough. --- * et Error table compiler (from MIT). --- * undel Replacement for rm(1). Marks files for deletion instead of removing them. You need the et package for version 2.0 to compile. --- * dither Displays a color image on a two-level display (White and black). Uses a non-standard picture format in input and output (that's mine ! :-)). --- * perl Larry Wall's Practical Extraction and Report Language. It combines the best features of C, awk, sed and sh. You need it to use the dist package. --- * patch The useful utility to apply diff files on a distribution. You could of course apply them by hand, but it may well be a long procedure ! Written by Larry Wall. --- mailagent-3.1-74.orig/agent/files/chkagent.sh0000755000175000017500000000577411444401133017132 0ustar jdgjdg#!/bin/sh # # $Id: chkagent.sh,v 3.0.1.3 1999/07/12 13:42:39 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: chkagent.sh,v $ # Revision 3.0.1.3 1999/07/12 13:42:39 ram # patch66: added the UNLOCKED pattern # # Revision 3.0.1.2 1994/10/10 10:21:35 ram # patch19: now honors config variables email and sendmail # # Revision 3.0.1.1 1994/04/25 15:10:32 ram # patch7: also extract system error messages from logfile # # Revision 3.0 1993/11/29 13:47:49 ram # Baseline for mailagent 3.0 netwide release. # # Make sure the mailagent is working well lookat='ERROR|FAILED|UNLOCKED|FATAL|DUMPED|SYSERR' trap "rm -f $report $output $todaylog $msg" 1 2 3 15 # Interpret the ~/.mailagent configuration file set X `<$HOME/.mailagent sed -n \ -e '/^[ ]*#/d' \ -e 's/[ ]*#/#/' \ -e 's/^[ ]*\([^ :\/]*\)[ ]*:[ ]*\([^#]*\).*/\1="\2";/p'` shift # Deal with possible white spaces in variables and ~ substitution cmd='' for line in $*; do cmd="$cmd$line" done cmd=`echo $cmd | sed -e "s|~|$HOME|g"` eval $cmd # Compute location of report file and log file report="/tmp/cAg$$" output="/tmp/cAo$$" logfile="$logdir/$log" todaylog="/tmp/tAg$$" # Current date format to look for in logfile today=`date "+%y/%m/%d"` if test -f "$logfile"; then grep "$today" $logfile > $todaylog egrep "]: ($lookat)" $todaylog > $output if test -s "$output"; then echo "*** Errors from logfile ($logfile):" > $report echo " " >> $report cat $output >> $report fi rm -f $todaylog $output else echo "Cannot find $logfile" > $report fi # Determine where they redirect the output from .forward fw=$HOME/.forward if test -f $fw; then errors=`perl -ne 's/^"(.*)"$/$1/; /(-o|>>)\s*(\S+)/ && print "$2\n"' $fw` fi case "$errors" in '') errors=/dev/null ;; esac if test -s $errors; then echo " " >> $report echo "*** Errors from $errors:" >> $report echo " " >> $report cat $errors >> $report cp /dev/null $errors fi # Look for mails in the emergency directory ls -C $emergdir > $output if test -s "$output"; then echo " " >> $report echo "*** Mails held in lost+mail ($emergdir):" >> $report echo " " >> $report cat $output >> $report fi rm -f $output # Spot any unprocessed mails in the queue cd $queue ls -C qm* fm* > $output 2>/dev/null if test -s "$output"; then echo " " >> $report echo "*** Unprocessed mails in queue ($queue):" >> $report echo " " >> $report cat $output >> $report fi rm -f $output if test -s "$report"; then msg="/tmp/mAg$$" test "$email" || email=$user test "$sendmail" || sendmail=/usr/lib/sendmail cat >$msg <>$msg rm -f $report $sendmail $mailopt $email <$msg rm -f $msg else rm -f $report fi exit 0 mailagent-3.1-74.orig/agent/files/passwd0000644000175000017500000000063110473324174016230 0ustar jdgjdgroot:*: Super user, may do almost anything security:*: Security password for critical requests system:: May add/delete powers, edit config files mail:: To work on mail messages in folders (from maildir) list:: May perform administration on mailing lists shell:*: Shell clearance needed to execute shell commands file:*: File clearance needed to retrieve arbitrary files mailagent-3.1-74.orig/agent/files/compressors0000644000175000017500000000255611017736617017322 0ustar jdgjdg# $Id: compressors,v 3.0.1.1 1995/09/15 13:38:00 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: compressors,v $ # Revision 3.0.1.1 1995/09/15 13:38:00 ram # patch43: created # # # This table list all the compressors and their associated decompressors # that may be used by mailagent to. They are referenced by their tag name # which is the first word on each line. # # Extensions listed should be unique amongst the file, since they are # used to determine how a compressed folder was generated. Folders # whose compression type is derived that way are re-compressed using # the same tagged compressor. # # You may add or change any compressor definition within this file to suit # your local needs. # # This file is formatted with tabstops set to 4 characters. Items in the row # must be separated with TABS, to allow spaces within command strings. # Tag Ext Compress Uncompress Cat compress .Z compress uncompress zcat pack .z pack unpack pcat gzip .gz gzip -9 gunzip gunzip -c bzip2 .bz2 bzip2 bunzip2 bzcat mailagent-3.1-74.orig/agent/files/agenthelp0000644000175000017500000001440210473324174016677 0ustar jdgjdgThe purpose of the mail agent is to enable me answer some of your requests, even if it's early in the morning and I've just gone to bed ! :-) For instance, you need Larry Wall's patch program or Rich Salz's cshar. I have them and I use them in my own kits. So you may ask me to send them to you. Of course, you could send me a mail saying "Please, could you send me the cshar distribution kit ?", but I certainly won't be able to do it at once , either because I am not there when the mail arrives, or because someone else asked before you... With the mail agent, there are no problems. You simply (!) send me a mail of the following form: Subject: Command @SH maildist =DEST= cshar 3.0 and you will get version 3.0 of cshar. Here are the possible commands: - mailhelp PATH # sends some help - maillist PATH # sends a list of what is available - mailpatch PATH SYSTEM VERSION LIST # sends patches for a system - maildist PATH SYSTEM VERSION # sends a whole distribution kit (latest patchlevel) where PATH is a return path FROM ME TO YOU either in Internet notation or in bang notation from some well-known host. As far as you are concerned, it appears to be =DEST=. PATH may be omitted for mailhelp and maillist, in which case the return address found in the mail header will be used. SYSTEM is the system's name and VERSION is the version number. For systems that are not maintained, the version number has no sense and thus may be omitted (for maildist). A '-' stands for the latest version. The LIST for mailpatch is the number of one or more patches you need, separated by spaces, commas, and/or hyphens. For instance: 2,3 4-7,10- asks for patches 2 and 3, then 4 to 7, and from 10 to the end, while -5 10 11 requests patches up to 5, then 10 and 11. Commands must be preceded by the token "@SH" at the beginning of a line. Do not put spaces/tabs in front of "@SH". In the mail examples I give, I do put one, but it is only for clarity purpose. In the same way, the line "Subject: Command" must be left-justified. Note that the subject of the mail does not need to be "Command", as long as you put the "Subject: Command" line in the body of your message, before your commands. You may use either "Command" or "command". Once the "Subject: Command" line appears in your mail, either in the header or in the body, you may put as many commands as necessary. For example: Subject: Command @SH maillist =DEST= @SH maildist =DEST= cshar 3.0 If you are in doubt of what is the return path, you may put "PATH" or a single '-' instead of your address, and the mail agent will replace it with the return path it finds in the mail header. In case you do not trust your mail headers, you may force the return path with the "@PATH" command. The mail agent reads the whole message before actually processing it, so the location of this command does not really matters. Here is an example: Subject: Command @SH mailhelp @SH mailpatch - kit 2.0 4,5 @PATH =DEST= When you ask for files to be sent, the mail agent makes shell archives or kit archives, depending on the amount of bytes that are to be returned. If it exceeds an arbitrary-fixed limit of =MAXSIZE= bytes, files are sent as kit archives. Otherwise, they will be sent as shell archives provided that no file is greater than the maximum allowed for a single shell archive. This is called the "auto" packing mode. The "@PACK" command forces the distribution mode, which is "auto" by default. The specified packing mode is used, until another "@PACK" command is found. Valid parameters are "auto", "kit" and "shar". Note that forcing mode to "shar" may well result in a failure if one of the files to be sent is bigger than the maximum size allowed for a shell-archive (around 50000 bytes). However, the mail agent does its best: it will split large files and uuencode non-ASCII ones. When you use maildist, please do not request for "shar" mode, as "kit" will be more efficient and safer. Note that when the packing mode is "auto" and the mailagent has to kit the files, a minikit is included. Hence you may unkit the distribution even if you do not have kit. But it will always be simpler with kit anyway. "Kit" is a binary tar-mailer that you must own in order to unkit the kit archives which do not include a 'minikit'. If you do not have it, send me the following mail: Subject: Command @SH maildist =DEST= kit - and you will get the latest release of "kit". Here is another example that uses the "@PACK" request (the following package names, revision numbers and patchlevels are here for the purpose of demonstration only. Reality may -- and often will -- be completely different): Subject: Command -- Set the return path, so that we can use '-' without fear. @PATH =DEST= -- Request patches for kit 2.0, sent in "auto" packing mode. -- Note that the '-' actually stands for the return path. -- We could also have said: -- @SH mailpatch =DEST= kit 2.0 3- -- but as long as we have more than one command in the file, -- it would be cumbersome to repeat the address each time. @SH mailpatch - kit 2.0 3- -- Force packing mode to "shar", as we don't want to kit 'kit'. -- We don't know what the latest version is, so we put a '-'. -- Maildist will send the version at its highest patchlevel. @PACK shar @SH maildist - kit - -- Kit is more reliable and will greatly reduce the amount of -- transmitted data (typical gain is 50% for sources). @PACK kit -- We want version 2.0 for dist and nothing else. @SH maildist - dist 2.0 -- Request all patches for the latest version of matrix @SH mailpatch - matrix - 1- A nice thing with the mail agent is that you can ask for a receipt, in order to be sure that I received your mail. You may do so by placing the "@RR" command at the beginning of any line in the body of your message. A receipt will then be sent to the return path extracted from the header. You may force the receipt to be sent to a given address by giving it after the @RR token. Saying "@RR PATH" or "@RR -" is possible but not very different from a single "@RR" !! Here are valid requests: @RR @RR =DEST= @RR login@cpu.domain.top Note that no "Subject: Command" line is necessary for that, so you may ask for receipts in every mail. If this help file is not clear enough, or if you have suggestions/questions, feel free to ask me. mailagent-3.1-74.orig/agent/files/server0000644000175000017500000000040710473324174016236 0ustar jdgjdg# Commands allowed by the server (file formatted with tabstops=4) # command name # type (shell/perl/end/help) # concealed arguments # collect data # file name # [function name (perl) / options (shell)] end end - - - help help - - - mailagent-3.1-74.orig/agent/files/help/0000755000175000017500000000000011675050334015733 5ustar jdgjdgmailagent-3.1-74.orig/agent/files/help/setauth.SH0000755000175000017500000000305210473324174017650 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/setauth (with variable substitutions)" $spitshell >/dev/null <setauth <<'!NO!SUBS!' NAME setauth -- Replaces current clearance file SYNOPSIS setauth name [password] ... list of users ... EOF DESCRIPTION This command sets the clearance file for the target power. No special power is required when the target power is already detained. Otherwise the 'system' power is needed. As usual, 'root' and 'security' clearances require the corresponding power to be held or the appropriate password. EXAMPLE setauth root root-password ram@acri.fr EOF !NO!SUBS! chmod 644 setauth mailagent-3.1-74.orig/agent/files/help/Jmakefile0000644000175000017500000000167010473324174017552 0ustar jdgjdg/* * Jmakefile for server help files. */ ;# $Id: Jmakefile,v 3.0 1993/11/29 13:47:52 ram Exp ram $ ;# ;# Copyright (c) 1990-2006, Raphael Manfredi ;# ;# You may redistribute only under the terms of the Artistic License, ;# as specified in the README file that comes with the distribution. ;# You may reuse parts of this distribution only within the terms of ;# that same Artistic License; a copy of which may be found at the root ;# of the source tree for mailagent 3.0. ;# ;# $Log: Jmakefile,v $ ;# Revision 3.0 1993/11/29 13:47:52 ram ;# Baseline for mailagent 3.0 netwide release. ;# FILES = addauth approve delpower end getauth help newpower \ passwd password power release remauth set setauth user >PRIVLIB /* Force metaconfig to ask for privlib location */ all:: NoManPages() SimpleShellScriptTarget($(FILES)) MakeInstallDirectories($(PRIVLIB) $(PRIVLIB)/help) InstallMultipleDestFlags(install,$(FILES),$(PRIVLIB)/help,-m 444) mailagent-3.1-74.orig/agent/files/help/getauth.SH0000755000175000017500000000274010473324174017637 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/getauth (with variable substitutions)" $spitshell >/dev/null <getauth <<'!NO!SUBS!' NAME getauth -- Gets power clearance file SYNOPSIS getauth power [password] DESCRIPTION This command requests the power clearance file for the specified power. The power password is optional if the power is already detained or the user has already got the 'system' power. To get the 'root' or 'security' clearances, you need the corresponding power. EXAMPLE getauth list-power mypasswd !NO!SUBS! chmod 644 getauth mailagent-3.1-74.orig/agent/files/help/release.SH0000755000175000017500000000342410473324174017616 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/release (with variable substitutions)" $spitshell >/dev/null <release <<'!NO!SUBS!' NAME release -- Releases power SYNOPSIS release name DESCRIPTION This command releases the specified power. If the 'root' power is released, other powers obtained while root or before are kept. That way, it makes sense to ask for powers while root, when the password for some minor power has been changed, since you do not need to supply it. Then 'root' may be released and the work continued with the minor power handy. It is not recommend to run an entire session with 'root' privileges, unless needed to bypass some restrictions like the maximum number of commands that may be issued in a session. EXAMPLE release list !NO!SUBS! chmod 644 release mailagent-3.1-74.orig/agent/files/help/newpower.SH0000755000175000017500000000354710473324174020052 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/newpower (with variable substitutions)" $spitshell >/dev/null <newpower <<'!NO!SUBS!' NAME newpower -- Adds a new power to the system SYNOPSIS newpower power password [alias] ... users ... EOF DESCRIPTION This command creates a new server power and assigns a password to protect it. If the power name is longer than 12 characters, you may specify an alias for that power, which will be used internally by mailagent to reference it, or leave the field blank and mailagent will generate one for you. The 'system' power is normally required to create a new power. The 'security' power is required to create the root power and the 'root' power is needed to create 'security'. In order to bootstrap either power, please refer to the mailagent manual page where this is explained in detail. EXAMPLE newpower list-power mypasswd ram@acri.fr ram@eiffel.com EOF !NO!SUBS! chmod 644 newpower mailagent-3.1-74.orig/agent/files/help/passwd.SH0000755000175000017500000000252610473324174017501 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/passwd (with variable substitutions)" $spitshell >/dev/null <passwd <<'!NO!SUBS!' NAME passwd -- Changes power password SYNOPSIS passwd power old new DESCRIPTION This command changes a power password from 'old' to 'new'. Since you have to give the old password, there is no power requirements. EXAMPLE passwd list-power oldpass newpass !NO!SUBS! chmod 644 passwd mailagent-3.1-74.orig/agent/files/help/remauth.SH0000755000175000017500000000322710473324174017644 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/remauth (with variable substitutions)" $spitshell >/dev/null <remauth <<'!NO!SUBS!' NAME remauth -- Removes users from power clearance file SYNOPSIS remauth name [password] ... list of users ... EOF DESCRIPTION This command removes specified users from the power's clearance file. No special power is required when the target power is already detained. Otherwise the 'system' power is needed. As usual, 'root' and 'security' clearances require the corresponding power to be held or the appropriate password. Only users matching exactly the addresses listed in the clearance file will be removed. EXAMPLE remauth list list-password root@acri.fr EOF !NO!SUBS! chmod 644 remauth mailagent-3.1-74.orig/agent/files/help/addauth.SH0000755000175000017500000000302510473324174017605 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/addauth (with variable substitutions)" $spitshell >/dev/null <addauth <<'!NO!SUBS!' NAME addauth -- Adds users to power clearance file SYNOPSIS addauth power [password] ... users ... EOF DESCRIPTION This command adds the specified users to the specified power. The power password is optional if the power is already detained or the user has already got the 'system' power. To alter 'root' and 'security' clearances, the corresponding power is needed. EXAMPLE addauth list-power mypasswd ram@acri.fr ram@eiffel.com EOF !NO!SUBS! chmod 644 addauth mailagent-3.1-74.orig/agent/files/help/delpower.SH0000755000175000017500000000301310473324174020011 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/delpower (with variable substitutions)" $spitshell >/dev/null <delpower <<'!NO!SUBS!' NAME delpower -- Deletes a power from the system SYNOPSIS delpower power password [security] DESCRIPTION This command deletes a power and its associated clearance list. The 'system' power is required to delete all powers but 'root' and 'security'. The 'security' power may only be deleted by security and the 'root' power may only be deleted when the security password is also specified. EXAMPLE delpower list list-password !NO!SUBS! chmod 644 delpower mailagent-3.1-74.orig/agent/files/help/power.SH0000755000175000017500000000325510473324174017334 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/power (with variable substitutions)" $spitshell >/dev/null <power <<'!NO!SUBS!' NAME power -- Asks for a new power SYNOPSIS power name password DESCRIPTION This command requests for a new power. You must give the proper password and be listed in the clearance file in order to get it. Moreover, the server processing your commands must be in trusted mode to grant you the power, even if your credentials are otherwise perfectly valid. Any power is granted automatically to 'root', except 'security' of course which must be requested for separately. It is recommended you release a power when you don't need it any longer, to guard against mistakes. EXAMPLE power list list-passwd !NO!SUBS! chmod 644 power mailagent-3.1-74.orig/agent/files/help/approve.SH0000755000175000017500000000313510473324174017651 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/approve (with variable substitutions)" $spitshell >/dev/null <approve <<'!NO!SUBS!' NAME approve -- Approves command in advance by specifying a password SYNOPSIS approve password command DESCRIPTION This command records the specified password in the environment and then launches the command given as argument. It is entirely up to the command to check the approve variable when it otherwise expects a password, otherwise this command has no visible effect. It is not currently possible to approve a command which collects input. EXAMPLE approve list-password subscribe agent-users ram@acri.fr !NO!SUBS! chmod 644 approve mailagent-3.1-74.orig/agent/files/help/set.SH0000755000175000017500000000313210473324174016765 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/set (with variable substitutions)" $spitshell >/dev/null <set <<'!NO!SUBS!' NAME set -- Sets a command environment variable SYNOPSIS set variable value DESCRIPTION This command sets the variable to the specified value. Flags are only set to 'true' or 'false', although 'on', 'yes' and an empty value are also recognized to be 'true', anything else being 'false'. A 'set' all by itself will list all the defined variables along with their values. EXAMPLES set eof END_OF_FILE set trace on set !NO!SUBS! chmod 644 set mailagent-3.1-74.orig/agent/files/help/end.SH0000755000175000017500000000267010473324174016746 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/end (with variable substitutions)" $spitshell >/dev/null <end <<'!NO!SUBS!' NAME end -- Ends a server request SYNOPSIS end DESCRIPTION This pseudo command simply ends the processing of your request. The remaining of your message is discarded. Usually, a server request is also ended when a signature delimiter "--" is reached or at the physical end of the message. EXAMPLE ... some commands ... end ... mail message continues (ignored) ... !NO!SUBS! chmod 644 end mailagent-3.1-74.orig/agent/files/help/user.SH0000755000175000017500000000364110473324174017155 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/user (with variable substitutions)" $spitshell >/dev/null <user <<'!NO!SUBS!' NAME user -- Runs a command on behalf of another user SYNOPSIS user [name [command]] DESCRIPTION This command may be used to execute some other commands on behalf of a user. If a command is specified, it is immediately executed under the new identity (which is merely an e-mail address), and that new identity only lasts for that single command. Otherwise, the remaining commands are executed with the new identity. If no user name is specified, the original sender identity is restored. All the powers are lost when the 'user' command is executed, but this is only temporary when a command is specified on the same line. Note that it is up to the command to make use of this "effective" user identity, by looking at the proper environment variables. EXAMPLES user root@acri.fr ... some commands ... user user ram@acri.fr subscribe agent-users !NO!SUBS! chmod 644 user mailagent-3.1-74.orig/agent/files/help/help.SH0000755000175000017500000000251210473324174017123 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/help (with variable substitutions)" $spitshell >/dev/null <help <<'!NO!SUBS!' NAME help -- Tells more about a specific server command SYNOPSIS help [command] DESCRIPTION The help command will send you some help regarding a particular command. Without any argument, it prints a list of all the known commands. EXAMPLE help addauth !NO!SUBS! chmod 644 help mailagent-3.1-74.orig/agent/files/help/Makefile.SH0000755000175000017500000001110310473324174017704 0ustar jdgjdg: Makefile.SH generated from Jmake.tmpl and Jmakefile [jmake 3.0 PL48] : $X-Id: Jmake.tmpl,v 3.0.1.2 1995/01/11 14:50:21 ram Exp ram $ case $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac CURRENT=agent/files/help DIR=`echo $CURRENT/ | sed -e 's/\.\///g'` echo "Extracting ${DIR}Makefile (with variable substitutions)" INSTALL=`echo $install | sed -e 's,\./i,\$(TOP)/i,'` INSTALLDIR=`echo $installdir | sed -e 's,\./i,\$(TOP)/i,'` DATE=`date` $spitshell >Makefile <>Makefile <<'!NO!SUBS!' ######################################################################## # Jmake rules for building libraries, programs, scripts, and data files # $X-Id: Jmake.rules,v 3.0.1.2 1995/01/11 14:49:55 ram Exp ram $ ######################################################################## # Start of Jmakefile # $X-Id: Jmakefile,v 3.0 1993/11/29 13:47:52 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $X-Log: Jmakefile,v $ # Revision 3.0 1993/11/29 13:47:52 ram # Baseline for mailagent 3.0 netwide release. # FILES = addauth approve delpower end getauth help newpower \ passwd password power release remauth set setauth user all:: all:: $(FILES) local_realclean:: $(RM) $(FILES) addauth: addauth.SH /bin/sh addauth.SH approve: approve.SH /bin/sh approve.SH delpower: delpower.SH /bin/sh delpower.SH end: end.SH /bin/sh end.SH getauth: getauth.SH /bin/sh getauth.SH help: help.SH /bin/sh help.SH newpower: newpower.SH /bin/sh newpower.SH passwd: passwd.SH /bin/sh passwd.SH password: password.SH /bin/sh password.SH power: power.SH /bin/sh power.SH release: release.SH /bin/sh release.SH remauth: remauth.SH /bin/sh remauth.SH set: set.SH /bin/sh set.SH setauth: setauth.SH /bin/sh setauth.SH user: user.SH /bin/sh user.SH install:: @for dir in $(PRIVLIB) $(PRIVLIB)/help; do \ case '${MFLAGS}' in *[i]*) set +e;; esac; \ (set -x; test -d $$dir || $(INSTALLDIR) $$dir); \ done deinstall:: $(RM) -r $(PRIVLIB) $(PRIVLIB)/help install:: $(FILES) @case '${MFLAGS}' in *[i]*) set +e;; esac; \ for i in $(FILES); do \ (set -x; $(INSTALL) -c -m 444 $$i $(PRIVLIB)/help); \ done deinstall:: @case '${MFLAGS}' in *[i]*) set +e;; esac; \ for i in $(FILES); do \ (set -x; $(RM) $(PRIVLIB)/help/$$i); \ done ######################################################################## # Common rules for all Makefiles -- do not edit emptyrule:: clean: local_clean realclean: local_realclean clobber: local_clobber local_clean:: $(RM) core *~ *.o local_realclean:: local_clean local_clobber:: local_realclean $(RM) Makefile config.sh Makefile.SH: Jmakefile -@if test -f $(TOP)/.package; then \ if test -f Makefile.SH; then \ echo " $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~"; \ $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~; \ fi; \ echo " $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT)" ; \ $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT) ; \ else touch $@; exit 0; fi Makefile: Makefile.SH /bin/sh Makefile.SH tags:: $(CTAGS) -w *.[ch] $(CTAGS) -xw *.[ch] > tags local_clobber:: $(RM) tags ######################################################################## # Empty rules for directories with no sub-directories -- do not edit install:: @echo "install in $(CURRENT) done." deinstall:: @echo "deinstall in $(CURRENT) done." install.man:: @echo "install.man in $(CURRENT) done." deinstall.man:: @echo "deinstall.man in $(CURRENT) done." Makefiles:: Makefiles.SH:: !NO!SUBS! chmod 644 Makefile $eunicefix Makefile mailagent-3.1-74.orig/agent/files/help/password.SH0000755000175000017500000000274410473324174020044 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/files/help/password (with variable substitutions)" $spitshell >/dev/null <password <<'!NO!SUBS!' NAME password -- Sets new power password SYNOPSIS password power new DESCRIPTION This command sets a new power password. You usually need the corresponding power or have the 'system' power, hence showing you know the password for that power or have greater privileges. To change the 'root' and 'security' passwords, you need the corresponding power. EXAMPLE password list-power mypass !NO!SUBS! chmod 644 password mailagent-3.1-74.orig/agent/files/help/README0000644000175000017500000000010310473324174016606 0ustar jdgjdgThis directory contains help files for mailagent's SERVER command. mailagent-3.1-74.orig/agent/files/distribs0000644000175000017500000000144710473324174016560 0ustar jdgjdg# Distributions (under vi, use ':set ts=4') # prog version path archiv .Z patches kit 1.0 ~/home/projects/kit n n o kit 2.0 ~/home/projects/kit n n y dist 2.0 ~/home/projects/dist n n y matrix 1.1 ~/home/projects/matrix n n y cshar 3.0 ~/home/projects/cshar-3.0 n n y file --- ~/arch/dist/file y y n rcs 5.5 ~/arch/dist/rcs-5.5 y y n cops --- ~/arch/dist/cops y y n flex 2.3 ~/arch/dist/flex2.3 y y n xfmt --- ~/arch/dist/xfmt y y n et --- ~/arch/dist/et y y n less 123 ~/arch/dist/less y y n undel 2.0 ~/arch/dist/undel2 y y n perl 3.0 ~/arch/dist/perl-3.0 n n n perl 4.0 ~/arch/dist/perl-4.0 n n p patch 2.0 ~/arch/dist/patch y y n #rcs 4.3 ~/arch/dist/rcs.4_3 y y n #undel 1.0 ~/arch/dist/UNDEL y y n #dither 1.0 ~/arch/dist/DITHER y y y mailagent-3.1-74.orig/agent/files/mailagent.cf0000644000175000017500000002010611566404213017253 0ustar jdgjdg# # Configuration file for mailagent # # $Id: mailagent.cf,v 3.0.1.13 2001/03/17 18:03:59 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $Log: mailagent.cf,v $ # Revision 3.0.1.13 2001/03/17 18:03:59 ram # patch72: added two variables: domain and hidenet # # Revision 3.0.1.12 1998/07/28 16:56:21 ram # patch62: added servshell variable # # Revision 3.0.1.11 1998/03/31 14:35:29 ram # patch59: added "vacfixed" and "tofake" configuration parameters # # Revision 3.0.1.10 1997/02/20 11:33:49 ram # patch55: new groupsafe, execskip and lockwarn variables # # Revision 3.0.1.9 1997/01/07 18:26:06 ram # patch52: new execsafe configuration variable # # Revision 3.0.1.8 1995/09/15 13:39:50 ram # patch43: added locksafe, compspecs and comptag config variables # patch43: new "folder compression" section # # Revision 3.0.1.7 1995/08/07 16:07:48 ram # patch37: new biffing configuration variables # # Revision 3.0.1.6 1995/02/16 14:21:47 ram # patch32: new config variable 'fromfake' for mail without From: lines # # Revision 3.0.1.5 1994/10/29 17:39:44 ram # patch20: six new configuration variables for biffing support # # Revision 3.0.1.4 1994/10/04 17:15:20 ram # patch17: new email and mboxlock config parameters # # Revision 3.0.1.3 1994/09/22 13:44:11 ram # patch12: new config parameters callout and linkdirs # # Revision 3.0.1.2 1994/07/01 14:51:36 ram # patch8: eleven new config variables for better tuning # # Revision 3.0.1.1 1994/04/25 15:11:03 ram # patch7: added new 'fromesc' config variable for From line escapes # # Revision 3.0 1993/11/29 13:48:02 ram # Baseline for mailagent 3.0 netwide release. # # # Configuration section # # Paramters likely to change home : /lyon/ram # Home directory (must be correctly set) level : 9 # Logging level tmpdir : /tmp # Temporary directory to be used emergdir : ~/tmp/lost+mail # Emergency directory (for dumps) track : OFF # Track matches on stdout (on/off) # Minimum path to ensure and path depending on the machine path : /bin:/usr/bin:/usr/ucb p_york : ~/bin:~/bin/rs2030 p_lyon : ~/bin:~/bin/rs2030 p_rome : ~/bin:~/bin/sun4:/base/common/GENERAL/sun4/bin # User running mailagent user : ram name : Raphael email : you@your.domain.top # Your accurate e-mail address domain : domain.top # Your domain name (no leading '.') hidenet : OFF # Prefix domain with hostname when OFF # Vacation mode (on/off), vacation file and period vacation : OFF # Vacation mode on/off vacfile : ~/.vacation # File to be sent back vacperiod: 1d # Period between two vacation messages vacfixed : OFF # Turn to on to solely allow vacfile message # Mail and news transport agents # By default, values for sendmail and sendnews are determined at configuration # time. The default mailopt is "-odq -i" when sendmail is used. # The -h option is always added to the sendnews program to indicate headers # are already present. sendmail : /usr/lib/sendmail sendnews : /usr/lib/news/inews mailopt : -odq -i newsopt : # # Parameters which should not change very often # # Define main configuration parameters umask : 077 # Default umask spool : ~/var/mailagent # Spool directory queue : $spool/queue # Queue directory (must exist) logdir : ~/var/log # Where logfile is stored context : $spool/context # Mailagent's context file callout : $spool/callout # Callout queue log : agentlog # Log file is in $logdir seq : .seq # Seq file is in $spool timezone : PST8PDT # Time zone location statfile : $spool/mailagent.st # Statistics file rules : ~/.rules # Filter's rules location (optional) rulecache: $spool/rulecache # Cache for compiled rules (optional) # Security checks secure : ON # Make extended checks on sensitive files linkdirs : ON # Also carefully check symlinks to dirs groupsafe: ON # Allow group-writable files when OFF execsafe : OFF # Make extended checks on exec()ed files execskip : OFF # Turn to ON to avoid all checks on exec() # Mailbox parameters maildrop : /usr/mail # System mail drop directory (optional) mailbox : $user # Mailbox file name (optional) mboxlock : %f.lock # Lock mailbox with .lock file mmdf : OFF # Allow MMDF-style mailbox delivery mmdfbox : OFF # Force new folders to MMDF format fromesc : ON # Escape leading From into >From fromall : OFF # Escape all From, even within paragraph fromfake : ON # Attempt creation of From: header when missing tofake : ON # Fake a To: line when missing # Biffing support biff : ON # Whether biff is wanted biffhead : From, To, Subject # Which header fields should be printed bifflen : 560 # Maximum body length printed anyway bifflines: 7 # Maximum body lines printed biffnl : ON # Turn to OFF to avoid blank body lines biffmsg : ~/.biffmsg # Template format for biff (optional) bifftrim : ON # Whether trim info should be part of biffing bifftrlen: 2 # Minimal trimming length, in lines biffquote: ON # Whether the attribution line should be shown biffmh : OFF # Compact biffing message ala MH biffnice : OFF # Whether compacted body should be reformatted # MH-style folders mhprofile: ~/.mh_profile # Name of the MH profile file (optional) msgprefix: .msg_prefix # File containing message name prefix # Locking parameters lockmax : 20 # Maximum number of locking attempts lockdelay: 2 # Amount of seconds between two lock attempts lockhold : 3600 # Amount of seconds before breaking lock locksafe : ON # Locking style on mailboxes lockwarn : 20,300 # Warn on busy locks after 20s, then every 300 nfslock : OFF # NFS-secure locking (optional) # Timeout parameters queuewait: 60 # Delay for filter before calling mailagent queuehold: 1800 # Amount of seconds queued mail remains skipped queuelost: 86400 # Timeout before flagging old queued mail runmax : 3600 # Timeout for RUN command and friends # Folder compression #compress : ~/.compress # Folder compression list compspecs: $spool/compressors # Compression progs config file comptag : gzip # Default compression tag # Optional parameters (for experts...) #newcmd : $spool/newcmd # Definition of new filtering commands #perlib : pl # Extended perl library search path #tome : also-me # Alternate logins for me #rulemac : ON # Macro substitution in rule patterns # Database hashing directory (in $spool) and other controls hash : dbr # Hashing directory cleanlaps: 1M # Laps between cleanings autoclean: ON # Turn periodic cleaning on/off agemax : 1y # Maximum lifetime for entries # # Parameters for SERVER # comserver: $spool/server # Valid server commands servdir : $spool/cmds # Default path for perl server commands servshell: /bin/sh # Shell used to spawn shell commands (optional) maxerrors: 10 # Allow at most ten errors before flushing maxcmds : 10 # Allow maximum of ten commands in one request scriptcc : ON # Send copy of sesssion transcripts to user? bqueue : $spool/batch # Batch queue (not implemented yet) powers : $spool/powers # Directory for power administration powerlog : $logdir/powerlog # Log requests for new powers powerlist: $powers/aliases # Mapping of powers to filename in powerdir powerdir : $powers/clearance # Directory listing user clearances for powers passwd : $powers/passwd # Power passwords helpdir : $spool/help # Help directory for server commands # # Parameters for PROCESS # comfile : $spool/commands # Valid commands distlist : $spool/distribs # Distribution list proglist : $spool/proglist # Program description list maxsize : 150000 # Maximum size before kiting plsave : $spool/plsave # Where patchlevels are saved authfile : $spool/auth # Remote sending authorizations (not yet) mailagent-3.1-74.orig/agent/files/Makefile.SH0000755000175000017500000001346210473324174016766 0ustar jdgjdg: Makefile.SH generated from Jmake.tmpl and Jmakefile [jmake 3.0 PL58] : $X-Id: Jmake.tmpl,v 3.0.1.2 1995/01/11 14:50:21 ram Exp ram $ case $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac CURRENT=agent/files DIR=`echo $CURRENT/ | sed -e 's/\.\///g'` echo "Extracting ${DIR}Makefile (with variable substitutions)" INSTALL=`echo $install | sed -e 's,\./i,\$(TOP)/i,'` INSTALLDIR=`echo $installdir | sed -e 's,\./i,\$(TOP)/i,'` DATE=`date` $spitshell >Makefile <>Makefile <<'!NO!SUBS!' ######################################################################## # Jmake rules for building libraries, programs, scripts, and data files # $X-Id: Jmake.rules,v 3.0.1.4 1995/07/25 13:33:59 ram Exp ram $ ######################################################################## # Start of Jmakefile # $X-Id: Jmakefile,v 3.0.1.2 1995/09/15 13:36:23 ram Exp ram $ # # Copyright (c) 1990-2006, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # You may reuse parts of this distribution only within the terms of # that same Artistic License; a copy of which may be found at the root # of the source tree for mailagent 3.0. # # $X-Log: Jmakefile,v $ # Revision 3.0.1.2 1995/09/15 13:36:23 ram # patch43: new compressors file installed in the private library # # Revision 3.0.1.1 1995/02/16 14:06:56 ram # patch32: added new file setup.cf for initial configuration setup # # Revision 3.0 1993/11/29 13:47:46 ram # Baseline for mailagent 3.0 netwide release. # FILES = agenthelp commands distribs filter.sh mailagent.cf proglist \ chkagent.sh setup.cf compressors all:: install:: @for dir in $(PRIVLIB); do \ case '${MFLAGS}' in *[i]*) set +e;; esac; \ (set -x; test -d $$dir || $(INSTALLDIR) $$dir); \ done deinstall:: $(RM) -r $(PRIVLIB) install:: $(FILES) @case '${MFLAGS}' in *[i]*) set +e;; esac; \ for i in $(FILES); do \ (set -x; $(INSTALL) -c -m 444 $$i $(PRIVLIB)); \ done deinstall:: @case '${MFLAGS}' in *[i]*) set +e;; esac; \ for i in $(FILES); do \ (set -x; $(RM) $(PRIVLIB)/$$i); \ done ######################################################################## # Common rules for all Makefiles -- do not edit emptyrule:: clean: sub_clean local_clean realclean: sub_realclean local_realclean clobber: sub_clobber local_clobber local_clean:: $(RM) core *~ *.o local_realclean:: local_clean local_clobber:: local_realclean $(RM) Makefile config.sh Makefile.SH: Jmakefile -@if test -f $(TOP)/.package; then \ if test -f Makefile.SH; then \ echo " $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~"; \ $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~; \ fi; \ echo " $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT)" ; \ $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT) ; \ else touch $@; exit 0; fi Makefile: Makefile.SH /bin/sh Makefile.SH tags:: $(CTAGS) -w *.[ch] $(CTAGS) -xw *.[ch] > tags local_clobber:: $(RM) tags ######################################################################## # Rules for building in sub-directories -- do not edit subdirs: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ (cd $$i ; echo $(VERB) "in $(DIR)$$i..."; \ $(MAKE) $(MFLAGS) $(FLAGS) $(TARGET)); \ done install:: @$(MAKE) subdirs TARGET=install VERB="Installing" FLAGS= deinstall:: @$(MAKE) subdirs TARGET=deinstall VERB="Deinstalling" FLAGS= install.man:: @$(MAKE) subdirs TARGET=install.man VERB="Installing man pages" FLAGS= deinstall.man:: @$(MAKE) subdirs TARGET=deinstall.man VERB="Deinstalling man pages" FLAGS= sub_clean:: @$(MAKE) subdirs TARGET=clean VERB="Cleaning" FLAGS= @echo "Back to $(CURRENT) for "clean... sub_realclean:: @$(MAKE) subdirs TARGET=realclean VERB="Real cleaning" FLAGS= @echo "Back to $(CURRENT) for "realclean... sub_clobber:: @$(MAKE) subdirs TARGET=clobber VERB="Clobbering" FLAGS= @echo "Back to $(CURRENT) for "clobber... tag:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS) ;\ do \ (cd $$i ; echo "Tagging" "in $(DIR)$$i..."; \ $(MAKE) $(MFLAGS) tag); \ done Makefiles:: @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS);\ do \ echo "Making "Makefiles" in $(DIR)$$i..."; \ (cd $$i || exit 1; \ if test ! -f Makefile; then /bin/sh Makefile.SH; fi; \ $(MAKE) $(MFLAGS) Makefiles) \ done Makefiles.SH:: Makefile.SH @case '${MFLAGS}' in *[ik]*) set +e;; esac; \ for i in $(SUBDIRS);\ do \ case "$(DIR)$$i/" in \ */*/*/*/) newtop=../../../..;; \ */*/*/) newtop=../../..;; \ */*/) newtop=../..;; \ */) newtop=..;; \ esac; \ case "$(TOP)" in \ /*) newtop="$(TOP)" ;; \ esac; \ echo "Making Makefiles.SH in $(DIR)$$i..."; \ (cd $$i || exit 1; $(MAKE) $(MFLAGS) -f ../Makefile \ Makefile TOP=$$newtop CURRENT=$(DIR)$$i;\ $(MAKE) $(MFLAGS) Makefiles.SH) \ done all:: @$(MAKE) subdirs TARGET=all VERB="Making all" FLAGS= !NO!SUBS! chmod 644 Makefile $eunicefix Makefile mailagent-3.1-74.orig/agent/files/README0000644000175000017500000000253611017740714015667 0ustar jdgjdgThis directory holds the shell version of the filter, and some other sample files which will be installed in the public mailagent directory. agenthelp: The generic help message used by the @SH mailhelp command. You may of course rewrite this completely to fit your taste. chkagent.sh: A small script I am using to monitor the whole mailagent installation. This is run by cron every night, and mails me problems logged in the log file, or unusual messages from my ~/.bak, etc... (The name chkagent.sh was chosen to leave room for the RCS ,v extension on some old systems with 14 characters limit in the file names.) Here is my crontab entry: # Check the mailagent log file for the current day 55 23 * * * /usr/share/mailagent/chkagent.sh commands: This file holds the allowed commands for @SH hooks. distribs: A description table which states where each program is located, whether it is archived or not, or has patches, etc... This is used by the @SH commands. filter.sh: The shell version of the filter program. Note that this script is not tested by the automatic regression tests and needs some tailoring before it can be used. It is provided only as a guideline for people who cannot use the C version. mailagent.cf: A template for your ~/.mailagent. proglist: A list of program description which will be used by the 'maillist' command. mailagent-3.1-74.orig/agent/package.SH0000755000175000017500000003550111030765550015535 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; *) TOP=..;; esac revision=`awk '/^#define[ ]*REVISION/ {print $3}' < $TOP/revision.h` case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/package (with variable substitutions)" $spitshell >package <>package <<'!NO!SUBS!' $userlist = "users"; $prog_name = $0; # Who I am $prog_name =~ s|^.*/(.*)|$1|; # Keep only base name $lockext = $long_filenames ? '.lock' : '!'; # Extension used by lock routines &read_config; # First, read configuration file (in ~/.mailagent) &catch_signals; # Protect against signals # take job number and command from environment # (passed by mailagent) $jobnum = $ENV{'jobnum'}; $fullcmd = $ENV{'fullcmd'}; $pack = $ENV{'pack'}; $path = $ENV{'path'}; &read_dist; # Read distributions $dest = shift; # Who should the patches be sent to $system = shift; # Which system do patches belong $version = shift; # Which version it is $theirpl = shift; # which patchlevel they've got $request = shift; # what would they like to ask for # A single '-' as first argument stands for return path $dest = $path if $dest eq '-'; # A single '-' for version means "highest available" version. $version = $Version{$system} if $version eq '-'; # Convert empty pl to a dash $theirpl = '-' if $theirpl eq ''; # Full name of system for H table access $pname = $system . "|" . $version; $maillist = "To obtain a list of what is available, send me the following mail: Subject: Command \@SH maillist $path ^ note the l"; # Silently discard hostile addresses unless (&addr'valid($dest)) { &add_log("FAILED (HOSTILE $dest)") if $loglvl > 1; exit 0; } if (!$System{$system}) { open(MAILER, "|$cf'sendmail $cf'mailopt $path $cf'email") || &nofork; print MAILER "To: $path Subject: No program called $system X-Mailer: mailagent [version $mversion-$revision] I have not heard of a program called $system. Sorry. -- $prog_name speaking for $cf'user "; close MAILER; if ($?) { &add_log("ERROR cannot mail back error") if $loglvl; } else { &add_log("MSG unknown system $system") if $loglvl > 8; } &add_log("FAILED (UNKNOWN SYSTEM)") if $loglvl > 1; exit 0; } if (!$Program{$pname}) { open(MAILER, "|$cf'sendmail $cf'mailopt $path $cf'email") || &nofork; print MAILER "To: $path Subject: No package $system version $version X-Mailer: mailagent [version $mversion-$revision] I don't know anything about version $version of $system. Sorry."; if ($Version{$system} ne '') { print MAILER " [The highest version for $system is $Version{$system}.]"; &add_log("MSG highest version is $Version{$system}") if $loglvl > 8; } else { print MAILER " [There is no version number for $system.]"; &add_log("MSG no version number") if $loglvl > 8; } print MAILER " -- $prog_name speaking for $cf'user "; close MAILER; if ($?) { &add_log("ERROR cannot mail back error") if $loglvl; } else { &add_log("MSG bad $system version number") if $loglvl > 8; } &add_log("FAILED (BAD SYSTEM NUMBER)") if $loglvl > 1; exit 0; } # If the request is not for the most recent version, warn the user and abort. if ($version < $Version{$system}) { open(MAILER, "|$cf'sendmail $cf'mailopt $path $cf'email") || &nofork; print MAILER "To: $path Subject: Version $version of $system is out-of-date X-Mailer: mailagent [version $mversion-$revision] This short note to warn you that $system version $version is not the lattest one available. If you have some interest in $system, I suggest you upgrade by fetching version $Version{$system} as soon as possible. $maillist I did not record you as a $system user since your version is not the one currently maintained. -- $prog_name speaking for $cf'user "; close MAILER; if ($?) { &add_log("ERROR cannot inform newer version exists") if $loglvl; } else { &add_log("MSG old version $system $version") if $loglvl > 8; } exit 0; } if (!($Maintained{$pname} || $Patches{$pname})) { open(MAILER, "|$cf'sendmail $cf'mailopt $path $cf'email") || &nofork; print MAILER "To: $path Subject: $system version $version is not maintained X-Mailer: mailagent [version $mversion-$revision] I can't keep you up to date on changes to version $version of $system, because this code is not maintained by $cf'name. -- $prog_name speaking for $cf'user "; close MAILER; if ($?) { &add_log("ERROR cannot mail back error") if $loglvl; } else { &add_log("MSG $system is not maintained") if $loglvl > 8; } &add_log("FAILED (NOT MAINTAINED)") if $loglvl > 1; exit 0; } # decode their request into a status letter. # they may be asking to be left alone. if ((($theirpl eq '-') && $request eq '') || $request eq 'leavealone') { $leavealone = 1; $letter = 'L'; } elsif ($request eq '') { $letter = 'U'; } # just a user elsif ($request eq 'mailpatches') { $letter = 'M'; } # want patches elsif ($request eq 'notifypatches') { $letter = 'N'; } # notify only elsif ($request eq 'badaddress') { $leavealone = 1; $letter = 'B'; } else { open(MAILER, "|$cf'sendmail $cf'mailopt $path $cf'email") || &nofork; print MAILER "To: $path Subject: I didn't understand your package command X-Mailer: mailagent [version $mversion-$revision] Your package command requested `$request', and I don't know what that means. -- $prog_name speaking for $cf'user "; close MAILER; if ($?) { &add_log("ERROR cannot mail back error") if $loglvl; } else { &add_log("MSG bad request $request") if $loglvl > 8; } &add_log("FAILED (BAD REQUEST)") if $loglvl > 1; exit 0; } # Go to the package root directory and check for possible forwarding... chdir($Location{$pname}) || &abort("cannot chdir to $Location{$pname}: $!"); &check_forward; # Returns only if command is not forwarded open(PATCHLEVEL, "patchlevel.h") || &abort("cannot open patchlevel.h"); $maxnum = 0; while () { if (/.*PATCHLEVEL[ \t]*(\d+)/) { $maxnum = $1; last; } } close PATCHLEVEL; # if they have Configured a patchlevel which is not the latest, let them know. if (!$leavealone && $theirpl ne '-' && $maxnum ne $theirpl) { $upgrade = $theirpl + 1; # In fact, if they've asked for patch mailing, send it directly. This # works because our environment, set up by mailagent, will be propagated # to the mailpatch command as-is. if ($letter eq 'M') { system('mailpatch', $dest, $system, $version, "$upgrade-"); if ($? == 0) { &add_log("MAILED missing patches for $system $version to $dest") if $loglvl > 6; } else { &add_log("WARNING unable to mail patches for $system $version") if $loglvl > 1; } } else { # Send the following to $dest (address given to the package command), # not $path (return address) since it is legitimate for them to differ # and the following is not an error message but something concerning # the address we're recording. Likewise, the above mailpatch command # sends patches to $dest. open(MAILER, "|$cf'sendmail $cf'mailopt $dest $cf'email") || &nofork; print MAILER "To: $dest Subject: The latest patchlevel for $system version $version is $maxnum X-Mailer: mailagent [version $mversion-$revision] Just a quick note to let you know that the latest patchlevel for $system version $version is $maxnum; if you are still at patchlevel $theirpl, I strongly suggest you upgrade by applying the more recent patches. You can fetch these automatically by sending me the following mail: Subject: Command \@SH mailpatch $dest $system $version $upgrade- ^ note the c -- $prog_name speaking for $cf'user "; close MAILER; if ($?) { &add_log("ERROR cannot inform $system is now $version PL$maxnum") if $loglvl; } else { &add_log("MSG latest version is $system $version PL$maxnum") if $loglvl > 8; } } } # Lock users file. That file should only be edited with the edusers script. if (0 != &acs_rqst($userlist)) { &add_log("WARNING updating $userlist without lock") if $loglvl > 5; } # look for them in the userlist file if (open(USERLIST, $userlist)) { while () { next if /^#/; chop if /\n$/; ($status, $pl, $name) = split; # convert oldstyle user file format (dist 3.0 PL13). unless (defined $name) { $name = $pl; # Shift left $pl = '-'; } # have we heard from them before? if (&addr'match($name, $dest)) { if ($found++) { &add_log("WARNING removing duplicate for $dest ($name)") if $loglvl > 5; &add_log("NOTICE status for $dest was $oldstatus, now $status") if $oldstatus ne $status && $loglvl > 6; next; } $oldstatus = $status; # Save status $oldpl = $pl; # And patchlevel $status = $letter; $pl = $theirpl if $theirpl ne '-'; } # save entry push(@status, $status); push(@pl, $pl); push(@name, $name); # in case we have to go to &send_closest push(@registered, $name) if $status =~ /^[MN]/; } close USERLIST; } # optimize a little... if ( $found == 1 && $oldstatus eq $letter && ($theirpl eq '-' || $oldpl eq $theirpl) ) { &add_log("NOTICE no change for $dest") if $loglvl > 6; close USERLIST; &free_file($userlist); exit 0; } # add them if they're new. if (!$found) { if ($letter eq 'L') { &add_log("WARNING unknown $dest wants to be left alone") if $loglvl > 5; &free_file($userlist); &send_closest; &add_log("FAILED (UNREGISTERED $dest)") if $loglvl > 1; exit 0; } elsif ($letter eq 'B') { &add_log("WARNING unknown $dest bounced back") if $loglvl > 5; &free_file($userlist); &add_log("FAILED (BAD BOUNCE ADDRESS $dest)") if $loglvl > 1; exit 0; } else { push(@name, $dest); push(@status, $letter); push(@pl, $theirpl); } } # write the file back out. open(USERLIST,">$userlist.new") || &abort("can't create new $userlist file: $!"); for ($i = 0; $i <= $#name; $i++) { print USERLIST $status[$i], "\t", $pl[$i], "\t", $name[$i], "\n" || &abort("error writing new $userlist file"); } close(USERLIST) || &abort("error closing new $userlist file"); rename("$userlist.new", $userlist); &free_file($userlist); # Emergency exit with clean-up sub abort { local($reason) = shift(@_); # Why we are exiting &free_file($userlist); &fatal($reason); } # Send closest matching addresses, among @registered sub send_closest { open(MAILER, "|$cf'sendmail $cf'mailopt $path $cf'email") || &nofork; print MAILER "To: $path Subject: You were not recorded as a $system $version user X-Mailer: mailagent [version $mversion-$revision] I can't honour your desire to be left alone for $system version $version updates because you were not found among the registered users. Your command was: $fullcmd For your information, here is the list of the closest addresses to your own e-mail address ($dest) that are registered: "; local($first) = ''; foreach $addr (@registered) { if (&addr'close($dest, $addr)) { print MAILER "\t$addr\n"; $first = $addr if $first eq ''; } } print MAILER < 6; } } # Report error while forking a sendmail process sub nofork { &add_log("SYSERR fork: $!") if $loglvl; &add_log("ERROR cannot launch $cf'sendmail") if $loglvl; } !NO!SUBS! $grep -v '^;#' pl/fatal.pl >>package $grep -v '^;#' pl/add_log.pl >>package $grep -v '^;#' pl/read_conf.pl >>package $grep -v '^;#' pl/distribs.pl >>package $grep -v '^;#' pl/secure.pl >>package $grep -v '^;#' pl/cdir.pl >>package $grep -v '^;#' pl/addr.pl >>package $grep -v '^;#' pl/acs_rqst.pl >>package $grep -v '^;#' pl/free_file.pl >>package $grep -v '^;#' pl/checklock.pl >>package $grep -v '^;#' pl/signals.pl >>package $grep -v '^;#' pl/hostname.pl >>package $grep -v '^;#' pl/forward.pl >>package chmod 755 package $eunicefix package mailagent-3.1-74.orig/agent/mailhelp.SH0000755000175000017500000000627711030765550015745 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; *) TOP=..;; esac revision=`awk '/^#define[ ]*REVISION/ {print $3}' < $TOP/revision.h` case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/mailhelp (with variable substitutions)" $spitshell >mailhelp <>mailhelp <<'!NO!SUBS!' $prog_name = $0; # Who I am $prog_name =~ s|^.*/(.*)|$1|; # Keep only base name &read_config; # First, read configuration file (in ~/.mailagent) # take job number and command from environment # (passed by mailagent) $jobnum = $ENV{'jobnum'}; $fullcmd = $ENV{'fullcmd'}; $dest=shift; # Who should the help be sent to $dest = $ENV{'path'} if $dest eq ''; # If dest was ommitted # A single '-' as first argument stands for return path $dest = $ENV{'path'} if $dest eq '-'; # Silently discard hostile addresses unless (&addr'valid($dest)) { &add_log("FAILED (HOSTILE $dest)") if $loglvl > 1; exit 0; } open(HELP, "$cf'spool/agenthelp") || &fatal("no help file!\n"); open(MAILER, "|$cf'sendmail $cf'mailopt $dest") || &nofork; print MAILER "To: $dest Subject: How to use my mail agent X-Mailer: mailagent [version $mversion-$revision] "; while () { # Replace some tokens by parameters s/=DEST=/$dest/g; s/=MAXSIZE=/$cf'maxsize/g; print MAILER; } print MAILER " -- $prog_name speaking for $cf'user "; close MAILER; if ($?) { &add_log("ERROR couldn't send help to $dest") if $loglvl > 0; } else { &add_log("SENT help to $dest") if $loglvl > 2; } close HELP; # Report error while forking a sendmail process sub nofork { &add_log("SYSERR fork: $!") if $loglvl; &add_log("ERROR cannot launch $cf'sendmail") if $loglvl; } !NO!SUBS! $grep -v '^;#' pl/fatal.pl >>mailhelp $grep -v '^;#' pl/add_log.pl >>mailhelp $grep -v '^;#' pl/read_conf.pl >>mailhelp $grep -v '^;#' pl/secure.pl >>mailhelp $grep -v '^;#' pl/cdir.pl >>mailhelp $grep -v '^;#' pl/addr.pl >>mailhelp chmod 755 mailhelp $eunicefix mailhelp mailagent-3.1-74.orig/agent/man/0000755000175000017500000000000011675050334014454 5ustar jdgjdgmailagent-3.1-74.orig/agent/man/Jmakefile0000644000175000017500000000161110473324174016266 0ustar jdgjdg/* * Jmakefile for mailagent's manual pages */ ;# $Id: Jmakefile,v 3.0.1.1 1994/09/22 13:52:52 ram Exp ram $ ;# ;# Copyright (c) 1990-2006, Raphael Manfredi ;# ;# You may redistribute only under the terms of the Artistic License, ;# as specified in the README file that comes with the distribution. ;# You may reuse parts of this distribution only within the terms of ;# that same Artistic License; a copy of which may be found at the root ;# of the source tree for mailagent 3.0. ;# ;# $Log: Jmakefile,v $ ;# Revision 3.0.1.1 1994/09/22 13:52:52 ram ;# patch12: new manual page for edusers ;# ;# Revision 3.0 1993/11/29 13:48:25 ram ;# Baseline for mailagent 3.0 netwide release. ;# >L /* I expect to fix this with an |append command */ MPAGES = mailagent.$(L) maildist.$(L) maillist.$(L) mailhelp.$(L) \ mailpatch.$(L) package.$(L) edusers.$(L) ComplexShellManualTarget($(MPAGES)) mailagent-3.1-74.orig/agent/man/edusers.SH0000755000175000017500000000702110473324174016366 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/man/edusers.$manext (with variable substitutions)" $rm -f edusers.$manext $spitshell >edusers.$manext < .SH "SEE ALSO" mailagent($manext), metaconfig($manext), package($manext), packinit($manext). !GROK!THIS! chmod 444 edusers.$manext mailagent-3.1-74.orig/agent/man/maillist.SH0000755000175000017500000000256610473324174016543 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/man/maillist.$manext (with variable substitutions)" $rm -f maillist.$manext $spitshell >maillist.$manext <maildist.$manext <package.$manext < .br Raphael Manfredi (minor enhancements) .SH "SEE ALSO" edusers($manext), mailagent($manext), metaconfig($manext). !GROK!THIS! chmod 444 package.$manext mailagent-3.1-74.orig/agent/man/mailhelp.SH0000755000175000017500000001556110473324174016517 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/man/mailhelp.$manext (with variable substitutions)" $rm -f mailhelp.$manext $spitshell >mailhelp.$manext < .SH "SEE ALSO" mailagent($manext), package($manext). !GROK!THIS! chmod 444 mailhelp.$manext mailagent-3.1-74.orig/agent/man/mailpatch.SH0000755000175000017500000000257110473324174016663 0ustar jdgjdgcase $CONFIG in '') if test -f config.sh; then TOP=.; elif test -f ../config.sh; then TOP=..; elif test -f ../../config.sh; then TOP=../..; elif test -f ../../../config.sh; then TOP=../../..; elif test -f ../../../../config.sh; then TOP=../../../..; else echo "Can't find config.sh."; exit 1 fi . $TOP/config.sh ;; esac case "$0" in */*) cd `expr X$0 : 'X\(.*\)/'` ;; esac echo "Extracting agent/man/mailpatch.$manext (with variable substitutions)" $rm -f mailpatch.$manext $spitshell >mailpatch.$manext <mailagent.$manext <>/users/ram/.bak 2>&1" .Ef This will pipe all your mails to the \fIfilter\fR program, redirecting all unusual messages to \fI~/.bak\fR. A sample filter shell script may be found in \fILib/mailagent\fR, as well as a C filter program. On some systems, it may be necessary to move the '|' character before the leading quote, but don't try this unless you have no other choice (i.e. only as a last resort). .PP It is \fIvery\fR important to redirect error messages to some file within your home directory. For one thing, that will get you out of trouble if strange things start to happen, but more to the point, it makes your \fI.forward\fR file unique. Older \fIsendmail\fR program, in an heroic attempt to "optimize" delivery, will silently remove duplicate recipients, and if a recipient has a \fI.forward\fR, its literal content is used in place of his e-mail address. Therefore, two local recipients with the same filtering string will be considered as one unique recipient and only one of them will get the message... .PP If your system does not allow shell redirection from within the .forward, you can use this instead (only supported by the C filter): .Ex "| exec /users/ram/mail/filter -o /users/ram/.bak" .Ef which in effect redirects \fIstdout\fR and \fIstderr\fR to the specified file for you, appending data at the end of the file. If the filter runs setuid or setgid, you will not be allowed to create the file, nor to append to it unless the owner of the file is the \fIreal\fR uid invoking the program (for security reasons). .PP Note that the \fI.forward\fR file only pipes the mail to the \fIfilter\fR program and does not leave any copy in the mailbox. It is up to you to decide in the rule file whether you want to trash the mail away or leave it in the mailbox. If you do not have a rule file (i.e. you left a blank entry in your \fI~/.mailagent\fR, or you named a non-existent file, or your file is simply empty), don't worry: the default action is to leave the mail in the mailbox. ''' .SS "Allowed Commands" .PP The allowed command file (as specified by the \fIcomfile\fR variable in your \fI~/.mailagent\fR) contains all the recognized and allowed commands. The file \fIcommands\fR held in directory \fILib/mailagent\fR should be copied as-is into your Spool directory. ''' .SS "Testing Your Installation" .PP Now, assuming you have set a proper \fI~/.mailagent\fR file and edited the configuration section of the \fIfilter\fR, it is time to test your installation. Make sure your \fI.forward\fR is world readable and that the \fIfilter\fR has the execution bits set (there is no reason to make the \fIfilter\fR world readable). Set a log-level of 20 and disable vacation mode (the \fIvacation\fR entry in the \fI~/.mailagent\fR should be OFF). Set the name of the rule file to an empty file (or a non-existing file for that matter). You are ready to proceed... .PP Send yourself a mail and give mailagent time to process your mail. The subject of the message should be 'test' (in fact, anything but 'Command'). You may want to run a "\fItail -f logfile\fR" to see what's happening. At the end of the processing, the logfile should contain something like the following (names of temporaries may \-and will\- of course differ; timestamps have been removed): .Ex got the right to process mail building default rules parsing mail analyzing mail in mode 'INITIAL' for ALL selector 'All' on '<1,->', pattern '/^Subject: [Cc]ommand/' matching '/^Subject: [Cc]ommand/' on 'All' (<1,->) was false NOTICE no match, leaving in mailbox XEQ (LEAVE) starting LEAVE starting SAVE /usr/spool/mail/ram LEFT [qm7831] in mailbox FILTERED [qm7831] from ram (Raphael Manfredi) mailagent continues mailagent exits .Ef .PP If you do not get that, there is a problem somewhere. Start by looking at the \fI~/.bak\fR file (or whatever file the \fI.forward\fR uses to redirect output of the filter). If you see something like: .Ex FATAL no valid queue directory DUMPED in ~/mbox.filter .Ef then it means the \fIqueue\fR parameter in your \fI~/.mailagent\fR does not point to a valid directory. Your mail has been dumped in an emergency mailbox. .PP The \fI~/.bak\fR file may also contain error messages stating that \fIperl\fR was not found. In that case, there should be an error message in the logfile: .Ex ERROR mailagent failed, [qm7886] left in queue .Ef In that case, make sure the mail has correctly been queued in a file \fIqm7886\fR. The queue will be processed again when another mail arrives or when the \fImailagent\fR is invoked with \fB\-q\fR (however, to avoid race conditions, only mails which have remained for a while will be processed). .PP Queuing of mail also happens when another \fImailagent\fR is running. If the logfile says: .Ex denied right to process mail .Ef then remove the \fIperl.lock\fR file in the Spool directory. Old lock files are automatically discarded by the \fImailagent\fR anyway (after one hour). .PP If none of these occurs, then maybe \fIsendmail\fR did not process your \fI~/.forward\fR at all or the file has a syntax error. Check your mailbox, and if your mail is in there, your \fI.forward\fR has not been processed. Otherwise, ask your system administrator to check \fIsendmail\fR's logfile. A correct entry would appear as (with leading timestamps and syslog stamps removed): .Ex message-id=<9202041919.AA07882@york.eiffel.com> from=ram, size=395, class=0, received from local to="| /york/ram/mail/filter >>/york/ram/.bak 2>&1", delay=00:00:05, stat=Sent .Ef .PP If you still cannot find why the mail was not correctly processed, you should make sure you normally receive mail by removing (or renaming) your \fI~/.forward\fR and sending yourself another test mail. Also make sure your home directory is world readable and "executable". .PP If you are using the C filter, make sure it is running on the right platform. There may be a low-level routing of all your mail to a \fImailhost\fR machine, responsible for the final delivery, and the filter program will run on that machine, which may be a different platform than the one you compiled filter on. Also make sure your home directory is mounted on that machine, or the mail transport agent will be unable to locate your \fI.forward\fR file, less process it. .PP This kind of centralized mail delivery is good only when a few people have mail processing hooks (i.e. \fI.forward\fR files piping mail to a program); otherwise it's better to route mail to each user's workstation or machine, for local processing, to avoid an excessive workload on the \fImailhost\fR machine, especially if it is a dedicated NFS server. If you are a system administrator installing \fImailagent\fR and expect many people to use it, keep this in mind. ''' ''' O p t i o n s ''' .SH OPTIONS There is a limited set of options which may be used when calling the mailagent directly. Only one special option at a time may be specified. Invoking mailagent as \fImailqueue\fR is equivalent to using the \fB\-l\fR option. .TP 15 .B \-c\fI file\fR Specify an alternate configuration file (~ substitution occurs). The default is \fI~/.mailagent\fR. .TP .B \-d The mailagent parses the rule file, compiles the rules and dumps them on the standard output. This option is mainly used to check the syntax of the rule file and make sure the rules are what the user really thinks they are. .TP \fB\-e\fI rule\fR This option lets you specify some rules on the command line, which will override those specified via the ~/.mailagent, if any. There may be as many \fB\-e\fR as necessary, all the rules being concatenated together as one happy array, which is then parsed the same way a rule file is. If only \fBone\fR rule is given and there is no action specified between {...} braces, then the whole line is enclosed between braces. Hence saying \fI-e 'SAVE foo'\fR will be understood as \fI-e '{SAVE foo}'\fR, which will always match and be executed. Using the \fB\-d\fR option in conjunction with this one is a convenient way to debug a set of rules. .TP \fB\-f\fI mailfile\fR Using \fImailfile\fR as a UNIX-style mailbox (i.e. one where each mail is preceded by a special From line stating the sender and the date the message was issued), extract all its messages into the queue and process them as if they were freshly arrived from the mail delivery subsystem. .TP .B \-F Force processing on already seen messages. Usually, \fImailagent\fR enters the special \fI_SEEN_\fR state when it detects an \fIX-Filter:\fR line issued by itself, but this option will have it continue as usual (although vacation messages are disabled). Use this option when post-processing mail already filtered. Also look at the .B \-U switch if you are using the RECORD or UNIQUE actions in some rules. .TP .B \-h Print out a usage message on the standard error and exit. .TP .B \-i Interactive mode, directs mailagent to print a copy of all the log messages on \fIstderr\fR. .TP .B \-I Install a \fI~/.mailagent\fR file from template, or merge new configuration variables into an existing file; then perform sanity checks and create mandatory files or directories. This option may be viewed as an help into setting up \fImailagent\fR's environment. In any case, the created/merged \fI~/.mailagent\fR file should be manually verified before letting \fImailagent\fR deal with your mail by hooking it into \fI~/.forward\fR. .TP .B \-l List the mailagent queue. Recently queued mails which are waited for by the \fIfilter\fR are \fIskipped\fR for about half an hour, to avoid race conditions. This may be configured via the \fIqueuehold\fR variable. Really old messages (more than \fIqueuelost\fR seconds old) are flagged with a '#' character. Messages out of the queue (\fIqueue\fR variable) are flagged with a '*', whilst old messages out of the queue are signaled by an '@'. Locked messages have a '*' appended to their status. .TP .B \-L\fI level\fR Override the log level specified in the configuration file. .TP .B \-o\fI override\fR This option lets you override a specific configuration option. The option must be followed by a valid configuration line, which will be parsed after the configuration file itself. For instance, the \fI\-L 4\fR option is completely equivalent to \fI\-o 'level: 4'\fR. Note that any white space must be protected against shell interpretation by using the appropriate quoting mechanism. There may be as many \fB\-o\fR options on the command line as necessary. .TP .B \-q Force processing of mailagent's queue. Only the mails not tagged as \fIskipped\fR by the \fB\-l\fR option will be processed. .TP .B \-r\fI file\fR Specify an alternate rule file. .TP .B \-s {umaryt} Build a summary of all the statistics gathered so far. The output can be controlled by appending one or more letters from the set {umaryt}. Using \fB\-summary\fR is a convenient way to get the whole history of the filter actions. The \fBu\fR modifier will print only used rules. The \fBm\fR will merge all the statistics at the end while \fBa\fR reports the mode the filter was in when the command was executed. The \fBr\fR asks for rule-based statistics and the \fBy\fR is pretty useless and is here only to get a nice mnemonic option. Note that specifying an option more than once has no effect whatsoever on the option itself (i.e. you may put three \fBUu\fR and only one \fBm\fR, but you'll still get the summary!). The \fBt\fR letter may be followed by digits specifying how many rule file versions relative to the topmost (most recent) rule file we should extract from the statistics, that amount defaulting to 1: using \fB-surat\fR will print a complete statistics report for the last version of your rules, while \fB-surt12a\fR would do the same for the last twelve versions of those same rules. .TP .B \-t Put mailagent in a special tracking mode where all the rule matches and executed actions are printed on the standard output. This is mostly useful for debugging a rule file. See also the \fItrack\fR parameter in the configuration file. .TP .B \-V Print version number and exit. .TP .B \-U Prevent the UNIQUE and RECORD commands from rejecting an already processed Message-ID the first time they are run on a given message. This is useful when processing messages that have been dropped in the .I emergdir directory due to some abnormal (but transient) condition and you wish to reprocess the message. Also see the .B \-F switch if you are re-processing messages. .PP If you invoke mailagent without options and without any arguments, the program waits for a mail on its standard input. If an argument is provided, it is the name of a file holding one mail to be processed. This is the normal calling procedure from the filter, the argument being the location of the queued mail. ''' ''' D e f a u l t R u l e s ''' .SH "USING THE DEFAULT RULES" If you do not want to use the filtering feature of mailagent, then the default built-in rules will be used. Those are really simple: all the mails are left in your mailbox and mails with a line "Subject: Command" anywhere in the message will be processed. Commands are looked for on lines starting with "@SH". The remaining of the line is then given to a shell for execution. .PP Available commands are read from a file (entry \fIcomfile\fR in your configuration file), one command name per line. Only those listed there will be executed, others will produce an error message. The mailagent traps the exit status and will send an error report if a command fails (provided that the command does not issue a message by itself, in which case it should return a zero exit status). .PP If you do not want to use the default rules, you may skip the remaining of this section. ''' .SS "Configuring Help" .PP The help text mailagent will send to people must be copied from \fILib/mailagent/agenthelp\fR into your own spool directory, as specified in your \fI~/.mailagent\fR. Two macros may be used: .TP 10 .I =DEST= This will be expanded to the sender's address (the one who sent you the mail currently processed by mailagent). .TP .I =MAXSIZE= This stands for the maximum size set before \fIkit\fR is used to send files back (parameter \fImaxsize\fR in your \fI~/.mailagent\fR file\fR). .PP You may use the default help file or design one that will give even more details to the poor user. ''' .SS "Distribution Files" .PP The two files \fIproglist\fR and \fIdistribs\fR held in \fILib/mailagent\fR describe the distributions your mailagent will be able to distribute. The samples given show the expected syntax. In order to clarify things, here is what the format should be: .PP File \fIproglist\fR contains a small description for programs. The name of the program appears after a single star. It is followed by lines in free format. An optional three-dashes line separates each program's description. Note that a leading tab will be added to each line of description. .PP The \fIdistribs\fR file holds lines of the following form: .Ex \fIprogname version path archived compressed patches\fR .Ef where: .TP 10 .I progname is the program name (the same as the one mentioned in \fIproglist\fR). .TP .I version is the current version number. If none, a three-dashed line may be used. .TP .I path is the path where the distribution is stored. The ~ will be expanded into your home directory. Note that if the distribution is stored in archived form, the path name is the one of the archive without the ending extension (which may be \fI.cpio.Z\fR or \fI.tar.Z\fR). .TP .I archived is either \fIy\fR or \fIn\fR depending on whether the distribution is archived or not. .TP .I compressed is either \fIy\fR or \fIn\fR depending on whether the distribution is compressed or not. This could be guessed from the extension's name, but we must think of file systems with short names. .TP .I patches is \fIy\fR or \fIn\fR depending on whether the distribution is maintained or not by you. If you put a \fIp\fR, this means official patches are available, although you do not maintain the distribution. Finally, an \fIo\fR means that this is an old version, where only patches are available, but maildist will not work. In that case, assuming the version number is \fI1.0\fR, old patches are expected in a \fIbugs-1.0\fR directory. .PP You may include comments in both files: all lines starting with a leading # will be ignored. ''' .SS "Testing Your Mail Agent" .PP It is now time to make sure your mailagent works. Send yourself the following mail: .Ex Subject: Command @SH mailhelp .Ef You should receive back a mail from yourself with the subject set to: "How to use my mailagent". If you don't, check the file \fI~/.bak\fR (or whatever file you set in your \fI.forward\fR). If it is empty, look at the log file. If the log file is not empty, then perhaps the mail has been queued. Check the \fIsendmail\fR queue. Also make sure that you removed the '#' comments in the \fIfilter\fR script. On some systems, they cause some trouble. If you are using the C filter, maybe your sendmail is broken and you need to make your own setuid copy (or perl might complain that you have a kernel bug, etc...). .PP If you have done everything right but it still does not work properly, increase log level to 20 and resend your command mail. Then check the log file. The diagnosis should be easier. .PP Once this works, you should check your \fIdistribs\fR and \fIproglist\fR files by sending yourself the following mail: .Ex Subject: Command @SH maillist .Ef If the list you have in return is incorrect, then your distribution files are wrongly written. If you do not get the list, there is a problem with your mailagent's configuration. Retry with a log level set to 20 and look at the issued log messages in your Log directory. Make sure that the file listed in the \fIplsave\fR entry of your \fI~/.mailagent\fR is correctly updated after a \fImaillist\fR has been run. ''' ''' F i l t e r i n g R u l e s ''' .SH "USING THE FILTER" The \fImailagent\fR can also be used as a filter: mail is parsed and some actions are taken based on simple \fIlex\fR-like rules. Actions range from a simple saving in a folder, a forwarding to another person, or even spawning of a shell command. Before going further, here is a small example of a valid rule file: .Ex From: root { FORWARD postmaster }; To: gue@eiffel.fr { POST mail.gue }; Subject: /metaconfig/ { SAVE dist }; .Ef There are three distinct rules. Rules are applied in sequence, until one matches (so the order is important). Any mail coming from \fIroot\fR will be forwarded to user \fIpostmaster\fR. A mail addressed to \fIgue@eiffel.fr\fR is a mail coming from a mailing list. The mail is posted on a local newsgroup \fImail.gue\fR. Mails whose subject contains the word "metaconfig" will be saved in a folder \fIdist\fR for delayed reading and will not appear in the main mailbox. If no rule matched, the mail is left in the mailbox. ''' .SS "Rule File Syntax" .PP Here is a non-formal description of the rule file. Parsing of the file is done lexically, hence the choice of non-ambiguous tokens like '{' or ';' which are easily parsed. This introduces some limitations which are silently applied: for instance, no '{' may be used as part of an address. .PP Comments are introduced by a leading '#' , which must be on the left margin. Unlike shell comments, a '#' which is not left justified will not be understood as a comment. However, spaces or tabs are allowed in front of '#'. .PP All the statements in the rule file must end with a ';'. There are mainly four parts in each line. A list of comma separated modes, between '<' and '>', which give the set of modes in which the rule applies. The special mode ALL will match everything. The filter begins in the mode INITIAL. Omitting the mode defaults to "". It is possible to guard a rule against some specific mode by negating it, which is done by prefixing the mode with '!'. Negated modes take precedence other plain modes, meaning "" will never be matched, ever, and that "" is equivalent to "". .PP Then comes a list of selectors. Those selectors must be space separated and end with ':'. They represent the names of header fields which must be looked at by the forthcoming pattern. An empty selector list defaults to "Subject:". Special selectors "All:", "Body:" and "Head:" apply to the whole message, its body or its header. A commonly used selector list is "To Cc:" which tests the recipient fields of the header. If the selector name is preceded by an exclamation mark '!', then the logical value of the test for that selector is negated. .PP The list of selectors may end with an optional range specification, given as \fI\fR, before the final ':' character marking the end of the selector list. The minimum or the maximum may be given as '-', in which case it is replaced with the minimal or maximal possible value. Indices for selection begin at 1 (not 0), for instance: \fI<3, 7>\fR. If no range selection is given, then the default \fI<1, ->\fR is used. Ranges normally select lines within the matching buffer, unless the selector is expecting a list in which case it operates on the list items. For instance, \fIBody <3, 5>:\fR would select lines #3 to #5 (included) from the mail body, whereas \fITo Cc <1,3>:\fR would focus on the first three addresses on each To: or Cc: header lines. Negative values refer to that many lines or addresses back from the end, i.e. \fICc <-2,->:\fR selects the last two addresses on the Cc: line. A single number such as \fI<2>\fR is understood as \fI<2, 2>\fR, i.e. it select only one item in the list, \fI<->\fR meaning everything (and being therefore redundant). .PP The selector is then followed by a pattern within '/' or by a single name. In order to ease the writing of the rules, the semantic of a single name varies depending on the selector used. For the special selectors "From:", "To:", "Cc:", "Sender:", their associated "Resent-" fields, "Reply-To:", "Envelope:" and "Apparently-To:", a single name is understood as a match on the \fIlogin name\fR of the address. Note that if no "To:" field is present in the header, one will be forged from the "Apparently-To:" for the purpose of filtering only (i.e. no physical modification on the header is done). If the login name of the address is a full name of the form First.Last, only the last name is kept, and is lower-cased. If only a single name is given, only shell metacharacters * and ? are allowed, as well as intervals []. .PP If the pattern is preceded by a single exclamation mark '!', then the matching status is negated (i.e. it will succeed if the pattern is not found). If a single word is used for non-special selectors, the same rules apply but the pattern is anchored at the beginning and the end for an exact match. With a pattern starting with '/', any regular expression understood by \fIperl\fR may be used and your pattern will not be modified in any way. The other special selector "Newsgroups:" works as "To:", excepted that newsgroups names are expected and a match is attempted on every item in the list. Every pattern match on a single name for an address-type field (i.e. "Newsgroups:" excluded), are made in case-insensitive mode. Otherwise, you can force a case-insensitive match by appending a trailing \fIi\fR option, as in \fI/pattern/i\fR. .PP There is also a little magic involved when matching on an address field. Namely, if the pattern is not a single word and is \fIanchored at the beginning\fR, then only the address part of the field will be kept. For instance, if we have a From: field whose value is \fIRaphael Manfredi \fR, then the pattern \fI/Raphael/\fR would match, but not \fI/^Raphael/\fR. Instead, \fI/^ram@.*$/\fR would match, but this is more easily done with a single word pattern \fIram\fR, for it only focuses on the login name of the address and would also match if the address was written as \fIeiffel.com!ram\fR. A single address in Internet form, as in \fIram@eiffel.com\fR is implicitely matching on the address part of the field, and you must not escape the '.' as you would have to in a regular expression. .PP This may sound a little complex, but this design is meant to make things easier for the user. Here are some other examples: .Ex # Match \fIram@eiffel.com\fR as well as \fIram@educ.emse.fr\fR. From: ram # Match \fIroot@eiffel.com\fR, \fIram\fR but not \fIribbon@eiffel.com\fR From: r[oa]* # Match \fIgue@eiffel.fr\fR but not \fIalgue@eiffel.fr\fR To Cc: /^gue@eiffel\\\\.fr/ # This will match \fIgue@eiffel.fr\fR as well as \fIalgue@eiffel.com\fR To Cc: /gue@eiffel/ # Match \fIcomp.lang.perl\fR but not \fIcomp.lang.perl.poetry\fR (?) Newsgroups: comp.lang.perl # Accept anything but messages coming from \fIroot\fR From: !root .Ef When attempting a match on "To:", "Cc:" or "Apparently-To:", a list of addresses separated by a comma is expected, whereas only one address is expected after "From:". If you omit the pattern, it will be understood as * (recall that a single word uses shell meta-characters), which will match anything. .PP Then comes the action to be taken when a match occurs. There are only a limited set of valid actions which will be described soon in detail. The action is enclosed in curly braces '{' and '}' and actions are separated or terminated (depending on your taste) by a ';'. Action names are spelled in upper-case for readability, but case is irrelevant. If you want to put a ';' within the rule, it must be escaped by preceding it with a backslash. A double backslash is translated into a single one, and any other escape sequence involving the backslash character is ignored (i.e. \\\\n would be kept verbatim). .PP Note that a rule should be ended by a single ';' after the last '}'. It is possible to omit this final ';', but that single token is the re-synchronizing point for error recovery. One could argue however that there should be no syntax error, and thus the ';' ought to be safely omitted. Whenever in doubt, check your rule file with the \fB\-d\fR option. .PP Here is a prototypical rule (using \fIperl\fR regular expressions; please refer to the subsection \fBRegular Expressions\fR for more information): .Ex From: /^\\\\w+@eiffel.com$/ { SAVE eiffel }; .Ef That rule will only be taken into account when the filter is in the mode ROOT (recall that the processing starts in mode INITIAL; use BEGIN to change the mode, as in \fIlex\fR). So in mode ROOT, anything which comes from a user located in the \fIeiffel.com\fR site is saved in folder \fIeiffel\fR for deferred reading. The mail will not appear in the mailbox. .PP It is possible to have more than one selection for a rule. Identical selectors are logically \fIor\fR'ed while different ones are \fIand\fR'ed. The selections are comma separated. For instance, .Ex From: root, To: ram, From: ram, Subject: /\\\\btest\\\\b/ { DELETE }; .Ef will delete a mail from \fIroot\fR or \fIram\fR if it is sent to \fIram\fR and has the word \fItest\fR in its subject. It is also possible to write the previous rule as: .Ex From: root, ram, To: ram, Subject: /\\\\btest\\\\b/ { DELETE }; .Ef because if no selector is given, the previous one is used (with the first selector being "Subject:" by default). .PP Anywhere in the rule file, it is possible to define some variables. The list of recognized variables is given later. For now, let's say that \fImaildir\fR is the default folder directory. This variable is used by the SAVE command when the argument is not an absolute path. Setting .Ex maildir = ~/mail; .Ef will direct the filter to use \fI~/mail\fR as the folder directory (default is \fI~/Mail\fR). Note the ~ substitution and the final ';'. It is not possible (currently) to modify the environment by setting PATH for instance. .PP Finally, there is a special construct to load patterns from a file. A pattern enclosed in double quotes means that the patterns to be applied should be taken from the specified file. The file is expected to be in the directory \fImailfilter\fR if it is not an absolute path (~ substitution occurs). If the variable is not set \fImaildir\fR will be used. If by chance (!) \fImaildir\fR is not set either, the home directory is used. The file should contain one pattern per line, shell comments (#) being allowed at the beginning of each line. .PP An action may be followed by other rules. Hence the following is perfectly valid: .Ex From: ram { SAVE ram } /plc/i { SAVE plc } root { SAVE ~/admin } /xyz/ { DELETE } "users" { LEAVE } ; .Ef Note the use of the file inclusion: all the users listed in file \fIusers\fR will have their mail left in the system mailbox. The usual rules apply for these loaded patterns. ''' .SS "Selector Combination" .PP A single rule may have a various set of selectors. For instance, in the following rule: .Ex From: ram, To Cc: root, !Subject: /test/, From: raphael .Ef we have the following set { From, To Cc, !Subject }. The first two selectors are called \fIdirect\fR selectors, !Subject: is called a \fInegated\fR selector. The To Cc: selector is a \fIgroup\fR selector decomposing into two \fIdirect\fR selectors, while From: is an \fIatomic\fR selector. Finally, From: is also a selector with \fImultiple\fR occurrences. The \fIvalue\fR of a selector is its matching status logical value. .PP Let \fID\fR be the set of direct selectors and \fIN\fR the set of negated selectors, which form a partition of \fIR\fR, the set of all the selectors in the rule. That is to say, \fIR\fR is the union of \fID\fR and \fIN\fR, and \fID\fR intersected with \fIN\fR is the empty set (trivial proof: a selector is either direct or negated). If either \fID\fR or \fIN\fR is empty, then it's not a partition but in that case we have either \fID\fR = \fIR\fR or else \fIN\fR = \fIR\fR. .PP Let's define the logical value of a set \fIS\fR as being the logical value the filter would return if those rules were actually written. Then the logical value of \fID\fR is the logical value of each of its item with the AND logical operator distributed among them, i.e. the logical value of { a, b, c } is the value of (a AND b AND c). Let's write it AND(\fID\fR). The logical value of each of the items is the logical value of the selector itself if it is not multiple, or it is the logical value of all the occurrences of the multiple selector within the rule, with the logical OR operation distributed among them. That is to say, in the above example, the value of From is true iff the From: fields contains \fIram\fR OR \fIraphael\fR. Let's write that OR[From]. .PP To be sound, we have to apply De Morgan's Law on \fIN\fR, hence the following rules: the logical value of \fIN\fR is OR(\fIN\fR) and given a negated selector \fIs\fR, its logical value is AND[\fIs\fR]. And finally, the logical value of \fIR\fR is that of \fID\fR AND \fIN\fR, with by convention having the logical value of the empty set be \fItrue\fR. .PP For those who do not know De Morgan's Law, here it is: given two logical propositions \fIp\fR and \fIq\fR, then the following identities occur: .Ex NOT (p AND q) <=> (NOT p) OR (NOT q) NOT (p OR q) <=> (NOT p) AND (NOT q) .Ef While we are in the logic of the propositions, note also that OR and AND are mutually distributive, that is to say, given three logical propositions \fIp\fR, \fIq\fR and \fIr\fR, we have: .Ex p AND (q OR r) <=> (p AND q) OR (p AND r) p OR (q AND r) <=> (p OR q) AND (p OR r) .Ef To be complete, OR and AND are associative with themselves and commutative. And the \fIB\fR set { 0, 1 } equipped with the set of operations (NOT, OR, AND) is an \fIalgebra\fR (a Boolean one). I will spare you the definition of an algebra, which really has nothing to do in this manual page (which is for a mail agent, in case you don't remember :-). .PP The attentive reader will certainly have noted that I have not specified the logical value of a group selector. Well, given a group selector \fIG\fR, we decompose it into a \fIDG\fR and \fING\fR partition, \fIDG\fR being the subset of (atomic) direct selectors of \fIG\fR and \fING\fR being the subset of (atomic) negated selectors. Then the logical value of \fIDG\fR is OR(\fIDG\fR) and the logical value of \fING\fR is AND(\fING\fR); the global logical value of \fIG\fR being that of \fIDG\fR OR \fING\fR. In case either \fIDG\fR or \fING\fR is empty, then we don't have a partition, but by convention the value of the empty set is \fIfalse\fR, and one of the sets is equal to \fIG\fR. Note that within a group selector, the rules are exactly the dual of the rules within \fIR\fR. .PP Now the only rule which is not \fIlogical\fR is whether a group selector belongs to \fID\fR or \fIN\fR. I've chosen, for analogy reasons, to make the group selector belong to \fID\fR if it does not start by '!' and to \fIN\fR otherwise. That is, !To Cc: belongs to \fIN\fR whilst Cc !To: belongs to \fID\fR. Apart from that, order within the group selector is irrelevant: To Cc: is equivalent to Cc To:, so the behavior in the quotient set is sound. .PP Here are some examples: .Ex # Match anything: (not from ram OR not from root) is always true. From: !ram, !root # Match anything but reject mails coming from ram OR root !From: ram, root # Reject mails whose headers matching /^Re.*/ contain the word test !^Re.*: /\\\\btest\\\\b/ # Keep mails whose subject contains \fItest\fR AND \fIhost\fR !Subject: !/test/, !/host/ # Matches if \fIram\fR is listed in the \fITo\fR OR the \fICc\fR line To Cc: ram .Ef ''' .SS "Minimal Header" .PP A minimal set of selectors are guaranteed to be set, regardless of the actual header of the message. This is for the purpose of filtering only, no physical alteration is performed. .sp .PD 0 .TP 10 .I Envelope: This is the address found in the mail envelope, i.e. the address where the mail seems to originate from. This can be different from the \fIFrom:\fR address field if the mail originates from a \fItrusted\fR user, in sendmail's terminology. If you don't know what that is, simply ignore it. .TP .I From: User who wrote the mail. If this line is missing, uses the address found in the first From line. .TP .I Length: The physical length of the body, in bytes, once content-transfer-encoding (if any) has been removed. .TP .I Lines: The amount of lines in the body (decoded, if necessary). .TP .I To: The main recipient(s) of the message. If this line is missing but a set of \fIApparently-To:\fR lines is found, then those addresses are used instead. If no such line exists, then assume the mail was directed to the user (which seems a reasonable assumption :-). .TP .I Sender: User who sent the mail. This may differ from the \fIFrom:\fR line. If no such field exists, then the address in the first From line is used (mail envelope). .TP .I Relayed: This computed header is a comma-separated list of all the hosts where the message was relayed, in the proper transmission order. Each item in this list can be a machine name such as \fImail.hp.com\fR or an IP address such as \fI[15.125.38.12]\fR. The list is derived from the \fIReceived:\fR lines present in the message. .TP .I Reply-To: Where any reply should be sent. If no \fIReply-To:\fR field is present, then the \fIReturn-Path\fR is used (with <> stripped out), or the \fIFrom:\fR line is parsed to extract the e-mail address of the author. .PD ''' .SS "Variables" .PP The mailagent supports user-defined variables, which are globals. They are set via the ASSIGN command and referred to with the %# macro. Assuming we set a variable \fIhost\fR, then %#\fIhost\fR would be replaced by the actual value of the variable. This enables some variable propagation across the rules. .PP For example, let's say the user receives cron outputs from various machines and wishes to save them on a per-machine basis, differentiating between daily outputs and weekly ones. Here is a solution: .Ex Subject: /output for host (\\\\w+)/ { ASSIGN host '%1'; REJECT }; Subject: /^Daily output/ { SAVE %#host/daily.%D }; Subject: /^Weekly output/ { SAVE %#host/weekly.%m-%d }; .Ef Besides variable interpolation via the %# escape, it is also possible to perform substitutions and translations on the content of a variable (or a back-reference, i.e. a number between 1 and 99). The two commands SUBST and TR will respectively perform in-place substitutions and translations. In that case however, the name of the variable must be preceded by a single #. This differentiates the back-reference \fI1\fR from the variable \fI#1\fR, although \fI1\fR is a funny name for a variable. The need for # also prevents the common mistake of writing %#, as mailagent will loudly complain if the first parameter of SUBST or TR is not a digit between 1 and 99 or does not start with a #. .PP Here are some actions to canonicalize the host name into lower case and strip down the domain name, if any: .Ex { TR #host /A-Z/a-z/; SUBST #host /^([^.]*)\\\\..*/\$1/ }; .Ef Those actions are directly translated into their \fIperl\fR equivalent, and any error in the specification of the regular expression will be reported. .PP If the variable name begins with a colon ':', then the variable is made persistent. That is to say it will keep its value across different mailagent invocations. The variable is simply stored (with the leading ':' removed) in mailagent's database and is thus subject to the aging policy set up in the ~/.mailagent. .PP Within PERL commands or mail hooks using perl (see the MAIL HOOKS section), you can manipulate those (so-called) external variables via a set of interface functions located in the \fIextern\fR package (i.e. you must prefix each of the function name with its package name, \fIset\fR becoming \fIextern'set\fR). The following three interface functions are provided: .PD .TP 10 val(name) Return the value of the variable \fIname\fR (the leading ':' is not part of the name, in any of these three interface functions). .TP set(name, value) Set the external variable \fIname\fR to hold \fIvalue\fR. No interpretation is done by the function on the actual content of the \fIvalue\fR you are providing. .TP age(name) Returns the age of the variable, i.e. the elapsed time in seconds since the last modification made by \fIset\fR. .PP There is currently no way for erasing a variable from the database. But if you do not use the variable any more, it will be removed when its age becomes greater than the maximum age specified by the \fIagemax\fR configuration variable. ''' .SS "Regular Expressions" .PP All the regular expressions follow the V8 syntax, as in \fIperl\fR, with all the \fIperl\fR extensions. If a bracketing construct (...) is used inside a rule, then the %\fIdigit\fR macro matches the \fIdigit\fR's substring held inside the bracket. All those back-references are memorized on a per-rule basis, numbered from left to right. However, great care must be taken when using a back-reference in multiply present selectors, as all the matches will be performed up-to the first match, and back-references are computed on the fly while doing pattern matching. .PP For instance: .Ex To: /(.*)/, Subject: /Output from (\\\\w+)/ { ASSIGN to '%1'; SAVE %2 }; .Ef will save the To: field in variable 'to' and save the mail in a folder derived from the host name specified in the subject. However, if we say: .Ex Subject: /host (\\\\w+)/, /from (\\\\w+)/ { ASSIGN match '%1' }; .Ef then there will be only one back-reference set, and it will come from the first pattern matching if it succeeds, or from the second. Should the second or the first pattern have no bracketing construct and still match, then the back-reference would not be recorded at all, which means the following is probably not what you want: .Ex Subject: /from/, /host (\\\\w+)/, To: /(.*)/ { SAVE %1; REJECT }; .Ef as if the /from/ pattern matches then /host (\\\\w+)/ will not be checked (identical selectors are \fIor\fR'ed and that is optimized), then %1 would refer to the To: field whereas if /host (\\\\w+)/ matches, then %1 will be the host name. .PP However, this behavior can be used to selectively store a news article which has been mailed to you in a folder whose name is the newsgroup name in dot form. Assuming we want to give priority to comp.lang.perl, we could say: .Ex Newsgroups: /(comp.lang.perl)/, /(comp.mail.mh)/, /(comp.compilers)/, /([^,]*)/ { SAVE %1 }; .Ef An article cross-posted to both comp.lang.perl and comp.mail.mh would be saved in a comp.lang.perl folder, since this is what would match first. The last rules takes care of other articles: the folder used being whatever newsgroup appears first. .PP There is also a special macro %&, which lists (it's a comma separated list) all the selectors specified via a regular expression which indeed matched. For instance: .Ex Re.*: /york/ { ASSIGN which '%&' }; .Ef would assign to \fIwhich\fR the list of all the fields matching the /Re.*/ pattern which contained 'york', be it a Received: field or a Resent-From: field (as both match the selector specification). Assuming both those fields contained the word \fIyork\fR, the value of %& would be 'Received,Resent-From;' (the fields are alphabetically sorted). .PP Should you have more than one such specified selector within a single rule, then it might be worth knowing that all the set of matching selectors are recorded within %&, each set terminated with a ';'. If a negated selector is used, then %& will record all the fields which did not contain the pattern, assuming the selection succeeded (otherwise nothing is recorded). ''' .SS "Available Actions" .PP The following actions are available as filtering commands. Case is irrelevant although the recommended style is to spell them upper-cased. As explained later, most of the actions record their exit status in a special variable which may be tested via the \fB\-t\fR and \fB\-f\fR options of ABORT, REJECT and RESTART. For every command returning such an exit status, the failure or success conditions are given at the end of each description. If nothing is specified, then the command does not return a meaningful status. .TP 10 ABORT [\fB\-tf\fR] [\fImode\fR] Abort application of filtering rules immediately. See REJECT for the meaning of the optional parameters. (Does not modify existing status) .TP AFTER [\fB\-sanc\fR] \fI(time) action\fR Records a callback for after the specified \fItime\fR, where \fIaction\fR will be performed. By default, a mailagent filtering action is assumed (\fB\-a\fR option), on the current mail message. A shell command (\fB\-c\fR) may be given instead, receiving the current mail message as standard input. Finally, a plain shell command may be run (with no input) using the \fB\-s\fR option. The option \fB-n\fR may be used when the current mail message does not need to be kept for input. For instance: .Ex AFTER \fB\-an\fR (1 day) DO ~/process:proc'run(%u) .Ef would call \fIproc'run\fR defined in the \fI~/process\fR file in one day from now, without giving any input (the action here does not require any). .sp When running mailagent commands, the initial working mode is set to _CALLOUT_. This may matter if you call APPLY for instance. If the recorded time is less or equal than the current time (which is \fInow\fR), the callback will occur when mailagent is done with the messages in its queue, before exiting. This allows for the following cute trick, found out by Randal Schwartz: .Ex AFTER (now) # fork a copy I can mangle STRIP Reply-To \\\\; RESYNC \\\\; ANNOTATE -du Reply-To %2 \\\\; RESYNC \\\\; NOTIFY message %r \\\\; DELETE \\\\; ; .Ef Note that the command is not called \fIAT\fR because the call will only be performed at the next mailagent invocation after the specified time has elapsed. Dates are specified using the same format as in SELECT. (Fails if the action cannot be recorded in the callout queue). .TP ANNOTATE [\fB\-du\fR] \fIfield value\fR Annotate message by adding \fIfield\fR into the mail header, with the supplied \fIvalue\fR. This is like the MH command \fIanno\fR, but the annotation is performed at the end of the header, whereas MH does it at the top. Normally, an extra \fIfield\fR is added, with the current date as field value. .sp This can be suppressed by using the \fB\-d\fR option. If \fIvalue\fR is omitted, only the date field is generated (hence it is an error to use the \fB\-d\fR option without supplying a \fIvalue\fR). As with all the commands which alter the header, a RESYNC is necessary for the filter part to actually see the new header. .sp The \fB\-u\fR option means "unique", and prevents ANNOTATE from executing if the specified \fIfield\fR is already present in the header. Don't forget to RESYNC between successive ANNOTATE commands using this option if the \fIfield\fR refers to a previous ANNOTATE target. (Fails when no annotation takes place) .TP APPLY \fIrulefile\fR Get the rules held in \fIrulefile\fR and apply them to the current message. The filter will begin in whatever mode you were when using this command, but no feed back will occur, i.e. any mode changing will be lost when returning from the command. .sp Variables (see the %# macro) are propagated back and forth through APPLY, meaning you see variables set by the caller, and you may change their values or create new variables for the caller to later use. .sp If mail is saved during the application of the rules, then the corresponding flag is set in the main filter (the one that started the APPLY command). You may nest them, of course. (Fails if mail is not saved by the rules held in \fIrulefile\fR) .TP ASSIGN \fIvar value\fR Assign the value to the user-defined variable \fIvar\fR, which may further be accessed as \fI%#var\fR for macro substitution or \fI#var\fR in the TR and SUBST commands in place of the variable name. Note that there is no leading \fI#\fR in front of the variable name. The \fIvalue\fR you provide is first ran through \fIperl\fR to see if it contains some arithmetic operations. If the evaluation is successful, the resulting value is used instead. If an error occurs in this evaluation process, then the literal value provided is used. To avoid the evaluation, you may enclose the whole value in simple quotes. Those will be trimmed before the assignment takes place. If you actually want simple quotes in the first AND last position, you have to double each of them. (Does not modify existing status) .TP BACK \fIcommand\fR Execute \fIcommand\fR and take its output as new actions to be performed on the mail (hence performing something analogous to \fI\`command\`\fR in shell). If there is no output, nothing is done. BACK commands can be nested, although this may lead to surprises this manpage will not disclose (but I assure you it will be funny, assuming we have the same sense of humor... :-). Note that both the standard output and the standard error from the command are used. .sp If the command fails, the output is mailed back to the user and no action is performed. Furthermore, normal feedback does not occur here: any output from the command is taken as filter actions, which means the semantics of PASS, for instance, is changed: we do not take a body back but commands. (The execution status is that of the \fIcommand\fR) .TP BEEP [\fB\-l\fR] \fIcount\fR This command may be used to tune the amount of beeps emitted when biffing on the terminal, for each \fI%a\fR expansion. By default, that amount is set to 1. Using the \fB\-l\fR option alters the beep count locally for the rule. Otherwise, the default amount is changed. .sp Note that this simply expands %a into the suitable amount of Ctrl-G characters. Your terminal must be allowed to issue consecutive bells for this to work. Very often, terminals are configured so that the first bell received disables further beeps for some period, to avoid cascades of bells. If you use \fIxterm\fR for instance, you should use: .Ex xterm -xrm "XTerm*BellSuppressTime: 0" .Ef to enable consecutive bells. Otherwise, \fIxterm\fR will swallow them during 200 ms, hence making the BEEP command ineffective, apparently. (Does not modify existing status) .TP BEGIN [\fB\-ft\fR] \fIstate\fR Enter a new state. An explicit REJECT or RESTART is necessary to abort the processing of the current rule. The processing begins in the state INITIAL. If the \fB\-f\fR (resp. \fB\-t\fR) flag is specified, then the state change only occurs if the last command status indicated a failure (resp. a success). A state name can contain alphanumeric characters and underscores. (Does not modify existing status) .TP BIFF [\fB\-l\fR] \fIon|off|path\fR Allow or disallow biffing dynamically. When biffing is turned on via the configuration file or via this command, a message is printed on some of the terminals where the user is logged when mail is received, as explained under the section \fBMAIL BIFFING\fR. .sp Instead of \fIon\fR or \fIoff\fR, you can specify a file name (~ substitution allowed) being the new path to be used for the biffing format template. .sp If you use the \fB\-l\fR option, changes are made locally, for the duration of the rule only. If you REJECT to go to some other rule, your changes will be lost. The global value of the altered parameters is changed on the first local usage and restored when a new rule is entered. (Does not alter execution status) .TP BOUNCE \fIaddress(es)\fR Bounce the message to the specified address(es) and acts as if a save had been done. The only difference with FORWARD is that no Resent-like lines are added to the header. If an address is specified in double quotes, it is taken as the name of a file to be loaded to get addresses (one address per line, shell comments (#) allowed). The file name resolving is the same as the one used for pattern loading. (Fails if mail cannot be resent) .TP DO \fIroutine\fR [\fI(arg1, arg2, ... , argn)\fR] Calls the perl \fIroutine\fR, with the supplied arguments if any. This is a very low level hook into \fImailagent's\fR internal. The routine can be specified by itself (\fIpackage'name\fR, \fIpackage\fR being \fImain\fR by default), or identified by a leading \fItag\fR, followed by a ':', then the routine name as before. The \fItag\fR can be a path to a file where the routine is defined, or a command name (for user-defined commands which are loaded dynamically). For instance .Ex DO UNKIT:newcmd'unkit('true') .Ef would lookup the user-defined \fIUNKIT\fR command, load the file where it is defined (in the \fInewcmd\fR package), then call the routine with \fI'true'\fR as argument. The \fIpackage\fR specified determines where the loading is done, so be sure it is consistent with the definition in the file where the routine is defined. (Fails if the routine cannot be located and executed) .TP DELETE Delete the current message. Actually, this does not do anything, it just marks the mail as saved. If no further action involving saving is done, then the mail will never show up in the mailbox. (Never fails) .TP FEED [\fB-be\fR] \fIprogram\fR Feed the whole message to a program and get the output back as the new message. Hence the program appears as a filter for the whole message. It does not tag the message as having been saved. A RESYNC is automatically done upon return. (Returns the status of \fIprogram\fR) .sp .B WARNING: Your program must be able to properly parse a MIME message and must deal with transfer-encoded bodies by itself. To make the program task simpler, you can supply the .B -b switch wich will let mailagent decode the whole body for you, suppressing any Content-Transfer-Encoding header (implying "binary"). This is an invalid message format for sending the message, but it makes processing easier. You still have to parse the MIME parts yourself though. .sp Using .B -b does not prevent your program from outputing a valid message back, one that can be possibly sent on the network so you have two options: either you do not supply any Content-Transfer-Encoding in the headers, and mailagent will recode the body for you using the initial transfer encoding present in the message (a relatively safe option if you make only changes in the body at well-defined spots without introducing 8-bit chars), or you can supply the Content-Transfer-Encoding yourself and perform the body encoding manually. .sp To be completely safe and minimize the work in your program, the .B -e switch will let mailagent analyse the message body you are returning and select the proper transfer encoding automatically. Since this will cause the whole body to be analysed, and it can be potentially huge, that behaviour must be explicitly asked for. If you need .B -e then you probably want .B -b as well (you can supply both by saying .B -be naturally). .sp If you do not supply any switch, mailagent will give you the message as-is and will get your message as-is without any additional magic. .TP FORWARD \fIaddress(es)\fR Forward mail to the specified address(es). This acts as if a save had been done, in order to avoid the DELETE. Usually when you forward a mail, you do not wish to keep it. The command adds Resent-like lines in the header. As for BOUNCE, file inclusion is possible (i.e. use an address \fI"forward_list"\fR to forward a mail to all the users listed in the file \fIforward_list\fR). (Fails if mail cannot be resent) .TP GIVE \fIprogram\fR Give the body of the message to the specified program by feeding its standard input. Any output is mailed to the user who runs the \fImailagent\fR. Note that the message is not tagged as having been saved. (Returns the status of \fIprogram\fR) .sp .B NOTE: If the message had a body that was encoded for transport (using one of the base64 or quoted-printable transfer encoding), mailagent will transparently decode it and supply a version that can be properly handled. In other words, the program does not need to care about the body being encoded in the message, as it will get a plain one. (Since no headers are supplied, this is the only possible option). .sp Caution though for MIME messages: you should use PIPE for them to give a chance to the program to properly handle the body, but then it needs to be fully MIME-aware. .TP KEEP \fIheader_fields_list\fR Keeps only the corresponding lines in the header of the mail. For instance, a "KEEP From To Cc Subject" will keep only the principal fields from the mail message. This is suitable for archiving mailing lists messages. You may add a ':' after each header field name if you wish, but that is not strictly necessary. Headers may be specified using shell-style regular expressions, and file inclusion is allowed to get headers from a file. (Does not modify existing status) .TP LEAVE Leave incoming mail in the system mailbox. This is the default action if no rule matched or if no saving occurred. (Fails if mail cannot be saved) .TP MACRO [\fB\-rdp\fR] \fIname\fR [= (\fIvalue\fR, \fItype\fR)] Lets you specify user-defined macros, of the form %-(\fIname\fR). See the paragraph on user-defined macros for explanation about the available types (SCALAR, EXPR, CONST, FN, PROG, PROGC). A perl interface to the underlying user macros is available for your perl commands. The \fB\-r\fR option is used to replace an existing macro (instead of pushing a new instance on the stack), the \fB\-d\fR is to delete all the instances of a named macro (in that case it takes only the first argument), and \fB\-p\fR pops the last instance of the macro from the stack and reverts to the previous definition, if any (otherwise, it acts as \fB\-d\fR). If you wish to define a simple SCALAR macro, you may omit the \fI= (value, type)\fR part and simply continue with the macro value. (Does not modify existing status) .TP MESSAGE \fIfile\fR Send message \fIfile\fR back to the sender of the message (as derived from the header of the message). The text of the message is run through the macro substitution mechanism (described later on). (Fails if message cannot be sent) .TP NOP [\fB\-ft\fR] No operation. If this seems a bit odd, think of it in terms of a ONCE command. (Does not alter existing status unless \fB\-f\fR or \fB\-t\fR is used, in which case it forces a \fIfalse\fR \-\-failure\-\- or \fItrue\fR success status) .TP NOTIFY \fIfile\fR \fIaddress(es)\fR Send a notification message \fIfile\fR to a given address list. The text of the message is run through the macro substitution mechanism (described later on). As with FORWARD, file inclusion for address specification is possible. (Fails if message cannot be sent) .TP ON \fI(day list) command\fR Execute the specified filter command only on the specified day list. That list is a space-separated list of days, specified using the English names. Only the first three characters are taken into account, case-insensitively. Therefore, the shortest valid day specifications are \fIMon, Tue, Wed, Thu, Fri, Sat\fR and \fISun\fR. .sp This command can be used in conjunction with SELECT to do time-based selective bouncing of messages to, for instance, your home address: .Ex ON (Mon Tue Wed Thu) SELECT (18:30 .. 23:00) BOUNCE me@home.net; ON (Fri) SELECT (18:30 .. 23:59) BOUNCE me@home.net; ON (Sat Sun) BOUNCE me@home.net; .Ef That would bounce messages only on week-ends and during the week, after 18:30, and until 23:00 (assuming that's bed time, other messages will be seen at work the next day). Note that on Fridays, we go as far as 23:59. (Propagates status from \fIcommand\fR. If the command is not executed, always return success) .TP ONCE \fI(name, tag, period) command\fR Execute the specified filter command once per \fIperiod\fR. The \fIname\fR and \fItag\fR fields are used to record timestamps of the last ONCE command. More on this later. (Propagates status from \fIcommand\fR. If the command is not executed, always return success) .TP PASS \fIprogram\fR Feed the body of the message to the specified program and get a new body back from the output of the program. Note that the message is not tagged as having been saved. (Returns the status of \fIprogram\fR) .sp .B NOTE: If the message had a body that was encoded for transport (using one of the base64 or quoted-printable transfer encoding), mailagent will transparently decode it and supply a version that can be properly handled. The body generated by the program will then be automatically encoded back using the same transfer encoding. .sp Caution though for MIME messages: you should use FEED for them to give a chance to the program to properly handle the body, but then it needs to be fully MIME-aware. .TP PERL \fIscript\fR [\fIarguments\fR] Escape to a perl \fIscript\fR to perform some actions on the message. This is fully described further in the manpage, and is very different from a \fIRUN perl script\fR command. (Returns failure if the script did not compile or returned a non-zero status). .TP PIPE [\fB-b\fR] \fIprogram\fR Pipe the whole message to the specified program, but do not get anything back. Any output is mailed to the user who runs the \fImailagent\fR. The message is not tagged as having been saved in any case, so you must explicitly DELETE it if piping was enough and it did not fail: "REJECT -f" is your friend here to avoid unwanted deletion. (Returns the status of \fIprogram\fR) .sp .B WARNING: Your program must be able to properly parse a MIME message and must deal with transfer-encoded bodies by itself. To make the program task simpler, you can supply the .B -b switch wich will let mailagent decode the whole body for you, suppressing any Content-Transfer-Encoding header (implying "binary"). This is an invalid message format for sending the message, but it makes processing easier. You still have to parse the MIME parts yourself though. .TP POST [\fB\-lb\fR] \fInewsgroup(s)\fR Post the message to the specified newsgroup(s) after having cleaned-up the header: mail-related fields like Received: or In-Reply-To: are removed, a valid From: line is generated, the original To: and Cc: are renamed with an X- prefix, the References: line is updated/generated if necessary based on existing In-Reply-To, and NNTP-specific fields are stripped so that the server can add its own. .sp Running POST successfully acts as a saving. .sp If the first name is \fB\-l\fR as in "POST -l comp.mail.mh", then a "Distribution: local" header is added to force a local delivery. Otherwise, the default \fIinews\fR distribution will be used (world, usually). .sp When the \fB-b\fR switch is given, a successful POST will result in biffing being activated (see section \fBMAIL BIFFING\fR) for the resulting news article. .sp If more than one newsgroup is specified, they should be space separated. It is possible to get a newsgroup list via file inclusion. (Fails if message cannot be posted) .TP PROCESS Run the mailagent processing which looks for @SH commands and executes them. This was described before in the section dealing with default rules. The action associated by default to a mail having [Cc]ommand as its subject is PROCESS. (Always returns success) .TP PROTECT [\fB\-lu\fR] \fImode\fR Sets the default protection mode that should be set on created folders (or created files when saving into an MH folder or a directory). By default, permissions are governed by the UMASK command, but this lets you override the default. The specified \fImode\fR should be preceded by a \fB0\fR as in \fI0644\fR to give the familiar octal permissions. Otherwise, it is interpreted as a decimal number, so beware! .sp The \fB\-l\fR option may be used to specify a mode locally for one rule. Otherwise, the protection mode is set globally. The \fB\-u\fR option unsets the global (or local when combined with \fB-l\fR) mode, reverting to the default behaviour where only the umask is taken into account by the system. .sp Note that when saving into an MH folder, the PROTECT command takes precedence over the \fIMsg-Protect\fR field from your ~/.mh_profile file. (Does not alter execution status) .TP PURIFY \fIprogram\fR Feed the header into a program and get new header back. RESYNC is done automatically upon return. This may be used to indeed purify the header by removing all the verbose stuff added by so many mail transport agents (X-400 like lines for instance). Obviously, this does not flag the message as having been saved. (Returns the status of \fIprogram\fR) .sp If your program removes the Content-Transfer-Encoding header in a MIME message, mailagent will properly transform the message to have a non-encoded body. If you change the value of the Content-Transfer-Encoding header, mailagent will also correctly recode the body for you. The only supported encodings are base64 and quoted-printable. .TP QUEUE Queue mail again. A successful queuing counts as if mail has been saved. Mail queued that way will not be processed during the next 30 minutes. Note that unless mailagent is invoked on a regular basis by \fIcron\fR, the mail will remain in the queue until another mail arrives. (Fails when mail cannot be queued) .TP RECORD [\fB\-acr\fR] [\fIstate\fR] [\fI(tag-list)\fR] Record message in the history and enters state _SEEN_ if the message was already present there. If the message is recorded for the first time, processing continues normally. Otherwise a REJECT is performed. This behavior may be somewhat modified by using some options. See UNIQUE for a complete description of the options and arguments. Naturally, when a \fIstate\fR is specified, that overrides the default _SEEN_. A state name can contain alphanumeric characters and underscores. .sp When a \fItag-list\fR (comma-separated list of names) is specified, the message is only recorded and checked against all those tags, but only them. Not specifying any tag list means any occurrence, whether it is tagged or not. See paragraph \fBUsing Tags in Record and Unique\fR for more information. (Returns a failure status if mail was already recorded) .TP REJECT [\fB\-tf\fR] [\fIstate\fR] Abort execution of current action, and continue matching. If \fB\-t\fR is specified, the reject will occur only if the previous action was successfully completed (return status of true), whilst \fB\-f\fR would cause the reject only when a failure occurred. If a \fIstate\fR is specified, we enter that state before rejection. REJECT resets the matching flag, which means that if no further match occurs, the default action will apply. A state name can contain alphanumeric characters and underscores. (Does not alter execution status) .TP REQUIRE \fIfile\fR [\fIpackage\fR] Behaves like the perl \fIrequire\fR operator by loading a perl file into memory. By default, the file is read in the \fInewcmd\fR package, but you may specify whatever package you wish to load it in. This command will only perform the loading once per (file, package) tuple. Unlike its perl equivalent, the file "value" is not important, i.e. it does not have to end with a statement returning a true value. (Fails if file cannot be loaded) .TP RESTART [\fB\-tf\fR] [\fIstate\fR] Abort execution of current action and restart the matching process from the beginning. To avoid loops, each rule may be walked through once in a given state. See REJECT for the meaning of the optional parameters. RESTART resets the matching flag, which means that the default action will apply, should no further match occur. (Does not alter execution status) .TP RESYNC Re-synchronize header used for matching with the header of the mail. This is probably useful only when a SUBST or ANNOTATE command was run. (Does not alter execution status) .sp .B NOTE: At RESYNC time, mailagent will check whether the Content-Transfer-Encoding header was changed and will transparently recode the body if required, so that the whole message remains valid despite header mangling. It will also take care of updating Content-Length if required. Whenever you do change these important headers via SUBST or ANNOTATE, be sure to call RESYNC before disposing of the message or you run the risk of saving a corrupted version that will not be properly understood by your mail user agent. .TP RUN \fIprogram\fR Run the specified program and mail any output to the user who runs \fImailagent\fR. This action does not flag the message as having been saved. (Returns the status of \fIprogram\fR) .TP SAVE \fIfolder\fR Save message in the specified folder. If folder name starts with a '+', it is handled as an MH-style folder and \fIrcvstore\fR is emulated to deliver the message into that folder. If folder is a directory, message is delivered in a single file within that directory. See the \fBFOLDERS\fR section. (Fails if message cannot be saved) .TP SELECT (\fIstart .. end\fR) \fIcommand\fR Execute the \fIcommand\fR only within the time selection period specified. Dates can be specified in a wide range of formats. The output of the \fIdate\fR(1) command is an example of a valid specification. If the date, the year or the month is missing, then the current one is substituted in place of it. The following dates are valid specifications: '10:04:25', 'now' ,'April 1 1992', 'Dec 25', 'July 14 1789, 07:40' (err... it's valid according to the grammar, but it's before the Epoch so it does not mean anything). Other fancy dates like 'last month - 5 minutes' or '3 weeks ago' are also enabled. (Isn't that great to have a \fBreal\fR parser? The filtering rules could have been more elaborated if only I had known about this Berkeley \fIyacc\fR producing a \fIperl\fR parser...). (Returns the status of \fIcommand\fR, if run, otherwise returns true). .TP SERVER [\fB\-t\fR] [\fB\-d \fIdisabled commands\fR] Activate server processing. The body of the message is interpreted as a list of commands to execute. See section \fBGENERIC MAIL SERVER\fR for more information about the server itself. The \fB\-t\fR option turns the server into \fItrusted mode\fR, where \fIpowers\fR may be gained. The \fB\-d\fR option must be followed by a list of disabled commands, separated by commas with no intervening spaces between them. .TP SPLIT [\fB\-adeiw\fR] \fIfolder\fR Split a mail in digest format into the specified folder (same naming conventions as in SAVE). If no folder is specified, each digest item is queued and will be analyzed as a single mail by itself. The \fB\-d\fR option deletes the digest header. The \fB\-i\fR option means split is done in-place and the original mail is discarded. All the options may be used simultaneously provided they are stuck together at the beginning (option parsing being really rudimentary). .sp If the mail is not in digest format and a folder is specified, then it is saved in that folder. Otherwise, the SPLIT action fails and nothing occurs (the filter continues its processing though). The SPLIT command will correctly burst RFC-934 digest messages and will try to do its best otherwise. If the digest was not RFC-934 compliant and there is a chance SPLIT might have produced something incorrect, then the original message is also saved if \fB\-i\fR, otherwise it is not tagged as saved (so that the default LEAVE command may apply). The \fB\-w\fR (watch) requests special care and will detect every non RFC-934 digest, even when the non-compliance is otherwise harmless; furthermore, any trailing garbage longer that 100 bytes will be saved as a digest item by itself. .sp The \fB\-a\fR option annotates every digest item with an X-Digest-To: header line, which is the concatenation of the To: and Cc: fields of the original digest message. This may be used for instance to burst the digest into the queue and then re-process each of its items according to this added field. Finally, the \fB\-e\fR option will discard the digest header only if its body is empty (i.e. the moderator did not include any leading comment). (Returns success if mail was in digest format and correctly split without any error) .TP STORE \fIfolder\fR Save message in the specified folder and leave a copy in the system mailbox. The \fIfolder\fR parameter follows the same naming conventions as in SAVE. (Fails if message cannot be saved either in the \fIfolder\fR or in the mailbox) .TP STRIP \fIheader_fields_list\fR Remove the corresponding lines in the header of the mail. For instance, a "STRIP Newsgroups Apparently-To" will remove the appropriate lines to wipe out any Newsgroups: or Apparently-To: header. You may add a ':' after each header field name if you wish, but that is not strictly necessary. Headers may be specified via shell-style regular expressions or via "file" inclusion. (Does not alter execution status) .TP SUBST \fIvar/header expression\fR Substitutes the expression on the specified user-defined variable (name starting with a #) or back-reference (digit), or header field (optionally ending with ':'). For instance .Ex SUBST #foo /w/y/g .Ef would substitute in user-defined variable \fIfoo\fR all the \fIw\fR by \fIy\fR. See also ASSIGN and TR. For substitutions on header fields, like: .Ex SUBST Subject: /\\\\[foo\\\\\]\\\\s+//; .Ef matching header lines will be reformatted when the substitution is successful, which likely means original continuations will not be preserved. The target of the substitution is the whole header, with continuations normalized to one space. You are therefore guaranteed to be independent from the actual header formatting in the original. Do not forget to issue a RESYNC after a header field SUBST, since some routines (like POST) probe into the parsed header hash table to generate the saved message. (Fails if error in \fIexpression\fR) .TP TR \fIvar/header translation\fR Perform the translation on the specified variable, back-reference or header field. For instance .Ex TR 1 /A-Z/a-z/ .Ef would canonicalize content of reference 1 into lowercase. Successfully transliterated headers are reformatted, even when their overall size is not changed. See also ASSIGN and SUBST. (Fails if error in \fItranslation\fR) .TP UMASK [\fB\-l\fR] \fImode\fR Changes the process's umask to the specified \fImode\fR, which can be decimal, octal (if preceded by '0') or hexadecimal (starting with '0x'). The octal notation is the clearest way to specify the umask anyway. Aren't rumors saying that octal was invented for that purpose only? ;-) Use the \fB\-l\fR option to change the umask for the duration of the current action rule only. Note that the default umask specified in your config file is used to reset \fImailagent\fR's umask at the start of each mail processing. (Does not alter execution status) .TP UNIQUE [\fB\-acr\fR] [\fIstate\fR] [\fI(tag-list)\fR] Record message in the history and tag message as saved if it was already present there. If the message is recorded for the first time, processing continues normally. Otherwise a REJECT is performed. If \fB\-r\fR was used, a RESTART is used instead whilst \fB\-a\fR would run an ABORT. For instance, to remove duplicate messages from mailing lists, run a UNIQUE \fB\-a\fR before saving the mail. The \fB\-c\fR option may be used alone to actually prevent the command from disturbing the execution flow, and to later use the return status to see what happened: UNIQUE returns a failure status if the message was already recorded. If an optional \fIstate\fR argument is given, then the automaton will enter that state if the mail was previously in the database. See also RECORD, and the paragraph entitled \fBUsing Tags in Record and Unique\fR for more information about the \fItag-list\fR. (Fails if mail was already recorded) .TP VACATION [\fB\-l\fR] \fIon|off|path\fR [\fIperiod\fR] Allow or disallow a vacation message. When vacation mode is turned on via the configuration file, a message is sent whenever the user receives a mail meeting some requirements, as explained under the section \fBVACATION MODE\fR. One of the conditions is that the vacation flag modified by this command be true. This makes it easy to disallow vacation messages, ever, to a group of people for instance. .sp Instead of \fIon\fR or \fIoff\fR, you can specify a file name (~ substitution allowed) being the new path to be used for locating the vacation file. Optionally, you may specify a last parameter, which will be taken as the period to apply when sending the vacation message. Changes to the vacation message \fIpath\fR are forbidden when the configuration variable \fIvacfixed\fR is set to ON. .sp If you use the \fB\-l\fR option, changes are made locally, for the duration of the rule only. If you REJECT to go to some other rule, your changes will be lost. The global value of the altered parameters is changed on the first local usage and restored when a new rule is entered. (Does not alter execution status) .TP WRITE \fIfolder\fR Write the message in the specified folder, removing any pre-existing folder with the same name. Hence, successive WRITE commands will overwrite the previous one. This is useful to store output of system commands ran by \fIcron\fR. Don't try to use it with an MH folder or a directory folder or it will behave like SAVE. (Fails if message cannot be written) ''' .SS "Execution Status" .PP Almost all the actions modify a variable which keeps track of the execution status (analogous to the \$? variable in the shell). This variable can be tested via the \fB\-t\fR or \fB\-f\fR option of the REJECT command for instance. To give but a single example, the SAVE action would return \fIfailed\fR if it could not save the mail in the specified folder. If that SAVE command was followed by a "REJECT -f FAILED", then the execution of the current rule would stop and the automaton would continue to analyze the mail in the FAILED state. .PP Some of the actions however do not modify this last execution status. Typically, those are actions which make decisions based on that status, or simply actions which may never fail. Those special actions are: ABORT, ASSIGN, BEGIN, KEEP, MACRO, NOP, REJECT, RESTART, RESYNC, STRIP and VACATION. .PP It is unfortunate that ONCE or SELECT commands cannot make the difference between a non-execution and a successful execution of the specified command. There may be a change in the way this scheme works, but it should remain backward compatible. ''' .SS "Perl Escape" .PP By using the PERL command, you have the ability to perform filtering and other sophisticated actions directly in \fIperl\fR. This is really different from what you could do by feeding your mail to a perl script. First of all, no extra process is created: the script is loaded directly into mailagent and compiled in a special package called \fImailhook\fR. Secondly, you have a perl interface to all the filtering commands: each filtering action is associated to a perl function (spelled lower-cased). Finally, some pre-defined variables are set for you by mailagent. .PP Before we go any further, please note that as there is no extra process created, you \fBmust not\fR call the perl \fIexit\fR function. Use \fI&exit\fR instead, so that the exit may be trapped. \fI&exit\fR takes one argument, the exit code. If you use 0, this is understood as a success, any other value meaning failure (i.e. the PERL command will return a failure status). Using the perl \fIexit\fR function directly would kill \fImailagent\fR and would probably incur some mail losses. .PP The scripts used should remain simple. In particular, you should avoid the use of the \fIpackage\fR directive or define functions with a package name other than \fImailhook\fR (i.e. the package where your script is loaded). Failure to do so may raise some name clashes with \fImailagent\fR's own routines. In particular, avoid the \fImain\fR package. Note that since the compilation environment is set-up to \fImailhook\fR, not specifying package names in your variables and subroutine is fine (in fact, it's meant to work that way). .PP Your script is free to do whatever it wants to the mail. Most of the time however, you end up using the \fImailagent\fR primitives to save the mail or forward it (but you are free to redesign your own and call them instead, of course). The interface is simple: each function takes but one argument, a string, which is the arguments to the command, if any. For instance, in a perl escape script, you would express: .Ex { SAVE list; FORWARD "users"; FEED ~/bin/newmail -tty; REJECT } .Ef with: .Ex &save('list'); &forward('"users"'); &feed('~/bin/newmail -tty'); &reject; .Ef The rule is simple: each command is replaced by a function call, with the remaining parameters enclosed in a string, if any. Alternatively, you may specify parameters as a list: all the arguments you provide are joined into a big happy string, using a space character as separator. The macro substitution mechanism is then ran on this resulting argument string. .PP Each function returns a boolean success status of the command (i.e. 1 means success). For those functions which usually do not modify the filter's last execution status variable, a success is always returned. This makes it possible to (intuitively) write: .Ex &exit(0) if &save('uucp'); &bounce('root') || &save('emergency'); .Ef and get the expected result. The mail will be saved in the emergency folder only when saving in uucp folder failed and the mail could not be bounced to root. .PP It is important to understand that these commands have \fIexactly\fR the same effect on the filtering process when they are run from a perl escape script or from within the rule file as regular actions. A \fI&reject\fR call will simply abandon the execution of the current perl script and the filter automaton will regain control and attempt a new match. But \fIperl\fR brings you much more power, in particular system calls, control structures like \fBif\fR and \fBfor\fR, raw regular expressions, etc... .PP The special \fIperl\fR @INC array (which controls the search path for \fIrequire\fR) is slightly modified by prepending mailagent's own private library path. This leaves the door open for future mailagent library perl scripts which may be required by the perl script. Furthermore, the following special variables are set-up by perl before invoking your script: .sp .PD 0 .TP 15 .I @ARGV The arguments of the script, which were given by the PERL command. This array is set up the exact same way you would expect it to be set up if you invoked the command directly from the shell, excepted that .I @ARGV[0] is the name of the script (since you cannot use perl's \fI\$0\fR to get at it; that would give you mailagent's name). .TP .I \$address The address part of the From: line. .TP .I \$cc The raw content of the Cc: line. .TP .I @cc The list of addresses on the Cc: line, with comments suppressed. .TP .I \$envelope The mail envelope, as computed using the first From line of the message. .TP .I \$friendly The comment part of the From: line, if any. .TP .I \$from The content of the From: line, with address and comment part. .TP .I %header This table, indexed by field name, returns the raw content on the corresponding header line. See below. .TP .I \$msgpath The full path name of the folder (or message within an MH folder) where the last saving operation has occurred. This is intended to be used if you wish to construct your own mail reception notification. .TP .I \$length The message length, in bytes. .TP .I \$lines The number of lines in the message. .TP .I \$login The login name of the address on the From: line. .TP .I \$precedence The content of the Precedence: line, if any at all. .TP .I @relayed The list of host names (possibly raw IP addresses if no DNS mapping) listed in the (computed) Relayed: header line. .TP .I \$reply_to The e-mail address where a reply should be sent to, with comment suppressed. .TP .I \$sender The sender of the message (may have a comment), derived in the same way the Sender: line is computed by mailagent. .TP .I \$subject The subject of the message. .TP .I \$to The raw content of the To: line. .TP .I @to The list of addresses on the To: line, with comments suppressed. .PD .PP The associative array \fI%header\fR gives you access to all the fields in the header of the message. For instance, \fI\$to\fR is really the value of \fI\$header{'To'}\fR. The key is specified using a normalized case, i.e. the first letter of each word is uppercased, the remaining being lowercased. This is independent of the actual physical representation in the message itself. .PP The pseudo keys \fIHead\fR, \fIBody\fR and \fIAll\fR respectively gives you access to the raw header of the message, the body and the whole message. The \fI%header\fR array is really a reference to the \fImailagent\fR's internal data structure, so modifying the values will influence the filtering process. For instance, the SAVE command writes the \fIHead\fR, the \fIX-Filter:\fR line, the end of header (a single newline) and then the \fIBody\fR (this is an example only, not a documented feature :-). The \fI=Body=\fR key is special: it is a Perl reference to a scalar containing the body with any content transfer encoding removed. .PP Note that the \fI\$msgpath\fR variable holds only a snapshot of the folder path at the time where the PERL escape was called. If you perform your own savings in perl, then you need to look at the \fI\$main'folder_saved\fR variable instead to get the up-to-date folder path value. .PP As a final note, resist the temptation of reading the internals of the mailagent and directly calling the routines you need. If it is not documented in the manual page, it may be changed without notice by any further patch. (And this does not say that documented features may not change also... It's just more unlikely, and patches would clearly state that, of course.) ''' .SS "Program Environment" .PP All the programs started by mailagent via RUN and friends inherit the following environment variables: HOME, USER and NAME, respectively set from the configuration parameters \fIhome\fR, \fIuser\fR and \fIname\fR. If the mailagent is invoked by the \fIfilter\fR, then the PATH is also set according to the configuration file (if you are using the C filter) or to whatever you set PATH (if you are using the shell filter). .PP All the programs are executed from within the \fIhome\fR directory. This includes scripts started via the PERL command and mail hooks. The latter will be described in detail further down. ''' .SS "File inclusion" .PP Some commands like FORWARD or KEEP allow you to specify a file name between double quotes to actually load parameters from this file. Unless a full path is given, the following method is used to locate the file: first in the location pointed to by the \fImailfilter\fR variable if set, otherwise in \fImaildir\fR and finally in the home directory. Note that this is not a search path in the sense that if \fImailfilter\fR is defined and the file is not there, an error will be reported. .PP The file should list each parameter (be it an address, a header or a pattern) on a line by itself. Shell-style comments (#) are allowed within that file and leading white spaces are trimmed (but not trailing spaces). ''' .SS "Macros Substitutions" .PP All the commands go through a macro substitution mechanism before being executed. The following macros are available: .sp .PD 0 .TP 10 %% A real percent sign .TP %A The internet address extracted out of the \fIFrom:\fR field (\fIa.b.c\fR in \fIu@a.b.c\fR), converted to lower-case. .TP %C CPU name on which mailagent runs. That is a fully qualified hostname with the domain name, e.g. \fIlyon.eiffel.com\fR. .TP %D Day of the week (0-6) .TP %H Host name (name of the machine on which the \fImailagent\fR runs), without any domain name. Always in lower-case, regardless of the machine name. .TP %I The internet domain name extracted out of the \fIFrom:\fR field (\fIb.c\fR in \fIu@a.b.c\fR), converted to lower-case. .TP %L Length of the body part, in bytes, with content-transfer-encoding removed. .TP %N Full name of the sender (login name if none) .TP %O The organization name extracted out of the \fIFrom:\fR field (\fIb\fR in \fIu@a.b.c\fR), converted to lower-case. .TP %R Subject of the original message with leading Re: suppressed .TP %S Re: subject of original message .TP %T Time of the last modification on mailed file (commands MESSAGE and NOTIFY) .TP %U Full name of the user .TP %Y Full year, with four digits (so-called \fIyyyy format\fR) .TP %_ A white space (useful to put white spaces in single patterns) .TP %& List of selectors which incurred match (among those specified via a regular expression such as 'X-*: /foo/i'. If we find the \fIfoo\fR substring in the X-Mailer: header line, then %& will be set to this value). Values in the list are comma separated. .TP %~ A null character, wiped out from the resulting string. .TP %\fIdigit\fR Value of the corresponding back reference from the last match. .TP %#\fIvar\fR Value of user-defined variable \fIvar\fR .TP %=\fIvar\fR Value of the mailagent configuration variable \fIvar\fR as specified in the \fI~/.mailagent\fR file. .TP %d Day of the month (01-31) .TP %e The user's e-mail address (yours!). .TP %f Contents of the "From:" line, something like %N <%r> or %r (%N) depending on how the mailer is configured. .TP %h Hour of the day (00-23) .TP %i Message ID, if available (otherwise, this is a null string) .TP %l Number of lines in the message, once content-transfer-encoding has been removed .TP %m Month of the year (01-12) .TP %n Lower-case login name of sender .TP %o Organization (where \fImailagent\fR runs) .TP %r Return address of message .TP %s Subject of original message .TP %t Current hour and minute (in HH:MM format) .TP %u Login name of the user .TP %y Year (last two digits) .TP %[To] Value of the header field (here To:) .PD ''' .SS "User-defined Macros" .PP The mailagent lets you define your own macros in two ways: at the filter level via the MACRO command, or at the perl level in your own commands or perl actions. .PP Once defined, a user macro (say \fIfoo\fR) can be substituted by using \fI%-(foo)\fR. In the case of a single-letter macro, that can be optimized into \fI%-f\fR for instance, i.e. the parenthesis can be omitted. .PP There are six types of macros: .sp .TP 10 SCALAR A scalar value is given, e.g: \fIred\fR. The macro's value is the literal scalar value, no further interpretation is performed on the data. .TP EXPR A perl expression will be \fIeval\fRed to get the value, e.g: \fI\$red\fR. Note that the evaluation will be performed within the \fIusrmac\fR package, so if you are referring to a variable in another package, it would be wise to specify it, as in \fI\$foo'bar\fR. .TP CONST It's really the same as EXPR, but the value is known to be a constant. So the first time a substitution is made, the expression will be evaluated, and then its result is cached. .TP FN A perl function name (without the leading &), such as \fImain'do_this\fR. The function will be called with a single parameter: the name of the macro itself. That leaves the door open for further user-defined conventions by forcing evaluation through one single perl function. .TP PROG A program to run to get the actual value. Only trailing newline is chopped, others are preserved. The program is forked each time. In the argument list given to the program, %n is expanded as the macro name we are trying to evaluate. If you specify that in the filtering rules, don't forget to escape the first %. .TP PROGC Same as PROG really, but the program is forked only once and the value is cached for later perusal. .PD .PP At the perl level, four functions let you manipulate and define your macros (all part of the \fIusrmac\fR package): .sp .TP 10 .I new(name, value, type) Replace or create a %-(name) macro. For instance: .Ex new('foo', "\$mailhook'header{'X-Foo'}", 'EXPR'); .Ef would create a new macro \fIfoo\fR that would expand into the value of an hypothetical \fIX-Foo\fR header. .TP .I delete(name) Delete all values recorded for the macro. .TP .I push(name, value, type) Stack a new macro, creating it if necessary. .TP .I pop(name) Remove last macro definition on the stack. .PD .PP One macro stack is allocated for each macro, so that some kind of crude dynamic scoping may be implemented. Creating a macro via \fIpush\fR is like taking a local variable in perl, while creating one by \fInew\fR is simply assigning to a variable. Likely, \fIpop\fR is like exiting a block with a local variable definition and \fIdelete\fR frees \fIall\fR the macro bearing that name, i.e. it deletes the whole stack. .PP At the filter level, the MACRO command has three options. By default, the command defines a new macro by using \fIpush\fR, and the other options each let you access one of the other interface functions. Note that macro definitions persist across APPLY commands. ''' .SS "User-defined Logging" .PP Most of the time when writing a new mailagent filtering command or an perl hook, you will have a need for specific logging, either to report a problem or to keep track of what you are performing. .PP Normally, logs are appended into the \fIagentlog\fR file by calling \fI&main'add_log(string)\fR (see subsection \fBGeneral Purpose Routines\fR). For plain mailagent actions, this is fine. .PP But mailagent lets you define alternate logging files, referred to by name. This generic logging interface is defined in the \fIusrlog\fR package: .sp .TP 10 .I new(name, file, flag) Records a new log file known as \fIname\fR and done in \fIfile\fR. If the pathname given for this file is not absolute, it is rooted under the \fIlogdir\fR directory. If \fIflag\fR is set to true, any logging done to this file will also be copied to the default system-wide logfile. Nothing is done if a logfile with the same name has already been defined. .TP .I delete(name) Deletes the logfile known as \fIname\fR. Further logging done to that file is redirected to the default logfile. .TP .I main'usr_log(name, string) Adds an entry to the logfile \fIname\fR. The default logfile is known as \fIdefault\fR and cannot be redefined nor deleted. Note that this function is available from the \fImain\fR package. Calling it with \fIname\fR set to the string \fI'default'\fR is mostly equivalent to calling directly \fImain'add_log\fR with the notable exception that the \fB\-i\fR mailagent option will not be honored in that case. This may or may not be useful to you. .PP If you call \fI&main'usr_log\fR with a non-existent logfile name, logging is redirected to the default system-wide logfile defined in your \fI~/.mailagent\fR. ''' .SS "Dynamically Loading New Code" .PP In you perl routines (user-defined commands, perl hooks, etc...), you may feel the need to dynamically load some new code into mailagent. You have direct access to the internal routine used by mailagent to implement the REQUIRE command or load your new filtering commands for example. .PP Using the so-called \fIdynload\fR interface buys you some extra features: .IP \(bu 5 The mailagent public library path is automatically prepended to the @INC array, which lets you define your own system-wide or private perl library files (the private library path is defined by the \fIperlib\fR configuration variable, the public library path was defined at installation time). .IP \(bu Like perl's \fIrequire\fR, mailagent keeps track of which files were loaded into which packages and will not reload the same file in the same package twice. .IP \(bu It is possible to make sure that a specific function be defined in the loaded file, with an error reported if this is not the case. .IP \(bu You benefit from the default logging done by \fIdynload\fR when some error occurs. .PP In order to do all this, you call: .Ex \fI&dynload'load(package, file, function)\fR .Ef specifying the package into which you wish to load the file, and optionally the name of a function that must be defined once the file has been loaded (leave this field to \fIundef\fR if you do not have such a constraint). The routine returns \fIundef\fR if the file cannot be loaded (non-existent file, most probably), \fB0\fR if the file was loaded but contained a syntax error or did not define the specified function, and \fB1\fR for success. ''' .SS "Using Once Commands" .PP The ONCE constructs lets you specify a given command to be run once every period (day, week...). The command is identified by a \fIname\fR and a \fItag\fR, the combination of the two being unique. Why not just a single identifier? Well, that would be fine, but assume you want to send a message in reply to someone once every week. You could use the e-mail address of the person as the command identifier. But what if you also want to send another message to the same address, this time once a month? .PP Here is a prototypical usage of a ONCE, which acts like the vacation program, excepted that it sends a reply only once a day for a given address: .Ex { ONCE (%r, message, 1d) MESSAGE ~/.message }; .Ef This relies on the macro substitution mechanism to send only once a day the message held in \fI~/.message\fR. Do not use the tag \fIvacation\fR, unless you know what you are doing: this is the tag used internally by mailagent in vacation mode. Recall that no selector nor pattern is understood as "Subject: *", hence the rule is always executed because that pattern always matches. .PP The timestamps associated with each commands are kept in files under the Hash directory. The name is used as a hashing key to compute the name of the file (the two first letters are used). Inside the file, timestamps are sorted by name, then by tag. Of course, you could say (inverting tag and name): .Ex { ONCE (message, %r, 1d) MESSAGE ~/.message }; .Ef but that would be likely to be less efficient, as the first hashing would be done on a fixed word, hence all the timestamps would be located in the file \fIHash/m/e\fR (where \fIHash\fR is the name of your hashing directory, which is the \fIhash\fR parameter in the configuration file). ''' .SS "Using Tags in Record and Unique" .PP Both the RECORD and UNIQUE commands let you specify a comma-separated tag list between '(' and ')'. For each tag present in the list, there is a separate entry in the database associated with the message ID. When the message is recorded for at least one of the tags, the command "fails". Not specifying any tags means looking for any occurrence of that message ID, whether it is tagged or not. .PP This is very useful when receiving mail cross-posted to distinct mailing lists and you want to save one instance of the message in each folder, but still guard against duplicates. You may say: .Ex To Cc: unix-wizards { UNIQUE (wizards); SAVE wizards; REJECT; }; To Cc: majordomo-users { UNIQUE (majordomo); SAVE majordomo; REJECT; }; .Ef and only one instance of the message will end up in each folder. When you have folders with conflicting interests, you might use a tag list, instead of a single tag. For instance, assuming you wish to keep a single copy for messages cross-posted to both \fIdist-users\fR and \fIagent-users\fR, but have a separate copy if also cross-posted to \fImajordomo-users\fR, then say: .Ex To Cc: majordomo-users { UNIQUE (majordomo); SAVE majordomo; REJECT; }; To Cc: dist-users { UNIQUE (dist, agent); SAVE dist-users; REJECT; }; To Cc: agent-users { UNIQUE (dist, agent); SAVE dist-users; REJECT; }; .Ef If you have some rule using UNIQUE without any tags, it will match when at least one instance of the message has been recorded, no matter what tag (if any at all) was used in the first place. ''' .SS "Specifying A Period" .PP The period parameter of the ONCE commands or the \fIvacperiod\fR parameter of your configuration file has the following format: a number followed by a modifier. The modifier is an atomic period like a day or a week, the number is the number of atomic periods the final period should be equal to. The available modifiers are: .sp .PD 0 .TP 10 m minute .TP h hour (60 minutes) .TP d day (24 hours) .TP w week (7 days) .TP M month (30 days) .TP y year (365 days) .PD .PP All the periods are converted internally in seconds, although you do not really care... Examples of valid periods range from "1m" to "136y" on a 32 bits machine (why ?). ''' .SS "Timeouts" .PP In order to avoid having a \fImailagent\fR waiting for a command forever, a maximum execution time of one hour is allowed by default. Past that amount of time, the child is sent a SIGTERM signal. If it does not die within the next 30 seconds, a SIGKILL is sent. Output from the program, if any so far, is mailed back to the user. This default behaviour may be altered by setting a proper \fIrunmax\fR variable in your configuration file to allow more time for the command to complete. .PP There is also a \fIfilter\fR queue timeout. In order to moderate system load, the C \fIfilter\fR program waits 60 seconds by default (or whatever .I queuewait was set to in the config file) before launching \fImailagent\fR. To avoid conflicts, messages queued by the first filter (which will then sleep for .I queuewait seconds) are not processed by \fImailagent\fR's \fB\-q\fR option until they are at least .I queuehold seconds old. Another queue-related parameter is .I queuelost, the amount of seconds after which \fImailagent\fR will flag messages as "lost" when listing the queue. .PP Finally, the locking timeout policy may also be configured. By default, a lock is broken when it is one hour old (configured by the .I lockhold variable) and \fImailagent\fR will only make .I lockmax attempts, spaced by .I lockdelay seconds to acquire the lock. It will then proceed whether or not it got that lock. If you want a secure locking policy, make sure .I lockmax times .I lockdelay is greater than \fIlockhold\fR, that parameter being "large" enough. ''' .SS "Avoiding Loops" .PP The \fImailagent\fR leaves an "X-Filter:" header on each filtered message, which in turn is used to detect loops. If a message already filtered is to be processed, the \fImailagent\fR enters a special state _SEEN_. This state is special in the sense it is built-in, it is not matched by ALL, and some actions are not made available, namely: BACK, BOUNCE, FEED, FORWARD, GIVE, NOTIFY, PASS, PIPE, POST, PURIFY, QUEUE and RUN. Also note that although the ONCE and SELECT constructs are enabled, they will not let you execute disallowed commands. Otherwise, the _SEEN_ state behaves like any other state you can select or negate, so a guard will not select the rule when we are in state _SEEN_. .PP The _SEEN_ state makes it easy to deal with mails which loop because of an alias loop you have no control on. If no action is found in the _SEEN_ state, the mail is left in the mailbox, as usual. Moreover, if no saving is done, a LEAVE is executed. This is the normal behavior. .PP The "X-Filter:" header is only added when the message is saved. Actions such as PIPE or GIVE do not flag the message as being saved and therefore they do .B not add that header line. You can add one via ANNOTATE if you wish to prevent loops, in case the program to which you are feeding the message might return it to you in some strange way. ''' .SS "Message Files" .PP The text of the message to be sent back (for MESSAGE or NOTIFY) is read from a file and passed through the macro substitution mechanism. The special macro \fI%T\fR is set to the date of last modification made on that file. The format is \fImonth/day\fR, and the year is added before the month only if it differs from the current year. .PP At the head of the message, you may put header lines. Those lines will overwrite the default supplied lines. That may be useful to change the default subject or add some additional fields like the name of your organization. The end of your header is given by the first blank line encountered. If the top of the message you wish to send looks like a mail header, you may protect it by adding a blank line at the very top of the file. This dummy line will be removed from the message and the whole file will be sent as a body part. .PP Here is an example of a vacation file. We add a carbon copy as well as the name of our organization in the header: .Ex Cc: ram Organization: %o Precedence: bulk [Last revision made on %T] Dear %N: I've received your mail regarding "%R". It will be read as soon as I come back from vacation. Sincerely, -- %U <%u@%C> .Ef .SH "VACATION MODE" .PP When it's time to take some vacation, it is possible to set up mailagent in vacation mode. Every \fIvacperiod\fR, the message \fIvacfile\fR will be sent back to the user (with macros substitutions) if the user is explicitly listed in the \fITo\fR or \fICc\fR field and if the sender is not a special user (\fIroot\fR, \fIuucp\fR, \fInews\fR, \fIdaemon\fR, \fIpostmaster\fR, \fInewsmaster\fR, \fIusenet\fR, \fIMailer-Daemon\fR, \fIMailer-Agent\fR or \fInobody\fR). Matches are done in a case insensitive manner, so \fIMAILER-DAEMON\fR will also be recognized as a special user. Furthermore, any message tagged with a \fIPrecedence:\fR field set to \fIbulk\fR, \fIlist\fR or \fIjunk\fR will not trigger a vacation message. This built-in behavior can of course be overloaded by suitable rules (by testing and issuing the vacation message yourself via MESSAGE). .PP Internally, mailagent uses a ONCE command tagged \fI(%r, vacation, \$vacperiod)\fR. This implies you must not use the \fIvacation\fR tag in your own ONCE commands, unless you know what you are doing. .PP Besides, the vacation message is sent only if no "VACATION off" commands were issued, or if another "VACATION on" overwrote the previous one. Note that whether a rule matched or not is irrelevant to the algorithm. By default, of course, the vacation message is allowed when the \fIvacation\fR configuration parameter is set to \fIon\fR. .PP If you are not pleased by the fact that a vacation message is sent to people who addressed you a carbon copy only, then you may write at the top of your rule file: .Ex Cc: ram { VACATION off; REJECT }; .Ef Of course, you have to substitute your own login name in place of \fIram\fR. You cannot use the same scheme to allow vacation messages to special users like \fIroot\fR, because the test for "specialness" occurs after the vacation mode flag. This is construed as a feature as it prevents stupid mistakes, like using \fIr*\fR instead of \fIram\fR in the previous rule. .PP You may also want to setup a different vacation message, meant only for people in your organization given the sensitive nature of the information revealed ;-). A simple way of doing that is: .Ex From: /^\\\\w+\$/, /^\\\\w+@\\\\w+\$/, /^[\\\\w.-]+@.*\\\\.hp\\\\.com\$/i { VACATION ~/.hp_vacation 1w; REJECT HP }; .Ef Assuming the domain of my organization is \fI.hp.com\fR and that messages not bearing any domain are local messages, the above rule sets up the file \fI~/.hp_vacation\fR, sent once a week, for all HP employees. .PP The VACATION command will not let you change the message path (but will allow frequency changes anyway) when the \fIvacfixed\fR configuration variable is set to ON. This is meant to be used in emergency situations, when only one vacation message will fit. For instance, when you are on a sick leave, a simple trigger message to your mailagent from home could change your \fI~/.mailagent\fR configuration to force the \fI~/.i_am_sick\fR message, regardless of what the various rules have to say. Actually, this is precisely why this feature was added, amazing... :-) .SH VARIABLES The following variables are paid attention to: they may come from the environment or be set in the rule file: .TP 10 .I mailfilter indicates where loaded patterns are to be looked for, if the name of the file is not fully qualified. If it is not set, \fImaildir\fR will be used instead. If \fImaildir\fR is not set either, the home directory is used. .TP .I maildir is the location of your mail folders. Any relative path is understood as starting from \fImaildir\fR. If it is not set, \fI~/Mail\fR is used. .PP Those variables remain active while in the scope of the rule file. Should an alternate rule file be used (via rules hook or the APPLY command), the current values are propagated to the new rule set unless overridden in the alternate rule file. In any case, the previous value is restored when control is transferred back to the previous set of rules. That is, those variables are dynamically instead of statically scoped. .SH "AUTOMATIC ACKNOWLEDGMENTS" Anywhere in the mail, there can be an @RR left-justified line which will send back an acknowledgment to the sender of the mail. The @RR may optionally be followed by an address, in which case the acknowledgment will be sent to that address instead. In fact (but let's keep that a secret), this is a way for me to be able to see who runs my mailagent program and who doesn't... .PP The \fIsendmail\fR program usually implements such a feature via a Return-Receipt-To: header line, which sends the whole header back upon successful delivery. However, this is not implemented on all mail transport agents, and @RR is a good alternative :-). .SH "NOTA BENE" Throughout this manual page, I have always written header fields with the first letter of each word uppercased, as in \fIReturn-Receipt-To\fR. But RFC-822 does not impose this spelling convention, and a mailer could legally rewrite the previous field as \fIreturn-receipt-to\fR (and in fact so does \fIsendmail\fR in its own private mail queue files). .PP However, you must always specify the headers in what could be called a \fInormalized\fR case (for headers anyway). The mailagent will correctly recognize \fIcc:\fR, \fICC:\fR or \fICc:\fR in a mail message and will allow you to select those fields via the normalized \fICc:\fR selector. In fact, it operates the normalization for you, and a \fIcc:\fR selector would not be recognized as such. Of course, no physical alteration is ever made on the header itself. .PP This is also true for headers specified in the STRIP or KEEP command. If you write \fISTRIP Cc\fR, it will correctly remove any \fIcc:\fR line. Likewise, if you use regular expressions to specify a selector, \fIRe.*:\fR would match both original \fIreceived:\fR and \fIReturn-path:\fR fields, internally known through their normalized representation. .SH "MAIL HOOKS" The mail hooks allow mailagent to transparently invoke some scripts or perform further processing on the message. Those hooks are activated via the SAVE, STORE or LEAVE commands. Namely, saving in a folder whose executable bit is set will raise a special processing. By default, the folder is taken as a program where the mail should be piped to. If the "folder" program returns a zero status, then the message is considered \fIsaved\fR by the mailagent. Otherwise, all the processing attached to failed save commands is started (including emergency saving attempts). Executable folders provide a transparent way (from the rule file point of view) to deal with special kind of messages. .PP In fact, five different types of hooks are available. The first one is the plain executable folder we have just spoken about. But in fact, here is what really happens when a saving command detects an executable folder: the mailagent scans the first line of the folder (in fact, the first 128 bytes) and looks for something starting with #: and followed by a single word, describing a special kind of hook. This is similar in the way the kernel deals with the #! hook in executable programs. If no #: is found or #: is followed by some garbage, then \fImailagent\fR decides it is a simple program and feeds the mail message to this program. End of the story. .PP But if the #: token is followed (spaces allowed, case is irrelevant) by one of the following words, then special actions are taken: .PD .TP 10 .I rules The file holds a set of mailagent rules which are to be applied. A new mailagent process is created to actually deal with those and the exit status is propagated back to the original mailagent. .TP .I audit This is similar in spirit to what Martin Streicher's audit.pl package does, hence the name of this hook. The special variables which are set up by the PERL filter commands are initialized and the script is loaded in the special \fImailhook\fR package name space, which also gives you an interface to the mailagent's own routines. You may safely use the \fIexit\fR function here, since an extra \fIfork\fR is done. This is the only difference between an \fIaudit\fR and a \fIperl\fR hook. .TP .I deliver Same thing as for the \fIaudit\fR hook, but the standard output of your script is monitored by \fImailagent\fR and understood as mailagent filtering commands. Upon successful return, a mailagent process will be invoked to actually execute those commands on the message. Again, this is similar in spirit to Chip Salzenberg's \fIdeliver\fR package and gave the name of this hook. .TP .I perl This hook is the same as \fIaudit\fR but it is executed without forking a new mailagent, and you have the perl interface to mailagent's filtering commands. There is no difference with the PERL command, because it is implemented that way, by calling a mailagent and forcing the PERL command to be executed. This is similar in spirit to Larry Wall's famous \fIperl\fR language and it is responsible for the name of this hook :-). .PP As mentioned earlier in this manual page, the hook is invoked from with the \fIhome\fR directory specified in your ~/.mailagent (which may differ from your real home directory, as far as \fImailagent\fR or \fImailhook\fR are concerned). .PP For those hooks which are finally ran by perl, the special @INC array has mailagent's own private library path prepended to it, so that \fIrequire\fR first looks in this place. ''' ''' F o l d e r s ''' .SH "FOLDERS" A folder is a file or a directory which can be the target of a delivery by the mailagent, that is to say the argument of SAVE-like commands. ''' .SS "Folder Format" .PP By default, mails are written into folders according to the standard UNIX-style mailbox format: each mail starts with a leading \fIFrom\fR line bearing the sender's address and the date. However, by setting the \fImmdf\fR parameter from the \fI~/.mailagent\fR to ON, the \fImailagent\fR will be able to save messages in MMDF format: each message is sandwiched between two lines of four Ctrl-A characters (ASCII code 1) and the leading \fIFrom\fR line is removed. .PP When MMDF mode is activated, each folder will be scanned to see if it is a UNIX-style or MMDF-style mailbox and the message will be saved accordingly. When saving to a new folder, the default is to create a UNIX-style mailbox, unless the \fImmdfbox\fR configuration variable was set to ON, in which case the MMDF format prevails. .PP Note that the MMDF format is also the standard for MH packed folders, so by enabling the MMDF mode, you can actually deliver directly to those packed folders. The MH command \fIinc\fR is able to incorporate mail from either form anyway, i.e. it does not matter whether the folder is in UNIX format (also called UUCP-style) or in MMDF format. .PP MH-style folders are also supported. It is mainly a directory in which messages are stored in individual files. To save directly into an MH folder, simply prefix the folder name with '+', just as you would do with MH commands. The unseen sequences specified in your MH profile (the \fImhprofile\fR parameter in your \fI~/.mailagent\fR, default is \fI~/.mh_profile\fR) will be correctly updated, as \fIrcvstore\fR would. .PP When the target folder is a directory, mailagent attempts the delivery in an individual numbered file. If a prefix file is present (config parameter \fImsgprefix\fR, default is \fI.msg_prefix\fR), its first line is used to specify the base name of the message, then a number is appended to give the name of the message file to use. That is, if there is no such file, the folder will look like an MH one, without any MH sequence file though. ''' .SS "Folder Compression" .PP If you have one or more of the widely available file compression utilities such as \fIcompress\fR or \fIgzip\fR in your PATH (as set up by \fI~/.mailagent\fR), then you may wish to use folder compression to save some disk space, especially when you are away for some time and do not want to see your mail fill-up the filesystem. .PP To achieve folder compression, you have to set up a file, referred to by the \fIcompress\fR configuration variable. This file must list folder names, one per line, with blank lines ignored and shell-style (#) comments allowed. You may use shell-style patterns to specify the folders, and the match will be attempted on the full pathname of the folder (~ substitution occurs). If you do not specify a pattern starting with a leading '/' character, then the match will be attempted on the basename of the folder (i.e. the last component of the folder path). If you want to compress all your folders, then simply put a single '*' inside this file. .PP Mailagent uses the filename extension to determine what compression scheme is used for a particular folder. The file referred to by the \fIcompspecs\fR configuration variable (default is \$spool/compressors) is used to define the commands that mailagent will use to perform the compress, uncompress, and cat operations for a particular extension. .PP The \fIcompressors\fR file holds lines of the following form: .Ex \fItag extension compression_prog uncompress_prog cat_prog\fR .Ef where: .TP 10 .I tag is the logical name for the compression scheme. This is typically the same as the name of the program used to provide the compression, but could be different for some unforeseen reason. This must be unique across all records in the file. .TP .I extension is the extension to recognize as belonging to the specified tag. This must be unique across all records in the file. .TP .I compression_prog is the name of the command to run to compress a folder. The program must replace the uncompressed file with the compressed one with the extension appended to the filename (like \fIcompress\fR or \fIgzip\fR). .TP .I uncompression_prog is the name of the command to run to uncompress a folder. The program must replace the compressed file with the uncompressed one without the extension (like \fIuncompress\fR or \fIgunzip\fR). .TP .I cat_prog is the name of the command to output the uncompressed contents of a compressed folder to stdout (like \fIzcat\fR or \fIgzcat\fR). .PP The fields are separated by \fBTABS\fR to allow for the use of space characters in the command fields. .PP If the file referred to by the \fIcompspecs\fR configuration variable cannot be accessed for whatever reason, a default entry is hard-wired into mailagent (knows about both \fIcompress\fR and \fIgzip\fR programs): .Ex compress .Z compress uncompress zcat gzip .gz gzip gunzip gunzip -c .Ef .PP If you wish to add more compressors, you can copy the default \fIcompressors\fR file from mailagent's private library directory and setup a correct entry for your alternate compressor. Keep in mind that the trailing extension needs to be unique amongst all the listed programs, since that extension is used to determine the type of compression performed on the folder. .PP If the folder is created without any existing compressed form around, a default compressor is selected for you, as defined by the \fIcomptag\fR configuration variable. That refers to the tag name of the \fIcompspecs\fR file, i.e. the first word on the line (usually the name of the compression program, but not necessarily). .PP When attempting delivery, mailagent will check the folder name against the list of patterns in the compress file. If there is a match, the folder is flagged as compressed. Then mailagent attempts decompression if there is already a compressed form (ie. the file has a recognized filename extension) and if no uncompressed form is present. Delivery is then made to the uncompressed folder. However, re-compression is not done immediately, since it is still possible to get messages to that folder in a single batch delivery. Should disk space become so tight that decompression of other folders is impossible, mailagent will re-compress the folders it has already uncompressed. Otherwise, it waits until the last moment. .PP If for some reason there is a compressed folder which cannot be decompressed, mailagent will deliver the mail to the plain folder. Further delivery to that folder will be faced with both a compressed and a plain version of the folder, and that will get you a warning in the log file, but delivery will be made automatically to the plain file. .PP On newly created folders the \fIcomptag\fR configuration variable is referenced to determine the compression type to use for the folder. ''' ''' M a i l B i f f i n g ''' .SH MAIL BIFFING If you are receiving and processing mail on your own machine, then you have access to local mail biffing where \fImailagent\fR can warn you about new messages and tell you about where they have been saved, printing a small subset of the header and the first few lines of the body. .PP To use biffing, all you need is the setting of the few biff parameters in your \fI~/.mailagent\fR and make sure \fIbiff\fR is set to ON. Actually, this is the only parameter you need to set to get minimal default biffing behaviour. Don't forget to run the shell command "\fIbiff y\fR" on the terminals where you want to get notification (you may do that on several ttys, one for each virtual display for instance). .PP Upon mail reception and saving on a folder or posting to a newsgroup, \fImailagent\fR locates all the ttys where you are logged on, then selects those where biffing was requested, finally emitting a message and making a beeping sound (if your terminal supports this and you are using the standard format--see below). .SS "Customizing Biffing Output" .PP Should the default format not suit your needs, you may customize the biffing message freely, setting the \fIbiffmsg\fR parameter to point to the file where the format is stored. Standard macros substitutions will be performed on your message, the following macro set superseding and completing the standard set: .sp .PD 0 .TP 10 %-A Same as writing %-H, new line, %-B .TP %-B The body part of the biffing message, with content-transfer-encoding removed. If the message is a MIME multipart one, the text/plain part is shown. If only a text/html part is available, the HTML markup is stripped for biffing. .TP %-H The header part of the biffing message. If shows only From:, To: Subject: and Date: headers, or whatever you have set the \fIbiffhead\fR configuration variable to. All headers are showed as one line of text, regardless of their actual length. There will be three trailing dots at the end to signal that truncation occurred. For a news article (biffing after a POST -b), the To: and Cc: fields are never shown, even if specified in \fIbiffhead\fR. .TP %-T Same as %-B, but trimming is activated. The purpose of trimming is to remove any leading quotation in the message, to get only the most meaningful part. This assumes the quoting character is a single non-alphanumeric character. The leading attribution line that may introduce the quotation can be also removed, and a minimum length for the quotation can be set in the configuration file. .TP %B The relative path under %d of the message folder, full path (%p) if not saved under that directory. The newsgroup name for news articles. .TP %D The directory where the message is stored. If an MH folder, this is the folder full path. The home directory is replaced by a ~. Empty for news articles. .TP %F The base name (last path component) of the message. For an MH message, this is the message number. Empty for news articles. .TP %P The folder path. It has the correct semantics for MH and directory folders, i.e. it points to the folder directory itself. Otherwise, the same as %p. .TP %a Alarm characters (^G). May expand to more than one under the control of the BEEP filtering command. Use %b if you only want a single bell. .TP %b A beeping character (^G). As opposed to %a, this only expands to give \fBone\fR bell. .TP %d Full path where folders such as the one being saved into are stored if not qualified (i.e. your MH path for MH folders, of something like \fI~/Mail\fR for other folders). Empty for news articles. .TP %f Folder where mail was saved, home replaced by ~ for short. The newsgroup when article was posted for news. .TP %m A '+' sign if the folder is an MH one, empty otherwise. .TP %p The full path name (same as %f) of the message, but without any ~ shortcut. The newsgroup name for news articles. .TP %t The type of message: usually "mail", but set to "article" for biffing after a POST command. .PD .PP You can get the standard macro expansion by using \fI%:f\fR for instance, since the \fI%f\fR macro is superseded. The \fI%:\fR form lets you obtain the standard macro definition anyway, no matter what, so you don't have to remember whether a given macro is superseded in this context or not. Besides, it is safer since new macros may be added here without notice. Note that macros related to the message content all start with \fI%-\fR and therefore are not conflicting with standard one. .PP Here is the format you need to use to get the same behaviour as the default hardwired format: .Ex %b New %t for %u has arrived in %f: ---- %-A ----%b .Ef Note that the string \fI...more...\fR appears at the end of the body when it has not been completely printed out on the screen and the remaining lines are not blank or similar. .SS "Trimming Leading Quotation" .PP It is a standard practice, when replying to a message, to include an excerpt of the sentences being replied-to, using a non-alphanumeric character such as '>' to prefix quoted lines. Something like: .Ex Quoting John Doe: > This is quoted material. > Another line from John's mail. This is part of the reply to John. .Ef The leading "Quoting ..." line, called the \fIattribution\fR line, is optional and may be missing or take another free form. .PP However, when biffing, this may be seen as useless noise, especially nowadays where people freely quote more and more in their replies. Since the biff message only shows the top lines of the message, it may be desirable to automatically trim those quoted lines. .PP Via the \fI%-T\fR macro in the customized biff format, you may request trimming of the leading quotation material, keeping the attribution line or not, and even replace trimmed material with a notification that so many lines have been removed. .PP All this customization is done from the \fI~/.mailagent\fR configuration file, using the \fIbifftrim\fR, \fIbifftrlen\fR and \fIbiffquote\fR variables. .PP You first need to turn trimming on by using a customized biff format using the \fI%-T\fR macro. By setting \fIbifftrlen\fR to 3, you may request that only quotations of at least 3 lines be trimmed. Turning \fIbifftrim\fR off will remove the trimming notification, whilst turning \fIbiffquote\fR off will also strip the attribution line, when present. .PP For instance, assuming the following settings: .Ex bifftrim : ON bifftrlen: 2 biffquote: OFF .Ef then the above example would produce the following biffing output (header of the message not withstanding): .Ex [trimmed 3 lines starting with a leading '>' character & attribution line] This is part of the reply to John. .Ef because the blank line following the quoted material is counted as being part of the quotation. The "[trimmed ..]" message can be turned off by setting \fIbifftrim\fR to OFF. .PP The trimming algorithm considers the first line of the body to see if it starts with a non-alphanumeric character. If it does, then all the following lines starting with that same character, or any blank line is removed, up to the first non-blank line starting with another character. Optionally, the first line (and that line only) is skipped if the second one starts with a non-alphanumeric character, and the first line is taken as being the attribution line. .SS "Using Compact MH-style Biffing" .PP The so-called \fIMH-style\fR biffing is a way of presenting a compacted body where all the lines are joined together into a big happy string with successive spaces turned into a single space character. To enable it, you need to set the \fIbiffmh\fR variable to ON. .PP Since this compacting is output verbatim on the tty, line breaks will occur randomly and this may make reading difficult. You may request an automatic reformatting of the compacted body by turning \fIbiffnice\fR to ON and the biff output will fit nicely within the terminal. .PP Unfortunately, it is not possible to customize the amount of columns that should be used for formatting: since you may biff to any tty you are logged on, that would force \fImailagent\fR to probe the tty for its column size, for each possible tty where output may go, and there is no reliable portable way of doing that. Sorry. ''' ''' E x t e n d i n g F i l t e r i n g C o m m a n d s ''' .SH EXTENDING FILTERING COMMANDS Once you've reached the \fIexpert\fR level, and provided you have a fair knowledge of \fIperl\fR, you may feel the need for more advanced commands which are not part of the standard set. This section explains how you can achieve this dynamically, without the need of diving deep inside the source code. .PP Once you have extended the filtering command set, you may use those commands inside the rule file as if they were built-in. You may even choose to redefine the standard commands if they do not suit you (however, if you wish to do that, you should know exactly what you are doing, or you may start losing some mail or get an unexpected behavior -- this also voids your warranty :-). .PP The ability to provide external commands without actually modifying the main source code is, I believe, a strong point in favor of having a program written in an interpreted language like \fIperl\fR. This of course once you have convinced yourself that it is a Good Thing to customize and extend a program in the same language as the one used for the core, meaning usually a fairly low-level language with fewer user-friendly hooks. ''' .SS Overview .PP In order to implement a new command, say FOLD, you will need to do the following: .IP \(bu 5 Write a perl subroutine to implement the FOLD action and put that into an external file. Say we write the subroutine \fIfold\fR and we store that in a \fIfold.pl\fR file. This is naturally the difficult part, where you need to know some basic things about mailagent internals. .IP \(bu Choose where you want to store your \fIfold.pl\fR file. Then check the syntax with \fIperl \-c\fR, just to be sure... .IP \(bu Edit the \fInewcmd\fR file (as given by the configuration file) to record your new command. Then make sure this file is tightly protected. You must own it, and it should not be writable by any other individual but you. .IP \(bu Additionally, you may want to specify whether FOLD is to modify the existing execution status and whether or not it will be allowed within the special _SEEN_ state. .IP \(bu Write some rules using the new FOLD command. This is the \fIeasy\fR part! Note that your command may also be used within perl hooks as if it were a builtin command (this means there is an interface function built for you within the \fImailhook\fR package). .PP In the following sections, we're going to describe the syntax of the \fInewcmd\fR file, and we'll then present some low-level internal variables which may be used when implementing new commands. ''' .SS New Command File Format .PP The \fInewcmd\fR file consists of a series of lines, each line describing one command. Blank lines are ignored and shell-style comments introduced by the sharp (#) character are allowed. .PP Each line is formed by 3 principal fields and 2 optional ones; fields are separated by spaces or tabs. Here is a skeleton: .Ex .Ef The \fIcmd_name\fR is the name of the command you wish to add. In our previous example, it would be FOLD. The next field, \fIpath\fR, tells mailagent where the file containing the command implementation is located. Say we store it in \fI~/mail/cmds/fold.pl\fR. The \fIfunction\fR field is the name of the \fIperl\fR function implementing FOLD, which may be found in \fIfold.pl\fR. Here, we named our function \fIfold\fR. Note that if your function has its name within the \fInewcmd\fR package, which is the default behavior if you do not specify any, then there is no need to prefix the function name with the package. Otherwise, you must use a fully qualified name. .PP The last two fields are optional, and are boolean values which may be specified by \fItrue\fR or \fIyes\fR to express truth, and \fIfalse\fR or \fIno\fR to express falsehood. If \fIstatus_flag\fR is set to true, then the command will modify the last execution status variable. If \fIseen_flag\fR is true, then the command may be used when the filter is in _SEEN_ state. The default values are respectively \fItrue\fR and \fIfalse\fR. .PP So in our example, we would have written: .Ex FOLD ~/mail/cmds/fold.pl fold no yes .Ef to allow FOLD even in _SEEN_ state and have it executed without modifying the current value of the \fIlast-command-status\fR variable. ''' .SS Writing An Implementation .PP Your perl function will be loaded when needed into the special package \fInewcmd\fR, so that its own name-space is protected and does not accidentally conflict with other mailagent routines or variables. When you need to call the perl interface of some common mailagent functions, you will have to remember to use the fully qualified routine name, for instance \fI&mailhook'leave\fR to actually execute the LEAVE command. .PP (Normally, in PERL hooks, there is no need for this prefixing since the perl script is loaded in the \fImailhook\fR package. When you are extending your mailagent, you should be extra careful however, and it does not really hurt to use this prefixing. You are free to use the perl \fIpackage\fR directive within your function, hence switching to the \fImailhook\fR package in the body of the routine but leaving its name in the \fInewcmd\fR package.) .PP Since mailagent will dynamically load the implementation of your command the first time it is run, by loading the specified perl script into memory and evaluating it, I suggest you put each command implementation in a separate file, to avoid storing potentially unneeded code in memory. .PP Each command is called with one argument, namely the full command string as read from the filter rules. Additionally, the special \fI@ARGV\fR array is set by performing a shell-style parsing of the command line (which will fail if quotes are mismatched, but then you can do the parsing by yourself since you get the command line). At the end of your routine, you must return a failure status, i.e. \fB0\fR for success and \fB1\fR to signal failure. .PP Those are your only requirements. You are free to do whatever you want inside the routine. To ease your task however, some variables are pre-computed for you, the same ones that are made available within mail hooks, only they are defined within the \fInewcmd\fR package this time. There are also a few special variables which you need to know about, and a set of standard routines you may want to call. Please avoid calling something which is not documented here, since it may change without prior notice. If you would like to use one routine and it is not documented in this manual page, please let me know. .PP Each command is called from within an \fIeval\fR construct, so you may safely use \fIdie\fR or call external library routines that use \fIdie\fR. If you use \fIrequire\fR, be aware that mailagent is setting up a special \fI@INC\fR array by putting its private library path first, so you may place all your \fImailagent\fR-related library files in this place. ''' .SS Special Variables .PP The following special variables (some of them marked read-only, meaning you shouldn't modify them, and indeed you can't) made available directly within the \fInewcmd\fR package, are pre-set by the filter automaton, and are used to control the filtering process: .sp .TP 15 .I \$mfile The base name of the mail file being processed. This variable is read-only. It is mainly used in log messages, as in [\$mfile] to tag each log, since a single mailagent process may deal with multiple messages. .TP .I \$ever_saved This is a boolean, which should be \fIset\fR to \fB1\fR once a successful saving operation has been completed. If at the end of the filtering, this variable is still \fB0\fR, then the default LEAVE will be executed. .TP .I \$folder_saved The value of that variable governs the \fI\$msgpath\fR convenience variable set for PERL escapes. It is updated whenever a message is written to a file, to hold the path of the written file. .TP .I \$cont This is the continuation status, a variable of the utmost importance when dealing with the control flow. Four constants from the \fImain\fR package can be used to specify whether we should continue with the current rule (\$FT_CONT), abandon current rule (\$FT_REJECT), restart filtering from the beginning (\$FT_RESTART) or simply abort processing (\$FT_ABORT). More on this later. .TP .I \$lastcmd The last failure status recorded by the last command (among those which do modify the execution status). You should not have to update this by yourself unless you are implementing some encapsulation for other commands, like BACK or ONCE, since by default \fI\$lastcmd\fR will be set to the value you return at the end of the command. .TP .I \$wmode This records the current state of the filter automaton (working mode), in a literal string form, typically modified by the BEGIN command or as a side effect, as in REJECT for instance. .PP All the special variables set-up for PERL escapes are also installed within the \fInewcmd\fR package. Those are \fI\$login\fR, \fI%header\fR, etc... You may peruse them at will. .PP Other variables you might have a need for are configuration parameters, held in the \fI~/.mailagent\fR configuration file. Well, the rule is simple. The value of each parameter \fIparam\fR from the configuration file is held in variable \fI\$cf'param\fR. Variable \fI\$main'loglvl\fR is the copy of \fI\$cf'level\fR, since it's always shorter to type in \fI\$'loglvl\fR after each call to the logging routine \fI&add_log\fR. .PP There is one more variable worth knowing about: \fI\$main'FILTER\fR, which is the suitable X-Filter line that should be appended in \fBall\fR the mail you send via mailagent, in order to avoid loops. Also when you save mails to a folder, it's wise adding this line in case a problem arises: you may then identify the culprit. ''' .SS Rule Environment .PP An action might have a legitimate desire of altering the environment for the scope of one rule only, reverting to the previous value when exiting the rule. Or you might want to change the value forever. .PP When we speak about altering the environment, we refer to the one set up via the configuration file, whose values end-up in the \fIcf\fR package. Well, some of those variables are copied in the \fIenv\fR package before filtering of a message starts (under the control of the \fI@env'Env\fR array). .PP All rules should then refer to the version in the \fIenv\fR package, and not in the \fIcf\fR package, to see alterations. Global changes are made by affecting directly to the variable in the \fIenv\fR package, while local changes are requested by calling the \fI&env'local\fR routine. .PP For instance, the \fIcf'umask\fR value is copied as \fIenv'umask\fR because \fIumask\fR is held in \fI@env'Env\fR. Global changes are made by setting that copy directly, while local changes may be made with: .Ex &env'local('umask', 0722); .Ef to set-up a new local value. The first time \fI&env'local\fR is called on a variable, its value is saved somewhere, and will be restored upon exiting the scope of the rule. Then the new value is affected to the variable. .PP Variables requiring a side effect when their value is changed (such as the umask variable, which requires a system call to let the kernel see the change) may specify it by accessing the \fI%env'Spec\fR array, the key being the name of the variable requiring a side effect, the value being interpreted as a bit of perl code ran once the original value is restored. For instance, we say somewhere (in \fI&env'init\fR): .Ex package env; \$Spec{'umask'} = 'umask(\$umask)'; .Ef to update the kernel view when leaving scope. Note that the side effect is evaluated once the variable has recovered its original value, and within the \fIenv\fR package. .PP Internally, the \fI&analyze_mail\fR routine calls \fI&env'setup\fR before starting its processing to initialize the \fIenv\fR package, and \fI&env'cleanup\fR at the end before returning. Before running the actions specified on a rule match, \fI&apply_rules\fR calls \fI&env'restore\fR to ensure a coherent view of the environment while running the actions for that particular rule. ''' .SS Altering Control Flow .PP When you want to alter control flow to perform a REJECT, a RESTART or an ABORT, you have three choices. If you wish to control that action via an option, the same way the standard UNIQUE does (with \fB\-c\fR, \fB\-r\fR or \fB\-a\fR), you may call \fI&main'alter_execution(option, state)\fR giving it two parameters: the option letter and the state you wish to change to before altering the control flow. .PP You may also want to directly alter the \fI\$wmode\fR and \fI\$cont\fR variables, but then you'll have to do your own logging if you want some. Or you may call low-level routines \fI&main'do_reject\fR, \fI&main'do_restart\fR and \fI&main'do_abort\fR to perform the corresponding operation (with logging). .PP Remember that the _SEEN_ state is special and directly handled at the filter level, and the filter begins in the INITIAL state. The default action is to continue with the current rule, which is why there is no routine to perform this task. .PP The preferred way is to invoke the \fImailhook\fR interface functions, \fI&mailhook'begin\fR, \fI&mailhook'reject\fR, etc..., and that will work even if you redefine those functions yourself. Besides, that's the only interface which is likely not to be changed by new versions. ''' .SS General Purpose Routines .PP The following is a list of all the general routines you may wish to call when performing some low-level tasks. Note that this information is version-dependent. Since I document them, I'll try to keep them in new versions, but I cannot guarantee I will not have to slightly change some of their semantics. There is a good chance you will never have to worry about that anyway. .sp .TP 10 .I &header'format(rfc822-field) Return a formatted RFC822 field to fit in 78 columns, with proper continuations introduced by eight spaces. .TP .I &header'normalize(rfc822-header-name) Normalize case in RFC822 header and return the new header name with every first letter uppercased. .TP .I &header'reset This is part of an RFC822 header validation, mainly used when splitting a digest. This resets the recognition automaton (see &header'valid). .TP .I &header'valid(line) Returns a boolean status, indicating if all the lines given so far to this function since the last \fI&header'reset\fR are part of a valid RFC822 header. The function understands the first From line which is part of UNIX mails. At any time, the variable \fI\$header'maybe\fR may be checked to see if so far we have found at least one essential mail header field. .TP .I &main'acs_rqst(file) Perform a .lock locking on the file, returning 0 on success and -1 on failure. If an old lock was present, it is removed (time limit set to one hour). Use \fI&main'free_file\fR to release the lock. .TP .I &main'add_log(string) Add the \fIstring\fR to the logfile. The usual idiom is to postfix that call with the \fIif \$'loglvl > value\fR, where \fIvalue\fR is the logging level you wish to have before emitting that kind of log (\fI$'loglvl\fR is a short form for \fI\$main'loglvl\fR). .TP .I &main'free_file(file) Remove a .lock on a file, obtained by \fI&main'acs_rqst\fR. It returns 0 if the lock was successfully removed, -1 if it was a stale lock (obtained by someone else). .TP .I &main'header_found(file) Scan the head of a file and try to determine whether there is a mail header at the beginning or not. Return true if a header was found. .TP .I &main'history_record Record the message ID of the current message and return 0 if the message had not been previously seen, 1 if it is a duplicate. .TP .I &main'hostname Return the value of the hostname, lowercased, with possible domain name appended to it. The hostname is cached, since its value must initially be obtained by forking. (see also \fI&main'myhostname\fR) .TP .I &main'internet_info(email-address) Parse an e-mail internet address and return a three-element array containing the host, the domain and the country part of the internet host. For instance, if the address is \fIuser@d.c.b.a\fR, it will return \fI(c, b, a)\fR. .TP .I &main'login_name(email-address) Parse the e-mail internet address and return the login name. .TP .I &main'macros_subst(*line) Perform in-place macro substitution (line passed as a type glob) using the information currently held in the \fI%main'Header\fR array. Do \fInot\fR pass \fI*_\fR as a parameter, since internally \fImacros_subst\fR uses a local variable bearing that name to perform the substitutions and you would end up with an unmodified version. If you really want to pass \fI*_\fR, then you must use the returned value from \fImacros_subst\fR which is the substituted text, but that's less efficient than having it modified in place. .TP .I &main'makedir(pathname, mode) Make directory, creating all the intermediate directories needed to make \fIpathname\fR a valid directory. Has no effect if the directory already exists. The mode parameter is optional, 0700 is used (octal number) if not specified. .TP .I &main'myhostname Returns the hostname of the current machine, without any domain name. The hostname is cached, since its value must initially be obtained by forking. .TP .I &main'run_command(filter-command) Execute the single filter command specified and return the continuation status, which should normally be affected to the \fI\$cont\fR variable. You will need this routine when trying to implement commands which encapsulate other commands, like ONCE or SELECT. .TP .I &main'seconds_in_period(period) Return the number of seconds in the period specified. See section \fISpecifying A Period\fR to get valid period strings. .TP .I &main'shell_command(program, input, feedback) Run a shell command and return a failure status (0 for OK). The input parameter may be one of the following constants (defined in the \fImain\fR package): \$NO_INPUT to close standard input, \$BODY_INPUT to pipe the body of the current message, \$MAIL_INPUT to pipe the whole mail as-is, \$MAIL_INPUT_BINARY to pipe the whole mail after having removed any content transfer-encoding and \$HEADER_INPUT to pipe the message header. The feedback parameter may be one of \$FEEDBACK or \$NO_FEEDBACK depending whether or not you wish to use the standard output to alter the corresponding part of the message. If no feedback is wanted, the output of the command is mailed back to the user. The \$FEEDBACK_ENCODING is handled like \$FEEDBACK but will tell mailagent to look at the best suitable body encoding when the input is the whole message. .TP .I &main'parse_address(rfc822-address) Parse an RFC822 e-mail address and return a two-elements array containing the internet address and the comment part of that address. .TP .I &main'xeqte(filter-actions) Execute a series of actions separated by the ';' character, calling \fIrun_command\fR to actually perform the job. Return the continuation status. Note that \$FT_ABORT will \fInever\fR be returned, since mailagent usually stops after having executed one set of actions, only continuing if it saw an RESTART or a REJECT. What ABORT does is skipping the remaining commands on the line and exiting as if all the commands had been run. You could say \fIxeqte\fR is the equivalent of the \fIeval\fR function in perl, since it interprets a little filter script and returns control to the caller once finished, and ABORT is perl's \fIdie\fR. .PP You may also use the three functions from the \fIextern\fR package which manipulate persistent variables (already documented in the section dealing with variables) as well as the user-defined macro routines. ''' .SS Example .PP Writing your own commands is not easy, since it requires some basic knowledge regarding mailagent internals. However, once you are familiar with that, it should be relatively straightforward. .PP Here is a small example. We want to write a command to bounce back a mail message to the original sender, the way sendmail does, with some leading text to explain what happened. The command would have the following syntax: .Ex SENDBACK \fIreason\fR .Ef and we would like that command to modify the existing status, returning a failure if the mail cannot be bounced back. Since this command actually sends something back, we do not want it to be executed in the _SEEN_ state. Here is my implementation (untested): .Ex sub sendback { local(\$cmd_line) = @_; local(\$reason) = join(' ', @ARGV[1..\$#ARGV]); unless (open(MAILER, "|/usr/lib/sendmail -odq -t")) { &'add_log("ERROR cannot run sendmail to send message") if \$'loglvl; return 1; } print MAILER <