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