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