]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - configure
adc05f865d04b42b2b95677de48867c6d432163b
[user/henk/code/inspircd.git] / configure
1 #!/usr/bin/perl
2 ###################################################
3 # InspIRCd Configuration Script
4 #
5 # Copyright 2002-2007 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 require 5.8.0;
16 use Socket;
17 use Cwd;
18 use Getopt::Long;
19
20 # Utility functions for our buildsystem
21 use make::utilities;
22 use make::configure;
23 use make::gnutlscert;
24 use make::opensslcert;
25
26 ###############################################################################################
27 #
28 #                                   EDITABLE VARIABLES
29 #
30 ###############################################################################################
31
32 # This is a list of all files in the core. Each cpp file is mapped to a shared object file,
33 # whos file extension is omitted (these can vary from system to system).
34
35 my %filelist = (
36         "channels.cpp"      =>      "libIRCDchannels",
37         "mode.cpp"          =>      "libIRCDmode",
38         "xline.cpp"         =>      "libIRCDxline",
39         "inspstring.cpp"    =>      "libIRCDstring",
40         "dns.cpp"           =>      "libIRCDasyncdns",
41         "base.cpp"          =>      "libIRCDbase",
42         "configreader.cpp"  =>      "libIRCDconfigreader",
43         "inspsocket.cpp"    =>      "libIRCDinspsocket",
44         "commands.cpp"      =>      "libIRCDcommands",
45         "dynamic.cpp"       =>      "libIRCDdynamic",
46         "users.cpp"         =>      "libIRCDusers",
47         "modules.cpp"       =>      "libIRCDmodules",
48         "wildcard.cpp"      =>      "libIRCDwildcard",
49         "helperfuncs.cpp"   =>      "libIRCDhelper",
50         "hashcomp.cpp"      =>      "libIRCDhash",
51         "socket.cpp"        =>      "libIRCDsocket",
52         "socketengine.cpp"  =>      "libIRCDsocketengine",
53         "userprocess.cpp"   =>      "libIRCDuserprocess",
54         "cull_list.cpp"     =>      "libIRCDcull_list",
55         "command_parse.cpp" =>      "libIRCDcommand_parse",
56         "timer.cpp"         =>      "libIRCDtimer",
57         "snomasks.cpp"      =>      "libIRCDsnomasks",
58         "server.cpp"        =>      "libIRCDserver",
59         "filelogger.cpp"    =>      "libIRCDfilelogger",
60         "user_resolver.cpp" =>      "libIRCDuserresolver",
61 );
62
63 # If you wish for a file to have special dependencies in the makefile, add an entry here.
64
65 my %specialdeps = (
66         "mode.cpp"      =>      "\$(RELCPPFILES)",
67 );
68
69 # If you wish for a file to have extra make lines (in between the compile and link steps)
70 # then insert them here.
71         
72 my %extrabuildlines = (
73         "mode.cpp"      =>      "\${MAKE} -C \"modes\" DIRNAME=\"src/modes\" CC=\"\$(CC)\" \$(MAKEARGS) CPPFILES=\"\$(CPPFILES)\"",
74 );
75
76 # If you wish for a file to be linked against extra objects or arctives, insert them here.
77
78 my %extraobjects = (
79         "mode.cpp"      =>      "modes/modeclasses.a"
80 );
81
82 # If you wish to compile extra cpp sources into an object, define them here.
83 # NOTE: Certain cpp files such as the socket engines have a value auto calculated
84 # for this table so that their derived class is built.
85
86 my %extrasources = (
87 );
88
89 # If you wish to ignore a dependency throughout the entire core, add it here.
90
91 my @ignoredeps = (
92         "inspircd_win32wrapper.h",      # windows has its own configure program
93 );
94
95 # If you wish for all files in the entire core to have a given dependency, insert it here.
96 # You should keep this to an absolute minimum to avoid rebuilds that are not neccessary.
97
98 my @immutabledeps = (
99         "inspircd_config.h",            # auto re-generated by configure
100         "inspircd.h",
101 );
102
103
104 ###############################################################################################
105 #
106 #                                 NON-EDITABLE VARIABLES
107 #
108 ###############################################################################################
109
110
111 GetOptions (
112         'enable-gnutls' => \$opt_use_gnutls,
113         'rebuild' => \$opt_rebuild,
114         'enable-openssl' => \$opt_use_openssl,
115         'disable-interactive' => \$opt_nointeractive,
116         'with-nick-length=i' => \$opt_nick_length,
117         'with-channel-length=i' => \$opt_chan_length,
118         'with-max-clients=i' => \$opt_maxclients,
119         'enable-ports' => \$opt_ports,
120         'enable-epoll' => \$opt_epoll,
121         'enable-kqueue' => \$opt_kqueue,
122         'disable-ports' => \$opt_noports,
123         'disable-epoll' => \$opt_noepoll,
124         'disable-kqueue' => \$opt_nokqueue,
125         'enable-ipv6' => \$opt_ipv6,
126         'enable-remote-ipv6' => \$opt_ipv6links,
127         'disable-remote-ipv6' => \$opt_noipv6links,
128         'with-cc=s' => \$opt_cc,
129         'with-ident-length=i' => \$opt_ident,
130         'with-quit-length=i' => \$opt_quit,
131         'with-topic-length=i' => \$opt_topic,
132         'with-maxbuf=i' => \$opt_maxbuf,
133         'with-kick-length=i' => \$opt_kick,
134         'with-gecos-length=i' => \$opt_gecos,
135         'with-away-length=i' => \$opt_away,
136         'with-max-modes=i' => \$opt_modes,
137         'prefix=s' => \$opt_base_dir,
138         'config-dir=s' => \$opt_config_dir,
139         'module-dir=s' => \$opt_module_dir,
140         'binary-dir=s' => \$opt_binary_dir,
141         'library-dir=s' => \$opt_library_dir,
142         'disable-debuginfo' => sub { $opt_disable_debug = 1 },
143         'help'  => sub { showhelp(); },
144         'modupdate' => sub { modupdate(); },
145         'update' => sub { update(); },
146         'svnupdate' => sub { svnupdate(); },
147         'clean' => sub { clean(); },
148 );
149
150 my $non_interactive = (
151         (defined $opt_library_dir) ||
152         (defined $opt_base_dir) ||
153         (defined $opt_config_dir) ||
154         (defined $opt_module_dir) ||
155         (defined $opt_base_dir) ||
156         (defined $opt_binary_dir) ||
157         (defined $opt_nointeractive) ||
158         (defined $opt_away) ||
159         (defined $opt_gecos) ||
160         (defined $opt_kick) ||
161         (defined $opt_maxclients) ||
162         (defined $opt_modes) ||
163         (defined $opt_topic) ||
164         (defined $opt_quit) ||
165         (defined $opt_ident) ||
166         (defined $opt_cc) ||
167         (defined $opt_ipv6) ||
168         (defined $opt_ipv6links) ||
169         (defined $opt_noipv6links) ||
170         (defined $opt_kqueue) ||
171         (defined $opt_epoll) ||
172         (defined $opt_ports) ||
173         (defined $opt_maxchans) ||
174         (defined $opt_opermaxchans) ||
175         (defined $opt_chan_length) ||
176         (defined $opt_nick_length) ||
177         (defined $opt_use_openssl) ||
178         (defined $opt_nokqueue) ||
179         (defined $opt_noepoll) ||
180         (defined $opt_noports) ||
181         (defined $opt_maxbuf) ||
182         (defined $opt_use_gnutls)
183 );
184 my $interactive = !$non_interactive;
185
186
187 chomp($topdir = getcwd());
188 $this = resolve_directory($topdir);                                             # PWD, Regardless.
189 @modlist = ();                                                                  # Declare for Module List..
190 %config = ();                                                                   # Initiate Configuration Hash..
191 $config{ME}              = resolve_directory($topdir);                          # Present Working Directory
192
193 $config{BASE_DIR}          = $config{ME};
194
195 if (defined $opt_base_dir)
196 {
197         $config{BASE_DIR} = $opt_base_dir;
198 }
199
200 $config{CONFIG_DIR}      = resolve_directory($config{BASE_DIR}."/conf");        # Configuration Directory
201 $config{MODULE_DIR}      = resolve_directory($config{BASE_DIR}."/modules");     # Modules Directory
202 $config{BINARY_DIR}      = resolve_directory($config{BASE_DIR}."/bin");         # Binary Directory
203 $config{LIBRARY_DIR}    = resolve_directory($config{BASE_DIR}."/lib");          # Library Directory
204
205 if (defined $opt_config_dir)
206 {
207         $config{CONFIG_DIR} = $opt_config_dir;
208 }
209 if (defined $opt_module_dir)
210 {
211         $config{MODULE_DIR} = $opt_module_dir;
212 }
213 if (defined $opt_binary_dir)
214 {
215         $config{BINARY_DIR} = $opt_binary_dir;
216 }
217 if (defined $opt_library_dir)
218 {
219         $config{LIBRARY_DIR} = $opt_library_dir;
220 }
221 chomp($config{HAS_GNUTLS}   = `libgnutls-config --version 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
222 chomp($config{HAS_OPENSSL}  = `pkg-config --modversion openssl 2>/dev/null`);           # Openssl version
223 chomp($gnutls_ver = $config{HAS_GNUTLS});
224 chomp($openssl_ver = $config{HAS_OPENSSL});
225 $config{USE_GNUTLS}         = "n";
226 if (defined $opt_use_gnutls)
227 {
228         $config{USE_GNUTLS} = "y";                                      # Use gnutls.
229 }
230 $config{USE_OPENSSL}    = "n";                                          # Use openssl.
231 if (defined $opt_use_openssl)
232 {
233         $config{USE_OPENSSL} = "y";
234 }
235
236 # no, let's not change these.
237 $config{OPTIMITEMP}      = "0";                                         # Default Optimisation Value
238 if (!defined $opt_disable_debug)
239 {
240         $config{OPTIMISATI}      = "-g1";                               # Optimisation Flag
241 }
242 else
243 {
244         $config{OPTIMISATI}      = "-O2";                               # DEBUGGING OFF!
245 }
246
247 $config{NICK_LENGT}      = "31";                                        # Default Nick Length
248 if (defined $opt_nick_length)
249 {
250         $config{NICK_LENGT} = $opt_nick_length;
251 }
252 $config{CHAN_LENGT}      = "64";                                        # Default Channel Name Length
253 if (defined $opt_chan_length)
254 {
255         $config{CHAN_LENGT} = $opt_chan_length;
256 }
257 $config{MAXI_MODES}      = "20";                                        # Default Max. Number of Modes set at once.
258 if (defined $opt_modes)
259 {
260         $config{MAXI_MODES} = $opt_modes;
261 }
262 $config{HAS_STRLCPY}    = "false";                                      # strlcpy Check.
263 $config{HAS_STDINT}      = "false";                                     # stdint.h check
264 $config{USE_KQUEUE}      = "y";                                         # kqueue enabled
265 if (defined $opt_kqueue)
266 {
267         $config{USE_KQUEUE} = "y";
268 }
269 if (defined $opt_nokqueue)
270 {
271         $config{USE_KQUEUE} = "n";
272 }
273 $config{USE_EPOLL}        = "y";                                        # epoll enabled
274 if (defined $opt_epoll)
275 {
276         $config{USE_EPOLL} = "y";
277 }
278 if (defined $opt_noepoll)
279 {
280         $config{USE_EPOLL} = "n";
281 }
282 $config{USE_PORTS}        = "y";                                        # epoll enabled
283 if (defined $opt_ports)
284 {
285         $config{USE_PORTS} = "y";
286 }
287 if (defined $opt_noports)
288 {
289         $config{USE_PORTS} = "n";
290 }
291 $config{IPV6}          = "n";                                           # IPv6 support (experimental)
292 if (defined $opt_ipv6)
293 {
294         $config{IPV6} = "y";
295 }
296 $config{SUPPORT_IP6LINKS}   = "y";                                      # IPv4 supporting IPv6 links (experimental)
297 if (defined $opt_ipv6links)
298 {
299         $config{SUPPORT_IP6LINKS} = "y";
300 }
301 if (defined $opt_noipv6links)
302 {
303         $config{SUPPORT_IP6LINKS} = "n";
304 }
305 chomp($config{MAX_CLIENT_T} = `sh -c \"ulimit -n\"`);                   # FD Limit
306 chomp($config{MAX_DESCRIPTORS} = `sh -c \"ulimit -n\"`);                # Hard FD Limit
307 chomp($config{GCCVER}       = `g++ -dumpversion | cut -c 1`);           # Major GCC Version
308 $config{_SOMAXCONN} = SOMAXCONN;                                        # Max connections in accept queue
309 $config{OSNAME}             = $^O;                                      # Operating System Name
310 $config{IS_DARWIN}        = "NO";                                       # Is OSX?
311 $config{STARTSCRIPT}      = "inspircd";                 # start script?
312 $config{DESTINATION}      = "BASE";                             # Is target path.
313 $config{EXTRA_DIR}        = "";                                         # Is empty.
314 if ($config{OSNAME} =~ /darwin/i)
315 {
316         $config{IS_DARWIN} = "YES";
317         $config{STARTSCRIPT}      = "org.inspircd.plist";               # start script for OSX.
318         $config{DESTINATION}      = "LAUNCHDPATH";                              # Is OSX target.
319         $config{EXTRA_DIR}          = " launchd_dir";                           # Is OSX specific path.
320 }
321 $config{CC}                 = "g++";                                            # C++ compiler
322 if (defined $opt_cc)
323 {
324         $config{CC} = $opt_cc;
325 }
326 $exec = $config{CC} . " -dumpversion | cut -c 1";
327 chomp($config{GCCVER}           = `$exec`);                             # Major GCC Version
328 $config{MAKEORDER}              = "ircd mods";                          # build order
329 $config{MAX_IDENT}              = "12";                                 # max ident size
330 $config{MAX_QUIT}               = "255";                                # max quit message size
331 $config{MAX_TOPIC}              = "307";                                # max topic size
332 $config{MAX_KICK}               = "255";                                # max kick message size
333 $config{MAX_GECOS}              = "128";                                # max GECOS size
334 $config{MAX_AWAY}               = "200";                                # max AWAY size
335 $config{MAXBUF}                 = "512";                                # Max buffer size
336 if (defined $opt_ident)
337 {
338         $config{MAX_IDENT} = $opt_ident;
339 }
340 if (defined $opt_quit)
341 {
342         $config{MAX_QUIT} = $opt_quit;
343 }
344 if (defined $opt_topic)
345 {
346         $config{MAX_TOPIC} = $opt_topic;
347 }
348 if (defined $opt_kick)
349 {
350         $config{MAX_KICK} = $opt_kick;
351 }
352 if (defined $opt_gecos)
353 {
354         $config{MAX_GECOS} = $opt_gecos;
355 }
356 if (defined $opt_away)
357 {
358         $config{MAX_AWAY} = $opt_away;
359 }
360
361 $config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/;
362 $config{HAS_OPENSSL} = $1;
363
364 if ($config{GCCVER} eq "") {
365         print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
366         exit;
367 }
368
369 if (!$config{MAX_CLIENT_T}) { 
370         $config{MAX_CLIENT_T} = 1024;                            # Set a reasonable 'Default'
371         $fd_scan_fail = "true";                                # Used Later
372 }
373
374 # Get and Set some important vars..
375 getmodules();
376
377 sub clean
378 {
379         system("rm -rf .config.cache");
380 }
381
382 sub update
383 {
384         eval {
385                 chomp($topdir = getcwd());
386                 $this = resolve_directory($topdir);                                          # PWD, Regardless.
387                 getmodules();
388                 # Does the cache file exist?
389                 if (!getcache()) {
390                         # No, No it doesn't.. *BASH*
391                         print "You have not run ./configure before. Please do this before trying to run the update script.\n";
392                         exit 0;
393                 } else {
394                         # We've Loaded the cache file and all our variables..
395                         print "Updating Files..\n";
396                         getosflags();
397                         if ($opt_disable_debug == 1)
398                         {
399                                 print "Disabling debug information (-g).\n";
400                                 $config{OPTIMISATI} = "";
401                                 getosflags();
402                         }
403                         $has_epoll = $config{HAS_EPOLL};
404                         $has_ports = $config{HAS_PORTS};
405                         $has_kqueue = $config{HAS_KQUEUE};
406                         writefiles(1);
407                         makecache();
408                         print "Complete.\n";
409                         exit;
410                 }
411         };
412         if ($@)
413         {
414                 print "Configure update failed: $@\n";
415         }
416         exit;
417 }
418
419 sub modupdate
420 {
421         eval {
422                 chomp($topdir = getcwd());
423                 $this = resolve_directory($topdir);                                          # PWD, Regardless.
424                 getmodules();
425                 # Does the cache file exist?
426                 if (!getcache()) {
427                         # No, No it doesn't.. *BASH*
428                         print "You have not run ./configure before. Please do this before trying to run the update script.\n";
429                         exit 0;
430                 } else {
431                         # We've Loaded the cache file and all our variables..
432                         print "Updating Files..\n";
433                         getosflags();
434                         $has_epoll = $config{HAS_EPOLL};
435                         $has_ports = $config{HAS_PORTS};
436                         $has_kqueue = $config{HAS_KQUEUE};
437                         writefiles(0);
438                         makecache();
439                         print "Complete.\n";
440                         exit;
441                 }
442         };
443         if ($@)
444         {
445                 print "Module update failed: $@\n";
446         }
447         exit;
448 }
449
450
451
452 sub svnupdate
453 {
454         my $fail = 0;
455         open(FH,"<.svn/entries") or $fail = 1;
456         if ($fail) {
457                 print "This is not an SVN copy of InspIRCd.\n";
458                 exit;
459         }
460         else
461         {
462                 close(FH);
463         }
464         system("svn update");
465         system("perl configure -update");
466         if (defined $opt_rebuild) {
467                 system("make install");
468         }
469         exit;
470 }
471
472 print "Running non-interactive configure...\n" unless $interactive;
473 print "Checking for cache from previous configure... ";
474 print ((!getcache()) ? "not found\n" : "found\n");
475 print "Checking operating system version... ";
476 print getosflags() . "\n";
477
478 if (defined $opt_maxclients)
479 {
480         $config{MAX_CLIENT} = $opt_maxclients;
481 }
482
483 if (!$config{MAX_CLIENT}) { 
484         # If the cache hasn't set the max clients, copy the variable of MAX_CLIENT_T, this
485         # allows us to keep _T for testing purposes. (ie. "Are you sure you want to go
486         # higher than the found value" :))
487         $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
488 }
489
490 printf "Checking if stdint.h exists... ";
491 $config{HAS_STDINT} = "true";
492 my $fail = 0;
493 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
494 if ($config{HAS_STDINT} eq "true") {
495         close(STDINT);
496 }
497 print "yes\n" if $config{HAS_STDINT} eq "true";
498 print "no\n" if $config{HAS_STDINT} eq "false";
499
500
501 printf "Checking if strlcpy exists... ";
502 # Perform the strlcpy() test..
503 $config{HAS_STRLCPY} = "false";
504 my $fail = 0;
505 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
506 if (!$fail) {
507         while (chomp($line = <STRLCPY>)) {
508                 # try and find the delcaration of:
509                 # size_t strlcpy(...)
510                 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
511                         $config{HAS_STRLCPY} = "true";
512                 }
513         }
514         close(STRLCPY);
515 }
516 print "yes\n" if $config{HAS_STRLCPY} eq "true";
517 print "no\n" if $config{HAS_STRLCPY} eq "false";
518
519
520 printf "Checking if kqueue exists... ";
521 $has_kqueue = 0;
522 $fail = 0;
523 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
524 if (!$fail) {
525         while (chomp($line = <KQUEUE>)) {
526                 # try and find the delcaration of:
527                 # int kqueue(void);
528                 if ($line =~ /int(\0x9|\s)+kqueue/) {
529                         $has_kqueue = 1;
530                 }
531         }
532         close(KQUEUE);
533 }
534 print "yes\n" if $has_kqueue == 1;
535 print "no\n" if $has_kqueue == 0;
536
537 printf "Checking if epoll exists... ";
538 $has_epoll = 0;
539 $fail = 0;
540 open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
541 if (!$fail) {
542         $has_epoll = 1;
543         close(EPOLL);
544 }
545 if ($has_epoll) {
546         my $kernel = `uname -r`;
547         chomp($kernel);
548         if (($kernel =~ /^2\.0\./) || ($kernel =~ /^2\.2\./) || ($kernel =~ /^2\.4\./)) {
549                 $has_epoll = 0;
550         }
551         else
552         {
553                 # Suggestion from nenolod, weed out odd systems which have glibc built
554                 # against 2.4 kernels (ick)
555                 my $kernel_arch = `uname -p`;
556                 chomp($kernel_arch);
557                 $libcv = 0.0;
558                 $kernelv = 0.0;
559                 if ($kernel_arch =~ /x86_64/) {
560                         open (FH,"/lib64/libc.so.6|") or $has_epoll = 0;
561                 }
562                 else {
563                         open (FH,"/lib/libc.so.6|") or $has_epoll = 0;
564                 }
565                 if ($has_epoll)
566                 {
567                         while (chomp($line = <FH>))
568                         {
569                                 if ($line =~ /GNU C Library .* version (.*?) /)
570                                 {
571                                         $libcv = $1;
572                                         $libcv =~  /(\d+\.\d+)/;
573                                         $libcv = $1;
574                                 }
575                                 elsif ($line =~ /Compiled on a Linux (.*?\..*?)\.* system/)
576                                 {
577                                         $kernelv = $1;
578                                         # Fix for some retarded libc builds, strip off >> and << etc.
579                                         $kernelv =~ /(\d+\.\d+)/;
580                                         $kernelv = $1;
581                                 }
582                         }
583                         close FH;
584                         if ($libcv < 2.3)
585                         {
586                                 $has_epoll = 0;
587                                 printf "libc too old: $libcv... ";
588                         }
589                         if ($kernelv < 2.6)
590                         {
591                                 $has_epoll = 0;
592                                 printf "libc built against older kernel $kernelv... ";
593                         }
594                 }
595         }
596 }
597 print "yes\n" if $has_epoll == 1;
598 print "no\n" if $has_epoll == 0;
599
600 printf "Checking if Solaris I/O completion ports are available... ";
601 $has_ports = 0;
602 my $system = `uname -s`;
603 chomp ($system);
604 $has_ports = 1 if ($system eq "SunOS");
605
606 if ($has_ports) {
607         my $kernel = `uname -r`;
608         chomp($kernel);
609         if (($kernel !~ /^5\.1./)) {
610                 $has_ports = 0;
611         }
612 }
613 print "yes\n" if $has_ports == 1;
614 print "no\n" if $has_ports == 0;
615
616 $config{HAS_EPOLL} = $has_epoll;
617 $config{HAS_KQUEUE} = $has_kqueue; 
618
619 printf "Checking for libgnutls... ";
620 if (($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS} >= 1.2) || ($config{HAS_GNUTLS} eq "y"))) {
621         print "yes\n";
622         $config{HAS_GNUTLS} = "y";
623 } else {
624         print "no\n";
625         $config{HAS_GNUTLS} = "n";
626 }
627
628 printf "Checking for openssl... ";
629 if (($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL} >= 0.8) || ($config{HAS_OPENSSL} eq "y"))) {
630         print "yes\n";
631         $config{HAS_OPENSSL} = "y";
632 } else {
633         print "no\n";
634         $config{HAS_OPENSSL} = "n";
635 }
636
637 printf "Checking if you are running an ancient, unsupported OS... ";
638 if ($config{OSNAME} =~ /FreeBSD/i)
639 {
640         $version = `uname -r`;
641         if ($version =~ /^4\./)
642         {
643                 $foundit = `ls -l /usr/local/lib/libgnugetopt* | wc -l`;
644                 if ($foundit > 0)
645                 {
646                         # ICKY ICKY ICK, FREEBSD 4.x! GET AN UPGRADE!
647                         $config{CRAQ} = "-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1";
648                         print "yes\n";
649                 }
650                 else
651                 {
652                         print "\n\nERROR: You require libgnugetopt (from ports or packages) to build InspIRCd on FreeBSD 4.11.\n";
653                 }
654         }
655         else
656         {
657                 $config{CRAQ} = " ";
658                 print "no ($version)\n";
659         }
660 }
661 else
662 {
663         $config{CRAQ} = " ";
664         print "no ($config{OSNAME})\n";
665 }
666
667 ################################################################################
668 #                         BEGIN INTERACTIVE PART                              #
669 ################################################################################
670
671 # Clear the Screen..
672 if ($interactive)
673 {
674         system("clear");
675         $wholeos = $^O;
676
677         my $rev = getrevision();
678         # Display Introduction Message..
679         print "
680 Welcome to the \033[1mInspIRCd\033[0m Configuration program! (\033[1minteractive mode\033[0m)
681 \033[1mPackage maintainers: Type ./configure --help for non-interactive help\033[0m
682
683 *** If you are unsure of any of these values, leave it blank for    ***
684 *** standard settings that will work, and your server will run      ***
685 *** using them. Please consult your IRC network admin if in doubt.  ***
686
687 Press \033[1m<RETURN>\033[0m to accept the default for any option, or enter
688 a new value. Please note: You will \033[1mHAVE\033[0m to read the docs
689 dir, otherwise you won't have a config file!
690
691 Your operating system is: \033[1;32m$config{OSNAME}\033[0m ($wholeos)
692 Maximum file descriptors: \033[1;32m$config{MAX_CLIENT_T}\033[0m
693 Your InspIRCd revision ID is \033[1;32mr$rev\033[0m";
694         if ($rev eq "r0") {
695                 print " (Non-SVN build)";
696         }
697         print ".\n\n";
698
699         $config{CHANGE_COMPILER} = "n";
700         print "I have detected the following compiler: \033[1;32m$config{CC}\033[0m (version \033[1;32m$config{GCCVER}.x\033[0m)\n";
701
702         while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
703                 print "\033[1;32mIMPORTANT!\033[0m A GCC 2.x compiler has been detected, and
704 should NOT be used. You should probably specify a newer compiler.\n\n";
705                 yesno(CHANGE_COMPILER,"Do you want to change the compiler?");
706                 if ($config{CHANGE_COMPILER} =~ /y/i) {
707                         print "What command do you want to use to invoke your compiler?\n";
708                         print "[\033[1;32m$config{CC}\033[0m] -> ";
709                         chomp($config{CC} = <STDIN>);
710                         if ($config{CC} eq "") {
711                                 $config{CC} = "g++";
712                         }
713                         chomp($foo = `$config{CC} -dumpversion | cut -c 1`);
714                         if ($foo ne "") {
715                                 chomp($config{GCCVER}       = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
716                                 print "Queried compiler: \033[1;32m$config{CC}\033[0m (version \033[1;32m$config{GCCVER}.x\033[0m)\n";
717                                 if ($config{GCCVER} < 3) {
718                                         print "\033[1;32mGCC 2.x WILL NOT WORK!\033[0m. Let's try that again, shall we?\n";
719                                 }
720                         }
721                         else {
722                                 print "\033[1;32mWARNING!\033[0m Could not execute the compiler you specified. You may want to try again.\n";
723                         }
724                 }
725         }
726
727         print "\n";
728
729         # Directory Settings..
730         my $tmpbase = $config{BASE_DIR};
731         dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
732         if ($tmpbase ne $config{BASE_DIR}) {
733                 $config{CONFIG_DIR}      = resolve_directory($config{BASE_DIR}."/conf");           # Configuration Dir
734                 $config{MODULE_DIR}      = resolve_directory($config{BASE_DIR}."/modules");     # Modules Directory
735                 $config{BINARY_DIR}      = resolve_directory($config{BASE_DIR}."/bin");     # Binary Directory
736                 $config{LIBRARY_DIR}    = resolve_directory($config{BASE_DIR}."/lib");      # Library Directory
737         }
738
739         dir_check("are the configuration files", "CONFIG_DIR");
740         dir_check("are the modules to be compiled to", "MODULE_DIR");
741         dir_check("is the IRCd binary to be placed", "BINARY_DIR");
742         dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
743
744         if ($has_kqueue) {
745                 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?");
746                 print "\n";
747         }
748         if ($has_epoll) {
749                 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?");
750                 print "\n";
751         }
752         if ($has_ports) {
753                 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?");
754                 print "\n";
755         }
756         $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y") || ($config{USE_PORTS} eq "y"));
757         if (!$chose_hiperf) {
758                 print "No high-performance socket engines are available, or you chose\n";
759                 print "not to enable one. Defaulting to select() engine.\n\n";
760         }
761
762         yesno(IPV6,"Would you like to build InspIRCd with IPv6 support?");
763         print "\n";
764
765         if ($config{IPV6} eq "y") {
766                 print "You have chosen to build an \033[1;32mIPV6-enabled\033[0m server.\nTo accept IPV4 users, you can still use IPV4 addresses\nin your port bindings..\n\n";
767                 $config{SUPPORT_IP6LINKS} = "y";
768         } else {
769                 yesno(SUPPORT_IP6LINKS,"You have chosen to build an \033[1;32mIPV4-only\033[0m server.\nWould you like to enable support for linking to IPV6-enabled\nInspIRCd servers?\nIf you are using a recent operating\nsystem and are unsure, answer yes.\nIf you answer 'no' here, your InspIRCd server will be unable\nto parse IPV6 addresses (e.g. for CIDR bans)");
770                 print "\n";
771         }
772
773         if (($config{HAS_GNUTLS} eq "y") && ($config{HAS_OPENSSL} eq "y")) {
774                 print "I have detected both \033[1;32mGnuTLS\033[0m and \033[1;32mOpenSSL\033[0m on your system.\n";
775                 print "I will default to GnuTLS. If you wish to use OpenSSL\n";
776                 print "instead, you should enable the OpenSSL module yourself\n";
777                 print "by copying it from src/modules/extra to src/modules.\n\n";
778                 print "Detected GnuTLS version: \033[1;32m" . $gnutls_ver . "\033[0m\n";
779                 print "Detected OpenSSL version: \033[1;32m" . $openssl_ver . "\033[0m\n\n";
780         }
781
782         if ($config{HAS_GNUTLS} eq "y") {
783                 yesno(USE_GNUTLS, "Would you like to enable SSL Support?");
784                 if ($config{USE_GNUTLS} eq "y") {
785                         print "\nUsing GnuTLS SSL module.\n";
786                 }
787         } elsif ($config{HAS_OPENSSL} eq "y") {
788                         yesno(USE_OPENSSL, "Would you like to enable SSL Support?");
789         if ($config{USE_OPENSSL} eq "y") {
790                         print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
791                 }
792         }
793         else {
794                 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed if\nyou intend to use OpenSSL, or that GnuTLS is in your path if you intend\nto use GnuTLS.\n\n";
795         }
796
797         print "\nThe following questions will ask you for various figures relating\n";
798         print "To your IRCd install. Please note that these should usually be left\n";
799         print "as defaults unless you have a real reason to change them. If they\n";
800         print "changed, then the values must be identical on all servers on your\n";
801         print "network, or malfunctions and/or crashes may occur, with the exception\n";
802         print "of the 'maximum number of clients' setting which may be different on\n";
803         print "different servers on the network.\n\n";
804
805         # File Descriptor Settings..
806         promptnumeric("number of clients at any one time", "MAX_CLIENT_T");
807         $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
808         $config{MAX_DESCRIPTORS} = $config{MAX_CLIENT_T};
809
810         promptnumeric("length of nicknames", "NICK_LENGT");
811         promptnumeric("length of channel names", "CHAN_LENGT");
812         promptnumeric("number of mode changes in one line", "MAXI_MODES");
813         promptnumeric("length of an ident (username)", "MAX_IDENT");
814         promptnumeric("length of a quit message", "MAX_QUIT");
815         promptnumeric("length of a channel topic", "MAX_TOPIC");
816         promptnumeric("length of a kick message", "MAX_KICK");
817         promptnumeric("length of a GECOS (real name)", "MAX_GECOS");
818         promptnumeric("length of an away message", "MAX_AWAY");
819 }
820
821 dumphash();
822
823 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
824 {
825         print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
826         exit(0);
827 }
828 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
829 {
830         print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
831         exit(0);
832 }
833
834 if ($config{USE_GNUTLS} eq "y") {
835         $failed = 0;
836         open(TMP, "<src/modules/m_ssl_gnutls.cpp") or $failed = 1;
837         close(TMP);
838         if ($failed) {
839                 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
840                 chdir("src/modules");
841                 system("ln -s extra/m_ssl_gnutls.cpp");
842                 chdir("../..");
843         }
844         getmodules();
845         if ($interactive)
846         {
847                 $failed = 0;
848                 open(TMP, "<$config{CONFIG_DIR}/key.pem") or $failed = 1;
849                 close(TMP);
850                 open(TMP, "<$config{CONFIG_DIR}/cert.pem") or $failed = 1;
851                 close(TMP);
852                 if ($failed) {
853                         print "SSL Certificates Not found, Generating.. \n\n
854 *************************************************************
855 * Generating the Private Key may take some time, go grab a  *
856 * Coffee. Even better, to generate some more entropy if it  *
857 * is taking a while, open another console and type du / a   *
858 * few times and get that HD going :) Then answer the        *
859 * Questions which follow. If you are unsure, just hit enter *
860 *************************************************************\n\n";
861                         $failed = make_gnutls_cert();
862                         if ($failed) {
863                                 print "\n\033[1;32mCertificate generation failed!\033[0m\n\n";
864                         } else {
865                                 print "\nCertificate generation complete, copying to config directory... ";
866                                 system("mv key.pem $config{CONFIG_DIR}/key.pem");
867                                 system("mv cert.pem $config{CONFIG_DIR}/cert.pem");
868                                 print "Done.\n\n";
869                         }
870                 }
871                 else {
872                         print "SSL Certificates found, skipping.\n\n";
873                 }
874         }
875         else
876         {
877                 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
878         }
879 } elsif ($config{USE_OPENSSL} eq "y") {
880         $failed = 0;
881         open(TMP, "<src/modules/m_ssl_openssl.cpp") or $failed = 1;
882         close(TMP);
883         if ($failed) {
884                 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
885                 chdir("src/modules");
886                 system("ln -s extra/m_ssl_openssl.cpp");
887                 chdir("../..");
888         }
889         getmodules();
890         $failed = 0;
891         if ($interactive)
892         {
893                 open(TMP, "<$config{CONFIG_DIR}/key.pem") or $failed = 1;
894                 close(TMP);
895                 open(TMP, "<$config{CONFIG_DIR}/cert.pem") or $failed = 1;
896                 close(TMP);
897                 if ($failed) {
898                         print "SSL Certificates Not found, Generating.. \n\n
899 *************************************************************
900 * Generating the certificates may take some time, go grab a *
901 * coffee, or something.                                     *
902 *************************************************************\n\n";
903                         make_openssl_cert();
904                         print "\nCertificate generation complete, copying to config directory... ";
905                         system("mv key.pem $config{CONFIG_DIR}/key.pem");
906                         system("mv cert.pem $config{CONFIG_DIR}/cert.pem");
907                         system("mv dhparams.pem $config{CONFIG_DIR}/dhparams.pem");
908                         print "Done.\n\n";
909                 } else {
910                         print "SSL Certificates found, skipping.\n\n"
911                 }
912         }
913         else
914         {
915                 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
916         }
917 }
918 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
919         print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
920 }
921
922 getosflags();
923 writefiles(1);
924 makecache();
925
926 print "\n\n";
927 print "To build your server with these settings, please type '\033[1;32m$config{MAKEPROG}\033[0m' now.\n";
928 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
929         print "Please remember that to enable \033[1;32mSSL support\033[0m you must\n";
930         print "load the required modules in your config. This configure process\n";
931         print "has just prepared these modules to be compiled for you, and has not\n";
932         print "configured them to be compiled into the core of the ircd.\n";
933 }
934 print "*** \033[1;32mRemember to edit your configuration files!!!\033[0m ***\n\n\n";
935 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
936         print "\033[1;32mWARNING!\033[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";
937 }
938
939 if ($config{GCCVER} < "3") {
940         print <<FOO2;
941 \033[1;32mWARNING!\033[0m You are attempting to compile InspIRCd on GCC 2.x!
942 GCC 2.x series compilers only had partial (read as broken) C++ support, and
943 your compile will most likely fail horribly! If you have any problems, do NOT
944 report them to the bugtracker or forums without first upgrading your compiler
945 to a newer 3.x or 4.x (or whatever is available currently) version.
946 FOO2
947 }
948
949 ################################################################################
950 #                             HELPER FUNCTIONS                          #
951 ################################################################################
952 sub getcache {
953         # Retrieves the .config.cache file, and loads values into the main config hash.
954         open(CACHE, ".config.cache") or return 0;
955         while (<CACHE>) {
956                 chomp;
957                 # Ignore Blank lines, and comments..
958                 next if /^\s*$/;
959                 next if /^\s*#/;
960                 my ($key, $value) = split("=", $_, 2);
961                 $value =~ /^\"(.*)\"$/;
962                 # Do something with data here!
963                 $config{$key} = $1;
964         }
965         close(CONFIG);
966         return 1;
967 }
968
969 sub makecache {
970         # Dump the contents of %config
971         print "Writing \033[1;32mcache file\033[0m for future ./configures ...\n";
972         open(FILEHANDLE, ">.config.cache");
973         foreach $key (keys %config) {
974                 print FILEHANDLE "$key=\"$config{$key}\"\n";
975         }
976         close(FILEHANDLE);
977 }
978
979 sub dir_check {
980         my ($desc, $hash_key) = @_;
981         my $complete = 0;
982         while (!$complete) {
983                 print "In what directory $desc?\n";
984                 print "[\033[1;32m$config{$hash_key}\033[0m] -> ";
985                 chomp($var = <STDIN>);
986                 if ($var eq "") {
987                         $var = $config{$hash_key};
988                 }
989                 if ($var =~ /^\~\/(.+)$/) {
990                         # Convert it to a full path..
991                         $var = resolve_directory($ENV{HOME} . "/" . $1);
992                 }
993                 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
994                 {
995                         # Assume relative Path was given.. fill in the rest.
996                         $var = $this . "/$var";
997                 }
998                 
999                 $var = resolve_directory($var); 
1000                 if (! -e $var) {
1001                         print "$var does not exist. Create it?\n[\033[1;32my\033[0m] ";
1002                         chomp($tmp = <STDIN>);
1003                         if (($tmp eq "") || ($tmp =~ /^y/i)) {
1004                                 # Attempt to Create the Dir..
1005                                 
1006                                 system("mkdir -p \"$var\" >> /dev/null 2>&1");
1007                                 $chk = system("mkdir -p \"$var\" >> /dev/null 2>&1") / 256;
1008                                 if ($chk != 0) {
1009                                         print "Unable to create directory. ($var)\n\n";
1010                                         # Restart Loop..
1011                                         next;
1012                                 }
1013                         } else {
1014                                 # They said they don't want to create, and we can't install there.
1015                                 print "\n\n";
1016                                 next;
1017                         }
1018                 } else {
1019                         if (!is_dir($var)) {
1020                                 # Target exists, but is not a directory.
1021                                 print "File $var exists, but is not a directory.\n\n";
1022                                 next;
1023                         }
1024                 }
1025                 # Either Dir Exists, or was created fine.
1026                 $config{$hash_key} = $var;
1027                 $complete = 1;
1028                 print "\n";
1029         }
1030 }
1031
1032 sub getosflags {
1033
1034         $config{LDLIBS} = "-lstdc++";
1035         $config{FLAGS}  = "-fno-strict-aliasing -fPIC -Wall -Woverloaded-virtual -Wno-deprecated $config{OPTIMISATI}";
1036         $config{DEVELOPER} = "-fno-strict-aliasing -fPIC -Wall -Woverloaded-virtual -Wno-deprecated -g";
1037         $SHARED = "-Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared";
1038         $config{MAKEPROG} = "make";
1039
1040         if ($config{OSNAME} =~ /darwin/i) {
1041                 $config{FLAGS}  = "-DDARWIN -frtti -fPIC -Wall -Woverloaded-virtual -Wno-deprecated $config{OPTIMISATI}";
1042                 $SHARED = "-bundle -twolevel_namespace -undefined dynamic_lookup";
1043                 $config{LDLIBS} = "-ldl -lstdc++";
1044         }
1045
1046         if ($config{OSNAME} =~ /OpenBSD/i) {
1047                 $config{MAKEPROG} = "gmake";
1048                 $config{LDLIBS} = $config{LDLIBS} . " -lunwind";
1049                 chomp($foo = `eg++ -dumpversion | cut -c 1`);
1050                 # theyre running the package version of gcc (eg++)... detect it and set up its version numbers.
1051                 # if theyre not running this, configure lets the build continue but they probably wont manage to
1052                 # compile as this standard version is 2.95.3!
1053                 if ($foo ne "") {
1054                         $config{CC} = "eg++";
1055                         chomp($config{GCCVER}       = `eg++ -dumpversion | cut -c 1`); # we must redo these if we change the compiler path
1056                 }
1057                 return "OpenBSD";
1058         }
1059
1060         if ($config{OSNAME} =~ /Linux/i) {
1061                 $config{LDLIBS} = "-ldl -lstdc++";
1062                 $config{FLAGS}  = "-fno-strict-aliasing -fPIC -Wall -Woverloaded-virtual -Wno-deprecated $config{OPTIMISATI}";
1063                 $config{FLAGS}  .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1064                 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1065                 $config{MAKEPROG} = "make";
1066         }
1067
1068         if ($config{OSNAME} =~ /FreeBSD/i) {
1069                 $config{FLAGS}  .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
1070                 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
1071         }
1072
1073         if ($config{OSNAME} =~ /SunOS/i or $config{OSNAME} =~ /solaris/i)
1074         {
1075                 # solaris/sunos needs these
1076                 # socket = bsd sockets api
1077                 # nsl = dns stuff
1078                 # rt = POSIX realtime extensions
1079                 # resolv = inet_aton only (why isnt this in nsl?!)
1080                 $config{MAKEPROG} = "gmake";
1081                 $config{LDLIBS} .= " -lsocket -lnsl -lrt -lresolv";
1082                 return "Solaris";
1083         }
1084         
1085         if($config{OSNAME} =~ /MINGW32/i)
1086         {
1087                 # All code is position-independent on windows
1088                 $config{FLAGS} =~ s/-fPIC //;
1089                 return "MinGW";
1090         }
1091
1092         return $config{OSNAME};
1093 }
1094
1095 sub writefiles {
1096         my($writeheader) = @_;
1097         # First File.. inspircd_config.h
1098         chomp(my $incos = `uname -n -s -r`);
1099         chomp($version = `sh src/version.sh`);
1100         chomp(my $revision2 = getrevision());
1101         if ($writeheader == 1)
1102         {
1103                 print "Writing \033[1;32minspircd_config.h\033[0m\n";
1104                 open(FILEHANDLE, ">include/inspircd_config.h");
1105                 my $NL = $config{NICK_LENGT}+1;
1106                 my $CL = $config{CHAN_LENGT}+1;
1107                 print FILEHANDLE <<EOF;
1108 /* Auto generated by configure, do not modify! */
1109 #ifndef __CONFIGURATION_AUTO__
1110 #define __CONFIGURATION_AUTO__
1111
1112 /* this is for windows support. */
1113 #define CoreExport /**/
1114 #define DllExport /**/
1115
1116 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
1117 #define MOD_PATH "$config{MODULE_DIR}"
1118 #define VERSION "$version"
1119 #define REVISION "$revision2"
1120 #define MAXCLIENTS $config{MAX_CLIENT}
1121 #define MAXCLIENTS_S "$config{MAX_CLIENT}"
1122 #define SOMAXCONN_S "$config{_SOMAXCONN}"
1123 #define MAX_DESCRIPTORS $config{MAX_DESCRIPTORS}
1124 #define NICKMAX $NL
1125 #define CHANMAX $CL
1126 #define MAXMODES $config{MAXI_MODES}
1127 #define IDENTMAX $config{MAX_IDENT}
1128 #define MAXQUIT $config{MAX_QUIT}
1129 #define MAXTOPIC $config{MAX_TOPIC}
1130 #define MAXKICK $config{MAX_KICK}
1131 #define MAXGECOS $config{MAX_GECOS}
1132 #define MAXAWAY $config{MAX_AWAY}
1133 #define OPTIMISATION $config{OPTIMITEMP}
1134 #define LIBRARYDIR "$config{LIBRARY_DIR}"
1135 #define SYSTEM "$incos"
1136 EOF
1137 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
1138
1139                 if ($config{OSNAME} =~ /SunOS/i) {
1140                         print FILEHANDLE "#define IS_SOLARIS\n";
1141                 }
1142                 if ($config{OSNAME} =~ /MINGW32/i) {
1143                         print FILEHANDLE "#define IS_MINGW\n";
1144                 }
1145                 if ($config{GCCVER} >= 3) {
1146                         print FILEHANDLE "#define GCC3\n";
1147                 }
1148                 if ($config{HAS_STRLCPY} eq "true") {
1149                         print FILEHANDLE "#define HAS_STRLCPY\n";
1150                 }
1151                 if ($config{HAS_STDINT} eq "true") {
1152                         print FILEHANDLE "#define HAS_STDINT\n";
1153                 }
1154                 if ($config{IPV6} =~ /y/i) {
1155                         print FILEHANDLE "#define IPV6\n";
1156                 }
1157                 if ($config{SUPPORT_IP6LINKS} =~ /y/i) {
1158                         print FILEHANDLE "#define SUPPORT_IP6LINKS\n";
1159                 }
1160                 my $use_hiperf = 0;
1161                 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
1162                         print FILEHANDLE "#define USE_KQUEUE\n";
1163                         $se = "socketengine_kqueue";
1164                         $use_hiperf = 1;
1165                 }
1166                 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
1167                         print FILEHANDLE "#define USE_EPOLL\n";
1168                         $se = "socketengine_epoll";
1169                         $use_hiperf = 1;
1170                 }
1171                 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
1172                         print FILEHANDLE "#define USE_PORTS\n";
1173                         $se = "socketengine_ports";
1174                         $use_hiperf = 1;
1175                 }
1176                 # user didn't choose either epoll or select for their OS.
1177                 # default them to USE_SELECT (ewwy puke puke)
1178                 if (!$use_hiperf) {
1179                         print FILEHANDLE "#define USE_SELECT\n";
1180                         $se = "socketengine_select";
1181                 }
1182                 print FILEHANDLE "\n#endif\n";
1183                 close(FILEHANDLE);
1184         }
1185
1186         if ($writeheader)
1187         {
1188                 open(FILEHANDLE, ">include/inspircd_se_config.h");
1189                 print FILEHANDLE <<EOF;
1190 /* Auto generated by configure, do not modify or commit to svn! */
1191 #ifndef __CONFIGURATION_SOCKETENGINE__
1192 #define __CONFIGURATION_SOCKETENGINE__
1193
1194 #include "$se.h"
1195
1196 #endif
1197 EOF
1198                 close(FILEHANDLE);
1199         }
1200
1201
1202         # Create a Modules List..
1203         my $modules = "";
1204         foreach $i (@modlist)
1205         {
1206                 $modules .= "m_".$i.".so ";
1207         }
1208         chomp($modules);   # Remove Redundant whitespace..
1209
1210         opendir(DIRHANDLE, "src/modules");
1211         foreach $name (sort readdir(DIRHANDLE)) {
1212                 if ($name =~ /^m_(.+?)$/) {
1213                         if (opendir(MDIRHANDLE, "src/modules/$name") != 0) {
1214                                 closedir(MDIRHANDLE);
1215                                 $modules .= "$name.so ";
1216                         }
1217                 }
1218         }
1219         closedir(DIRHANDLE);
1220
1221
1222         # Write all .in files.
1223         my $tmp = "";
1224         my $file = "";
1225         my $exe = "inspircd";
1226
1227         opendir(DIRHANDLE, $this);
1228
1229         # Do this once here, and cache it in the .*.inc files,
1230         # rather than attempting to read src/version.sh from
1231         # compiled code -- we might not have the source to hand.
1232         # Fix for bug#177 by Brain.
1233
1234         chomp(my $version = `sh ./src/version.sh`);
1235         chomp(my $revision = getrevision());
1236         $version = "$version(r$revision)";
1237
1238         my $LIBEXT = "so";
1239         if ($config{IS_DARWIN} eq "YES")
1240         {
1241                 $LIBEXT = "dylib";
1242         }
1243         # We can actually parse any file starting with . and ending with .inc,
1244         # but right now we only parse .inspircd.inc to form './inspircd'
1245
1246         foreach $name (sort readdir(DIRHANDLE)) {
1247                 if ($name =~ /^\.(.+)\.inc$/) {
1248                         $file = $1;
1249
1250                         # Bug #353, omit this on non-darwin
1251                         next if (($config{OSNAME} !~ /darwin/) && ($file eq "org.inspircd.plist"));
1252
1253                         # All .name.inc files need parsing!
1254                         $tmp = "";
1255                         open(FILEHANDLE, ".$file.inc");
1256                         while (<FILEHANDLE>) {
1257                                 $tmp .= $_;
1258                         }
1259                         close(FILEHANDLE);
1260
1261                         $tmp =~ s/\@CC\@/$config{CC}/;
1262                         $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/;
1263                         $tmp =~ s/\@FLAGS\@/$config{FLAGS}/;
1264                         $tmp =~ s/\@DEVELOPER\@/$config{DEVELOPER}/;
1265                         $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/;
1266                         $tmp =~ s/\@BASE_DIR\@/$config{BASE_DIR}/;
1267                         $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/;
1268                         $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/;
1269                         $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/;
1270                         $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/;
1271                         $tmp =~ s/\@LIBRARY_EXT\@/$LIBEXT/;
1272                         $tmp =~ s/\@MODULES\@/$modules/;
1273                         $tmp =~ s/\@STARTSCRIPT\@/$config{STARTSCRIPT}/;
1274                         $tmp =~ s/\@DESTINATION\@/$config{DESTINATION}/;
1275                         $tmp =~ s/\@EXTRA_DIR\@/$config{EXTRA_DIR}/;
1276                         $tmp =~ s/\@EXECUTABLE\@/$exe/;
1277                         $tmp =~ s/\@MAKEORDER\@/$config{MAKEORDER}/;
1278                         $tmp =~ s/\@VERSION\@/$version/;
1279
1280                         print "Writing \033[1;32m$file\033[0m\n";
1281                         open(FILEHANDLE, ">$file");
1282                         print FILEHANDLE $tmp;
1283                 }
1284         }
1285         closedir(DIRHANDLE);
1286
1287         # Make inspircd executable!
1288         chmod 0744, 'inspircd';
1289
1290         print "Writing dynamic-build \033[1;32msrc/Makefile\033[0m\n";
1291         write_dynamic_makefile();
1292         write_dynamic_modules_makefile();
1293 }
1294
1295 sub write_dynamic_modules_makefile {
1296         # Modules Makefile..
1297         print "Writing \033[1;32msrc/modules/Makefile\033[0m\n";
1298         open(FILEHANDLE, ">src/modules/Makefile");
1299
1300 ###
1301 # Module Makefile Header
1302 ###
1303         print FILEHANDLE <<EOF;
1304 ###################################################
1305 # Copyright 2002-2007 The InspIRCd Development Team
1306 #  http://www.inspircd.org/wiki/index.php/Credits
1307 #
1308 # Thanks to Andrew Church <achurch\@achurch.org>
1309 #   for assisting with making this work right.
1310 #
1311 # Automatically Generated by ./configure to add a
1312 #  modules please run ./configure -modupdate
1313 ###################################################
1314
1315 all: \$(MODULES)
1316
1317 EOF
1318
1319 if ($config{OSNAME} =~ /darwin/) {
1320                 print FILEHANDLE <<EOCHEESE;
1321
1322 PICLDFLAGS = -twolevel_namespace -undefined dynamic_lookup \$(FLAGS) -bundle
1323
1324 EOCHEESE
1325 } else {
1326                 print FILEHANDLE <<EOCHEESE;
1327
1328 PICLDFLAGS = -fPIC -DPIC -shared \$(FLAGS)
1329
1330 EOCHEESE
1331 }
1332
1333         ###
1334         # End Module Makefile Header
1335         ###
1336
1337         # Create a Modules List..
1338         my $modules = "";
1339         my $cmflags = "";
1340         my $liflags = "";
1341         my $crud = "";
1342
1343         foreach $i (@modlist) {
1344                 ###
1345                 # Write Entry to the MakeFile
1346                 ###
1347                 $cmflags = getcompilerflags("src/modules/m_".$i.".cpp");
1348                 $liflags = getlinkerflags("src/modules/m_".$i.".cpp");
1349                 $deps = getdependencies("src/modules/m_".$i.".cpp");
1350         
1351                 #print "file: $i: cmflags=$cmflags; liflags=$liflags; deps=$deps\n";
1352         
1353                 print FILEHANDLE <<EOCHEESE;
1354 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
1355         \$(CC) -pipe -I../../include \$(FLAGS) $cmflags \$(PICLDFLAGS) $liflags -export-dynamic -o m_$i.so m_$i.cpp
1356 EOCHEESE
1357                 $crud = $crud . "       install -m \$(INSTMODE) m_$i.so \$(MODPATH)\n";
1358 ###
1359                 # End Write Entry to the MakeFile
1360                 ###
1361         }
1362
1363         opendir(DIRHANDLE, "src/modules");
1364         foreach $name (sort readdir(DIRHANDLE)) {
1365                 if ($name =~ /^m_(.+?)$/) {
1366                         $mfrules = "";
1367                         $mobjs = "";
1368                         $mliflags = "";
1369                         $mfcount = 0;
1370                         # A module made of multiple files, in a dir, e.g. src/modules/m_spanningtree/
1371                         if (opendir(MDIRHANDLE, "src/modules/$name") != 0) {
1372                                 read_module_directory("src/modules/$name", $name);
1373                                 print "Composing Makefile rules for directory \033[1;32m$name\033[0m... (\033[1;32m$mfcount files found\033[0m)\n";
1374                                 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"; 
1375                                 if ($config{IS_DARWIN} eq "YES") {
1376                                         print FILEHANDLE "      \$(CC) -pipe -twolevel_namespace -undefined dynamic_lookup \$(FLAGS) $mliflags -bundle -o $name.so $mobjs\n"; 
1377                                 } else {
1378                                         print FILEHANDLE "      \$(CC) -pipe \$(FLAGS) -shared $mliflags -o $name.so $mobjs\n";
1379                                 }
1380                                 print FILEHANDLE "\n$mfrules\n";
1381                                 closedir(MDIRHANDLE);
1382                                 $crud = $crud . "       install -m \$(INSTMODE) $name.so \$(MODPATH)\n";
1383                         }
1384                 }
1385         }
1386         closedir(DIRHANDLE);
1387
1388         print FILEHANDLE "modinst:\n    \@echo \"Installing modules...\"\n" . $crud;
1389 }
1390
1391 sub read_module_directory {
1392         my ($dpath, $reldpath) = @_;
1393         
1394         if (opendir(MDIRHANDLE, $dpath) == 0) {
1395                 return;
1396         }
1397         
1398         foreach $fname (sort readdir(MDIRHANDLE)) {
1399                 if ($fname =~ /\.cpp$/) {
1400                         $cmflags = getcompilerflags("$dpath/$fname");
1401                         $mliflags = $mliflags . " " . getlinkerflags("$dpath/$fname");
1402                         $deps = getdependencies("$dpath/$fname");
1403                         $oname = $fname;
1404                         $oname =~ s/\.cpp$/.o/g;
1405                         $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";
1406                         $mfrules = $mfrules .  "        \$(CC) -pipe -I../../include -I. \$(FLAGS) $cmflags -export-dynamic -o $reldpath/$oname -c $reldpath/$fname\n\n";
1407                         $mobjs = $mobjs . " $reldpath/$oname";
1408                         $mfcount++;
1409                 }
1410                 elsif ((-d "$dpath/$fname") && !($fname eq ".") && !($fname eq "..")) {
1411                         read_module_directory($dpath."/".$fname, $reldpath."/".$fname);
1412                 }
1413         }
1414 }
1415
1416 sub calcdeps($)
1417 {
1418         # Yes i know we could use gcc -M but it seems to ideneify a lot of 'deep'
1419         # dependencies which are not relevent in C++.
1420
1421         my $file = $_[0];
1422
1423         open (CPP, "<$file") or die("Can't open $file for reading!");
1424
1425         my %dupe = ();
1426         my $retlist = "";
1427
1428         foreach my $d (@ignoredeps)
1429         {
1430                 $dupe{$d} = 1;
1431         }
1432
1433         my $immutable = "";
1434         foreach my $dep (@immutabledeps)
1435         {
1436                 $immutable = $immutable . "../include/$dep ";
1437         }
1438         $immutable =~ s/ $//g;
1439
1440         while (chomp($line = <CPP>))
1441         {
1442                 if ($line =~ /#include "(.+\.h)"/)
1443                 {
1444                         if (!exists($dupe{$1}))
1445                         {
1446                                 $retlist = $retlist . "../include/$1 ";
1447                                 $dupe{$1} = 1;
1448                         }
1449                 }
1450         }
1451         close CPP;
1452         return length($immutable) ? $immutable . " " . $retlist : $retlist;
1453 }
1454
1455 sub write_dynamic_makefile {
1456
1457         my $i = 0;
1458         my @cmdlist = ();
1459         opendir(DIRHANDLE, "src/commands");
1460         foreach $name (sort readdir(DIRHANDLE)) {
1461                 if ($name =~ /^cmd_(.+)\.cpp$/) {
1462                         $cmdlist[$i++] = $1;
1463                 }
1464         }
1465         closedir(DIRHANDLE);
1466
1467         $se = "socketengine_select";
1468         if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
1469                 $se = "socketengine_kqueue";
1470         }
1471         elsif (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
1472                 $se = "socketengine_epoll";
1473         }
1474         elsif (($has_ports) && ($config{USE_PORTS} eq "y")) {
1475                 $se = "socketengine_ports";
1476         }
1477
1478         $extrasources{"socketengine.cpp"} = $se . ".cpp";
1479         $extraobjects{"socketengine.cpp"} = $se . ".o";
1480
1481         $freebsd4libs = $config{CRAQ};
1482
1483         my $all = "all: ";
1484         $all_libsonly = "";
1485
1486         if ($config{IS_DARWIN} eq "YES")
1487         {
1488                 $libraryext = "dylib";
1489                 $othercrap = "  \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c inspircd.cpp\n   \$(CC) -pipe -dynamic -bind_at_load -L. -o inspircd \$(LDLIBS) inspircd.o "
1490         }
1491         else
1492         {
1493                 $libraryext = "so";
1494                 $othercrap = "  \$(CC) -pipe -I../include -Wl,--rpath -Wl,$config{LIBRARY_DIR} \$(FLAGS) $freebsd4libs -rdynamic -L. inspircd.cpp -o inspircd \$(LDLIBS) ";
1495         }
1496
1497         foreach my $cpp (sort keys %filelist)
1498         {
1499                 $all = $all . $filelist{$cpp} . "." . $libraryext . " ";
1500                 $all_libsonly = $all_libsonly . $filelist{$cpp} . "." . $libraryext . " ";
1501         }
1502         $all = $all . "moo inspircd\n";
1503
1504         $othercrap = $othercrap . " $all_libsonly\n\n";
1505
1506         open(FH,">src/Makefile") or die("Could not write src/Makefile");
1507         print FH <<EOM;
1508
1509 CC = im a cheezeball
1510 CXXFLAGS = -I../include \${FLAGS}
1511 CPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* //' | grep -v svn)
1512 RELCPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* /modes\\//' | grep -v svn)
1513
1514 EOM
1515
1516         print FH "$all\n\n";
1517
1518         $deps = calcdeps("src/inspircd.cpp");
1519         print FH "inspircd: inspircd.cpp $deps $all_libsonly\n";
1520         print FH "$othercrap\n";
1521
1522         foreach my $cpp (sort keys %filelist)
1523         {
1524                 my $thislib = $filelist{$cpp} . "." . $libraryext; 
1525                 my $objs = $cpp;
1526                 my $rawcpp = $cpp;
1527                 $objs =~ s/\.cpp$/.o/;
1528                 if (exists($extraobjects{$cpp}))
1529                 {
1530                         $objs = $objs . " " . $extraobjects{$cpp};
1531                 }
1532                 if (exists($extrasources{$cpp}))
1533                 {
1534                         $rawcpp = $rawcpp . " " . $extrasources{$cpp};
1535                 }
1536                 if ($config{IS_DARWIN} eq "YES")
1537                 {
1538                         $libcrap = "-install_name " . $config{LIBRARY_DIR} . "/" . $thislib . " -dynamiclib -twolevel_namespace -undefined dynamic_lookup";
1539                 }
1540                 else
1541                 {
1542                         $libcrap = "-Wl,--rpath -Wl," . $config{LIBRARY_DIR} . " -shared";
1543                 }
1544                 $deps = calcdeps("src/$cpp");
1545                 if (exists($extrasources{$cpp}))
1546                 {
1547                         foreach my $seperate (sort split(' ',$extrasources{$cpp}))
1548                         {
1549                                 $d = calcdeps("src/$extrasources{$cpp}") . " ";
1550                                 if ($d ne "")
1551                                 {
1552                                         $deps = $deps . $d . " ";
1553                                 }
1554                         }
1555                 }
1556                 print FH $thislib . ": $cpp $deps ". $specialdeps{$cpp} . "\n";
1557                 print FH "      \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c $rawcpp\n";
1558                 if (exists($extrabuildlines{$cpp}))
1559                 {
1560                         print FH "      " . $extrabuildlines{$cpp} . "\n";
1561                 }
1562                 print FH "      \$(CC) -pipe $libcrap -o " . $thislib . " " . $objs . "\n\n";
1563         }
1564
1565         print FH "moo:\n        \${MAKE} -C \"commands\" DIRNAME=\"src/commands\" CC=\"\$(CC)\" \$(MAKEARGS)\n\n";
1566
1567         # close main makefile
1568         close(FH);
1569
1570         # generate a list of .so
1571         foreach my $cmd (@cmdlist) {
1572                 $cmdobjs = $cmdobjs . "cmd_$cmd.so ";
1573         }
1574
1575         # and now reopen the commands makefile
1576         open(FH,">src/commands/Makefile") or die("Could not write src/commands/Makefile");
1577         print FH <<ITEM;
1578 CC = i am cornholio
1579 CXXFLAGS = -I../../include ${FLAGS}
1580
1581 all: $cmdobjs
1582
1583
1584 ITEM
1585
1586         # now print the command file details.
1587         foreach my $cmd (@cmdlist) {
1588                 print FH <<ITEM;
1589 cmd_$cmd.so: cmd_$cmd.cpp ../../include/base.h ../../include/modules.h ../../include/inspircd.h ../../include/channels.h ../../include/users.h ../../include/globals.h ../../include/inspircd_config.h ../../include/commands/cmd_$cmd.h
1590         \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic -c cmd_$cmd.cpp
1591         \$(CC) -pipe $SHARED -o cmd_$cmd.so cmd_$cmd.o
1592
1593 ITEM
1594         }
1595 #try build a .so, no intermediate .o
1596 #       \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic $SHARED -o cmd_$cmd.so
1597
1598 #this works for sure
1599 #       \$(CC) -pipe -I../../include \$(FLAGS) -export-dynamic -c cmd_$cmd.cpp
1600 #       \$(CC) -pipe $SHARED -o cmd_$cmd.so cmd_$cmd.o
1601 }
1602