]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - configure
clean some trailing space and fix a year on copyright
[user/henk/code/inspircd.git] / configure
1 #!/usr/bin/perl
2 ###################################################
3 # InspIRCd Configuration Script
4 #
5 # Copyright 2002-2009 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 -export-dynamic";
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-2009 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 $SHARED -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 $SHARED -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                                 print FILEHANDLE "      \@../../make/run-cc.pl \$(CC) -pipe \$(FLAGS) $SHARED $mliflags -o $name.so $mobjs\n";
1463                                 print FILEHANDLE "\n$mfrules\n";
1464                                 closedir(MDIRHANDLE);
1465                                 $install_list = $install_list . "       install -m \$(INSTMODE) src/modules/$name.so \$(MODPATH)\n";
1466                         }
1467                 }
1468         }
1469         closedir(DIRHANDLE);
1470 }
1471
1472 sub read_module_directory {
1473         my ($dpath, $reldpath) = @_;
1474
1475         if (opendir(MDIRHANDLE, $dpath) == 0) {
1476                 return;
1477         }
1478
1479         foreach my $fname (sort readdir(MDIRHANDLE)) {
1480                 if ($fname =~ /\.cpp$/) {
1481                         my $cmflags = getcompilerflags("$dpath/$fname");
1482                         $mliflags = $mliflags . " " . getlinkerflags("$dpath/$fname");
1483                         my $deps = getdependencies("$dpath/$fname");
1484                         my $oname = $fname;
1485                         $oname =~ s/\.cpp$/.o/g;
1486                         $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";
1487                         $mfrules = $mfrules .  "        \@../../make/run-cc.pl \$(CC) -pipe -I../../include -I. \$(FLAGS) $cmflags $SHARED -o $reldpath/$oname -c $reldpath/$fname\n\n";
1488                         $mobjs = $mobjs . " $reldpath/$oname";
1489                         $mfcount++;
1490                 }
1491                 elsif ((-d "$dpath/$fname") && !($fname eq ".") && !($fname eq "..")) {
1492                         read_module_directory($dpath."/".$fname, $reldpath."/".$fname);
1493                 }
1494         }
1495 }
1496
1497 sub calcdeps($)
1498 {
1499         # Yes i know we could use gcc -M but it seems to ideneify a lot of 'deep'
1500         # dependencies which are not relevent in C++.
1501
1502         my $file = $_[0];
1503
1504         open (CPP, "<$file") or die("Can't open $file for reading!");
1505
1506         my %dupe = ();
1507         my $retlist = "";
1508
1509         foreach my $d (@ignoredeps)
1510         {
1511                 $dupe{$d} = 1;
1512         }
1513
1514         my $immutable = "";
1515         foreach my $dep (@immutabledeps)
1516         {
1517                 $immutable = $immutable . "../include/$dep ";
1518         }
1519         $immutable =~ s/ $//g;
1520
1521         while (defined(my $line = <CPP>))
1522         {
1523                 chomp($line);
1524                 if ($line =~ /#include "(.+\.h)"/)
1525                 {
1526                         if (!exists($dupe{$1}))
1527                         {
1528                                 $retlist = $retlist . "../include/$1 ";
1529                                 $dupe{$1} = 1;
1530                         }
1531                 }
1532         }
1533         close CPP;
1534         return length($immutable) ? $immutable . " " . $retlist : $retlist;
1535 }
1536
1537 sub write_dynamic_makefile
1538 {
1539         my $i = 0;
1540         my @cmdlist = ();
1541         my %existing_install_list = ();
1542         my %core_files_list = ();
1543
1544         opendir(DIRHANDLE, "src/commands");
1545         foreach my $name (sort readdir(DIRHANDLE))
1546         {
1547                 if ($name =~ /^cmd_(.+)\.cpp$/)
1548                 {
1549                         $cmdlist[$i++] = $1;
1550                         $install_list = $install_list . "       -install -m \$(INSTMODE) src/commands/cmd_" . $1 . ".so \$(LIBPATH)\n";
1551                         $uninstall_list = $uninstall_list . "   -rm \$(LIBPATH)/cmd_$1.so\n";
1552                 }
1553         }
1554         closedir(DIRHANDLE);
1555
1556         if (!$has_epoll)
1557         {
1558                 $config{USE_EPOLL} = 0;
1559         }
1560         if (!$has_kqueue)
1561         {
1562                 $config{USE_KQUEUE} = 0;
1563         }
1564         if (!$has_ports)
1565         {
1566                 $config{USE_PORTS} = 0;
1567         }
1568
1569         # formerly generated below this foreach, now it's not! magic.
1570         my $all_core = "";
1571
1572         foreach my $dir (("src","src/commands","src/modes","src/socketengines","src/modules"))
1573         {
1574                 print "Scanning \e[1;32m$dir\e[0m for core files ";
1575                 opendir(DIRHANDLE, $dir);
1576                 foreach my $name (sort readdir(DIRHANDLE))
1577                 {
1578                         if ($name =~ /\.cpp$/)
1579                         {
1580                                 open (CPP, "<$dir/$name") or die("Can't open $dir/$name to scan it! oh bugger");
1581                                 print ".";
1582                                 while (defined(my $line = <CPP>))
1583                                 {
1584                                         chomp($line);
1585                                         if ($line =~ /\/\* \$Core \*\//i)
1586                                         {
1587                                                 my $sname = $name;
1588                                                 $sname =~ s/\.cpp$/.o/;
1589
1590                                                 # append it to list to be built
1591                                                 $all_core = $all_core . $sname . " ";
1592                                                 $filelist{$name} = $sname;
1593
1594                                                 # mark it as a core file, so it won't get shared object cflags
1595                                                 if (!exists($core_files_list{$name}))
1596                                                 {
1597                                                         $core_files_list{$name} = 1;
1598                                                 }
1599                                         }
1600                                         elsif ($line =~ /\/\* \$ExtraDeps: (.*?) \*\//i)
1601                                         {
1602                                                 $specialdeps{$name} = $1;
1603                                         }
1604                                         elsif ($line =~ /\/\* \$ExtraObjects: (.*?) \*\//i)
1605                                         {
1606                                                 $extraobjects{$name} = $1;
1607                                         }
1608                                         elsif ($line =~ /\/\* \$ExtraBuild: (.*?) \*\//i)
1609                                         {
1610                                                 $extrabuildlines{$name} = $1;
1611                                         }
1612                                         elsif ($line =~ /\/\* \$ExtraSources: (.*?) \*\//i)
1613                                         {
1614                                                 $extrasources{$name} = $1;
1615                                                 }
1616                                         elsif ($line =~ /\/\* \$If: (\w+) \*\//i)
1617                                         {
1618                                                 if (defined $config{$1})
1619                                                 {
1620                                                         if (($config{$1} !~ /y/i) and ($config{$1} ne "1"))
1621                                                         {
1622                                                                 # Skip to 'endif'
1623                                                                 while (defined($line = <CPP>))
1624                                                                 {
1625                                                                         chomp($line);
1626                                                                         die ("\$If buildsystem instruction within another \$If in file $dir/$name") if ($line =~ /\/\* \$If: (\w+) \*\//i);
1627                                                                         last if ($line =~ /\/\* \$EndIf \*\//i);
1628                                                                 }
1629                                                         }
1630                                                 }
1631                                         }
1632                                         elsif ($line =~ /\/\* \$Install: (.*?) \*\//i)
1633                                         {
1634                                                 if (!exists($existing_install_list{$1}))
1635                                                 {
1636                                                         $existing_install_list{$1} = 1;
1637                                                         my $idir = (split(' ',$1))[1];
1638                                                         my $ifile = (split(' ',$1))[0];
1639                                                         $install_list = $install_list . "       -install -m \$(INSTMODE) $1\n";
1640                                                         $ifile =~ s/.*\///g;
1641                                                         $uninstall_list = $uninstall_list . "   -rm $idir/$ifile\n";
1642                                                 }
1643                                         }
1644                                         elsif ($line =~ /\/\* \$CopyInstall: (.*?) \*\//i)
1645                                         {
1646                                                 if (!exists($existing_install_list{$1}))
1647                                                 {
1648                                                         $existing_install_list{$1} = 1;
1649                                                         my $idir = (split(' ',$1))[1];
1650                                                         my $ifile = (split(' ',$1))[0];
1651                                                         $install_list = $install_list . "       -cp $1\n";
1652                                                         $ifile =~ s/.*\///g;
1653                                                         $uninstall_list = $uninstall_list . "   -rm $idir/$ifile\n";
1654                                                 }
1655                                         }
1656                                 }
1657                                 close CPP;
1658                         }
1659                 }
1660                 closedir(DIRHANDLE);
1661                 print " done!\n";
1662         }
1663
1664         # modes need to be compiled in too
1665         $all_core = $all_core . "modes/modeclasses.a";
1666
1667         my $freebsd4libs = (defined $config{CRAQ} ? $config{CRAQ} : "");
1668
1669         my $libraryext = "";
1670         my $binary_rule = "";
1671
1672         if ($config{IS_DARWIN} eq "YES")
1673         {
1674                 $libraryext = "dylib";
1675                 $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 "
1676         }
1677         else
1678         {
1679                 $libraryext = "so";
1680                 $binary_rule = "        \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) $freebsd4libs -rdynamic -L. inspircd.cpp -o inspircd \$(LDLIBS) ";
1681         }
1682
1683         open(FH,">src/Makefile") or die("Could not write src/Makefile");
1684         print FH <<EOM;
1685
1686 CC = im a cheezeball
1687 CXXFLAGS = -I../include \${FLAGS}
1688 CPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* //' | grep -v svn)
1689 RELCPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* /modes\\//' | grep -v svn)
1690
1691 EOM
1692
1693         my $buildstring = "";
1694         my $deps = "";
1695
1696         foreach my $cpp (sort keys %filelist)
1697         {
1698                 my $objs = $cpp;
1699                 my $rawcpp = $cpp;
1700                 $objs =~ s/\.cpp$/.o/;
1701                 if (exists($extraobjects{$cpp}))
1702                 {
1703                         $objs = $objs . " " . $extraobjects{$cpp};
1704                         $all_core = $all_core . " " . $extraobjects{$cpp};
1705                 }
1706                 if (exists($extrasources{$cpp}))
1707                 {
1708                         $rawcpp = $rawcpp . " " . $extrasources{$cpp};
1709                 }
1710
1711                 $deps = calcdeps("src/$cpp");
1712                 if (exists($extrasources{$cpp}))
1713                 {
1714                         foreach my $seperate (sort split(' ',$extrasources{$cpp}))
1715                         {
1716                                 my $d = calcdeps("src/$extrasources{$cpp}") . " ";
1717                                 if ($d ne "")
1718                                 {
1719                                         $deps = $deps . $d . " ";
1720                                 }
1721                         }
1722                 }
1723                 $buildstring = $buildstring . $objs . ": $cpp $deps ". (defined($specialdeps{$cpp}) ? $specialdeps{$cpp} : "") . "\n";
1724
1725                 if (exists($core_files_list{$cpp}))
1726                 {
1727                         # core files are statically linked into the binary and do not require $SHARED shared libs switches
1728                         $buildstring = $buildstring . " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) -c $rawcpp\n";
1729                 }
1730                 else
1731                 {
1732                         $buildstring = $buildstring . " \@../make/run-cc.pl \$(CC) -pipe -I../include \$(FLAGS) $SHARED -c $rawcpp\n";
1733                 }
1734
1735                 if (exists($extrabuildlines{$cpp}))
1736                 {
1737                         $buildstring = $buildstring . " " . $extrabuildlines{$cpp} . "\n";
1738                 }
1739         }
1740
1741         print FH "all: inspircd moo\n\n\n";
1742
1743         $deps = calcdeps("src/inspircd.cpp");
1744         print FH "inspircd: inspircd.cpp $deps $all_core\n";
1745         print FH "$binary_rule $all_core\n\n";
1746
1747         print FH $buildstring;
1748         print FH "moo:\n        \@\${MAKE} -C \"commands\" DIRNAME=\"src/commands\" CC=\"\$(CC)\" \$(MAKEARGS)\n\n";
1749
1750         # close main makefile
1751         close(FH);
1752
1753         my $cmdobjs = "";
1754         # generate a list of .so
1755         foreach my $cmd (@cmdlist) {
1756                 $cmdobjs = $cmdobjs . "cmd_$cmd.so ";
1757         }
1758
1759         # and now reopen the commands makefile
1760         open(FH,">src/commands/Makefile") or die("Could not write src/commands/Makefile");
1761         print FH <<ITEM;
1762 CC = i am cornholio
1763 CXXFLAGS = -I../../include \${FLAGS}
1764
1765 all: $cmdobjs
1766
1767
1768 ITEM
1769
1770         # now print the command file detail
1771         foreach my $cmd (@cmdlist) {
1772                 print FH <<ITEM;
1773 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
1774         \@../../make/run-cc.pl \$(CC) -pipe -I../../include \$(FLAGS) $SHARED -o cmd_$cmd.so cmd_$cmd.cpp
1775
1776 ITEM
1777         }
1778 }
1779
1780 # Routine to list out the extra/ modules that have been enabled.
1781 # Note: when getting any filenames out and comparing, it's important to lc it if the
1782 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1783 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1784 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1785 sub list_extras () {
1786         use File::Spec;
1787         # @_ not used
1788         my $srcdir = File::Spec->catdir("src", "modules");
1789         my $abs_srcdir = File::Spec->rel2abs($srcdir);
1790         local $_;
1791         my $dd;
1792         opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1793         my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1794         closedir $dd;
1795         undef $dd;
1796         opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1797         my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1798         closedir $dd;
1799         undef $dd;
1800         my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1801         my %extras = ();
1802 EXTRA:  for my $extra (@extras) {
1803                 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1804                 next if ($extra eq '.svn');
1805                 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1806                 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1807                 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1808                 if (-l $abs_source) {
1809                         # Symlink, is it in the right place?
1810                         my $targ = readlink($abs_source);
1811                         my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1812                         if ($abs_targ eq $abs_extra) {
1813                                 $extras{$extra} = "\e[32;1menabled\e[0m";
1814                         } else {
1815                                 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1816                         }
1817                 } elsif (-e $abs_source) {
1818                         my ($devext, $inoext) = stat($abs_extra);
1819                         my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1820                         if ($lnksrc > 1) {
1821                                 if ($devsrc == $devext && $inosrc == $inoext) {
1822                                         $extras{$extra} = "\e[32;1menabled\e[0m";
1823                                 } else {
1824                                         $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1825                                 }
1826                         } else {
1827                                 open my $extfd, "<", $abs_extra;
1828                                 open my $srcfd, "<", $abs_source;
1829                                 local $/ = undef;
1830                                 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1831                                         $extras{$extra} = "\e[32;1menabled\e[0m";
1832                                 } else {
1833                                         $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1834                                 }
1835                         }
1836                 } else {
1837                         $extras{$extra} = "\e[33;1mdisabled\e[0m";
1838                 }
1839         }
1840         # Now let's add dependency info
1841         for my $extra (keys(%extras)) {
1842                 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1843                 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1844                 my @deps = split / +/, getdependencies($abs_extra);
1845                 for my $dep (@deps) {
1846                         if (exists($extras{$dep})) {
1847                                 my $ref = \$extras{$dep}; # Take reference.
1848                                 if ($$ref !~ m/needed by/) {
1849                                         # First dependency found.
1850                                         if ($$ref =~ m/enabled/) {
1851                                                 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1852                                         } else {
1853                                                 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1854                                                 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1855                                         }
1856                                 } else {
1857                                         if ($$ref =~ m/enabled/) {
1858                                                 $$ref .= ", \e[32;1m$extra\e[0m";
1859                                         } else {
1860                                                 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1861                                         }
1862                                 }
1863                         }
1864                 }
1865         }
1866         for my $extra (sort {$a cmp $b} keys(%extras)) {
1867                 my $text = $extras{$extra};
1868                 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1869                         printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1870                 } else {
1871                         printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1872                 }
1873         }
1874         return keys(%extras) if wantarray; # Can be used by manage_extras.
1875 }
1876
1877 sub enable_extras (@) {
1878         my (@extras) = @_;
1879         for my $extra (@extras) {
1880                 my $extrapath = "src/modules/extra/$extra";
1881                 if (!-e $extrapath) {
1882                         print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1883                         next;
1884                 }
1885                 my $source = "src/modules/$extra";
1886                 if (-e $source) {
1887                         print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1888                         next;
1889                 }
1890                 # Get dependencies, and add them to be processed.
1891                 my @deps = split / +/, getdependencies($extrapath);
1892                 for my $dep (@deps) {
1893                         next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1894                         if (!-e "src/modules/$dep") {
1895                                 if (-e "src/modules/extra/$dep") {
1896                                         print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1897                                         push @extras, $dep;
1898                                 } else {
1899                                         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";
1900                                 }
1901                         }
1902                 }
1903                 print "Enabling $extra ... \n";
1904                 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1905         }
1906 }
1907
1908 sub disable_extras (@)
1909 {
1910         opendir my $dd, "src/modules/extra/";
1911         my @files = readdir($dd);
1912         closedir $dd;
1913         my (@extras) = @_;
1914 EXTRA:  for my $extra (@extras) {
1915                 my $extrapath = "src/modules/extra/$extra";
1916                 my $source = "src/modules/$extra";
1917                 if (!-e $extrapath) {
1918                         print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1919                         next;
1920                 }
1921                 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1922                         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";
1923                         next;
1924                 }
1925                 # Check if anything needs this.
1926                 for my $file (@files) {
1927                         my @deps = split / +/, getdependencies("src/modules/extra/$file");
1928                         # File depends on this extra...
1929                         if (scalar(grep { $_ eq $extra } @deps) > 0) {
1930                                 # And is both enabled and not about to be disabled.
1931                                 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1932                                         print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1933                                         next EXTRA;
1934                                 }
1935                         }
1936                 }
1937                 # Now remove.
1938                 print "Disabling $extra ... \n";
1939                 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";
1940         }
1941 }