package Init::Freebsd::RCConf; use strict; use warnings; use Carp; use Fcntl qw(:flock); use FindBin; use Init::Freebsd::RCConf::Line; use File::Copy; use Class::Std; { my %file : ATTR( :get :set ); my %file_name : ATTR( :get :set ); sub BUILD { my ( $self, $ident, $args_ref ) = @_; $file_name{$ident} = (-f '/etc/rc.conf') ? '/etc/rc.conf' : $FindBin::Bin . '/rc.conf'; $file{$ident} = []; $self->load(); } sub add_line : RESTRICTED { my $self = shift; my $line = shift; my $ident = ident($self); push @{ $file{$ident} }, $line; } sub load { my $self = shift; my $ident = ident($self); open my $read_fh, '<', $self->get_file_name() or croak('Can not find ' . $self->get_file_name() . ': ' . $!); flock($read_fh, LOCK_SH); while ( <$read_fh> ) { chomp; #print $_ . "\n"; my $line = Init::Freebsd::RCConf::Line->new( { line => $_ } ); $self->add_line($line); } close($read_fh); } sub set_value { my $self = shift; my $key = shift; my $value = shift; my $ident = ident($self); $key .= '_enable'; $value = sprintf(qq{"%s"}, $value); for my $line (@{ $file{$ident} }) { if ( $line->get_key() eq $key ) { $line->set_value($value); return; } } # If we've made it this far, it must be new line and # will be added to the end of the file my $new_line = Init::Freebsd::RCConf::Line->new(); $new_line->set_key($key); $new_line->set_value($value); $self->add_line($new_line); } sub write_file { my $self = shift; my $ident = ident($self); my $temp_file = '/tmp/temp.rc.conf'; open my $write_fh, '>', $temp_file or die 'Cannot open '. $temp_file . ': ' . $!; flock($write_fh, LOCK_EX); for my $line ( @{ $file{$ident} } ) { print {$write_fh} $line->print_line() . "\n"; } close($write_fh); File::Copy::copy($temp_file, $self->get_file_name()) or croak 'Unable to copy file ' . "$!"; unlink $temp_file if (-s $self->get_file_name() ); } } 1;