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);
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 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
97 'help' => sub { showhelp(); },
98 'update' => sub { update(); },
99 'clean' => sub { clean(); },
100 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
101 'enable-extras=s@' => \@opt_enableextras, # ^
102 'disable-extras=s@' => \@opt_disableextras, # ^
103 'generate-openssl-cert' => sub { make_openssl_cert(); exit(0); },
104 'generate-gnutls-cert' => sub { make_gnutls_cert(); exit(0); }
107 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
108 @opt_enableextras = split /,/, join(',', @opt_enableextras);
109 @opt_disableextras = split /,/, join(',', @opt_disableextras);
110 enable_extras(@opt_enableextras);
111 disable_extras(@opt_disableextras);
113 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
117 our $interactive = !(
118 (defined $opt_base_dir) ||
119 (defined $opt_config_dir) ||
120 (defined $opt_module_dir) ||
121 (defined $opt_base_dir) ||
122 (defined $opt_binary_dir) ||
123 (defined $opt_nointeractive) ||
125 (defined $opt_noipv6) ||
126 (defined $opt_kqueue) ||
127 (defined $opt_epoll) ||
128 (defined $opt_ports) ||
129 (defined $opt_use_openssl) ||
130 (defined $opt_nokqueue) ||
131 (defined $opt_noepoll) ||
132 (defined $opt_noports) ||
133 (defined $opt_maxbuf) ||
134 (defined $opt_system) ||
135 (defined $opt_uid) ||
136 (defined $opt_use_gnutls) ||
137 (defined $opt_freebsd_port)
140 chomp(our $topdir = getcwd());
141 our $this = resolve_directory($topdir); # PWD, Regardless.
142 our @modlist = (); # Declare for Module List..
143 our %config = (); # Initiate Configuration Hash..
144 $config{ME} = resolve_directory($topdir); # Present Working Directory
146 $config{BASE_DIR} = $config{ME}."/run";
148 if (defined $opt_base_dir) {
149 $config{BASE_DIR} = $opt_base_dir;
150 } elsif (defined $opt_system || defined $opt_uid) {
151 $config{BASE_DIR} = '/var/lib/inspircd';
154 if (defined $opt_system || defined $opt_uid) {
155 $config{UID} = $opt_uid || 'ircd';
156 $config{CONFIG_DIR} = '/etc/inspircd';
157 $config{MODULE_DIR} = '/usr/lib/inspircd';
158 $config{BINARY_DIR} = '/usr/sbin/';
159 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
162 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
163 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
164 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
165 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
168 if (defined $opt_config_dir) {
169 $config{CONFIG_DIR} = $opt_config_dir;
171 if (defined $opt_module_dir) {
172 $config{MODULE_DIR} = $opt_module_dir;
174 if (defined $opt_binary_dir) {
175 $config{BINARY_DIR} = $opt_binary_dir;
177 chomp($config{HAS_GNUTLS} = `pkg-config --modversion gnutls 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
179 if (defined $opt_freebsd_port)
181 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`);
182 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`);
183 $config{USE_FREEBSD_BASE_SSL} = "n";
187 if ($^O eq "freebsd")
189 # default: use base ssl
190 chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`); # OpenSSL version, freebsd specific
191 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`); # Port version, may be different
195 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version, others
196 $config{HAS_OPENSSL_PORT} = "";
200 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
201 chomp(our $openssl_ver = $config{HAS_OPENSSL});
202 $config{USE_GNUTLS} = "n";
203 if (defined $opt_use_gnutls)
205 $config{USE_GNUTLS} = "y"; # Use gnutls.
207 $config{USE_OPENSSL} = "n"; # Use openssl.
208 if (defined $opt_use_openssl)
210 $config{USE_OPENSSL} = "y";
213 if (!defined $opt_disable_debug) {
214 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
216 $config{OPTIMISATI} = "-O2";
219 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
220 $config{HAS_STDINT} = "false"; # stdint.h check
221 $config{USE_KQUEUE} = "y"; # kqueue enabled
222 if (defined $opt_nokqueue) {
223 $config{USE_KQUEUE} = "n";
225 $config{USE_POLL} = "y"; # poll enabled
226 $config{USE_EPOLL} = "y"; # epoll enabled
227 if (defined $opt_noepoll)
229 $config{USE_EPOLL} = "n";
231 $config{USE_PORTS} = "y"; # epoll enabled
232 if (defined $opt_noports)
234 $config{USE_PORTS} = "n";
236 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
237 $config{OSNAME} = $^O; # Operating System Name
238 $config{IS_DARWIN} = "NO"; # Is OSX?
239 $config{STARTSCRIPT} = "inspircd"; # start script?
240 $config{DESTINATION} = "BASE"; # Is target path.
241 if ($config{OSNAME} =~ /darwin/i)
243 $config{IS_DARWIN} = "YES";
244 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
245 $config{CC} = "xcrun clang++"; # C++ compiler for OSX.
249 $config{CC} = "g++"; # C++ compiler
253 $config{CC} = $opt_cc;
255 our $exec = $config{CC} . " -dumpversion | cut -c 1";
256 chomp($config{GCCVER} = `$exec`); # Major GCC Version
257 $exec = $config{CC} . " -dumpversion | cut -c 3";
258 chomp($config{GCCMINOR} = `$exec`);
259 $config{MAXBUF} = "512"; # Max buffer size
261 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/) {
262 $config{HAS_OPENSSL} = $1;
264 $config{HAS_OPENSSL} = "";
267 if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
268 if ($config{IS_DARWIN} eq "YES") {
269 print $config{CC} . " was not found! You require clang++ (the LLVM C++ compiler, part of the OSX developer tools) to build InspIRCd!\n";
271 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
276 # Get and Set some important vars..
281 unlink(".config.cache");
284 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
289 chomp($topdir = getcwd());
290 $this = resolve_directory($topdir); # PWD, Regardless.
292 # Does the cache file exist?
294 # No, No it doesn't.. *BASH*
295 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
298 # We've Loaded the cache file and all our variables..
299 print "Updating files...\n";
300 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
302 print "Disabling debug information (-g).\n";
303 $config{OPTIMISATI} = "";
305 $has_epoll = $config{HAS_EPOLL};
306 $has_ports = $config{HAS_PORTS};
307 $has_kqueue = $config{HAS_KQUEUE};
316 print "Configure update failed: $@\n";
325 $fail ||= system "$config{CC} -o test_$feature make/check_$feature.cpp >/dev/null 2>&1";
326 $fail ||= system "./test_$feature";
327 unlink "test_$feature";
331 print "Running non-interactive configure...\n" unless $interactive;
332 print "Checking for cache from previous configure... ";
333 print ((!getcache()) ? "not found\n" : "found\n");
334 $config{SYSTEM} = lc $^O;
335 print "Checking operating system version... $config{SYSTEM}\n";
337 $exec = $config{CC} . " -dumpversion | cut -c 1";
338 chomp($config{GCCVER} = `$exec`); # Major GCC Version
339 $exec = $config{CC} . " -dumpversion | cut -c 3";
340 chomp($config{GCCMINOR} = `$exec`);
342 printf "Checking if stdint.h exists... ";
343 $config{HAS_STDINT} = "true";
345 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
346 if ($config{HAS_STDINT} eq "true") {
349 print "yes\n" if $config{HAS_STDINT} eq "true";
350 print "no\n" if $config{HAS_STDINT} eq "false";
352 printf "Checking if strlcpy exists... ";
353 # Perform the strlcpy() test..
354 $config{HAS_STRLCPY} = "false";
356 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
358 while (defined(my $line = <STRLCPY>)) {
360 # try and find the delcaration of:
361 # size_t strlcpy(...)
362 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
363 $config{HAS_STRLCPY} = "true";
368 print "yes\n" if $config{HAS_STRLCPY} eq "true";
369 print "no\n" if $config{HAS_STRLCPY} eq "false";
371 printf "Checking if kqueue exists... ";
374 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
376 while (defined(my $line = <KQUEUE>)) {
378 # try and find the delcaration of:
380 if ($line =~ /int(\0x9|\s)+kqueue/) {
386 print "yes\n" if $has_kqueue == 1;
387 print "no\n" if $has_kqueue == 0;
389 printf "Checking for epoll support... ";
390 $has_epoll = test_compile('epoll');
391 print $has_epoll ? "yes\n" : "no\n";
393 printf "Checking for eventfd support... ";
394 $config{HAS_EVENTFD} = test_compile('eventfd') ? 'true' : 'false';
395 print $config{HAS_EVENTFD} eq 'true' ? "yes\n" : "no\n";
397 printf "Checking if Solaris I/O completion ports are available... ";
399 our $system = `uname -s`;
401 $has_ports = 1 if ($system eq "SunOS");
404 my $kernel = `uname -r`;
406 if (($kernel !~ /^5\.1./)) {
410 print "yes\n" if $has_ports == 1;
411 print "no\n" if $has_ports == 0;
413 $config{HAS_EPOLL} = $has_epoll;
414 $config{HAS_KQUEUE} = $has_kqueue;
416 printf "Checking for libgnutls... ";
417 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
418 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
420 $config{HAS_GNUTLS} = "y";
423 $config{HAS_GNUTLS} = "n";
427 $config{HAS_GNUTLS} = "n";
430 printf "Checking for openssl... ";
431 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
432 if (defined($openssl_ver) && ($openssl_ver ne "")) {
434 $config{HAS_OPENSSL} = "y";
437 $config{HAS_OPENSSL} = "n";
441 $config{HAS_OPENSSL} = "n";
444 printf "Checking if you are running an ancient, unsupported OS... ";
445 if ($config{OSNAME} =~ /FreeBSD/i)
447 my $version = `uname -r`;
448 if ($version =~ /^4\./)
451 print "FreeBSD 4.x is no longer supported. By ANYONE.\n";
452 print "To build, you will need to add the following to CXXFLAGS:\n";
453 print "\t-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1\n";
457 print "no ($version)\n";
462 print "no ($config{OSNAME})\n";
465 ################################################################################
466 # BEGIN INTERACTIVE PART #
467 ################################################################################
472 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
475 my $rev = getrevision();
476 # Display Introduction Message..
478 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
479 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
481 *** If you are unsure of any of these values, leave it blank for ***
482 *** standard settings that will work, and your server will run ***
483 *** using them. Please consult your IRC network admin if in doubt. ***
485 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
486 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
487 dir, otherwise you won't have a config file!
489 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
490 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
493 print " (Non-SVN build)";
497 $config{CHANGE_COMPILER} = "n";
498 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";
500 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
501 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
502 should NOT be used. You should probably specify a newer compiler.\n\n";
503 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
504 if ($config{CHANGE_COMPILER} =~ /y/i) {
505 print "What command do you want to use to invoke your compiler?\n";
506 print "[\e[1;32m$config{CC}\e[0m] -> ";
507 chomp($config{CC} = <STDIN>);
508 if ($config{CC} eq "") {
511 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
513 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
514 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
515 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
516 if ($config{GCCVER} < 3) {
517 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
521 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
528 # Directory Settings..
529 my $tmpbase = $config{BASE_DIR};
530 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
531 if ($tmpbase ne $config{BASE_DIR}) {
532 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
533 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
534 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
537 dir_check("are the configuration files", "CONFIG_DIR");
538 dir_check("are the modules to be compiled to", "MODULE_DIR");
539 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
540 dir_check("do you want the build to take place", "BUILD_DIR");
542 my $chose_hiperf = 0;
544 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?");
546 if ($config{USE_KQUEUE} eq "y") {
551 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?");
553 if ($config{USE_EPOLL} eq "y") {
558 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?");
560 if ($config{USE_PORTS} eq "y") {
565 if (!$chose_hiperf) {
566 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?");
567 if ($config{USE_POLL} ne "y")
569 print "No high-performance socket engines are available, or you chose\n";
570 print "not to enable one. Defaulting to select() engine.\n\n";
574 $config{USE_FREEBSD_BASE_SSL} = "n";
575 $config{USE_FREEBSD_PORTS_SSL} = "n";
576 if ($config{HAS_OPENSSL_PORT} ne "")
578 $config{USE_FREEBSD_PORTS_SSL} = "y";
579 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
580 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";
581 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
583 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
585 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
587 # update to port version
588 $openssl_ver = $config{HAS_OPENSSL_PORT};
593 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
596 $config{USE_SSL} = "n";
597 $config{MODUPDATE} = 'n';
599 if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
601 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
602 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
604 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
605 if ($config{USE_SSL} eq "y")
607 if ($config{HAS_GNUTLS} eq "y")
609 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
610 if ($config{USE_GNUTLS} eq "y")
612 print "\nUsing GnuTLS SSL module.\n";
616 if ($config{HAS_OPENSSL} eq "y")
618 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
619 if ($config{USE_OPENSSL} eq "y")
621 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
628 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed and\n";
629 print "is in your path.\n\n";
632 yesno('MODUPDATE',"Would you like to check for updates to third-party modules?");
634 if ($config{MODUPDATE} eq "y") {
635 print "Checking for upgrades to extra and third party modules... ";
636 system "./modulemanager upgrade";
640 # We are on a POSIX system, we can enable POSIX extras without asking
641 symlink "extra/m_regex_posix.cpp", "src/modules/m_regex_posix.cpp";
645 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
647 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
650 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
652 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
657 $config{CERTGEN} ||= 'y';
658 yesno('CERTGEN',"Would you like generate SSL certificates now?") if ($interactive && ($config{USE_GNUTLS} eq "y" || $config{USE_OPENSSL} eq "y"));
660 if ($config{USE_GNUTLS} eq "y") {
661 unless (-r "src/modules/m_ssl_gnutls.cpp") {
662 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
663 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
665 if ($interactive && $config{CERTGEN} eq 'y')
667 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
668 print "SSL Certificates Not found, Generating.. \n\n
669 *************************************************************
670 * Generating the Private Key may take some time, go grab a *
671 * Coffee. Even better, to generate some more entropy if it *
672 * is taking a while, open another console and type du / a *
673 * few times and get that HD going :) Then answer the *
674 * Questions which follow. If you are unsure, just hit enter *
675 *************************************************************\n\n";
676 $failed = make_gnutls_cert();
678 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
680 print "\nCertificate generation complete, copying to config directory... ";
681 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
682 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
687 print "SSL Certificates found, skipping.\n\n";
692 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
696 if ($config{USE_OPENSSL} eq "y") {
697 unless (-r "src/modules/m_ssl_openssl.cpp") {
698 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
699 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
702 if ($interactive && $config{CERTGEN} eq 'y')
704 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
705 print "SSL Certificates Not found, Generating.. \n\n
706 *************************************************************
707 * Generating the certificates may take some time, go grab a *
708 * coffee, or something. *
709 *************************************************************\n\n";
711 print "\nCertificate generation complete, copying to config directory... ";
712 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
713 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
714 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
717 print "SSL Certificates found, skipping.\n\n"
722 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
725 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
726 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
734 print "To build your server with these settings, please run '\e[1;32mmake\e[0m' now.\n";
735 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
736 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
737 print "modules in your config. This configure script has added those modules to the\n";
738 print "build process. For more info please refer to:\n";
739 print "\e[1;32mhttp://wiki.inspircd.org/Installation_From_Tarball\e[0m\n";
741 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
742 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
743 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";
746 if ($config{GCCVER} < "3") {
748 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
749 GCC 2.x series compilers only had partial (read as broken) C++ support, and
750 your compile will most likely fail horribly! If you have any problems, do NOT
751 report them to the bugtracker or forums without first upgrading your compiler
752 to a newer 3.x or 4.x (or whatever is available currently) version.
756 ################################################################################
758 ################################################################################
760 # Retrieves the .config.cache file, and loads values into the main config hash.
761 open(CACHE, ".config.cache") or return 0;
764 # Ignore Blank lines, and comments..
767 my ($key, $value) = split("=", $_, 2);
768 $value =~ /^\"(.*)\"$/;
769 # Do something with data here!
777 # Dump the contents of %config
778 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
779 open(FILEHANDLE, ">.config.cache");
780 foreach my $key (keys %config) {
781 print FILEHANDLE "$key=\"$config{$key}\"\n";
787 my ($desc, $hash_key) = @_;
790 print "In what directory $desc?\n";
791 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
792 chomp(my $var = <STDIN>);
794 $var = $config{$hash_key};
796 if ($var =~ /^\~\/(.+)$/) {
797 # Convert it to a full path..
798 $var = resolve_directory($ENV{HOME} . "/" . $1);
800 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
802 # Assume relative Path was given.. fill in the rest.
803 $var = $this . "/$var";
806 $var = resolve_directory($var);
808 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
809 chomp(my $tmp = <STDIN>);
810 if (($tmp eq "") || ($tmp =~ /^y/i)) {
811 # Attempt to Create the Dir..
814 File::Path::mkpath($var, 0, 0777);
817 unless (defined($chk) && -d $var) {
818 print "Unable to create directory. ($var)\n\n";
823 # They said they don't want to create, and we can't install there.
829 # Target exists, but is not a directory.
830 print "File $var exists, but is not a directory.\n\n";
834 # Either Dir Exists, or was created fine.
835 $config{$hash_key} = $var;
843 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
846 my($writeheader) = @_;
847 # First File.. inspircd_config.h
848 chomp(my $incos = `uname -n -s -r`);
849 chomp(my $version = `sh src/version.sh`);
850 chomp(my $revision2 = getrevision());
851 my $branch = "InspIRCd-0.0";
852 if ($version =~ /^(InspIRCd-[0-9]+\.[0-9]+)\.[0-9]+/)
856 if ($writeheader == 1)
858 print "Writing \e[1;32minspircd_config.h\e[0m\n";
859 open(FILEHANDLE, ">include/inspircd_config.h.tmp");
860 print FILEHANDLE <<EOF;
861 /* Auto generated by configure, do not modify! */
862 #ifndef __CONFIGURATION_AUTO__
863 #define __CONFIGURATION_AUTO__
865 /* this is for windows support. */
866 #define CoreExport /**/
867 #define DllExport /**/
869 #define CONFIG_PATH "$config{CONFIG_DIR}"
870 #define MOD_PATH "$config{MODULE_DIR}"
871 #define SOMAXCONN_S "$config{_SOMAXCONN}"
872 #define ENTRYPOINT int main(int argc, char** argv)
875 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
877 if ($config{OSNAME} =~ /SunOS/i) {
878 print FILEHANDLE "#define IS_SOLARIS\n";
880 if ($config{OSNAME} =~ /MINGW32/i) {
881 print FILEHANDLE "#define IS_MINGW\n";
883 if ($config{GCCVER} >= 3) {
884 print FILEHANDLE "#define GCC3\n";
887 (($config{GCCVER} == 4) && ($config{GCCMINOR} >= 3))
889 ($config{GCCVER} > 4)
891 print FILEHANDLE "#define HASHMAP_DEPRECATED\n";
893 if ($config{HAS_STRLCPY} eq "true") {
894 print FILEHANDLE "#define HAS_STRLCPY\n";
896 if ($config{HAS_STDINT} eq "true") {
897 print FILEHANDLE "#define HAS_STDINT\n";
899 if ($config{HAS_EVENTFD} eq 'true') {
900 print FILEHANDLE "#define HAS_EVENTFD\n";
902 if ($config{OSNAME} !~ /DARWIN/i) {
903 print FILEHANDLE "#define HAS_CLOCK_GETTIME\n";
906 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
907 print FILEHANDLE "#define USE_KQUEUE\n";
908 $config{SOCKETENGINE} = "socketengine_kqueue";
911 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
912 print FILEHANDLE "#define USE_EPOLL\n";
913 $config{SOCKETENGINE} = "socketengine_epoll";
916 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
917 print FILEHANDLE "#define USE_PORTS\n";
918 $config{SOCKETENGINE} = "socketengine_ports";
921 # user didn't choose either epoll or select for their OS.
922 # default them to USE_SELECT (ewwy puke puke)
924 print "no hi-perf, " . $config{USE_POLL};
925 if ($config{USE_POLL} eq "y")
927 print FILEHANDLE "#define USE_POLL\n";
928 $config{SOCKETENGINE} = "socketengine_poll";
932 print FILEHANDLE "#define USE_SELECT\n";
933 $config{SOCKETENGINE} = "socketengine_select";
936 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
939 open(FILEHANDLE, ">include/inspircd_version.h.tmp");
940 print FILEHANDLE <<EOF;
941 #define BRANCH "$branch"
942 #define VERSION "$version"
943 #define REVISION "$revision2"
944 #define SYSTEM "$incos"
948 for my $file (qw(include/inspircd_config.h include/inspircd_version.h)) {
950 open my $fh1, $file or $diff = 1;
951 open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
955 if (defined($line1) != defined($line2)) {
957 } elsif (!defined $line1) {
960 $diff = ($line1 ne $line2);
965 rename "$file.tmp", $file;
972 # Write all .in files.
975 my $exe = "inspircd";
977 # Do this once here, and cache it in the .*.inc files,
978 # rather than attempting to read src/version.sh from
979 # compiled code -- we might not have the source to hand.
980 # Fix for bug#177 by Brain.
982 chomp($version = `sh ./src/version.sh`);
983 chomp(my $revision = getrevision());
984 $version = "$version(r$revision)";
986 # We can actually parse any file starting with . and ending with .inc,
987 # but right now we only parse .inspircd.inc to form './inspircd'
988 prepare_dynamic_makefile();
990 my @dotfiles = qw(main.mk inspircd);
991 push @dotfiles, 'org.inspircd.plist' if $config{OSNAME} eq 'darwin';
993 foreach my $file (@dotfiles) {
994 open(FILEHANDLE, "make/template/$file") or die "Can't open make/template/$file: $!";
995 $_ = join '', <FILEHANDLE>;
998 $config{BUILD_DIR} ||= resolve_directory($config{ME}."/build");
1001 CC SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR UID
1002 STARTSCRIPT DESTINATION SOCKETENGINE
1004 s/\@$var\@/$config{$var}/g;
1006 s/\@EXECUTABLE\@/$exe/ if defined $exe;
1007 s/\@VERSION\@/$version/ if defined $version;
1009 if ($file eq 'main.mk') {
1010 print "Writing \e[1;32mGNUmakefile\e[0m ...\n";
1013 s/\@IFDEF (\S+)/ifdef $1/g;
1014 s/\@IFNDEF (\S+)/ifndef $1/g;
1015 s/\@IFEQ (\S+) (\S+)/ifeq ($1,$2)/g;
1016 s/\@ELSIFEQ (\S+) (\S+)/else ifeq ($1,$2)/g;
1019 s/ *\@BSD_ONLY .*\n//g;
1021 s/\@DO_EXPORT (.*)/export $1/g;
1022 open MKF, '>GNUmakefile' or die "Can't write to GNUmakefile: $!";
1026 print "Writing \e[1;32mBSDmakefile\e[0m ...\n";
1028 s/\@IFDEF (\S+)/.if defined($1)/g;
1029 s/\@IFNDEF (\S+)/.if !defined($1)/g;
1030 s/\@IFEQ (\S+) (\S+)/.if $1 == $2/g;
1031 s/\@ELSIFEQ (\S+) (\S+)/.elif $1 == $2/g;
1035 s/ *\@GNU_ONLY .*\n//g;
1037 $mk_tmp =~ s#\@DO_EXPORT (.*)#"MAKEENV += ".join ' ', map "$_='\${$_}'", split /\s/, $1#eg;
1038 open MKF, '>BSDmakefile' or die "Can't write to BSDmakefile: $!";
1042 print "Writing \e[1;32m$file\e[0m ...\n";
1043 open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
1044 print FILEHANDLE $_;
1049 chmod 0755, 'inspircd';
1055 for my $mod (@modlist) {
1056 getcompilerflags("src/modules/m_$mod.cpp");
1057 getlinkerflags("src/modules/m_$mod.cpp");
1061 sub prepare_dynamic_makefile
1067 $config{USE_EPOLL} = 0;
1071 $config{USE_KQUEUE} = 0;
1075 $config{USE_PORTS} = 0;
1079 # Routine to list out the extra/ modules that have been enabled.
1080 # Note: when getting any filenames out and comparing, it's important to lc it if the
1081 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1082 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1083 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1084 sub list_extras () {
1087 my $srcdir = File::Spec->catdir("src", "modules");
1088 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1091 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1092 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1095 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1096 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1099 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1101 EXTRA: for my $extra (@extras) {
1102 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1103 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1104 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1105 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1106 if (-l $abs_source) {
1107 # Symlink, is it in the right place?
1108 my $targ = readlink($abs_source);
1109 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1110 if ($abs_targ eq $abs_extra) {
1111 $extras{$extra} = "\e[32;1menabled\e[0m";
1113 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1115 } elsif (-e $abs_source) {
1116 my ($devext, $inoext) = stat($abs_extra);
1117 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1119 if ($devsrc == $devext && $inosrc == $inoext) {
1120 $extras{$extra} = "\e[32;1menabled\e[0m";
1122 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1125 open my $extfd, "<", $abs_extra;
1126 open my $srcfd, "<", $abs_source;
1128 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1129 $extras{$extra} = "\e[32;1menabled\e[0m";
1131 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1135 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1138 # Now let's add dependency info
1139 for my $extra (keys(%extras)) {
1140 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1141 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1142 my @deps = split / +/, getdependencies($abs_extra);
1143 for my $dep (@deps) {
1144 if (exists($extras{$dep})) {
1145 my $ref = \$extras{$dep}; # Take reference.
1146 if ($$ref !~ m/needed by/) {
1147 # First dependency found.
1148 if ($$ref =~ m/enabled/) {
1149 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1151 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1152 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1155 if ($$ref =~ m/enabled/) {
1156 $$ref .= ", \e[32;1m$extra\e[0m";
1158 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1164 for my $extra (sort {$a cmp $b} keys(%extras)) {
1165 my $text = $extras{$extra};
1166 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1167 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1169 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1172 return keys(%extras) if wantarray; # Can be used by manage_extras.
1175 sub enable_extras (@) {
1177 for my $extra (@extras) {
1178 my $extrapath = "src/modules/extra/$extra";
1179 if (!-e $extrapath) {
1180 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1183 my $source = "src/modules/$extra";
1185 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1188 # Get dependencies, and add them to be processed.
1189 my @deps = split / +/, getdependencies($extrapath);
1190 for my $dep (@deps) {
1191 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1192 if (!-e "src/modules/$dep") {
1193 if (-e "src/modules/extra/$dep") {
1194 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1197 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";
1201 print "Enabling $extra ... \n";
1202 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1206 sub disable_extras (@)
1208 opendir my $dd, "src/modules/extra/";
1209 my @files = readdir($dd);
1212 EXTRA: for my $extra (@extras) {
1213 my $extrapath = "src/modules/extra/$extra";
1214 my $source = "src/modules/$extra";
1215 if (!-e $extrapath) {
1216 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1219 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1220 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";
1223 # Check if anything needs this.
1224 for my $file (@files) {
1225 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1226 # File depends on this extra...
1227 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1228 # And is both enabled and not about to be disabled.
1229 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1230 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1236 print "Disabling $extra ... \n";
1237 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";