4 # InspIRCd -- Internet Relay Chat Daemon
6 # Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
7 # Copyright (C) 2007, 2009 Dennis Friis <peavey@inspircd.org>
8 # Copyright (C) 2003, 2006-2008 Craig Edwards <craigedwards@brainbox.cc>
9 # Copyright (C) 2006-2008 Robin Burchell <robin+git@viroteck.net>
10 # Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
11 # Copyright (C) 2007 John Brooks <john.brooks@dereferenced.net>
12 # Copyright (C) 2006 Oliver Lupton <oliverlupton@gmail.com>
13 # Copyright (C) 2003-2006 Craig McLure <craig@chatspike.net>
15 # This file is part of InspIRCd. InspIRCd is free software: you can
16 # redistribute it and/or modify it under the terms of the GNU General Public
17 # License as published by the Free Software Foundation, version 2.
19 # This program is distributed in the hope that it will be useful, but WITHOUT
20 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
24 # You should have received a copy of the GNU General Public License
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
34 use warnings FATAL => qw(all);
38 $Data::Dumper::Sortkeys = 1;
39 $Data::Dumper::Useqq = 1;
46 # Utility functions for our buildsystem
50 ###############################################################################################
52 # NON-EDITABLE VARIABLES
54 ###############################################################################################
56 our ($opt_use_gnutls, $opt_use_openssl, $opt_nointeractive, $opt_ports, $opt_epoll, $opt_kqueue,
57 $opt_noports, $opt_noepoll, $opt_nokqueue, $opt_freebsd_port, $opt_system, $opt_uid);
59 our ($opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir, $opt_data_dir, $opt_log_dir);
63 sub enable_extras (@);
65 sub disable_extras (@);
68 my @opt_disableextras;
71 'enable-gnutls' => \$opt_use_gnutls,
72 'system' => \$opt_system,
74 'enable-openssl' => \$opt_use_openssl,
75 'disable-interactive' => \$opt_nointeractive,
76 'enable-ports' => \$opt_ports,
77 'enable-epoll' => \$opt_epoll,
78 'enable-kqueue' => \$opt_kqueue,
79 'disable-ports' => \$opt_noports,
80 'disable-epoll' => \$opt_noepoll,
81 'disable-kqueue' => \$opt_nokqueue,
82 'enable-freebsd-ports-openssl' => \$opt_freebsd_port,
83 'prefix=s' => \$opt_base_dir,
84 'config-dir=s' => \$opt_config_dir,
85 'module-dir=s' => \$opt_module_dir,
86 'binary-dir=s' => \$opt_binary_dir,
87 'data-dir=s' => \$opt_data_dir,
88 'log-dir=s' => \$opt_log_dir,
89 'help' => sub { showhelp(); },
90 'update' => sub { update(); },
91 'clean' => sub { clean(); },
92 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
93 'enable-extras=s@' => \@opt_enableextras, # ^
94 'disable-extras=s@' => \@opt_disableextras, # ^
97 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
98 @opt_enableextras = split /,/, join(',', @opt_enableextras);
99 @opt_disableextras = split /,/, join(',', @opt_disableextras);
100 enable_extras(@opt_enableextras);
101 disable_extras(@opt_disableextras);
103 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
107 our $interactive = !(
108 (defined $opt_base_dir) ||
109 (defined $opt_config_dir) ||
110 (defined $opt_module_dir) ||
111 (defined $opt_base_dir) ||
112 (defined $opt_binary_dir) ||
113 (defined $opt_data_dir) ||
114 (defined $opt_log_dir) ||
115 (defined $opt_nointeractive) ||
116 (defined $opt_kqueue) ||
117 (defined $opt_epoll) ||
118 (defined $opt_ports) ||
119 (defined $opt_use_openssl) ||
120 (defined $opt_nokqueue) ||
121 (defined $opt_noepoll) ||
122 (defined $opt_noports) ||
123 (defined $opt_system) ||
124 (defined $opt_uid) ||
125 (defined $opt_use_gnutls) ||
126 (defined $opt_freebsd_port)
129 chomp(our $topdir = getcwd());
130 our $this = resolve_directory($topdir); # PWD, Regardless.
131 our @modlist = (); # Declare for Module List..
132 our %config = (); # Initiate Configuration Hash..
133 our $cache_loaded = getcache();
134 $config{ME} = resolve_directory($topdir); # Present Working Directory
136 $config{BASE_DIR} = $config{ME}."/run";
138 if (defined $opt_base_dir) {
139 $config{BASE_DIR} = $opt_base_dir;
140 } elsif (defined $opt_system) {
141 $config{BASE_DIR} = '/var/lib/inspircd';
144 if (defined $opt_system) {
145 $config{UID} = $opt_uid || 'ircd';
146 $config{CONFIG_DIR} = '/etc/inspircd';
147 $config{MODULE_DIR} = '/usr/lib/inspircd';
148 $config{BINARY_DIR} = '/usr/sbin/';
149 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
150 $config{DATA_DIR} = '/var/inspircd';
151 $config{LOG_DIR} = '/var/log/inspircd';
153 $config{UID} = $opt_uid || $<;
154 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
155 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
156 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
157 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
158 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data directory
159 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log directory
162 if (defined $opt_config_dir) {
163 $config{CONFIG_DIR} = $opt_config_dir;
165 if (defined $opt_module_dir) {
166 $config{MODULE_DIR} = $opt_module_dir;
168 if (defined $opt_binary_dir) {
169 $config{BINARY_DIR} = $opt_binary_dir;
171 if (defined $opt_data_dir) {
172 $config{DATA_DIR} = $opt_data_dir;
174 if (defined $opt_log_dir) {
175 $config{LOG_DIR} = $opt_log_dir;
177 chomp($config{HAS_GNUTLS} = `pkg-config --modversion gnutls 2>/dev/null`); # GNUTLS Version.
179 if (defined $opt_freebsd_port)
181 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`);
182 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`);
183 $config{USE_FREEBSD_BASE_SSL} = "n";
187 if ($^O eq "freebsd")
189 # default: use base ssl
190 chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`); # OpenSSL version, freebsd specific
191 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`); # Port version, may be different
195 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version, others
196 $config{HAS_OPENSSL_PORT} = "";
200 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
201 chomp(our $openssl_ver = $config{HAS_OPENSSL});
202 $config{USE_GNUTLS} = "n";
203 if (defined $opt_use_gnutls)
205 $config{USE_GNUTLS} = "y"; # Use gnutls.
207 $config{USE_OPENSSL} = "n"; # Use openssl.
208 if (defined $opt_use_openssl)
210 $config{USE_OPENSSL} = "y";
213 $config{HAS_STDINT} = "false"; # stdint.h check
214 $config{USE_KQUEUE} = "y"; # kqueue enabled
215 if (defined $opt_nokqueue) {
216 $config{USE_KQUEUE} = "n";
218 $config{USE_POLL} = "y"; # poll enabled
219 $config{USE_EPOLL} = "y"; # epoll enabled
220 if (defined $opt_noepoll)
222 $config{USE_EPOLL} = "n";
224 $config{USE_PORTS} = "y"; # epoll enabled
225 if (defined $opt_noports)
227 $config{USE_PORTS} = "n";
229 $config{OSNAME} = $^O; # Operating System Name
230 $config{STARTSCRIPT} = "inspircd"; # start script?
231 $config{DESTINATION} = "BASE"; # Is target path.
232 if ($config{OSNAME} =~ /darwin/i)
234 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
235 $config{CC} = "xcrun clang++"; # C++ compiler for OSX.
239 $config{CC} = "g++"; # C++ compiler
241 if (defined $ENV{CXX})
243 $config{CC} = $ENV{CXX};
245 our $exec = $config{CC} . " -dumpversion | cut -c 1";
246 chomp($config{GCCVER} = `$exec`); # Major GCC Version
247 $exec = $config{CC} . " -dumpversion | cut -c 3";
248 chomp($config{GCCMINOR} = `$exec`);
250 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)(?:[a-z])?(?:\-[a-z][0-9])?/) {
251 $config{HAS_OPENSSL} = $1;
253 $config{HAS_OPENSSL} = "";
256 if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
257 if ($config{OSNAME} eq 'darwin') {
258 print $config{CC} . " was not found! You require clang++ (the LLVM C++ compiler, part of the OSX developer tools) to build InspIRCd!\n";
260 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
265 # Get and Set some important vars..
270 unlink(".config.cache");
273 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
278 chomp($topdir = getcwd());
279 $this = resolve_directory($topdir); # PWD, Regardless.
281 # Does the cache file exist?
283 # No, No it doesn't.. *BASH*
284 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
287 # We've Loaded the cache file and all our variables..
288 print "Updating files...\n";
289 $has_epoll = $config{HAS_EPOLL};
290 $has_ports = $config{HAS_PORTS};
291 $has_kqueue = $config{HAS_KQUEUE};
300 print "Configure update failed: $@\n";
305 print "Running non-interactive configure...\n" unless $interactive;
306 print "Checking for cache from previous configure... ";
307 print ($cache_loaded ? "found\n" : "not found\n");
308 $config{SYSTEM} = lc $^O;
309 print "Checking operating system version... $config{SYSTEM}\n";
311 $exec = $config{CC} . " -dumpversion | cut -c 1";
312 chomp($config{GCCVER} = `$exec`); # Major GCC Version
313 $exec = $config{CC} . " -dumpversion | cut -c 3";
314 chomp($config{GCCMINOR} = `$exec`);
317 print "Checking whether <stdint.h> exists... ";
318 if (test_header($config{CC}, "stdint.h")) {
319 $config{HAS_STDINT} = "true";
322 $config{HAS_STDINT} = "false";
326 printf "Checking whether clock_gettime() exists... ";
327 if (test_file($config{CC}, "clock_gettime.cpp", "-lrt")) {
328 $config{HAS_CLOCK_GETTIME} = "true";
331 $config{HAS_CLOCK_GETTIME} = "false";
335 printf "Checking whether eventfd() exists... ";
336 if (test_file($config{CC}, "eventfd.cpp")) {
337 $config{HAS_EVENTFD} = "true";
340 $config{HAS_EVENTFD} = "false";
344 printf "Checking if a TCP deferring mechanism is available... ";
345 if (test_file($config{CC}, "tcp_defer_accept.cpp")) {
346 $config{HAS_DEFER} = "TCP_DEFER_ACCEPT";
347 print "yes (TCP_DEFER_ACCEPT)\n";
348 } elsif (test_file($config{CC}, "so_acceptfilter.cpp")) {
349 $config{HAS_DEFER} = "SO_ACCEPTFILTER";
350 print "yes (SO_ACCEPTFILTER)\n";
352 $config{HAS_DEFER} = "false";
356 print "Checking whether epoll is available... ";
357 $has_epoll = test_header($config{CC}, "sys/epoll.h");
358 print $has_epoll ? "yes\n" : "no\n";
360 print "Checking whether Kqueue is available... ";
361 $has_kqueue = test_file($config{CC}, "kqueue.cpp");
362 print $has_kqueue ? "yes\n" : "no\n";
364 print 'Checking whether Solaris IOCP is available... ';
365 $has_ports = test_header($config{CC}, 'port.h');
366 print $has_ports ? "yes\n" : "no\n";
368 $config{HAS_EPOLL} = $has_epoll;
369 $config{HAS_KQUEUE} = $has_kqueue;
371 printf "Checking for libgnutls... ";
372 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
373 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
375 $config{HAS_GNUTLS} = "y";
378 $config{HAS_GNUTLS} = "n";
382 $config{HAS_GNUTLS} = "n";
385 printf "Checking for openssl... ";
386 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
387 if (defined($openssl_ver) && ($openssl_ver ne "")) {
389 $config{HAS_OPENSSL} = "y";
392 $config{HAS_OPENSSL} = "n";
396 $config{HAS_OPENSSL} = "n";
399 printf "Checking if you are running an ancient, unsupported OS... ";
400 if ($config{OSNAME} =~ /FreeBSD/i)
402 my $version = `uname -r`;
403 if ($version =~ /^4\./)
406 print "FreeBSD 4.x is no longer supported. By ANYONE.\n";
407 print "To build, you will need to add the following to CXXFLAGS:\n";
408 print "\t-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1\n";
412 print "no ($version)\n";
417 print "no ($config{OSNAME})\n";
420 ################################################################################
421 # BEGIN INTERACTIVE PART #
422 ################################################################################
427 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
430 my $rev = getrevision();
431 # Display Introduction Message..
433 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
434 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
436 *** If you are unsure of any of these values, leave it blank for ***
437 *** standard settings that will work, and your server will run ***
438 *** using them. Please consult your IRC network admin if in doubt. ***
440 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
441 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
442 dir, otherwise you won't have a config file!
444 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
445 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
448 print " (Non-SVN build)";
452 $config{CHANGE_COMPILER} = "n";
453 print "I have detected the following compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
455 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
456 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
457 should NOT be used. You should probably specify a newer compiler.\n\n";
458 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
459 if ($config{CHANGE_COMPILER} =~ /y/i) {
460 print "What command do you want to use to invoke your compiler?\n";
461 print "[\e[1;32m$config{CC}\e[0m] -> ";
462 chomp($config{CC} = <STDIN>);
463 if ($config{CC} eq "") {
466 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
468 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
469 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
470 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
471 if ($config{GCCVER} < 4 || $config{GCCVER} == 4 && $config{GCCMINOR} < 1) {
472 print "\e[1;32mGCC 4.1 and earlier WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
476 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
483 # Directory Settings..
484 my $tmpbase = $config{BASE_DIR};
485 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
486 if ($tmpbase ne $config{BASE_DIR}) {
487 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
488 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
489 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data Directory
490 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log Directory
491 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
494 dir_check("are the configuration files", "CONFIG_DIR");
495 dir_check("are the modules to be compiled to", "MODULE_DIR");
496 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
497 dir_check("are variable data files to be located in", "DATA_DIR");
498 dir_check("are the logs to be stored in", "LOG_DIR");
499 dir_check("do you want the build to take place", "BUILD_DIR");
501 my $chose_hiperf = 0;
503 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?");
505 if ($config{USE_KQUEUE} eq "y") {
510 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?");
512 if ($config{USE_EPOLL} eq "y") {
517 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?");
519 if ($config{USE_PORTS} eq "y") {
524 if (!$chose_hiperf) {
525 yesno('USE_POLL', "Would you like to use poll?\n This is likely to increase performance.\nIf you are unsure, answer yes.\n\nEnable poll?");
526 if ($config{USE_POLL} ne "y")
528 print "No high-performance socket engines are available, or you chose\n";
529 print "not to enable one. Defaulting to select() engine.\n\n";
533 $config{USE_FREEBSD_BASE_SSL} = "n";
534 $config{USE_FREEBSD_PORTS_SSL} = "n";
535 if ($config{HAS_OPENSSL_PORT} ne "")
537 $config{USE_FREEBSD_PORTS_SSL} = "y";
538 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
539 print "version \e[1;32m".$config{HAS_OPENSSL_PORT}."\e[0m. Your base system OpenSSL is version \e[1;32m".$openssl_ver."\e[0m.\n\n";
540 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
542 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
544 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
546 # update to port version
547 $openssl_ver = $config{HAS_OPENSSL_PORT};
552 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
555 $config{USE_SSL} = "n";
556 $config{MODUPDATE} = 'n';
558 if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
560 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
561 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
563 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
564 if ($config{USE_SSL} eq "y")
566 if ($config{HAS_GNUTLS} eq "y")
568 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
569 if ($config{USE_GNUTLS} eq "y")
571 print "\nUsing GnuTLS SSL module.\n";
575 if ($config{HAS_OPENSSL} eq "y")
577 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
578 if ($config{USE_OPENSSL} eq "y")
580 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
587 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed and\n";
588 print "is in your path.\n\n";
591 yesno('MODUPDATE',"Would you like to check for updates to third-party modules?");
593 if ($config{MODUPDATE} eq "y") {
594 print "Checking for upgrades to extra and third party modules... ";
595 system "./modulemanager upgrade";
599 # We are on a POSIX system, we can enable POSIX extras without asking
600 symlink "extra/m_regex_posix.cpp", "src/modules/m_regex_posix.cpp";
604 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
606 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
609 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
611 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
616 $config{CERTGEN} ||= 'y';
617 yesno('CERTGEN',"Would you like generate SSL certificates now?") if ($interactive && ($config{USE_GNUTLS} eq "y" || $config{USE_OPENSSL} eq "y"));
619 if ($config{USE_GNUTLS} eq "y") {
620 unless (-r "src/modules/m_ssl_gnutls.cpp") {
621 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
622 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
624 if ($interactive && $config{CERTGEN} eq 'y')
626 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
627 print "SSL Certificates Not found, Generating.. \n\n
628 *************************************************************
629 * Generating the Private Key may take some time, go grab a *
630 * Coffee. Even better, to generate some more entropy if it *
631 * is taking a while, open another console and type du / a *
632 * few times and get that HD going :) Then answer the *
633 * Questions which follow. If you are unsure, just hit enter *
634 *************************************************************\n\n";
635 $failed = system "./tools/genssl gnutls";
637 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
639 print "\nCertificate generation complete, copying to config directory... ";
640 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
641 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
646 print "SSL Certificates found, skipping.\n\n";
651 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
655 if ($config{USE_OPENSSL} eq "y") {
656 unless (-r "src/modules/m_ssl_openssl.cpp") {
657 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
658 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
661 if ($interactive && $config{CERTGEN} eq 'y')
663 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
664 print "SSL Certificates Not found, Generating.. \n\n
665 *************************************************************
666 * Generating the certificates may take some time, go grab a *
667 * coffee, or something. *
668 *************************************************************\n\n";
669 system "./tools/genssl openssl";
670 print "\nCertificate generation complete, copying to config directory... ";
671 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
672 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
673 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
676 print "SSL Certificates found, skipping.\n\n"
681 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
684 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
685 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
693 print "To build your server with these settings, please run '\e[1;32mmake\e[0m' now.\n";
694 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
695 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
696 print "modules in your config. This configure script has added those modules to the\n";
697 print "build process. For more info please refer to:\n";
698 print "\e[1;32mhttp://wiki.inspircd.org/Installation_From_Tarball\e[0m\n";
700 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
701 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
702 print "\e[1;32mWARNING!\e[0m You are running OpenBSD but you are using the base gcc package\nrather than eg++. This compile will most likely fail, but i'm letting you\ngo ahead with it anyway, just in case i'm wrong :-)\n";
705 if ($config{GCCVER} < "3") {
707 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
708 GCC 2.x series compilers only had partial (read as broken) C++ support, and
709 your compile will most likely fail horribly! If you have any problems, do NOT
710 report them to the bugtracker or forums without first upgrading your compiler
711 to a newer 3.x or 4.x (or whatever is available currently) version.
715 ################################################################################
717 ################################################################################
719 # Retrieves the .config.cache file, and loads values into the main config hash.
720 open(CACHE, ".config.cache") or return 0;
723 # Ignore Blank lines, and comments..
726 my ($key, $value) = split("=", $_, 2);
727 $value =~ /^\"(.*)\"$/;
728 # Do something with data here!
736 # Dump the contents of %config
737 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
738 open(FILEHANDLE, ">.config.cache");
739 foreach my $key (keys %config) {
740 print FILEHANDLE "$key=\"$config{$key}\"\n";
746 my ($desc, $hash_key) = @_;
749 print "In what directory $desc?\n";
750 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
751 chomp(my $var = <STDIN>);
753 $var = $config{$hash_key};
755 if ($var =~ /^\~\/(.+)$/) {
756 # Convert it to a full path..
757 $var = resolve_directory($ENV{HOME} . "/" . $1);
759 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
761 # Assume relative Path was given.. fill in the rest.
762 $var = $this . "/$var";
765 $var = resolve_directory($var);
767 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
768 chomp(my $tmp = <STDIN>);
769 if (($tmp eq "") || ($tmp =~ /^y/i)) {
770 # Attempt to Create the Dir..
773 File::Path::mkpath($var, 0, 0777);
776 unless (defined($chk) && -d $var) {
777 print "Unable to create directory. ($var)\n\n";
782 # They said they don't want to create, and we can't install there.
788 # Target exists, but is not a directory.
789 print "File $var exists, but is not a directory.\n\n";
793 # Either Dir Exists, or was created fine.
794 $config{$hash_key} = $var;
802 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
805 my($writeheader) = @_;
806 # First File.. config.h
807 chomp(my $incos = `uname -n -s -r`);
808 chomp(my $version = `sh src/version.sh`);
809 chomp(my $revision2 = getrevision());
810 my $branch = "InspIRCd-0.0";
811 if ($version =~ /^(InspIRCd-[0-9]+\.[0-9]+)\.[0-9]+/)
815 if ($writeheader == 1)
817 print "Writing \e[1;32mconfig.h\e[0m\n";
818 open(FILEHANDLE, ">include/config.h.tmp");
819 print FILEHANDLE <<EOF;
820 /* Auto generated by configure, do not modify! */
823 #define BRANCH "$branch"
824 #define VERSION "$version"
825 #define REVISION "$revision2"
826 #define SYSTEM "$incos"
828 #define CONFIG_PATH "$config{CONFIG_DIR}"
829 #define DATA_PATH "$config{DATA_DIR}"
830 #define LOG_PATH "$config{LOG_DIR}"
831 #define MOD_PATH "$config{MODULE_DIR}"
835 if ($config{OSNAME} =~ /SunOS/i) {
836 print FILEHANDLE "#define IS_SOLARIS\n";
838 if ($config{OSNAME} =~ /MINGW32/i) {
839 print FILEHANDLE "#define IS_MINGW\n";
841 if ($config{GCCVER} >= 3) {
842 print FILEHANDLE "#define GCC3\n";
844 if ($config{HAS_STDINT} eq "true") {
845 print FILEHANDLE "#define HAS_STDINT\n";
847 if ($config{HAS_EVENTFD} eq 'true') {
848 print FILEHANDLE "#define HAS_EVENTFD\n";
850 if ($config{HAS_CLOCK_GETTIME} eq 'true') {
851 print FILEHANDLE "#define HAS_CLOCK_GETTIME\n";
854 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
855 print FILEHANDLE "#define USE_KQUEUE\n";
856 $config{SOCKETENGINE} = "socketengine_kqueue";
859 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
860 print FILEHANDLE "#define USE_EPOLL\n";
861 $config{SOCKETENGINE} = "socketengine_epoll";
864 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
865 print FILEHANDLE "#define USE_PORTS\n";
866 $config{SOCKETENGINE} = "socketengine_ports";
869 # user didn't choose either epoll or select for their OS.
870 # default them to USE_SELECT (ewwy puke puke)
872 print "no hi-perf, " . $config{USE_POLL};
873 if ($config{USE_POLL} eq "y")
875 print FILEHANDLE "#define USE_POLL\n";
876 $config{SOCKETENGINE} = "socketengine_poll";
880 print FILEHANDLE "#define USE_SELECT\n";
881 $config{SOCKETENGINE} = "socketengine_select";
885 if ($config{HAS_DEFER} eq "TCP_DEFER_ACCEPT") {
886 print FILEHANDLE "#define USE_TCP_DEFER_ACCEPT\n";
887 } elsif ($config{HAS_DEFER} eq "SO_ACCEPTFILTER") {
888 print FILEHANDLE "#define USE_SO_ACCEPTFILTER\n"
891 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n";
894 my $file = 'include/config.h';
896 open my $fh1, $file or $diff = 1;
897 open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
901 if (defined($line1) != defined($line2)) {
903 } elsif (!defined $line1) {
906 $diff = ($line1 ne $line2);
911 rename "$file.tmp", $file;
917 # Write all .in files.
920 my $exe = "inspircd";
922 # Do this once here, and cache it in the .*.inc files,
923 # rather than attempting to read src/version.sh from
924 # compiled code -- we might not have the source to hand.
925 # Fix for bug#177 by Brain.
927 chomp($version = `sh ./src/version.sh`);
928 chomp(my $revision = getrevision());
929 $version = "$version(r$revision)";
931 # We can actually parse any file starting with . and ending with .inc,
932 # but right now we only parse .inspircd.inc to form './inspircd'
933 prepare_dynamic_makefile();
935 my @dotfiles = qw(main.mk inspircd);
936 push @dotfiles, 'org.inspircd.plist' if $config{OSNAME} eq 'darwin';
938 foreach my $file (@dotfiles) {
939 open(FILEHANDLE, "make/template/$file") or die "Can't open make/template/$file: $!";
940 $_ = join '', <FILEHANDLE>;
943 $config{BUILD_DIR} ||= resolve_directory($config{ME}."/build");
946 CC SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR DATA_DIR UID
947 STARTSCRIPT DESTINATION SOCKETENGINE
949 s/\@$var\@/$config{$var}/g;
951 s/\@EXECUTABLE\@/$exe/ if defined $exe;
952 s/\@VERSION\@/$version/ if defined $version;
954 if ($file eq 'main.mk') {
955 print "Writing \e[1;32mGNUmakefile\e[0m ...\n";
958 s/\@IFDEF (\S+)/ifdef $1/g;
959 s/\@IFNDEF (\S+)/ifndef $1/g;
960 s/\@IFEQ (\S+) (\S+)/ifeq ($1,$2)/g;
961 s/\@IFNEQ (\S+) (\S+)/ifneq ($1,$2)/g;
962 s/\@ELSIFEQ (\S+) (\S+)/else ifeq ($1,$2)/g;
965 s/ *\@BSD_ONLY .*\n//g;
967 s/\@DO_EXPORT (.*)/export $1/g;
968 open MKF, '>GNUmakefile' or die "Can't write to GNUmakefile: $!";
972 print "Writing \e[1;32mBSDmakefile\e[0m ...\n";
974 s/\@IFDEF (\S+)/.if defined($1)/g;
975 s/\@IFNDEF (\S+)/.if !defined($1)/g;
976 s/\@IFEQ (\S+) (\S+)/.if $1 == $2/g;
977 s/\@IFNEQ (\S+) (\S+)/.if $1 != $2/g;
978 s/\@ELSIFEQ (\S+) (\S+)/.elif $1 == $2/g;
982 s/ *\@GNU_ONLY .*\n//g;
984 $mk_tmp =~ s#\@DO_EXPORT (.*)#"MAKEENV += ".join ' ', map "$_='\${$_}'", split /\s/, $1#eg;
985 open MKF, '>BSDmakefile' or die "Can't write to BSDmakefile: $!";
989 print "Writing \e[1;32m$file\e[0m ...\n";
990 open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
996 chmod 0755, 'inspircd';
1002 for my $mod (@modlist) {
1003 getcompilerflags("src/modules/m_$mod.cpp");
1004 getlinkerflags("src/modules/m_$mod.cpp");
1008 sub prepare_dynamic_makefile
1014 $config{USE_EPOLL} = 0;
1018 $config{USE_KQUEUE} = 0;
1022 $config{USE_PORTS} = 0;
1026 # Routine to list out the extra/ modules that have been enabled.
1027 # Note: when getting any filenames out and comparing, it's important to lc it if the
1028 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1029 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1030 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1031 sub list_extras () {
1034 my $srcdir = File::Spec->catdir("src", "modules");
1035 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1038 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1039 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1042 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1043 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1046 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1048 EXTRA: for my $extra (@extras) {
1049 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1050 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1051 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1052 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1053 if (-l $abs_source) {
1054 # Symlink, is it in the right place?
1055 my $targ = readlink($abs_source);
1056 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1057 if ($abs_targ eq $abs_extra) {
1058 $extras{$extra} = "\e[32;1menabled\e[0m";
1060 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1062 } elsif (-e $abs_source) {
1063 my ($devext, $inoext) = stat($abs_extra);
1064 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1066 if ($devsrc == $devext && $inosrc == $inoext) {
1067 $extras{$extra} = "\e[32;1menabled\e[0m";
1069 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1072 open my $extfd, "<", $abs_extra;
1073 open my $srcfd, "<", $abs_source;
1075 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1076 $extras{$extra} = "\e[32;1menabled\e[0m";
1078 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1082 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1085 # Now let's add dependency info
1086 for my $extra (keys(%extras)) {
1087 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1088 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1089 my @deps = split / +/, getdependencies($abs_extra);
1090 for my $dep (@deps) {
1091 if (exists($extras{$dep})) {
1092 my $ref = \$extras{$dep}; # Take reference.
1093 if ($$ref !~ m/needed by/) {
1094 # First dependency found.
1095 if ($$ref =~ m/enabled/) {
1096 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1098 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1099 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1102 if ($$ref =~ m/enabled/) {
1103 $$ref .= ", \e[32;1m$extra\e[0m";
1105 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1111 for my $extra (sort {$a cmp $b} keys(%extras)) {
1112 my $text = $extras{$extra};
1113 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1114 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1116 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1119 return keys(%extras) if wantarray; # Can be used by manage_extras.
1122 sub enable_extras (@) {
1124 for my $extra (@extras) {
1125 my $extrapath = "src/modules/extra/$extra";
1126 if (!-e $extrapath) {
1127 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1130 my $source = "src/modules/$extra";
1132 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1135 # Get dependencies, and add them to be processed.
1136 my @deps = split / +/, getdependencies($extrapath);
1137 for my $dep (@deps) {
1138 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1139 if (!-e "src/modules/$dep" && !-e "include/$dep") {
1140 if (-e "src/modules/extra/$dep") {
1141 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1144 print STDERR "\e[33;1mWARNING:\e[0m module \e[32;1m$extra\e[0m might be missing dependency \e[32;1m$dep\e[0m - YOU are responsible for satisfying it!\n";
1148 print "Enabling $extra ... \n";
1149 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1153 sub disable_extras (@)
1155 opendir my $dd, "src/modules/extra/";
1156 my @files = readdir($dd);
1159 EXTRA: for my $extra (@extras) {
1160 my $extrapath = "src/modules/extra/$extra";
1161 my $source = "src/modules/$extra";
1162 if (!-e $extrapath) {
1163 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1166 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1167 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Source is not a link or doesn't refer to the right file. Remove manually if this is in error.\n";
1170 # Check if anything needs this.
1171 for my $file (@files) {
1172 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1173 # File depends on this extra...
1174 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1175 # And is both enabled and not about to be disabled.
1176 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1177 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1183 print "Disabling $extra ... \n";
1184 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";