###
###  Copyright 2000-2007 University of Illinois Board of Trustees
###  All rights reserved. 
###
###  sendmail.pm - sendmail module for psgconf
###
###  Campus Information Technologies and Educational Services
###  University of Illinois at Urbana-Champaign
###


package PSGConf::Control::sendmail;

use strict;

use File::Basename;
use File::stat;

use PSGConf::Action::GenerateFile::sendmail_aliases;
use PSGConf::Action::GenerateFile::sendmail_mc;
use PSGConf::Action::GenerateFile::sendmail_cf;
use PSGConf::Action::GenerateFile::sendmail_trusted_users;
use PSGConf::Action::GenerateFile::sendmail_map;
use PSGConf::Action::MkDir;
use PSGConf::Action::RunCommand;
use PSGConf::Action::RestartDaemon;
use PSGConf::Data::Boolean;
use PSGConf::Data::List;
use PSGConf::Data::Hash;
use PSGConf::Data::Integer;
use PSGConf::Data::String;
use PSGConf::Control::Packages qw(_add_pkgs);
use PSGConf::Control::syslog qw(_add_syslog);


###############################################################################
###  plugin function for PSGConf::Action::RunCommand
###############################################################################

sub _check_map
{
	my ($self, $psgconf) = @_;
	my ($action, $ext, $st, $st2, $found, $cnt);

     $action = $psgconf->get_action($self->{filename});

     return 1
		if (defined($action) && $action->changed());

	$st = stat $self->{filename};

	###
	### Originally I was going to use the DATABASE_MAP_TYPE to determine
	### which extension to look for against the alias file, but I found
	### some sendmail installations would use one format for most maps but
	### the aliases file was a different format.  Now I am going to check
	### and make sure that I find at least one file that is newer.  If ALL
	### of the map files that we find are out of date, then run newaliases.
	###
	$found = $cnt = 0;
	foreach $ext ( 'db', 'dir', 'pag') {
		if ( -f $self->{filename} . '.' . ${ext} ) {
			$found++;
			$st2 = stat $self->{filename} . '.' . ${ext};

			### If our map file is newer than the
			### .dir/.pag or .db files, then cause the
			### map command to be rerun.
			$cnt++
				if ( $st->mtime > $st2->mtime );
		}
	}

	return ($cnt == $found)? 1: 0;
}


###############################################################################
###  policy methods
###############################################################################

### set up rc scripts
sub _policy_add_rc_scripts
{
	my ($self, $psgconf) = @_;
	my ($start_cmd);

	### FIXME:  Put this into the config files instead
	### set start command
	$start_cmd = $psgconf->data_obj('sendmail_path')->get() . ' -bd -q20m \
			&& ' . $psgconf->data_obj('rc_echo')->get() . ' " (MTA)\c" 
		if [ -s ' . $psgconf->data_obj('sendmail_cf_dir')->get() . '/submit.cf ]; then
			' . $psgconf->data_obj('sendmail_path')->get() . ' -L sm-msp -Ac -q20m \
				&& ' . $psgconf->data_obj('rc_echo')->get() . ' ", (MSP)\c" 
		fi';

	$start_cmd =~ s/-q20m/-qp/
		if ($psgconf->data_obj('sendmail_use_persistent_queue_runners')->equals('true'));

	$psgconf->data_obj('rc_scripts')->insert(
		{ 'sendmail' => {
			'state' => 'enable',
			'start_cmd' => $start_cmd
			}
		}
	) if ( $psgconf->data_obj('sendmail_enable')->equals('true') );
}


### add TCP wrappers entry
sub _policy_add_tcpwrapper_entry
{
     my ($self, $psgconf) = @_;

	### NOTE: Adding sendmail wrappers for all platforms, but I think
	### the only ones that need it are FreeBSD, RHEL3+, and Solaris 10

     return
          if ( $psgconf->data_obj('sendmail_enable')->equals('false') );

     $psgconf->data_obj('tcp_wrappers')->insert_row(
          { 1 => 'all' },
          [ 'sendmail', 'ALL', 'allow' ]
     )
          if (! $psgconf->data_obj('tcp_wrappers')->find_row(
                         { 0 => qr/\bsendmail\b/ }));
}

### add smmsp user and group
sub _policy_add_user
{
	my ($self, $psgconf) = @_;

	return
		if ($psgconf->data_obj('sendmail_enable')->equals('false'));

	$psgconf->data_obj('group_info')->insert(
		{ $psgconf->data_obj('sendmail_msa_group')->get() => {
			'recommended_gid' => $psgconf->data_obj('sendmail_msa_gid')->get()
			}
		} 
	) if (!defined $psgconf->data_obj('group_info')->find(
			$psgconf->data_obj('sendmail_msa_group')->get()));

	$psgconf->data_obj('user_info')->insert(
		{ $psgconf->data_obj('sendmail_msa_user')->get() => {
			'recommended_uid' => $psgconf->data_obj('sendmail_msa_uid')->get(),
			'passwd'		=> $psgconf->data_obj('passwd_token')->get(),
			'group'		=> $psgconf->data_obj('sendmail_msa_group')->get(),
			'gecos'		=> 'sendmail message submission program',
			'home'		=> '/var/spool/clientmqueue'
			}
		}
	) if (!defined $psgconf->data_obj('user_info')->find(
			$psgconf->data_obj('sendmail_msa_user')->get()));
}


### set confPID_FILE option
sub _policy_default_pidfile
{
	my ($self, $psgconf) = @_;

	return
		if ($psgconf->data_obj('sendmail_enable')->equals('false'));

	$psgconf->data_obj('sendmail_options')->insert(
		{ 'confPID_FILE' =>
				$psgconf->data_obj('pidfile_dir')->get() . '/sendmail.pid'
		}
	) if (!defined $psgconf->data_obj('sendmail_options')->find('confPID_FILE'));
}


### set default trusted-users file
sub _policy_default_ct_file
{
	my ($self, $psgconf) = @_;

	return
		if ($psgconf->data_obj('sendmail_enable')->equals('false'));

	if (!defined $psgconf->data_obj('sendmail_options')->find('confCT_FILE')
		&& $psgconf->data_obj('sendmail_trusted_users')->count()) {
		$psgconf->data_obj('sendmail_options')->insert(
			{ 'confCT_FILE' => '-o ' 
				. $psgconf->data_obj('sendmail_cf_dir')->get()
				. '/trusted-users' }
		);
		$psgconf->data_obj('sendmail_features')->insert(
			{ 'use_ct_file' => undef }
		);
	}
}


my %_default_aliases = (
	postmaster	=> 'root',
	'MAILER-DAEMON'	=> 'postmaster',
	nobody		=> '/dev/null'
);

### set default aliases
sub _policy_default_aliases
{
	my ($self, $psgconf) = @_;
	my ($aliases);

	$aliases = $psgconf->data_obj('sendmail_aliases')->get();

	map {
		$psgconf->data_obj('sendmail_aliases')->insert(
			{ $_ => $_default_aliases{$_} }
		) if (!defined $psgconf->data_obj('sendmail_aliases')->find($_));
	} keys %_default_aliases;
}


###############################################################################
###  decide() method
###############################################################################

sub _add_queue_dirs
{
	my ($self, $psgconf, $qdir, $uid, $gid) = @_;

	$psgconf->register_actions(
		PSGConf::Action::MkDir->new(
			name	=> $qdir,
			mode	=> $psgconf->data_obj('sendmail_queue_mode')->get(),
			uid => $uid,
			gid => $gid
		),
		($psgconf->data_obj('sendmail_queue_qf_subdirs')->equals('true')
		 ? (map {
			PSGConf::Action::MkDir->new(
				name	=> "$qdir/$_",
				mode	=> $psgconf->data_obj('sendmail_queue_mode')->get(),
				uid => $uid,
				gid => $gid
			)
		    } qw(qf df xf))
		 : ()
		),
	);
}

sub decide
{
	my ($self, $psgconf) = @_;
	my ($smopts, $smfeatures, $qgrps);
	my ($alias_file, $uid, $gid, $smmsp_gid, $smmsp_uid);
	my ($platform, $access_map, $mailertable, $map_type, $map_path);
	my ($num_queues, $qdir);

	return
		if ($psgconf->data_obj('sendmail_enable')->equals('false'));

	$smopts = $psgconf->data_obj('sendmail_options')->get();
	$smfeatures = $psgconf->data_obj('sendmail_features')->get();
	$qgrps = $psgconf->data_obj('sendmail_queue_groups')->get();
	$num_queues = $psgconf->data_obj('sendmail_num_queues_per_group')->get();

	$alias_file = $smopts->{'ALIAS_FILE'};
	$alias_file =~ s|,.*||;

	$smmsp_uid = $psgconf->data_obj('user_info')->find(
			$psgconf->data_obj('sendmail_msa_user')->get()
		)->{'uid'};

	$smmsp_gid = $psgconf->data_obj('group_info')->find(
			$psgconf->data_obj('sendmail_msa_group')->get()
		)->{'gid'};

	$uid = ( defined $psgconf->data_obj('user_info')->find($psgconf->data_obj('sendmail_mta_user')->get()))?
		$psgconf->data_obj('user_info')->find($psgconf->data_obj('sendmail_mta_user')->get())->{'uid'}:
		25;

	$gid = ( defined $psgconf->data_obj('group_info')->find($psgconf->data_obj('sendmail_mta_group')->get()))?
		$psgconf->data_obj('group_info')->find($psgconf->data_obj('sendmail_mta_group')->get())->{'gid'}:
		25;

	foreach $qdir ($smopts->{'QUEUE_DIR'},
		       map { $_->{Path} }
		           grep { exists($_->{Path}) }
			       (values %$qgrps))
	{
		if (substr($qdir, -1, 1) ne '*')
		{
			$self->_add_queue_dirs($psgconf, $qdir, $uid, $gid);
			next;
		}

		map {
			$self->_add_queue_dirs(
				$psgconf,
				sprintf('%s%0*d',
					substr($qdir, 0, length($qdir) - 1),
					length("$num_queues"),
					$_),
				$uid,
				$gid
			);
		} (1 .. $num_queues);
	}

	$psgconf->register_actions(
		PSGConf::Action::MkDir->new(
			'name'	=> $smopts->{'confHOST_STATUS_DIRECTORY'},
			'uid'		=> $uid,
			'gid'		=> $gid
		)
	)
		if (exists($smopts->{'confHOST_STATUS_DIRECTORY'}));

	$psgconf->register_actions(
		PSGConf::Action::MkDir->new(
			'name'		=> '/var/spool/clientmqueue',
			'uid'		=> $smmsp_uid,
			'gid'		=> $smmsp_gid,
			'mode'		=> 0770
		),
		PSGConf::Action::GenerateFile::sendmail_mc->new(
			'name'		=> $psgconf->data_obj('sendmail_cf_dir')->get() . '/sendmail.mc',
			'comment_str'	=> 'dnl',
			'description'	=> 'sendmail configuration file',
			'ostype'		=> $psgconf->data_obj('sendmail_ostype')->get(),
			'versionid'	=> 'sendmail.mc - generated by ' . $0,
			'uid'		=> $uid,
			'gid'		=> $gid,
			'defines'		=> $smopts,
			'features'	=> $smfeatures,
			'masquerade_as'	=> $psgconf->data_obj('sendmail_masquerade_as')->get(),
			'exposed_users'	=> $psgconf->data_obj('sendmail_exposed_users')->get(),
			'mailers'		=> [ qw(local smtp) ],
			'queue_groups'	=> $psgconf->data_obj('sendmail_queue_groups')->get(),
			'literal'		=> $psgconf->data_obj('sendmail_literal')->get()
		),
		PSGConf::Action::GenerateFile::sendmail_cf->new(
			'name'		=> $psgconf->data_obj('sendmail_cf_dir')->get() . '/sendmail.cf',
			'comment_str'	=> undef,
			'uid'		=> $uid,
			'gid'		=> $gid,
			'user'		=> $psgconf->data_obj('sendmail_mta_user')->get(),
			'mc_file'		=> $psgconf->data_obj('sendmail_cf_dir')->get() . '/sendmail.mc',
			'm4_command'	=> $psgconf->data_obj('sendmail_m4_command')->get(),
			'sendmail_m4_dir' => $psgconf->data_obj('sendmail_m4_dir')->get()
		),
		PSGConf::Action::GenerateFile::sendmail_mc->new(
			'name'		=> $psgconf->data_obj('sendmail_cf_dir')->get() . '/submit.mc',
			'comment_str'	=> 'dnl',
			'description'	=> 'MSP configuration file',
			'versionid'	=> 'submit.mc - generated by ' . $0,
			'uid'		=> $smmsp_uid,
			'gid'		=> $smmsp_gid,
			'defines'	=> {
				confCF_VERSION		=> 'Submit',
				__OSTYPE__		=> '',
				_USE_DECNET_SYNTAX_	=> 1,
				confTIME_ZONE		=> 'USE_TZ',
				confDONT_INIT_GROUPS	=> 'true',
				'confCT_FILE' => '-o ' 
					. $psgconf->data_obj('sendmail_cf_dir')->get()
					. '/trusted-users',
				confPID_FILE	=>  $psgconf->data_obj('pidfile_dir')->get() . '/sm-client.pid'
			},
			'features'	=> {
				use_ct_file	=> undef
			},
			### the msp feature must come at the end,
			### regardless of sort order
			'literal'	=> 'FEATURE(`msp\')dnl'
		),
		PSGConf::Action::GenerateFile::sendmail_cf->new(
			'name'		=> $psgconf->data_obj('sendmail_cf_dir')->get() . '/submit.cf',
			'comment_str'	=> undef,
			'uid'		=> $smmsp_uid,
			'gid'		=> $smmsp_gid,
			'mc_file'		=> $psgconf->data_obj('sendmail_cf_dir')->get() . '/submit.mc',
			'user'		=> $psgconf->data_obj('sendmail_mta_user')->get(),
			'm4_command'	=> $psgconf->data_obj('sendmail_m4_command')->get(),
			'sendmail_m4_dir' => $psgconf->data_obj('sendmail_m4_dir')->get()
		),
		PSGConf::Action::GenerateFile::sendmail_trusted_users->new(
			'name'		=> $psgconf->data_obj('sendmail_cf_dir')->get() . '/trusted-users',
			'description'	=> 'trusted users file',
			'uid'		=> $uid,
			'gid'		=> $gid,
			'trusted_users'	=> [ keys %{$psgconf->data_obj('sendmail_trusted_users')->get()} ]
		),
		PSGConf::Action::GenerateFile::sendmail_aliases->new(
			'name'		=> $alias_file,
			'description'	=> 'Local mail aliases',
			'uid'		=> $uid,
			'gid'		=> $gid,
			'aliases'	=> $psgconf->data_obj('sendmail_aliases')->get()
		),
		PSGConf::Action::RestartDaemon->new(
			name           => 'sendmail',
			pidfile        => $psgconf->data_obj('sendmail_options')->find('confPID_FILE'),
			filename       => 
				[ $psgconf->data_obj('sendmail_cf_dir')->get() . '/sendmail.cf',
					$psgconf->data_obj('sendmail_cf_dir')->get() . '/trusted-users' ]
		),
		PSGConf::Action::RestartDaemon->new(
			name           => 'msp',
			pidfile        => '/var/spool/clientmqueue/sm-client.pid',
			filename       => 
				[ $psgconf->data_obj('sendmail_cf_dir')->get() . '/submit.cf',
					$psgconf->data_obj('sendmail_cf_dir')->get() . '/trusted-users' ]
		),
		PSGConf::Action::RunCommand->new(
			name			=> 'sendmail alias file',
			command		=> $psgconf->data_obj('sendmail_newaliases_command')->get()
							. ' -C '
							. $psgconf->data_obj('sendmail_cf_dir')->get()
							.'/sendmail.cf',
			check_func	=> \&_check_map,
			filename		=> $alias_file
		)
	);

	$access_map = $psgconf->data_obj('sendmail_access_map')->get();
	if (%$access_map
	    && exists($smfeatures->{access_db}))
	{
		$map_type = $smfeatures->{access_db};
		$map_type =~ s/\s.*//;
		$map_type = $smopts->{DATABASE_MAP_TYPE}
			if ($map_type eq 'DATABASE_MAP_TYPE');

		$map_path = $smfeatures->{access_db};
		$map_path = (split(/\s+/, $map_path))[-1];

		$psgconf->register_actions(
			PSGConf::Action::GenerateFile::sendmail_map->new(
				name		=> $map_path,
				description	=> 'sendmail access map',
				entries		=> $access_map
			),
			PSGConf::Action::RunCommand->new(
				name			=> 'sendmail access map',
				command		=> $psgconf->data_obj('sendmail_makemap_command')->get()
						   . ' '
						   . $map_type
						   . ' '
						   . $map_path
						   . ' < '
						   . $map_path,
				check_func	=> \&_check_map,
				filename		=> $map_path
			)
		);
	}

	$mailertable = $psgconf->data_obj('sendmail_mailertable')->get();
	if (%$mailertable
	    && exists($smfeatures->{mailertable}))
	{
		$map_type = $smfeatures->{mailertable};
		$map_type =~ s/\s.*//;
		$map_type = $smopts->{DATABASE_MAP_TYPE}
			if ($map_type eq 'DATABASE_MAP_TYPE');

		$map_path = $smfeatures->{mailertable};
		$map_path = (split(/\s+/, $map_path))[-1];

		$psgconf->register_actions(
			PSGConf::Action::GenerateFile::sendmail_map->new(
				name		=> $map_path,
				description	=> 'sendmail mailertable',
				'uid'		=> $uid,
				'gid'		=> $gid,
				entries		=> $mailertable
			),
			PSGConf::Action::RunCommand->new(
				name			=> 'sendmail mailertable',
				command		=> $psgconf->data_obj('sendmail_makemap_command')->get()
						   . ' '
						   . $map_type
						   . ' '
						   . $map_path
						   . ' < '
						   . $map_path,
				check_func	=> \&_check_map,
				filename		=> $map_path
			)
		);
	}
}


###############################################################################
###  Constructor
###############################################################################

sub new
{
	my ($class, $psgconf) = @_;
	my ($self, %smopts, $cf_dir);

	$self = {};
	bless($self, $class);

	$cf_dir = '/etc/mail';

	%smopts = (
		'QUEUE_DIR'	=> '/var/spool/mqueue',
		'ALIAS_FILE'	=> $cf_dir . '/aliases'
	);

	### So that _add_pkgs knows which directives to look at
	$self->{name} = 'sendmail';
	$self->{enable} = $self->{name} . '_enable';
	$self->{packages} = $self->{name} . '_packages';

	### So that _add_syslog knows which directives to look at
	$self->{syslog} = 'mail';
	$self->{facility} = $self->{syslog} . '.info';

	$psgconf->register_data(
		'sendmail_m4_command'	=> PSGConf::Data::String->new(
						'value_abspath' => 1,
						value => '/usr/bin/m4'
					),
		'sendmail_m4_dir'	=> PSGConf::Data::String->new(
						'value_abspath' => 1,
						'value' => '/usr/share/sendmail'
					),
		'sendmail_cf_dir'	=> PSGConf::Data::String->new(
						'value_abspath' => 1,
						'value' => $cf_dir
					),
		'sendmail_path'		=> PSGConf::Data::String->new(
						'value_abspath' => 1,
						value => '/usr/sbin/sendmail'
					),
		'sendmail_makemap_command'
					=> PSGConf::Data::String->new(
						'value_abspath' => 1,
						value => '/usr/sbin/makemap'
					),
		'sendmail_newaliases_command'	=> PSGConf::Data::String->new(
						'value_abspath' => 1,
						value => '/usr/bin/newaliases'
					),
		'sendmail_enable'	=> PSGConf::Data::Boolean->new(
						'value' => 'false'
					),
		'sendmail_packages'	=> PSGConf::Data::List->new(),
		'sendmail_access_map'	=> PSGConf::Data::Hash->new(),
		'sendmail_mailertable'	=> PSGConf::Data::Hash->new(),
		'sendmail_aliases'	=> PSGConf::Data::Hash->new(),
		'sendmail_features'	=> PSGConf::Data::Hash->new(
						'value_optional' => 1
					),
		'sendmail_literal'	=> PSGConf::Data::String->new(),
		'sendmail_masquerade_as'
					=> PSGConf::Data::String->new(),
		'sendmail_exposed_users'	=> PSGConf::Data::List->new(),
		'sendmail_mta_user'	=> PSGConf::Data::String->new(
						value => 'root'
					),
		'sendmail_mta_group'	=> PSGConf::Data::String->new(
						value => 'daemon'
					),
		'sendmail_msa_user'	=> PSGConf::Data::String->new(
						value => 'smmsp'
					),
		'sendmail_queue_mode'	=> PSGConf::Data::Integer->new(
						value => 0755
					),
		'sendmail_msa_uid'	=> PSGConf::Data::Integer->new(
						value => 25
					),
		'sendmail_msa_group'	=> PSGConf::Data::String->new(
						value => 'smmsp'
					),
		'sendmail_msa_gid'	=> PSGConf::Data::Integer->new(
						value => 25
					),
		'sendmail_ostype'	=> PSGConf::Data::String->new(),
		'sendmail_options'	=> PSGConf::Data::Hash->new(
						'value' => \%smopts
					),
		'sendmail_trusted_users'
					=> PSGConf::Data::Hash->new(
						'value_optional' => 1
					),
		'sendmail_queue_groups'	=> PSGConf::Data::Hash->new(
						'value_type' => 'HASH'
					),
		'sendmail_queue_qf_subdirs'
					=> PSGConf::Data::Boolean->new(
						'value' => 'false'
					),
		'sendmail_num_queues_per_group'
					=> PSGConf::Data::Integer->new(
						value	=> 5
					),
		'sendmail_use_persistent_queue_runners'
					=> PSGConf::Data::Boolean->new(
						'value' => 'false'
					)
	);

	$psgconf->register_policy($self,
		sm_default_pidfile		=> '_policy_default_pidfile',
		sm_default_ct_file		=> '_policy_default_ct_file',
		sm_default_aliases		=> '_policy_default_aliases',
		sm_add_rc_scripts		=> '_policy_add_rc_scripts',
		sm_add_tcpwrapper_entry	=> '_policy_add_tcpwrapper_entry',
		sm_add_packages		=> '_add_pkgs',
		sm_add_syslog			=> '_add_syslog',
		sm_add_user			=> '_policy_add_user'
	);

	return $self;
}


###############################################################################
###  documentation
###############################################################################

1;

__END__

=head1 NAME

PSGConf::Control::sendmail - psgconf control class for sendmail

=head1 SYNOPSIS

In F<psgconf_modules>:

  Control PSGConf::Control::sendmail

=head1 DESCRIPTION

The B<PSGConf::Control::sendmail> module provides a B<psgconf> control object
for configuring C<sendmail>.  It supports the following methods:

=over 4

=item new()

The constructor.  Its parameter is a reference to the B<PSGConf>
object.  It registers the following data objects:

=over 4

=item I<sendmail_path>

A B<PSGConf::Data::String> object that contains the absolute path to the
C<sendmail> binary.  The default is C</usr/sbin/sendmail>.

=item I<sendmail_makemap_command>

A B<PSGConf::Data::String> object that contains the C<makemap> command to
be used to generate map files.  The default is C</usr/sbin/makemap>.

=item I<sendmail_newaliases_command>

A B<PSGConf::Data::String> object that contains the C<newaliases> command to
be used to generate alias files.  The default is C</usr/bin/newaliases>.

=item I<sendmail_enable>

A B<PSGConf::Data::Boolean> object that indicates whether C<sendmail>
should be configured.

=item I<sendmail_packages>

A B<PSGConf::Data::List> object that lists all packages to install.

=item I<sendmail_aliases>

A B<PSGConf::Data::Hash> object that contains entries for the
F<aliases> file.

=item I<sendmail_access_map>

A B<PSGConf::Data::Hash> object that contains entries for the
access map.

=item I<sendmail_mailertable>

A B<PSGConf::Data::Hash> object that contains entries for the
mailertable.

=item I<sendmail_m4_command>

A B<PSGConf::Data::String> object that contains the C<m4> command to
be used by the B<PSGConf::Action::GenerateFile::sendmail_cf> object's
check() method.  The default is C</usr/bin/m4>.

=item I<sendmail_m4_dir>

A B<PSGConf::Data::String> object that contains the absolute path to
the directory containing C<sendmail>'s C<m4> macros.  The default is
F</usr/share/sendmail>.

=item I<sendmail_cf_dir>

A B<PSGConf::Data::String> object that contains the absolute path to
the directory containing C<sendmail>'s config files.  The default is
F</etc/mail>.

=item I<sendmail_features>

A B<PSGConf::Data::Hash> object that contains the C<FEATURE()> macros
for the C<sendmail_cf_dir>F</sendmail.mc> file.  The hash key is the name
of the feature, and the optional value is the argument.  If the argument
is not enclosed in C<`'> quotes, they will be added.

=item I<sendmail_mta_user>

A B<PSGConf::Data::String> object that contains the name of the account
to own the sendmail queue directories and run the m4 command to build 
F<sendmail.cf> files.  Defaults to C<root>.

=item I<sendmail_mta_group>

A B<PSGConf::Data::String> object that contains the group name to own
the sendmail queue directories.  Defaults to C<daemon>.

=item I<sendmail_msa_user>

A B<PSGConf::Data::String> object that contains the login for the 
Sendmail Submission User.  Defaults to C<smmsp>.

=item I<sendmail_msa_uid>

A B<PSGConf::Data::Integer> object that contains the recommended uid for
the B<sendmail_msa_user> account.  Defaults to 25.

=item I<sendmail_msa_group>

A B<PSGConf::Data::String> object that contains the group name for the 
Sendmail Submission User.  Defaults to C<smmsp>.

=item I<sendmail_msa_gid>

A B<PSGConf::Data::Integer> object that contains the recommended gid for 
the B<sendmail_msa_user> account.  Defaults to 25.

=item I<sendmail_queue_mode>

A B<PSGConf::Data::Integer> object that contains the mode of the queue
directories.  The default is 0755.

=item I<sendmail_literal>

A B<PSGConf::Data::String> object that contains literal text to add to
the end of the C<sendmail_cf_dir>F</sendmail.mc> file.

=item I<sendmail_masquerade_as>

A B<PSGConf::Data::String> object that contains a hostname for
C<sendmail> to masquerade as.

=item I<sendmail_exposed_users>

A B<PSGConf::Data::List> object that contains list of users to have
C<sendmail> expose, even when I<sendmail_masquerade_as> is set.

=item I<sendmail_ostype>

A B<PSGConf::Data::String> object that contains the value for the
C<OSTYP> feature macro for the sendmail mc file.

=item I<sendmail_options>

A B<PSGConf::Data::Hash> object that contains the macros to be
C<define()>ed in the C<sendmail_cf_dir>F</sendmail.mc> file.  By default,
C<QUEUE_DIR> is set to F</var/spool/mqueue>, and C<ALIAS_FILE> is set to
C<sendmail_cf_dir>F</aliases>.

=item I<sendmail_trusted_users>

A B<PSGConf::Data::Hash> object whose keys are the list of C<sendmail>'s
trusted users.

=item I<sendmail_queue_groups>

A B<PSGConf::Data::Hash> object that contains the queue groups to be
configured in the C<sendmail_cf_dir>F</sendmail.mc> file.  The hash key is the
name of the queue group, and the value is an anonymous hash containing
the attributes for that queue group.

=item I<sendmail_queue_qf_subdirs>

A B<PSGConf::Data::Boolean> object that indicates whether the C<qf>,
C<df>, and C<xf> queue subdirectories should be created.

B<NOTE:> If you enable this on a system where C<sendmail> is already
running, you must stop C<sendmail>, go to each queue directory and move
all C<qf?*> files to the C<qf> subdirectory and all C<df?*> files to
the C<df> subdirectory, and then restart C<sendmail>.  Failure to do
this can result in lost messages!

=item I<sendmail_num_queues_per_group>

A B<PSGConf::Data::Integer> object that indicates the number of queues
to be created for each queue group.  This is only relevant if either
I<sendmail_queue_groups> is set or if the value of the C<QUEUE_DIR>
entry in I<sendmail_options> ends with a C<*>.

=item I<sendmail_use_persistent_queue_runners>

A B<PSGConf::Data::Boolean> object that indicates whether persistent
queue runners should be used.

=back

The constructor also registers the following policy methods:

=over 4

=item I<sm_add_rc_scripts>

Sets up the C<sendmail> RC script.  This is done using the I<rc_scripts>
data object, which are provided by the B<PSGConf::Control::InitScripts> module.

=item I<sm_add_user>

Adds the C<smmsp> user and group using the I<user_info> and
I<group_info> data objects, which are provided by the
B<PSGConf::Control::Users> module.

=item I<sm_add_tcpwrapper_entry>

Adds an entry for I<sendmail> to the I<tcp_wrappers> object (provided
by B<PSGConf::Control::TCPWrappers>).

=item I<sm_add_packages>

Requests that the C<sendmail> package be installed.  This is done using
the I<pkg_install_list> object, which is provided by the
B<PSGConf::Control::Packages> module.

=item I<sm_default_pidfile>

If the I<sendmail_options> object does not contain an entry for
C<confPID_FILE>, set it to F<I<pidfile_dir>/sendmail.pid>.  (The
I<pidfile_dir> object is provided by the B<PSGConf::Control::Core>
module.)

=item I<sm_default_ct_file>

If the I<sendmail_trusted_users> object has been set and the
I<sendmail_options> object does not contain an entry for C<confCT_FILE>,
set C<confCT_FILE> to C<-o sendmail_cf_dir/trusted-users> and add an entry
for C<use_ct_file> to the I<sendmail_features> object.

=item I<sm_default_aliases>

If there is no entry for C<postmaster> in the I<sendmail_aliases> data
object, set it to C<root>.

If there is no entry for C<MAILER-DAEMON> in the I<sendmail_aliases> data
object, set it to C<postmaster>.

If there is no entry for C<nobody> in the I<sendmail_aliases> data
object, set it to C</dev/null>.

=back

=item decide()

If I<sendmail_enable> is on, instantiates and registers action objects,
as follows:

=over 4

=item *

Registers B<PSGConf::Action::MkDir> action objects to create
any needed queue directories.  The queue directories are
calculated based on the values of the I<sendmail_queue_groups> and
I<sendmail_num_queues_per_group> data objects and the C<QUEUE_DIR>
entry in the I<sendmail_options> object.

=item *

Registers a B<PSGConf::Action::MkDir> action object to create the
F</var/spool/clientmqueue> directory.  The directory will be given mode
0770 with the group ID of the C<smmsp> group.  (The group ID is obtained
from the I<group_info> object, which is provided by the
B<PSGConf::Control::Users> module.)

=item *

Registers B<PSGConf::Action::GenerateFile::sendmail_mc> action objects
to create the C<sendmail_cf_dir>F</sendmail.mc> and
C<sendmail_cf_dir>F</submit.mc> files.

=item *

Registers B<PSGConf::Action::GenerateFile::sendmail_cf> action objects
to create the C<sendmail_cf_dir>F</sendmail.cf> and
C<sendmail_cf_dir>F</submit.cf> files.

=item *

Registers a B<PSGConf::Action::GenerateFile::sendmail_trusted_users>
object to create the C<sendmail_cf_dir>F</trusted-users> file.

=item *

Registers a B<PSGConf::Action::GenerateFile::sendmail_aliases> action
object to create the F<aliases> file and a B<PSGConf::Action::RunCommand>
action object to run C<newaliases>.  The path for the file is taken
from the C<ALIAS_FILE> entry in the I<sendmail_options> object.
The C<ALIAS_FILE> value will be truncated at the first C<,> character.

=item *

If C<confHOST_STATUS_DIRECTORY> is set in the I<sendmail_options> object,
registers a B<PSGConf::Action::MkDir> action object to create the
specified directory.

=item *

If I<sendmail_access_map> is set and I<sendmail_features> contains an
entry called C<access_db>, registers a
B<PSGConf::Action::GenerateFile::sendmail_map> object to create the
access map and a B<PSGConf::Action::RunCommand> object to run C<makemap>
on the new map file.

=item *

If I<sendmail_mailertable> is set, registers a
B<PSGConf::Action::GenerateFile::sendmail_map> object to create the
access map and a B<PSGConf::Action::RunCommand> object to run C<makemap>
on the new map file.

=back

=back

=head1 SEE ALSO

C<CE<lt>sendmail(8)E<gt>>

C<CE<lt>newaliases(1)E<gt>>

C<CE<lt>m4(1)E<gt>>

C<CE<lt>makemap(1)E<gt>>

L<perl>

L<PSGConf>

L<PSGConf::Action::GenerateFile::sendmail_aliases>

L<PSGConf::Action::GenerateFile::sendmail_mc>

L<PSGConf::Action::GenerateFile::sendmail_cf>

L<PSGConf::Action::GenerateFile::sendmail_trusted_users>

L<PSGConf::Action::GenerateFile::sendmail_map>

L<PSGConf::Action::MkDir>

L<PSGConf::Action::RunCommand>

L<PSGConf::Action::RestartDaemon>

L<PSGConf::Control::Core>

L<PSGConf::Control::InitScripts>

L<PSGConf::Control::Packages>

L<PSGConf::Control::TCPWrappers>

L<PSGConf::Control::Users>

L<PSGConf::Data::Boolean>

L<PSGConf::Data::Hash>

L<PSGConf::Data::String>

L<psgconf-intro>

=cut



syntax highlighted by Code2HTML, v. 0.9.1