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;
47 # Utility functions for our buildsystem
51 use make::opensslcert;
53 ###############################################################################################
55 # NON-EDITABLE VARIABLES
57 ###############################################################################################
59 our ($opt_use_gnutls, $opt_rebuild, $opt_use_openssl, $opt_nointeractive, $opt_ports,
60 $opt_epoll, $opt_kqueue, $opt_noports, $opt_noepoll, $opt_nokqueue,
61 $opt_noipv6, $opt_maxbuf, $opt_disable_debug, $opt_freebsd_port,
62 $opt_system, $opt_uid);
64 our ($opt_cc, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir, $opt_data_dir, $opt_log_dir);
68 sub enable_extras (@);
70 sub disable_extras (@);
73 my @opt_disableextras;
76 'enable-gnutls' => \$opt_use_gnutls,
77 'rebuild' => \$opt_rebuild,
78 'system' => \$opt_system,
80 'enable-openssl' => \$opt_use_openssl,
81 'disable-interactive' => \$opt_nointeractive,
82 'enable-ports' => \$opt_ports,
83 'enable-epoll' => \$opt_epoll,
84 'enable-kqueue' => \$opt_kqueue,
85 'disable-ports' => \$opt_noports,
86 'disable-epoll' => \$opt_noepoll,
87 'disable-kqueue' => \$opt_nokqueue,
88 'disable-ipv6' => \$opt_noipv6,
89 'with-cc=s' => \$opt_cc,
90 'with-maxbuf=i' => \$opt_maxbuf,
91 'enable-freebsd-ports-openssl' => \$opt_freebsd_port,
92 'prefix=s' => \$opt_base_dir,
93 'config-dir=s' => \$opt_config_dir,
94 'module-dir=s' => \$opt_module_dir,
95 'binary-dir=s' => \$opt_binary_dir,
96 'data-dir=s' => \$opt_data_dir,
97 'log-dir=s' => \$opt_log_dir,
98 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
99 'help' => sub { showhelp(); },
100 'update' => sub { update(); },
101 'clean' => sub { clean(); },
102 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
103 'enable-extras=s@' => \@opt_enableextras, # ^
104 'disable-extras=s@' => \@opt_disableextras, # ^
105 'generate-openssl-cert' => sub { make_openssl_cert(); exit(0); },
106 'generate-gnutls-cert' => sub { make_gnutls_cert(); exit(0); }
109 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
110 @opt_enableextras = split /,/, join(',', @opt_enableextras);
111 @opt_disableextras = split /,/, join(',', @opt_disableextras);
112 enable_extras(@opt_enableextras);
113 disable_extras(@opt_disableextras);
115 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
119 our $interactive = !(
120 (defined $opt_base_dir) ||
121 (defined $opt_config_dir) ||
122 (defined $opt_module_dir) ||
123 (defined $opt_base_dir) ||
124 (defined $opt_binary_dir) ||
125 (defined $opt_data_dir) ||
126 (defined $opt_log_dir) ||
127 (defined $opt_nointeractive) ||
129 (defined $opt_noipv6) ||
130 (defined $opt_kqueue) ||
131 (defined $opt_epoll) ||
132 (defined $opt_ports) ||
133 (defined $opt_use_openssl) ||
134 (defined $opt_nokqueue) ||
135 (defined $opt_noepoll) ||
136 (defined $opt_noports) ||
137 (defined $opt_maxbuf) ||
138 (defined $opt_system) ||
139 (defined $opt_uid) ||
140 (defined $opt_use_gnutls) ||
141 (defined $opt_freebsd_port)
144 chomp(our $topdir = getcwd());
145 our $this = resolve_directory($topdir); # PWD, Regardless.
146 our @modlist = (); # Declare for Module List..
147 our %config = (); # Initiate Configuration Hash..
148 our $cache_loaded = getcache();
149 $config{ME} = resolve_directory($topdir); # Present Working Directory
151 $config{BASE_DIR} = $config{ME}."/run";
153 if (defined $opt_base_dir) {
154 $config{BASE_DIR} = $opt_base_dir;
155 } elsif (defined $opt_system) {
156 $config{BASE_DIR} = '/var/lib/inspircd';
159 if (defined $opt_system) {
160 $config{UID} = $opt_uid || 'ircd';
161 $config{CONFIG_DIR} = '/etc/inspircd';
162 $config{MODULE_DIR} = '/usr/lib/inspircd';
163 $config{BINARY_DIR} = '/usr/sbin/';
164 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
165 $config{DATA_DIR} = '/var/inspircd';
166 $config{LOG_DIR} = '/var/log/inspircd';
168 $config{UID} = $opt_uid || $<;
169 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
170 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
171 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
172 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
173 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data directory
174 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log directory
177 if (defined $opt_config_dir) {
178 $config{CONFIG_DIR} = $opt_config_dir;
180 if (defined $opt_module_dir) {
181 $config{MODULE_DIR} = $opt_module_dir;
183 if (defined $opt_binary_dir) {
184 $config{BINARY_DIR} = $opt_binary_dir;
186 if (defined $opt_data_dir) {
187 $config{DATA_DIR} = $opt_data_dir;
189 if (defined $opt_log_dir) {
190 $config{LOG_DIR} = $opt_log_dir;
192 chomp($config{HAS_GNUTLS} = `pkg-config --modversion gnutls 2>/dev/null`); # GNUTLS Version.
194 if (defined $opt_freebsd_port)
196 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`);
197 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`);
198 $config{USE_FREEBSD_BASE_SSL} = "n";
202 if ($^O eq "freebsd")
204 # default: use base ssl
205 chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`); # OpenSSL version, freebsd specific
206 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`); # Port version, may be different
210 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version, others
211 $config{HAS_OPENSSL_PORT} = "";
212 $config{USE_FREEBSD_BASE_SSL} = "n";
216 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
217 chomp(our $openssl_ver = $config{HAS_OPENSSL});
218 $config{USE_GNUTLS} = "n";
219 if (defined $opt_use_gnutls)
221 $config{USE_GNUTLS} = "y"; # Use gnutls.
223 $config{USE_OPENSSL} = "n"; # Use openssl.
224 if (defined $opt_use_openssl)
226 $config{USE_OPENSSL} = "y";
229 if (!defined $opt_disable_debug) {
230 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
232 $config{OPTIMISATI} = "-O2";
235 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
236 $config{HAS_STDINT} = "false"; # stdint.h check
237 $config{USE_KQUEUE} = "y"; # kqueue enabled
238 if (defined $opt_nokqueue) {
239 $config{USE_KQUEUE} = "n";
241 $config{USE_POLL} = "y"; # poll enabled
242 $config{USE_EPOLL} = "y"; # epoll enabled
243 if (defined $opt_noepoll)
245 $config{USE_EPOLL} = "n";
247 $config{USE_PORTS} = "y"; # epoll enabled
248 if (defined $opt_noports)
250 $config{USE_PORTS} = "n";
252 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
253 $config{OSNAME} = $^O; # Operating System Name
254 $config{IS_DARWIN} = "NO"; # Is OSX?
255 $config{STARTSCRIPT} = "inspircd"; # start script?
256 $config{DESTINATION} = "BASE"; # Is target path.
257 if ($config{OSNAME} =~ /darwin/i)
259 $config{IS_DARWIN} = "YES";
260 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
261 $config{CC} = "xcrun clang++"; # C++ compiler for OSX.
263 elsif ($config{OSNAME} =~ /freebsd/i)
265 chomp(my $fbsd_version = `uname -r`);
266 $config{CC} = $fbsd_version ge '10.0' ? 'clang++' : 'g++';
270 $config{CC} = "g++"; # C++ compiler
274 $config{CC} = $opt_cc;
276 our $exec = $config{CC} . " -dumpversion | cut -c 1";
277 chomp($config{GCCVER} = `$exec`); # Major GCC Version
278 $exec = $config{CC} . " -dumpversion | cut -c 3";
279 chomp($config{GCCMINOR} = `$exec`);
280 $config{MAXBUF} = "512"; # Max buffer size
282 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)(?:[a-z])?(?:\-[a-z][0-9])?/) {
283 $config{HAS_OPENSSL} = $1;
285 $config{HAS_OPENSSL} = "";
288 if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
289 print "`$config{CC}` was not found! A C++ compiler is required to build InspIRCd!\n";
290 print "You can pass a custom compiler to $0 using --with-cc=[name].\n";
294 # Get and Set some important vars..
299 unlink(".config.cache");
302 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
307 chomp($topdir = getcwd());
308 $this = resolve_directory($topdir); # PWD, Regardless.
310 # Does the cache file exist?
312 # No, No it doesn't.. *BASH*
313 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
316 # We've Loaded the cache file and all our variables..
317 print "Updating files...\n";
318 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
320 print "Disabling debug information (-g).\n";
321 $config{OPTIMISATI} = "";
323 $has_epoll = $config{HAS_EPOLL};
324 $has_ports = $config{HAS_PORTS};
325 $has_kqueue = $config{HAS_KQUEUE};
334 print "Configure update failed: $@\n";
343 $fail ||= system "$config{CC} -o test_$feature make/check_$feature.cpp >/dev/null 2>&1";
344 $fail ||= system "./test_$feature";
345 unlink "test_$feature";
349 print "Running non-interactive configure...\n" unless $interactive;
350 print "Checking for cache from previous configure... ";
351 print ($cache_loaded ? "found\n" : "not found\n");
352 $config{SYSTEM} = lc $^O;
353 print "Checking operating system version... $config{SYSTEM}\n";
355 $exec = $config{CC} . " -dumpversion | cut -c 1";
356 chomp($config{GCCVER} = `$exec`); # Major GCC Version
357 $exec = $config{CC} . " -dumpversion | cut -c 3";
358 chomp($config{GCCMINOR} = `$exec`);
360 printf "Checking if stdint.h exists... ";
361 $config{HAS_STDINT} = "true";
363 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
364 if ($config{HAS_STDINT} eq "true") {
367 print "yes\n" if $config{HAS_STDINT} eq "true";
368 print "no\n" if $config{HAS_STDINT} eq "false";
370 printf "Checking if strlcpy exists... ";
371 # Perform the strlcpy() test..
372 $config{HAS_STRLCPY} = "false";
374 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
376 while (defined(my $line = <STRLCPY>)) {
378 # try and find the delcaration of:
379 # size_t strlcpy(...)
380 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
381 $config{HAS_STRLCPY} = "true";
386 print "yes\n" if $config{HAS_STRLCPY} eq "true";
387 print "no\n" if $config{HAS_STRLCPY} eq "false";
389 printf "Checking if kqueue exists... ";
392 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
394 while (defined(my $line = <KQUEUE>)) {
396 # try and find the delcaration of:
398 if ($line =~ /int(\0x9|\s)+kqueue/) {
404 print "yes\n" if $has_kqueue == 1;
405 print "no\n" if $has_kqueue == 0;
407 printf "Checking for epoll support... ";
408 $has_epoll = test_compile('epoll');
409 print $has_epoll ? "yes\n" : "no\n";
411 printf "Checking for eventfd support... ";
412 $config{HAS_EVENTFD} = test_compile('eventfd') ? 'true' : 'false';
413 print $config{HAS_EVENTFD} eq 'true' ? "yes\n" : "no\n";
415 printf "Checking if Solaris I/O completion ports are available... ";
417 our $system = `uname -s`;
419 $has_ports = 1 if ($system eq "SunOS");
422 my $kernel = `uname -r`;
424 if (($kernel !~ /^5\.1./)) {
428 print "yes\n" if $has_ports == 1;
429 print "no\n" if $has_ports == 0;
431 $config{HAS_EPOLL} = $has_epoll;
432 $config{HAS_KQUEUE} = $has_kqueue;
434 printf "Checking for libgnutls... ";
435 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
436 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
438 $config{HAS_GNUTLS} = "y";
441 $config{HAS_GNUTLS} = "n";
445 $config{HAS_GNUTLS} = "n";
448 printf "Checking for openssl... ";
449 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
450 if (defined($openssl_ver) && ($openssl_ver ne "")) {
452 $config{HAS_OPENSSL} = "y";
455 $config{HAS_OPENSSL} = "n";
459 $config{HAS_OPENSSL} = "n";
462 printf "Checking if you are running an ancient, unsupported OS... ";
463 if ($config{OSNAME} =~ /FreeBSD/i)
465 my $version = `uname -r`;
466 if ($version =~ /^4\./)
469 print "FreeBSD 4.x is no longer supported. By ANYONE.\n";
470 print "To build, you will need to add the following to CXXFLAGS:\n";
471 print "\t-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1\n";
475 print "no ($version)\n";
480 print "no ($config{OSNAME})\n";
483 ################################################################################
484 # BEGIN INTERACTIVE PART #
485 ################################################################################
490 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
493 my $rev = getrevision();
494 # Display Introduction Message..
496 Welcome to the \e[1mInspIRCd\e[0m configuration program! (\e[1minteractive mode\e[0m)
497 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
499 *** If you are unsure of any of these values, leave it blank for ***
500 *** standard settings that will work, and your server will run ***
501 *** using them. Please consult your IRC network admin if in doubt. ***
503 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
504 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
505 dir, otherwise you won't have a config file!
507 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
508 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
511 print " (Non-SVN build)";
515 $config{CHANGE_COMPILER} = "n";
516 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";
518 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
519 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
520 should NOT be used. You should probably specify a newer compiler.\n\n";
521 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
522 if ($config{CHANGE_COMPILER} =~ /y/i) {
523 print "What command do you want to use to invoke your compiler?\n";
524 print "[\e[1;32m$config{CC}\e[0m] -> ";
525 chomp($config{CC} = <STDIN>);
526 if ($config{CC} eq "") {
529 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
531 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
532 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
533 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
534 if ($config{GCCVER} < 3) {
535 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
539 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
546 # Directory Settings..
547 my $tmpbase = $config{BASE_DIR};
548 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
549 if ($tmpbase ne $config{BASE_DIR}) {
550 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
551 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
552 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data Directory
553 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log Directory
554 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
557 dir_check("are the configuration files", "CONFIG_DIR");
558 dir_check("are the modules to be compiled to", "MODULE_DIR");
559 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
560 dir_check("are variable data files to be located in", "DATA_DIR");
561 dir_check("are the logs to be stored in", "LOG_DIR");
562 dir_check("do you want the build to take place", "BUILD_DIR");
564 my $chose_hiperf = 0;
566 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?");
568 if ($config{USE_KQUEUE} eq "y") {
573 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?");
575 if ($config{USE_EPOLL} eq "y") {
580 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?");
582 if ($config{USE_PORTS} eq "y") {
587 if (!$chose_hiperf) {
588 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?");
589 if ($config{USE_POLL} ne "y")
591 print "No high-performance socket engines are available, or you chose\n";
592 print "not to enable one. Defaulting to select() engine.\n\n";
596 $config{USE_FREEBSD_BASE_SSL} = "n";
597 $config{USE_FREEBSD_PORTS_SSL} = "n";
598 if ($config{HAS_OPENSSL_PORT} ne "")
600 $config{USE_FREEBSD_PORTS_SSL} = "y";
601 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
602 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";
603 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
605 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
607 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
609 # update to port version
610 $openssl_ver = $config{HAS_OPENSSL_PORT};
615 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
618 $config{USE_SSL} = "n";
619 $config{MODUPDATE} = 'n';
621 if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
623 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
624 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
626 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
627 if ($config{USE_SSL} eq "y")
629 if ($config{HAS_GNUTLS} eq "y")
631 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
632 if ($config{USE_GNUTLS} eq "y")
634 print "\nUsing GnuTLS SSL module.\n";
638 if ($config{HAS_OPENSSL} eq "y")
640 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
641 if ($config{USE_OPENSSL} eq "y")
643 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
650 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed and\n";
651 print "is in your path.\n\n";
654 yesno('MODUPDATE',"Would you like to check for updates to third-party modules?");
656 if ($config{MODUPDATE} eq "y") {
657 print "Checking for upgrades to extra and third-party modules... ";
658 system "./modulemanager upgrade";
662 # We are on a POSIX system, we can enable POSIX extras without asking
663 symlink "extra/m_regex_posix.cpp", "src/modules/m_regex_posix.cpp";
667 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
669 print "Sorry, but I couldn't detect GnuTLS. Make sure gnutls-config is in your path.\n";
672 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
674 print "Sorry, but I couldn't detect OpenSSL. Make sure openssl is in your path.\n";
679 $config{CERTGEN} ||= 'y';
680 yesno('CERTGEN',"Would you like to generate SSL certificates now?") if ($interactive && ($config{USE_GNUTLS} eq "y" || $config{USE_OPENSSL} eq "y"));
682 if ($config{USE_GNUTLS} eq "y") {
683 unless (-r "src/modules/m_ssl_gnutls.cpp") {
684 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
685 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
687 if ($interactive && $config{CERTGEN} eq 'y')
689 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
690 print "SSL certificates not found, generating.. \n\n
691 *************************************************************
692 * Generating the private key may take some time, once done, *
693 * answer the questions which follow. If you are unsure, *
695 *************************************************************\n\n";
696 $failed = make_gnutls_cert();
698 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
700 print "\nCertificate generation complete, copying to config directory... ";
701 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
702 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
707 print "SSL certificates found, skipping.\n\n";
712 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
716 if ($config{USE_OPENSSL} eq "y") {
717 unless (-r "src/modules/m_ssl_openssl.cpp") {
718 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
719 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
722 if ($interactive && $config{CERTGEN} eq 'y')
724 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
725 print "SSL certificates not found, generating.. \n\n
726 *************************************************************
727 * Generating the certificates may take some time, go grab a *
728 * coffee or something. *
729 *************************************************************\n\n";
731 print "\nCertificate generation complete, copying to config directory... ";
732 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
733 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
734 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
737 print "SSL certificates found, skipping.\n\n"
742 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
745 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
746 print "Skipping SSL certificate generation as SSL support is not available.\n\n";
754 print "To build your server with these settings, please run '\e[1;32mmake\e[0m' now.\n";
755 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
756 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
757 print "modules in your config. This configure script has added those modules to the\n";
758 print "build process. For more info, please refer to:\n";
759 print "\e[1;32mhttp://wiki.inspircd.org/Installation_From_Tarball\e[0m\n";
761 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
762 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
763 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";
766 if ($config{GCCVER} < "3") {
768 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
769 GCC 2.x series compilers only had partial (read as broken) C++ support, and
770 your compile will most likely fail horribly! If you have any problems, do NOT
771 report them to the bugtracker or forums without first upgrading your compiler
772 to a newer 3.x or 4.x (or whatever is available currently) version.
776 ################################################################################
778 ################################################################################
780 # Retrieves the .config.cache file, and loads values into the main config hash.
781 open(CACHE, ".config.cache") or return 0;
784 # Ignore Blank lines, and comments..
787 my ($key, $value) = split("=", $_, 2);
788 $value =~ /^\"(.*)\"$/;
789 # Do something with data here!
797 # Dump the contents of %config
798 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
799 open(FILEHANDLE, ">.config.cache");
800 foreach my $key (keys %config) {
801 print FILEHANDLE "$key=\"$config{$key}\"\n";
807 my ($desc, $hash_key) = @_;
810 print "In what directory $desc?\n";
811 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
812 chomp(my $var = <STDIN>);
814 $var = $config{$hash_key};
816 if ($var =~ /^\~\/(.+)$/) {
817 # Convert it to a full path..
818 $var = resolve_directory($ENV{HOME} . "/" . $1);
820 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
822 # Assume relative Path was given.. fill in the rest.
823 $var = $this . "/$var";
826 $var = resolve_directory($var);
828 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
829 chomp(my $tmp = <STDIN>);
830 if (($tmp eq "") || ($tmp =~ /^y/i)) {
831 # Attempt to Create the Dir..
834 File::Path::mkpath($var, 0, 0777);
837 unless (defined($chk) && -d $var) {
838 print "Unable to create directory. ($var)\n\n";
843 # They said they don't want to create, and we can't install there.
849 # Target exists, but is not a directory.
850 print "File $var exists, but is not a directory.\n\n";
854 # Either Dir Exists, or was created fine.
855 $config{$hash_key} = $var;
863 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
866 my($writeheader) = @_;
867 # First File.. inspircd_config.h
868 chomp(my $incos = `uname -n -s -r`);
869 chomp(my $version = `sh src/version.sh`);
870 chomp(my $revision2 = getrevision());
871 my $branch = "InspIRCd-0.0";
872 if ($version =~ /^(InspIRCd-[0-9]+\.[0-9]+)\.[0-9]+/)
876 if ($writeheader == 1)
878 print "Writing \e[1;32minspircd_config.h\e[0m\n";
879 open(FILEHANDLE, ">include/inspircd_config.h.tmp");
880 print FILEHANDLE <<EOF;
881 /* Auto generated by configure, do not modify! */
882 #ifndef __CONFIGURATION_AUTO__
883 #define __CONFIGURATION_AUTO__
885 /* this is for windows support. */
886 #define CoreExport /**/
887 #define DllExport /**/
889 #define CONFIG_PATH "$config{CONFIG_DIR}"
890 #define DATA_PATH "$config{DATA_DIR}"
891 #define LOG_PATH "$config{LOG_DIR}"
892 #define MOD_PATH "$config{MODULE_DIR}"
893 #define SOMAXCONN_S "$config{_SOMAXCONN}"
894 #define ENTRYPOINT int main(int argc, char** argv)
897 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
899 if ($config{OSNAME} =~ /SunOS/i) {
900 print FILEHANDLE "#define IS_SOLARIS\n";
902 if ($config{OSNAME} =~ /MINGW32/i) {
903 print FILEHANDLE "#define IS_MINGW\n";
905 if ($config{GCCVER} >= 3) {
906 print FILEHANDLE "#define GCC3\n";
908 if ($config{HAS_STRLCPY} eq "true") {
909 print FILEHANDLE "#define HAS_STRLCPY\n";
911 if ($config{HAS_STDINT} eq "true") {
912 print FILEHANDLE "#define HAS_STDINT\n";
914 if ($config{HAS_EVENTFD} eq 'true') {
915 print FILEHANDLE "#define HAS_EVENTFD\n";
917 if ($config{OSNAME} !~ /DARWIN/i) {
918 print FILEHANDLE "#define HAS_CLOCK_GETTIME\n";
921 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
922 print FILEHANDLE "#define USE_KQUEUE\n";
923 $config{SOCKETENGINE} = "socketengine_kqueue";
926 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
927 print FILEHANDLE "#define USE_EPOLL\n";
928 $config{SOCKETENGINE} = "socketengine_epoll";
931 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
932 print FILEHANDLE "#define USE_PORTS\n";
933 $config{SOCKETENGINE} = "socketengine_ports";
936 # user didn't choose either epoll or select for their OS.
937 # default them to USE_SELECT (ewwy puke puke)
939 print "no hi-perf, " . $config{USE_POLL};
940 if ($config{USE_POLL} eq "y")
942 print FILEHANDLE "#define USE_POLL\n";
943 $config{SOCKETENGINE} = "socketengine_poll";
947 print FILEHANDLE "#define USE_SELECT\n";
948 $config{SOCKETENGINE} = "socketengine_select";
951 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
954 open(FILEHANDLE, ">include/inspircd_version.h.tmp");
955 print FILEHANDLE <<EOF;
956 #define BRANCH "$branch"
957 #define VERSION "$version"
958 #define REVISION "$revision2"
959 #define SYSTEM "$incos"
963 for my $file (qw(include/inspircd_config.h include/inspircd_version.h)) {
965 open my $fh1, $file or $diff = 1;
966 open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
970 if (defined($line1) != defined($line2)) {
972 } elsif (!defined $line1) {
975 $diff = ($line1 ne $line2);
980 rename "$file.tmp", $file;
987 # Write all .in files.
990 my $exe = "inspircd";
992 # Do this once here, and cache it in the .*.inc files,
993 # rather than attempting to read src/version.sh from
994 # compiled code -- we might not have the source to hand.
995 # Fix for bug#177 by Brain.
997 chomp($version = `sh ./src/version.sh`);
998 chomp(my $revision = getrevision());
999 $version = "$version(r$revision)";
1001 # We can actually parse any file starting with . and ending with .inc,
1002 # but right now we only parse .inspircd.inc to form './inspircd'
1003 prepare_dynamic_makefile();
1005 my @dotfiles = qw(main.mk inspircd);
1006 push @dotfiles, 'org.inspircd.plist' if $config{OSNAME} eq 'darwin';
1008 foreach my $file (@dotfiles) {
1009 open(FILEHANDLE, "make/template/$file") or die "Can't open make/template/$file: $!";
1010 $_ = join '', <FILEHANDLE>;
1013 $config{BUILD_DIR} ||= resolve_directory($config{ME}."/build");
1016 CC SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR DATA_DIR UID
1017 STARTSCRIPT DESTINATION SOCKETENGINE
1019 s/\@$var\@/$config{$var}/g;
1021 s/\@EXECUTABLE\@/$exe/ if defined $exe;
1022 s/\@VERSION\@/$version/ if defined $version;
1024 if ($file eq 'main.mk') {
1025 print "Writing \e[1;32mGNUmakefile\e[0m ...\n";
1028 s/\@IFDEF (\S+)/ifdef $1/g;
1029 s/\@IFNDEF (\S+)/ifndef $1/g;
1030 s/\@IFEQ (\S+) (\S+)/ifeq ($1,$2)/g;
1031 s/\@ELSIFEQ (\S+) (\S+)/else ifeq ($1,$2)/g;
1034 s/ *\@BSD_ONLY .*\n//g;
1036 s/\@DO_EXPORT (.*)/export $1/g;
1037 open MKF, '>GNUmakefile' or die "Can't write to GNUmakefile: $!";
1041 print "Writing \e[1;32mBSDmakefile\e[0m ...\n";
1043 s/\@IFDEF (\S+)/.if defined($1)/g;
1044 s/\@IFNDEF (\S+)/.if !defined($1)/g;
1045 s/\@IFEQ (\S+) (\S+)/.if $1 == $2/g;
1046 s/\@ELSIFEQ (\S+) (\S+)/.elif $1 == $2/g;
1050 s/ *\@GNU_ONLY .*\n//g;
1052 $mk_tmp =~ s#\@DO_EXPORT (.*)#"MAKEENV += ".join ' ', map "$_='\${$_}'", split /\s/, $1#eg;
1053 open MKF, '>BSDmakefile' or die "Can't write to BSDmakefile: $!";
1057 print "Writing \e[1;32m$file\e[0m ...\n";
1058 open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
1059 print FILEHANDLE $_;
1064 chmod 0755, 'inspircd';
1070 for my $mod (@modlist) {
1071 getcompilerflags("src/modules/m_$mod.cpp");
1072 getlinkerflags("src/modules/m_$mod.cpp");
1076 sub prepare_dynamic_makefile
1082 $config{USE_EPOLL} = 0;
1086 $config{USE_KQUEUE} = 0;
1090 $config{USE_PORTS} = 0;
1094 # Routine to list out the extra/ modules that have been enabled.
1095 # Note: when getting any filenames out and comparing, it's important to lc it if the
1096 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1097 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1098 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1099 sub list_extras () {
1102 my $srcdir = File::Spec->catdir("src", "modules");
1103 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1106 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1107 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1110 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1111 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1114 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1116 EXTRA: for my $extra (@extras) {
1117 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1118 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1119 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1120 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1121 if (-l $abs_source) {
1122 # Symlink, is it in the right place?
1123 my $targ = readlink($abs_source);
1124 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1125 if ($abs_targ eq $abs_extra) {
1126 $extras{$extra} = "\e[32;1menabled\e[0m";
1128 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1130 } elsif (-e $abs_source) {
1131 my ($devext, $inoext) = stat($abs_extra);
1132 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1134 if ($devsrc == $devext && $inosrc == $inoext) {
1135 $extras{$extra} = "\e[32;1menabled\e[0m";
1137 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1140 open my $extfd, "<", $abs_extra;
1141 open my $srcfd, "<", $abs_source;
1143 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1144 $extras{$extra} = "\e[32;1menabled\e[0m";
1146 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1150 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1153 # Now let's add dependency info
1154 for my $extra (keys(%extras)) {
1155 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1156 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1157 my @deps = split / +/, getdependencies($abs_extra);
1158 for my $dep (@deps) {
1159 if (exists($extras{$dep})) {
1160 my $ref = \$extras{$dep}; # Take reference.
1161 if ($$ref !~ m/needed by/) {
1162 # First dependency found.
1163 if ($$ref =~ m/enabled/) {
1164 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1166 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1167 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1170 if ($$ref =~ m/enabled/) {
1171 $$ref .= ", \e[32;1m$extra\e[0m";
1173 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1179 for my $extra (sort {$a cmp $b} keys(%extras)) {
1180 my $text = $extras{$extra};
1181 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1182 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1184 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1187 return keys(%extras) if wantarray; # Can be used by manage_extras.
1190 sub enable_extras (@) {
1192 for my $extra (@extras) {
1193 my $extrapath = "src/modules/extra/$extra";
1194 if (!-e $extrapath) {
1195 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1198 my $source = "src/modules/$extra";
1200 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1203 # Get dependencies, and add them to be processed.
1204 my @deps = split / +/, getdependencies($extrapath);
1205 for my $dep (@deps) {
1206 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1207 if (!-e "src/modules/$dep") {
1208 if (-e "src/modules/extra/$dep") {
1209 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1212 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";
1216 print "Enabling $extra ... \n";
1217 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1221 sub disable_extras (@)
1223 opendir my $dd, "src/modules/extra/";
1224 my @files = readdir($dd);
1227 EXTRA: for my $extra (@extras) {
1228 my $extrapath = "src/modules/extra/$extra";
1229 my $source = "src/modules/$extra";
1230 if (!-e $extrapath) {
1231 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1234 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1235 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";
1238 # Check if anything needs this.
1239 for my $file (@files) {
1240 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1241 # File depends on this extra...
1242 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1243 # And is both enabled and not about to be disabled.
1244 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1245 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1251 print "Disabling $extra ... \n";
1252 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";