1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
package IdaliusConfig;
use strict;
use warnings;
use Config::Tiny;
use ListParser;
sub config_describe {
my ($plugin, $parm) = @_;
# Plugin "_" is the root config
return $parm unless $plugin ne "_";
return "$plugin -> $parm";
}
sub assert_common {
my ($config, $plugin, $parm, $human_type, $ref_type) = @_;
my $ref = $config->{$parm};
my $name = config_describe($plugin, $parm);
die "Error: Configuration \"$name\" must be of type $human_type" unless
defined $ref
and ref($ref) eq $ref_type;
}
sub assert_scalar {
my ($config, $plugin, $parm) = @_;
assert_common($config, $plugin, $parm, "scalar", "");
}
sub assert_list {
my ($config, $plugin, $parm) = @_;
assert_common($config, $plugin, $parm, "list", "ARRAY");
}
sub assert_dict {
my ($config, $plugin, $parm) = @_;
assert_common($config, $plugin, $parm, "dictionary", "HASH");
}
# Check presence and/or sanity of config parameters for the bot's core
# I.e. it is up to each module to ensure its own config is there and sane,
# normally in sub configure.
sub check_config
{
my ($config) = @_;
# Lists of mandatory config variables
my @scalars = qw/nick username ircname server port usessl sslcert sslkey user group prefix_nick prefix log_debug/;
my @lists = qw/plugins ignore/;
foreach my $name (@scalars) {
assert_scalar($config->{_}, "_", $name);
}
foreach my $name (@lists) {
assert_list($config->{_}, "_", $name);
}
# Special case: password is optional scalar
if (defined $config->{_}->{password}) {
assert_scalar($config->{_}, "_", "password");
}
}
sub parse_die {
my ($parsed, $line) = @_;
my $pad = " " x ($parsed->{column_start} + 1);
my $underline = "^" x ($parsed->{column_end} - $parsed->{column_start} + 1);
die "$parsed->{error}:\n$line\n$pad$underline\n";
}
sub parse_config
{
my $file = $_[0];
my %built_config;
my $config = Config::Tiny->read($file);
foreach my $section (keys %{$config}) {
foreach my $opt (keys %{$config->{$section}}) {
# Detect list or hash config option
my $c = substr $config->{$section}->{$opt}, 0, 1;
if ($c eq "[") {
my $parsed = ListParser::parse_list($config->{$section}->{$opt}, 0);
parse_die($parsed, $config->{$section}->{$opt}) if $parsed->{error};
$config->{$section}->{$opt} = $parsed->{array};
} elsif ($c eq "{") {
my $parsed = ListParser::parse_list($config->{$section}->{$opt}, 1);
parse_die($parsed, $config->{$section}->{$opt}) if $parsed->{error};
$config->{$section}->{$opt} = $parsed->{hash};
}
}
}
# my ($error, @tmp) = ListParser::parse_list($config->{_}->{plugins});
# $config->{_}->{plugins} = \@tmp;
# Special case
$config->{_}->{uid} = getpwnam($config->{_}->{user})
or die "Cannot get uid of $config->{_}->{user}: $!\n";
$config->{_}->{gid} = getgrnam($config->{_}->{group})
or die "Cannot get gid of $config->{_}->{group}: $!\n";
check_config($config);
return $config;
}
1;
|