]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - configure
Fix incorrect watch usage, patch from dz (thanks).
[user/henk/code/inspircd.git] / configure
1 #!/usr/bin/perl
2 ###################################################
3 # InspIRCd Configuration Script
4 #
5 # Copyright 2002-2008 The InspIRCd Development Team
6 #  http://www.inspircd.org/wiki/index.php/Credits
7 #
8 # Licensed under GPL, please see the COPYING file
9 # for more information
10 #
11 # $Id$
12 #
13 ###################################################
14
15 BEGIN {
16         require 5.8.0;
17 }
18
19 use strict;
20 use warnings FATAL => qw(all);
21
22 use Data::Dumper;
23 BEGIN {
24         $Data::Dumper::Sortkeys = 1;
25         $Data::Dumper::Useqq = 1;
26 };
27
28 use File::Copy ();
29 use Socket;
30 use Cwd;
31 use Getopt::Long;
32
33 # Utility functions for our buildsystem
34 use make::utilities;
35 use make::configure;
36 use make::gnutlscert;
37 use make::opensslcert;
38
39 ###############################################################################################
40 #
41 #                                   EDITABLE VARIABLES
42 #
43 ###############################################################################################
44
45 # If you wish to ignore a dependency throughout the entire core, add it here.
46
47 our @ignoredeps = (
48         "inspircd_win32wrapper.h",      # windows has its own configure program
49 );
50
51 # If you wish for all files in the entire core to have a given dependency, insert it here.
52 # You should keep this to an absolute minimum to avoid rebuilds that are not neccessary.
53
54 our @immutabledeps = (
55         "inspircd_config.h",            # auto re-generated by configure
56         "inspircd.h",
57 );
58
59 ###############################################################################################
60 #
61 #                                 NON-EDITABLE VARIABLES
62 #
63 ###############################################################################################
64
65 # List of commands that make up 'make install' and 'make deinstall'
66
67 our $install_list = "";
68 our $uninstall_list = "";
69
70 # This is a list of all files in the core. Each cpp file is mapped to a shared object file,
71 # whos file extension is omitted (these can vary from system to system). Auto detected by
72 # scanning the src/*.cpp files for files containing /* $Core */ identifiers.
73
74 our %filelist = ();
75
76 # If you wish for a file to have special dependencies in the makefile, add an entry here.
77 # Auto populated by /* $ExtraDeps: */ instruction
78
79 our %specialdeps = ();
80
81 # If you wish for a file to have extra make lines (in between the compile and link steps)
82 # then insert them here.
83 # Auto populated by /* $ExtraBuild: */ instruction
84         
85 our %extrabuildlines = ();
86
87 # If you wish for a file to be linked against extra objects or arctives, insert them here.
88 # Auto populated by /* $ExtraObjects: */ instruction
89
90 our %extraobjects = ();
91
92 # If you wish to compile extra cpp sources into an object, define them here.
93 # NOTE: Certain cpp files such as the socket engines have a value auto calculated
94 # for this table so that their derived class is built.
95 # Auto populated by /* $ExtraSources: */ instruction
96
97 our %extrasources = ();
98
99 our ($opt_use_gnutls, $opt_rebuild, $opt_use_openssl, $opt_nointeractive, $opt_ports,
100     $opt_epoll, $opt_kqueue, $opt_noports, $opt_noepoll, $opt_nokqueue,
101     $opt_ipv6, $opt_ipv6links, $opt_noipv6links, $opt_maxbuf, $opt_disable_debug,
102     $opt_freebsd_port);
103
104 our ($opt_cc, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir,
105     $opt_library_dir);
106
107 sub list_extras ();
108
109 sub enable_extras (@);
110
111 sub disable_extras (@);
112
113 my @opt_enableextras;
114 my @opt_disableextras;
115
116 GetOptions (
117         'enable-gnutls' => \$opt_use_gnutls,
118         'rebuild' => \$opt_rebuild,
119         'enable-openssl' => \$opt_use_openssl,
120         'disable-interactive' => \$opt_nointeractive,
121         'enable-ports' => \$opt_ports,
122         'enable-epoll' => \$opt_epoll,
123         'enable-kqueue' => \$opt_kqueue,
124         'disable-ports' => \$opt_noports,
125         'disable-epoll' => \$opt_noepoll,
126         'disable-kqueue' => \$opt_nokqueue,
127         'enable-ipv6' => \$opt_ipv6,
128         'enable-remote-ipv6' => \$opt_ipv6links,
129         'disable-remote-ipv6' => \$opt_noipv6links,
130         'with-cc=s' => \$opt_cc,
131         'with-maxbuf=i' => \$opt_maxbuf,
132         'enable-freebsd-ports-openssl' => \$opt_freebsd_port,
133         'prefix=s' => \$opt_base_dir,
134         'config-dir=s' => \$opt_config_dir,
135         'module-dir=s' => \$opt_module_dir,
136         'binary-dir=s' => \$opt_binary_dir,
137         'library-dir=s' => \$opt_library_dir,
138         'disable-debuginfo' => sub { $opt_disable_debug = 1 },
139         'help'  => sub { showhelp(); },
140         'modupdate' => sub { modupdate(); },
141         'update' => sub { update(); },
142         'svnupdate' => sub { svnupdate(); },
143         'clean' => sub { clean(); },
144         'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
145         'enable-extras=s@' => \@opt_enableextras, # ^
146         'disable-extras=s@' => \@opt_disableextras, # ^
147 );
148
149 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
150         @opt_enableextras = split /,/, join(',', @opt_enableextras);
151         @opt_disableextras = split /,/, join(',', @opt_disableextras);
152         enable_extras(@opt_enableextras);
153         disable_extras(@opt_disableextras);
154         list_extras;
155         print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
156         print "Run $0 -modupdate after you've done this to update the makefiles.\n";
157         exit 0;
158 }
159
160 our $non_interactive = (
161         (defined $opt_library_dir) ||
162         (defined $opt_base_dir) ||
163         (defined $opt_config_dir) ||
164         (defined $opt_module_dir) ||
165         (defined $opt_base_dir) ||
166         (defined $opt_binary_dir) ||
167         (defined $opt_nointeractive) ||
168         (defined $opt_cc) ||
169         (defined $opt_ipv6) ||
170         (defined $opt_ipv6links) ||
171         (defined $opt_noipv6links) ||
172         (defined $opt_kqueue) ||
173         (defined $opt_epoll) ||
174         (defined $opt_ports) ||
175         (defined $opt_use_openssl) ||
176         (defined $opt_nokqueue) ||
177         (defined $opt_noepoll) ||
178         (defined $opt_noports) ||
179         (defined $opt_maxbuf) ||
180         (defined $opt_use_gnutls) ||
181         (defined $opt_freebsd_port)
182 );
183 our $interactive = !$non_interactive;
184
185 chomp(our $topdir = getcwd());
186 our $this = resolve_directory($topdir);                                         # PWD, Regardless.
187 our @modlist = ();                                                                      # Declare for Module List..
188 our %config = ();                                                                       # Initiate Configuration Hash..
189 $config{ME}              = resolve_directory($topdir);                          # Present Working Directory
190
191 $config{BASE_DIR}          = $config{ME};
192
193 if (defined $opt_base_dir)
194 {
195         $config{BASE_DIR} = $opt_base_dir;
196 }
197
198 $config{CONFIG_DIR}      = resolve_directory($config{BASE_DIR}."/conf");        # Configuration Directory
199 $config{MODULE_DIR}      = resolve_directory($config{BASE_DIR}."/modules");     # Modules Directory
200 $config{BINARY_DIR}      = resolve_directory($config{BASE_DIR}."/bin");         # Binary Directory
201 $config{LIBRARY_DIR}    = resolve_directory($config{BASE_DIR}."/lib");          # Library Directory
202
203 if (defined $opt_config_dir)
204 {
205         $config{CONFIG_DIR} = $opt_config_dir;
206 }
207 if (defined $opt_module_dir)
208 {
209         $config{MODULE_DIR} = $opt_module_dir;
210 }
211 if (defined $opt_binary_dir)
212 {
213         $config{BINARY_DIR} = $opt_binary_dir;
214 }
215 if (defined $opt_library_dir)
216 {
217         $config{LIBRARY_DIR} = $opt_library_dir;
218 }
219 chomp($config{HAS_GNUTLS}   = `libgnutls-config --version 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
220
221 if (defined $opt_freebsd_port)
222 {
223         chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`);
224         chomp($config{HAS_OPENSSL_PORT}  = `pkg-config --modversion openssl 2>/dev/null`);
225         $config{USE_FREEBSD_BASE_SSL} = "n";
226 }
227 else
228 {
229         if ($^O eq "freebsd")
230         {
231                 # default: use base ssl
232                 chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`);                      # OpenSSL version, freebsd specific
233                 chomp($config{HAS_OPENSSL_PORT}  = `pkg-config --modversion openssl 2>/dev/null`);      # Port version, may be different
234         }
235         else
236         {
237                 chomp($config{HAS_OPENSSL}  = `pkg-config --modversion openssl 2>/dev/null`);           # Openssl version, others
238                 $config{HAS_OPENSSL_PORT} = "";
239         }
240 }
241
242 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
243 chomp(our $openssl_ver = $config{HAS_OPENSSL});
244 $config{USE_GNUTLS}         = "n";
245 if (defined $opt_use_gnutls)
246 {
247         $config{USE_GNUTLS} = "y";                                      # Use gnutls.
248 }
249 $config{USE_OPENSSL}    = "n";                                          # Use openssl.
250 if (defined $opt_use_openssl)
251 {
252         $config{USE_OPENSSL} = "y";
253 }
254
255 # no, let's not change these.
256 $config{OPTIMITEMP}      = "0";                                         # Default Optimisation Value
257 if (!defined $opt_disable_debug)
258 {
259         $config{OPTIMISATI}      = "-g1";                               # Optimisation Flag
260 }
261 else
262 {
263         $config{OPTIMISATI}      = "-O2";                               # DEBUGGING OFF!
264 }
265
266 $config{HAS_STRLCPY}    = "false";                                      # strlcpy Check.
267 $config{HAS_STDINT}      = "false";                                     # stdint.h check
268 $config{USE_KQUEUE}      = "y";                                         # kqueue enabled
269 if (defined $opt_kqueue)
270 {
271         $config{USE_KQUEUE} = "y";
272 }
273 if (defined $opt_nokqueue)
274 {
275         $config{USE_KQUEUE} = "n";
276 }
277 $config{USE_POLL}     = "y";                                    # poll enabled
278 $config{USE_EPOLL}        = "y";                                        # epoll enabled
279 if (defined $opt_epoll)
280 {
281         $config{USE_EPOLL} = "y";
282 }
283 if (defined $opt_noepoll)
284 {
285         $config{USE_EPOLL} = "n";
286 }
287 $config{USE_PORTS}        = "y";                                        # epoll enabled
288 if (defined $opt_ports)
289 {
290         $config{USE_PORTS} = "y";
291 }
292 if (defined $opt_noports)
293 {
294         $config{USE_PORTS} = "n";
295 }
296 $config{IPV6}          = "n";                                           # IPv6 support (experimental)
297 if (defined $opt_ipv6)
298 {
299         $config{IPV6} = "y";
300 }
301 $config{SUPPORT_IP6LINKS}   = "y";                                      # IPv4 supporting IPv6 links (experimental)
302 if (defined $opt_ipv6links)
303 {
304         $config{SUPPORT_IP6LINKS} = "y";
305 }
306 if (defined $opt_noipv6links)
307 {
308         $config{SUPPORT_IP6LINKS} = "n";
309 }
310 chomp($config{GCCVER}       = `g++ -dumpversion | cut -c 1`);           # Major GCC Version
311 chomp($config{GCCMINOR}     = `g++ -dumpversion | cut -c 3`);
312 $config{_SOMAXCONN} = SOMAXCONN;                                        # Max connections in accept queue
313 $config{OSNAME}             = $^O;                                      # Operating System Name
314 $config{IS_DARWIN}        = "NO";                                       # Is OSX?
315 $config{STARTSCRIPT}      = "inspircd";                 # start script?
316 $config{DESTINATION}      = "BASE";                             # Is target path.
317 $config{EXTRA_DIR}        = "";                                         # Is empty.
318 if ($config{OSNAME} =~ /darwin/i)
319 {
320         $config{IS_DARWIN} = "YES";
321         $config{STARTSCRIPT}      = "org.inspircd.plist";               # start script for OSX.
322         $config{DESTINATION}      = "LAUNCHDPATH";                              # Is OSX target.
323         $config{EXTRA_DIR}          = " launchd_dir";                           # Is OSX specific path.
324 }
325 $config{CC}                 = "g++";                                            # C++ compiler
326 if (defined $opt_cc)
327 {
328         $config{CC} = $opt_cc;
329 }
330 our $exec = $config{CC} . " -dumpversion | cut -c 1";
331 chomp($config{GCCVER}           = `$exec`);                             # Major GCC Version
332 $exec = $config{CC} . " -dumpversion | cut -c 3";
333 chomp($config{GCCMINOR}         = `$exec`);
334 $config{MAKEORDER}              = "ircd mods";                          # build order
335 $config{MAXBUF}                 = "512";                                # Max buffer size
336
337 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/) {
338         $config{HAS_OPENSSL} = $1;
339 } else {
340         $config{HAS_OPENSSL} = "";
341 }
342
343 if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
344         print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
345         exit;
346 }
347
348 # Get and Set some important vars..
349 getmodules();
350
351 sub clean
352 {
353         unlink(".config.cache");
354 }
355
356 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
357
358 sub update
359 {
360         eval {
361                 chomp($topdir = getcwd());
362                 $this = resolve_directory($topdir);                                          # PWD, Regardless.
363                 getmodules();
364                 # Does the cache file exist?
365                 if (!getcache()) {
366                         # No, No it doesn't.. *BASH*
367                         print "You have not run ./configure before. Please do this before trying to run the update script.\n";
368                         exit 0;
369                 } else {
370                         # We've Loaded the cache file and all our variables..
371                         print "Updating files...\n";
372                         getosflags();
373                         if (defined($opt_disable_debug) && $opt_disable_debug == 1)
374                         {
375                                 print "Disabling debug information (-g).\n";
376                                 $config{OPTIMISATI} = "";
377                                 getosflags();
378                         }
379                         $has_epoll = $config{HAS_EPOLL};
380                         $has_ports = $config{HAS_PORTS};
381                         $has_kqueue = $config{HAS_KQUEUE};
382                         writefiles(1);
383                         makecache();
384                         print "Complete.\n";
385                         exit;
386                 }
387         };
388         if ($@)
389         {
390                 print "Configure update failed: $@\n";
391         }
392         exit;
393 }
394
395 sub modupdate
396 {
397         eval {
398                 chomp($topdir = getcwd());
399                 $this = resolve_directory($topdir);                                          # PWD, Regardless.
400                 getmodules();
401                 # Does the cache file exist?
402                 if (!getcache()) {
403                         # No, No it doesn't.. *BASH*
404                         print "You have not run ./configure before. Please do this before trying to run the update script.\n";
405                         exit 0;
406                 } else {
407                         # We've Loaded the cache file and all our variables..
408                         print "Updating files...\n";
409                         getosflags();
410                         $has_epoll = $config{HAS_EPOLL};
411                         $has_ports = $config{HAS_PORTS};
412                         $has_kqueue = $config{HAS_KQUEUE};
413                         writefiles(0);
414                         makecache();
415                         print "Complete.\n";
416                         exit;
417                 }
418         };
419         if ($@)
420         {
421                 print "Module update failed: $@\n";
422         }
423         exit;
424 }
425
426
427
428 sub svnupdate
429 {
430         my $fail = 0;
431         open(FH,"<.svn/entries") or $fail = 1;
432         if ($fail) {
433                 print "This is not an SVN copy of InspIRCd.\n";
434                 exit 1;
435         }
436         else
437         {
438                 close(FH);
439         }
440         open my $fd, "-|", "svn update";
441         my $configurechanged = 0; # Needs ./configure -update
442         my $coredirchanged = 0; # Needs ./configure -update
443         my $moduledirchanged = 0; # Needs ./configure -modupdate
444         my $rootincchanged = 0;
445         my @conflicted = ();
446         while (defined(my $line = <$fd>))
447         {
448                 my ($action, $file);
449                 print $line;
450                 $line =~ m/^([ADUCG])\s+(.*)$/ or next;
451                 ($action, $file) = ($1, $2);
452                 if ($action eq "C")
453                 {
454                         push @conflicted, $file;
455                         if ($file eq "configure")
456                         {
457                                 $configurechanged = 1;
458                         }
459                         elsif ($file =~ m#^src/modules#)
460                         {
461                                 $moduledirchanged = 1;
462                         }
463                         elsif ($file =~ m#^src/#)
464                         {
465                                 $coredirchanged = 1;
466                         }
467                         elsif ($file =~ m/^\..*\.inc$/)
468                         {
469                                 $rootincchanged = 1;
470                         }
471                 }
472                 elsif ($action eq "U" || $action eq "G")
473                 {
474                         if ($file eq "configure")
475                         {
476                                 $configurechanged = 1;
477                         }
478                         elsif ($file =~ m/^\..*\.inc$/)
479                         {
480                                 $rootincchanged = 1;
481                         }
482                 }
483                 elsif ($action eq "A" || $action eq "D")
484                 {
485                         if ($file =~ m#^src/modules#)
486                         {
487                                 $moduledirchanged = 1;
488                         }
489                         elsif ($file =~ m#^src/#)
490                         {
491                                 $coredirchanged = 1;
492                         }
493                 }
494         }
495         unless (close $fd) # close() waits for exit and returns false if the command failed
496         {
497                 if ($! == 0)
498                 {
499                         print STDERR "Problem updating from SVN, please check above for errors\n";
500                 }
501                 else
502                 {
503                         print STDERR "Failed to run SVN: $!\n";
504                 }
505                 exit 1;
506         }
507         if (scalar(@conflicted) > 0)
508         {
509                 print STDERR "\e[0;33;1mERROR:\e[0m You have local modifications which conflicted with the updates from SVN\n";
510                 printf STDERR "Configure is not able to complete the update. Please resolve these conflicts, then run ./configure -%supdate\n", (($coredirchanged || $configurechanged) ? "" : "mod");
511                 print "Conflicted files: " . join ", ", @conflicted . "\n";
512                 exit 1;
513         }
514         if ($configurechanged || $coredirchanged)
515         {
516                 system("perl configure -update");
517         }
518         elsif ($moduledirchanged || $rootincchanged)
519         {
520                 system("perl configure -modupdate");
521         }
522         else
523         {
524                 print "No need to update Makefiles.\n";
525         }
526         if (defined $opt_rebuild) {
527                 system("make install");
528         }
529         exit;
530 }
531
532 print "Running non-interactive configure...\n" unless $interactive;
533 print "Checking for cache from previous configure... ";
534 print ((!getcache()) ? "not found\n" : "found\n");
535 print "Checking operating system version... ";
536 print getosflags() . "\n";
537
538 printf "Checking if stdint.h exists... ";
539 $config{HAS_STDINT} = "true";
540 our $fail = 0;
541 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
542 if ($config{HAS_STDINT} eq "true") {
543         close(STDINT);
544 }
545 print "yes\n" if $config{HAS_STDINT} eq "true";
546 print "no\n" if $config{HAS_STDINT} eq "false";
547
548 printf "Checking if strlcpy exists... ";
549 # Perform the strlcpy() test..
550 $config{HAS_STRLCPY} = "false";
551 $fail = 0;
552 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
553 if (!$fail) {
554         while (defined(my $line = <STRLCPY>)) {
555                 chomp($line);
556                 # try and find the delcaration of:
557                 # size_t strlcpy(...)
558                 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
559                         $config{HAS_STRLCPY} = "true";
560                 }
561         }
562         close(STRLCPY);
563 }
564 print "yes\n" if $config{HAS_STRLCPY} eq "true";
565 print "no\n" if $config{HAS_STRLCPY} eq "false";
566
567 printf "Checking if kqueue exists... ";
568 $has_kqueue = 0;
569 $fail = 0;
570 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
571 if (!$fail) {
572         while (defined(my $line = <KQUEUE>)) {
573                 chomp($line);
574                 # try and find the delcaration of:
575                 # int kqueue(void);
576                 if ($line =~ /int(\0x9|\s)+kqueue/) {
577                         $has_kqueue = 1;
578                 }
579         }
580         close(KQUEUE);
581 }
582 print "yes\n" if $has_kqueue == 1;
583 print "no\n" if $has_kqueue == 0;
584
585 printf "Checking if epoll exists... ";
586 $has_epoll = 0;
587 $fail = 0;
588 open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
589 if (!$fail) {
590         $has_epoll = 1;
591         close(EPOLL);
592 }
593 if ($has_epoll) {
594         my $kernel = `uname -r`;
595         chomp($kernel);
596         if (($kernel =~ /^2\.0\./) || ($kernel =~ /^2\.2\./) || ($kernel =~ /^2\.4\./)) {
597                 $has_epoll = 0;
598         }
599         else
600         {
601                 # Suggestion from nenolod, weed out odd systems which have glibc built
602                 # against 2.4 kernels (ick)
603                 my $kernel_arch = `uname -p`;
604                 chomp($kernel_arch);
605                 my $libcv = 0.0;
606                 my $kernelv = 0.0;
607                 if ($kernel_arch =~ /x86_64/) {
608                         open (FH,"/lib64/libc.so.6|") or $has_epoll = 0;
609                 }
610                 else {
611                         open (FH,"/lib/libc.so.6|") or $has_epoll = 0;
612                 }
613                 if ($has_epoll)
614                 {
615                         while (defined(my $line = <FH>))
616                         {
617                                 chomp($line);
618                                 if ($line =~ /GNU C Library .* version (.*?) /)
619                                 {
620                                         $libcv = $1;
621                                         $libcv =~  /(\d+\.\d+)/;
622                                         $libcv = $1;
623                                 }
624                                 elsif ($line =~ /Compiled on a Linux (.*?\..*?)\.* system/)
625                                 {
626                                         $kernelv = $1;
627                                         # Fix for some retarded libc builds, strip off >> and << etc.
628                                         $kernelv =~ /(\d+\.\d+)/;
629                                         $kernelv = $1;
630                                 }
631                         }
632                         close FH;
633                         if ($libcv < 2.3)
634                         {
635                                 $has_epoll = 0;
636                                 printf "libc too old: $libcv... ";
637                         }
638                         if ($kernelv < 2.6)
639                         {
640                                 $has_epoll = 0;
641                                 printf "libc built against older kernel $kernelv... ";
642                         }
643                 }
644         }
645 }
646 print "yes\n" if $has_epoll == 1;
647 print "no\n" if $has_epoll == 0;
648
649 printf "Checking if Solaris I/O completion ports are available... ";
650 $has_ports = 0;
651 our $system = `uname -s`;
652 chomp ($system);
653 $has_ports = 1 if ($system eq "SunOS");
654
655 if ($has_ports) {
656         my $kernel = `uname -r`;
657         chomp($kernel);
658         if (($kernel !~ /^5\.1./)) {
659                 $has_ports = 0;
660         }
661 }
662 print "yes\n" if $has_ports == 1;
663 print "no\n" if $has_ports == 0;
664
665 $config{HAS_EPOLL} = $has_epoll;
666 $config{HAS_KQUEUE} = $has_kqueue; 
667
668 printf "Checking for libgnutls... ";
669 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
670         if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
671                 print "yes\n";
672                 $config{HAS_GNUTLS} = "y";
673         } else {
674                 print "no\n";
675                 $config{HAS_GNUTLS} = "n";
676         }
677 } else {
678         print "no\n";
679         $config{HAS_GNUTLS} = "n";
680 }
681
682 printf "Checking for openssl... ";
683 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
684         if (defined($openssl_ver) && ($openssl_ver ne "")) {
685                 print "yes\n";
686                 $config{HAS_OPENSSL} = "y";
687         } else {
688                 print "no\n";
689                 $config{HAS_OPENSSL} = "n";
690         }
691 } else {
692         print "no\n";
693         $config{HAS_OPENSSL} = "n";
694 }
695
696 printf "Checking if you are running an ancient, unsupported OS... ";
697 if ($config{OSNAME} =~ /FreeBSD/i)
698 {
699         my $version = `uname -r`;
700         if ($version =~ /^4\./)
701         {
702                 my $foundit = `ls -l /usr/local/lib/libgnugetopt* | wc -l`;
703                 if ($foundit > 0)
704                 {
705                         # ICKY ICKY ICK, FREEBSD 4.x! GET AN UPGRADE!
706                         $config{CRAQ} = "-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1";
707                         print "yes (upgrade ffs, freebsd 4 is *way* out of date)\n";
708                 }
709                 else
710                 {
711                         print "\n\nERROR: You require libgnugetopt (from ports or packages) to build InspIRCd on FreeBSD 4.11.\n";
712                 }
713         }
714         else
715         {
716                 $config{CRAQ} = " ";
717                 print "no ($version)\n";
718         }
719 }
720 else
721 {
722         $config{CRAQ} = " ";
723         print "no ($config{OSNAME})\n";
724 }
725
726 ################################################################################
727 #                         BEGIN INTERACTIVE PART                              #
728 ################################################################################
729
730 # Clear the Screen..
731 if ($interactive)
732 {
733         print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
734         my $wholeos = $^O;
735
736         my $rev = getrevision();
737         # Display Introduction Message..
738         print <<"STOP" ;
739 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
740 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
741
742 *** If you are unsure of any of these values, leave it blank for    ***
743 *** standard settings that will work, and your server will run      ***
744 *** using them. Please consult your IRC network admin if in doubt.  ***
745
746 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
747 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
748 dir, otherwise you won't have a config file!
749
750 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
751 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
752 STOP
753         if ($rev eq "r0") {
754                 print " (Non-SVN build)";
755         }
756         print ".\n\n";
757
758         $config{CHANGE_COMPILER} = "n";
759         print "I have detected the following compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
760
761         while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
762                 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
763 should NOT be used. You should probably specify a newer compiler.\n\n";
764                 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
765                 if ($config{CHANGE_COMPILER} =~ /y/i) {
766                         print "What command do you want to use to invoke your compiler?\n";
767                         print "[\e[1;32m$config{CC}\e[0m] -> ";
768                         chomp($config{CC} = <STDIN>);
769                         if ($config{CC} eq "") {
770                                 $config{CC} = "g++";
771                         }
772                         chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
773                         if ($foo ne "") {
774                                 chomp($config{GCCVER}       = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
775                                 chomp($config{GCCMINOR}     = `$config{CC} -dumpversion | cut -c 3`);
776                                 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
777                                 if ($config{GCCVER} < 3) {
778                                         print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
779                                 }
780                         }
781                         else {
782                                 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
783                         }
784                 }
785         }
786
787         print "\n";
788
789         # Directory Settings..
790         my $tmpbase = $config{BASE_DIR};
791         dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
792         if ($tmpbase ne $config{BASE_DIR}) {
793                 $config{CONFIG_DIR}      = resolve_directory($config{BASE_DIR}."/conf");           # Configuration Dir
794                 $config{MODULE_DIR}      = resolve_directory($config{BASE_DIR}."/modules");     # Modules Directory
795                 $config{BINARY_DIR}      = resolve_directory($config{BASE_DIR}."/bin");     # Binary Directory
796                 $config{LIBRARY_DIR}    = resolve_directory($config{BASE_DIR}."/lib");      # Library Directory
797         }
798
799         dir_check("are the configuration files", "CONFIG_DIR");
800         dir_check("are the modules to be compiled to", "MODULE_DIR");
801         dir_check("is the IRCd binary to be placed", "BINARY_DIR");
802         dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
803
804         my $chose_hiperf = 0;
805         if ($has_kqueue) {
806                 yesno('USE_KQUEUE',"You are running a BSD operating system, and kqueue\nwas detected. Would you like to enable kqueue support?\nThis is likely to increase performance.\nIf you are unsure, answer yes.\n\nEnable kqueue?");
807                 print "\n";
808                 if ($config{USE_KQUEUE} eq "y") {
809                         $chose_hiperf = 1;
810                 }
811         }
812         if ($has_epoll) {
813                 yesno('USE_EPOLL',"You are running a Linux 2.6+ operating system, and epoll\nwas detected. Would you like to enable epoll support?\nThis is likely to increase performance.\nIf you are unsure, answer yes.\n\nEnable epoll?");
814                 print "\n";
815                 if ($config{USE_EPOLL} eq "y") {
816                         $chose_hiperf = 1;
817                 }
818         }
819         if ($has_ports) {
820                 yesno('USE_PORTS',"You are running Solaris 10.\nWould you like to enable I/O completion ports support?\nThis is likely to increase performance.\nIf you are unsure, answer yes.\n\nEnable support for I/O completion ports?");
821                 print "\n";
822                 if ($config{USE_PORTS} eq "y") {
823                         $chose_hiperf = 1;
824                 }
825         }
826
827         if (!$chose_hiperf) {
828                 yesno('USE_POLL', "Would you like to use poll?\n This is likely to increase performance.\nIf you are unsure, answer yes.\n\nEnable poll?\n");
829                 if ($config{USE_POLL} ne "y")
830                 {
831                         print "No high-performance socket engines are available, or you chose\n";
832                         print "not to enable one. Defaulting to select() engine.\n\n";
833                 }
834         }
835
836         yesno('IPV6',"Would you like to build InspIRCd with IPv6 support?");
837         print "\n";
838
839         if ($config{IPV6} eq "y") {
840                 print "You have chosen to build an \e[1;32mIPV6-enabled\e[0m server.\nTo accept IPV4 users, you can still use IPV4 addresses\nin your port bindings..\n\n";
841                 $config{SUPPORT_IP6LINKS} = "y";
842         } else {
843                 yesno('SUPPORT_IP6LINKS',"You have chosen to build an \e[1;32mIPV4-only\e[0m server.\nWould you like to enable support for linking to IPV6-enabled\nInspIRCd servers? If you are using a recent operating system and are\nunsure, answer yes. If you answer 'no' here, your InspIRCd server will\nbe unable to parse IPV6 addresses (e.g. for CIDR bans)\n\nEnable linking to servers which have IPV6 enabled?");
844                 print "\n";
845         }
846
847         $config{USE_FREEBSD_BASE_SSL} = "n";
848         $config{USE_FREEBSD_PORTS_SSL} = "n";
849         if ($config{HAS_OPENSSL_PORT} ne "")
850         {
851                 $config{USE_FREEBSD_PORTS_SSL} = "y";
852                 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
853                 print "version \e[1;32m".$config{HAS_OPENSSL_PORT}."\e[0m. Your base system OpenSSL is version \e[1;32m".$openssl_ver."\e[0m.\n\n";
854                 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
855                 print "\n";
856                 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
857
858                 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
859                 {
860                         # update to port version
861                         $openssl_ver = $config{HAS_OPENSSL_PORT};
862                 }
863         }
864         else
865         {
866                 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
867         }
868
869         $config{USE_SSL} = "n";
870
871         if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
872         {
873                 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
874                 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
875
876                 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
877                 if ($config{USE_SSL} eq "y")
878                 {
879                         if ($config{HAS_GNUTLS} eq "y")
880                         {
881                                 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
882                                 if ($config{USE_GNUTLS} eq "y")
883                                 {
884                                         print "\nUsing GnuTLS SSL module.\n";
885                                 }
886                         }
887
888                         if ($config{HAS_OPENSSL} eq "y")
889                         {
890                                 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
891                                 if ($config{USE_OPENSSL} eq "y")
892                                 {
893                                         print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
894                                 }
895                         }
896                 }
897         }
898         else
899         {
900                 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed if\n";
901                 print "you intend to use OpenSSL, or that GnuTLS is in your path if you intend\nto use GnuTLS.\n\n";
902         }
903 }
904
905 dumphash();
906
907 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
908 {
909         print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
910         exit(0);
911 }
912 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
913 {
914         print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
915         exit(0);
916 }
917 our $failed = 0;
918
919 if ($config{USE_GNUTLS} eq "y") {
920         unless (-r "src/modules/m_ssl_gnutls.cpp") {
921                 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
922                 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
923         }
924         getmodules();
925         if ($interactive)
926         {
927                 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
928                         print "SSL Certificates Not found, Generating.. \n\n
929 *************************************************************
930 * Generating the Private Key may take some time, go grab a  *
931 * Coffee. Even better, to generate some more entropy if it  *
932 * is taking a while, open another console and type du / a   *
933 * few times and get that HD going :) Then answer the        *
934 * Questions which follow. If you are unsure, just hit enter *
935 *************************************************************\n\n";
936                         $failed = make_gnutls_cert();
937                         if ($failed) {
938                                 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
939                         } else {
940                                 print "\nCertificate generation complete, copying to config directory... ";
941                                 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
942                                 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
943                                 print "Done.\n\n";
944                         }
945                 }
946                 else {
947                         print "SSL Certificates found, skipping.\n\n";
948                 }
949         }
950         else
951         {
952                 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
953         }
954 } elsif ($config{USE_OPENSSL} eq "y") {
955         unless (-r "src/modules/m_ssl_openssl.cpp") {
956                 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
957                 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
958         }
959         getmodules();
960         $failed = 0;
961         if ($interactive)
962         {
963                 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
964                         print "SSL Certificates Not found, Generating.. \n\n
965 *************************************************************
966 * Generating the certificates may take some time, go grab a *
967 * coffee, or something.                                     *
968 *************************************************************\n\n";
969                         make_openssl_cert();
970                         print "\nCertificate generation complete, copying to config directory... ";
971                         File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
972                         File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
973                         File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
974                         print "Done.\n\n";
975                 } else {
976                         print "SSL Certificates found, skipping.\n\n"
977                 }
978         }
979         else
980         {
981                 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
982         }
983 }
984 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
985         print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
986 }
987
988 getosflags();
989 writefiles(1);
990 makecache();
991
992 print "\n\n";
993 print "To build your server with these settings, please type '\e[1;32m$config{MAKEPROG}\e[0m' now.\n";
994 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
995         print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
996         print "modules in your config. This configure script has added those modules to the\n";
997         print "build process. For more info please refer to:\n";
998         print "\e[1;32mhttp://www.inspircd.org/wiki/Installation_From_Tarball\e[0m\n";
999 }
1000 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
1001 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
1002         print "\e[1;32mWARNING!\e[0m You are running OpenBSD but you are using the base gcc package\nrather than eg++. This compile will most likely fail, but i'm letting you\ngo ahead with it anyway, just in case i'm wrong :-)\n";
1003 }
1004
1005 if ($config{GCCVER} < "3") {
1006         print <<FOO2;
1007 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
1008 GCC 2.x series compilers only had partial (read as broken) C++ support, and
1009 your compile will most likely fail horribly! If you have any problems, do NOT
1010 report them to the bugtracker or forums without first upgrading your compiler
1011 to a newer 3.x or 4.x (or whatever is available currently) version.
1012 FOO2
1013 }
1014
1015 ################################################################################
1016 #                             HELPER FUNCTIONS                          #
1017 ################################################################################
1018 sub getcache {
1019         # Retrieves the .config.cache file, and loads values into the main config hash.
1020         open(CACHE, ".config.cache") or return 0;
1021         while (<CACHE>) {
1022                 chomp;
1023                 # Ignore Blank lines, and comments..
1024                 next if /^\s*$/;
1025                 next if /^\s*#/;
1026                 my ($key, $value) = split("=", $_, 2);
1027                 $value =~ /^\"(.*)\"$/;
1028                 # Do something with data here!
1029                 $config{$key} = $1;
1030         }
1031         close(CACHE);
1032         return 1;
1033 }
1034
1035 sub makecache {
1036         # Dump the contents of %config
1037         print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
1038         open(FILEHANDLE, ">.config.cache");
1039         foreach my $key (keys %config) {
1040                 print FILEHANDLE "$key=\"$config{$key}\"\n";
1041         }
1042         close(FILEHANDLE);
1043 }
1044
1045 sub dir_check {
1046         my ($desc, $hash_key) = @_;
1047         my $complete = 0;
1048         while (!$complete) {
1049                 print "In what directory $desc?\n";
1050                 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
1051                 chomp(my $var = <STDIN>);
1052                 if ($var eq "") {
1053                         $var = $config{$hash_key};
1054                 }
1055                 if ($var =~ /^\~\/(.+)$/) {
1056                         # Convert it to a full path..
1057                         $var = resolve_directory($ENV{HOME} . "/" . $1);
1058                 }
1059                 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
1060                 {
1061                         # Assume relative Path was given.. fill in the rest.
1062                         $var = $this . "/$var";
1063                 }
1064                 
1065                 $var = resolve_directory($var); 
1066                 if (! -e $var) {
1067                         print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
1068                         chomp(my $tmp = <STDIN>);
1069                         if (($tmp eq "") || ($tmp =~ /^y/i)) {
1070                                 # Attempt to Create the Dir..
1071                                 my $chk = eval {
1072                                         use File::Path ();
1073                                         File::Path::mkpath($var, 0, 0777);
1074                                         1;
1075                                 };
1076                                 unless (defined($chk) && -d $var) {
1077                                         print "Unable to create directory. ($var)\n\n";
1078                                         # Restart Loop..
1079                                         next;
1080                                 }
1081                         } else {
1082                                 # They said they don't want to create, and we can't install there.
1083                                 print "\n\n";
1084                                 next;
1085                         }
1086                 } else {
1087                         if (!is_dir($var)) {
1088                                 # Target exists, but is not a directory.
1089                                 print "File $var exists, but is not a directory.\n\n";
1090                                 next;
1091                         }
1092                 }
1093                 # Either Dir Exists, or was created fine.
1094                 $config{$hash_key} = $var;
1095                 $complete = 1;
1096                 print "\n";
1097         }
1098 }
1099
1100 our $SHARED = "";
1101
1102 sub getosflags {
1103
1104         # Beware: Linux sets it's own cflags below for some retarded reason
1105         $config{LDLIBS} = "-pthread -lstdc++";
1106         $config{FLAGS}  = "-fPIC -Woverloaded-virtual -Wshadow -Wformat=2 -Wmissing-format-attribute -Wall $config{OPTIMISATI}";
1107         $config{DEVELOPER} = "-fPIC -Woverloaded-virtual -Wshadow -Wall -Wformat=2 -Wmissing-format-attribute -g";
1108         $SHARED = "-shared";
1109         $config{MAKEPROG} = "make";
1110
1111         if ($config{OSNAME} =~ /darwin/i) {
1112                 $config{FLAGS}  = "-DDARWIN -frtti -fPIC -Wall $config{OPTIMISATI}";
1113                 $SHARED = "-bundle -twolevel_namespace -undefined dynamic_lookup";
1114                 $config{LDLIBS} = "-ldl -pthread -lstdc++";
1115         }
1116
1117         if ($config{OSNAME} =~ /OpenBSD/i) {
1118                 $config{MAKEPROG} = "gmake";
1119 # apparantly (Dagonet says) that this causes problems, so let's try without it.
1120 #               $config{LDLIBS} = $config{LDLIBS} . " -lunwind";
1121                 chomp(my $foo = `eg++ -dumpversion | cut -c 1`);
1122                 # theyre running the package version of gcc (eg++)... detect it and set up its version numbers.
1123                 # if theyre not running this, configure lets the build continue but they probably wont manage to
1124                 # compile as this standard version is 2.95.3!
1125                 if ($foo ne "") {
1126                         $config{CC} = "eg++";
1127                         chomp($config{GCCVER}       = `eg++ -dumpversion | cut -c 1`); # we must redo these if we change the compiler path
1128                         chomp($config{GCCMINOR}     = `eg++ -dumpversion | cut -c 3`);
1129                 }
1130                 return "OpenBSD";
1131         }
1132
1133         if ($config{OSNAME} =~ /Linux/i) {
1134                 $config{LDLIBS} = "-ldl -lstdc++ -pthread";
1135 #               $config{FLAGS}  = "-fPIC -Woverloaded-virtual -Wshadow -Wall $config{OPTIMISATI}";
1136                 $config{FLAGS}  .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1137                 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1138                 $config{MAKEPROG} = "make";
1139         }
1140
1141         if ($config{OSNAME} =~ /FreeBSD/i) {
1142                 $config{FLAGS}  .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1143                 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1144         }
1145
1146         if ($config{OSNAME} =~ /SunOS/i or $config{OSNAME} =~ /solaris/i)
1147         {
1148                 # solaris/sunos needs these
1149                 # socket = bsd sockets api
1150                 # nsl = dns stuff
1151                 # rt = POSIX realtime extensions
1152                 # resolv = inet_aton only (why isnt this in nsl?!)
1153                 $config{MAKEPROG} = "gmake";
1154                 $config{LDLIBS} .= " -lsocket -lnsl -lrt -lresolv -pthread";
1155                 return "Solaris";
1156         }
1157         
1158         if($config{OSNAME} =~ /MINGW32/i)
1159         {
1160                 # All code is position-independent on windows
1161                 $config{FLAGS} =~ s/-fPIC //;
1162                 return "MinGW";
1163         }
1164
1165         return $config{OSNAME};
1166 }
1167
1168 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
1169
1170 sub writefiles {
1171         my($writeheader) = @_;
1172         my $se = "";
1173         # First File.. inspircd_config.h
1174         chomp(my $incos = `uname -n -s -r`);
1175         chomp(my $version = `sh src/version.sh`);
1176         chomp(my $revision2 = getrevision());
1177         if ($writeheader == 1)
1178         {
1179                 print "Writing \e[1;32minspircd_config.h\e[0m\n";
1180                 open(FILEHANDLE, ">include/inspircd_config.h");
1181                 print FILEHANDLE <<EOF;
1182 /* Auto generated by configure, do not modify! */
1183 #ifndef __CONFIGURATION_AUTO__
1184 #define __CONFIGURATION_AUTO__
1185
1186 /* this is for windows support. */
1187 #define CoreExport /**/
1188 #define DllExport /**/
1189
1190 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
1191 #define MOD_PATH "$config{MODULE_DIR}"
1192 #define VERSION "$version"
1193 #define REVISION "$revision2"
1194 #define SOMAXCONN_S "$config{_SOMAXCONN}"
1195 #define OPTIMISATION $config{OPTIMITEMP}
1196 #define LIBRARYDIR "$config{LIBRARY_DIR}"
1197 #define SYSTEM "$incos"
1198 #define ENTRYPOINT int main(int argc, char** argv)
1199
1200 EOF
1201 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
1202
1203                 if ($config{OSNAME} =~ /SunOS/i) {
1204                         print FILEHANDLE "#define IS_SOLARIS\n";
1205                 }
1206                 if ($config{OSNAME} =~ /MINGW32/i) {
1207                         print FILEHANDLE "#define IS_MINGW\n";
1208                 }
1209                 if ($config{GCCVER} >= 3) {
1210                         print FILEHANDLE "#define GCC3\n";
1211                 }
1212                 if (
1213                         (($config{GCCVER} == 4) && ($config{GCCMINOR} >= 3))
1214                                 ||
1215                         ($config{GCCVER} > 4)
1216                 ) {
1217                         print FILEHANDLE "#define HASHMAP_DEPRECATED\n";
1218                 }
1219                 if ($config{HAS_STRLCPY} eq "true") {
1220                         print FILEHANDLE "#define HAS_STRLCPY\n";
1221                 }
1222                 if ($config{HAS_STDINT} eq "true") {
1223                         print FILEHANDLE "#define HAS_STDINT\n";
1224                 }
1225                 if ($config{IPV6} =~ /y/i) {
1226                         print FILEHANDLE "#define IPV6\n";
1227                 }
1228                 if ($config{SUPPORT_IP6LINKS} =~ /y/i) {
1229                         print FILEHANDLE "#define SUPPORT_IP6LINKS\n";
1230                 }
1231                 my $use_hiperf = 0;
1232                 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
1233                         print FILEHANDLE "#define USE_KQUEUE\n";
1234                         $se = "socketengine_kqueue";
1235                         $use_hiperf = 1;
1236                 }
1237                 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
1238                         print FILEHANDLE "#define USE_EPOLL\n";
1239                         $se = "socketengine_epoll";
1240                         $use_hiperf = 1;
1241                 }
1242                 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
1243                         print FILEHANDLE "#define USE_PORTS\n";
1244                         $se = "socketengine_ports";
1245                         $use_hiperf = 1;
1246                 }
1247                 # user didn't choose either epoll or select for their OS.
1248                 # default them to USE_SELECT (ewwy puke puke)
1249                 if (!$use_hiperf) {
1250                         print "no hi-perf, " . $config{USE_POLL};
1251                         if ($config{USE_POLL} eq "y")
1252                         {
1253                                 print FILEHANDLE "#define USE_POLL\n";
1254                                 $se = "socketengine_poll";
1255                         }
1256                         else
1257                         {
1258                                 print FILEHANDLE "#define USE_SELECT\n";
1259                                 $se = "socketengine_select";
1260                         }
1261                 }
1262                 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
1263                 close(FILEHANDLE);
1264         }
1265
1266         if ($writeheader)
1267         {
1268                 open(FILEHANDLE, ">include/inspircd_se_config.h");
1269                 print FILEHANDLE <<EOF;
1270 /* Auto generated by configure, do not modify or commit to svn! */
1271 #ifndef __CONFIGURATION_SOCKETENGINE__
1272 #define __CONFIGURATION_SOCKETENGINE__
1273
1274 #include "socketengines/$se.h"
1275
1276 #endif
1277 EOF
1278                 close(FILEHANDLE);
1279         }
1280
1281
1282         # Create a Modules List..
1283         my $modules = "";
1284         foreach my $i (@modlist)
1285         {
1286                 $modules .= "m_".$i.".so ";
1287         }
1288         chomp($modules);   # Remove Redundant whitespace..
1289
1290         opendir(DIRHANDLE, "src/modules");
1291         foreach my $name2 (sort readdir(DIRHANDLE)) {
1292                 if ($name2 =~ /^m_(.+?)$/) {
1293                         if (defined(opendir(MDIRHANDLE, "src/modules/$name2"))) {
1294                                 closedir(MDIRHANDLE);
1295                                 $modules .= "$name2.so ";
1296                                 $uninstall_list = $uninstall_list . "   -rm \$(MODULES)/$name2.so\n";
1297                         }
1298                 }
1299         }
1300         closedir(DIRHANDLE);
1301
1302
1303         # Write all .in files.
1304         my $tmp = "";
1305         my $file = "";
1306         my $exe = "inspircd";
1307
1308         # Do this once here, and cache it in the .*.inc files,
1309         # rather than attempting to read src/version.sh from
1310         # compiled code -- we might not have the source to hand.
1311         # Fix for bug#177 by Brain.
1312
1313         chomp($version = `sh ./src/version.sh`);
1314         chomp(my $revision = getrevision());
1315         $version = "$version(r$revision)";
1316
1317         # We can actually parse any file starting with . and ending with .inc,
1318         # but right now we only parse .inspircd.inc to form './inspircd'
1319
1320         print "Writing \e[1;32mMakefiles\e[0m\n";
1321         write_dynamic_modules_makefile();
1322         write_dynamic_makefile();
1323
1324         opendir(DIRHANDLE, $this);
1325
1326         foreach my $name (sort readdir(DIRHANDLE)) {
1327                 if ($name =~ /^\.(.+)\.inc$/) {
1328                         $file = $1;
1329
1330                         # Bug #353, omit this on non-darwin
1331                         next if (($config{OSNAME} !~ /darwin/) && ($file eq "org.inspircd.plist"));
1332
1333                         # All .name.inc files need parsing!
1334                         $tmp = "";
1335                         open(FILEHANDLE, ".$file.inc") or die ("Can't open .$file.inc");
1336                         while (<FILEHANDLE>) {
1337                                 $tmp .= $_;
1338                         }
1339                         close(FILEHANDLE);
1340
1341                         print "Writing \e[1;32m$file\e[0m ...\n";
1342                         $tmp =~ s/\@CC\@/$config{CC}/ if defined $config{CC};
1343                         $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/ if defined $config{MAKEPROG};
1344                         $tmp =~ s/\@FLAGS\@/$config{FLAGS}/ if defined $config{FLAGS};
1345                         $tmp =~ s/\@DEVELOPER\@/$config{DEVELOPER}/ if defined $config{DEVELOPER};
1346                         $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/ if defined $config{LDLIBS};
1347                         $tmp =~ s/\@BASE_DIR\@/$config{BASE_DIR}/ if defined $config{BASE_DIR};
1348                         $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/ if defined $config{CONFIG_DIR};
1349                         $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/ if defined $config{MODULE_DIR};
1350                         $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/ if defined $config{BINARY_DIR};
1351                         $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/ if defined $config{LIBRARY_DIR};
1352                         $tmp =~ s/\@MODULES\@/$modules/ if defined $modules;
1353                         $tmp =~ s/\@STARTSCRIPT\@/$config{STARTSCRIPT}/ if defined $config{STARTSCRIPT};
1354                         $tmp =~ s/\@DESTINATION\@/$config{DESTINATION}/ if defined $config{DESTINATION};
1355                         $tmp =~ s/\@EXTRA_DIR\@/$config{EXTRA_DIR}/ if defined $config{EXTRA_DIR};
1356                         $tmp =~ s/\@EXECUTABLE\@/$exe/ if defined $exe;
1357                         $tmp =~ s/\@MAKEORDER\@/$config{MAKEORDER}/ if defined $config{MAKEORDER};
1358                         $tmp =~ s/\@VERSION\@/$version/ if defined $version;
1359                         $tmp =~ s/\@INSTALL_LIST\@/$install_list/ if defined $install_list;
1360                         $tmp =~ s/\@UNINSTALL_LIST\@/$uninstall_list/ if defined $uninstall_list;
1361
1362                         open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
1363                         print FILEHANDLE $tmp;
1364                 }
1365         }
1366         closedir(DIRHANDLE);
1367
1368         # Make inspircd executable!
1369         chmod 0744, 'inspircd';
1370 }
1371
1372 sub write_dynamic_modules_makefile {
1373         # Modules Makefile..
1374         print "Writing \e[1;32msrc/modules/Makefile\e[0m\n";
1375         open(FILEHANDLE, ">src/modules/Makefile");
1376
1377 ###
1378 # Module Makefile Header
1379 ###
1380         print FILEHANDLE <<EOF;
1381 ###################################################
1382 # Copyright 2002-2007 The InspIRCd Development Team
1383 #  http://www.inspircd.org/wiki/index.php/Credits
1384 #
1385 # Thanks to Andrew Church <achurch\@achurch.org>
1386 #   for assisting with making this work right.
1387 #
1388 # Automatically Generated by ./configure to add a
1389 #  modules please run ./configure -modupdate
1390 ###################################################
1391
1392 all: \$(MODULES)
1393
1394 EOF
1395
1396 if ($config{OSNAME} =~ /darwin/) {
1397                 print FILEHANDLE <<EOCHEESE;
1398
1399 PICLDFLAGS = -twolevel_namespace -undefined dynamic_lookup -bundle
1400
1401 EOCHEESE
1402 } else {
1403                 print FILEHANDLE <<EOCHEESE;
1404
1405 PICLDFLAGS = -fPIC -DPIC -shared
1406
1407 EOCHEESE
1408 }
1409
1410         ###
1411         # End Module Makefile Header
1412         ###
1413
1414         # Create a Modules List..
1415         my $modules = "";
1416         my $cmflags = "";
1417         my $liflags = "";
1418         foreach my $i (@modlist) {
1419                 ###
1420                 # Write Entry to the MakeFile
1421                 ###
1422                 $cmflags = getcompilerflags("src/modules/m_".$i.".cpp");
1423                 $liflags = getlinkerflags("src/modules/m_".$i.".cpp");
1424                 my $deps = getdependencies("src/modules/m_".$i.".cpp");
1425         
1426                 #print "file: $i: cmflags=$cmflags; liflags=$liflags; deps=$deps\n";
1427         
1428
1429                 if (nopedantic("src/modules/m_".$i.".cpp"))
1430                 {
1431                         print FILEHANDLE "
1432 m_$i.so: m_$i.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/base.h ../../include/inspircd_config.h ../../include/inspircd.h ../../include/configreader.h $deps
1433         \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(NICEFLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1434 "
1435                 }
1436                 else
1437                 {
1438                         print FILEHANDLE "
1439 m_$i.so: m_$i.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/base.h ../../include/inspircd_config.h ../../include/inspircd.h ../../include/configreader.h $deps
1440         \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(FLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1441 ";
1442                 }
1443                 $install_list = $install_list . "       install -m \$(INSTMODE) src/modules/m_$i.so \$(MODPATH)\n";
1444                 $uninstall_list = $uninstall_list . "   -rm \$(MODULES)/m_$i.so\n";
1445 ###
1446                 # End Write Entry to the MakeFile
1447                 ###
1448         }
1449
1450         opendir(DIRHANDLE, "src/modules");
1451         foreach my $name (sort readdir(DIRHANDLE)) {
1452                 if ($name =~ /^m_(.+?)$/) {
1453                         $mfrules = "";
1454                         $mobjs = "";
1455                         $mliflags = "";
1456                         $mfcount = 0;
1457                         # A module made of multiple files, in a dir, e.g. src/modules/m_spanningtree/
1458                         if (defined(opendir(MDIRHANDLE, "src/modules/$name"))) {
1459                                 read_module_directory("src/modules/$name", $name);
1460                                 print "Composing Makefile rules for directory \e[1;32m$name\e[0m... (\e[1;32m$mfcount files found\e[0m)\n";
1461                                 print FILEHANDLE "$name.so: ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/base.h ../../include/inspircd_config.h ../../include/inspircd.h ../../include/configreader.h $mobjs\n"; 
1462                                 if ($config{IS_DARWIN} eq "YES") {
1463                                         print FILEHANDLE "      \@../../make/run-cc.pl \$(CC) -pipe -twolevel_namespace -undefined dynamic_lookup \$(FLAGS) $mliflags -bundle -o $name.so $mobjs\n"; 
1464                                 } else {
1465                                         print FILEHANDLE "      \@../../make/run-cc.pl \$(CC) -pipe \$(FLAGS) -shared $mliflags -o $name.so $mobjs\n";
1466                                 }
1467                                 print FILEHANDLE "\n$mfrules\n";
1468                                 closedir(MDIRHANDLE);
1469                                 $install_list = $install_list . "       install -m \$(INSTMODE) src/modules/$name.so \$(MODPATH)\n";
1470                         }
1471                 }
1472         }
1473         closedir(DIRHANDLE);
1474 }
1475
1476 sub read_module_directory {
1477         my ($dpath, $reldpath) = @_;
1478         
1479         if (opendir(MDIRHANDLE, $dpath) == 0) {
1480                 return;
1481         }
1482         
1483         foreach my $fname (sort readdir(MDIRHANDLE)) {
1484                 if ($fname =~ /\.cpp$/) {
1485                         my $cmflags = getcompilerflags("$dpath/$fname");
1486                         $mliflags = $mliflags . " " . getlinkerflags("$dpath/$fname");
1487                         my $deps = getdependencies("$dpath/$fname");
1488                         my $oname = $fname;
1489                         $oname =~ s/\.cpp$/.o/g;
1490                         $mfrules = $mfrules .  "$reldpath/$oname: $reldpath/$fname ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/base.h ../../include/inspircd_config.h ../../include/inspircd.h ../../include/configreader.h $deps\n";
1491                         $mfrules = $mfrules .  "        \@../../make/run-cc.pl \$(CC) -pipe -I../../include -I. \$(FLAGS) $cmflags -export-dynamic -o $reldpath/$oname -c $reldpath/$fname\n\n";
1492                         $mobjs = $mobjs . " $reldpath/$oname";
1493                         $mfcount++;
1494                 }
1495                 elsif ((-d "$dpath/$fname") && !($fname eq ".") && !($fname eq "..")) {
1496                         read_module_directory($dpath."/".$fname, $reldpath."/".$fname);
1497                 }
1498         }
1499 }
1500
1501 sub calcdeps($)
1502 {
1503         # Yes i know we could use gcc -M but it seems to ideneify a lot of 'deep'
1504         # dependencies which are not relevent in C++.
1505
1506         my $file = $_[0];
1507
1508         open (CPP, "<$file") or die("Can't open $file for reading!");
1509
1510         my %dupe = ();
1511         my $retlist = "";
1512
1513         foreach my $d (@ignoredeps)
1514         {
1515                 $dupe{$d} = 1;
1516         }
1517
1518         my $immutable = "";
1519         foreach my $dep (@immutabledeps)
1520         {
1521                 $immutable = $immutable . "../include/$dep ";
1522         }
1523         $immutable =~ s/ $//g;
1524
1525         while (defined(my $line = <CPP>))
1526         {
1527                 chomp($line);
1528                 if ($line =~ /#include "(.+\.h)"/)
1529                 {
1530                         if (!exists($dupe{$1}))
1531                         {
1532                                 $retlist = $retlist . "../include/$1 ";
1533                                 $dupe{$1} = 1;
1534                         }
1535                 }
1536         }
1537         close CPP;
1538         return length($immutable) ? $immutable . " " . $retlist : $retlist;
1539 }
1540
1541 sub write_dynamic_makefile
1542 {
1543         my $i = 0;
1544         my @cmdlist = ();
1545         my %existing_install_list = ();
1546         my %core_files_list = ();
1547
1548         opendir(DIRHANDLE, "src/commands");
1549         foreach my $name (sort readdir(DIRHANDLE))
1550         {
1551                 if ($name =~ /^cmd_(.+)\.cpp$/)
1552                 {
1553                         $cmdlist[$i++] = $1;
1554                         $install_list = $install_list . "       -install -m \$(INSTMODE) src/commands/cmd_" . $1 . ".so \$(LIBPATH)\n";
1555                         $uninstall_list = $uninstall_list . "   -rm \$(LIBPATH)/cmd_$1.so\n";
1556                 }
1557         }
1558         closedir(DIRHANDLE);
1559
1560         if (!$has_epoll)
1561         {
1562                 $config{USE_EPOLL} = 0;
1563         }
1564         if (!$has_kqueue)
1565         {
1566                 $config{USE_KQUEUE} = 0;
1567         }
1568         if (!$has_ports)
1569         {
1570                 $config{USE_PORTS} = 0;
1571         }
1572
1573         # formerly generated below this foreach, now it's not! magic.
1574         my $all_core = "";
1575
1576         foreach my $dir (("src","src/commands","src/modes","src/socketengines","src/modules"))
1577         {
1578                 print "Scanning \e[1;32m$dir\e[0m for core files ";
1579                 opendir(DIRHANDLE, $dir);
1580                 foreach my $name (sort readdir(DIRHANDLE))
1581                 {
1582                         if ($name =~ /\.cpp$/)
1583                         {
1584                                 open (CPP, "<$dir/$name") or die("Can't open $dir/$name to scan it! oh bugger");
1585                                 print ".";
1586                                 while (defined(my $line = <CPP>))
1587                                 {
1588                                         chomp($line);
1589                                         if ($line =~ /\/\* \$Core \*\//i)
1590                                         {
1591                                                 my $sname = $name;
1592                                                 $sname =~ s/\.cpp$/.o/;
1593
1594                                                 # append it to list to be built
1595                                                 $all_core = $all_core . $sname . " ";
1596                                                 $filelist{$name} = $sname;
1597
1598                                                 # mark it as a core file, so it won't get shared object cflags
1599                                                 if (!exists($core_files_list{$name}))
1600                                                 {
1601                                                         $core_files_list{$name} = 1;
1602                                                 }
1603                                         }
1604                                         elsif ($line =~ /\/\* \$ExtraDeps: (.*?) \*\//i)
1605                                         {
1606                                                 $specialdeps{$name} = $1;
1607                                         }
1608                                         elsif ($line =~ /\/\* \$ExtraObjects: (.*?) \*\//i)
1609                                         {
1610                                                 $extraobjects{$name} = $1;
1611                                         }
1612                                         elsif ($line =~ /\/\* \$ExtraBuild: (.*?) \*\//i)
1613                                         {
1614                                                 $extrabuildlines{$name} = $1;
1615                                         }
1616                                         elsif ($line =~ /\/\* \$ExtraSources: (.*?) \*\//i)
1617                                         {
1618                                                 $extrasources{$name} = $1;
1619                                                 }
1620                                         elsif ($line =~ /\/\* \$If: (\w+) \*\//i)
1621                                         {
1622                                                 if (defined $config{$1})
1623                                                 {
1624                                                         if (($config{$1} !~ /y/i) and ($config{$1} ne "1"))
1625                                                         {
1626                                                                 # Skip to 'endif'
1627                                                                 while (defined($line = <CPP>))
1628                                                                 {
1629                                                                         chomp($line);
1630                                                                         die ("\$If buildsystem instruction within another \$If in file $dir/$name") if ($line =~ /\/\* \$If: (\w+) \*\//i);
1631                                                                         last if ($line =~ /\/\* \$EndIf \*\//i);
1632                                                                 }
1633                                                         }
1634                                                 }
1635                                         }
1636                                         elsif ($line =~ /\/\* \$Install: (.*?) \*\//i)
1637                                         {
1638                                                 if (!exists($existing_install_list{$1}))
1639                                                 {
1640                                                         $existing_install_list{$1} = 1;
1641                                                         my $idir = (split(' ',$1))[1];
1642                                                         my $ifile = (split(' ',$1))[0];
1643                                                         $install_list = $install_list . "       -install -m \$(INSTMODE) $1\n";
1644                                                         $ifile =~ s/.*\///g;
1645                                                         $uninstall_list = $uninstall_list . "   -rm $idir/$ifile\n";
1646                                                 }
1647                                         }
1648                                         elsif ($line =~ /\/\* \$CopyInstall: (.*?) \*\//i)
1649                                         {
1650                                                 if (!exists($existing_install_list{$1}))
1651                                                 {
1652                                                         $existing_install_list{$1} = 1;
1653                                                         my $idir = (split(' ',$1))[1];
1654                                                         my $ifile = (split(' ',$1))[0];
1655                                                         $install_list = $install_list . "       -cp $1\n";
1656                                                         $ifile =~ s/.*\///g;
1657                                                         $uninstall_list = $uninstall_list . "   -rm $idir/$ifile\n";
1658                                                 }
1659                                         }
1660                                 }
1661                                 close CPP;
1662                         }
1663                 }
1664                 closedir(DIRHANDLE);
1665                 print " done!\n";
1666         }
1667
1668         # modes need to be compiled in too
1669         $all_core = $all_core . "modes/modeclasses.a";
1670
1671         my $freebsd4libs = (defined $config{CRAQ} ? $config{CRAQ} : "");
1672
1673         my $libraryext = "";
1674         my $binary_rule = "";
1675
1676         if ($config{IS_DARWIN} eq "YES")
1677         {
1678                 $libraryext = "dylib";
1679                 $binary_rule = "        \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) -c inspircd.cpp\n       \@../make/run-cc.pl \$(CC) -pipe -dynamic -bind_at_load -L. -o inspircd \$(LDLIBS) inspircd.o "
1680         }
1681         else
1682         {
1683                 $libraryext = "so";
1684                 $binary_rule = "        \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) $freebsd4libs -rdynamic -L. inspircd.cpp -o inspircd \$(LDLIBS) ";
1685         }
1686
1687         open(FH,">src/Makefile") or die("Could not write src/Makefile");
1688         print FH <<EOM;
1689
1690 CC = im a cheezeball
1691 CXXFLAGS = -I../include \${FLAGS}
1692 CPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* //' | grep -v svn)
1693 RELCPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* /modes\\//' | grep -v svn)
1694
1695 EOM
1696
1697         my $buildstring = "";
1698         my $deps = "";
1699
1700         foreach my $cpp (sort keys %filelist)
1701         {
1702                 my $objs = $cpp;
1703                 my $rawcpp = $cpp;
1704                 $objs =~ s/\.cpp$/.o/;
1705                 if (exists($extraobjects{$cpp}))
1706                 {
1707                         $objs = $objs . " " . $extraobjects{$cpp};
1708                         $all_core = $all_core . " " . $extraobjects{$cpp};
1709                 }
1710                 if (exists($extrasources{$cpp}))
1711                 {
1712                         $rawcpp = $rawcpp . " " . $extrasources{$cpp};
1713                 }
1714
1715                 $deps = calcdeps("src/$cpp");
1716                 if (exists($extrasources{$cpp}))
1717                 {
1718                         foreach my $seperate (sort split(' ',$extrasources{$cpp}))
1719                         {
1720                                 my $d = calcdeps("src/$extrasources{$cpp}") . " ";
1721                                 if ($d ne "")
1722                                 {
1723                                         $deps = $deps . $d . " ";
1724                                 }
1725                         }
1726                 }
1727                 $buildstring = $buildstring . $objs . ": $cpp $deps ". (defined($specialdeps{$cpp}) ? $specialdeps{$cpp} : "") . "\n";
1728
1729                 if (exists($core_files_list{$cpp}))
1730                 {
1731                         # core files are statically linked into the binary and do not require -export-dynamic
1732                         $buildstring = $buildstring . " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) -c $rawcpp\n";
1733                 }
1734                 else
1735                 {
1736                         $buildstring = $buildstring . " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c $rawcpp\n";
1737                 }
1738
1739                 if (exists($extrabuildlines{$cpp}))
1740                 {
1741                         $buildstring = $buildstring . " " . $extrabuildlines{$cpp} . "\n";
1742                 }
1743         }
1744
1745         print FH "all: inspircd moo\n\n\n";
1746
1747         $deps = calcdeps("src/inspircd.cpp");
1748         print FH "inspircd: inspircd.cpp $deps $all_core\n";
1749         print FH "$binary_rule $all_core\n\n";
1750
1751         print FH $buildstring;
1752         print FH "moo:\n        \@\${MAKE} -C \"commands\" DIRNAME=\"src/commands\" CC=\"\$(CC)\" \$(MAKEARGS)\n\n";
1753
1754         # close main makefile
1755         close(FH);
1756
1757         my $cmdobjs = "";
1758         # generate a list of .so
1759         foreach my $cmd (@cmdlist) {
1760                 $cmdobjs = $cmdobjs . "cmd_$cmd.so ";
1761         }
1762
1763         # and now reopen the commands makefile
1764         open(FH,">src/commands/Makefile") or die("Could not write src/commands/Makefile");
1765         print FH <<ITEM;
1766 CC = i am cornholio
1767 CXXFLAGS = -I../../include \${FLAGS}
1768
1769 all: $cmdobjs
1770
1771
1772 ITEM
1773
1774         # now print the command file details.
1775         foreach my $cmd (@cmdlist) {
1776                 print FH <<ITEM;
1777 cmd_$cmd.so: cmd_$cmd.cpp ../../include/base.h ../../include/modules.h ../../include/inspircd.h ../../include/channels.h ../../include/users.h ../../include/inspircd_config.h ../../include/commands/cmd_$cmd.h
1778         \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic $SHARED -o cmd_$cmd.so cmd_$cmd.cpp
1779
1780 ITEM
1781         }
1782 }
1783
1784 # Routine to list out the extra/ modules that have been enabled.
1785 # Note: when getting any filenames out and comparing, it's important to lc it if the
1786 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1787 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1788 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1789 sub list_extras () {
1790         use File::Spec;
1791         # @_ not used
1792         my $srcdir = File::Spec->catdir("src", "modules");
1793         my $abs_srcdir = File::Spec->rel2abs($srcdir);
1794         local $_;
1795         my $dd;
1796         opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1797         my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1798         closedir $dd;
1799         undef $dd;
1800         opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1801         my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1802         closedir $dd;
1803         undef $dd;
1804         my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1805         my %extras = ();
1806 EXTRA:  for my $extra (@extras) {
1807                 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1808                 next if ($extra eq '.svn');
1809                 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1810                 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1811                 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1812                 if (-l $abs_source) {
1813                         # Symlink, is it in the right place?
1814                         my $targ = readlink($abs_source);
1815                         my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1816                         if ($abs_targ eq $abs_extra) {
1817                                 $extras{$extra} = "\e[32;1menabled\e[0m";
1818                         } else {
1819                                 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1820                         }
1821                 } elsif (-e $abs_source) {
1822                         my ($devext, $inoext) = stat($abs_extra);
1823                         my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1824                         if ($lnksrc > 1) {
1825                                 if ($devsrc == $devext && $inosrc == $inoext) {
1826                                         $extras{$extra} = "\e[32;1menabled\e[0m";
1827                                 } else {
1828                                         $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1829                                 }
1830                         } else {
1831                                 open my $extfd, "<", $abs_extra;
1832                                 open my $srcfd, "<", $abs_source;
1833                                 local $/ = undef;
1834                                 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1835                                         $extras{$extra} = "\e[32;1menabled\e[0m";
1836                                 } else {
1837                                         $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1838                                 }
1839                         }
1840                 } else {
1841                         $extras{$extra} = "\e[33;1mdisabled\e[0m";
1842                 }
1843         }
1844         # Now let's add dependency info
1845         for my $extra (keys(%extras)) {
1846                 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1847                 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1848                 my @deps = split / +/, getdependencies($abs_extra);
1849                 for my $dep (@deps) {
1850                         if (exists($extras{$dep})) {
1851                                 my $ref = \$extras{$dep}; # Take reference.
1852                                 if ($$ref !~ m/needed by/) {
1853                                         # First dependency found.
1854                                         if ($$ref =~ m/enabled/) {
1855                                                 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1856                                         } else {
1857                                                 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1858                                                 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1859                                         }
1860                                 } else {
1861                                         if ($$ref =~ m/enabled/) {
1862                                                 $$ref .= ", \e[32;1m$extra\e[0m";
1863                                         } else {
1864                                                 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1865                                         }
1866                                 }
1867                         }
1868                 }
1869         }
1870         for my $extra (sort {$a cmp $b} keys(%extras)) {
1871                 my $text = $extras{$extra};
1872                 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1873                         printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1874                 } else {
1875                         printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1876                 }
1877         }
1878         return keys(%extras) if wantarray; # Can be used by manage_extras.
1879 }
1880
1881 sub enable_extras (@) {
1882         my (@extras) = @_;
1883         for my $extra (@extras) {
1884                 my $extrapath = "src/modules/extra/$extra";
1885                 if (!-e $extrapath) {
1886                         print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1887                         next;
1888                 }
1889                 my $source = "src/modules/$extra";
1890                 if (-e $source) {
1891                         print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1892                         next;
1893                 }
1894                 # Get dependencies, and add them to be processed.
1895                 my @deps = split / +/, getdependencies($extrapath);
1896                 for my $dep (@deps) {
1897                         next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1898                         if (!-e "src/modules/$dep") {
1899                                 if (-e "src/modules/extra/$dep") {
1900                                         print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1901                                         push @extras, $dep;
1902                                 } else {
1903                                         print STDERR "\e[33;1mWARNING:\e[0m module \e[32;1m$extra\e[0m might be missing dependency \e[32;1m$dep\e[0m - YOU are responsible for satisfying it!\n";
1904                                 }
1905                         }
1906                 }
1907                 print "Enabling $extra ... \n";
1908                 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1909         }
1910 }
1911
1912 sub disable_extras (@)
1913 {
1914         opendir my $dd, "src/modules/extra/";
1915         my @files = readdir($dd);
1916         closedir $dd;
1917         my (@extras) = @_;
1918 EXTRA:  for my $extra (@extras) {
1919                 my $extrapath = "src/modules/extra/$extra";
1920                 my $source = "src/modules/$extra";
1921                 if (!-e $extrapath) {
1922                         print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1923                         next;
1924                 }
1925                 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1926                         print STDERR "Cannot disable \e[32;1m$extra\e[0m : Source is not a link or doesn't refer to the right file. Remove manually if this is in error.\n";
1927                         next;
1928                 }
1929                 # Check if anything needs this.
1930                 for my $file (@files) {
1931                         my @deps = split / +/, getdependencies("src/modules/extra/$file");
1932                         # File depends on this extra...
1933                         if (scalar(grep { $_ eq $extra } @deps) > 0) {
1934                                 # And is both enabled and not about to be disabled.
1935                                 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1936                                         print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1937                                         next EXTRA;
1938                                 }
1939                         }
1940                 }
1941                 # Now remove.
1942                 print "Disabling $extra ... \n";
1943                 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";
1944         }
1945 }