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.
265 $config{CC} = "g++"; # C++ compiler
269 $config{CC} = $opt_cc;
271 our $exec = $config{CC} . " -dumpversion | cut -c 1";
272 chomp($config{GCCVER} = `$exec`); # Major GCC Version
273 $exec = $config{CC} . " -dumpversion | cut -c 3";
274 chomp($config{GCCMINOR} = `$exec`);
275 $config{MAXBUF} = "512"; # Max buffer size
277 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)(?:[a-z])?(?:\-[a-z][0-9])?/) {
278 $config{HAS_OPENSSL} = $1;
280 $config{HAS_OPENSSL} = "";
283 if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
284 if ($config{IS_DARWIN} eq "YES") {
285 print $config{CC} . " was not found! You require clang++ (the LLVM C++ compiler, part of the OSX developer tools) to build InspIRCd!\n";
287 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
292 # Get and Set some important vars..
297 unlink(".config.cache");
300 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
305 chomp($topdir = getcwd());
306 $this = resolve_directory($topdir); # PWD, Regardless.
308 # Does the cache file exist?
310 # No, No it doesn't.. *BASH*
311 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
314 # We've Loaded the cache file and all our variables..
315 print "Updating files...\n";
316 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
318 print "Disabling debug information (-g).\n";
319 $config{OPTIMISATI} = "";
321 $has_epoll = $config{HAS_EPOLL};
322 $has_ports = $config{HAS_PORTS};
323 $has_kqueue = $config{HAS_KQUEUE};
332 print "Configure update failed: $@\n";
341 $fail ||= system "$config{CC} -o test_$feature make/check_$feature.cpp >/dev/null 2>&1";
342 $fail ||= system "./test_$feature";
343 unlink "test_$feature";
347 print "Running non-interactive configure...\n" unless $interactive;
348 print "Checking for cache from previous configure... ";
349 print ($cache_loaded ? "found\n" : "not found\n");
350 $config{SYSTEM} = lc $^O;
351 print "Checking operating system version... $config{SYSTEM}\n";
353 $exec = $config{CC} . " -dumpversion | cut -c 1";
354 chomp($config{GCCVER} = `$exec`); # Major GCC Version
355 $exec = $config{CC} . " -dumpversion | cut -c 3";
356 chomp($config{GCCMINOR} = `$exec`);
358 printf "Checking if stdint.h exists... ";
359 $config{HAS_STDINT} = "true";
361 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
362 if ($config{HAS_STDINT} eq "true") {
365 print "yes\n" if $config{HAS_STDINT} eq "true";
366 print "no\n" if $config{HAS_STDINT} eq "false";
368 printf "Checking if strlcpy exists... ";
369 # Perform the strlcpy() test..
370 $config{HAS_STRLCPY} = "false";
372 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
374 while (defined(my $line = <STRLCPY>)) {
376 # try and find the delcaration of:
377 # size_t strlcpy(...)
378 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
379 $config{HAS_STRLCPY} = "true";
384 print "yes\n" if $config{HAS_STRLCPY} eq "true";
385 print "no\n" if $config{HAS_STRLCPY} eq "false";
387 printf "Checking if kqueue exists... ";
390 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
392 while (defined(my $line = <KQUEUE>)) {
394 # try and find the delcaration of:
396 if ($line =~ /int(\0x9|\s)+kqueue/) {
402 print "yes\n" if $has_kqueue == 1;
403 print "no\n" if $has_kqueue == 0;
405 printf "Checking for epoll support... ";
406 $has_epoll = test_compile('epoll');
407 print $has_epoll ? "yes\n" : "no\n";
409 printf "Checking for eventfd support... ";
410 $config{HAS_EVENTFD} = test_compile('eventfd') ? 'true' : 'false';
411 print $config{HAS_EVENTFD} eq 'true' ? "yes\n" : "no\n";
413 printf "Checking if Solaris I/O completion ports are available... ";
415 our $system = `uname -s`;
417 $has_ports = 1 if ($system eq "SunOS");
420 my $kernel = `uname -r`;
422 if (($kernel !~ /^5\.1./)) {
426 print "yes\n" if $has_ports == 1;
427 print "no\n" if $has_ports == 0;
429 $config{HAS_EPOLL} = $has_epoll;
430 $config{HAS_KQUEUE} = $has_kqueue;
432 printf "Checking for libgnutls... ";
433 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
434 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
436 $config{HAS_GNUTLS} = "y";
439 $config{HAS_GNUTLS} = "n";
443 $config{HAS_GNUTLS} = "n";
446 printf "Checking for openssl... ";
447 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
448 if (defined($openssl_ver) && ($openssl_ver ne "")) {
450 $config{HAS_OPENSSL} = "y";
453 $config{HAS_OPENSSL} = "n";
457 $config{HAS_OPENSSL} = "n";
460 printf "Checking if you are running an ancient, unsupported OS... ";
461 if ($config{OSNAME} =~ /FreeBSD/i)
463 my $version = `uname -r`;
464 if ($version =~ /^4\./)
467 print "FreeBSD 4.x is no longer supported. By ANYONE.\n";
468 print "To build, you will need to add the following to CXXFLAGS:\n";
469 print "\t-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1\n";
473 print "no ($version)\n";
478 print "no ($config{OSNAME})\n";
481 ################################################################################
482 # BEGIN INTERACTIVE PART #
483 ################################################################################
488 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
491 my $rev = getrevision();
492 # Display Introduction Message..
494 Welcome to the \e[1mInspIRCd\e[0m configuration program! (\e[1minteractive mode\e[0m)
495 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
497 *** If you are unsure of any of these values, leave it blank for ***
498 *** standard settings that will work, and your server will run ***
499 *** using them. Please consult your IRC network admin if in doubt. ***
501 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
502 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
503 dir, otherwise you won't have a config file!
505 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
506 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
509 print " (Non-SVN build)";
513 $config{CHANGE_COMPILER} = "n";
514 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";
516 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
517 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
518 should NOT be used. You should probably specify a newer compiler.\n\n";
519 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
520 if ($config{CHANGE_COMPILER} =~ /y/i) {
521 print "What command do you want to use to invoke your compiler?\n";
522 print "[\e[1;32m$config{CC}\e[0m] -> ";
523 chomp($config{CC} = <STDIN>);
524 if ($config{CC} eq "") {
527 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
529 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
530 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
531 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
532 if ($config{GCCVER} < 3) {
533 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
537 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
544 # Directory Settings..
545 my $tmpbase = $config{BASE_DIR};
546 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
547 if ($tmpbase ne $config{BASE_DIR}) {
548 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
549 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
550 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data Directory
551 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log Directory
552 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
555 dir_check("are the configuration files", "CONFIG_DIR");
556 dir_check("are the modules to be compiled to", "MODULE_DIR");
557 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
558 dir_check("are variable data files to be located in", "DATA_DIR");
559 dir_check("are the logs to be stored in", "LOG_DIR");
560 dir_check("do you want the build to take place", "BUILD_DIR");
562 my $chose_hiperf = 0;
564 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?");
566 if ($config{USE_KQUEUE} eq "y") {
571 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?");
573 if ($config{USE_EPOLL} eq "y") {
578 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?");
580 if ($config{USE_PORTS} eq "y") {
585 if (!$chose_hiperf) {
586 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?");
587 if ($config{USE_POLL} ne "y")
589 print "No high-performance socket engines are available, or you chose\n";
590 print "not to enable one. Defaulting to select() engine.\n\n";
594 $config{USE_FREEBSD_BASE_SSL} = "n";
595 $config{USE_FREEBSD_PORTS_SSL} = "n";
596 if ($config{HAS_OPENSSL_PORT} ne "")
598 $config{USE_FREEBSD_PORTS_SSL} = "y";
599 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
600 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";
601 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
603 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
605 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
607 # update to port version
608 $openssl_ver = $config{HAS_OPENSSL_PORT};
613 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
616 $config{USE_SSL} = "n";
617 $config{MODUPDATE} = 'n';
619 if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
621 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
622 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
624 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
625 if ($config{USE_SSL} eq "y")
627 if ($config{HAS_GNUTLS} eq "y")
629 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
630 if ($config{USE_GNUTLS} eq "y")
632 print "\nUsing GnuTLS SSL module.\n";
636 if ($config{HAS_OPENSSL} eq "y")
638 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
639 if ($config{USE_OPENSSL} eq "y")
641 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
648 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed and\n";
649 print "is in your path.\n\n";
652 yesno('MODUPDATE',"Would you like to check for updates to third-party modules?");
654 if ($config{MODUPDATE} eq "y") {
655 print "Checking for upgrades to extra and third-party modules... ";
656 system "./modulemanager upgrade";
660 # We are on a POSIX system, we can enable POSIX extras without asking
661 symlink "extra/m_regex_posix.cpp", "src/modules/m_regex_posix.cpp";
665 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
667 print "Sorry, but I couldn't detect GnuTLS. Make sure gnutls-config is in your path.\n";
670 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
672 print "Sorry, but I couldn't detect OpenSSL. Make sure openssl is in your path.\n";
677 $config{CERTGEN} ||= 'y';
678 yesno('CERTGEN',"Would you like to generate SSL certificates now?") if ($interactive && ($config{USE_GNUTLS} eq "y" || $config{USE_OPENSSL} eq "y"));
680 if ($config{USE_GNUTLS} eq "y") {
681 unless (-r "src/modules/m_ssl_gnutls.cpp") {
682 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
683 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
685 if ($interactive && $config{CERTGEN} eq 'y')
687 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
688 print "SSL certificates not found, generating.. \n\n
689 *************************************************************
690 * Generating the private key may take some time, once done, *
691 * answer the questions which follow. If you are unsure, *
693 *************************************************************\n\n";
694 $failed = make_gnutls_cert();
696 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
698 print "\nCertificate generation complete, copying to config directory... ";
699 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
700 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
705 print "SSL certificates found, skipping.\n\n";
710 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
714 if ($config{USE_OPENSSL} eq "y") {
715 unless (-r "src/modules/m_ssl_openssl.cpp") {
716 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
717 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
720 if ($interactive && $config{CERTGEN} eq 'y')
722 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
723 print "SSL certificates not found, generating.. \n\n
724 *************************************************************
725 * Generating the certificates may take some time, go grab a *
726 * coffee or something. *
727 *************************************************************\n\n";
729 print "\nCertificate generation complete, copying to config directory... ";
730 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
731 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
732 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
735 print "SSL certificates found, skipping.\n\n"
740 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
743 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
744 print "Skipping SSL certificate generation as SSL support is not available.\n\n";
752 print "To build your server with these settings, please run '\e[1;32mmake\e[0m' now.\n";
753 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
754 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
755 print "modules in your config. This configure script has added those modules to the\n";
756 print "build process. For more info, please refer to:\n";
757 print "\e[1;32mhttp://wiki.inspircd.org/Installation_From_Tarball\e[0m\n";
759 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
760 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
761 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";
764 if ($config{GCCVER} < "3") {
766 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
767 GCC 2.x series compilers only had partial (read as broken) C++ support, and
768 your compile will most likely fail horribly! If you have any problems, do NOT
769 report them to the bugtracker or forums without first upgrading your compiler
770 to a newer 3.x or 4.x (or whatever is available currently) version.
774 ################################################################################
776 ################################################################################
778 # Retrieves the .config.cache file, and loads values into the main config hash.
779 open(CACHE, ".config.cache") or return 0;
782 # Ignore Blank lines, and comments..
785 my ($key, $value) = split("=", $_, 2);
786 $value =~ /^\"(.*)\"$/;
787 # Do something with data here!
795 # Dump the contents of %config
796 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
797 open(FILEHANDLE, ">.config.cache");
798 foreach my $key (keys %config) {
799 print FILEHANDLE "$key=\"$config{$key}\"\n";
805 my ($desc, $hash_key) = @_;
808 print "In what directory $desc?\n";
809 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
810 chomp(my $var = <STDIN>);
812 $var = $config{$hash_key};
814 if ($var =~ /^\~\/(.+)$/) {
815 # Convert it to a full path..
816 $var = resolve_directory($ENV{HOME} . "/" . $1);
818 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
820 # Assume relative Path was given.. fill in the rest.
821 $var = $this . "/$var";
824 $var = resolve_directory($var);
826 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
827 chomp(my $tmp = <STDIN>);
828 if (($tmp eq "") || ($tmp =~ /^y/i)) {
829 # Attempt to Create the Dir..
832 File::Path::mkpath($var, 0, 0777);
835 unless (defined($chk) && -d $var) {
836 print "Unable to create directory. ($var)\n\n";
841 # They said they don't want to create, and we can't install there.
847 # Target exists, but is not a directory.
848 print "File $var exists, but is not a directory.\n\n";
852 # Either Dir Exists, or was created fine.
853 $config{$hash_key} = $var;
861 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
864 my($writeheader) = @_;
865 # First File.. inspircd_config.h
866 chomp(my $incos = `uname -n -s -r`);
867 chomp(my $version = `sh src/version.sh`);
868 chomp(my $revision2 = getrevision());
869 my $branch = "InspIRCd-0.0";
870 if ($version =~ /^(InspIRCd-[0-9]+\.[0-9]+)\.[0-9]+/)
874 if ($writeheader == 1)
876 print "Writing \e[1;32minspircd_config.h\e[0m\n";
877 open(FILEHANDLE, ">include/inspircd_config.h.tmp");
878 print FILEHANDLE <<EOF;
879 /* Auto generated by configure, do not modify! */
880 #ifndef __CONFIGURATION_AUTO__
881 #define __CONFIGURATION_AUTO__
883 /* this is for windows support. */
884 #define CoreExport /**/
885 #define DllExport /**/
887 #define CONFIG_PATH "$config{CONFIG_DIR}"
888 #define DATA_PATH "$config{DATA_DIR}"
889 #define LOG_PATH "$config{LOG_DIR}"
890 #define MOD_PATH "$config{MODULE_DIR}"
891 #define SOMAXCONN_S "$config{_SOMAXCONN}"
892 #define ENTRYPOINT int main(int argc, char** argv)
895 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
897 if ($config{OSNAME} =~ /SunOS/i) {
898 print FILEHANDLE "#define IS_SOLARIS\n";
900 if ($config{OSNAME} =~ /MINGW32/i) {
901 print FILEHANDLE "#define IS_MINGW\n";
903 if ($config{GCCVER} >= 3) {
904 print FILEHANDLE "#define GCC3\n";
906 if ($config{HAS_STRLCPY} eq "true") {
907 print FILEHANDLE "#define HAS_STRLCPY\n";
909 if ($config{HAS_STDINT} eq "true") {
910 print FILEHANDLE "#define HAS_STDINT\n";
912 if ($config{HAS_EVENTFD} eq 'true') {
913 print FILEHANDLE "#define HAS_EVENTFD\n";
915 if ($config{OSNAME} !~ /DARWIN/i) {
916 print FILEHANDLE "#define HAS_CLOCK_GETTIME\n";
919 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
920 print FILEHANDLE "#define USE_KQUEUE\n";
921 $config{SOCKETENGINE} = "socketengine_kqueue";
924 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
925 print FILEHANDLE "#define USE_EPOLL\n";
926 $config{SOCKETENGINE} = "socketengine_epoll";
929 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
930 print FILEHANDLE "#define USE_PORTS\n";
931 $config{SOCKETENGINE} = "socketengine_ports";
934 # user didn't choose either epoll or select for their OS.
935 # default them to USE_SELECT (ewwy puke puke)
937 print "no hi-perf, " . $config{USE_POLL};
938 if ($config{USE_POLL} eq "y")
940 print FILEHANDLE "#define USE_POLL\n";
941 $config{SOCKETENGINE} = "socketengine_poll";
945 print FILEHANDLE "#define USE_SELECT\n";
946 $config{SOCKETENGINE} = "socketengine_select";
949 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
952 open(FILEHANDLE, ">include/inspircd_version.h.tmp");
953 print FILEHANDLE <<EOF;
954 #define BRANCH "$branch"
955 #define VERSION "$version"
956 #define REVISION "$revision2"
957 #define SYSTEM "$incos"
961 for my $file (qw(include/inspircd_config.h include/inspircd_version.h)) {
963 open my $fh1, $file or $diff = 1;
964 open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
968 if (defined($line1) != defined($line2)) {
970 } elsif (!defined $line1) {
973 $diff = ($line1 ne $line2);
978 rename "$file.tmp", $file;
985 # Write all .in files.
988 my $exe = "inspircd";
990 # Do this once here, and cache it in the .*.inc files,
991 # rather than attempting to read src/version.sh from
992 # compiled code -- we might not have the source to hand.
993 # Fix for bug#177 by Brain.
995 chomp($version = `sh ./src/version.sh`);
996 chomp(my $revision = getrevision());
997 $version = "$version(r$revision)";
999 # We can actually parse any file starting with . and ending with .inc,
1000 # but right now we only parse .inspircd.inc to form './inspircd'
1001 prepare_dynamic_makefile();
1003 my @dotfiles = qw(main.mk inspircd);
1004 push @dotfiles, 'org.inspircd.plist' if $config{OSNAME} eq 'darwin';
1006 foreach my $file (@dotfiles) {
1007 open(FILEHANDLE, "make/template/$file") or die "Can't open make/template/$file: $!";
1008 $_ = join '', <FILEHANDLE>;
1011 $config{BUILD_DIR} ||= resolve_directory($config{ME}."/build");
1014 CC SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR DATA_DIR UID
1015 STARTSCRIPT DESTINATION SOCKETENGINE
1017 s/\@$var\@/$config{$var}/g;
1019 s/\@EXECUTABLE\@/$exe/ if defined $exe;
1020 s/\@VERSION\@/$version/ if defined $version;
1022 if ($file eq 'main.mk') {
1023 print "Writing \e[1;32mGNUmakefile\e[0m ...\n";
1026 s/\@IFDEF (\S+)/ifdef $1/g;
1027 s/\@IFNDEF (\S+)/ifndef $1/g;
1028 s/\@IFEQ (\S+) (\S+)/ifeq ($1,$2)/g;
1029 s/\@ELSIFEQ (\S+) (\S+)/else ifeq ($1,$2)/g;
1032 s/ *\@BSD_ONLY .*\n//g;
1034 s/\@DO_EXPORT (.*)/export $1/g;
1035 open MKF, '>GNUmakefile' or die "Can't write to GNUmakefile: $!";
1039 print "Writing \e[1;32mBSDmakefile\e[0m ...\n";
1041 s/\@IFDEF (\S+)/.if defined($1)/g;
1042 s/\@IFNDEF (\S+)/.if !defined($1)/g;
1043 s/\@IFEQ (\S+) (\S+)/.if $1 == $2/g;
1044 s/\@ELSIFEQ (\S+) (\S+)/.elif $1 == $2/g;
1048 s/ *\@GNU_ONLY .*\n//g;
1050 $mk_tmp =~ s#\@DO_EXPORT (.*)#"MAKEENV += ".join ' ', map "$_='\${$_}'", split /\s/, $1#eg;
1051 open MKF, '>BSDmakefile' or die "Can't write to BSDmakefile: $!";
1055 print "Writing \e[1;32m$file\e[0m ...\n";
1056 open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
1057 print FILEHANDLE $_;
1062 chmod 0755, 'inspircd';
1068 for my $mod (@modlist) {
1069 getcompilerflags("src/modules/m_$mod.cpp");
1070 getlinkerflags("src/modules/m_$mod.cpp");
1074 sub prepare_dynamic_makefile
1080 $config{USE_EPOLL} = 0;
1084 $config{USE_KQUEUE} = 0;
1088 $config{USE_PORTS} = 0;
1092 # Routine to list out the extra/ modules that have been enabled.
1093 # Note: when getting any filenames out and comparing, it's important to lc it if the
1094 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1095 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1096 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1097 sub list_extras () {
1100 my $srcdir = File::Spec->catdir("src", "modules");
1101 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1104 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1105 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1108 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1109 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1112 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1114 EXTRA: for my $extra (@extras) {
1115 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1116 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1117 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1118 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1119 if (-l $abs_source) {
1120 # Symlink, is it in the right place?
1121 my $targ = readlink($abs_source);
1122 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1123 if ($abs_targ eq $abs_extra) {
1124 $extras{$extra} = "\e[32;1menabled\e[0m";
1126 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1128 } elsif (-e $abs_source) {
1129 my ($devext, $inoext) = stat($abs_extra);
1130 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1132 if ($devsrc == $devext && $inosrc == $inoext) {
1133 $extras{$extra} = "\e[32;1menabled\e[0m";
1135 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1138 open my $extfd, "<", $abs_extra;
1139 open my $srcfd, "<", $abs_source;
1141 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1142 $extras{$extra} = "\e[32;1menabled\e[0m";
1144 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1148 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1151 # Now let's add dependency info
1152 for my $extra (keys(%extras)) {
1153 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1154 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1155 my @deps = split / +/, getdependencies($abs_extra);
1156 for my $dep (@deps) {
1157 if (exists($extras{$dep})) {
1158 my $ref = \$extras{$dep}; # Take reference.
1159 if ($$ref !~ m/needed by/) {
1160 # First dependency found.
1161 if ($$ref =~ m/enabled/) {
1162 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1164 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1165 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1168 if ($$ref =~ m/enabled/) {
1169 $$ref .= ", \e[32;1m$extra\e[0m";
1171 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1177 for my $extra (sort {$a cmp $b} keys(%extras)) {
1178 my $text = $extras{$extra};
1179 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1180 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1182 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1185 return keys(%extras) if wantarray; # Can be used by manage_extras.
1188 sub enable_extras (@) {
1190 for my $extra (@extras) {
1191 my $extrapath = "src/modules/extra/$extra";
1192 if (!-e $extrapath) {
1193 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1196 my $source = "src/modules/$extra";
1198 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1201 # Get dependencies, and add them to be processed.
1202 my @deps = split / +/, getdependencies($extrapath);
1203 for my $dep (@deps) {
1204 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1205 if (!-e "src/modules/$dep") {
1206 if (-e "src/modules/extra/$dep") {
1207 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1210 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";
1214 print "Enabling $extra ... \n";
1215 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1219 sub disable_extras (@)
1221 opendir my $dd, "src/modules/extra/";
1222 my @files = readdir($dd);
1225 EXTRA: for my $extra (@extras) {
1226 my $extrapath = "src/modules/extra/$extra";
1227 my $source = "src/modules/$extra";
1228 if (!-e $extrapath) {
1229 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1232 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1233 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";
1236 # Check if anything needs this.
1237 for my $file (@files) {
1238 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1239 # File depends on this extra...
1240 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1241 # And is both enabled and not about to be disabled.
1242 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1243 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1249 print "Disabling $extra ... \n";
1250 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";