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_maxbuf, $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 'with-maxbuf=i' => \$opt_maxbuf,
84 'enable-freebsd-ports-openssl' => \$opt_freebsd_port,
85 'prefix=s' => \$opt_base_dir,
86 'config-dir=s' => \$opt_config_dir,
87 'module-dir=s' => \$opt_module_dir,
88 'binary-dir=s' => \$opt_binary_dir,
89 'data-dir=s' => \$opt_data_dir,
90 'log-dir=s' => \$opt_log_dir,
91 'help' => sub { showhelp(); },
92 'update' => sub { update(); },
93 'clean' => sub { clean(); },
94 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
95 'enable-extras=s@' => \@opt_enableextras, # ^
96 'disable-extras=s@' => \@opt_disableextras, # ^
99 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
100 @opt_enableextras = split /,/, join(',', @opt_enableextras);
101 @opt_disableextras = split /,/, join(',', @opt_disableextras);
102 enable_extras(@opt_enableextras);
103 disable_extras(@opt_disableextras);
105 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
109 our $interactive = !(
110 (defined $opt_base_dir) ||
111 (defined $opt_config_dir) ||
112 (defined $opt_module_dir) ||
113 (defined $opt_base_dir) ||
114 (defined $opt_binary_dir) ||
115 (defined $opt_data_dir) ||
116 (defined $opt_log_dir) ||
117 (defined $opt_nointeractive) ||
119 (defined $opt_kqueue) ||
120 (defined $opt_epoll) ||
121 (defined $opt_ports) ||
122 (defined $opt_use_openssl) ||
123 (defined $opt_nokqueue) ||
124 (defined $opt_noepoll) ||
125 (defined $opt_noports) ||
126 (defined $opt_maxbuf) ||
127 (defined $opt_system) ||
128 (defined $opt_uid) ||
129 (defined $opt_use_gnutls) ||
130 (defined $opt_freebsd_port)
133 chomp(our $topdir = getcwd());
134 our $this = resolve_directory($topdir); # PWD, Regardless.
135 our @modlist = (); # Declare for Module List..
136 our %config = (); # Initiate Configuration Hash..
137 our $cache_loaded = getcache();
138 $config{ME} = resolve_directory($topdir); # Present Working Directory
140 $config{BASE_DIR} = $config{ME}."/run";
142 if (defined $opt_base_dir) {
143 $config{BASE_DIR} = $opt_base_dir;
144 } elsif (defined $opt_system) {
145 $config{BASE_DIR} = '/var/lib/inspircd';
148 if (defined $opt_system) {
149 $config{UID} = $opt_uid || 'ircd';
150 $config{CONFIG_DIR} = '/etc/inspircd';
151 $config{MODULE_DIR} = '/usr/lib/inspircd';
152 $config{BINARY_DIR} = '/usr/sbin/';
153 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
154 $config{DATA_DIR} = '/var/inspircd';
155 $config{LOG_DIR} = '/var/log/inspircd';
157 $config{UID} = $opt_uid || $<;
158 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
159 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
160 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
161 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
162 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data directory
163 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log directory
166 if (defined $opt_config_dir) {
167 $config{CONFIG_DIR} = $opt_config_dir;
169 if (defined $opt_module_dir) {
170 $config{MODULE_DIR} = $opt_module_dir;
172 if (defined $opt_binary_dir) {
173 $config{BINARY_DIR} = $opt_binary_dir;
175 if (defined $opt_data_dir) {
176 $config{DATA_DIR} = $opt_data_dir;
178 if (defined $opt_log_dir) {
179 $config{LOG_DIR} = $opt_log_dir;
181 chomp($config{HAS_GNUTLS} = `pkg-config --modversion gnutls 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
183 if (defined $opt_freebsd_port)
185 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`);
186 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`);
187 $config{USE_FREEBSD_BASE_SSL} = "n";
191 if ($^O eq "freebsd")
193 # default: use base ssl
194 chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`); # OpenSSL version, freebsd specific
195 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`); # Port version, may be different
199 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version, others
200 $config{HAS_OPENSSL_PORT} = "";
204 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
205 chomp(our $openssl_ver = $config{HAS_OPENSSL});
206 $config{USE_GNUTLS} = "n";
207 if (defined $opt_use_gnutls)
209 $config{USE_GNUTLS} = "y"; # Use gnutls.
211 $config{USE_OPENSSL} = "n"; # Use openssl.
212 if (defined $opt_use_openssl)
214 $config{USE_OPENSSL} = "y";
217 $config{HAS_STDINT} = "false"; # stdint.h check
218 $config{USE_KQUEUE} = "y"; # kqueue enabled
219 if (defined $opt_nokqueue) {
220 $config{USE_KQUEUE} = "n";
222 $config{USE_POLL} = "y"; # poll enabled
223 $config{USE_EPOLL} = "y"; # epoll enabled
224 if (defined $opt_noepoll)
226 $config{USE_EPOLL} = "n";
228 $config{USE_PORTS} = "y"; # epoll enabled
229 if (defined $opt_noports)
231 $config{USE_PORTS} = "n";
233 $config{OSNAME} = $^O; # Operating System Name
234 $config{STARTSCRIPT} = "inspircd"; # start script?
235 $config{DESTINATION} = "BASE"; # Is target path.
236 if ($config{OSNAME} =~ /darwin/i)
238 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
239 $config{CC} = "xcrun clang++"; # C++ compiler for OSX.
243 $config{CC} = "g++"; # C++ compiler
247 $config{CC} = $opt_cc;
249 our $exec = $config{CC} . " -dumpversion | cut -c 1";
250 chomp($config{GCCVER} = `$exec`); # Major GCC Version
251 $exec = $config{CC} . " -dumpversion | cut -c 3";
252 chomp($config{GCCMINOR} = `$exec`);
253 $config{MAXBUF} = "512"; # Max buffer size
255 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)(?:[a-z])?(?:\-[a-z][0-9])?/) {
256 $config{HAS_OPENSSL} = $1;
258 $config{HAS_OPENSSL} = "";
261 if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
262 if ($config{OSNAME} eq 'darwin') {
263 print $config{CC} . " was not found! You require clang++ (the LLVM C++ compiler, part of the OSX developer tools) to build InspIRCd!\n";
265 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
270 # Get and Set some important vars..
275 unlink(".config.cache");
278 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
283 chomp($topdir = getcwd());
284 $this = resolve_directory($topdir); # PWD, Regardless.
286 # Does the cache file exist?
288 # No, No it doesn't.. *BASH*
289 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
292 # We've Loaded the cache file and all our variables..
293 print "Updating files...\n";
294 $has_epoll = $config{HAS_EPOLL};
295 $has_ports = $config{HAS_PORTS};
296 $has_kqueue = $config{HAS_KQUEUE};
305 print "Configure update failed: $@\n";
310 print "Running non-interactive configure...\n" unless $interactive;
311 print "Checking for cache from previous configure... ";
312 print ($cache_loaded ? "found\n" : "not found\n");
313 $config{SYSTEM} = lc $^O;
314 print "Checking operating system version... $config{SYSTEM}\n";
316 $exec = $config{CC} . " -dumpversion | cut -c 1";
317 chomp($config{GCCVER} = `$exec`); # Major GCC Version
318 $exec = $config{CC} . " -dumpversion | cut -c 3";
319 chomp($config{GCCMINOR} = `$exec`);
322 print "Checking whether <stdint.h> exists... ";
323 if (test_header($config{CC}, "stdint.h")) {
324 $config{HAS_STDINT} = "true";
327 $config{HAS_STDINT} = "false";
331 printf "Checking whether clock_gettime() exists... ";
332 if (test_file($config{CC}, "clock_gettime.cpp", "-lrt")) {
333 $config{HAS_CLOCK_GETTIME} = "true";
336 $config{HAS_CLOCK_GETTIME} = "false";
340 printf "Checking whether eventfd() exists... ";
341 if (test_file($config{CC}, "eventfd.cpp")) {
342 $config{HAS_EVENTFD} = "true";
345 $config{HAS_EVENTFD} = "false";
349 print "Checking whether epoll is available... ";
350 $has_epoll = test_header($config{CC}, "sys/epoll.h");
351 print $has_epoll ? "yes\n" : "no\n";
353 print "Checking whether Kqueue is available... ";
354 $has_kqueue = test_file($config{CC}, "kqueue.cpp");
355 print $has_kqueue ? "yes\n" : "no\n";
357 print 'Checking whether Solaris IOCP is available... ';
358 $has_ports = test_header($config{CC}, 'port.h');
359 print $has_ports ? "yes\n" : "no\n";
361 $config{HAS_EPOLL} = $has_epoll;
362 $config{HAS_KQUEUE} = $has_kqueue;
364 printf "Checking for libgnutls... ";
365 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
366 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
368 $config{HAS_GNUTLS} = "y";
371 $config{HAS_GNUTLS} = "n";
375 $config{HAS_GNUTLS} = "n";
378 printf "Checking for openssl... ";
379 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
380 if (defined($openssl_ver) && ($openssl_ver ne "")) {
382 $config{HAS_OPENSSL} = "y";
385 $config{HAS_OPENSSL} = "n";
389 $config{HAS_OPENSSL} = "n";
392 printf "Checking if you are running an ancient, unsupported OS... ";
393 if ($config{OSNAME} =~ /FreeBSD/i)
395 my $version = `uname -r`;
396 if ($version =~ /^4\./)
399 print "FreeBSD 4.x is no longer supported. By ANYONE.\n";
400 print "To build, you will need to add the following to CXXFLAGS:\n";
401 print "\t-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1\n";
405 print "no ($version)\n";
410 print "no ($config{OSNAME})\n";
413 ################################################################################
414 # BEGIN INTERACTIVE PART #
415 ################################################################################
420 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
423 my $rev = getrevision();
424 # Display Introduction Message..
426 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
427 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
429 *** If you are unsure of any of these values, leave it blank for ***
430 *** standard settings that will work, and your server will run ***
431 *** using them. Please consult your IRC network admin if in doubt. ***
433 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
434 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
435 dir, otherwise you won't have a config file!
437 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
438 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
441 print " (Non-SVN build)";
445 $config{CHANGE_COMPILER} = "n";
446 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";
448 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
449 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
450 should NOT be used. You should probably specify a newer compiler.\n\n";
451 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
452 if ($config{CHANGE_COMPILER} =~ /y/i) {
453 print "What command do you want to use to invoke your compiler?\n";
454 print "[\e[1;32m$config{CC}\e[0m] -> ";
455 chomp($config{CC} = <STDIN>);
456 if ($config{CC} eq "") {
459 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
461 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
462 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
463 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
464 if ($config{GCCVER} < 4 || $config{GCCVER} == 4 && $config{GCCMINOR} < 1) {
465 print "\e[1;32mGCC 4.1 and earlier WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
469 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
476 # Directory Settings..
477 my $tmpbase = $config{BASE_DIR};
478 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
479 if ($tmpbase ne $config{BASE_DIR}) {
480 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
481 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
482 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data Directory
483 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log Directory
484 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
487 dir_check("are the configuration files", "CONFIG_DIR");
488 dir_check("are the modules to be compiled to", "MODULE_DIR");
489 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
490 dir_check("are variable data files to be located in", "DATA_DIR");
491 dir_check("are the logs to be stored in", "LOG_DIR");
492 dir_check("do you want the build to take place", "BUILD_DIR");
494 my $chose_hiperf = 0;
496 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?");
498 if ($config{USE_KQUEUE} eq "y") {
503 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?");
505 if ($config{USE_EPOLL} eq "y") {
510 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?");
512 if ($config{USE_PORTS} eq "y") {
517 if (!$chose_hiperf) {
518 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?");
519 if ($config{USE_POLL} ne "y")
521 print "No high-performance socket engines are available, or you chose\n";
522 print "not to enable one. Defaulting to select() engine.\n\n";
526 $config{USE_FREEBSD_BASE_SSL} = "n";
527 $config{USE_FREEBSD_PORTS_SSL} = "n";
528 if ($config{HAS_OPENSSL_PORT} ne "")
530 $config{USE_FREEBSD_PORTS_SSL} = "y";
531 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
532 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";
533 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
535 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
537 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
539 # update to port version
540 $openssl_ver = $config{HAS_OPENSSL_PORT};
545 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
548 $config{USE_SSL} = "n";
549 $config{MODUPDATE} = 'n';
551 if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
553 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
554 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
556 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
557 if ($config{USE_SSL} eq "y")
559 if ($config{HAS_GNUTLS} eq "y")
561 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
562 if ($config{USE_GNUTLS} eq "y")
564 print "\nUsing GnuTLS SSL module.\n";
568 if ($config{HAS_OPENSSL} eq "y")
570 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
571 if ($config{USE_OPENSSL} eq "y")
573 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
580 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed and\n";
581 print "is in your path.\n\n";
584 yesno('MODUPDATE',"Would you like to check for updates to third-party modules?");
586 if ($config{MODUPDATE} eq "y") {
587 print "Checking for upgrades to extra and third party modules... ";
588 system "./modulemanager upgrade";
592 # We are on a POSIX system, we can enable POSIX extras without asking
593 symlink "extra/m_regex_posix.cpp", "src/modules/m_regex_posix.cpp";
597 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
599 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
602 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
604 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
609 $config{CERTGEN} ||= 'y';
610 yesno('CERTGEN',"Would you like generate SSL certificates now?") if ($interactive && ($config{USE_GNUTLS} eq "y" || $config{USE_OPENSSL} eq "y"));
612 if ($config{USE_GNUTLS} eq "y") {
613 unless (-r "src/modules/m_ssl_gnutls.cpp") {
614 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
615 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
617 if ($interactive && $config{CERTGEN} eq 'y')
619 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
620 print "SSL Certificates Not found, Generating.. \n\n
621 *************************************************************
622 * Generating the Private Key may take some time, go grab a *
623 * Coffee. Even better, to generate some more entropy if it *
624 * is taking a while, open another console and type du / a *
625 * few times and get that HD going :) Then answer the *
626 * Questions which follow. If you are unsure, just hit enter *
627 *************************************************************\n\n";
628 $failed = system "./tools/genssl gnutls";
630 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
632 print "\nCertificate generation complete, copying to config directory... ";
633 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
634 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
639 print "SSL Certificates found, skipping.\n\n";
644 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
648 if ($config{USE_OPENSSL} eq "y") {
649 unless (-r "src/modules/m_ssl_openssl.cpp") {
650 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
651 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
654 if ($interactive && $config{CERTGEN} eq 'y')
656 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
657 print "SSL Certificates Not found, Generating.. \n\n
658 *************************************************************
659 * Generating the certificates may take some time, go grab a *
660 * coffee, or something. *
661 *************************************************************\n\n";
662 system "./tools/genssl openssl";
663 print "\nCertificate generation complete, copying to config directory... ";
664 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
665 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
666 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
669 print "SSL Certificates found, skipping.\n\n"
674 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
677 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
678 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
686 print "To build your server with these settings, please run '\e[1;32mmake\e[0m' now.\n";
687 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
688 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
689 print "modules in your config. This configure script has added those modules to the\n";
690 print "build process. For more info please refer to:\n";
691 print "\e[1;32mhttp://wiki.inspircd.org/Installation_From_Tarball\e[0m\n";
693 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
694 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
695 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";
698 if ($config{GCCVER} < "3") {
700 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
701 GCC 2.x series compilers only had partial (read as broken) C++ support, and
702 your compile will most likely fail horribly! If you have any problems, do NOT
703 report them to the bugtracker or forums without first upgrading your compiler
704 to a newer 3.x or 4.x (or whatever is available currently) version.
708 ################################################################################
710 ################################################################################
712 # Retrieves the .config.cache file, and loads values into the main config hash.
713 open(CACHE, ".config.cache") or return 0;
716 # Ignore Blank lines, and comments..
719 my ($key, $value) = split("=", $_, 2);
720 $value =~ /^\"(.*)\"$/;
721 # Do something with data here!
729 # Dump the contents of %config
730 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
731 open(FILEHANDLE, ">.config.cache");
732 foreach my $key (keys %config) {
733 print FILEHANDLE "$key=\"$config{$key}\"\n";
739 my ($desc, $hash_key) = @_;
742 print "In what directory $desc?\n";
743 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
744 chomp(my $var = <STDIN>);
746 $var = $config{$hash_key};
748 if ($var =~ /^\~\/(.+)$/) {
749 # Convert it to a full path..
750 $var = resolve_directory($ENV{HOME} . "/" . $1);
752 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
754 # Assume relative Path was given.. fill in the rest.
755 $var = $this . "/$var";
758 $var = resolve_directory($var);
760 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
761 chomp(my $tmp = <STDIN>);
762 if (($tmp eq "") || ($tmp =~ /^y/i)) {
763 # Attempt to Create the Dir..
766 File::Path::mkpath($var, 0, 0777);
769 unless (defined($chk) && -d $var) {
770 print "Unable to create directory. ($var)\n\n";
775 # They said they don't want to create, and we can't install there.
781 # Target exists, but is not a directory.
782 print "File $var exists, but is not a directory.\n\n";
786 # Either Dir Exists, or was created fine.
787 $config{$hash_key} = $var;
795 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
798 my($writeheader) = @_;
799 # First File.. config.h
800 chomp(my $incos = `uname -n -s -r`);
801 chomp(my $version = `sh src/version.sh`);
802 chomp(my $revision2 = getrevision());
803 my $branch = "InspIRCd-0.0";
804 if ($version =~ /^(InspIRCd-[0-9]+\.[0-9]+)\.[0-9]+/)
808 if ($writeheader == 1)
810 print "Writing \e[1;32mconfig.h\e[0m\n";
811 open(FILEHANDLE, ">include/config.h.tmp");
812 print FILEHANDLE <<EOF;
813 /* Auto generated by configure, do not modify! */
816 #define BRANCH "$branch"
817 #define VERSION "$version"
818 #define REVISION "$revision2"
819 #define SYSTEM "$incos"
821 #define CONFIG_PATH "$config{CONFIG_DIR}"
822 #define DATA_PATH "$config{DATA_DIR}"
823 #define LOG_PATH "$config{LOG_DIR}"
824 #define MOD_PATH "$config{MODULE_DIR}"
827 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
829 if ($config{OSNAME} =~ /SunOS/i) {
830 print FILEHANDLE "#define IS_SOLARIS\n";
832 if ($config{OSNAME} =~ /MINGW32/i) {
833 print FILEHANDLE "#define IS_MINGW\n";
835 if ($config{GCCVER} >= 3) {
836 print FILEHANDLE "#define GCC3\n";
838 if ($config{HAS_STDINT} eq "true") {
839 print FILEHANDLE "#define HAS_STDINT\n";
841 if ($config{HAS_EVENTFD} eq 'true') {
842 print FILEHANDLE "#define HAS_EVENTFD\n";
844 if ($config{HAS_CLOCK_GETTIME} eq 'true') {
845 print FILEHANDLE "#define HAS_CLOCK_GETTIME\n";
848 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
849 print FILEHANDLE "#define USE_KQUEUE\n";
850 $config{SOCKETENGINE} = "socketengine_kqueue";
853 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
854 print FILEHANDLE "#define USE_EPOLL\n";
855 $config{SOCKETENGINE} = "socketengine_epoll";
858 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
859 print FILEHANDLE "#define USE_PORTS\n";
860 $config{SOCKETENGINE} = "socketengine_ports";
863 # user didn't choose either epoll or select for their OS.
864 # default them to USE_SELECT (ewwy puke puke)
866 print "no hi-perf, " . $config{USE_POLL};
867 if ($config{USE_POLL} eq "y")
869 print FILEHANDLE "#define USE_POLL\n";
870 $config{SOCKETENGINE} = "socketengine_poll";
874 print FILEHANDLE "#define USE_SELECT\n";
875 $config{SOCKETENGINE} = "socketengine_select";
878 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n";
881 my $file = 'include/config.h';
883 open my $fh1, $file or $diff = 1;
884 open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
888 if (defined($line1) != defined($line2)) {
890 } elsif (!defined $line1) {
893 $diff = ($line1 ne $line2);
898 rename "$file.tmp", $file;
904 # Write all .in files.
907 my $exe = "inspircd";
909 # Do this once here, and cache it in the .*.inc files,
910 # rather than attempting to read src/version.sh from
911 # compiled code -- we might not have the source to hand.
912 # Fix for bug#177 by Brain.
914 chomp($version = `sh ./src/version.sh`);
915 chomp(my $revision = getrevision());
916 $version = "$version(r$revision)";
918 # We can actually parse any file starting with . and ending with .inc,
919 # but right now we only parse .inspircd.inc to form './inspircd'
920 prepare_dynamic_makefile();
922 my @dotfiles = qw(main.mk inspircd);
923 push @dotfiles, 'org.inspircd.plist' if $config{OSNAME} eq 'darwin';
925 foreach my $file (@dotfiles) {
926 open(FILEHANDLE, "make/template/$file") or die "Can't open make/template/$file: $!";
927 $_ = join '', <FILEHANDLE>;
930 $config{BUILD_DIR} ||= resolve_directory($config{ME}."/build");
933 CC SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR DATA_DIR UID
934 STARTSCRIPT DESTINATION SOCKETENGINE
936 s/\@$var\@/$config{$var}/g;
938 s/\@EXECUTABLE\@/$exe/ if defined $exe;
939 s/\@VERSION\@/$version/ if defined $version;
941 if ($file eq 'main.mk') {
942 print "Writing \e[1;32mGNUmakefile\e[0m ...\n";
945 s/\@IFDEF (\S+)/ifdef $1/g;
946 s/\@IFNDEF (\S+)/ifndef $1/g;
947 s/\@IFEQ (\S+) (\S+)/ifeq ($1,$2)/g;
948 s/\@ELSIFEQ (\S+) (\S+)/else ifeq ($1,$2)/g;
951 s/ *\@BSD_ONLY .*\n//g;
953 s/\@DO_EXPORT (.*)/export $1/g;
954 open MKF, '>GNUmakefile' or die "Can't write to GNUmakefile: $!";
958 print "Writing \e[1;32mBSDmakefile\e[0m ...\n";
960 s/\@IFDEF (\S+)/.if defined($1)/g;
961 s/\@IFNDEF (\S+)/.if !defined($1)/g;
962 s/\@IFEQ (\S+) (\S+)/.if $1 == $2/g;
963 s/\@ELSIFEQ (\S+) (\S+)/.elif $1 == $2/g;
967 s/ *\@GNU_ONLY .*\n//g;
969 $mk_tmp =~ s#\@DO_EXPORT (.*)#"MAKEENV += ".join ' ', map "$_='\${$_}'", split /\s/, $1#eg;
970 open MKF, '>BSDmakefile' or die "Can't write to BSDmakefile: $!";
974 print "Writing \e[1;32m$file\e[0m ...\n";
975 open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
981 chmod 0755, 'inspircd';
987 for my $mod (@modlist) {
988 getcompilerflags("src/modules/m_$mod.cpp");
989 getlinkerflags("src/modules/m_$mod.cpp");
993 sub prepare_dynamic_makefile
999 $config{USE_EPOLL} = 0;
1003 $config{USE_KQUEUE} = 0;
1007 $config{USE_PORTS} = 0;
1011 # Routine to list out the extra/ modules that have been enabled.
1012 # Note: when getting any filenames out and comparing, it's important to lc it if the
1013 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1014 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1015 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1016 sub list_extras () {
1019 my $srcdir = File::Spec->catdir("src", "modules");
1020 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1023 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1024 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1027 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1028 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1031 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1033 EXTRA: for my $extra (@extras) {
1034 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1035 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1036 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1037 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1038 if (-l $abs_source) {
1039 # Symlink, is it in the right place?
1040 my $targ = readlink($abs_source);
1041 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1042 if ($abs_targ eq $abs_extra) {
1043 $extras{$extra} = "\e[32;1menabled\e[0m";
1045 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1047 } elsif (-e $abs_source) {
1048 my ($devext, $inoext) = stat($abs_extra);
1049 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1051 if ($devsrc == $devext && $inosrc == $inoext) {
1052 $extras{$extra} = "\e[32;1menabled\e[0m";
1054 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1057 open my $extfd, "<", $abs_extra;
1058 open my $srcfd, "<", $abs_source;
1060 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1061 $extras{$extra} = "\e[32;1menabled\e[0m";
1063 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1067 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1070 # Now let's add dependency info
1071 for my $extra (keys(%extras)) {
1072 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1073 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1074 my @deps = split / +/, getdependencies($abs_extra);
1075 for my $dep (@deps) {
1076 if (exists($extras{$dep})) {
1077 my $ref = \$extras{$dep}; # Take reference.
1078 if ($$ref !~ m/needed by/) {
1079 # First dependency found.
1080 if ($$ref =~ m/enabled/) {
1081 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1083 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1084 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1087 if ($$ref =~ m/enabled/) {
1088 $$ref .= ", \e[32;1m$extra\e[0m";
1090 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1096 for my $extra (sort {$a cmp $b} keys(%extras)) {
1097 my $text = $extras{$extra};
1098 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1099 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1101 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1104 return keys(%extras) if wantarray; # Can be used by manage_extras.
1107 sub enable_extras (@) {
1109 for my $extra (@extras) {
1110 my $extrapath = "src/modules/extra/$extra";
1111 if (!-e $extrapath) {
1112 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1115 my $source = "src/modules/$extra";
1117 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1120 # Get dependencies, and add them to be processed.
1121 my @deps = split / +/, getdependencies($extrapath);
1122 for my $dep (@deps) {
1123 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1124 if (!-e "src/modules/$dep") {
1125 if (-e "src/modules/extra/$dep") {
1126 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1129 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";
1133 print "Enabling $extra ... \n";
1134 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1138 sub disable_extras (@)
1140 opendir my $dd, "src/modules/extra/";
1141 my @files = readdir($dd);
1144 EXTRA: for my $extra (@extras) {
1145 my $extrapath = "src/modules/extra/$extra";
1146 my $source = "src/modules/$extra";
1147 if (!-e $extrapath) {
1148 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1151 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1152 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";
1155 # Check if anything needs this.
1156 for my $file (@files) {
1157 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1158 # File depends on this extra...
1159 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1160 # And is both enabled and not about to be disabled.
1161 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1162 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1168 print "Disabling $extra ... \n";
1169 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";