File Coverage

blib/lib/EB/Config.pm
Criterion Covered Total %
statement 86 154 55.8
branch 19 70 27.1
condition 5 12 41.6
subroutine 15 23 65.2
pod 0 1 0.0
total 125 260 48.0


line stmt bran cond sub pod time code
1             #! perl -- -*- coding: utf-8 -*-
2              
3 6     6   186706 use utf8;
  6         34  
  6         57  
4              
5             # Config.pm -- Configuration files.
6             # Author : Johan Vromans
7             # Created On : Fri Jan 20 17:57:13 2006
8             # Last Modified By: Johan Vromans
9             # Last Modified On: Thu Aug 31 10:01:04 2017
10             # Update Count : 263
11             # Status : Unknown, Use with caution!
12              
13             package main;
14              
15             our $cfg;
16             our $dbh;
17              
18             package EB::Config;
19              
20 6     6   360 use strict;
  6         14  
  6         136  
21 6     6   27 use warnings;
  6         8  
  6         151  
22 6     6   24 use Carp;
  6         12  
  6         353  
23 6     6   35 use File::Spec;
  6         11  
  6         3577  
24              
25             sub init_config {
26 6     6 0 19 my ($pkg, $opts) = @_;
27 6         10 my $app;
28              
29             Carp::croak("Internal error -- missing package arg for __PACKAGE__\n")
30 6 50       32 unless $app = delete $opts->{app};
31              
32 6         17 $app = lc($app);
33              
34 6 0 33     24 return if $::cfg && $app && $::cfg->{app} eq lc($app);
      33        
35              
36             # Pre-parse @ARGV for "-f configfile".
37 6         10 my $extraconf = $opts->{config};
38 6         12 my $skipconfig = $opts->{nostdconf};
39              
40             # Resolve extraconf to a file name. It must exist.
41 6 50       15 if ( $extraconf ) {
42 0 0       0 if ( -d $extraconf ) {
43 0         0 my $f = File::Spec->catfile( $extraconf,
44             EB::Config::Handler::std_config($app) );
45 0 0       0 if ( -e $f ) {
46 0         0 $extraconf = $f;
47             }
48             else {
49 0         0 $extraconf = File::Spec->catfile($extraconf,
50             EB::Config::Handler::std_config_alt($app));
51             }
52             }
53 0 0       0 die("$extraconf: $!\n") unless -f $extraconf;
54             }
55              
56             # Build the list of config files.
57 6         11 my @cfgs;
58 6 100       18 if ( !$skipconfig ) {
59 2         7 @cfgs = ( File::Spec->catfile( "etc", $app,
60             EB::Config::Handler::std_config($app) ),
61             EB::Config::Handler::user_dir
62             ( $app, EB::Config::Handler::std_config($app) ),
63             );
64 2 50       10 unless ( $extraconf ) {
65 2         4 push(@cfgs, EB::Config::Handler::std_config($app));
66 2 50       39 $cfgs[-1] = EB::Config::Handler::std_config_alt($app) unless -e $cfgs[-1];
67             }
68             }
69 6 50       21 push(@cfgs, $extraconf) if $extraconf;
70              
71             # Load configs.
72 6         28 my $cfg = EB::Config::Handler->new($app);
73 6         31 for my $file ( @cfgs ) {
74 6 50       84 next unless -s $file;
75 0         0 $cfg->load($file);
76             }
77              
78 6 50       50 if ( $opts->{define} ) {
79 0         0 while ( my ($k, $v) = each( %{ $opts->{define} } ) ) {
  0         0  
80 0 0       0 if ( $k =~ /^(\w+(?:::\w+)*)::?(\w+)/ ) {
81 0         0 $cfg->newval($1, $2, $v);
82             }
83             else {
84 0         0 warn("define error: \"$k\" = \"$v\"\n");
85             }
86             }
87             }
88              
89 6         23 $cfg->_plug(qw(database name EB_DB_NAME));
90              
91 6 50       17 if ( my $db = $cfg->val(qw(database name), undef) ) {
92 0         0 $db =~ s/^eekboek_//; # legacy
93 0         0 $cfg->newval(qw(database name), $db);
94 0         0 $ENV{EB_DB_NAME} = $db;
95             }
96              
97 6         36 $cfg->_plug(qw(database host EB_DB_HOST));
98 6         22 $cfg->_plug(qw(database port EB_DB_PORT));
99 6         13 $cfg->_plug(qw(database user EB_DB_USER));
100 6         16 $cfg->_plug(qw(database password EB_DB_PASSWORD));
101              
102 6         16 $cfg->_plug(qw(csv separator EB_CSV_SEPARATOR));
103              
104 6         14 $cfg->_plug(qw(internal now EB_SQL_NOW));
105              
106 6         12 $cfg->_plug("internal sql", qw(trace EB_SQL_TRACE));
107 6         12 $cfg->_plug("internal sql", qw(prepstats EB_SQL_PREP_STATS));
108 6         15 $cfg->_plug("internal sql", qw(replayout EB_SQL_REP_LAYOUT));
109              
110 6 50       27 if ( $cfg->val(__PACKAGE__, "showfiles", 0) ) {
111 0         0 warn("Config files:\n ",
112             join( "\n ", $cfg->files ), "\n");
113             }
114              
115 6 50       20 if ( $cfg->val(__PACKAGE__, "dumpcfg", 0) ) {
116 6     6   1220 use Data::Dumper;
  6         12926  
  6         7918  
117 0         0 warn(Dumper($cfg));
118             }
119 6         20 $::cfg = $cfg;
120             }
121              
122             sub import {
123 2     2   23 my ($self, $app) = @_;
124 2 50       21 return unless defined $app;
125 0         0 die("PROGRAM ERROR: EB::Config cannot import anything");
126             }
127              
128             package EB::Config::Handler;
129              
130             # Very simple inifile handler (read-only).
131              
132             sub _key {
133 79     79   116 my ($section, $parameter) = @_;
134 79         194 $section.'::'.$parameter;
135             }
136              
137             sub val {
138 79     79   161 my ($self, $section, $parameter, $default) = @_;
139 79         90 my $res;
140 79         159 $res = $self->{data}->{ _key($section, $parameter) };
141 79 50       171 $res = $default unless defined $res;
142 79 50 66     217 Carp::cluck("=> missing config: \"" . _key($section, $parameter) . "\"\n")
143             unless defined $res || @_ > 3;
144 79         183 $res;
145             }
146              
147             sub newval {
148 0     0   0 my ($self, $section, $parameter, $value) = @_;
149 0         0 $self->{data}->{ _key($section, $parameter) } = $value;
150             }
151              
152             sub setval {
153 0     0   0 my ($self, $section, $parameter, $value) = @_;
154 0         0 my $key = _key( $section, $parameter );
155             Carp::cluck("=> missing config: \"$key\"\n")
156 0 0       0 unless exists $self->{data}->{ $key };
157 0         0 $self->{data}->{ $key } = $value;
158             }
159              
160             sub _plug {
161 60     60   138 my ($self, $section, $parameter, $env) = @_;
162             $self->newval($section, $parameter, $ENV{$env})
163 60 50 33     135 if $ENV{$env} && !$self->val($section, $parameter, undef);
164             }
165              
166             sub files {
167 0     0   0 my ($self) = @_;
168 0 0       0 return $self->{files}->[-1] unless wantarray;
169 0         0 return @{ $self->{files} };
  0         0  
170             }
171              
172             sub file {
173 0     0   0 goto &files; # for convenience
174             }
175              
176             sub set_file {
177 0     0   0 my ( $self, $file ) = @_;
178 0 0       0 if ( $self->{files}->[0] eq '' ) {
179 0         0 $self->{files} = [];
180             }
181 0         0 push( @{ $self->{files} }, $file );
  0         0  
182             }
183              
184             sub app {
185 0     0   0 my ($self) = @_;
186 0         0 $self->{app};
187             }
188              
189             sub new {
190 6     6   15 my ($package, $app, $file) = @_;
191 6         15 my $self = bless {}, $package;
192 6         47 $self->{files} = [ '' ];
193 6         13 $self->{data} = {};
194 6         16 $self->{app} = $app;
195 6 50       17 $self->load($file) if defined $file;
196 6         15 return $self;
197             }
198              
199             sub load {
200 0     0   0 my ($self, $file) = @_;
201              
202 0 0       0 open( my $fd, "<:encoding(utf-8)", $file )
203             or Carp::croak("Error opening config $file: $!\n");
204              
205 0         0 $self->set_file($file);
206              
207 0         0 my $section = "global";
208 0         0 my $fail;
209 0         0 while ( <$fd> ) {
210 0         0 chomp;
211 0 0       0 next unless /\S/;
212 0 0       0 next if /^[#;]/;
213 0 0       0 if ( /^\s*\[\s*(.*?)\s*\]\s*$/ ) {
214 0         0 $section = lc $1;
215 0         0 next;
216             }
217 0 0       0 if ( /^\s*(.*?)\s*=\s*(.*?)\s*$/ ) {
218 0         0 $self->{data}->{ _key($section, lc($1)) } = $2;
219 0         0 next;
220             }
221 0         0 Carp::cluck("Error in config $file, line $.:\n$_\n");
222 0         0 $fail++;
223             }
224 0 0       0 Carp::croak("Error processing config $file, aborted\n")
225             if $fail;
226              
227 0         0 $self;
228             }
229              
230             sub printconf {
231 0     0   0 my ( $self, $list ) = @_;
232 0 0       0 return unless @$list > 0;
233 0         0 foreach my $conf ( @$list ) {
234 0 0       0 unless ( $conf =~ /^(.+?):([^:]+)/ ) {
235 0         0 print STDOUT ("\n");
236 0         0 next;
237             }
238 0         0 my ($sec, $conf) = ($1, $2);
239 0         0 $sec =~ s/:+$//;
240 0         0 my $val = $self->val($sec, $conf, undef);
241 0 0       0 print STDOUT ($val) if defined $val;
242 0         0 print STDOUT ("\n");
243             }
244             }
245              
246             sub user_dir {
247 2     2   6 my ( $app, $item ) = @_;
248             {
249 2         3 local $SIG{__WARN__};
  2         5  
250 2         5 local $SIG{__DIE__};
251 2         4 eval { $app = $app->app };
  2         15  
252             }
253              
254 2 50       12 if ( $^O =~ /^mswin/i ) {
255             my $f = File::Spec->catpath( $ENV{HOMEDRIVE}, $ENV{HOMEPATH},
256 0         0 File::Spec->catfile( $app, $item ));
257              
258 0         0 return $f;
259             }
260 2 50       103 File::Spec->catfile( glob("~"),
261             "." . lc( $app),
262             defined($item) ? $item : (),
263             );
264             }
265              
266             sub std_config {
267 8     8   17 my ( $app ) = @_;
268             {
269 8         10 local $SIG{__WARN__};
  8         26  
270 8         16 local $SIG{__DIE__};
271 8         12 eval { $app = $app->app };
  8         88  
272             }
273 8         61 lc($app) . ".conf";
274             }
275              
276             sub std_config_alt {
277 2     2   5 "." . &std_config;
278             }
279              
280             1;