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