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);
41 # Utility functions for our buildsystem
45 use make::opensslcert;
47 ###############################################################################################
49 # NON-EDITABLE VARIABLES
51 ###############################################################################################
53 our ($opt_use_gnutls, $opt_rebuild, $opt_use_openssl, $opt_nointeractive, $opt_ports,
54 $opt_epoll, $opt_kqueue, $opt_noports, $opt_noepoll, $opt_nokqueue,
55 $opt_noipv6, $opt_maxbuf, $opt_disable_debug, $opt_freebsd_port,
56 $opt_system, $opt_uid);
58 our ($opt_cc, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir, $opt_data_dir, $opt_log_dir);
62 sub enable_extras (@);
64 sub disable_extras (@);
67 my @opt_disableextras;
70 'enable-gnutls' => \$opt_use_gnutls,
71 'rebuild' => \$opt_rebuild,
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 'disable-ipv6' => \$opt_noipv6,
83 'with-cc=s' => \$opt_cc,
84 'with-maxbuf=i' => \$opt_maxbuf,
85 'enable-freebsd-ports-openssl' => \$opt_freebsd_port,
86 'prefix=s' => \$opt_base_dir,
87 'config-dir=s' => \$opt_config_dir,
88 'module-dir=s' => \$opt_module_dir,
89 'binary-dir=s' => \$opt_binary_dir,
90 'data-dir=s' => \$opt_data_dir,
91 'log-dir=s' => \$opt_log_dir,
92 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
93 'help' => sub { showhelp(); },
94 'update' => sub { update(); },
95 'clean' => sub { clean(); },
96 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
97 'enable-extras=s@' => \@opt_enableextras, # ^
98 'disable-extras=s@' => \@opt_disableextras, # ^
99 'generate-openssl-cert' => sub { make_openssl_cert(); exit(0); },
100 'generate-gnutls-cert' => sub { make_gnutls_cert(); exit(0); }
103 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
104 @opt_enableextras = split /,/, join(',', @opt_enableextras);
105 @opt_disableextras = split /,/, join(',', @opt_disableextras);
106 enable_extras(@opt_enableextras);
107 disable_extras(@opt_disableextras);
109 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
113 our $interactive = !(
114 (defined $opt_base_dir) ||
115 (defined $opt_config_dir) ||
116 (defined $opt_module_dir) ||
117 (defined $opt_base_dir) ||
118 (defined $opt_binary_dir) ||
119 (defined $opt_data_dir) ||
120 (defined $opt_log_dir) ||
121 (defined $opt_nointeractive) ||
123 (defined $opt_noipv6) ||
124 (defined $opt_kqueue) ||
125 (defined $opt_epoll) ||
126 (defined $opt_ports) ||
127 (defined $opt_use_openssl) ||
128 (defined $opt_nokqueue) ||
129 (defined $opt_noepoll) ||
130 (defined $opt_noports) ||
131 (defined $opt_maxbuf) ||
132 (defined $opt_system) ||
133 (defined $opt_uid) ||
134 (defined $opt_use_gnutls) ||
135 (defined $opt_freebsd_port)
138 chomp(our $topdir = getcwd());
139 our $this = resolve_directory($topdir); # PWD, Regardless.
140 our @modlist = (); # Declare for Module List..
141 our %config = (); # Initiate Configuration Hash..
142 our $cache_loaded = getcache();
143 $config{ME} = resolve_directory($topdir); # Present Working Directory
145 $config{BASE_DIR} = $config{ME}."/run";
147 if (defined $opt_base_dir) {
148 $config{BASE_DIR} = $opt_base_dir;
149 } elsif (defined $opt_system) {
150 $config{BASE_DIR} = '/var/lib/inspircd';
153 if (defined $opt_system) {
154 $config{UID} = $opt_uid || 'ircd';
155 $config{CONFIG_DIR} = '/etc/inspircd';
156 $config{MODULE_DIR} = '/usr/lib/inspircd';
157 $config{BINARY_DIR} = '/usr/sbin/';
158 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
159 $config{DATA_DIR} = '/var/inspircd';
160 $config{LOG_DIR} = '/var/log/inspircd';
162 $config{UID} = $opt_uid || $<;
163 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
164 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
165 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
166 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
167 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data directory
168 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log directory
171 if (defined $opt_config_dir) {
172 $config{CONFIG_DIR} = $opt_config_dir;
174 if (defined $opt_module_dir) {
175 $config{MODULE_DIR} = $opt_module_dir;
177 if (defined $opt_binary_dir) {
178 $config{BINARY_DIR} = $opt_binary_dir;
180 if (defined $opt_data_dir) {
181 $config{DATA_DIR} = $opt_data_dir;
183 if (defined $opt_log_dir) {
184 $config{LOG_DIR} = $opt_log_dir;
186 chomp($config{HAS_GNUTLS} = `pkg-config --modversion gnutls 2>/dev/null`); # GNUTLS Version.
188 if (defined $opt_freebsd_port)
190 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`);
191 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`);
192 $config{USE_FREEBSD_BASE_SSL} = "n";
196 if ($^O eq "freebsd")
198 # default: use base ssl
199 chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`); # OpenSSL version, freebsd specific
200 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`); # Port version, may be different
204 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version, others
205 $config{HAS_OPENSSL_PORT} = "";
206 $config{USE_FREEBSD_BASE_SSL} = "n";
210 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
211 chomp(our $openssl_ver = $config{HAS_OPENSSL});
212 $config{USE_GNUTLS} = "n";
213 if (defined $opt_use_gnutls)
215 $config{USE_GNUTLS} = "y"; # Use gnutls.
217 $config{USE_OPENSSL} = "n"; # Use openssl.
218 if (defined $opt_use_openssl)
220 $config{USE_OPENSSL} = "y";
223 if (!defined $opt_disable_debug) {
224 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
226 $config{OPTIMISATI} = "-O2";
229 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
230 $config{HAS_STDINT} = "false"; # stdint.h check
231 $config{USE_KQUEUE} = "y"; # kqueue enabled
232 if (defined $opt_nokqueue) {
233 $config{USE_KQUEUE} = "n";
235 $config{USE_POLL} = "y"; # poll enabled
236 $config{USE_EPOLL} = "y"; # epoll enabled
237 if (defined $opt_noepoll)
239 $config{USE_EPOLL} = "n";
241 $config{USE_PORTS} = "y"; # epoll enabled
242 if (defined $opt_noports)
244 $config{USE_PORTS} = "n";
246 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
247 $config{OSNAME} = $^O; # Operating System Name
248 $config{IS_DARWIN} = "NO"; # Is OSX?
249 $config{STARTSCRIPT} = "inspircd"; # start script?
250 $config{DESTINATION} = "BASE"; # Is target path.
251 if ($config{OSNAME} =~ /darwin/i)
253 $config{IS_DARWIN} = "YES";
254 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
255 $config{CC} = "xcrun clang++"; # C++ compiler for OSX.
257 elsif ($config{OSNAME} =~ /freebsd/i)
259 chomp(my $fbsd_version = `uname -r`);
260 $config{CC} = $fbsd_version ge '10.0' ? 'clang++' : 'g++';
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 print "`$config{CC}` was not found! A C++ compiler is required to build InspIRCd!\n";
284 print "You can pass a custom compiler to $0 using --with-cc=[name].\n";
288 # Get and Set some important vars..
293 unlink(".config.cache");
296 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
301 chomp($topdir = getcwd());
302 $this = resolve_directory($topdir); # PWD, Regardless.
304 # Does the cache file exist?
306 # No, No it doesn't.. *BASH*
307 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
310 # We've Loaded the cache file and all our variables..
311 print "Updating files...\n";
312 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
314 print "Disabling debug information (-g).\n";
315 $config{OPTIMISATI} = "";
317 $has_epoll = $config{HAS_EPOLL};
318 $has_ports = $config{HAS_PORTS};
319 $has_kqueue = $config{HAS_KQUEUE};
328 print "Configure update failed: $@\n";
337 $fail ||= system "$config{CC} -o test_$feature make/check_$feature.cpp >/dev/null 2>&1";
338 $fail ||= system "./test_$feature";
339 unlink "test_$feature";
343 print "Running non-interactive configure...\n" unless $interactive;
344 print "Checking for cache from previous configure... ";
345 print ($cache_loaded ? "found\n" : "not found\n");
346 $config{SYSTEM} = lc $^O;
347 print "Checking operating system version... $config{SYSTEM}\n";
349 $exec = $config{CC} . " -dumpversion | cut -c 1";
350 chomp($config{GCCVER} = `$exec`); # Major GCC Version
351 $exec = $config{CC} . " -dumpversion | cut -c 3";
352 chomp($config{GCCMINOR} = `$exec`);
354 printf "Checking if stdint.h exists... ";
355 $config{HAS_STDINT} = "true";
357 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
358 if ($config{HAS_STDINT} eq "true") {
361 print "yes\n" if $config{HAS_STDINT} eq "true";
362 print "no\n" if $config{HAS_STDINT} eq "false";
364 printf "Checking if strlcpy exists... ";
365 # Perform the strlcpy() test..
366 $config{HAS_STRLCPY} = "false";
368 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
370 while (defined(my $line = <STRLCPY>)) {
372 # try and find the delcaration of:
373 # size_t strlcpy(...)
374 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
375 $config{HAS_STRLCPY} = "true";
380 print "yes\n" if $config{HAS_STRLCPY} eq "true";
381 print "no\n" if $config{HAS_STRLCPY} eq "false";
383 printf "Checking if kqueue exists... ";
386 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
388 while (defined(my $line = <KQUEUE>)) {
390 # try and find the delcaration of:
392 if ($line =~ /int(\0x9|\s)+kqueue/) {
398 print "yes\n" if $has_kqueue == 1;
399 print "no\n" if $has_kqueue == 0;
401 printf "Checking for epoll support... ";
402 $has_epoll = test_compile('epoll');
403 print $has_epoll ? "yes\n" : "no\n";
405 printf "Checking for eventfd support... ";
406 $config{HAS_EVENTFD} = test_compile('eventfd') ? 'true' : 'false';
407 print $config{HAS_EVENTFD} eq 'true' ? "yes\n" : "no\n";
409 printf "Checking if Solaris I/O completion ports are available... ";
411 our $system = `uname -s`;
413 $has_ports = 1 if ($system eq "SunOS");
416 my $kernel = `uname -r`;
418 if (($kernel !~ /^5\.1./)) {
422 print "yes\n" if $has_ports == 1;
423 print "no\n" if $has_ports == 0;
425 $config{HAS_EPOLL} = $has_epoll;
426 $config{HAS_KQUEUE} = $has_kqueue;
428 printf "Checking for libgnutls... ";
429 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
430 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
432 $config{HAS_GNUTLS} = "y";
435 $config{HAS_GNUTLS} = "n";
439 $config{HAS_GNUTLS} = "n";
442 printf "Checking for openssl... ";
443 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
444 if (defined($openssl_ver) && ($openssl_ver ne "")) {
446 $config{HAS_OPENSSL} = "y";
449 $config{HAS_OPENSSL} = "n";
453 $config{HAS_OPENSSL} = "n";
456 printf "Checking if you are running an ancient, unsupported OS... ";
457 if ($config{OSNAME} =~ /FreeBSD/i)
459 my $version = `uname -r`;
460 if ($version =~ /^4\./)
463 print "FreeBSD 4.x is no longer supported. By ANYONE.\n";
464 print "To build, you will need to add the following to CXXFLAGS:\n";
465 print "\t-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1\n";
469 print "no ($version)\n";
474 print "no ($config{OSNAME})\n";
477 ################################################################################
478 # BEGIN INTERACTIVE PART #
479 ################################################################################
484 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
487 my $rev = getrevision();
488 # Display Introduction Message..
490 Welcome to the \e[1mInspIRCd\e[0m configuration program! (\e[1minteractive mode\e[0m)
491 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
493 *** If you are unsure of any of these values, leave it blank for ***
494 *** standard settings that will work, and your server will run ***
495 *** using them. Please consult your IRC network admin if in doubt. ***
497 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
498 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
499 dir, otherwise you won't have a config file!
501 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
502 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
505 print " (Non-SVN build)";
509 $config{CHANGE_COMPILER} = "n";
510 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";
512 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
513 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
514 should NOT be used. You should probably specify a newer compiler.\n\n";
515 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
516 if ($config{CHANGE_COMPILER} =~ /y/i) {
517 print "What command do you want to use to invoke your compiler?\n";
518 print "[\e[1;32m$config{CC}\e[0m] -> ";
519 chomp($config{CC} = <STDIN>);
520 if ($config{CC} eq "") {
523 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
525 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
526 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
527 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
528 if ($config{GCCVER} < 3) {
529 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
533 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
540 # Directory Settings..
541 my $tmpbase = $config{BASE_DIR};
542 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
543 if ($tmpbase ne $config{BASE_DIR}) {
544 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
545 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
546 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data Directory
547 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log Directory
548 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
551 dir_check("are the configuration files", "CONFIG_DIR");
552 dir_check("are the modules to be compiled to", "MODULE_DIR");
553 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
554 dir_check("are variable data files to be located in", "DATA_DIR");
555 dir_check("are the logs to be stored in", "LOG_DIR");
556 dir_check("do you want the build to take place", "BUILD_DIR");
558 my $chose_hiperf = 0;
560 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?");
562 if ($config{USE_KQUEUE} eq "y") {
567 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?");
569 if ($config{USE_EPOLL} eq "y") {
574 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?");
576 if ($config{USE_PORTS} eq "y") {
581 if (!$chose_hiperf) {
582 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?");
583 if ($config{USE_POLL} ne "y")
585 print "No high-performance socket engines are available, or you chose\n";
586 print "not to enable one. Defaulting to select() engine.\n\n";
590 $config{USE_FREEBSD_BASE_SSL} = "n";
591 $config{USE_FREEBSD_PORTS_SSL} = "n";
592 if ($config{HAS_OPENSSL_PORT} ne "")
594 $config{USE_FREEBSD_PORTS_SSL} = "y";
595 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
596 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";
597 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
599 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
601 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
603 # update to port version
604 $openssl_ver = $config{HAS_OPENSSL_PORT};
609 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
612 $config{USE_SSL} = "n";
613 $config{MODUPDATE} = 'n';
615 if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
617 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
618 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
620 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
621 if ($config{USE_SSL} eq "y")
623 if ($config{HAS_GNUTLS} eq "y")
625 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
626 if ($config{USE_GNUTLS} eq "y")
628 print "\nUsing GnuTLS SSL module.\n";
632 if ($config{HAS_OPENSSL} eq "y")
634 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
635 if ($config{USE_OPENSSL} eq "y")
637 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
644 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed and\n";
645 print "is in your path.\n\n";
648 yesno('MODUPDATE',"Would you like to check for updates to third-party modules?");
650 if ($config{MODUPDATE} eq "y") {
651 print "Checking for upgrades to extra and third-party modules... ";
652 system "./modulemanager upgrade";
656 # We are on a POSIX system, we can enable POSIX extras without asking
657 symlink "extra/m_regex_posix.cpp", "src/modules/m_regex_posix.cpp";
661 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
663 print "Sorry, but I couldn't detect GnuTLS. Make sure pkg-config is in your path.\n";
666 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
668 print "Sorry, but I couldn't detect OpenSSL. Make sure pkg-config and openssl are in your path.\n";
673 $config{CERTGEN} ||= 'y';
674 yesno('CERTGEN',"Would you like to generate SSL certificates now?") if ($interactive && ($config{USE_GNUTLS} eq "y" || $config{USE_OPENSSL} eq "y"));
676 if ($config{USE_GNUTLS} eq "y") {
677 unless (-r "src/modules/m_ssl_gnutls.cpp") {
678 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
679 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
681 if ($interactive && $config{CERTGEN} eq 'y')
683 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
684 print "SSL certificates not found, generating.. \n\n
685 *************************************************************
686 * Generating the private key may take some time, once done, *
687 * answer the questions which follow. If you are unsure, *
689 *************************************************************\n\n";
690 $failed = make_gnutls_cert();
692 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
694 print "\nCertificate generation complete, copying to config directory... ";
695 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
696 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
701 print "SSL certificates found, skipping.\n\n";
706 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
710 if ($config{USE_OPENSSL} eq "y") {
711 unless (-r "src/modules/m_ssl_openssl.cpp") {
712 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
713 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
716 if ($interactive && $config{CERTGEN} eq 'y')
718 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
719 print "SSL certificates not found, generating.. \n\n
720 *************************************************************
721 * Generating the certificates may take some time, go grab a *
722 * coffee or something. *
723 *************************************************************\n\n";
725 print "\nCertificate generation complete, copying to config directory... ";
726 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
727 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
728 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
731 print "SSL certificates found, skipping.\n\n"
736 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
739 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
740 print "Skipping SSL certificate generation as SSL support is not available.\n\n";
748 print "To build your server with these settings, please run '\e[1;32mmake\e[0m' now.\n";
749 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
750 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
751 print "modules in your config. This configure script has added those modules to the\n";
752 print "build process. For more info, please refer to:\n";
753 print "\e[1;32mhttp://wiki.inspircd.org/Installation_From_Tarball\e[0m\n";
755 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
756 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
757 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";
760 if ($config{GCCVER} < "3") {
762 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
763 GCC 2.x series compilers only had partial (read as broken) C++ support, and
764 your compile will most likely fail horribly! If you have any problems, do NOT
765 report them to the bugtracker or forums without first upgrading your compiler
766 to a newer 3.x or 4.x (or whatever is available currently) version.
770 ################################################################################
772 ################################################################################
774 # Retrieves the .config.cache file, and loads values into the main config hash.
775 open(CACHE, ".config.cache") or return 0;
778 # Ignore Blank lines, and comments..
781 my ($key, $value) = split("=", $_, 2);
782 $value =~ /^\"(.*)\"$/;
783 # Do something with data here!
791 # Dump the contents of %config
792 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
793 open(FILEHANDLE, ">.config.cache");
794 foreach my $key (keys %config) {
795 print FILEHANDLE "$key=\"$config{$key}\"\n";
801 my ($desc, $hash_key) = @_;
804 print "In what directory $desc?\n";
805 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
806 chomp(my $var = <STDIN>);
808 $var = $config{$hash_key};
810 if ($var =~ /^\~\/(.+)$/) {
811 # Convert it to a full path..
812 $var = resolve_directory($ENV{HOME} . "/" . $1);
814 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
816 # Assume relative Path was given.. fill in the rest.
817 $var = $this . "/$var";
820 $var = resolve_directory($var);
822 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
823 chomp(my $tmp = <STDIN>);
824 if (($tmp eq "") || ($tmp =~ /^y/i)) {
825 # Attempt to Create the Dir..
828 File::Path::mkpath($var, 0, 0777);
831 unless (defined($chk) && -d $var) {
832 print "Unable to create directory. ($var)\n\n";
837 # They said they don't want to create, and we can't install there.
843 # Target exists, but is not a directory.
844 print "File $var exists, but is not a directory.\n\n";
848 # Either Dir Exists, or was created fine.
849 $config{$hash_key} = $var;
857 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
860 my($writeheader) = @_;
861 # First File.. inspircd_config.h
862 chomp(my $incos = `uname -n -s -r`);
863 chomp(my $version = `sh src/version.sh`);
864 chomp(my $revision2 = getrevision());
865 my $branch = "InspIRCd-0.0";
866 if ($version =~ /^(InspIRCd-[0-9]+\.[0-9]+)\.[0-9]+/)
870 if ($writeheader == 1)
872 print "Writing \e[1;32minspircd_config.h\e[0m\n";
873 open(FILEHANDLE, ">include/inspircd_config.h.tmp");
874 print FILEHANDLE <<EOF;
875 /* Auto generated by configure, do not modify! */
876 #ifndef __CONFIGURATION_AUTO__
877 #define __CONFIGURATION_AUTO__
879 /* this is for windows support. */
880 #define CoreExport /**/
881 #define DllExport /**/
883 #define CONFIG_PATH "$config{CONFIG_DIR}"
884 #define DATA_PATH "$config{DATA_DIR}"
885 #define LOG_PATH "$config{LOG_DIR}"
886 #define MOD_PATH "$config{MODULE_DIR}"
887 #define SOMAXCONN_S "$config{_SOMAXCONN}"
888 #define ENTRYPOINT int main(int argc, char** argv)
891 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
893 if ($config{OSNAME} =~ /SunOS/i) {
894 print FILEHANDLE "#define IS_SOLARIS\n";
896 if ($config{OSNAME} =~ /MINGW32/i) {
897 print FILEHANDLE "#define IS_MINGW\n";
899 if ($config{GCCVER} >= 3) {
900 print FILEHANDLE "#define GCC3\n";
902 if ($config{HAS_STRLCPY} eq "true") {
903 print FILEHANDLE "#define HAS_STRLCPY\n";
905 if ($config{HAS_STDINT} eq "true") {
906 print FILEHANDLE "#define HAS_STDINT\n";
908 if ($config{HAS_EVENTFD} eq 'true') {
909 print FILEHANDLE "#define HAS_EVENTFD\n";
911 if ($config{OSNAME} !~ /DARWIN/i) {
912 print FILEHANDLE "#define HAS_CLOCK_GETTIME\n";
915 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
916 print FILEHANDLE "#define USE_KQUEUE\n";
917 $config{SOCKETENGINE} = "socketengine_kqueue";
920 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
921 print FILEHANDLE "#define USE_EPOLL\n";
922 $config{SOCKETENGINE} = "socketengine_epoll";
925 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
926 print FILEHANDLE "#define USE_PORTS\n";
927 $config{SOCKETENGINE} = "socketengine_ports";
930 # user didn't choose either epoll or select for their OS.
931 # default them to USE_SELECT (ewwy puke puke)
933 print "no hi-perf, " . $config{USE_POLL};
934 if ($config{USE_POLL} eq "y")
936 print FILEHANDLE "#define USE_POLL\n";
937 $config{SOCKETENGINE} = "socketengine_poll";
941 print FILEHANDLE "#define USE_SELECT\n";
942 $config{SOCKETENGINE} = "socketengine_select";
945 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
948 open(FILEHANDLE, ">include/inspircd_version.h.tmp");
949 print FILEHANDLE <<EOF;
950 #define BRANCH "$branch"
951 #define VERSION "$version"
952 #define REVISION "$revision2"
953 #define SYSTEM "$incos"
957 for my $file (qw(include/inspircd_config.h include/inspircd_version.h)) {
959 open my $fh1, $file or $diff = 1;
960 open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
964 if (defined($line1) != defined($line2)) {
966 } elsif (!defined $line1) {
969 $diff = ($line1 ne $line2);
974 rename "$file.tmp", $file;
981 # Write all .in files.
984 my $exe = "inspircd";
986 # Do this once here, and cache it in the .*.inc files,
987 # rather than attempting to read src/version.sh from
988 # compiled code -- we might not have the source to hand.
989 # Fix for bug#177 by Brain.
991 chomp($version = `sh ./src/version.sh`);
992 chomp(my $revision = getrevision());
993 $version = "$version(r$revision)";
995 # We can actually parse any file starting with . and ending with .inc,
996 # but right now we only parse .inspircd.inc to form './inspircd'
997 prepare_dynamic_makefile();
999 my @dotfiles = qw(main.mk inspircd);
1000 push @dotfiles, 'org.inspircd.plist' if $config{OSNAME} eq 'darwin';
1002 foreach my $file (@dotfiles) {
1003 open(FILEHANDLE, "make/template/$file") or die "Can't open make/template/$file: $!";
1004 $_ = join '', <FILEHANDLE>;
1007 $config{BUILD_DIR} ||= resolve_directory($config{ME}."/build");
1010 CC SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR DATA_DIR UID
1011 STARTSCRIPT DESTINATION SOCKETENGINE
1013 s/\@$var\@/$config{$var}/g;
1015 s/\@EXECUTABLE\@/$exe/ if defined $exe;
1016 s/\@VERSION\@/$version/ if defined $version;
1018 if ($file eq 'main.mk') {
1019 print "Writing \e[1;32mGNUmakefile\e[0m ...\n";
1022 s/\@IFDEF (\S+)/ifdef $1/g;
1023 s/\@IFNDEF (\S+)/ifndef $1/g;
1024 s/\@IFEQ (\S+) (\S+)/ifeq ($1,$2)/g;
1025 s/\@ELSIFEQ (\S+) (\S+)/else ifeq ($1,$2)/g;
1028 s/ *\@BSD_ONLY .*\n//g;
1030 s/\@DO_EXPORT (.*)/export $1/g;
1031 open MKF, '>GNUmakefile' or die "Can't write to GNUmakefile: $!";
1035 print "Writing \e[1;32mBSDmakefile\e[0m ...\n";
1037 s/\@IFDEF (\S+)/.if defined($1)/g;
1038 s/\@IFNDEF (\S+)/.if !defined($1)/g;
1039 s/\@IFEQ (\S+) (\S+)/.if $1 == $2/g;
1040 s/\@ELSIFEQ (\S+) (\S+)/.elif $1 == $2/g;
1044 s/ *\@GNU_ONLY .*\n//g;
1046 $mk_tmp =~ s#\@DO_EXPORT (.*)#"MAKEENV += ".join ' ', map "$_='\${$_}'", split /\s/, $1#eg;
1047 open MKF, '>BSDmakefile' or die "Can't write to BSDmakefile: $!";
1051 print "Writing \e[1;32m$file\e[0m ...\n";
1052 open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
1053 print FILEHANDLE $_;
1058 chmod 0755, 'inspircd';
1064 for my $mod (@modlist) {
1065 getcompilerflags("src/modules/m_$mod.cpp");
1066 getlinkerflags("src/modules/m_$mod.cpp");
1070 sub prepare_dynamic_makefile
1076 $config{USE_EPOLL} = 0;
1080 $config{USE_KQUEUE} = 0;
1084 $config{USE_PORTS} = 0;
1088 # Routine to list out the extra/ modules that have been enabled.
1089 # Note: when getting any filenames out and comparing, it's important to lc it if the
1090 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1091 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1092 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1093 sub list_extras () {
1096 my $srcdir = File::Spec->catdir("src", "modules");
1097 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1100 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1101 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1104 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1105 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1108 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1110 EXTRA: for my $extra (@extras) {
1111 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1112 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1113 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1114 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1115 if (-l $abs_source) {
1116 # Symlink, is it in the right place?
1117 my $targ = readlink($abs_source);
1118 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1119 if ($abs_targ eq $abs_extra) {
1120 $extras{$extra} = "\e[32;1menabled\e[0m";
1122 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1124 } elsif (-e $abs_source) {
1125 my ($devext, $inoext) = stat($abs_extra);
1126 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1128 if ($devsrc == $devext && $inosrc == $inoext) {
1129 $extras{$extra} = "\e[32;1menabled\e[0m";
1131 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1134 open my $extfd, "<", $abs_extra;
1135 open my $srcfd, "<", $abs_source;
1137 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1138 $extras{$extra} = "\e[32;1menabled\e[0m";
1140 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1144 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1147 # Now let's add dependency info
1148 for my $extra (keys(%extras)) {
1149 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1150 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1151 my @deps = split / +/, getdependencies($abs_extra);
1152 for my $dep (@deps) {
1153 if (exists($extras{$dep})) {
1154 my $ref = \$extras{$dep}; # Take reference.
1155 if ($$ref !~ m/needed by/) {
1156 # First dependency found.
1157 if ($$ref =~ m/enabled/) {
1158 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1160 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1161 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1164 if ($$ref =~ m/enabled/) {
1165 $$ref .= ", \e[32;1m$extra\e[0m";
1167 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1173 for my $extra (sort {$a cmp $b} keys(%extras)) {
1174 my $text = $extras{$extra};
1175 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1176 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1178 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1181 return keys(%extras) if wantarray; # Can be used by manage_extras.
1184 sub enable_extras (@) {
1186 for my $extra (@extras) {
1187 my $extrapath = "src/modules/extra/$extra";
1188 if (!-e $extrapath) {
1189 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1192 my $source = "src/modules/$extra";
1194 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1197 # Get dependencies, and add them to be processed.
1198 my @deps = split / +/, getdependencies($extrapath);
1199 for my $dep (@deps) {
1200 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1201 if (!-e "src/modules/$dep") {
1202 if (-e "src/modules/extra/$dep") {
1203 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1206 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";
1210 print "Enabling $extra ... \n";
1211 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1215 sub disable_extras (@)
1217 opendir my $dd, "src/modules/extra/";
1218 my @files = readdir($dd);
1221 EXTRA: for my $extra (@extras) {
1222 my $extrapath = "src/modules/extra/$extra";
1223 my $source = "src/modules/$extra";
1224 if (!-e $extrapath) {
1225 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1228 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1229 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";
1232 # Check if anything needs this.
1233 for my $file (@files) {
1234 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1235 # File depends on this extra...
1236 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1237 # And is both enabled and not about to be disabled.
1238 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1239 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1245 print "Disabling $extra ... \n";
1246 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";