#!/usr/bin/perl
	eval 'exec perl -S $0 "$@"'
		if $running_under_some_shell;

#
# This perl program uses dynamic loading [generated by perload]
#

# You'll need to set up a .forward file that feeds your mail to this script,
# via the filter. Mine looks like this:
#   "|exec /users/ram/mail/filter >>/users/ram/.bak 2>&1"

# $Id: magent.sh,v 3.0.1.17 2001/03/17 18:07: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: magent.sh,v $
# Revision 3.0.1.17  2001/03/17 18:07:49  ram
# patch72: mydomain and hiddennet now superseded by config vars
# patch72: changed email_addr() and domain_addr() to honour new config vars
#
# Revision 3.0.1.16  1999/01/13  18:08:48  ram
# patch64: changed agent_wait to AGENT_WAIT, now holding full path
#
# Revision 3.0.1.15  1997/09/15  15:05:06  ram
# patch57: call new pmail() routine to process main message
# patch57: fixed typo in -r usage
#
# Revision 3.0.1.14  1997/02/20  11:39:31  ram
# patch55: used  variable for no purpose
#
# Revision 3.0.1.13  1996/12/24  14:06:02  ram
# patch45: rule file path is now absolute, so caching can be safe
# patch45: changed queue processing/sleeping logic for better interactivity
# patch45: new stat constants, and updated usage line
#
# Revision 3.0.1.12  1995/09/15  13:54:28  ram
# patch43: rewrote mbox_lock routine to deal with new locksafe variable
# patch43: will now warn if configured to do flock() but can't actually
# patch43: can now be configured to do safe or allow partial mbox locking
#
# Revision 3.0.1.11  1995/08/31  16:26:54  ram
# patch42: forced numeric value when reading the Length header
#
# Revision 3.0.1.10  1995/08/07  16:12:03  ram
# patch37: now remove mailagent's lock as soon as possible before exiting
# patch37: added support for locking on filesystems with short filenames
#
# Revision 3.0.1.9  1995/03/21  12:54:50  ram
# patch35: added pl/cdir.pl to the list of appended files
#
# Revision 3.0.1.8  1995/02/16  14:24:42  ram
# patch32: new -I option for installation setup and checking
# patch32: usage message now sorts options by case type
#
# Revision 3.0.1.7  1995/02/03  17:57:16  ram
# patch30: also select hot piping on stderr to avoid problems on fork
#
# Revision 3.0.1.6  1995/01/03  17:56:52  ram
# patch24: new library files pl/rulenv.pl and pl/options.pl included
# patch24: no longer uses pl/umask.pl
#
# Revision 3.0.1.5  1994/10/29  17:40:14  ram
# patch20: added built-in biffing support
#
# Revision 3.0.1.4  1994/10/04  17:34:14  ram
# patch17: no longer report errors when orgname file is missing
# patch17: mailbox locking now uses customized mboxlock parameter
#
# Revision 3.0.1.3  1994/09/22  13:52:34  ram
# patch12: now performs &init_constants as soon as possible
# patch12: changed interface for &queue_mail to include first 2 letters
# patch12: context is loaded earlier to initialize callout queue
# patch12: added definition for , ,  and &abs
# patch12: changed &email_addr to cache its result and not rely on 'user
# patch12: moved &init_signals to pl/signals.pl as &catch_signals
#
# Revision 3.0.1.2  1994/07/01  14:54:29  ram
# patch8: fixed leading From date format (spacing problem)
#
# Revision 3.0.1.1  1994/01/26  09:27:56  ram
# patch5: new -F option to force procesing on filtered messages
#
# Revision 3.0  1993/11/29  13:48:22  ram
# Baseline for mailagent 3.0 netwide release.
#

# Perload ON

#
# The following were determined by Configure...
#

# Command used to compute hostname
$phostname = 'hostname';

# Our domain name
$mydomain = '.Unconfigured.Mailagent.Domain';

# Hidden network (advertised host)
$hiddennet = '';

# Directory where mail is spooled
$maildir = '/var/spool/mail';

# File in which mail is stored
$mailfile = '/var/spool/mail/%L';

# Current version number and patchlevel
$mversion = '3.1';
$patchlevel = '0';
$revision = '69';

# Want to lock mailboxes with flock ?
$lock_by_flock = '';

# Only use flock() and no .lock file
$flock_only = '';

# Our organization name
$orgname = '/etc/news/organization';

# Private mailagent library
$privlib = '/usr/share/mailagent';

# News posting program
$inews = 'inews';

# Mail sending program
$mailer = 'mail';

# Can we have filenames longer than 14 characters?
$long_filenames = 'define' eq 'define';

#
# End of configuration section.
#

$prog_name = $0;				# Who I am
$prog_name =~ s|^.*/(.*)|$1|;	# Keep only base name
$has_option = 0;				# True if invoked with options
$nolock = 0;					# Do we need to get a lock file?
$config_file = '~/.mailagent';	# Default configuration file
$log_level = -1;				# Changed by -L option

# Calling the mailagent as 'mailqueue' lists the queue
if ($prog_name eq 'mailqueue') {
	unshift(@ARGV, '-l');
}

# Parse options
while ($ARGV[0] =~ /^-/) {
	$_ = shift;
	last if /--/;
	if ($_ eq '-c') {		# Specify alternate configuration file
		++$nolock;			# Immediate processing wanted
		$config_file = shift;
	}
	elsif ($_ eq '-d') {	# Dump rules
		++$has_option;		# Incompatible with other special options
		++$dump_rule;
	}
	elsif ($_ eq '-e') {	# Rule supplied on command line
		$_ = shift;
		s/\n/ /g;
		push(@Linerules, $_);
		++$edited_rules;	# Signals rules came from command line
		++$nolock;			# Immediate processing wanted
	}
	elsif ($_ eq '-f') {	# Take messages from UNIX mailbox
		++$nolock;			# Immediate processing wanted
		++$mbox_mail;
		$mbox_file = shift;	# -f followed by file name
	}
	elsif ($_ eq '-h') {	# Usage help
		&usage;
	}
	elsif ($_ eq '-i') {	# Interactive mode: log messages also on stderr
		*add_log = *stderr_log;
	}
	elsif ($_ eq '-l') {	# List queue
		++$has_option;		# Incompatible with other special options
		++$list_queue;
		++$norule;			# No need to compile rules
	}
	elsif ($_ eq '-o') {	# Overwrite configuration variable
		++$nolock;			# Immediate processing wanted
		$over_config .= "\n" . shift;
	}
	elsif ($_ eq '-q') {	# Process the queue
		++$has_option;		# Incompatible with other special options
		++$run_queue;
	}
	elsif ($_ eq '-r') {	# Specify alternate rule file
		++$nolock;			# Immediate processing wanted
		$rule_file = shift;
		$rule_file = &cdir($rule_file);		# Make it an absolute path
	}
	elsif (/^-s(\S*)/) {	# Print statistics
		++$has_option;		# Incompatible with other special options
		++$stats;
		++$norule;			# No need to compile rules
		$stats_opt = $1;
	}
	elsif ($_ eq '-t') {	# Track rule matches on stdout
		++$track_all;
	}
	elsif ($_ eq '-F') {	# Force processing, even if already seen
		++$force_seen;
	}
	elsif ($_ eq '-I') {	# Install a suitable mailagent environment...
		++$has_option;		# That option must be the only one specified
		++$install_me;
	}
	elsif ($_ eq '-L') {	# Specify new logging level
		$log_level = int(shift);
	}
	elsif ($_ eq '-V') {	# Version number
		print STDERR "$prog_name $mversion-$revision\n";
		exit 0;
	}
	elsif ($_ eq '-U') {	# Do not allow UNIQUE to reject / abort
		++$disable_unique;
	}
	elsif ($_ eq '-TEST') {	# Mailagent run via TEST (undocumented feature)
		++$test_mode;
	}
	else {
		print STDERR "$prog_name: unknown option: $_\n";
		&usage;
	}
}

++$nolock if $has_option;		# No need to take a lock with special options

# Only one option at a time (among those options which change our goal)
if ($has_option > 1) {
	print STDERR "$prog_name: at most one special option may be specified.\n";
	exit 1;
}

exit(&cf'setup) if $install_me;	# Get a suitable configuration if -I

$file_name = shift;				# File name to be processed (null if stdin)
$ENV{'IFS'}='' if $ENV{'IFS'};	# Shell separation field
&init_constants;				# Constants definitions
&get_configuration;				# Get a suitable configuration package (cf)
&patch_constants;				# Change some constants after config
select(STDERR); $| = 1;			# In case we get perl warnings...
select(STDOUT);					# and because the -t option writes on STDOUT,
$| = 1;							# make sure it is flushed before we fork().
$privlib = "$cf'home/../.." if $test_mode;	# Tests ran from test/out
$AGENT_WAIT = "$cf'spool/agent.wait";		# Waiting file for mails

$orgname = &tilda_expand($orgname);		# Perform run-time ~name substitution

if ($orgname =~ m|^/|) {		# Name of organization kept in file
	unless (open(ORG, $orgname)) {
		&add_log("ERROR cannot read $orgname: $!") if $loglvl && -f $orgname;
	} else {
		chop($orgname = <ORG>);
		close ORG;
	}
}

$ENV{'HOME'} = $cf'home;
$ENV{'USER'} = $cf'user;
$ENV{'NAME'} = $cf'name;
$baselock = "$cf'spool/perl";	# This file does not exist
$lockext = $long_filenames ? '.lock' : '!';	# Extension used by lock routines
$lockfile = $baselock . $lockext;

umask(077);						# Files we create are private ones
$jobnum = &jobnum;				# Compute a job number

# Allow only ONE mailagent at a time (resource consumming)
&checklock($baselock);			# Make sure old locks do not remain
unless (-f $lockfile) {
	# Try to get the lock file (acting as a token). We do not need locking if
	# we have been invoked with an option and that option is not -q.
	if ($nolock && !$run_queue) {
		&add_log("no need to get a lock") if $loglvl > 19;
	} elsif (0 == &acs_rqst($baselock)) {
		&add_log("got the right to process mail") if $loglvl > 19;
		++$locked;
	} else {
		&add_log("denied right to process mail") if $loglvl > 19;
	}
}

if (!$locked && !$nolock) {
	# Another mailagent is running somewhere
	&queue_mail($file_name, 'fm');
	exit 0;
}

# Initialize mail filtering and compile filter rule if necessary
&init_all;
&compile_rules unless $norule;
&context'init;		# Load context, initialize callout queue

# If rules are to be dumped, this is the only action
if ($dump_rule) {
	&dump_rules(*print_rule_number, *void_func);
	unlink $lockfile if $locked;
	exit 0;
}

# Likewise, statistics dumping is the only option
if ($stats) {
	&report_stats($stats_opt);
	unlink $lockfile if $locked;
	exit 0;
}

# Listing the queue is also the only performed action
if ($list_queue) {
	&list_queue;
	unlink $lockfile if $locked;
	exit 0;
}

# Taking messages from mailbox file
if ($mbox_mail) {
	++$run_queue if 0 == &mbox_mail($mbox_file);
	unless ($run_queue) {
		unlink $lockfile if $locked;
		exit 1;		# -f failed
	}
	&add_log("processing queued mails") if $loglvl > 15;
}

# Suppress statistics when mailagent invoked manually (i.e. not in test mode)
&no_stats if $nolock && !$test_mode;

&read_stats;					# Load statistics into memory for fast update
&newcmd'load if $cf'newcmd;		# Load user-defined command definitions

#
# If -q is not specfied, we need to process the file which was given to us
# on the command line. We're calling pmail() to process it via locking,
# but unfortunately we can't allow pmail() to unlink the processed file,
# because it might be something the user wants to keep around...
# However, if we were invoked by the filter program, the processed mail
# will be unlinked later on. The trouble is the file was unlocked and
# there is a slight time window were the message could be processed again by
# another mailagent. If the 'queuehold' variable is reasonably set, such a
# message will be skipped anyway, so it's not that critical.
#

my $process_queue = 1;

if (!$run_queue) {				# Do not enter here if -q
	if (0 != &pmail($file_name, 0)) {
		&add_log("ERROR while processing main message--queing it") if $loglvl;
		&queue_mail($file_name, 'fm');
		unlink $lockfile;
		exit 0;					# Do not continue
	} 

	# If invoked from a tty and not in test mode, do not process queue
	$process_queue = 0 if -t STDOUT && !$test_mode; 
}

if ($process_queue) {
	unless ($test_mode) {
		# Fork a child: we have to take care of the filter script which is
		# waiting for us to finish processing of the delivered mail.
		&fork_child() unless $run_queue;

		# From now on, we are in the child process...
		# Don't sleep at all if logging level is greater that 11
		# or if $run_queue is true. Logging level of 12 and higher are
		# for debugging and should not be used on a permanent basis
		# anyway.

		$sleep = 1;					# Give others a chance to queue their mail
		$sleep = 0 if $loglvl > 11 || $run_queue;

		do {						# Eventually process the queue
			sleep 30 if $sleep;		# Wait in case new mail arrives
		} while (&pqueue);
	} else {
		&pqueue;					# Process the queue once in test mode
	}
}

# Mailagent is exiting. Remove lock file as early as possible to avoid a
# race condition: another mailagent could start up and decide another one
# is already processing mail, but since we're about to exit...
unlink $lockfile if $locked;
&add_log("mailagent exits") if $loglvl > 17;

# End of mailagent processing
&write_stats;					# Resynchronizes the statistics file
&compress'recompress;			# Compress some of the folders we delivered to
&contextual_operations;			# Perform all the contextual operations
exit 0;

sub main'usage { &auto_main'usage; }
sub auto_main'usage { &main'dataload; }

sub main'get_configuration { &auto_main'get_configuration; }
sub auto_main'get_configuration { &main'dataload; }

#
# The filtering routines
#

sub main'init_all { &auto_main'init_all; }
sub auto_main'init_all { &main'dataload; }

sub main'init_constants { &auto_main'init_constants; }
sub auto_main'init_constants { &main'dataload; }

sub main'patch_constants { &auto_main'patch_constants; }
sub auto_main'patch_constants { &main'dataload; }

sub main'init_env { &auto_main'init_env; }
sub auto_main'init_env { &main'dataload; }

sub main'init_pseudokey { &auto_main'init_pseudokey; }
sub auto_main'init_pseudokey { &main'dataload; }

#
# Miscellaneous utilities
#

sub main'mbox_lock { &auto_main'mbox_lock; }
sub auto_main'mbox_lock { &main'dataload; }

sub main'mbox_unlock { &auto_main'mbox_unlock; }
sub auto_main'mbox_unlock { &main'dataload; }

sub main'email_addr { &auto_main'email_addr; }
sub auto_main'email_addr { &main'dataload; }

sub main'domain_addr { &auto_main'domain_addr; }
sub auto_main'domain_addr { &main'dataload; }

sub main'tilda { &auto_main'tilda; }
sub auto_main'tilda { &main'dataload; }

# Compute absolute value -- on one line to avoid dataloading
sub abs { $_[0] > 0 ? $_[0] : -$_[0]; }

sub main'mailbox_name { &auto_main'mailbox_name; }
sub auto_main'mailbox_name { &main'dataload; }

sub main'fork_child { &auto_main'fork_child; }
sub auto_main'fork_child { &main'dataload; }

sub main'eval_error { &auto_main'eval_error; }
sub auto_main'eval_error { &main'dataload; }

sub main'jobnum { &auto_main'jobnum; }
sub auto_main'jobnum { &main'dataload; }

package cf;

# This package is responsible for keeping track of the configuration variables.

sub main'read_config { &auto_main'read_config; }
sub auto_main'read_config { &main'dataload; }

sub cf'parse { &auto_cf'parse; }
sub auto_cf'parse { &main'dataload; }

package main;

sub main'acs_rqst { &auto_main'acs_rqst; }
sub auto_main'acs_rqst { &main'dataload; }

sub main'acs_locktry { &auto_main'acs_locktry; }
sub auto_main'acs_locktry { &main'dataload; }

sub main'acs_lock { &auto_main'acs_lock; }
sub auto_main'acs_lock { &main'dataload; }

package lock;

sub lock'file { &auto_lock'file; }
sub auto_lock'file { &main'dataload; }

sub lock'base { &auto_lock'base; }
sub auto_lock'base { &main'dataload; }

sub lock'dir { &auto_lock'dir; }
sub auto_lock'dir { &main'dataload; }

package main;

sub main'free_file { &auto_main'free_file; }
sub auto_main'free_file { &main'dataload; }

sub main'add_log { &auto_main'add_log; }
sub auto_main'add_log { &main'dataload; }

sub main'stderr_log { &auto_main'stderr_log; }
sub auto_main'stderr_log { &main'dataload; }

sub main'stdout_log { &auto_main'stdout_log; }
sub auto_main'stdout_log { &main'dataload; }

#
# User-defined log files
#

package usrlog;

sub usrlog'new { &auto_usrlog'new; }
sub auto_usrlog'new { &main'dataload; }

sub usrlog'delete { &auto_usrlog'delete; }
sub auto_usrlog'delete { &main'dataload; }

sub main'usr_log { &auto_main'usr_log; }
sub auto_main'usr_log { &main'dataload; }

sub usrlog'write_log { &auto_usrlog'write_log; }
sub auto_usrlog'write_log { &main'dataload; }

package main;

sub main'checklock { &auto_main'checklock; }
sub auto_main'checklock { &main'dataload; }

#
# Lexical parsing of the rules
#

sub main'read_filerule { &auto_main'read_filerule; }
sub auto_main'read_filerule { &main'dataload; }

sub main'read_linerule { &auto_main'read_linerule; }
sub auto_main'read_linerule { &main'dataload; }

sub main'get_line { &auto_main'get_line; }
sub auto_main'get_line { &main'dataload; }

sub main'get_mode { &auto_main'get_mode; }
sub auto_main'get_mode { &main'dataload; }

sub main'get_selector { &auto_main'get_selector; }
sub auto_main'get_selector { &main'dataload; }

sub main'get_pattern { &auto_main'get_pattern; }
sub auto_main'get_pattern { &main'dataload; }

sub main'get_action { &auto_main'get_action; }
sub auto_main'get_action { &main'dataload; }

sub main'action_parse { &auto_main'action_parse; }
sub auto_main'action_parse { &main'dataload; }

#
# Parsing mail
#

sub main'parse_mail { &auto_main'parse_mail; }
sub auto_main'parse_mail { &main'dataload; }

sub main'header_parse { &auto_main'header_parse; }
sub auto_main'header_parse { &main'dataload; }

sub main'header_lines { &auto_main'header_lines; }
sub auto_main'header_lines { &main'dataload; }

sub main'header_update_size { &auto_main'header_update_size; }
sub auto_main'header_update_size { &main'dataload; }

sub main'body_check { &auto_main'body_check; }
sub auto_main'body_check { &main'dataload; }

sub main'body_recode_with { &auto_main'body_recode_with; }
sub auto_main'body_recode_with { &main'dataload; }

sub main'body_recode { &auto_main'body_recode; }
sub auto_main'body_recode { &main'dataload; }

sub main'body_recode_optimally { &auto_main'body_recode_optimally; }
sub auto_main'body_recode_optimally { &main'dataload; }

sub main'header_check_body_encoding { &auto_main'header_check_body_encoding; }
sub auto_main'header_check_body_encoding { &main'dataload; }

sub main'header_check { &auto_main'header_check; }
sub auto_main'header_check { &main'dataload; }

sub main'relay_list { &auto_main'relay_list; }
sub auto_main'relay_list { &main'dataload; }

sub main'header_append { &auto_main'header_append; }
sub auto_main'header_append { &main'dataload; }

sub main'header_prepend { &auto_main'header_prepend; }
sub auto_main'header_prepend { &main'dataload; }

sub main'best_body_encoding { &auto_main'best_body_encoding; }
sub auto_main'best_body_encoding { &main'dataload; }

#
# Analyzing mail
#

sub main'init_special { &auto_main'init_special; }
sub auto_main'init_special { &main'dataload; }

sub main'mail_logname { &auto_main'mail_logname; }
sub auto_main'mail_logname { &main'dataload; }

sub main'mail_logsize { &auto_main'mail_logsize; }
sub auto_main'mail_logsize { &main'dataload; }

sub main'analyze_mail { &auto_main'analyze_mail; }
sub auto_main'analyze_mail { &main'dataload; }

sub main'apply_rules { &auto_main'apply_rules; }
sub auto_main'apply_rules { &main'dataload; }

sub main'right_mode { &auto_main'right_mode; }
sub auto_main'right_mode { &main'dataload; }

sub main'special_user { &auto_main'special_user; }
sub auto_main'special_user { &main'dataload; }

sub main'fuzzy_domain { &auto_main'fuzzy_domain; }
sub auto_main'fuzzy_domain { &main'dataload; }

sub main'reception { &auto_main'reception; }
sub auto_main'reception { &main'dataload; }

sub main'track_rule { &auto_main'track_rule; }
sub auto_main'track_rule { &main'dataload; }


sub main'xeqte { &auto_main'xeqte; }
sub auto_main'xeqte { &main'dataload; }

sub main'run_command { &auto_main'run_command; }
sub auto_main'run_command { &main'dataload; }

sub main'init_filter { &auto_main'init_filter; }
sub auto_main'init_filter { &main'dataload; }

#
# Filter commands are run from here
#

sub main'run_process { &auto_main'run_process; }
sub auto_main'run_process { &main'dataload; }

sub main'run_server { &auto_main'run_server; }
sub auto_main'run_server { &main'dataload; }

sub main'run_leave { &auto_main'run_leave; }
sub auto_main'run_leave { &main'dataload; }

sub main'run_save { &auto_main'run_save; }
sub auto_main'run_save { &main'dataload; }

sub main'run_store { &auto_main'run_store; }
sub auto_main'run_store { &main'dataload; }

sub main'run_write { &auto_main'run_write; }
sub auto_main'run_write { &main'dataload; }

sub main'run_delete { &auto_main'run_delete; }
sub auto_main'run_delete { &main'dataload; }

sub main'run_macro { &auto_main'run_macro; }
sub auto_main'run_macro { &main'dataload; }

sub main'run_message { &auto_main'run_message; }
sub auto_main'run_message { &main'dataload; }

sub main'run_notify { &auto_main'run_notify; }
sub auto_main'run_notify { &main'dataload; }

sub main'run_reject { &auto_main'run_reject; }
sub auto_main'run_reject { &main'dataload; }

sub main'run_restart { &auto_main'run_restart; }
sub auto_main'run_restart { &main'dataload; }

sub main'run_abort { &auto_main'run_abort; }
sub auto_main'run_abort { &main'dataload; }

sub main'run_resync { &auto_main'run_resync; }
sub auto_main'run_resync { &main'dataload; }

sub main'run_begin { &auto_main'run_begin; }
sub auto_main'run_begin { &main'dataload; }

sub main'run_record { &auto_main'run_record; }
sub auto_main'run_record { &main'dataload; }

sub main'run_unique { &auto_main'run_unique; }
sub auto_main'run_unique { &main'dataload; }

sub main'run_forward { &auto_main'run_forward; }
sub auto_main'run_forward { &main'dataload; }

sub main'run_bounce { &auto_main'run_bounce; }
sub auto_main'run_bounce { &main'dataload; }

sub main'run_post { &auto_main'run_post; }
sub auto_main'run_post { &main'dataload; }

sub main'run_run { &auto_main'run_run; }
sub auto_main'run_run { &main'dataload; }

sub main'run_pipe { &auto_main'run_pipe; }
sub auto_main'run_pipe { &main'dataload; }

sub main'run_give { &auto_main'run_give; }
sub auto_main'run_give { &main'dataload; }

sub main'run_pass { &auto_main'run_pass; }
sub auto_main'run_pass { &main'dataload; }

sub main'run_feed { &auto_main'run_feed; }
sub auto_main'run_feed { &main'dataload; }

sub main'run_purify { &auto_main'run_purify; }
sub auto_main'run_purify { &main'dataload; }

sub main'run_back { &auto_main'run_back; }
sub auto_main'run_back { &main'dataload; }

sub main'run_on { &auto_main'run_on; }
sub auto_main'run_on { &main'dataload; }

sub main'run_once { &auto_main'run_once; }
sub auto_main'run_once { &main'dataload; }

sub main'run_select { &auto_main'run_select; }
sub auto_main'run_select { &main'dataload; }

sub main'run_nop { &auto_main'run_nop; }
sub auto_main'run_nop { &main'dataload; }

sub main'run_strip { &auto_main'run_strip; }
sub auto_main'run_strip { &main'dataload; }

sub main'run_keep { &auto_main'run_keep; }
sub auto_main'run_keep { &main'dataload; }

sub main'run_annotate { &auto_main'run_annotate; }
sub auto_main'run_annotate { &main'dataload; }

sub main'run_assign { &auto_main'run_assign; }
sub auto_main'run_assign { &main'dataload; }

sub main'run_tr { &auto_main'run_tr; }
sub auto_main'run_tr { &main'dataload; }

sub main'run_subst { &auto_main'run_subst; }
sub auto_main'run_subst { &main'dataload; }

sub main'run_split { &auto_main'run_split; }
sub auto_main'run_split { &main'dataload; }

sub main'run_vacation { &auto_main'run_vacation; }
sub auto_main'run_vacation { &main'dataload; }

sub main'run_queue { &auto_main'run_queue; }
sub auto_main'run_queue { &main'dataload; }

sub main'run_perl { &auto_main'run_perl; }
sub auto_main'run_perl { &main'dataload; }

sub main'run_require { &auto_main'run_require; }
sub auto_main'run_require { &main'dataload; }

sub main'run_apply { &auto_main'run_apply; }
sub auto_main'run_apply { &main'dataload; }

sub main'run_umask { &auto_main'run_umask; }
sub auto_main'run_umask { &main'dataload; }

sub main'run_after { &auto_main'run_after; }
sub auto_main'run_after { &main'dataload; }

sub main'run_do { &auto_main'run_do; }
sub auto_main'run_do { &main'dataload; }

sub main'run_beep { &auto_main'run_beep; }
sub auto_main'run_beep { &main'dataload; }

sub main'run_protect { &auto_main'run_protect; }
sub auto_main'run_protect { &main'dataload; }

sub main'run_biff { &auto_main'run_biff; }
sub auto_main'run_biff { &main'dataload; }

sub main'run_saving { &auto_main'run_saving; }
sub auto_main'run_saving { &main'dataload; }

sub main'alter_execution { &auto_main'alter_execution; }
sub auto_main'alter_execution { &main'dataload; }

sub main'save_message { &auto_main'save_message; }
sub auto_main'save_message { &main'dataload; }

#
# Matching functions
#

sub main'init_matcher { &auto_main'init_matcher; }
sub auto_main'init_matcher { &main'dataload; }

sub main'perl_pattern { &auto_main'perl_pattern; }
sub auto_main'perl_pattern { &main'dataload; }

sub main'make_pattern { &auto_main'make_pattern; }
sub auto_main'make_pattern { &main'dataload; }

sub main'match { &auto_main'match; }
sub auto_main'match { &main'dataload; }

sub main'apply_match { &auto_main'apply_match; }
sub auto_main'apply_match { &main'dataload; }

sub main'expr_selector_match { &auto_main'expr_selector_match; }
sub auto_main'expr_selector_match { &main'dataload; }

sub main'selector_match { &auto_main'selector_match; }
sub auto_main'selector_match { &main'dataload; }

# Pattern matching functions:
#	They are invoked as function($selector, $pattern, $range) and return true
#	if the pattern is found in the variable, according to some internal rules
#	which are different among the functions. For instance, match_single will
#	attempt a match with a login name or a regular pattern matching on the
#	whole variable if the pattern was not a single word.

sub main'match_single { &auto_main'match_single; }
sub auto_main'match_single { &main'dataload; }

sub main'match_list { &auto_main'match_list; }
sub auto_main'match_list { &main'dataload; }

sub main'match_var { &auto_main'match_var; }
sub auto_main'match_var { &main'dataload; }

#
# Backreference handling
#

sub main'reset_backref { &auto_main'reset_backref; }
sub auto_main'reset_backref { &main'dataload; }

sub main'update_backref { &auto_main'update_backref; }
sub auto_main'update_backref { &main'dataload; }

#
# Range interpolation
#

sub main'mrange { &auto_main'mrange; }
sub auto_main'mrange { &main'dataload; }

sub main'locate_file { &auto_main'locate_file; }
sub auto_main'locate_file { &main'dataload; }

sub main'locate_program { &auto_main'locate_program; }
sub auto_main'locate_program { &main'dataload; }


sub main'parse_address { &auto_main'parse_address; }
sub auto_main'parse_address { &main'dataload; }

sub main'login_name { &auto_main'login_name; }
sub auto_main'login_name { &main'dataload; }

sub main'last_name { &auto_main'last_name; }
sub auto_main'last_name { &main'dataload; }

sub main'internet_info { &auto_main'internet_info; }
sub auto_main'internet_info { &main'dataload; }

sub main'gen_message_id { &auto_main'gen_message_id; }
sub auto_main'gen_message_id { &main'dataload; }

#
# Macro handling (system)
#

sub main'macros_subst { &auto_main'macros_subst; }
sub auto_main'macros_subst { &main'dataload; }

package macro;

sub macro'info { &auto_macro'info; }
sub auto_macro'info { &main'dataload; }

sub macro'org { &auto_macro'org; }
sub auto_macro'org { &main'dataload; }

sub macro'domain { &auto_macro'domain; }
sub auto_macro'domain { &main'dataload; }

sub macro'internet { &auto_macro'internet; }
sub auto_macro'internet { &main'dataload; }

#
# Internal override feature
#

sub macro'overload { &auto_macro'overload; }
sub auto_macro'overload { &main'dataload; }

# Free routine defined by &overload
sub unload { undef &over }


package main;

package header;

# This package implements a header checker. To initialize it, call 'reset'.
# Then, call 'valid' with a header line and the function returns 0 if the
# line is not part of a header (which means all the lines seen since 'reset'
# are not part of a mail header). If the line may still be part of a header,
# returns 1. Finally, -1 is returned at the end of the header.

sub header'init { &auto_header'init; }
sub auto_header'init { &main'dataload; }

sub header'reset { &auto_header'reset; }
sub auto_header'reset { &main'dataload; }

sub header'valid { &auto_header'valid; }
sub auto_header'valid { &main'dataload; }

sub header'warning { &auto_header'warning; }
sub auto_header'warning { &main'dataload; }

sub header'clean { &auto_header'clean; }
sub auto_header'clean { &main'dataload; }

sub header'check { &auto_header'check; }
sub auto_header'check { &main'dataload; }

sub header'push { &auto_header'push; }
sub auto_header'push { &main'dataload; }

sub header'mta_date { &auto_header'mta_date; }
sub auto_header'mta_date { &main'dataload; }

sub header'normalize { &auto_header'normalize; }
sub auto_header'normalize { &main'dataload; }

sub header'msgid_cleanup { &auto_header'msgid_cleanup; }
sub auto_header'msgid_cleanup { &main'dataload; }

# Perload OFF

# Fixup one message ID by ensuring it has but one single "@" in it.
# Cannot be dataloaded since it is referenced from a regular expression
sub msgid_fix {
	my ($x, $fixupref) = @_;
	# Ensure at least one "@"
	unless ($x =~ /@/) {
		$$fixupref++;
		return $x . "\@faked-by-mailagent.local";
	}
	# Ensure only one "@"
	if ($x =~ tr/@/@/ > 1) {
		my ($leading, $trailing) = ($x =~ /(.*)@(.*)/);
		$leading =~ s/@/./g;
		$$fixupref++;
		return $leading . '@' . $trailing;
	}
	return $x;
}

# Perload ON

sub header'parsedate { &auto_header'parsedate; }
sub auto_header'parsedate { &main'dataload; }

sub header'format { &auto_header'format; }
sub auto_header'format { &main'dataload; }

sub header'news_fmt { &auto_header'news_fmt; }
sub auto_header'news_fmt { &main'dataload; }

sub main'header_found { &auto_main'header_found; }
sub auto_main'header_found { &main'dataload; }

package main;

#
# Implementation of filtering commands
#

sub main'leave { &auto_main'leave; }
sub auto_main'leave { &main'dataload; }

sub main'save { &auto_main'save; }
sub auto_main'save { &main'dataload; }

sub main'save_folder { &auto_main'save_folder; }
sub auto_main'save_folder { &main'dataload; }

sub main'save_hook { &auto_main'save_hook; }
sub auto_main'save_hook { &main'dataload; }

sub main'process { &auto_main'process; }
sub auto_main'process { &main'dataload; }

sub main'macro { &auto_main'macro; }
sub auto_main'macro { &main'dataload; }

sub main'message { &auto_main'message; }
sub auto_main'message { &main'dataload; }

sub main'notify { &auto_main'notify; }
sub auto_main'notify { &main'dataload; }

sub main'send_message { &auto_main'send_message; }
sub auto_main'send_message { &main'dataload; }

sub main'forward { &auto_main'forward; }
sub auto_main'forward { &main'dataload; }

sub main'bounce { &auto_main'bounce; }
sub auto_main'bounce { &main'dataload; }

sub main'post { &auto_main'post; }
sub auto_main'post { &main'dataload; }

sub main'apply { &auto_main'apply; }
sub auto_main'apply { &main'dataload; }

sub main'split { &auto_main'split; }
sub auto_main'split { &main'dataload; }

sub main'shell_command { &auto_main'shell_command; }
sub auto_main'shell_command { &main'dataload; }

sub main'popen_failed { &auto_main'popen_failed; }
sub auto_main'popen_failed { &main'dataload; }

sub main'alarm_clock { &auto_main'alarm_clock; }
sub auto_main'alarm_clock { &main'dataload; }

sub main'print_binary_mail { &auto_main'print_binary_mail; }
sub auto_main'print_binary_mail { &main'dataload; }

sub main'execute_command { &auto_main'execute_command; }
sub auto_main'execute_command { &main'dataload; }

sub main'handle_output { &auto_main'handle_output; }
sub auto_main'handle_output { &main'dataload; }

sub main'mail_back { &auto_main'mail_back; }
sub auto_main'mail_back { &main'dataload; }

sub main'feed_back { &auto_main'feed_back; }
sub auto_main'feed_back { &main'dataload; }

sub main'xeq_back { &auto_main'xeq_back; }
sub auto_main'xeq_back { &main'dataload; }

sub main'header_resync { &auto_main'header_resync; }
sub auto_main'header_resync { &main'dataload; }

sub main'alter_header { &auto_main'alter_header; }
sub auto_main'alter_header { &main'dataload; }

sub main'annotate_header { &auto_main'annotate_header; }
sub auto_main'annotate_header { &main'dataload; }


sub main'runop_on_field { &auto_main'runop_on_field; }
sub auto_main'runop_on_field { &main'dataload; }

sub main'alter_field { &auto_main'alter_field; }
sub auto_main'alter_field { &main'dataload; }

sub main'alter_value { &auto_main'alter_value; }
sub auto_main'alter_value { &main'dataload; }

sub main'perl { &auto_main'perl; }
sub auto_main'perl { &main'dataload; }

sub main'require { &auto_main'require; }
sub auto_main'require { &main'dataload; }

sub main'do { &auto_main'do; }
sub auto_main'do { &main'dataload; }

sub main'after { &auto_main'after; }
sub auto_main'after { &main'dataload; }

sub main'alter_flow { &auto_main'alter_flow; }
sub auto_main'alter_flow { &main'dataload; }

sub main'do_reject { &auto_main'do_reject; }
sub auto_main'do_reject { &main'dataload; }

sub main'do_restart { &auto_main'do_restart; }
sub auto_main'do_restart { &main'dataload; }

sub main'do_abort { &auto_main'do_abort; }
sub auto_main'do_abort { &main'dataload; }

sub main'complete_list { &auto_main'complete_list; }
sub auto_main'complete_list { &main'dataload; }

sub main'save_mail { &auto_main'save_mail; }
sub auto_main'save_mail { &main'dataload; }

sub main'empty_body { &auto_main'empty_body; }
sub auto_main'empty_body { &main'dataload; }

sub main'trace_dump { &auto_main'trace_dump; }
sub auto_main'trace_dump { &main'dataload; }

package stats;

$stats_wanted = 0;				# No statistics wanted by default
$new_record = 0;				# True when a new record is to be started
$start_date = 0;				# When statistics started
$suppressed = 0;				# Statistics suppressed by higher authority

# Suppress statistics. This function is called when options like -r or -e are
# used. Those usually specify one time rules and thus are not entitled to be
# recorded into the statistics.
sub main'no_stats { $suppressed = 1; }

sub main'read_stats { &auto_main'read_stats; }
sub auto_main'read_stats { &main'dataload; }

sub main'write_stats { &auto_main'write_stats; }
sub auto_main'write_stats { &main'dataload; }

sub stats'print_array { &auto_stats'print_array; }
sub auto_stats'print_array { &main'dataload; }

#
# Accounting routines
#

sub main's_filtered { &auto_main's_filtered; }
sub auto_main's_filtered { &main'dataload; }

sub main's_match { &auto_main's_match; }
sub auto_main's_match { &main'dataload; }

sub main's_default { &auto_main's_default; }
sub auto_main's_default { &main'dataload; }

sub main's_vacation { &auto_main's_vacation; }
sub auto_main's_vacation { &main'dataload; }

sub main's_saved { &auto_main's_saved; }
sub auto_main's_saved { &main'dataload; }

sub main's_seen { &auto_main's_seen; }
sub auto_main's_seen { &main'dataload; }

sub main's_action { &auto_main's_action; }
sub auto_main's_action { &main'dataload; }

sub main's_failed { &auto_main's_failed; }
sub auto_main's_failed { &main'dataload; }

sub main's_once { &auto_main's_once; }
sub auto_main's_once { &main'dataload; }

sub main's_noretry { &auto_main's_noretry; }
sub auto_main's_noretry { &main'dataload; }

#
# Low-level routines
#

sub stats'diff_rules { &auto_stats'diff_rules; }
sub auto_stats'diff_rules { &main'dataload; }

sub stats'fill_stats { &auto_stats'fill_stats; }
sub auto_stats'fill_stats { &main'dataload; }

#
# Reporting statistics
#

sub main'report_stats { &auto_main'report_stats; }
sub auto_main'report_stats { &main'dataload; }

sub stats'print_stats { &auto_stats'print_stats; }
sub auto_stats'print_stats { &main'dataload; }

sub stats'print_summary { &auto_stats'print_summary; }
sub auto_stats'print_summary { &main'dataload; }

sub stats'print_general { &auto_stats'print_general; }
sub auto_stats'print_general { &main'dataload; }

sub stats'print_commands { &auto_stats'print_commands; }
sub auto_stats'print_commands { &main'dataload; }

sub stats'uniform_rule { &auto_stats'uniform_rule; }
sub auto_stats'uniform_rule { &main'dataload; }

sub stats'print_rules_summary { &auto_stats'print_rules_summary; }
sub auto_stats'print_rules_summary { &main'dataload; }

#
# Hooks for rule dumping
#

sub stats'print_header { &auto_stats'print_header; }
sub auto_stats'print_header { &main'dataload; }

sub stats'rule_stats { &auto_stats'rule_stats; }
sub auto_stats'rule_stats { &main'dataload; }

package main;

sub main'qmail { &auto_main'qmail; }
sub auto_main'qmail { &main'dataload; }

sub main'queue_mail { &auto_main'queue_mail; }
sub auto_main'queue_mail { &main'dataload; }

sub main'waiting_mail { &auto_main'waiting_mail; }
sub auto_main'waiting_mail { &main'dataload; }

sub main'mv { &auto_main'mv; }
sub auto_main'mv { &main'dataload; }

sub main'same_device { &auto_main'same_device; }
sub auto_main'same_device { &main'dataload; }

sub main'pqueue { &auto_main'pqueue; }
sub auto_main'pqueue { &main'dataload; }

sub main'pmail { &auto_main'pmail; }
sub auto_main'pmail { &main'dataload; }

#
# Executing builtin commands
#

sub main'send_receipt { &auto_main'send_receipt; }
sub auto_main'send_receipt { &main'dataload; }

#
# Deal with builtins
#

sub main'init_builtins { &auto_main'init_builtins; }
sub auto_main'init_builtins { &main'dataload; }

# Whenever a builtin command is recognized (on the fly) while parsing the mail
# body, the corresponding builtin function is called with the remaining of the
# line given as argument (leading spaces removed).

sub main'builtin_rr { &auto_main'builtin_rr; }
sub auto_main'builtin_rr { &main'dataload; }

sub main'builtin_path { &auto_main'builtin_path; }
sub auto_main'builtin_path { &main'dataload; }

sub main'run_builtins { &auto_main'run_builtins; }
sub auto_main'run_builtins { &main'dataload; }

# Here are the data structures we use to store the compiled form of the rules:
#  @Rules has entries looking like "<$mode> {$action} $rulekeys..."
#  %Rule has entries looking like "$selector: $pattern"
# Each rule was saved in @Rules. The ruleskeys have the form H<num> where <num>
# is an increasing integer. They index the rules in %Rule.

sub main'compile_rules { &auto_main'compile_rules; }
sub auto_main'compile_rules { &main'dataload; }

sub main'default_rules { &auto_main'default_rules; }
sub auto_main'default_rules { &main'dataload; }

sub main'rule_cleanup { &auto_main'rule_cleanup; }
sub auto_main'rule_cleanup { &main'dataload; }

sub main'print_rule_number { &auto_main'print_rule_number; }
sub auto_main'print_rule_number { &main'dataload; }

sub main'void_func { &auto_main'void_func; }
sub auto_main'void_func { &main'dataload; }

sub main'exact_rule { &auto_main'exact_rule; }
sub auto_main'exact_rule { &main'dataload; }

sub nothing { }			 # Do nothing, really nothing

sub main'dump_rules { &auto_main'dump_rules; }
sub auto_main'dump_rules { &main'dataload; }

sub main'print_rule { &auto_main'print_rule; }
sub auto_main'print_rule { &main'dataload; }

#
# The following package added to hold all the new rule-specific functions
# added at version 3.0.
#

package rules;

sub rules'write_cache { &auto_rules'write_cache; }
sub auto_rules'write_cache { &main'dataload; }

sub rules'read_cache { &auto_rules'read_cache; }
sub auto_rules'read_cache { &main'dataload; }

sub rules'cache_ok { &auto_rules'cache_ok; }
sub auto_rules'cache_ok { &main'dataload; }

sub rules'write_fd { &auto_rules'write_fd; }
sub auto_rules'write_fd { &main'dataload; }

sub rules'writevar_fd { &auto_rules'writevar_fd; }
sub auto_rules'writevar_fd { &main'dataload; }

# Perload OFF
# (Used as a sort function, causes perl5 to dump core with native AUTOLOAD)

# Sorting for hash keys used by %Rule
sub hashkey {
	local($c) = $a =~ /^H(\d+)/;
	local($d) = $b =~ /^H(\d+)/;
	$c <=> $d;
}

# Perload ON

sub rules'alternate { &auto_rules'alternate; }
sub auto_rules'alternate { &main'dataload; }

package main;

sub main'seconds_in_period { &auto_main'seconds_in_period; }
sub auto_main'seconds_in_period { &main'dataload; }

sub main'relative_age { &auto_main'relative_age; }
sub auto_main'relative_age { &main'dataload; }

#
# The built-in expression interpreter
#

sub main'init_interpreter { &auto_main'init_interpreter; }
sub auto_main'init_interpreter { &main'dataload; }

sub main'set_priorities { &auto_main'set_priorities; }
sub auto_main'set_priorities { &main'dataload; }

sub main'set_functions { &auto_main'set_functions; }
sub auto_main'set_functions { &main'dataload; }

sub main'error { &auto_main'error; }
sub auto_main'error { &main'dataload; }

sub main'push_val { &auto_main'push_val; }
sub auto_main'push_val { &main'dataload; }

sub main'execute { &auto_main'execute; }
sub auto_main'execute { &main'dataload; }

sub main'update_stack { &auto_main'update_stack; }
sub auto_main'update_stack { &main'dataload; }

sub main'eval_expr { &auto_main'eval_expr; }
sub auto_main'eval_expr { &main'dataload; }

sub main'evaluate { &auto_main'evaluate; }
sub auto_main'evaluate { &main'dataload; }

#
# Boolean functions used by the interpreter. They all take two arguments
# and return 0 if false and 1 if true.
#

sub f_and { $_[0] && $_[1]; }		# Boolean AND
sub f_or { $_[0] || $_[1]; }		# Boolean OR
sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload; }

package main;

package getdate;

# This package parses a date string and converts it into a number of seconds.
# I did minor editing on this code, mainly to remove all the YYDEBUG #if tests
# and to reformat some of the table. I also encapsulated all the initializations
# into init subroutines and reworked on the indentation of semantic actions.
# Oh yes, I also made some minor modifications in place (i.e. without running
# yacc again) to apply some small fixes Richard sent me via e-mail.
# Other than that, it's pretty verbatim--RAM.

sub getdate'yyinit { &auto_getdate'yyinit; }
sub auto_getdate'yyinit { &main'dataload; }

sub yyclearin { $yychar = -1; }
sub yyerrok { $yyerrflag = 0; }
sub YYERROR { ++$yynerrs; &yy_err_recover; }
sub getdate'yy_err_recover { &auto_getdate'yy_err_recover; }
sub auto_getdate'yy_err_recover { &main'dataload; }

sub getdate'yyparse { &auto_getdate'yyparse; }
sub auto_getdate'yyparse { &main'dataload; }

sub getdate'dateconv { &auto_getdate'dateconv; }
sub auto_getdate'dateconv { &main'dataload; }

sub getdate'dayconv { &auto_getdate'dayconv; }
sub auto_getdate'dayconv { &main'dataload; }

sub getdate'timeconv { &auto_getdate'timeconv; }
sub auto_getdate'timeconv { &main'dataload; }

sub getdate'monthadd { &auto_getdate'monthadd; }
sub auto_getdate'monthadd { &main'dataload; }

sub getdate'daylcorr { &auto_getdate'daylcorr; }
sub auto_getdate'daylcorr { &main'dataload; }

sub getdate'yylex { &auto_getdate'yylex; }
sub auto_getdate'yylex { &main'dataload; }
		
sub getdate'lookup_init { &auto_getdate'lookup_init; }
sub auto_getdate'lookup_init { &main'dataload; }

sub getdate'lookup { &auto_getdate'lookup; }
sub auto_getdate'lookup { &main'dataload; }

sub main'getdate { &auto_main'getdate; }
sub auto_main'getdate { &main'dataload; }

sub getdate'yyerror { &auto_getdate'yyerror; }
sub auto_getdate'yyerror { &main'dataload; }

package main;

sub main'include_file { &auto_main'include_file; }
sub auto_main'include_file { &main'dataload; }

sub main'plural { &auto_main'plural; }
sub auto_main'plural { &main'dataload; }

sub main'myhostname { &auto_main'myhostname; }
sub auto_main'myhostname { &main'dataload; }

sub main'hostname { &auto_main'hostname; }
sub auto_main'hostname { &main'dataload; }

#
# MMDF-style saving routines
#

package mmdf;

sub mmdf'save { &auto_mmdf'save; }
sub auto_mmdf'save { &main'dataload; }
	
sub mmdf'save_mmdf { &auto_mmdf'save_mmdf; }
sub auto_mmdf'save_mmdf { &main'dataload; }

sub mmdf'save_unix { &auto_mmdf'save_unix; }
sub auto_mmdf'save_unix { &main'dataload; }

sub mmdf'force_flushing { &auto_mmdf'force_flushing; }
sub auto_mmdf'force_flushing { &main'dataload; }

sub mmdf'is_mmdf { &auto_mmdf'is_mmdf; }
sub auto_mmdf'is_mmdf { &main'dataload; }

sub mmdf'chmod { &auto_mmdf'chmod; }
sub auto_mmdf'chmod { &main'dataload; }

package main;

#
# Folder compression
#

package compress;

sub compress'init { &auto_compress'init; }
sub auto_compress'init { &main'dataload; }

sub compress'uncompress { &auto_compress'uncompress; }
sub auto_compress'uncompress { &main'dataload; }

sub compress'compress { &auto_compress'compress; }
sub auto_compress'compress { &main'dataload; }

sub compress'recompress { &auto_compress'recompress; }
sub auto_compress'recompress { &main'dataload; }

sub compress'restore { &auto_compress'restore; }
sub auto_compress'restore { &main'dataload; }

sub compress'is_compressed { &auto_compress'is_compressed; }
sub auto_compress'is_compressed { &main'dataload; }

sub compress'add_compressor { &auto_compress'add_compressor; }
sub auto_compress'add_compressor { &main'dataload; }

package main;


package newcmd;

#
# User-defined commands
#

sub newcmd'load { &auto_newcmd'load; }
sub auto_newcmd'load { &main'dataload; }

sub newcmd'run { &auto_newcmd'run; }
sub auto_newcmd'run { &main'dataload; }

package main;

sub main'q { &auto_main'q; }
sub auto_main'q { &main'dataload; }

#
# Mailhook handling
#

package hook;

sub hook'init { &auto_hook'init; }
sub auto_hook'init { &main'dataload; }

sub hook'process { &auto_hook'process; }
sub auto_hook'process { &main'dataload; }

sub hook'type { &auto_hook'type; }
sub auto_hook'type { &main'dataload; }

#
# Hook functions
#

sub hook'unknown { &auto_hook'unknown; }
sub auto_hook'unknown { &main'dataload; }

sub hook'program { &auto_hook'program; }
sub auto_hook'program { &main'dataload; }

sub hook'rules { &auto_hook'rules; }
sub auto_hook'rules { &main'dataload; }

sub hook'perl { &auto_hook'perl; }
sub auto_hook'perl { &main'dataload; }

sub hook'audit { &auto_hook'audit; }
sub auto_hook'audit { &main'dataload; }

sub hook'deliver { &auto_hook'deliver; }
sub auto_hook'deliver { &main'dataload; }

sub hook'hooking { &auto_hook'hooking; }
sub auto_hook'hooking { &main'dataload; }

package main;

sub main'file_secure { &auto_main'file_secure; }
sub auto_main'file_secure { &main'dataload; }

sub main'symdir_secure { &auto_main'symdir_secure; }
sub auto_main'symdir_secure { &main'dataload; }

sub main'symfile_secure { &auto_main'symfile_secure; }
sub auto_main'symfile_secure { &main'dataload; }

sub main'symdir_check { &auto_main'symdir_check; }
sub auto_main'symdir_check { &main'dataload; }

sub main'symfile_check { &auto_main'symfile_check; }
sub auto_main'symfile_check { &main'dataload; }

sub main'check_st_mode { &auto_main'check_st_mode; }
sub auto_main'check_st_mode { &main'dataload; }

sub main'exec_secure { &auto_main'exec_secure; }
sub auto_main'exec_secure { &main'dataload; }

sub main'cdir { &auto_main'cdir; }
sub auto_main'cdir { &main'dataload; }

#
# Command server
#

package cmdserv;

$loaded = 0;			# Set to true when loading done

sub cmdserv'init { &auto_cmdserv'init; }
sub auto_cmdserv'init { &main'dataload; }

sub cmdserv'load { &auto_cmdserv'load; }
sub auto_cmdserv'load { &main'dataload; }

sub cmdserv'process { &auto_cmdserv'process; }
sub auto_cmdserv'process { &main'dataload; }

#
# Command execution
#

sub cmdserv'execute { &auto_cmdserv'execute; }
sub auto_cmdserv'execute { &main'dataload; }

sub cmdserv'dispatch { &auto_cmdserv'dispatch; }
sub auto_cmdserv'dispatch { &main'dataload; }

sub cmdserv'exec_shell { &auto_cmdserv'exec_shell; }
sub auto_cmdserv'exec_shell { &main'dataload; }

sub cmdserv'exec_perl { &auto_cmdserv'exec_perl; }
sub auto_cmdserv'exec_perl { &main'dataload; }

sub cmdserv'exec_help { &auto_cmdserv'exec_help; }
sub auto_cmdserv'exec_help { &main'dataload; }

#
# Builtins
#

sub cmdserv'run_approve { &auto_cmdserv'run_approve; }
sub auto_cmdserv'run_approve { &main'dataload; }

sub cmdserv'run_power { &auto_cmdserv'run_power; }
sub auto_cmdserv'run_power { &main'dataload; }

sub cmdserv'run_release { &auto_cmdserv'run_release; }
sub auto_cmdserv'run_release { &main'dataload; }

sub cmdserv'run_powers { &auto_cmdserv'run_powers; }
sub auto_cmdserv'run_powers { &main'dataload; }

sub cmdserv'run_password { &auto_cmdserv'run_password; }
sub auto_cmdserv'run_password { &main'dataload; }

sub cmdserv'run_passwd { &auto_cmdserv'run_passwd; }
sub auto_cmdserv'run_passwd { &main'dataload; }

sub cmdserv'change_password { &auto_cmdserv'change_password; }
sub auto_cmdserv'change_password { &main'dataload; }

sub cmdserv'run_user { &auto_cmdserv'run_user; }
sub auto_cmdserv'run_user { &main'dataload; }

sub cmdserv'run_newpower { &auto_cmdserv'run_newpower; }
sub auto_cmdserv'run_newpower { &main'dataload; }

sub cmdserv'newpower { &auto_cmdserv'newpower; }
sub auto_cmdserv'newpower { &main'dataload; }

sub cmdserv'run_delpower { &auto_cmdserv'run_delpower; }
sub auto_cmdserv'run_delpower { &main'dataload; }

sub cmdserv'delpower { &auto_cmdserv'delpower; }
sub auto_cmdserv'delpower { &main'dataload; }

sub cmdserv'run_setauth { &auto_cmdserv'run_setauth; }
sub auto_cmdserv'run_sub f_ge { $_[0] >= $_[1]; }		# Greater or equal
sub f_le { $_[0] <= $_[1]; }		# Lesser or equal
sub f_lt { $_[0] < $_[1]; }			# Lesser than
sub f_gt { $_[0] > $_[1]; }			# Greater than
sub f_eq { "$_[0]" eq "$_[1]"; }	# Equal
sub f_ne { "$_[0]" ne "$_[1]"; }	# Not equal
sub f_match { $_[0] =~ /$_[1]/; }	# Pattern matches
sub f_nomatch { $_[0] !~ /$_[1]/; }	# Pattern does not match

package dbr;

sub dbr'hash_path { &auto_dbr'hash_path; }
sub auto_dbr'hash_path { &main'dataload; }

sub dbr'info { &auto_dbr'info; }
sub auto_dbr'info { &main'dataload; }

sub dbr'match { &auto_dbr'match; }
sub auto_dbr'match { &main'dataload; }

sub dbr'update { &auto_dbr'update; }
sub auto_dbr'update { &main'dataload; }

sub dbr'delete { &auto_dbr'delete; }
sub auto_dbr'delete { &main'dataload; }

sub dbr'default { &auto_dbr'default; }
sub auto_dbr'default { &main'dataload; }

sub dbr'clean { &auto_dbr'clean; }
sub auto_dbr'clean { &main'dataload; }

sub dbr'recursive_clean { &auto_dbr'recursive_clean; }
sub auto_dbr'recursive_clean { &main'dataload; }

sub dbr'clean_file { &auto_dbr'clean_file; }
sub auto_dbr'clean_file { &main'dataload; }

package main;

sub main'history_tag { &auto_main'history_tag; }
sub auto_main'history_tag { &main'dataload; }

sub main'history_ignore { &auto_main'history_ignore; }
sub auto_main'history_ignore { &main'dataload; }

sub main'history_record { &auto_main'history_record; }
sub auto_main'history_record { &main'dataload; }

sub main'once_check { &auto_main'once_check; }
sub auto_main'once_check { &main'dataload; }

sub main'makedir { &auto_main'makedir; }
sub auto_main'makedir { &main'dataload; }

#
# Emergency situation routines
#

# Perload OFF
# (Better not be dynamically loaded as it is a signal handler)

# Emergency signal was caught
sub emergency {
	local($sig) = @_;			# First argument is signal name
	if ($has_option) {			# Mailagent was invoked "manually"
		&resync;				# Resynchronize waiting file if necessary
		&add_log("ERROR trapped SIG$sig") if $loglvl;
		exit 1;
	}
	&fatal("trapped SIG$sig");
}

# Perload ON

sub main'fatal { &auto_main'fatal; }
sub auto_main'fatal { &main'dataload; }

sub main'emergency_save { &auto_main'emergency_save; }
sub auto_main'emergency_save { &main'dataload; }

sub main'dump_mbox { &auto_main'dump_mbox; }
sub auto_main'dump_mbox { &main'dataload; }

sub main'write_waitkeys { &auto_main'write_waitkeys; }
sub auto_main'write_waitkeys { &main'dataload; }

sub main'resync { &auto_main'resync; }
sub auto_main'resync { &main'dataload; }

sub main'list_queue { &auto_main'list_queue; }
sub auto_main'list_queue { &main'dataload; }

package mbox;

sub main'mbox_mail { &auto_main'mbox_mail; }
sub auto_main'mbox_mail { &main'dataload; }

sub mbox'flush_blanks { &auto_mbox'flush_blanks; }
sub auto_mbox'flush_blanks { &main'dataload; }

sub mbox'flush_buffer { &auto_mbox'flush_buffer; }
sub auto_mbox'flush_buffer { &main'dataload; }

sub mbox'flush { &auto_mbox'flush; }
sub auto_mbox'flush { &main'dataload; }

package main;

package context;

#
# General handling
#

sub context'init { &auto_context'init; }
sub auto_context'init { &main'dataload; }

sub context'default { &auto_context'default; }
sub auto_context'default { &main'dataload; }

sub context'load { &auto_context'load; }
sub auto_context'load { &main'dataload; }

sub context'clean { &auto_context'clean; }
sub auto_context'clean { &main'dataload; }

sub context'save { &auto_context'save; }
sub auto_context'save { &main'dataload; }

#
# Access features
#

sub context'set { &auto_context'set; }
sub auto_context'set { &main'dataload; }

sub context'get { &auto_context'get; }
sub auto_context'get { &main'dataload; }

sub context'delete { &auto_context'delete; }
sub auto_context'delete { &main'dataload; }

#
# Context-dependant actions
#

sub context'autoclean { &auto_context'autoclean; }
sub auto_context'autoclean { &main'dataload; }

#
# Perform all contextual actions
#

sub main'contextual_operations { &auto_main'contextual_operations; }
sub auto_main'contextual_operations { &main'dataload; }

package main;

#
# Persitent variables handling
#

package extern;

sub extern'val { &auto_extern'val; }
sub auto_extern'val { &main'dataload; }

sub extern'set { &auto_extern'set; }
sub auto_extern'set { &main'dataload; }

sub extern'age { &auto_extern'age; }
sub auto_extern'age { &main'dataload; }

package main;

#
# Various hook utilities
# (name in package hook, compiled in package mailhook)
#

package mailhook;

sub hook'initvar { &auto_hook'initvar; }
sub auto_hook'initvar { &main'dataload; }

sub hook'run { &auto_hook'run; }
sub auto_hook'run { &main'dataload; }

package main;

#
# Perl interface with the filter actions
#

package mailhook;

sub abort		{ &interface'dispatch; }
sub annotate	{ &interface'dispatch; }
sub apply		{ &interface'dispatch; }
sub assign		{ &interface'dispatch; }
sub back		{ &interface'dispatch; }
sub beep		{ &interface'dispatch; }
sub begin		{ &interface'dispatch; }
sub biff		{ &interface'dispatch; }
sub bounce		{ &interface'dispatch; }
sub delete		{ &interface'dispatch; }
sub feed		{ &interface'dispatch; }
sub forward		{ &interface'dispatch; }
sub give		{ &interface'dispatch; }
sub keep		{ &interface'dispatch; }
sub leave		{ &interface'dispatch; }
sub macro		{ &interface'dispatch; }
sub message		{ &interface'dispatch; }
sub nop			{ &interface'dispatch; }
sub notify		{ &interface'dispatch; }
sub on			{ &interface'dispatch; }
sub once		{ &interface'dispatch; }
sub pass		{ &interface'dispatch; }
sub perl		{ &interface'dispatch; }
sub pipe		{ &interface'dispatch; }
sub post		{ &interface'dispatch; }
sub process		{ &interface'dispatch; }
sub protect		{ &interface'dispatch; }
sub purify		{ &interface'dispatch; }
sub queue		{ &interface'dispatch; }
sub record		{ &interface'dispatch; }
sub reject		{ &interface'dispatch; }
sub require		{ &interface'dispatch; }
sub restart		{ &interface'dispatch; }
sub resync		{ &interface'dispatch; }
sub run			{ &interface'dispatch; }
sub save		{ &interface'dispatch; }
sub select		{ &interface'dispatch; }
sub server		{ &interface'dispatch; }
sub split		{ &interface'dispatch; }
sub store		{ &interface'dispatch; }
sub strip		{ &interface'dispatch; }
sub subst		{ &interface'dispatch; }
sub tr			{ &interface'dispatch; }
sub umask		{ &interface'dispatch; }
sub unique		{ &interface'dispatch; }
sub vacation	{ &interface'dispatch; }
sub write		{ &interface'dispatch; }

# Perload OFF
# A perl filtering script should call &exit and not exit directly.
# (Cannot be data-loaded or it will corrupt $@ expected by &main'perl)
sub exit { 
	local($code) = @_;
	die "OK\n" unless $code;
	die "Exit $code\n";
}
# Perload ON

package interface;

# Perload OFF
# (Cannot be dynamically loaded as it uses the caller() function)

# The dispatch routine is really simple. We compute the name of our caller,
# prepend it to the argument and call run_command to actually run the command.
# Upon return, if we get anything but a continue status, we simply die with
# an 'OK' string, which will be a signal to the routine monitoring the execution
# that nothing wrong happened.
sub dispatch {
	local($args) = join(' ', @_);			# Arguments for the command
	local($name) = (caller(1))[3];			# Function which called us
	local($status);							# Continuation status
	$name =~ s/^\w+('|::)//;				# Strip leading package name
	&'add_log("calling '$name $args'") if $'loglvl > 18;
	$status = &'run_command("$name $args");	# Case does not matter

	# The status propagation is the only thing we have to deal with, as this
	# is handled within run_command. All other variables which are meaningful
	# for the filter are dynamically bound to function called before in the
	# stack, hence they are modified directly from within the perl script.

	die "Status $status\n" unless $status == $'FT_CONT;

	# Return the status held in $lastcmd, unless the command does not alter
	# the status significantly, in which case we return success. Note that
	# this is in fact a boolean success status, so 1 means success, whereas
	# $lastcmd records a failure status.

	$name =~ tr/a-z/A-Z/;					# Stored upper-cased
	$'Nostatus{$name} ? 1 : !$'lastcmd;		# Propagate status
}

# Perload ON

$in_perl = 0;					# Number of nested perl evaluations

sub interface'new { &auto_interface'new; }
sub auto_interface'new { &main'dataload; }

sub interface'reset { &auto_interface'reset; }
sub auto_interface'reset { &main'dataload; }

sub interface'valid { &auto_interface'valid; }
sub auto_interface'valid { &main'dataload; }

sub interface'add { &auto_interface'add; }
sub auto_interface'add { &main'dataload;