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 $config{ME} = resolve_directory($topdir); # Present Working Directory
150 $config{BASE_DIR} = $config{ME}."/run";
152 if (defined $opt_base_dir) {
153 $config{BASE_DIR} = $opt_base_dir;
154 } elsif (defined $opt_system || defined $opt_uid) {
155 $config{BASE_DIR} = '/var/lib/inspircd';
158 if (defined $opt_system || defined $opt_uid) {
159 $config{UID} = $opt_uid || 'ircd';
160 $config{CONFIG_DIR} = '/etc/inspircd';
161 $config{MODULE_DIR} = '/usr/lib/inspircd';
162 $config{BINARY_DIR} = '/usr/sbin/';
163 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
164 $config{DATA_DIR} = '/var/inspircd';
165 $config{LOG_DIR} = '/var/log/inspircd';
168 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
169 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
170 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
171 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
172 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data directory
173 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log directory
176 if (defined $opt_config_dir) {
177 $config{CONFIG_DIR} = $opt_config_dir;
179 if (defined $opt_module_dir) {
180 $config{MODULE_DIR} = $opt_module_dir;
182 if (defined $opt_binary_dir) {
183 $config{BINARY_DIR} = $opt_binary_dir;
185 if (defined $opt_data_dir) {
186 $config{DATA_DIR} = $opt_data_dir;
188 if (defined $opt_log_dir) {
189 $config{LOG_DIR} = $opt_log_dir;
191 chomp($config{HAS_GNUTLS} = `pkg-config --modversion gnutls 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
193 if (defined $opt_freebsd_port)
195 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`);
196 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`);
197 $config{USE_FREEBSD_BASE_SSL} = "n";
201 if ($^O eq "freebsd")
203 # default: use base ssl
204 chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`); # OpenSSL version, freebsd specific
205 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`); # Port version, may be different
209 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version, others
210 $config{HAS_OPENSSL_PORT} = "";
214 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
215 chomp(our $openssl_ver = $config{HAS_OPENSSL});
216 $config{USE_GNUTLS} = "n";
217 if (defined $opt_use_gnutls)
219 $config{USE_GNUTLS} = "y"; # Use gnutls.
221 $config{USE_OPENSSL} = "n"; # Use openssl.
222 if (defined $opt_use_openssl)
224 $config{USE_OPENSSL} = "y";
227 if (!defined $opt_disable_debug) {
228 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
230 $config{OPTIMISATI} = "-O2";
233 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
234 $config{HAS_STDINT} = "false"; # stdint.h check
235 $config{USE_KQUEUE} = "y"; # kqueue enabled
236 if (defined $opt_nokqueue) {
237 $config{USE_KQUEUE} = "n";
239 $config{USE_POLL} = "y"; # poll enabled
240 $config{USE_EPOLL} = "y"; # epoll enabled
241 if (defined $opt_noepoll)
243 $config{USE_EPOLL} = "n";
245 $config{USE_PORTS} = "y"; # epoll enabled
246 if (defined $opt_noports)
248 $config{USE_PORTS} = "n";
250 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
251 $config{OSNAME} = $^O; # Operating System Name
252 $config{IS_DARWIN} = "NO"; # Is OSX?
253 $config{STARTSCRIPT} = "inspircd"; # start script?
254 $config{DESTINATION} = "BASE"; # Is target path.
255 if ($config{OSNAME} =~ /darwin/i)
257 $config{IS_DARWIN} = "YES";
258 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
259 $config{CC} = "xcrun clang++"; # C++ compiler for OSX.
263 $config{CC} = "g++"; # C++ compiler
267 $config{CC} = $opt_cc;
269 our $exec = $config{CC} . " -dumpversion | cut -c 1";
270 chomp($config{GCCVER} = `$exec`); # Major GCC Version
271 $exec = $config{CC} . " -dumpversion | cut -c 3";
272 chomp($config{GCCMINOR} = `$exec`);
273 $config{MAXBUF} = "512"; # Max buffer size
275 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/) {
276 $config{HAS_OPENSSL} = $1;
278 $config{HAS_OPENSSL} = "";
281 if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
282 if ($config{IS_DARWIN} eq "YES") {
283 print $config{CC} . " was not found! You require clang++ (the LLVM C++ compiler, part of the OSX developer tools) to build InspIRCd!\n";
285 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
290 # Get and Set some important vars..
295 unlink(".config.cache");
298 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
303 chomp($topdir = getcwd());
304 $this = resolve_directory($topdir); # PWD, Regardless.
306 # Does the cache file exist?
308 # No, No it doesn't.. *BASH*
309 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
312 # We've Loaded the cache file and all our variables..
313 print "Updating files...\n";
314 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
316 print "Disabling debug information (-g).\n";
317 $config{OPTIMISATI} = "";
319 $has_epoll = $config{HAS_EPOLL};
320 $has_ports = $config{HAS_PORTS};
321 $has_kqueue = $config{HAS_KQUEUE};
330 print "Configure update failed: $@\n";
339 $fail ||= system "$config{CC} -o test_$feature make/check_$feature.cpp >/dev/null 2>&1";
340 $fail ||= system "./test_$feature";
341 unlink "test_$feature";
345 print "Running non-interactive configure...\n" unless $interactive;
346 print "Checking for cache from previous configure... ";
347 print ((!getcache()) ? "not found\n" : "found\n");
348 $config{SYSTEM} = lc $^O;
349 print "Checking operating system version... $config{SYSTEM}\n";
351 $exec = $config{CC} . " -dumpversion | cut -c 1";
352 chomp($config{GCCVER} = `$exec`); # Major GCC Version
353 $exec = $config{CC} . " -dumpversion | cut -c 3";
354 chomp($config{GCCMINOR} = `$exec`);
356 printf "Checking if stdint.h exists... ";
357 $config{HAS_STDINT} = "true";
359 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
360 if ($config{HAS_STDINT} eq "true") {
363 print "yes\n" if $config{HAS_STDINT} eq "true";
364 print "no\n" if $config{HAS_STDINT} eq "false";
366 printf "Checking if strlcpy exists... ";
367 # Perform the strlcpy() test..
368 $config{HAS_STRLCPY} = "false";
370 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
372 while (defined(my $line = <STRLCPY>)) {
374 # try and find the delcaration of:
375 # size_t strlcpy(...)
376 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
377 $config{HAS_STRLCPY} = "true";
382 print "yes\n" if $config{HAS_STRLCPY} eq "true";
383 print "no\n" if $config{HAS_STRLCPY} eq "false";
385 printf "Checking if kqueue exists... ";
388 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
390 while (defined(my $line = <KQUEUE>)) {
392 # try and find the delcaration of:
394 if ($line =~ /int(\0x9|\s)+kqueue/) {
400 print "yes\n" if $has_kqueue == 1;
401 print "no\n" if $has_kqueue == 0;
403 printf "Checking for epoll support... ";
404 $has_epoll = test_compile('epoll');
405 print $has_epoll ? "yes\n" : "no\n";
407 printf "Checking for eventfd support... ";
408 $config{HAS_EVENTFD} = test_compile('eventfd') ? 'true' : 'false';
409 print $config{HAS_EVENTFD} eq 'true' ? "yes\n" : "no\n";
411 printf "Checking if Solaris I/O completion ports are available... ";
413 our $system = `uname -s`;
415 $has_ports = 1 if ($system eq "SunOS");
418 my $kernel = `uname -r`;
420 if (($kernel !~ /^5\.1./)) {
424 print "yes\n" if $has_ports == 1;
425 print "no\n" if $has_ports == 0;
427 $config{HAS_EPOLL} = $has_epoll;
428 $config{HAS_KQUEUE} = $has_kqueue;
430 printf "Checking for libgnutls... ";
431 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
432 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
434 $config{HAS_GNUTLS} = "y";
437 $config{HAS_GNUTLS} = "n";
441 $config{HAS_GNUTLS} = "n";
444 printf "Checking for openssl... ";
445 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
446 if (defined($openssl_ver) && ($openssl_ver ne "")) {
448 $config{HAS_OPENSSL} = "y";
451 $config{HAS_OPENSSL} = "n";
455 $config{HAS_OPENSSL} = "n";
458 printf "Checking if you are running an ancient, unsupported OS... ";
459 if ($config{OSNAME} =~ /FreeBSD/i)
461 my $version = `uname -r`;
462 if ($version =~ /^4\./)
465 print "FreeBSD 4.x is no longer supported. By ANYONE.\n";
466 print "To build, you will need to add the following to CXXFLAGS:\n";
467 print "\t-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1\n";
471 print "no ($version)\n";
476 print "no ($config{OSNAME})\n";
479 ################################################################################
480 # BEGIN INTERACTIVE PART #
481 ################################################################################
486 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
489 my $rev = getrevision();
490 # Display Introduction Message..
492 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
493 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
495 *** If you are unsure of any of these values, leave it blank for ***
496 *** standard settings that will work, and your server will run ***
497 *** using them. Please consult your IRC network admin if in doubt. ***
499 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
500 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
501 dir, otherwise you won't have a config file!
503 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
504 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
507 print " (Non-SVN build)";
511 $config{CHANGE_COMPILER} = "n";
512 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";
514 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
515 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
516 should NOT be used. You should probably specify a newer compiler.\n\n";
517 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
518 if ($config{CHANGE_COMPILER} =~ /y/i) {
519 print "What command do you want to use to invoke your compiler?\n";
520 print "[\e[1;32m$config{CC}\e[0m] -> ";
521 chomp($config{CC} = <STDIN>);
522 if ($config{CC} eq "") {
525 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
527 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
528 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
529 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
530 if ($config{GCCVER} < 3) {
531 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
535 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
542 # Directory Settings..
543 my $tmpbase = $config{BASE_DIR};
544 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
545 if ($tmpbase ne $config{BASE_DIR}) {
546 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
547 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
548 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data Directory
549 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log Directory
550 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
553 dir_check("are the configuration files", "CONFIG_DIR");
554 dir_check("are the modules to be compiled to", "MODULE_DIR");
555 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
556 dir_check("are variable data files to be located in", "DATA_DIR");
557 dir_check("are the logs to be stored in", "LOG_DIR");
558 dir_check("do you want the build to take place", "BUILD_DIR");
560 my $chose_hiperf = 0;
562 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?");
564 if ($config{USE_KQUEUE} eq "y") {
569 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?");
571 if ($config{USE_EPOLL} eq "y") {
576 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?");
578 if ($config{USE_PORTS} eq "y") {
583 if (!$chose_hiperf) {
584 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?");
585 if ($config{USE_POLL} ne "y")
587 print "No high-performance socket engines are available, or you chose\n";
588 print "not to enable one. Defaulting to select() engine.\n\n";
592 $config{USE_FREEBSD_BASE_SSL} = "n";
593 $config{USE_FREEBSD_PORTS_SSL} = "n";
594 if ($config{HAS_OPENSSL_PORT} ne "")
596 $config{USE_FREEBSD_PORTS_SSL} = "y";
597 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
598 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";
599 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
601 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
603 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
605 # update to port version
606 $openssl_ver = $config{HAS_OPENSSL_PORT};
611 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
614 $config{USE_SSL} = "n";
615 $config{MODUPDATE} = 'n';
617 if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
619 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
620 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
622 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
623 if ($config{USE_SSL} eq "y")
625 if ($config{HAS_GNUTLS} eq "y")
627 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
628 if ($config{USE_GNUTLS} eq "y")
630 print "\nUsing GnuTLS SSL module.\n";
634 if ($config{HAS_OPENSSL} eq "y")
636 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
637 if ($config{USE_OPENSSL} eq "y")
639 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
646 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed and\n";
647 print "is in your path.\n\n";
650 yesno('MODUPDATE',"Would you like to check for updates to third-party modules?");
652 if ($config{MODUPDATE} eq "y") {
653 print "Checking for upgrades to extra and third party modules... ";
654 system "./modulemanager upgrade";
658 # We are on a POSIX system, we can enable POSIX extras without asking
659 symlink "extra/m_regex_posix.cpp", "src/modules/m_regex_posix.cpp";
663 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
665 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
668 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
670 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
675 $config{CERTGEN} ||= 'y';
676 yesno('CERTGEN',"Would you like generate SSL certificates now?") if ($interactive && ($config{USE_GNUTLS} eq "y" || $config{USE_OPENSSL} eq "y"));
678 if ($config{USE_GNUTLS} eq "y") {
679 unless (-r "src/modules/m_ssl_gnutls.cpp") {
680 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
681 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
683 if ($interactive && $config{CERTGEN} eq 'y')
685 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
686 print "SSL Certificates Not found, Generating.. \n\n
687 *************************************************************
688 * Generating the Private Key may take some time, go grab a *
689 * Coffee. Even better, to generate some more entropy if it *
690 * is taking a while, open another console and type du / a *
691 * few times and get that HD going :) Then answer the *
692 * Questions which follow. If you are unsure, just hit enter *
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, 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";
907 (($config{GCCVER} == 4) && ($config{GCCMINOR} >= 3))
909 ($config{GCCVER} > 4)
911 print FILEHANDLE "#define HASHMAP_DEPRECATED\n";
913 if ($config{HAS_STRLCPY} eq "true") {
914 print FILEHANDLE "#define HAS_STRLCPY\n";
916 if ($config{HAS_STDINT} eq "true") {
917 print FILEHANDLE "#define HAS_STDINT\n";
919 if ($config{HAS_EVENTFD} eq 'true') {
920 print FILEHANDLE "#define HAS_EVENTFD\n";
922 if ($config{OSNAME} !~ /DARWIN/i) {
923 print FILEHANDLE "#define HAS_CLOCK_GETTIME\n";
926 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
927 print FILEHANDLE "#define USE_KQUEUE\n";
928 $config{SOCKETENGINE} = "socketengine_kqueue";
931 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
932 print FILEHANDLE "#define USE_EPOLL\n";
933 $config{SOCKETENGINE} = "socketengine_epoll";
936 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
937 print FILEHANDLE "#define USE_PORTS\n";
938 $config{SOCKETENGINE} = "socketengine_ports";
941 # user didn't choose either epoll or select for their OS.
942 # default them to USE_SELECT (ewwy puke puke)
944 print "no hi-perf, " . $config{USE_POLL};
945 if ($config{USE_POLL} eq "y")
947 print FILEHANDLE "#define USE_POLL\n";
948 $config{SOCKETENGINE} = "socketengine_poll";
952 print FILEHANDLE "#define USE_SELECT\n";
953 $config{SOCKETENGINE} = "socketengine_select";
956 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
959 open(FILEHANDLE, ">include/inspircd_version.h.tmp");
960 print FILEHANDLE <<EOF;
961 #define BRANCH "$branch"
962 #define VERSION "$version"
963 #define REVISION "$revision2"
964 #define SYSTEM "$incos"
968 for my $file (qw(include/inspircd_config.h include/inspircd_version.h)) {
970 open my $fh1, $file or $diff = 1;
971 open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
975 if (defined($line1) != defined($line2)) {
977 } elsif (!defined $line1) {
980 $diff = ($line1 ne $line2);
985 rename "$file.tmp", $file;
992 # Write all .in files.
995 my $exe = "inspircd";
997 # Do this once here, and cache it in the .*.inc files,
998 # rather than attempting to read src/version.sh from
999 # compiled code -- we might not have the source to hand.
1000 # Fix for bug#177 by Brain.
1002 chomp($version = `sh ./src/version.sh`);
1003 chomp(my $revision = getrevision());
1004 $version = "$version(r$revision)";
1006 # We can actually parse any file starting with . and ending with .inc,
1007 # but right now we only parse .inspircd.inc to form './inspircd'
1008 prepare_dynamic_makefile();
1010 my @dotfiles = qw(main.mk inspircd);
1011 push @dotfiles, 'org.inspircd.plist' if $config{OSNAME} eq 'darwin';
1013 foreach my $file (@dotfiles) {
1014 open(FILEHANDLE, "make/template/$file") or die "Can't open make/template/$file: $!";
1015 $_ = join '', <FILEHANDLE>;
1018 $config{BUILD_DIR} ||= resolve_directory($config{ME}."/build");
1021 CC SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR DATA_DIR UID
1022 STARTSCRIPT DESTINATION SOCKETENGINE
1024 s/\@$var\@/$config{$var}/g;
1026 s/\@EXECUTABLE\@/$exe/ if defined $exe;
1027 s/\@VERSION\@/$version/ if defined $version;
1029 if ($file eq 'main.mk') {
1030 print "Writing \e[1;32mGNUmakefile\e[0m ...\n";
1033 s/\@IFDEF (\S+)/ifdef $1/g;
1034 s/\@IFNDEF (\S+)/ifndef $1/g;
1035 s/\@IFEQ (\S+) (\S+)/ifeq ($1,$2)/g;
1036 s/\@ELSIFEQ (\S+) (\S+)/else ifeq ($1,$2)/g;
1039 s/ *\@BSD_ONLY .*\n//g;
1041 s/\@DO_EXPORT (.*)/export $1/g;
1042 open MKF, '>GNUmakefile' or die "Can't write to GNUmakefile: $!";
1046 print "Writing \e[1;32mBSDmakefile\e[0m ...\n";
1048 s/\@IFDEF (\S+)/.if defined($1)/g;
1049 s/\@IFNDEF (\S+)/.if !defined($1)/g;
1050 s/\@IFEQ (\S+) (\S+)/.if $1 == $2/g;
1051 s/\@ELSIFEQ (\S+) (\S+)/.elif $1 == $2/g;
1055 s/ *\@GNU_ONLY .*\n//g;
1057 $mk_tmp =~ s#\@DO_EXPORT (.*)#"MAKEENV += ".join ' ', map "$_='\${$_}'", split /\s/, $1#eg;
1058 open MKF, '>BSDmakefile' or die "Can't write to BSDmakefile: $!";
1062 print "Writing \e[1;32m$file\e[0m ...\n";
1063 open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
1064 print FILEHANDLE $_;
1069 chmod 0755, 'inspircd';
1075 for my $mod (@modlist) {
1076 getcompilerflags("src/modules/m_$mod.cpp");
1077 getlinkerflags("src/modules/m_$mod.cpp");
1081 sub prepare_dynamic_makefile
1087 $config{USE_EPOLL} = 0;
1091 $config{USE_KQUEUE} = 0;
1095 $config{USE_PORTS} = 0;
1099 # Routine to list out the extra/ modules that have been enabled.
1100 # Note: when getting any filenames out and comparing, it's important to lc it if the
1101 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1102 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1103 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1104 sub list_extras () {
1107 my $srcdir = File::Spec->catdir("src", "modules");
1108 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1111 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1112 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1115 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1116 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1119 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1121 EXTRA: for my $extra (@extras) {
1122 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1123 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1124 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1125 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1126 if (-l $abs_source) {
1127 # Symlink, is it in the right place?
1128 my $targ = readlink($abs_source);
1129 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1130 if ($abs_targ eq $abs_extra) {
1131 $extras{$extra} = "\e[32;1menabled\e[0m";
1133 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1135 } elsif (-e $abs_source) {
1136 my ($devext, $inoext) = stat($abs_extra);
1137 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1139 if ($devsrc == $devext && $inosrc == $inoext) {
1140 $extras{$extra} = "\e[32;1menabled\e[0m";
1142 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1145 open my $extfd, "<", $abs_extra;
1146 open my $srcfd, "<", $abs_source;
1148 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1149 $extras{$extra} = "\e[32;1menabled\e[0m";
1151 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1155 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1158 # Now let's add dependency info
1159 for my $extra (keys(%extras)) {
1160 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1161 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1162 my @deps = split / +/, getdependencies($abs_extra);
1163 for my $dep (@deps) {
1164 if (exists($extras{$dep})) {
1165 my $ref = \$extras{$dep}; # Take reference.
1166 if ($$ref !~ m/needed by/) {
1167 # First dependency found.
1168 if ($$ref =~ m/enabled/) {
1169 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1171 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1172 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1175 if ($$ref =~ m/enabled/) {
1176 $$ref .= ", \e[32;1m$extra\e[0m";
1178 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1184 for my $extra (sort {$a cmp $b} keys(%extras)) {
1185 my $text = $extras{$extra};
1186 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1187 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1189 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1192 return keys(%extras) if wantarray; # Can be used by manage_extras.
1195 sub enable_extras (@) {
1197 for my $extra (@extras) {
1198 my $extrapath = "src/modules/extra/$extra";
1199 if (!-e $extrapath) {
1200 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1203 my $source = "src/modules/$extra";
1205 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1208 # Get dependencies, and add them to be processed.
1209 my @deps = split / +/, getdependencies($extrapath);
1210 for my $dep (@deps) {
1211 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1212 if (!-e "src/modules/$dep") {
1213 if (-e "src/modules/extra/$dep") {
1214 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1217 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";
1221 print "Enabling $extra ... \n";
1222 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1226 sub disable_extras (@)
1228 opendir my $dd, "src/modules/extra/";
1229 my @files = readdir($dd);
1232 EXTRA: for my $extra (@extras) {
1233 my $extrapath = "src/modules/extra/$extra";
1234 my $source = "src/modules/$extra";
1235 if (!-e $extrapath) {
1236 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1239 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1240 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";
1243 # Check if anything needs this.
1244 for my $file (@files) {
1245 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1246 # File depends on this extra...
1247 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1248 # And is both enabled and not about to be disabled.
1249 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1250 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1256 print "Disabling $extra ... \n";
1257 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";