2 # modules.pl: pseudo-Module handler
4 # Version: v0.2 (20000629)
10 use vars qw($AUTOLOAD);
16 eval "use IO::Socket";
18 &ERROR("no IO::Socket?");
21 &showProc(" (IO::Socket)");
25 "babelfish" => "babelfish.pl",
26 "botmail" => "botmail.pl",
27 "BZFlag" => "BZFlag.pl",
28 "countdown" => "countdown.pl",
29 "Debian" => "Debian.pl",
30 "DebianExtra" => "DebianExtra.pl",
32 "DumpVars" => "DumpVars.pl",
33 "Exchange" => "Exchange.pl",
34 "Factoids" => "Factoids.pl",
35 "HTTPDtype" => "HTTPDtype.pl",
36 "insult" => "insult.pl",
37 "UserDCC" => "UserDCC.pl",
38 "Kernel" => "Kernel.pl",
40 "nickometer" => "nickometer.pl",
41 "pager" => "pager.pl",
44 "Quote" => "Quote.pl",
45 "RootWarn" => "RootWarn.pl",
47 "Search" => "Search.pl",
48 "slashdot" => "slashdot.pl",
49 "DumpVars2" => "DumpVars2.pl",
50 "Topic" => "Topic.pl",
51 "Units" => "Units.pl",
52 "Uptime" => "Uptime.pl",
53 "UserInfo" => "UserInfo.pl",
54 "Weather" => "Weather.pl",
55 "wikipedia" => "wikipedia.pl",
56 "wingate" => "Wingate.pl",
57 "wwwsearch" => "W3Search.pl",
59 "zippy" => "Zippy.pl",
62 ### THIS IS NOT LOADED ON RELOAD :(
64 my @myModulesReloadNot;
66 @myModulesLoadNow = ('Topic', 'Uptime', 'News', 'RootWarn', 'DumpVars2', 'botmail');
67 @myModulesReloadNot = ('IRC/Irc.pl','IRC/Schedulers.pl');
71 my @mods = &getPerlFiles($bot_src_dir);
73 &status("Loading CORE modules...");
75 foreach (sort @mods) {
76 my $mod = "$bot_src_dir/$_";
78 eval "require \"$mod\"";
85 $moduleAge{$mod} = (stat $mod)[9];
86 &showProc(" ($_)") if (&IsParam("DEBUG"));
92 # TODO: use function to load module.
94 if ($param{'DBType'} =~ /^(mysql|SQLite|pgsql)$/i) {
97 &ERROR("No support for DBI::" . $param{'DBType'} . ", exiting!");
100 &status("Loading " . $param{'DBType'} . " support.");
101 $f = "$bot_src_dir/dbi.pl";
103 $moduleAge{$f} = (stat $f)[9];
105 &showProc(" (DBI::" . $param{'DBType'} . ")");
107 &WARN("DB support DISABLED.");
112 sub loadFactoidsModules {
113 if (!&IsParam("factoids")) {
114 &status("Factoid support DISABLED.");
118 &status("Loading Factoids modules...");
120 foreach ( &getPerlFiles("$bot_src_dir/Factoids") ) {
121 my $mod = "$bot_src_dir/Factoids/$_";
123 eval "require \"$mod\"";
129 $moduleAge{$mod} = (stat $mod)[9];
130 &showProc(" ($_)") if (&IsParam("DEBUG"));
135 my ($interface) = &whatInterface();
136 if ($interface =~ /IRC/) {
137 &status("Loading IRC modules...");
141 &ERROR("libnet-irc-perl is not installed!");
144 &showProc(" (Net::IRC)");
146 &status("IRC support DISABLED.");
147 # disabling forking. Why?
148 #$param{forking} = 0;
152 foreach ( &getPerlFiles("$bot_src_dir/$interface") ) {
153 my $mod = "$bot_src_dir/$interface/$_";
155 # hrm... use another config option besides DEBUG to display
156 # change in memory usage.
157 &status("Loading Modules \"$mod\"") if (!&IsParam("DEBUG"));
158 eval "require \"$mod\"";
160 &ERROR("require \"$mod\" => $@");
165 $moduleAge{$mod} = (stat $mod)[9];
166 &showProc(" ($_)") if (&IsParam("DEBUG"));
170 sub loadMyModulesNow {
174 &status("Loading MyModules...");
175 foreach (@myModulesLoadNow) {
178 &WARN("mMLN: null element.");
182 if (!&IsParam($_) and !&IsChanConf($_) and !&getChanConfList($_)) {
183 if (exists $myModules{$_}) {
184 &status("myModule: $myModules{$_} or $_ (1) not loaded.");
186 &DEBUG("myModule: $_ (2) not loaded.");
192 &loadMyModule($myModules{$_});
196 &status("Module: Runtime: Loaded/Total [$loaded/$total]");
199 ### rename to moduleReloadAll?
200 sub reloadAllModules {
203 &VERB("Module: reloading all.",2);
205 # obscure usage of map and regex :)
206 foreach (map { s/.*?\/?src/src/; $_ } keys %moduleAge) {
207 $retval .= &reloadModule($_);
210 &VERB("Module: reloading done.",2);
214 ### rename to modulesReload?
217 my $file = (grep /\/$mod/, keys %INC)[0];
220 # don't reload if it's not our module.
221 if ($mod =~ /::/ or $mod !~ /pl$/) {
222 &VERB("Not reloading $mod.",3);
226 if (!defined $file) {
227 &WARN("rM: Cannot reload $mod since it was not loaded anyway.");
232 &ERROR("rM: file '$file' does not exist?");
236 if (grep /$mod/, @myModulesReloadNot) {
237 &DEBUG("rM: should not reload $mod");
241 my $age = (stat $file)[9];
243 if (!exists $moduleAge{$file}) {
244 &DEBUG("Looks like $file was not loaded; fixing.");
246 return $retval if ($age == $moduleAge{$file});
248 if ($age < $moduleAge{$file}) {
249 &WARN("rM: we're not gonna downgrade '$file'; use touch.");
250 &DEBUG("age => $age");
251 &DEBUG("mA{$file} => $moduleAge{$file}");
255 my $dc = &Time2String($age - $moduleAge{$file});
256 my $ago = &Time2String(time() - $moduleAge{$file});
258 &VERB("Module: delta change: $dc",2);
259 &VERB("Module: ago: $ago",2);
262 &status("Module: Loading $mod...");
265 eval "require \"$file\""; # require or use?
267 &DEBUG("rM: failure: @$ ");
269 my $basename = $file;
270 $basename =~ s/^.*\///;
271 &status("Module: reloaded $basename");
272 $retval = " $basename";
273 $moduleAge{$file} = $age;
279 ### OPTIONAL MODULES.
282 my %perlModulesLoaded = ();
283 my %perlModulesMissing = ();
286 return 0 if (exists $perlModulesMissing{$_[0]});
287 &reloadModule($_[0]);
288 return 1 if (exists $perlModulesLoaded{$_[0]});
292 &WARN("Module: $_[0] is not installed!");
293 $perlModulesMissing{$_[0]} = 1;
296 $perlModulesLoaded{$_[0]} = 1;
297 &status("Loaded $_[0]");
298 &showProc(" ($_[0])");
306 &WARN("loadMyModule: module is NULL.");
310 my ($modulename, $modulebase);
311 if (exists $myModules{$tmp}) {
312 ($modulename, $modulebase) = ($tmp, $myModules{$tmp});
315 if ($tmp = grep /^$modulebase$/, keys %myModules) {
316 &DEBUG("lMM: lame hack, file => name => $tmp.");
320 my $modulefile = "$bot_src_dir/Modules/$modulebase";
322 # call reloadModule() which checks age of file and reload.
323 if (grep /\/$modulebase$/, keys %INC) {
324 &reloadModule($modulebase);
325 return 1; # depend on reloadModule?
328 if (! -f $modulefile) {
329 &ERROR("lMM: module ($modulebase) does not exist.");
330 if ($$ == $bot_pid) { # parent.
331 &shutdown() if (defined $shm and defined $dbh);
333 &DEBUG("b4 delfork 1");
334 &delForked($modulename);
340 eval "require \"$modulefile\"";
342 &ERROR("cannot load my module: $modulebase");
343 if ($bot_pid != $$) { # child.
344 &DEBUG("b4 delfork 2");
345 &delForked($modulename);
351 $moduleAge{$modulefile} = (stat $modulefile)[9];
353 &status("Loaded $modulebase");
354 &showProc(" ($modulebase)");
360 eval "use Time::HiRes qw(gettimeofday tv_interval)";
362 &WARN("No Time::HiRes?");
365 &showProc(" (Time::HiRes)");
368 if (!defined $AUTOLOAD and defined $::AUTOLOAD) {
369 &DEBUG("AUTOLOAD: hrm.. ::AUTOLOAD defined!");
371 return unless (defined $AUTOLOAD);
372 return if ($AUTOLOAD =~ /__/); # internal.
374 my $str = join(', ', @_);
375 my ($package, $filename, $line) = caller;
376 &ERROR("UNKNOWN FUNCTION CALLED: $AUTOLOAD ($str) $filename line $line");
378 $AUTOLOAD =~ s/^(\S+):://g;
380 if (exists $myModules{lc $AUTOLOAD}) {
381 # hopefully this will work.
382 &DEBUG("Trying to load module $AUTOLOAD...");
383 &loadMyModule(lc $AUTOLOAD);
390 if (!opendir(DIR, $dir)) {
391 &ERROR("Cannot open source directory ($dir): $!");
396 while (defined(my $file = readdir DIR)) {
397 next unless $file =~ /\.pl$/;
398 next unless $file =~ /^[A-Z]/;
403 return reverse sort @mods;