#!/usr/bin/perl package loader; use Fcntl; use strict; use vars qw(@EXPORT_OK); @EXPORT_OK = qw(get_conf write_conf); #F_SETFD w/ fcntl() and $^F # This routine opens the file, then memoizes itself sub _open { local $^W = 0; my($fh,$type); if(open $fh, "+<&=27") { $type = 1; } elsif(open $fh, "<&=28") { $type = 0; } else { *_open = sub {}; warn "No conf file available: $!"; return; } fcntl($fh, F_GETFL, $_); *_open = sub { return($fh,$type); }; _open(); } # read conf and make it a data structure sub get_conf { my ($fh,$type) = _open(); my (%conf,%loader_comments); unless($fh) { warn("get_conf failed... no filehandle"); return; } local $_; while(<$fh>) { my($k,$v); next if /^\s+\#/; chomp; if(/^\#\s*(?:([^:]+):)?/) { push @{$loader_comments{$1}}, $_; } elsif((($k,$v) = split /:\s*/, $_, 2) == 2) { if($conf{$k}) { if(ref $conf{$k}) { push @{$conf{$k}}, $v; } else { $conf{$k} = [$conf{$k}, $v]; } } else { $conf{$k} = $v; } } } # save the comments for the nice people *_comments = sub { \%loader_comments; }; return wantarray ? %conf : \%conf; } # write conf data back to file, if it is writeable sub write_conf { my ($fh,$type) = _open(); unless($type) { warn("Conf file not writeable\n"); return; } my %conf; if(@_ == 1) { if(ref $_[0] eq 'HASH') { %conf = %{$_[0]}; } else { warn "Need to pass write_conf a hash or hash ref"; return; } } else { if(@_ % 2) { warn "Odd number of arguments to write_hash. Need to pass write_conf a hash or hash ref"; return; } %conf = @_; } seek($fh, 0, 0); my $c = &_comments; # write general comments at top for my $comment (@{$c->{''}}) { print $fh "$comment\n"; } print $fh "\n"; for my $k (sort keys %conf) { $c->{$k}[0] ||= "# $k: "; # write comments for indivisual keys for my $comment (@{$c->{$k}}) { print $fh "$comment\n"; } if(ref $conf{$k}) { for my $a (@{$conf{$k}}) { print $fh "$k: $a\n"; } } else { print $fh "$k: $conf{$k}\n"; } print $fh "\n"; } truncate $fh, tell $fh; } # close your file handles! END { my $fh = (_open())[0]; close $fh if $fh; } 1;