| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# Configuration reading and holding. |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package Bot::Pastebot::Conf; |
|
4
|
|
|
|
|
|
|
|
|
5
|
1
|
|
|
1
|
|
724
|
use strict; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
29
|
|
|
6
|
1
|
|
|
1
|
|
5
|
use Carp qw(croak); |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
43
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
13
|
use base qw(Exporter); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
337
|
|
|
9
|
|
|
|
|
|
|
our @EXPORT_OK = qw( |
|
10
|
|
|
|
|
|
|
get_names_by_type get_items_by_name load |
|
11
|
|
|
|
|
|
|
SCALAR LIST REQUIRED |
|
12
|
|
|
|
|
|
|
); |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
sub SCALAR () { 0x01 } |
|
15
|
|
|
|
|
|
|
sub LIST () { 0x02 } |
|
16
|
|
|
|
|
|
|
sub REQUIRED () { 0x04 } |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
my ($section, $section_line, %item, %config); |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
sub flush_section { |
|
21
|
0
|
|
|
0
|
0
|
|
my ($conf_file, $conf_definition) = @_; |
|
22
|
|
|
|
|
|
|
|
|
23
|
0
|
0
|
|
|
|
|
return unless defined $section; |
|
24
|
|
|
|
|
|
|
|
|
25
|
0
|
0
|
|
|
|
|
unless (exists $item{name}) { |
|
26
|
0
|
|
|
|
|
|
die( |
|
27
|
|
|
|
|
|
|
"conf error: ", |
|
28
|
|
|
|
|
|
|
"section `$section' has no `name' at $conf_file line $section_line" |
|
29
|
|
|
|
|
|
|
); |
|
30
|
|
|
|
|
|
|
} |
|
31
|
|
|
|
|
|
|
|
|
32
|
0
|
|
|
|
|
|
foreach my $item_name (sort keys %{$conf_definition->{$section}}) { |
|
|
0
|
|
|
|
|
|
|
|
33
|
0
|
|
|
|
|
|
my $item_type = $conf_definition->{$section}->{$item_name}; |
|
34
|
|
|
|
|
|
|
|
|
35
|
0
|
0
|
|
|
|
|
if ($item_type & REQUIRED) { |
|
36
|
0
|
0
|
|
|
|
|
die( |
|
37
|
|
|
|
|
|
|
"conf error: section `$section' ", |
|
38
|
|
|
|
|
|
|
"requires item `$item_name' ", |
|
39
|
|
|
|
|
|
|
"at $conf_file line $section_line\n" |
|
40
|
|
|
|
|
|
|
) unless exists $item{$item_name}; |
|
41
|
|
|
|
|
|
|
} |
|
42
|
|
|
|
|
|
|
} |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
die( |
|
45
|
0
|
0
|
|
|
|
|
"conf error: section `$section' ", |
|
46
|
|
|
|
|
|
|
"item `$item{name}' is redefined at $conf_file line $section_line\n" |
|
47
|
|
|
|
|
|
|
) if exists $config{$item{name}}; |
|
48
|
|
|
|
|
|
|
|
|
49
|
0
|
|
|
|
|
|
my $name = $item{name}; |
|
50
|
0
|
|
|
|
|
|
$config{$name} = { %item, type => $section }; |
|
51
|
|
|
|
|
|
|
} |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# Parse some configuration. |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub get_conf_file { |
|
56
|
1
|
|
|
1
|
|
2067
|
use Getopt::Std; |
|
|
1
|
|
|
|
|
42
|
|
|
|
1
|
|
|
|
|
677
|
|
|
57
|
|
|
|
|
|
|
|
|
58
|
0
|
|
|
0
|
0
|
|
my %opts; |
|
59
|
0
|
|
|
|
|
|
getopts("f:", \%opts); |
|
60
|
|
|
|
|
|
|
|
|
61
|
0
|
|
|
|
|
|
my $conf_file = $opts{"f"}; |
|
62
|
0
|
|
|
|
|
|
my @conf; |
|
63
|
0
|
0
|
|
|
|
|
if (defined $conf_file) { |
|
64
|
0
|
|
|
|
|
|
@conf = ($conf_file); |
|
65
|
|
|
|
|
|
|
} |
|
66
|
|
|
|
|
|
|
else { |
|
67
|
0
|
|
|
|
|
|
my $f = "pastebot.conf"; |
|
68
|
0
|
|
|
|
|
|
@conf = ( |
|
69
|
|
|
|
|
|
|
"./$f", "$ENV{HOME}/$f", "/usr/local/etc/pastebot/$f", "/etc/pastebot/$f" |
|
70
|
|
|
|
|
|
|
); |
|
71
|
|
|
|
|
|
|
|
|
72
|
0
|
|
|
|
|
|
foreach my $try ( @conf ) { |
|
73
|
0
|
0
|
|
|
|
|
next unless -f $try; |
|
74
|
0
|
|
|
|
|
|
$conf_file = $try; |
|
75
|
0
|
|
|
|
|
|
last; |
|
76
|
|
|
|
|
|
|
} |
|
77
|
|
|
|
|
|
|
} |
|
78
|
|
|
|
|
|
|
|
|
79
|
0
|
0
|
0
|
|
|
|
unless (defined $conf_file and -f $conf_file) { |
|
80
|
0
|
|
|
|
|
|
die( |
|
81
|
|
|
|
|
|
|
"\nconf error: Cannot read configuration file [$conf_file], tried: @conf" |
|
82
|
|
|
|
|
|
|
); |
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
|
|
85
|
0
|
|
|
|
|
|
return $conf_file; |
|
86
|
|
|
|
|
|
|
} |
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub load { |
|
89
|
0
|
|
|
0
|
0
|
|
my ($class, $conf_file, $conf_definition) = @_; |
|
90
|
|
|
|
|
|
|
|
|
91
|
0
|
0
|
|
|
|
|
open(MPH, "<", $conf_file) or |
|
92
|
|
|
|
|
|
|
die "\nconf error: Cannot open configuration file [$conf_file]: $!"; |
|
93
|
|
|
|
|
|
|
|
|
94
|
0
|
|
|
|
|
|
while (<MPH>) { |
|
95
|
0
|
|
|
|
|
|
chomp; |
|
96
|
0
|
|
|
|
|
|
s/\s*(?<!\\)\#.*$//; # remove comments ('#' not preceded by a '\') |
|
97
|
0
|
0
|
|
|
|
|
next if /^\s*$/; |
|
98
|
|
|
|
|
|
|
|
|
99
|
0
|
|
|
|
|
|
s/\\\#/\#/g; # '\#' -> '#' |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# Section item. |
|
102
|
0
|
0
|
|
|
|
|
if (/^\s+(\S+)\s+(.*?)\s*$/) { |
|
103
|
|
|
|
|
|
|
|
|
104
|
0
|
0
|
|
|
|
|
die( |
|
105
|
|
|
|
|
|
|
"conf error: ", |
|
106
|
|
|
|
|
|
|
"can't use an indented item ($1) outside of an unindented section ", |
|
107
|
|
|
|
|
|
|
"at $conf_file line $.\n" |
|
108
|
|
|
|
|
|
|
) unless defined $section; |
|
109
|
|
|
|
|
|
|
|
|
110
|
0
|
0
|
|
|
|
|
die( |
|
111
|
|
|
|
|
|
|
"conf error: item `$1' does not belong in section `$section' ", |
|
112
|
|
|
|
|
|
|
"at $conf_file line $.\n" |
|
113
|
|
|
|
|
|
|
) unless exists $conf_definition->{$section}->{$1}; |
|
114
|
|
|
|
|
|
|
|
|
115
|
0
|
0
|
|
|
|
|
if (exists $item{$1}) { |
|
116
|
0
|
0
|
|
|
|
|
if (ref($item{$1}) eq 'ARRAY') { |
|
117
|
0
|
|
|
|
|
|
push @{$item{$1}}, $2; |
|
|
0
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
else { |
|
120
|
0
|
|
|
|
|
|
die "conf error: option $1 redefined at $conf_file line $.\n"; |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
else { |
|
124
|
0
|
0
|
|
|
|
|
if ($conf_definition->{$section}->{$1} & LIST) { |
|
125
|
0
|
|
|
|
|
|
$item{$1} = [ $2 ]; |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
else { |
|
128
|
0
|
|
|
|
|
|
$item{$1} = $2; |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
} |
|
131
|
0
|
|
|
|
|
|
next; |
|
132
|
|
|
|
|
|
|
} |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
# Section leader. |
|
135
|
0
|
0
|
|
|
|
|
if (/^(\S+)\s*$/) { |
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# A new section ends the previous one. |
|
138
|
0
|
|
|
|
|
|
flush_section($conf_file, $conf_definition); |
|
139
|
|
|
|
|
|
|
|
|
140
|
0
|
|
|
|
|
|
$section = $1; |
|
141
|
0
|
|
|
|
|
|
$section_line = $.; |
|
142
|
0
|
|
|
|
|
|
undef %item; |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
# Pre-initialize any lists in the section. |
|
145
|
0
|
|
|
|
|
|
while (my ($item_name, $item_flags) = each %{$conf_definition->{$section}}) { |
|
|
0
|
|
|
|
|
|
|
|
146
|
0
|
0
|
|
|
|
|
if ($item_flags & LIST) { |
|
147
|
0
|
|
|
|
|
|
$item{$item_name} = []; |
|
148
|
|
|
|
|
|
|
} |
|
149
|
|
|
|
|
|
|
} |
|
150
|
|
|
|
|
|
|
|
|
151
|
0
|
|
|
|
|
|
next; |
|
152
|
|
|
|
|
|
|
} |
|
153
|
|
|
|
|
|
|
|
|
154
|
0
|
|
|
|
|
|
die "conf error: syntax error in $conf_file at line $.\n"; |
|
155
|
|
|
|
|
|
|
} |
|
156
|
|
|
|
|
|
|
|
|
157
|
0
|
|
|
|
|
|
flush_section($conf_file); |
|
158
|
|
|
|
|
|
|
|
|
159
|
0
|
|
|
|
|
|
close MPH; |
|
160
|
|
|
|
|
|
|
} |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
sub get_names_by_type { |
|
163
|
0
|
|
|
0
|
0
|
|
my $type = shift; |
|
164
|
0
|
|
|
|
|
|
my @names; |
|
165
|
|
|
|
|
|
|
|
|
166
|
0
|
|
|
|
|
|
while (my ($name, $item) = each %config) { |
|
167
|
0
|
0
|
|
|
|
|
next unless $item->{type} eq $type; |
|
168
|
0
|
|
|
|
|
|
push @names, $name; |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
|
|
171
|
0
|
|
|
|
|
|
return @names; |
|
172
|
|
|
|
|
|
|
} |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
sub get_items_by_name { |
|
175
|
0
|
|
|
0
|
0
|
|
my $name = shift; |
|
176
|
0
|
0
|
|
|
|
|
return () unless exists $config{$name}; |
|
177
|
0
|
|
|
|
|
|
return %{$config{$name}}; |
|
|
0
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
} |
|
179
|
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
1; |