2 # modules.pl: pseudo-Module handler
4 # Version: v0.2 (20000629)
9 use vars qw($AUTOLOAD);
15 eval "use IO::Socket";
17 &ERROR("no IO::Socket?");
20 &showProc(" (IO::Socket)");
24 "bzflag" => "BZFlag.pl",
25 "countdown" => "Countdown.pl",
26 "debian" => "Debian.pl",
27 "debianExtra" => "DebianExtra.pl",
29 "dumpvars" => "DumpVars.pl",
30 "symdump" => "DumpVars2.pl",
31 "factoids" => "Factoids.pl",
32 "freshmeat" => "Freshmeat.pl",
33 "kernel" => "Kernel.pl",
34 "perlMath" => "Math.pl",
37 "quote" => "Quote.pl",
38 "rootwarn" => "RootWarn.pl",
39 "search" => "Search.pl",
40 "slashdot" => "Slashdot3.pl",
41 "topic" => "Topic.pl",
42 "units" => "Units.pl",
43 "uptime" => "Uptime.pl",
44 "ircdcc" => "UserDCC.pl",
45 "userinfo" => "UserInfo.pl",
46 "weather" => "Weather.pl",
47 "wwwsearch" => "W3Search.pl",
48 "whatis" => "WhatIs.pl",
49 "wingate" => "Wingate.pl",
50 "babelfish" => "babel.pl",
51 "insult" => "insult.pl",
52 "nickometer" => "nickometer.pl",
56 ### THIS IS NOT LOADED ON RELOAD :(
58 my @myModulesReloadNot;
60 @myModulesLoadNow = ('topic', 'uptime', 'news', 'rootWarn', 'symdump');
61 @myModulesReloadNot = ('IRC/Irc.pl','IRC/Schedulers.pl');
65 my @mods = &getPerlFiles($bot_src_dir);
67 &status("Loading ".scalar(@mods)." CORE modules...");
69 foreach (sort @mods) {
70 my $mod = "$bot_src_dir/$_";
72 eval "require \"$mod\"";
79 $moduleAge{$mod} = (stat $mod)[9];
80 &showProc(" ($_)") if (&IsParam("DEBUG"));
85 my $f = "$bot_src_dir/modules.pl";
86 $moduleAge{$f} = (stat $f)[9];
88 if ($param{'DBType'} =~ /^mysql$/i) {
91 &ERROR("libdbd-mysql-perl is not installed!");
94 &status("Loading MySQL support.");
95 $f = "$bot_src_dir/db_mysql.pl";
97 $moduleAge{$f} = (stat $f)[9];
98 &showProc(" (DBI // mysql)");
99 } elsif ($param{'DBType'} =~ /^pgsql$/i) {
103 &ERROR("libpgperl is not installed!");
106 &status("Loading pgsql support.");
107 require "$bot_src_dir/db_pgsql.pl";
108 &showProc(" (pgsql)");
109 } elsif ($param{'DBType'} =~ /^sqlite$|^dbm$/i) {
110 &status("Loading " . $param{'DBType'} . " support.");
111 $f="$bot_src_dir/db_" . $param{'DBType'} . ".pl";
112 $moduleAge{$f} = (stat $f)[9];
114 &showProc(" $bot_src_dir/db_" . $param{'DBType'} . ".pl");
116 &status("DB support DISABLED.");
121 sub loadFactoidsModules {
122 if (!&IsParam("factoids")) {
123 &status("Factoid support DISABLED.");
127 &status("Loading Factoids modules...");
129 foreach ( &getPerlFiles("$bot_src_dir/Factoids") ) {
130 my $mod = "$bot_src_dir/Factoids/$_";
132 eval "require \"$mod\"";
138 $moduleAge{$mod} = (stat $mod)[9];
139 &showProc(" ($_)") if (&IsParam("DEBUG"));
144 my ($interface) = &whatInterface();
145 if ($interface =~ /IRC/) {
146 &status("Loading IRC modules...");
150 &ERROR("libnet-irc-perl is not installed!");
153 &showProc(" (Net::IRC)");
155 &status("IRC support DISABLED.");
161 foreach ( &getPerlFiles("$bot_src_dir/$interface") ) {
162 my $mod = "$bot_src_dir/$interface/$_";
164 # hrm... use another config option besides DEBUG to display
165 # change in memory usage.
166 &status("Loading Modules \"$mod\"") if (!&IsParam("DEBUG"));
167 eval "require \"$mod\"";
169 &ERROR("require \"$mod\" => $@");
174 $moduleAge{$mod} = (stat $mod)[9];
175 &showProc(" ($_)") if (&IsParam("DEBUG"));
179 sub loadMyModulesNow {
183 &status("Loading MyModules...");
184 foreach (@myModulesLoadNow) {
187 &WARN("mMLN: null element.");
191 if (!&IsParam($_) and !&IsChanConf($_) and !&getChanConfList($_)) {
192 if (exists $myModules{$_}) {
193 &status("myModule: $myModules{$_} or $_ (1) not loaded.");
195 &DEBUG("myModule: $_ (2) not loaded.");
201 # weird hack to get rootwarn to work.
202 # it may break on other cases though, any ideas?
203 &loadMyModule( $myModules{$_} || $myModules{lc $_} );
207 &status("Module: Runtime: Loaded/Total [$loaded/$total]");
210 ### rename to moduleReloadAll?
211 sub reloadAllModules {
212 &VERB("Module: reloading all.",2);
214 # obscure usage of map and regex :)
215 foreach (map { s/.*?\/?src/src/; $_ } keys %moduleAge) {
219 &VERB("Module: reloading done.",2);
222 ### rename to modulesReload?
225 my $file = (grep /\/$mod/, keys %INC)[0];
227 # don't reload if it's not our module.
228 if ($mod =~ /::/ or $mod !~ /pl$/) {
229 &VERB("Not reloading $mod.",3);
233 if (!defined $file) {
234 &WARN("rM: Cannot reload $mod since it was not loaded anyway.");
239 &ERROR("rM: file '$file' does not exist?");
243 if (grep /$mod/, @myModulesReloadNot) {
244 &DEBUG("rM: should not reload $mod");
248 my $age = (stat $file)[9];
250 if (!exists $moduleAge{$file}) {
251 &DEBUG("Looks like $file was not loaded; fixing.");
253 return if ($age == $moduleAge{$file});
255 if ($age < $moduleAge{$file}) {
256 &WARN("rM: we're not gonna downgrade '$file'; use touch.");
257 &DEBUG("age => $age");
258 &DEBUG("mA{$file} => $moduleAge{$file}");
262 my $dc = &Time2String($age - $moduleAge{$file});
263 my $ago = &Time2String(time() - $moduleAge{$file});
265 &VERB("Module: delta change: $dc",2);
266 &VERB("Module: ago: $ago",2);
269 &status("Module: Loading $mod...");
272 eval "require \"$file\""; # require or use?
274 &DEBUG("rM: failure: @$");
276 my $basename = $file;
277 $basename =~ s/^.*\///;
278 &status("Module: reloaded $basename");
279 $moduleAge{$file} = $age;
284 ### OPTIONAL MODULES.
287 my %perlModulesLoaded = ();
288 my %perlModulesMissing = ();
291 return 0 if (exists $perlModulesMissing{$_[0]});
292 &reloadModule($_[0]);
293 return 1 if (exists $perlModulesLoaded{$_[0]});
297 &WARN("Module: $_[0] is not installed!");
298 $perlModulesMissing{$_[0]} = 1;
301 $perlModulesLoaded{$_[0]} = 1;
302 &status("Module: Loaded $_[0] ...");
303 &showProc(" ($_[0])");
311 &WARN("loadMyModule: module is NULL.");
315 my ($modulename, $modulebase);
316 if (exists $myModules{$tmp}) {
317 ($modulename, $modulebase) = ($tmp, $myModules{$tmp});
320 if ($tmp = grep /^$modulebase$/, keys %myModules) {
321 &DEBUG("lMM: lame hack, file => name => $tmp.");
325 my $modulefile = "$bot_src_dir/Modules/$modulebase";
327 # call reloadModule() which checks age of file and reload.
328 if (grep /\/$modulebase$/, keys %INC) {
329 &reloadModule($modulebase);
330 return 1; # depend on reloadModule?
333 if (! -f $modulefile) {
334 &ERROR("lMM: module ($modulebase) does not exist.");
335 if ($$ == $bot_pid) { # parent.
336 &shutdown() if (defined $shm and defined $dbh);
338 &DEBUG("b4 delfork 1");
339 &delForked($modulebase);
345 eval "require \"$modulefile\"";
347 &ERROR("cannot load my module: $modulebase");
348 if ($bot_pid != $$) { # child.
349 &DEBUG("b4 delfork 2");
350 &delForked($modulebase);
356 $moduleAge{$modulefile} = (stat $modulefile)[9];
358 &status("myModule: Loaded $modulebase ...");
359 &showProc(" ($modulebase)");
365 eval "use Time::HiRes qw(gettimeofday tv_interval)";
367 &WARN("No Time::HiRes?");
370 &showProc(" (Time::HiRes)");
373 if (!defined $AUTOLOAD and defined $::AUTOLOAD) {
374 &DEBUG("AUTOLOAD: hrm.. ::AUTOLOAD defined!");
376 return unless (defined $AUTOLOAD);
377 return if ($AUTOLOAD =~ /__/); # internal.
379 my $str = join(', ', @_);
380 my ($package, $filename, $line) = caller;
381 &ERROR("UNKNOWN FUNCTION CALLED: $AUTOLOAD ($str) $filename line $line");
383 $AUTOLOAD =~ s/^(\S+):://g;
385 if (exists $myModules{lc $AUTOLOAD}) {
386 # hopefully this will work.
387 &DEBUG("Trying to load module $AUTOLOAD...");
388 &loadMyModule(lc $AUTOLOAD);
395 if (!opendir(DIR, $dir)) {
396 &ERROR("Cannot open source directory ($dir): $!");
401 while (defined(my $file = readdir DIR)) {
402 next unless $file =~ /\.pl$/;
403 next unless $file =~ /^[A-Z]/;
408 return reverse sort @mods;