###
### Copyright 2000-2007 University of Illinois Board of Trustees
### All rights reserved.
###
### syslog.pm - syslog module for psgconf
###
### Campus Information Technologies and Educational Services
### University of Illinois at Urbana-Champaign
###
package PSGConf::Control::syslog;
use strict;
use PSGConf::Action::GenerateFile::EnvFile;
use PSGConf::Action::GenerateFile::Literal;
use PSGConf::Action::GenerateFile::syslog_conf;
use PSGConf::Action::MkDir;
use PSGConf::Action::CreateFile;
use PSGConf::Action::ModifyFile;
use PSGConf::Action::RestartDaemon;
use PSGConf::Data::Boolean;
use PSGConf::Data::Hash;
use PSGConf::Data::List;
use PSGConf::Data::String;
use PSGConf::Control::Packages qw(_add_pkgs);
###############################################################################
### policy methods
###############################################################################
require Exporter;
our @ISA = qw (Exporter);
our %EXPORT_TAGS = ( 'all' => [ qw( _add_syslog) ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} });
our @EXPORT = qw();
### To be called from other Control modules
sub _add_syslog
{
my ($self, $psgconf) = @_;
if (!exists($self->{enable}) || $self->{enable} eq '' ) {
warn "\t!!!Control::syslog->_add_syslog(): no enable attribute(s)\n";
return;
}
return
if ($psgconf->data_obj($self->{enable})->equals('false'));
### Now check to make sure we are adding defined values in.
if ( !exists($self->{syslog}) || $self->{syslog} eq ''||
!exists($self->{facility}) || $self->{facility} eq '') {
warn "\t!!!Control::syslog->_add_syslog(): no syslog/facility attribute(s)\n";
return;
}
$psgconf->data_obj('syslog')->insert(
{ $self->{syslog} => $self->{facility} }
) if (!defined $psgconf->data_obj('syslog')->find($self->{syslog}));
}
### set default location for syslog_dir
sub _policy_default_dir
{
my ($self, $psgconf) = @_;
return
if ($psgconf->data_obj('syslog_enable')->equals('false'));
$psgconf->data_obj('syslog_dir')->prepend(
$psgconf->data_obj('log_dir')->get() . '/'
) if ( ! $psgconf->data_obj('syslog_dir')->match('^/'));
}
### set absolute path to log files
sub _policy_canonify_logfiles
{
my ($self, $psgconf) = @_;
my ($log, $new_log);
return
if ($psgconf->data_obj('syslog_enable')->equals('false'));
foreach $log (keys %{$psgconf->data_obj('syslog')->get()})
{
if (substr($log, 0, 1) ne '/' && substr($log, 0, 1) ne '@')
{
$new_log = $psgconf->data_obj('syslog_dir')->get() . "/$log";
$psgconf->data_obj('syslog')->insert(
{ $new_log => $psgconf->data_obj('syslog')->find($log) }
);
$psgconf->data_obj('syslog')->delete($log);
}
}
}
### handle platforms with "authpriv" facility
sub _policy_add_authpriv_facility
{
my ($self, $psgconf) = @_;
my ($target, $value);
return
if ($psgconf->data_obj('syslog_enable')->equals('false')
|| $psgconf->data_obj('platform')->match('solaris'));
foreach $target (sort keys %{$psgconf->data_obj('syslog')->get()})
{
$value = $psgconf->data_obj('syslog')->find($target);
$value =~ s/\bauth\b/$&,authpriv/;
$psgconf->data_obj('syslog')->insert(
{ $target => $value }
);
}
foreach $target (sort keys %{$psgconf->data_obj('syslog_literal')->get()})
{
$value = $psgconf->data_obj('syslog_literal')->find($target);
$value =~ s/\bauth\b/$&,authpriv/;
$psgconf->data_obj('syslog_literal')->insert(
{ $target => $value }
);
}
}
### expand USED_FACILITIES token
sub _policy_expand_used_facilities
{
my ($self, $psgconf) = @_;
my ($log, $levels, $facilities, %used_facilities, $default);
return
if ($psgconf->data_obj('syslog_enable')->equals('false'));
foreach $log (keys %{$psgconf->data_obj('syslog')->get()})
{
if ($psgconf->data_obj('syslog')->find($log) =~ m/USED_FACILITIES/)
{
$default = $log;
next;
}
foreach $levels (split(';', $psgconf->data_obj('syslog')->find($log)))
{
$levels =~ s/\.\w+//;
map {
$used_facilities{$_}++;
} split(',', $levels);
}
}
if (defined($default))
{
$facilities = join(',', sort keys %used_facilities);
$log = $psgconf->data_obj('syslog')->find($default);
$log =~ s/USED_FACILITIES/$facilities/;
$psgconf->data_obj('syslog')->insert(
{ $default => $log }
);
}
}
sub _policy_add_remote_servers
{
my ($self, $psgconf) = @_;
map {
$psgconf->data_obj('syslog')->insert(
{ '@' . $_ => '*.info' }
);
} @{$psgconf->data_obj('syslog_servers')->get()};
}
sub _policy_enable_rc_scripts
{
my ($self, $psgconf) = @_;
my ($args);
if ( $psgconf->data_obj('syslog_enable')->equals('true') ) {
$psgconf->data_obj('rc_scripts')->insert(
{ 'syslogd' => { 'state' => 'enable' }}
);
if ( $psgconf->data_obj('platform')->match('freebsd') ) {
$args =
$psgconf->data_obj('syslog_remote_enable')->equals('true')
? ''
: ($psgconf->data_obj('syslog_servers')->count()
### Turn off accepting packets remotely
? '-s '
### Turn off sending packets remotely, since
### we do not have any syslog_servers defined.
: '-ss ');
$psgconf->data_obj('rc_vars')->insert(
{ 'syslogd_flags' => $args . '-vv' }
);
}
}
}
###############################################################################
### ModfileFile plugin to edit /etc/rc.tcpip
###############################################################################
sub _modify_rc_tcpip {
my ($action, $infh, $fh, $psgconf) = @_;
my ($line);
while ($line = <$infh>) {
$line = 'start /usr/sbin/syslogd "$src_running"' .
($psgconf->data_obj('syslog_remote_enable')->equals('true')
? '': ' -r') . "\n"
if ($line =~ m|^start /usr/sbin/syslogd "\$src_running"( -r)?$| );
print $fh $line;
}
return 1;
}
###############################################################################
### decide() method
###############################################################################
sub decide
{
my ($self, $psgconf) = @_;
my ($file);
return
if ($psgconf->data_obj('syslog_enable')->equals('false'));
$psgconf->register_actions(
PSGConf::Action::GenerateFile::syslog_conf->new(
'name' => $psgconf->data_obj('syslog_file')->get(),
'description' => 'syslogd configuration file',
'syslog' => {
%{$psgconf->data_obj('syslog')->get()},
%{$psgconf->data_obj('syslog_literal')->get()}
}
),
PSGConf::Action::MkDir->new(
'name' => $psgconf->data_obj('syslog_dir')->get()
)
);
foreach $file ( keys %{$psgconf->data_obj('syslog')->get()}) {
if (substr($file, 0, 1) eq '/') {
$psgconf->register_actions(
PSGConf::Action::CreateFile->new(
'name' => $file
)
);
}
}
### Turn off accepting packets remotely
$psgconf->register_actions(
PSGConf::Action::GenerateFile::Literal->new(
'name' => '/etc/default/syslogd',
'content' => 'LOG_FROM_REMOTE=' .
($psgconf->data_obj('syslog_remote_enable')->equals('true')
? 'YES' : 'NO') . "\n"
)
) if ( $psgconf->data_obj('platform')->match('solaris'));
$psgconf->register_actions(
PSGConf::Action::GenerateFile::EnvFile->new(
'name' => '/etc/sysconfig/syslog',
'quote_values' => 1,
'vars' => {
'SYSLOGD_OPTIONS' => '-m 0' . ($psgconf->data_obj('syslog_remote_enable')->equals('true')? ' -r': ''),
'KLOGD_OPTIONS' => '-x'
}
)
) if ($psgconf->data_obj('platform')->match('(-rhel-)|(-rhl-)|(-fc-)'));
### Turn off accepting packets remotely
$psgconf->register_actions(
PSGConf::Action::ModifyFile->new(
'name' => '/etc/rc.tcpip',
'modify_func' => \&_modify_rc_tcpip,
'uid' => 0,
'gid' => 0,
'mode' => 0774
)
) if ( $psgconf->data_obj('platform')->match('aix'));
### Make sure we restart syslogd after we create all the files
$psgconf->register_actions(
PSGConf::Action::RestartDaemon->new(
name => 'syslogd',
filename => [ $psgconf->data_obj('syslog_dir')->get(),
$psgconf->data_obj('syslog_file')->get() ],
pidfile => $psgconf->data_obj('pidfile_dir')->get() . '/syslog.pid'
)
);
}
###############################################################################
### Constructor
###############################################################################
sub new
{
my ($class, $psgconf) = @_;
my ($self);
$self = {};
bless($self, $class);
### So that _add_pkgs knows which directives to look at
$self->{name} = 'syslog';
$self->{enable} = $self->{name} . '_enable';
$self->{packages} = $self->{name} . '_packages';
$psgconf->register_data(
'syslog_enable' => PSGConf::Data::Boolean->new(
value => 'true'
),
'syslog_remote_enable' => PSGConf::Data::Boolean->new(
value => 'false'
),
'syslog' => PSGConf::Data::Hash->new(),
'syslog_file' => PSGConf::Data::String->new(
'value_abspath' => 1,
'value' => '/etc/syslog.conf'
),
'syslog_dir' => PSGConf::Data::String->new(
'value' => 'syslog'
),
'syslog_literal' => PSGConf::Data::Hash->new(),
'syslog_packages' => PSGConf::Data::List->new(),
'syslog_servers' => PSGConf::Data::List->new()
);
$psgconf->register_policy($self,
syslog_default_dir => '_policy_default_dir',
syslog_canonify_logfiles
=> '_policy_canonify_logfiles',
syslog_add_authpriv_facility
=> '_policy_add_authpriv_facility',
syslog_expand_used_facilities
=> '_policy_expand_used_facilities',
syslog_enable_rc_scripts
=> '_policy_enable_rc_scripts',
syslog_add_packages => '_add_pkgs',
syslog_add_remote_servers => '_policy_add_remote_servers'
);
return $self;
}
###############################################################################
### documentation
###############################################################################
1;
__END__
=head1 NAME
PSGConf::Control::syslog - psgconf control class for syslog
=head1 SYNOPSIS
In F<psgconf_modules>:
Control PSGConf::Control::syslog
=head1 DESCRIPTION
The B<PSGConf::Control::syslog> module provides a B<psgconf> control object
for configuring C<syslogd>. 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<syslog_enable>
A B<PSGConf::Data::Boolean> object that indicates whether C<syslog>
should be configured. The default is true.
=item I<syslog_remote_enable>
A B<PSGConf::Data::Boolean> object that indicates whether C<syslog>
should accept remote packats. The default is false.
=item I<syslog_packages>
A B<PSGConf::Data::List> object that lists all packages to install.
=item I<syslog>
A B<PSGConf::Data::Hash> object that contains log file entries for
F<syslog.conf>. The hash key is the name of the file to create,
and the value is the facility and priority specification.
=item I<syslog_file>
A B<PSGConf::Data::String> object that contains the path for the
syslog config file. The default is F</etc/syslog.conf>.
=item I<syslog_dir>
A B<PSGConf::Data::String> object that contains the path to the
directory where log files will be stored. If not an absolute path, it
is relative to the value of the I<log_dir> object, which is supplied by
the B<PSGConf::Control::Core> module.
=item I<syslog_servers>
A B<PSGConf::Data::List> object that lists all remote syslog servers
to send data to.
=item I<syslog_literal>
A B<PSGConf::Data::Hash> object that contains non-file entries for
I<syslog_file>. The hash key is the target (e.g., a login name or
a C<*>), and the value is the facility and priority specification.
=back
The constructor also registers the following policy methods:
=over 4
=item I<syslog_default_dir>
If I<syslog_dir> is not set to an absolute path, prepend the value of
the I<log_dir> object, which is provided by the
B<PSGConf::Control::Core> module.
=item I<syslog_canonify_logfiles>
For each entry in the I<syslog> object that is not an absolute path,
prepend the value of the I<syslog_dir> object.
=item I<syslog_add_authpriv_facility>
On platforms other than Solaris, add the C<authpriv> facility to any
entry in I<syslog> or I<syslog_literal> that already specifies the
C<auth> facility.
=item I<syslog_expand_used_facilities>
Expands the token C<USED_FACILITIES> in the I<syslog> data object with
the list of facilities used by other entries in I<syslog>.
=item I<syslog_enable_rc_scripts>
Modifies the I<rc_scripts> data object (provided by
B<PSGConf::Control::InitScripts>) to enable C<syslogd>.
Also modifies the I<rc_vars> data object (provided by
B<PSGConf::Control::FreeBSD>) to set the C<syslogd> startup
flags to be C<-s -vv> or C<-ss -vv> if there are or are not
I<syslog_servers> defined, respectively.
=back
=item decide()
If the I<syslog_enable> data object is set, instantiates and registers
action objects, as follows:
=over 4
=item *
Registers a new B<PSGConf::Action::GenerateFile::syslog_conf> object to
create I<syslog_file>.
=item *
Registers a new B<PSGConf::Action::GenerateFile::Literal> object to
create I</etc/default/syslogd> on C<Solaris> systems.
=item *
Registers a new B<PSGConf::Action::MkDir> object to create the
I<syslog_dir> directory.
=item *
Registers new B<PSGConf::Action::CreateFile> objects for each file
in the I<syslog> object.
=item *
Registers new B<PSGConf::Action::ModifyFile> object for the
F</etc/rc.tcpip> file on AIX systems to add the C<-r> flag
to the startup of C<syslogd>.
=back
=back
=head1 SEE ALSO
syslog.conf(4)
L<perl>
L<PSGConf>
L<PSGConf::Action::GenerateFile::EnvFile>
L<PSGConf::Action::GenerateFile::Literal>
L<PSGConf::Action::GenerateFile::syslog_conf>
L<PSGConf::Action::MkDir>
L<PSGConf::Action::CreateFile>
L<PSGConf::Action::ModifyFile>
L<PSGConf::Action::RestartDaemon>
L<PSGConf::Control::Core>
L<PSGConf::Control::InitScripts>
L<PSGConf::Control::Packages>
L<PSGConf::Data::Boolean>
L<PSGConf::Data::Hash>
L<PSGConf::Data::List>
L<PSGConf::Data::String>
L<psgconf-intro>
=cut
syntax highlighted by Code2HTML, v. 0.9.1