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 || defined $opt_uid) {
156 $config{BASE_DIR} = '/var/lib/inspircd';
159 if (defined $opt_system || defined $opt_uid) {
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';
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 | cut -c 1,2,3`); # 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} = "";
215 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
216 chomp(our $openssl_ver = $config{HAS_OPENSSL});
217 $config{USE_GNUTLS} = "n";
218 if (defined $opt_use_gnutls)
220 $config{USE_GNUTLS} = "y"; # Use gnutls.
222 $config{USE_OPENSSL} = "n"; # Use openssl.
223 if (defined $opt_use_openssl)
225 $config{USE_OPENSSL} = "y";
228 if (!defined $opt_disable_debug) {
229 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
231 $config{OPTIMISATI} = "-O2";
234 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
235 $config{HAS_STDINT} = "false"; # stdint.h check
236 $config{USE_KQUEUE} = "y"; # kqueue enabled
237 if (defined $opt_nokqueue) {
238 $config{USE_KQUEUE} = "n";
240 $config{USE_POLL} = "y"; # poll enabled
241 $config{USE_EPOLL} = "y"; # epoll enabled
242 if (defined $opt_noepoll)
244 $config{USE_EPOLL} = "n";
246 $config{USE_PORTS} = "y"; # epoll enabled
247 if (defined $opt_noports)
249 $config{USE_PORTS} = "n";
251 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
252 $config{OSNAME} = $^O; # Operating System Name
253 $config{IS_DARWIN} = "NO"; # Is OSX?
254 $config{STARTSCRIPT} = "inspircd"; # start script?
255 $config{DESTINATION} = "BASE"; # Is target path.
256 if ($config{OSNAME} =~ /darwin/i)
258 $config{IS_DARWIN} = "YES";
259 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
260 $config{CC} = "xcrun clang++"; # C++ compiler for OSX.
264 $config{CC} = "g++"; # C++ compiler
268 $config{CC} = $opt_cc;
270 our $exec = $config{CC} . " -dumpversion | cut -c 1";
271 chomp($config{GCCVER} = `$exec`); # Major GCC Version
272 $exec = $config{CC} . " -dumpversion | cut -c 3";
273 chomp($config{GCCMINOR} = `$exec`);
274 $config{MAXBUF} = "512"; # Max buffer size
276 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/) {
277 $config{HAS_OPENSSL} = $1;
279 $config{HAS_OPENSSL} = "";
282 if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
283 if ($config{IS_DARWIN} eq "YES") {
284 print $config{CC} . " was not found! You require clang++ (the LLVM C++ compiler, part of the OSX developer tools) to build InspIRCd!\n";
286 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
291 # Get and Set some important vars..
296 unlink(".config.cache");
299 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
304 chomp($topdir = getcwd());
305 $this = resolve_directory($topdir); # PWD, Regardless.
307 # Does the cache file exist?
309 # No, No it doesn't.. *BASH*
310 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
313 # We've Loaded the cache file and all our variables..
314 print "Updating files...\n";
315 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
317 print "Disabling debug information (-g).\n";
318 $config{OPTIMISATI} = "";
320 $has_epoll = $config{HAS_EPOLL};
321 $has_ports = $config{HAS_PORTS};
322 $has_kqueue = $config{HAS_KQUEUE};
331 print "Configure update failed: $@\n";
340 $fail ||= system "$config{CC} -o test_$feature make/check_$feature.cpp >/dev/null 2>&1";
341 $fail ||= system "./test_$feature";
342 unlink "test_$feature";
346 print "Running non-interactive configure...\n" unless $interactive;
347 print "Checking for cache from previous configure... ";
348 print ($cache_loaded ? "found\n" : "not found\n");
349 $config{SYSTEM} = lc $^O;
350 print "Checking operating system version... $config{SYSTEM}\n";
352 $exec = $config{CC} . " -dumpversion | cut -c 1";
353 chomp($config{GCCVER} = `$exec`); # Major GCC Version
354 $exec = $config{CC} . " -dumpversion | cut -c 3";
355 chomp($config{GCCMINOR} = `$exec`);
357 printf "Checking if stdint.h exists... ";
358 $config{HAS_STDINT} = "true";
360 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
361 if ($config{HAS_STDINT} eq "true") {
364 print "yes\n" if $config{HAS_STDINT} eq "true";
365 print "no\n" if $config{HAS_STDINT} eq "false";
367 printf "Checking if strlcpy exists... ";
368 # Perform the strlcpy() test..
369 $config{HAS_STRLCPY} = "false";
371 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
373 while (defined(my $line = <STRLCPY>)) {
375 # try and find the delcaration of:
376 # size_t strlcpy(...)
377 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
378 $config{HAS_STRLCPY} = "true";
383 print "yes\n" if $config{HAS_STRLCPY} eq "true";
384 print "no\n" if $config{HAS_STRLCPY} eq "false";
386 printf "Checking if kqueue exists... ";
389 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
391 while (defined(my $line = <KQUEUE>)) {
393 # try and find the delcaration of:
395 if ($line =~ /int(\0x9|\s)+kqueue/) {
401 print "yes\n" if $has_kqueue == 1;
402 print "no\n" if $has_kqueue == 0;
404 printf "Checking for epoll support... ";
405 $has_epoll = test_compile('epoll');
406 print $has_epoll ? "yes\n" : "no\n";
408 printf "Checking for eventfd support... ";
409 $config{HAS_EVENTFD} = test_compile('eventfd') ? 'true' : 'false';
410 print $config{HAS_EVENTFD} eq 'true' ? "yes\n" : "no\n";
412 printf "Checking if Solaris I/O completion ports are available... ";
414 our $system = `uname -s`;
416 $has_ports = 1 if ($system eq "SunOS");
419 my $kernel = `uname -r`;
421 if (($kernel !~ /^5\.1./)) {
425 print "yes\n" if $has_ports == 1;
426 print "no\n" if $has_ports == 0;
428 $config{HAS_EPOLL} = $has_epoll;
429 $config{HAS_KQUEUE} = $has_kqueue;
431 printf "Checking for libgnutls... ";
432 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
433 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
435 $config{HAS_GNUTLS} = "y";
438 $config{HAS_GNUTLS} = "n";
442 $config{HAS_GNUTLS} = "n";
445 printf "Checking for openssl... ";
446 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
447 if (defined($openssl_ver) && ($openssl_ver ne "")) {
449 $config{HAS_OPENSSL} = "y";
452 $config{HAS_OPENSSL} = "n";
456 $config{HAS_OPENSSL} = "n";
459 printf "Checking if you are running an ancient, unsupported OS... ";
460 if ($config{OSNAME} =~ /FreeBSD/i)
462 my $version = `uname -r`;
463 if ($version =~ /^4\./)
466 print "FreeBSD 4.x is no longer supported. By ANYONE.\n";
467 print "To build, you will need to add the following to CXXFLAGS:\n";
468 print "\t-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1\n";
472 print "no ($version)\n";
477 print "no ($config{OSNAME})\n";
480 ################################################################################
481 # BEGIN INTERACTIVE PART #
482 ################################################################################
487 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
490 my $rev = getrevision();
491 # Display Introduction Message..
493 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
494 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
496 *** If you are unsure of any of these values, leave it blank for ***
497 *** standard settings that will work, and your server will run ***
498 *** using them. Please consult your IRC network admin if in doubt. ***
500 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
501 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
502 dir, otherwise you won't have a config file!
504 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
505 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
508 print " (Non-SVN build)";
512 $config{CHANGE_COMPILER} = "n";
513 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";
515 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
516 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
517 should NOT be used. You should probably specify a newer compiler.\n\n";
518 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
519 if ($config{CHANGE_COMPILER} =~ /y/i) {
520 print "What command do you want to use to invoke your compiler?\n";
521 print "[\e[1;32m$config{CC}\e[0m] -> ";
522 chomp($config{CC} = <STDIN>);
523 if ($config{CC} eq "") {
526 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
528 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
529 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
530 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
531 if ($config{GCCVER} < 3) {
532 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
536 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
543 # Directory Settings..
544 my $tmpbase = $config{BASE_DIR};
545 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
546 if ($tmpbase ne $config{BASE_DIR}) {
547 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
548 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
549 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data Directory
550 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log Directory
551 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
554 dir_check("are the configuration files", "CONFIG_DIR");
555 dir_check("are the modules to be compiled to", "MODULE_DIR");
556 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
557 dir_check("are variable data files to be located in", "DATA_DIR");
558 dir_check("are the logs to be stored in", "LOG_DIR");
559 dir_check("do you want the build to take place", "BUILD_DIR");
561 my $chose_hiperf = 0;
563 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?");
565 if ($config{USE_KQUEUE} eq "y") {
570 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?");
572 if ($config{USE_EPOLL} eq "y") {
577 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?");
579 if ($config{USE_PORTS} eq "y") {
584 if (!$chose_hiperf) {
585 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?");
586 if ($config{USE_POLL} ne "y")
588 print "No high-performance socket engines are available, or you chose\n";
589 print "not to enable one. Defaulting to select() engine.\n\n";
593 $config{USE_FREEBSD_BASE_SSL} = "n";
594 $config{USE_FREEBSD_PORTS_SSL} = "n";
595 if ($config{HAS_OPENSSL_PORT} ne "")
597 $config{USE_FREEBSD_PORTS_SSL} = "y";
598 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
599 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";
600 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
602 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
604 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
606 # update to port version
607 $openssl_ver = $config{HAS_OPENSSL_PORT};
612 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
615 $config{USE_SSL} = "n";
616 $config{MODUPDATE} = 'n';
618 if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
620 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
621 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
623 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
624 if ($config{USE_SSL} eq "y")
626 if ($config{HAS_GNUTLS} eq "y")
628 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
629 if ($config{USE_GNUTLS} eq "y")
631 print "\nUsing GnuTLS SSL module.\n";
635 if ($config{HAS_OPENSSL} eq "y")
637 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
638 if ($config{USE_OPENSSL} eq "y")
640 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
647 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed and\n";
648 print "is in your path.\n\n";
651 yesno('MODUPDATE',"Would you like to check for updates to third-party modules?");
653 if ($config{MODUPDATE} eq "y") {
654 print "Checking for upgrades to extra and third party modules... ";
655 system "./modulemanager upgrade";
659 # We are on a POSIX system, we can enable POSIX extras without asking
660 symlink "extra/m_regex_posix.cpp", "src/modules/m_regex_posix.cpp";
664 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
666 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
669 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
671 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
676 $config{CERTGEN} ||= 'y';
677 yesno('CERTGEN',"Would you like generate SSL certificates now?") if ($interactive && ($config{USE_GNUTLS} eq "y" || $config{USE_OPENSSL} eq "y"));
679 if ($config{USE_GNUTLS} eq "y") {
680 unless (-r "src/modules/m_ssl_gnutls.cpp") {
681 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
682 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
684 if ($interactive && $config{CERTGEN} eq 'y')
686 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
687 print "SSL Certificates Not found, Generating.. \n\n
688 *************************************************************
689 * Generating the Private Key may take some time, go grab a *
690 * Coffee. Even better, to generate some more entropy if it *
691 * is taking a while, open another console and type du / a *
692 * few times and get that HD going :) Then answer the *
693 * Questions which follow. If you are unsure, just hit enter *
694 *************************************************************\n\n";
695 $failed = make_gnutls_cert();
697 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
699 print "\nCertificate generation complete, copying to config directory... ";
700 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
701 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
706 print "SSL Certificates found, skipping.\n\n";
711 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
715 if ($config{USE_OPENSSL} eq "y") {
716 unless (-r "src/modules/m_ssl_openssl.cpp") {
717 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
718 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
721 if ($interactive && $config{CERTGEN} eq 'y')
723 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
724 print "SSL Certificates Not found, Generating.. \n\n
725 *************************************************************
726 * Generating the certificates may take some time, go grab a *
727 * coffee, or something. *
728 *************************************************************\n\n";
730 print "\nCertificate generation complete, copying to config directory... ";
731 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
732 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
733 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
736 print "SSL Certificates found, skipping.\n\n"
741 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
744 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
745 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
753 print "To build your server with these settings, please run '\e[1;32mmake\e[0m' now.\n";
754 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
755 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
756 print "modules in your config. This configure script has added those modules to the\n";
757 print "build process. For more info please refer to:\n";
758 print "\e[1;32mhttp://wiki.inspircd.org/Installation_From_Tarball\e[0m\n";
760 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
761 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
762 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";
765 if ($config{GCCVER} < "3") {
767 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
768 GCC 2.x series compilers only had partial (read as broken) C++ support, and
769 your compile will most likely fail horribly! If you have any problems, do NOT
770 report them to the bugtracker or forums without first upgrading your compiler
771 to a newer 3.x or 4.x (or whatever is available currently) version.
775 ################################################################################
777 ################################################################################
779 # Retrieves the .config.cache file, and loads values into the main config hash.
780 open(CACHE, ".config.cache") or return 0;
783 # Ignore Blank lines, and comments..
786 my ($key, $value) = split("=", $_, 2);
787 $value =~ /^\"(.*)\"$/;
788 # Do something with data here!
796 # Dump the contents of %config
797 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
798 open(FILEHANDLE, ">.config.cache");
799 foreach my $key (keys %config) {
800 print FILEHANDLE "$key=\"$config{$key}\"\n";
806 my ($desc, $hash_key) = @_;
809 print "In what directory $desc?\n";
810 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
811 chomp(my $var = <STDIN>);
813 $var = $config{$hash_key};
815 if ($var =~ /^\~\/(.+)$/) {
816 # Convert it to a full path..
817 $var = resolve_directory($ENV{HOME} . "/" . $1);
819 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
821 # Assume relative Path was given.. fill in the rest.
822 $var = $this . "/$var";
825 $var = resolve_directory($var);
827 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
828 chomp(my $tmp = <STDIN>);
829 if (($tmp eq "") || ($tmp =~ /^y/i)) {
830 # Attempt to Create the Dir..
833 File::Path::mkpath($var, 0, 0777);
836 unless (defined($chk) && -d $var) {
837 print "Unable to create directory. ($var)\n\n";
842 # They said they don't want to create, and we can't install there.
848 # Target exists, but is not a directory.
849 print "File $var exists, but is not a directory.\n\n";
853 # Either Dir Exists, or was created fine.
854 $config{$hash_key} = $var;
862 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
865 my($writeheader) = @_;
866 # First File.. inspircd_config.h
867 chomp(my $incos = `uname -n -s -r`);
868 chomp(my $version = `sh src/version.sh`);
869 chomp(my $revision2 = getrevision());
870 my $branch = "InspIRCd-0.0";
871 if ($version =~ /^(InspIRCd-[0-9]+\.[0-9]+)\.[0-9]+/)
875 if ($writeheader == 1)
877 print "Writing \e[1;32minspircd_config.h\e[0m\n";
878 open(FILEHANDLE, ">include/inspircd_config.h.tmp");
879 print FILEHANDLE <<EOF;
880 /* Auto generated by configure, do not modify! */
881 #ifndef __CONFIGURATION_AUTO__
882 #define __CONFIGURATION_AUTO__
884 /* this is for windows support. */
885 #define CoreExport /**/
886 #define DllExport /**/
888 #define CONFIG_PATH "$config{CONFIG_DIR}"
889 #define DATA_PATH "$config{DATA_DIR}"
890 #define LOG_PATH "$config{LOG_DIR}"
891 #define MOD_PATH "$config{MODULE_DIR}"
892 #define SOMAXCONN_S "$config{_SOMAXCONN}"
893 #define ENTRYPOINT int main(int argc, char** argv)
896 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
898 if ($config{OSNAME} =~ /SunOS/i) {
899 print FILEHANDLE "#define IS_SOLARIS\n";
901 if ($config{OSNAME} =~ /MINGW32/i) {
902 print FILEHANDLE "#define IS_MINGW\n";
904 if ($config{GCCVER} >= 3) {
905 print FILEHANDLE "#define GCC3\n";
908 (($config{GCCVER} == 4) && ($config{GCCMINOR} >= 3))
910 ($config{GCCVER} > 4)
911 || # HACK: temporary fix for non-GCC (i.e. clang) builds
912 ($config{CC} !~ /gcc/)
914 print FILEHANDLE "#define HASHMAP_DEPRECATED\n";
916 if ($config{HAS_STRLCPY} eq "true") {
917 print FILEHANDLE "#define HAS_STRLCPY\n";
919 if ($config{HAS_STDINT} eq "true") {
920 print FILEHANDLE "#define HAS_STDINT\n";
922 if ($config{HAS_EVENTFD} eq 'true') {
923 print FILEHANDLE "#define HAS_EVENTFD\n";
925 if ($config{OSNAME} !~ /DARWIN/i) {
926 print FILEHANDLE "#define HAS_CLOCK_GETTIME\n";
929 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
930 print FILEHANDLE "#define USE_KQUEUE\n";
931 $config{SOCKETENGINE} = "socketengine_kqueue";
934 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
935 print FILEHANDLE "#define USE_EPOLL\n";
936 $config{SOCKETENGINE} = "socketengine_epoll";
939 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
940 print FILEHANDLE "#define USE_PORTS\n";
941 $config{SOCKETENGINE} = "socketengine_ports";
944 # user didn't choose either epoll or select for their OS.
945 # default them to USE_SELECT (ewwy puke puke)
947 print "no hi-perf, " . $config{USE_POLL};
948 if ($config{USE_POLL} eq "y")
950 print FILEHANDLE "#define USE_POLL\n";
951 $config{SOCKETENGINE} = "socketengine_poll";
955 print FILEHANDLE "#define USE_SELECT\n";
956 $config{SOCKETENGINE} = "socketengine_select";
959 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
962 open(FILEHANDLE, ">include/inspircd_version.h.tmp");
963 print FILEHANDLE <<EOF;
964 #define BRANCH "$branch"
965 #define VERSION "$version"
966 #define REVISION "$revision2"
967 #define SYSTEM "$incos"
971 for my $file (qw(include/inspircd_config.h include/inspircd_version.h)) {
973 open my $fh1, $file or $diff = 1;
974 open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
978 if (defined($line1) != defined($line2)) {
980 } elsif (!defined $line1) {
983 $diff = ($line1 ne $line2);
988 rename "$file.tmp", $file;
995 # Write all .in files.
998 my $exe = "inspircd";
1000 # Do this once here, and cache it in the .*.inc files,
1001 # rather than attempting to read src/version.sh from
1002 # compiled code -- we might not have the source to hand.
1003 # Fix for bug#177 by Brain.
1005 chomp($version = `sh ./src/version.sh`);
1006 chomp(my $revision = getrevision());
1007 $version = "$version(r$revision)";
1009 # We can actually parse any file starting with . and ending with .inc,
1010 # but right now we only parse .inspircd.inc to form './inspircd'
1011 prepare_dynamic_makefile();
1013 my @dotfiles = qw(main.mk inspircd);
1014 push @dotfiles, 'org.inspircd.plist' if $config{OSNAME} eq 'darwin';
1016 foreach my $file (@dotfiles) {
1017 open(FILEHANDLE, "make/template/$file") or die "Can't open make/template/$file: $!";
1018 $_ = join '', <FILEHANDLE>;
1021 $config{BUILD_DIR} ||= resolve_directory($config{ME}."/build");
1024 CC SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR DATA_DIR UID
1025 STARTSCRIPT DESTINATION SOCKETENGINE
1027 s/\@$var\@/$config{$var}/g;
1029 s/\@EXECUTABLE\@/$exe/ if defined $exe;
1030 s/\@VERSION\@/$version/ if defined $version;
1032 if ($file eq 'main.mk') {
1033 print "Writing \e[1;32mGNUmakefile\e[0m ...\n";
1036 s/\@IFDEF (\S+)/ifdef $1/g;
1037 s/\@IFNDEF (\S+)/ifndef $1/g;
1038 s/\@IFEQ (\S+) (\S+)/ifeq ($1,$2)/g;
1039 s/\@ELSIFEQ (\S+) (\S+)/else ifeq ($1,$2)/g;
1042 s/ *\@BSD_ONLY .*\n//g;
1044 s/\@DO_EXPORT (.*)/export $1/g;
1045 open MKF, '>GNUmakefile' or die "Can't write to GNUmakefile: $!";
1049 print "Writing \e[1;32mBSDmakefile\e[0m ...\n";
1051 s/\@IFDEF (\S+)/.if defined($1)/g;
1052 s/\@IFNDEF (\S+)/.if !defined($1)/g;
1053 s/\@IFEQ (\S+) (\S+)/.if $1 == $2/g;
1054 s/\@ELSIFEQ (\S+) (\S+)/.elif $1 == $2/g;
1058 s/ *\@GNU_ONLY .*\n//g;
1060 $mk_tmp =~ s#\@DO_EXPORT (.*)#"MAKEENV += ".join ' ', map "$_='\${$_}'", split /\s/, $1#eg;
1061 open MKF, '>BSDmakefile' or die "Can't write to BSDmakefile: $!";
1065 print "Writing \e[1;32m$file\e[0m ...\n";
1066 open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
1067 print FILEHANDLE $_;
1072 chmod 0755, 'inspircd';
1078 for my $mod (@modlist) {
1079 getcompilerflags("src/modules/m_$mod.cpp");
1080 getlinkerflags("src/modules/m_$mod.cpp");
1084 sub prepare_dynamic_makefile
1090 $config{USE_EPOLL} = 0;
1094 $config{USE_KQUEUE} = 0;
1098 $config{USE_PORTS} = 0;
1102 # Routine to list out the extra/ modules that have been enabled.
1103 # Note: when getting any filenames out and comparing, it's important to lc it if the
1104 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1105 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1106 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1107 sub list_extras () {
1110 my $srcdir = File::Spec->catdir("src", "modules");
1111 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1114 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1115 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1118 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1119 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1122 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1124 EXTRA: for my $extra (@extras) {
1125 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1126 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1127 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1128 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1129 if (-l $abs_source) {
1130 # Symlink, is it in the right place?
1131 my $targ = readlink($abs_source);
1132 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1133 if ($abs_targ eq $abs_extra) {
1134 $extras{$extra} = "\e[32;1menabled\e[0m";
1136 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1138 } elsif (-e $abs_source) {
1139 my ($devext, $inoext) = stat($abs_extra);
1140 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1142 if ($devsrc == $devext && $inosrc == $inoext) {
1143 $extras{$extra} = "\e[32;1menabled\e[0m";
1145 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1148 open my $extfd, "<", $abs_extra;
1149 open my $srcfd, "<", $abs_source;
1151 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1152 $extras{$extra} = "\e[32;1menabled\e[0m";
1154 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1158 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1161 # Now let's add dependency info
1162 for my $extra (keys(%extras)) {
1163 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1164 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1165 my @deps = split / +/, getdependencies($abs_extra);
1166 for my $dep (@deps) {
1167 if (exists($extras{$dep})) {
1168 my $ref = \$extras{$dep}; # Take reference.
1169 if ($$ref !~ m/needed by/) {
1170 # First dependency found.
1171 if ($$ref =~ m/enabled/) {
1172 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1174 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1175 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1178 if ($$ref =~ m/enabled/) {
1179 $$ref .= ", \e[32;1m$extra\e[0m";
1181 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1187 for my $extra (sort {$a cmp $b} keys(%extras)) {
1188 my $text = $extras{$extra};
1189 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1190 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1192 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1195 return keys(%extras) if wantarray; # Can be used by manage_extras.
1198 sub enable_extras (@) {
1200 for my $extra (@extras) {
1201 my $extrapath = "src/modules/extra/$extra";
1202 if (!-e $extrapath) {
1203 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1206 my $source = "src/modules/$extra";
1208 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1211 # Get dependencies, and add them to be processed.
1212 my @deps = split / +/, getdependencies($extrapath);
1213 for my $dep (@deps) {
1214 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1215 if (!-e "src/modules/$dep") {
1216 if (-e "src/modules/extra/$dep") {
1217 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1220 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";
1224 print "Enabling $extra ... \n";
1225 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1229 sub disable_extras (@)
1231 opendir my $dd, "src/modules/extra/";
1232 my @files = readdir($dd);
1235 EXTRA: for my $extra (@extras) {
1236 my $extrapath = "src/modules/extra/$extra";
1237 my $source = "src/modules/$extra";
1238 if (!-e $extrapath) {
1239 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1242 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1243 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";
1246 # Check if anything needs this.
1247 for my $file (@files) {
1248 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1249 # File depends on this extra...
1250 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1251 # And is both enabled and not about to be disabled.
1252 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1253 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1259 print "Disabling $extra ... \n";
1260 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";