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_cc, $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 'with-cc=s' => \$opt_cc,
83 'enable-freebsd-ports-openssl' => \$opt_freebsd_port,
84 'prefix=s' => \$opt_base_dir,
85 'config-dir=s' => \$opt_config_dir,
86 'module-dir=s' => \$opt_module_dir,
87 'binary-dir=s' => \$opt_binary_dir,
88 'data-dir=s' => \$opt_data_dir,
89 'log-dir=s' => \$opt_log_dir,
90 'help' => sub { showhelp(); },
91 'update' => sub { update(); },
92 'clean' => sub { clean(); },
93 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
94 'enable-extras=s@' => \@opt_enableextras, # ^
95 'disable-extras=s@' => \@opt_disableextras, # ^
98 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
99 @opt_enableextras = split /,/, join(',', @opt_enableextras);
100 @opt_disableextras = split /,/, join(',', @opt_disableextras);
101 enable_extras(@opt_enableextras);
102 disable_extras(@opt_disableextras);
104 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
108 our $interactive = !(
109 (defined $opt_base_dir) ||
110 (defined $opt_config_dir) ||
111 (defined $opt_module_dir) ||
112 (defined $opt_base_dir) ||
113 (defined $opt_binary_dir) ||
114 (defined $opt_data_dir) ||
115 (defined $opt_log_dir) ||
116 (defined $opt_nointeractive) ||
118 (defined $opt_kqueue) ||
119 (defined $opt_epoll) ||
120 (defined $opt_ports) ||
121 (defined $opt_use_openssl) ||
122 (defined $opt_nokqueue) ||
123 (defined $opt_noepoll) ||
124 (defined $opt_noports) ||
125 (defined $opt_system) ||
126 (defined $opt_uid) ||
127 (defined $opt_use_gnutls) ||
128 (defined $opt_freebsd_port)
131 chomp(our $topdir = getcwd());
132 our $this = resolve_directory($topdir); # PWD, Regardless.
133 our @modlist = (); # Declare for Module List..
134 our %config = (); # Initiate Configuration Hash..
135 our $cache_loaded = getcache();
136 $config{ME} = resolve_directory($topdir); # Present Working Directory
138 $config{BASE_DIR} = $config{ME}."/run";
140 if (defined $opt_base_dir) {
141 $config{BASE_DIR} = $opt_base_dir;
142 } elsif (defined $opt_system) {
143 $config{BASE_DIR} = '/var/lib/inspircd';
146 if (defined $opt_system) {
147 $config{UID} = $opt_uid || 'ircd';
148 $config{CONFIG_DIR} = '/etc/inspircd';
149 $config{MODULE_DIR} = '/usr/lib/inspircd';
150 $config{BINARY_DIR} = '/usr/sbin/';
151 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
152 $config{DATA_DIR} = '/var/inspircd';
153 $config{LOG_DIR} = '/var/log/inspircd';
155 $config{UID} = $opt_uid || $<;
156 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
157 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
158 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
159 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
160 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data directory
161 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log directory
164 if (defined $opt_config_dir) {
165 $config{CONFIG_DIR} = $opt_config_dir;
167 if (defined $opt_module_dir) {
168 $config{MODULE_DIR} = $opt_module_dir;
170 if (defined $opt_binary_dir) {
171 $config{BINARY_DIR} = $opt_binary_dir;
173 if (defined $opt_data_dir) {
174 $config{DATA_DIR} = $opt_data_dir;
176 if (defined $opt_log_dir) {
177 $config{LOG_DIR} = $opt_log_dir;
179 chomp($config{HAS_GNUTLS} = `pkg-config --modversion gnutls 2>/dev/null`); # GNUTLS Version.
181 if (defined $opt_freebsd_port)
183 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`);
184 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`);
185 $config{USE_FREEBSD_BASE_SSL} = "n";
189 if ($^O eq "freebsd")
191 # default: use base ssl
192 chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`); # OpenSSL version, freebsd specific
193 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`); # Port version, may be different
197 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version, others
198 $config{HAS_OPENSSL_PORT} = "";
202 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
203 chomp(our $openssl_ver = $config{HAS_OPENSSL});
204 $config{USE_GNUTLS} = "n";
205 if (defined $opt_use_gnutls)
207 $config{USE_GNUTLS} = "y"; # Use gnutls.
209 $config{USE_OPENSSL} = "n"; # Use openssl.
210 if (defined $opt_use_openssl)
212 $config{USE_OPENSSL} = "y";
215 $config{HAS_STDINT} = "false"; # stdint.h check
216 $config{USE_KQUEUE} = "y"; # kqueue enabled
217 if (defined $opt_nokqueue) {
218 $config{USE_KQUEUE} = "n";
220 $config{USE_POLL} = "y"; # poll enabled
221 $config{USE_EPOLL} = "y"; # epoll enabled
222 if (defined $opt_noepoll)
224 $config{USE_EPOLL} = "n";
226 $config{USE_PORTS} = "y"; # epoll enabled
227 if (defined $opt_noports)
229 $config{USE_PORTS} = "n";
231 $config{OSNAME} = $^O; # Operating System Name
232 $config{STARTSCRIPT} = "inspircd"; # start script?
233 $config{DESTINATION} = "BASE"; # Is target path.
234 if ($config{OSNAME} =~ /darwin/i)
236 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
237 $config{CC} = "xcrun clang++"; # C++ compiler for OSX.
241 $config{CC} = "g++"; # C++ compiler
245 $config{CC} = $opt_cc;
247 our $exec = $config{CC} . " -dumpversion | cut -c 1";
248 chomp($config{GCCVER} = `$exec`); # Major GCC Version
249 $exec = $config{CC} . " -dumpversion | cut -c 3";
250 chomp($config{GCCMINOR} = `$exec`);
252 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)(?:[a-z])?(?:\-[a-z][0-9])?/) {
253 $config{HAS_OPENSSL} = $1;
255 $config{HAS_OPENSSL} = "";
258 if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
259 if ($config{OSNAME} eq 'darwin') {
260 print $config{CC} . " was not found! You require clang++ (the LLVM C++ compiler, part of the OSX developer tools) to build InspIRCd!\n";
262 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
267 # Get and Set some important vars..
272 unlink(".config.cache");
275 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
280 chomp($topdir = getcwd());
281 $this = resolve_directory($topdir); # PWD, Regardless.
283 # Does the cache file exist?
285 # No, No it doesn't.. *BASH*
286 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
289 # We've Loaded the cache file and all our variables..
290 print "Updating files...\n";
291 $has_epoll = $config{HAS_EPOLL};
292 $has_ports = $config{HAS_PORTS};
293 $has_kqueue = $config{HAS_KQUEUE};
302 print "Configure update failed: $@\n";
307 print "Running non-interactive configure...\n" unless $interactive;
308 print "Checking for cache from previous configure... ";
309 print ($cache_loaded ? "found\n" : "not found\n");
310 $config{SYSTEM} = lc $^O;
311 print "Checking operating system version... $config{SYSTEM}\n";
313 $exec = $config{CC} . " -dumpversion | cut -c 1";
314 chomp($config{GCCVER} = `$exec`); # Major GCC Version
315 $exec = $config{CC} . " -dumpversion | cut -c 3";
316 chomp($config{GCCMINOR} = `$exec`);
319 print "Checking whether <stdint.h> exists... ";
320 if (test_header($config{CC}, "stdint.h")) {
321 $config{HAS_STDINT} = "true";
324 $config{HAS_STDINT} = "false";
328 printf "Checking whether clock_gettime() exists... ";
329 if (test_file($config{CC}, "clock_gettime.cpp", "-lrt")) {
330 $config{HAS_CLOCK_GETTIME} = "true";
333 $config{HAS_CLOCK_GETTIME} = "false";
337 printf "Checking whether eventfd() exists... ";
338 if (test_file($config{CC}, "eventfd.cpp")) {
339 $config{HAS_EVENTFD} = "true";
342 $config{HAS_EVENTFD} = "false";
346 printf "Checking if a TCP deferring mechanism is available... ";
347 if (test_file($config{CC}, "tcp_defer_accept.cpp")) {
348 $config{HAS_DEFER} = "TCP_DEFER_ACCEPT";
349 print "yes (TCP_DEFER_ACCEPT)\n";
350 } elsif (test_file($config{CC}, "so_acceptfilter.cpp")) {
351 $config{HAS_DEFER} = "SO_ACCEPTFILTER";
352 print "yes (SO_ACCEPTFILTER)\n";
354 $config{HAS_DEFER} = "false";
358 print "Checking whether epoll is available... ";
359 $has_epoll = test_header($config{CC}, "sys/epoll.h");
360 print $has_epoll ? "yes\n" : "no\n";
362 print "Checking whether Kqueue is available... ";
363 $has_kqueue = test_file($config{CC}, "kqueue.cpp");
364 print $has_kqueue ? "yes\n" : "no\n";
366 print 'Checking whether Solaris IOCP is available... ';
367 $has_ports = test_header($config{CC}, 'port.h');
368 print $has_ports ? "yes\n" : "no\n";
370 $config{HAS_EPOLL} = $has_epoll;
371 $config{HAS_KQUEUE} = $has_kqueue;
373 printf "Checking for libgnutls... ";
374 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
375 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
377 $config{HAS_GNUTLS} = "y";
380 $config{HAS_GNUTLS} = "n";
384 $config{HAS_GNUTLS} = "n";
387 printf "Checking for openssl... ";
388 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
389 if (defined($openssl_ver) && ($openssl_ver ne "")) {
391 $config{HAS_OPENSSL} = "y";
394 $config{HAS_OPENSSL} = "n";
398 $config{HAS_OPENSSL} = "n";
401 printf "Checking if you are running an ancient, unsupported OS... ";
402 if ($config{OSNAME} =~ /FreeBSD/i)
404 my $version = `uname -r`;
405 if ($version =~ /^4\./)
408 print "FreeBSD 4.x is no longer supported. By ANYONE.\n";
409 print "To build, you will need to add the following to CXXFLAGS:\n";
410 print "\t-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1\n";
414 print "no ($version)\n";
419 print "no ($config{OSNAME})\n";
422 ################################################################################
423 # BEGIN INTERACTIVE PART #
424 ################################################################################
429 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
432 my $rev = getrevision();
433 # Display Introduction Message..
435 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
436 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
438 *** If you are unsure of any of these values, leave it blank for ***
439 *** standard settings that will work, and your server will run ***
440 *** using them. Please consult your IRC network admin if in doubt. ***
442 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
443 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
444 dir, otherwise you won't have a config file!
446 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
447 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
450 print " (Non-SVN build)";
454 $config{CHANGE_COMPILER} = "n";
455 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";
457 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
458 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
459 should NOT be used. You should probably specify a newer compiler.\n\n";
460 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
461 if ($config{CHANGE_COMPILER} =~ /y/i) {
462 print "What command do you want to use to invoke your compiler?\n";
463 print "[\e[1;32m$config{CC}\e[0m] -> ";
464 chomp($config{CC} = <STDIN>);
465 if ($config{CC} eq "") {
468 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
470 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
471 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
472 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
473 if ($config{GCCVER} < 4 || $config{GCCVER} == 4 && $config{GCCMINOR} < 1) {
474 print "\e[1;32mGCC 4.1 and earlier WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
478 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
485 # Directory Settings..
486 my $tmpbase = $config{BASE_DIR};
487 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
488 if ($tmpbase ne $config{BASE_DIR}) {
489 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
490 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
491 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data Directory
492 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log Directory
493 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
496 dir_check("are the configuration files", "CONFIG_DIR");
497 dir_check("are the modules to be compiled to", "MODULE_DIR");
498 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
499 dir_check("are variable data files to be located in", "DATA_DIR");
500 dir_check("are the logs to be stored in", "LOG_DIR");
501 dir_check("do you want the build to take place", "BUILD_DIR");
503 my $chose_hiperf = 0;
505 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?");
507 if ($config{USE_KQUEUE} eq "y") {
512 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?");
514 if ($config{USE_EPOLL} eq "y") {
519 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?");
521 if ($config{USE_PORTS} eq "y") {
526 if (!$chose_hiperf) {
527 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?");
528 if ($config{USE_POLL} ne "y")
530 print "No high-performance socket engines are available, or you chose\n";
531 print "not to enable one. Defaulting to select() engine.\n\n";
535 $config{USE_FREEBSD_BASE_SSL} = "n";
536 $config{USE_FREEBSD_PORTS_SSL} = "n";
537 if ($config{HAS_OPENSSL_PORT} ne "")
539 $config{USE_FREEBSD_PORTS_SSL} = "y";
540 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
541 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";
542 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
544 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
546 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
548 # update to port version
549 $openssl_ver = $config{HAS_OPENSSL_PORT};
554 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
557 $config{USE_SSL} = "n";
558 $config{MODUPDATE} = 'n';
560 if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
562 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
563 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
565 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
566 if ($config{USE_SSL} eq "y")
568 if ($config{HAS_GNUTLS} eq "y")
570 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
571 if ($config{USE_GNUTLS} eq "y")
573 print "\nUsing GnuTLS SSL module.\n";
577 if ($config{HAS_OPENSSL} eq "y")
579 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
580 if ($config{USE_OPENSSL} eq "y")
582 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
589 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed and\n";
590 print "is in your path.\n\n";
593 yesno('MODUPDATE',"Would you like to check for updates to third-party modules?");
595 if ($config{MODUPDATE} eq "y") {
596 print "Checking for upgrades to extra and third party modules... ";
597 system "./modulemanager upgrade";
601 # We are on a POSIX system, we can enable POSIX extras without asking
602 symlink "extra/m_regex_posix.cpp", "src/modules/m_regex_posix.cpp";
606 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
608 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
611 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
613 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
618 $config{CERTGEN} ||= 'y';
619 yesno('CERTGEN',"Would you like generate SSL certificates now?") if ($interactive && ($config{USE_GNUTLS} eq "y" || $config{USE_OPENSSL} eq "y"));
621 if ($config{USE_GNUTLS} eq "y") {
622 unless (-r "src/modules/m_ssl_gnutls.cpp") {
623 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
624 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
626 if ($interactive && $config{CERTGEN} eq 'y')
628 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
629 print "SSL Certificates Not found, Generating.. \n\n
630 *************************************************************
631 * Generating the Private Key may take some time, go grab a *
632 * Coffee. Even better, to generate some more entropy if it *
633 * is taking a while, open another console and type du / a *
634 * few times and get that HD going :) Then answer the *
635 * Questions which follow. If you are unsure, just hit enter *
636 *************************************************************\n\n";
637 $failed = system "./tools/genssl gnutls";
639 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
641 print "\nCertificate generation complete, copying to config directory... ";
642 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
643 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
648 print "SSL Certificates found, skipping.\n\n";
653 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
657 if ($config{USE_OPENSSL} eq "y") {
658 unless (-r "src/modules/m_ssl_openssl.cpp") {
659 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
660 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
663 if ($interactive && $config{CERTGEN} eq 'y')
665 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
666 print "SSL Certificates Not found, Generating.. \n\n
667 *************************************************************
668 * Generating the certificates may take some time, go grab a *
669 * coffee, or something. *
670 *************************************************************\n\n";
671 system "./tools/genssl openssl";
672 print "\nCertificate generation complete, copying to config directory... ";
673 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
674 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
675 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
678 print "SSL Certificates found, skipping.\n\n"
683 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
686 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
687 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
695 print "To build your server with these settings, please run '\e[1;32mmake\e[0m' now.\n";
696 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
697 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
698 print "modules in your config. This configure script has added those modules to the\n";
699 print "build process. For more info please refer to:\n";
700 print "\e[1;32mhttp://wiki.inspircd.org/Installation_From_Tarball\e[0m\n";
702 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
703 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
704 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";
707 if ($config{GCCVER} < "3") {
709 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
710 GCC 2.x series compilers only had partial (read as broken) C++ support, and
711 your compile will most likely fail horribly! If you have any problems, do NOT
712 report them to the bugtracker or forums without first upgrading your compiler
713 to a newer 3.x or 4.x (or whatever is available currently) version.
717 ################################################################################
719 ################################################################################
721 # Retrieves the .config.cache file, and loads values into the main config hash.
722 open(CACHE, ".config.cache") or return 0;
725 # Ignore Blank lines, and comments..
728 my ($key, $value) = split("=", $_, 2);
729 $value =~ /^\"(.*)\"$/;
730 # Do something with data here!
738 # Dump the contents of %config
739 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
740 open(FILEHANDLE, ">.config.cache");
741 foreach my $key (keys %config) {
742 print FILEHANDLE "$key=\"$config{$key}\"\n";
748 my ($desc, $hash_key) = @_;
751 print "In what directory $desc?\n";
752 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
753 chomp(my $var = <STDIN>);
755 $var = $config{$hash_key};
757 if ($var =~ /^\~\/(.+)$/) {
758 # Convert it to a full path..
759 $var = resolve_directory($ENV{HOME} . "/" . $1);
761 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
763 # Assume relative Path was given.. fill in the rest.
764 $var = $this . "/$var";
767 $var = resolve_directory($var);
769 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
770 chomp(my $tmp = <STDIN>);
771 if (($tmp eq "") || ($tmp =~ /^y/i)) {
772 # Attempt to Create the Dir..
775 File::Path::mkpath($var, 0, 0777);
778 unless (defined($chk) && -d $var) {
779 print "Unable to create directory. ($var)\n\n";
784 # They said they don't want to create, and we can't install there.
790 # Target exists, but is not a directory.
791 print "File $var exists, but is not a directory.\n\n";
795 # Either Dir Exists, or was created fine.
796 $config{$hash_key} = $var;
804 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
807 my($writeheader) = @_;
808 # First File.. config.h
809 chomp(my $incos = `uname -n -s -r`);
810 chomp(my $version = `sh src/version.sh`);
811 chomp(my $revision2 = getrevision());
812 my $branch = "InspIRCd-0.0";
813 if ($version =~ /^(InspIRCd-[0-9]+\.[0-9]+)\.[0-9]+/)
817 if ($writeheader == 1)
819 print "Writing \e[1;32mconfig.h\e[0m\n";
820 open(FILEHANDLE, ">include/config.h.tmp");
821 print FILEHANDLE <<EOF;
822 /* Auto generated by configure, do not modify! */
825 #define BRANCH "$branch"
826 #define VERSION "$version"
827 #define REVISION "$revision2"
828 #define SYSTEM "$incos"
830 #define CONFIG_PATH "$config{CONFIG_DIR}"
831 #define DATA_PATH "$config{DATA_DIR}"
832 #define LOG_PATH "$config{LOG_DIR}"
833 #define MOD_PATH "$config{MODULE_DIR}"
836 print FILEHANDLE "#define MAXBUF 514\n";
838 if ($config{OSNAME} =~ /SunOS/i) {
839 print FILEHANDLE "#define IS_SOLARIS\n";
841 if ($config{OSNAME} =~ /MINGW32/i) {
842 print FILEHANDLE "#define IS_MINGW\n";
844 if ($config{GCCVER} >= 3) {
845 print FILEHANDLE "#define GCC3\n";
847 if ($config{HAS_STDINT} eq "true") {
848 print FILEHANDLE "#define HAS_STDINT\n";
850 if ($config{HAS_EVENTFD} eq 'true') {
851 print FILEHANDLE "#define HAS_EVENTFD\n";
853 if ($config{HAS_CLOCK_GETTIME} eq 'true') {
854 print FILEHANDLE "#define HAS_CLOCK_GETTIME\n";
857 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
858 print FILEHANDLE "#define USE_KQUEUE\n";
859 $config{SOCKETENGINE} = "socketengine_kqueue";
862 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
863 print FILEHANDLE "#define USE_EPOLL\n";
864 $config{SOCKETENGINE} = "socketengine_epoll";
867 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
868 print FILEHANDLE "#define USE_PORTS\n";
869 $config{SOCKETENGINE} = "socketengine_ports";
872 # user didn't choose either epoll or select for their OS.
873 # default them to USE_SELECT (ewwy puke puke)
875 print "no hi-perf, " . $config{USE_POLL};
876 if ($config{USE_POLL} eq "y")
878 print FILEHANDLE "#define USE_POLL\n";
879 $config{SOCKETENGINE} = "socketengine_poll";
883 print FILEHANDLE "#define USE_SELECT\n";
884 $config{SOCKETENGINE} = "socketengine_select";
888 if ($config{HAS_DEFER} eq "TCP_DEFER_ACCEPT") {
889 print FILEHANDLE "#define USE_TCP_DEFER_ACCEPT";
890 } elsif ($config{HAS_DEFER} eq "SO_ACCEPTFILTER") {
891 print FILEHANDLE "#define USE_SO_ACCEPTFILTER"
894 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n";
897 my $file = 'include/config.h';
899 open my $fh1, $file or $diff = 1;
900 open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
904 if (defined($line1) != defined($line2)) {
906 } elsif (!defined $line1) {
909 $diff = ($line1 ne $line2);
914 rename "$file.tmp", $file;
920 # Write all .in files.
923 my $exe = "inspircd";
925 # Do this once here, and cache it in the .*.inc files,
926 # rather than attempting to read src/version.sh from
927 # compiled code -- we might not have the source to hand.
928 # Fix for bug#177 by Brain.
930 chomp($version = `sh ./src/version.sh`);
931 chomp(my $revision = getrevision());
932 $version = "$version(r$revision)";
934 # We can actually parse any file starting with . and ending with .inc,
935 # but right now we only parse .inspircd.inc to form './inspircd'
936 prepare_dynamic_makefile();
938 my @dotfiles = qw(main.mk inspircd);
939 push @dotfiles, 'org.inspircd.plist' if $config{OSNAME} eq 'darwin';
941 foreach my $file (@dotfiles) {
942 open(FILEHANDLE, "make/template/$file") or die "Can't open make/template/$file: $!";
943 $_ = join '', <FILEHANDLE>;
946 $config{BUILD_DIR} ||= resolve_directory($config{ME}."/build");
949 CC SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR DATA_DIR UID
950 STARTSCRIPT DESTINATION SOCKETENGINE
952 s/\@$var\@/$config{$var}/g;
954 s/\@EXECUTABLE\@/$exe/ if defined $exe;
955 s/\@VERSION\@/$version/ if defined $version;
957 if ($file eq 'main.mk') {
958 print "Writing \e[1;32mGNUmakefile\e[0m ...\n";
961 s/\@IFDEF (\S+)/ifdef $1/g;
962 s/\@IFNDEF (\S+)/ifndef $1/g;
963 s/\@IFEQ (\S+) (\S+)/ifeq ($1,$2)/g;
964 s/\@ELSIFEQ (\S+) (\S+)/else ifeq ($1,$2)/g;
967 s/ *\@BSD_ONLY .*\n//g;
969 s/\@DO_EXPORT (.*)/export $1/g;
970 open MKF, '>GNUmakefile' or die "Can't write to GNUmakefile: $!";
974 print "Writing \e[1;32mBSDmakefile\e[0m ...\n";
976 s/\@IFDEF (\S+)/.if defined($1)/g;
977 s/\@IFNDEF (\S+)/.if !defined($1)/g;
978 s/\@IFEQ (\S+) (\S+)/.if $1 == $2/g;
979 s/\@ELSIFEQ (\S+) (\S+)/.elif $1 == $2/g;
983 s/ *\@GNU_ONLY .*\n//g;
985 $mk_tmp =~ s#\@DO_EXPORT (.*)#"MAKEENV += ".join ' ', map "$_='\${$_}'", split /\s/, $1#eg;
986 open MKF, '>BSDmakefile' or die "Can't write to BSDmakefile: $!";
990 print "Writing \e[1;32m$file\e[0m ...\n";
991 open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
997 chmod 0755, 'inspircd';
1003 for my $mod (@modlist) {
1004 getcompilerflags("src/modules/m_$mod.cpp");
1005 getlinkerflags("src/modules/m_$mod.cpp");
1009 sub prepare_dynamic_makefile
1015 $config{USE_EPOLL} = 0;
1019 $config{USE_KQUEUE} = 0;
1023 $config{USE_PORTS} = 0;
1027 # Routine to list out the extra/ modules that have been enabled.
1028 # Note: when getting any filenames out and comparing, it's important to lc it if the
1029 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1030 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1031 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1032 sub list_extras () {
1035 my $srcdir = File::Spec->catdir("src", "modules");
1036 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1039 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1040 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1043 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1044 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1047 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1049 EXTRA: for my $extra (@extras) {
1050 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1051 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1052 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1053 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1054 if (-l $abs_source) {
1055 # Symlink, is it in the right place?
1056 my $targ = readlink($abs_source);
1057 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1058 if ($abs_targ eq $abs_extra) {
1059 $extras{$extra} = "\e[32;1menabled\e[0m";
1061 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1063 } elsif (-e $abs_source) {
1064 my ($devext, $inoext) = stat($abs_extra);
1065 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1067 if ($devsrc == $devext && $inosrc == $inoext) {
1068 $extras{$extra} = "\e[32;1menabled\e[0m";
1070 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1073 open my $extfd, "<", $abs_extra;
1074 open my $srcfd, "<", $abs_source;
1076 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1077 $extras{$extra} = "\e[32;1menabled\e[0m";
1079 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1083 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1086 # Now let's add dependency info
1087 for my $extra (keys(%extras)) {
1088 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1089 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1090 my @deps = split / +/, getdependencies($abs_extra);
1091 for my $dep (@deps) {
1092 if (exists($extras{$dep})) {
1093 my $ref = \$extras{$dep}; # Take reference.
1094 if ($$ref !~ m/needed by/) {
1095 # First dependency found.
1096 if ($$ref =~ m/enabled/) {
1097 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1099 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1100 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1103 if ($$ref =~ m/enabled/) {
1104 $$ref .= ", \e[32;1m$extra\e[0m";
1106 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1112 for my $extra (sort {$a cmp $b} keys(%extras)) {
1113 my $text = $extras{$extra};
1114 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1115 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1117 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1120 return keys(%extras) if wantarray; # Can be used by manage_extras.
1123 sub enable_extras (@) {
1125 for my $extra (@extras) {
1126 my $extrapath = "src/modules/extra/$extra";
1127 if (!-e $extrapath) {
1128 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1131 my $source = "src/modules/$extra";
1133 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1136 # Get dependencies, and add them to be processed.
1137 my @deps = split / +/, getdependencies($extrapath);
1138 for my $dep (@deps) {
1139 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1140 if (!-e "src/modules/$dep") {
1141 if (-e "src/modules/extra/$dep") {
1142 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1145 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";
1149 print "Enabling $extra ... \n";
1150 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1154 sub disable_extras (@)
1156 opendir my $dd, "src/modules/extra/";
1157 my @files = readdir($dd);
1160 EXTRA: for my $extra (@extras) {
1161 my $extrapath = "src/modules/extra/$extra";
1162 my $source = "src/modules/$extra";
1163 if (!-e $extrapath) {
1164 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1167 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1168 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";
1171 # Check if anything needs this.
1172 for my $file (@files) {
1173 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1174 # File depends on this extra...
1175 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1176 # And is both enabled and not about to be disabled.
1177 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1178 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1184 print "Disabling $extra ... \n";
1185 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";