4 # InspIRCd -- Internet Relay Chat Daemon
6 # Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
7 # Copyright (C) 2007, 2009 Dennis Friis <peavey@inspircd.org>
8 # Copyright (C) 2003, 2006-2008 Craig Edwards <craigedwards@brainbox.cc>
9 # Copyright (C) 2006-2008 Robin Burchell <robin+git@viroteck.net>
10 # Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
11 # Copyright (C) 2007 John Brooks <john.brooks@dereferenced.net>
12 # Copyright (C) 2006 Oliver Lupton <oliverlupton@gmail.com>
13 # Copyright (C) 2003-2006 Craig McLure <craig@chatspike.net>
15 # This file is part of InspIRCd. InspIRCd is free software: you can
16 # redistribute it and/or modify it under the terms of the GNU General Public
17 # License as published by the Free Software Foundation, version 2.
19 # This program is distributed in the hope that it will be useful, but WITHOUT
20 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
24 # You should have received a copy of the GNU General Public License
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
34 use warnings FATAL => qw(all);
41 # Utility functions for our buildsystem
45 use make::opensslcert;
47 ###############################################################################################
49 # NON-EDITABLE VARIABLES
51 ###############################################################################################
53 our ($opt_use_gnutls, $opt_rebuild, $opt_use_openssl, $opt_nointeractive, $opt_ports,
54 $opt_epoll, $opt_kqueue, $opt_noports, $opt_noepoll, $opt_nokqueue,
55 $opt_noipv6, $opt_maxbuf, $opt_disable_debug, $opt_freebsd_port,
56 $opt_system, $opt_uid);
58 our ($opt_cc, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir, $opt_data_dir, $opt_log_dir);
62 sub enable_extras (@);
64 sub disable_extras (@);
67 my @opt_disableextras;
70 'enable-gnutls' => \$opt_use_gnutls,
71 'rebuild' => \$opt_rebuild,
72 'system' => \$opt_system,
74 'enable-openssl' => \$opt_use_openssl,
75 'disable-interactive' => \$opt_nointeractive,
76 'enable-ports' => \$opt_ports,
77 'enable-epoll' => \$opt_epoll,
78 'enable-kqueue' => \$opt_kqueue,
79 'disable-ports' => \$opt_noports,
80 'disable-epoll' => \$opt_noepoll,
81 'disable-kqueue' => \$opt_nokqueue,
82 'disable-ipv6' => \$opt_noipv6,
83 'with-cc=s' => \$opt_cc,
84 'with-maxbuf=i' => \$opt_maxbuf,
85 'enable-freebsd-ports-openssl' => \$opt_freebsd_port,
86 'prefix=s' => \$opt_base_dir,
87 'config-dir=s' => \$opt_config_dir,
88 'module-dir=s' => \$opt_module_dir,
89 'binary-dir=s' => \$opt_binary_dir,
90 'data-dir=s' => \$opt_data_dir,
91 'log-dir=s' => \$opt_log_dir,
92 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
93 'help' => sub { showhelp(); },
94 'update' => sub { update(); },
95 'clean' => sub { clean(); },
96 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
97 'enable-extras=s@' => \@opt_enableextras, # ^
98 'disable-extras=s@' => \@opt_disableextras, # ^
99 'generate-openssl-cert' => sub { make_openssl_cert(); exit(0); },
100 'generate-gnutls-cert' => sub { make_gnutls_cert(); exit(0); }
103 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
104 @opt_enableextras = split /,/, join(',', @opt_enableextras);
105 @opt_disableextras = split /,/, join(',', @opt_disableextras);
106 enable_extras(@opt_enableextras);
107 disable_extras(@opt_disableextras);
109 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
113 our $interactive = !(
114 (defined $opt_base_dir) ||
115 (defined $opt_config_dir) ||
116 (defined $opt_module_dir) ||
117 (defined $opt_base_dir) ||
118 (defined $opt_binary_dir) ||
119 (defined $opt_data_dir) ||
120 (defined $opt_log_dir) ||
121 (defined $opt_nointeractive) ||
123 (defined $opt_noipv6) ||
124 (defined $opt_kqueue) ||
125 (defined $opt_epoll) ||
126 (defined $opt_ports) ||
127 (defined $opt_use_openssl) ||
128 (defined $opt_nokqueue) ||
129 (defined $opt_noepoll) ||
130 (defined $opt_noports) ||
131 (defined $opt_maxbuf) ||
132 (defined $opt_system) ||
133 (defined $opt_uid) ||
134 (defined $opt_use_gnutls) ||
135 (defined $opt_freebsd_port)
138 chomp(our $topdir = getcwd());
139 our $this = resolve_directory($topdir); # PWD, Regardless.
140 our @modlist = (); # Declare for Module List..
141 our %config = (); # Initiate Configuration Hash..
142 our $cache_loaded = getcache();
143 $config{ME} = resolve_directory($topdir); # Present Working Directory
145 $config{BASE_DIR} ||= $config{ME}."/run";
147 if (defined $opt_base_dir) {
148 $config{BASE_DIR} = $opt_base_dir;
149 } elsif (defined $opt_system) {
150 $config{BASE_DIR} = '/var/lib/inspircd';
153 if (defined $opt_system) {
154 $config{UID} = $opt_uid || 'ircd';
155 $config{CONFIG_DIR} = '/etc/inspircd';
156 $config{MODULE_DIR} = '/usr/lib/inspircd';
157 $config{BINARY_DIR} = '/usr/sbin/';
158 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
159 $config{DATA_DIR} = '/var/inspircd';
160 $config{LOG_DIR} = '/var/log/inspircd';
162 $config{UID} = $opt_uid || $config{UID} || $<;
163 $config{CONFIG_DIR} ||= resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
164 $config{MODULE_DIR} ||= resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
165 $config{BINARY_DIR} ||= resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
166 $config{BUILD_DIR} ||= resolve_directory($config{ME}."/build"); # Build Directory
167 $config{DATA_DIR} ||= resolve_directory($config{BASE_DIR}."/data"); # Data directory
168 $config{LOG_DIR} ||= resolve_directory($config{BASE_DIR}."/logs"); # Log directory
171 if (defined $opt_config_dir) {
172 $config{CONFIG_DIR} = $opt_config_dir;
174 if (defined $opt_module_dir) {
175 $config{MODULE_DIR} = $opt_module_dir;
177 if (defined $opt_binary_dir) {
178 $config{BINARY_DIR} = $opt_binary_dir;
180 if (defined $opt_data_dir) {
181 $config{DATA_DIR} = $opt_data_dir;
183 if (defined $opt_log_dir) {
184 $config{LOG_DIR} = $opt_log_dir;
186 chomp($config{HAS_GNUTLS} = `pkg-config --modversion gnutls 2>/dev/null`); # GNUTLS Version.
188 if (defined $opt_freebsd_port)
190 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`);
191 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`);
192 $config{USE_FREEBSD_BASE_SSL} = "n";
196 if ($^O eq "freebsd")
198 # default: use base ssl
199 chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`); # OpenSSL version, freebsd specific
200 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`); # Port version, may be different
204 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version, others
205 $config{HAS_OPENSSL_PORT} = "";
206 $config{USE_FREEBSD_BASE_SSL} = "n";
210 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
211 chomp(our $openssl_ver = $config{HAS_OPENSSL});
212 $config{USE_GNUTLS} ||= "n";
213 if (defined $opt_use_gnutls)
215 $config{USE_GNUTLS} = "y"; # Use gnutls.
217 $config{USE_OPENSSL} ||= "n"; # Use openssl.
218 if (defined $opt_use_openssl)
220 $config{USE_OPENSSL} = "y";
223 if (!defined $opt_disable_debug) {
224 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
226 $config{OPTIMISATI} = "-O2";
229 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
230 $config{HAS_STDINT} = "false"; # stdint.h check
231 $config{USE_KQUEUE} = "y"; # kqueue enabled
232 if (defined $opt_nokqueue) {
233 $config{USE_KQUEUE} = "n";
235 $config{USE_POLL} = "y"; # poll enabled
236 $config{USE_EPOLL} = "y"; # epoll enabled
237 if (defined $opt_noepoll)
239 $config{USE_EPOLL} = "n";
241 $config{USE_PORTS} = "y"; # epoll enabled
242 if (defined $opt_noports)
244 $config{USE_PORTS} = "n";
246 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
247 $config{OSNAME} = $^O; # Operating System Name
248 $config{IS_DARWIN} = "NO"; # Is OSX?
249 $config{STARTSCRIPT} = "inspircd"; # start script?
250 $config{DESTINATION} = "BASE"; # Is target path.
251 if ($config{OSNAME} =~ /darwin/i)
253 $config{IS_DARWIN} = "YES";
254 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
255 $config{CC} = "xcrun clang++"; # C++ compiler for OSX.
257 elsif ($config{OSNAME} =~ /freebsd/i)
259 chomp(my $fbsd_version = `uname -r`);
260 $fbsd_version =~ s/^(\d+\.\d+).*/$1/g;
261 $config{CC} = $fbsd_version >= 10.0 ? 'clang++' : 'g++';
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 print "`$config{CC}` was not found! A C++ compiler is required to build InspIRCd!\n";
285 print "You can pass a custom compiler to $0 using --with-cc=[name].\n";
289 # Get and Set some important vars..
294 unlink(".config.cache");
297 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
302 chomp($topdir = getcwd());
303 $this = resolve_directory($topdir); # PWD, Regardless.
305 # Does the cache file exist?
307 # No, No it doesn't.. *BASH*
308 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
311 # We've Loaded the cache file and all our variables..
312 print "Updating files...\n";
313 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
315 print "Disabling debug information (-g).\n";
316 $config{OPTIMISATI} = "";
318 $has_epoll = $config{HAS_EPOLL};
319 $has_ports = $config{HAS_PORTS};
320 $has_kqueue = $config{HAS_KQUEUE};
329 print "Configure update failed: $@\n";
338 $fail ||= system "$config{CC} -o test_$feature make/check_$feature.cpp >/dev/null 2>&1";
339 $fail ||= system "./test_$feature";
340 unlink "test_$feature";
344 print "Running non-interactive configure...\n" unless $interactive;
345 print "Checking for cache from previous configure... ";
346 print ($cache_loaded ? "found\n" : "not found\n");
347 $config{SYSTEM} = lc $^O;
348 print "Checking operating system version... $config{SYSTEM}\n";
350 $exec = $config{CC} . " -dumpversion | cut -c 1";
351 chomp($config{GCCVER} = `$exec`); # Major GCC Version
352 $exec = $config{CC} . " -dumpversion | cut -c 3";
353 chomp($config{GCCMINOR} = `$exec`);
355 printf "Checking if stdint.h exists... ";
356 $config{HAS_STDINT} = "true";
358 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
359 if ($config{HAS_STDINT} eq "true") {
362 print "yes\n" if $config{HAS_STDINT} eq "true";
363 print "no\n" if $config{HAS_STDINT} eq "false";
365 printf "Checking if strlcpy exists... ";
366 # Perform the strlcpy() test..
367 $config{HAS_STRLCPY} = "false";
369 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
371 while (defined(my $line = <STRLCPY>)) {
373 # try and find the delcaration of:
374 # size_t strlcpy(...)
375 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
376 $config{HAS_STRLCPY} = "true";
381 print "yes\n" if $config{HAS_STRLCPY} eq "true";
382 print "no\n" if $config{HAS_STRLCPY} eq "false";
384 printf "Checking if kqueue exists... ";
385 $has_kqueue = test_compile('kqueue');
386 print $has_kqueue ? "yes\n" : "no\n";
388 printf "Checking for epoll support... ";
389 $has_epoll = test_compile('epoll');
390 print $has_epoll ? "yes\n" : "no\n";
392 printf "Checking for eventfd support... ";
393 $config{HAS_EVENTFD} = test_compile('eventfd') ? 'true' : 'false';
394 print $config{HAS_EVENTFD} eq 'true' ? "yes\n" : "no\n";
396 printf "Checking if Solaris I/O completion ports are available... ";
398 our $system = `uname -s`;
400 $has_ports = 1 if ($system eq "SunOS");
403 my $kernel = `uname -r`;
405 if (($kernel !~ /^5\.1./)) {
409 print "yes\n" if $has_ports == 1;
410 print "no\n" if $has_ports == 0;
412 $config{HAS_EPOLL} = $has_epoll;
413 $config{HAS_KQUEUE} = $has_kqueue;
415 printf "Checking for libgnutls... ";
416 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
417 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
419 $config{HAS_GNUTLS} = "y";
422 $config{HAS_GNUTLS} = "n";
426 $config{HAS_GNUTLS} = "n";
429 printf "Checking for openssl... ";
430 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
431 if (defined($openssl_ver) && ($openssl_ver ne "")) {
433 $config{HAS_OPENSSL} = "y";
436 $config{HAS_OPENSSL} = "n";
440 $config{HAS_OPENSSL} = "n";
443 printf "Checking if you are running an ancient, unsupported OS... ";
444 if ($config{OSNAME} =~ /FreeBSD/i)
446 my $version = `uname -r`;
447 if ($version =~ /^4\./)
450 print "FreeBSD 4.x is no longer supported. By ANYONE.\n";
451 print "To build, you will need to add the following to CXXFLAGS:\n";
452 print "\t-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1\n";
456 print "no ($version)\n";
461 print "no ($config{OSNAME})\n";
464 ################################################################################
465 # BEGIN INTERACTIVE PART #
466 ################################################################################
471 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
474 my $rev = getrevision();
475 # Display Introduction Message..
477 Welcome to the \e[1mInspIRCd\e[0m configuration program! (\e[1minteractive mode\e[0m)
478 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
480 *** If you are unsure of any of these values, leave it blank for ***
481 *** standard settings that will work, and your server will run ***
482 *** using them. Please consult your IRC network admin if in doubt. ***
484 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
485 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
486 dir, otherwise you won't have a config file!
488 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
489 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
492 print " (Non-SVN build)";
496 $config{CHANGE_COMPILER} = "n";
497 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";
499 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
500 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
501 should NOT be used. You should probably specify a newer compiler.\n\n";
502 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
503 if ($config{CHANGE_COMPILER} =~ /y/i) {
504 print "What command do you want to use to invoke your compiler?\n";
505 print "[\e[1;32m$config{CC}\e[0m] -> ";
506 chomp($config{CC} = <STDIN>);
507 if ($config{CC} eq "") {
510 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
512 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
513 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
514 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
515 if ($config{GCCVER} < 3) {
516 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
520 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
527 # Directory Settings..
528 my $tmpbase = $config{BASE_DIR};
529 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
530 if ($tmpbase ne $config{BASE_DIR}) {
531 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
532 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
533 $config{DATA_DIR} = resolve_directory($config{BASE_DIR}."/data"); # Data Directory
534 $config{LOG_DIR} = resolve_directory($config{BASE_DIR}."/logs"); # Log Directory
535 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
538 dir_check("are the configuration files", "CONFIG_DIR");
539 dir_check("are the modules to be compiled to", "MODULE_DIR");
540 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
541 dir_check("are variable data files to be located in", "DATA_DIR");
542 dir_check("are the logs to be stored in", "LOG_DIR");
543 dir_check("do you want the build to take place", "BUILD_DIR");
545 my $chose_hiperf = 0;
547 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?");
549 if ($config{USE_KQUEUE} eq "y") {
554 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?");
556 if ($config{USE_EPOLL} eq "y") {
561 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?");
563 if ($config{USE_PORTS} eq "y") {
568 if (!$chose_hiperf) {
569 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?");
570 if ($config{USE_POLL} ne "y")
572 print "No high-performance socket engines are available, or you chose\n";
573 print "not to enable one. Defaulting to select() engine.\n\n";
577 $config{USE_FREEBSD_BASE_SSL} = "n";
578 $config{USE_FREEBSD_PORTS_SSL} = "n";
579 if ($config{HAS_OPENSSL_PORT} ne "")
581 $config{USE_FREEBSD_PORTS_SSL} = "y";
582 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
583 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";
584 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
586 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
588 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
590 # update to port version
591 $openssl_ver = $config{HAS_OPENSSL_PORT};
596 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
599 $config{USE_SSL} ||= "n";
600 $config{MODUPDATE} ||= 'n';
602 if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
604 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
605 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
607 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
608 if ($config{USE_SSL} eq "y")
610 if ($config{HAS_GNUTLS} eq "y")
612 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
613 if ($config{USE_GNUTLS} eq "y")
615 print "\nUsing GnuTLS SSL module.\n";
619 if ($config{HAS_OPENSSL} eq "y")
621 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
622 if ($config{USE_OPENSSL} eq "y")
624 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
631 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed and\n";
632 print "is in your path.\n\n";
635 yesno('MODUPDATE',"Would you like to check for updates to third-party modules?");
637 if ($config{MODUPDATE} eq "y") {
638 print "Checking for upgrades to extra and third-party modules... ";
639 system "./modulemanager upgrade";
643 # We are on a POSIX system, we can enable POSIX extras without asking
644 symlink "extra/m_regex_posix.cpp", "src/modules/m_regex_posix.cpp";
648 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
650 print "Sorry, but I couldn't detect GnuTLS. Make sure pkg-config is in your path.\n";
653 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
655 print "Sorry, but I couldn't detect OpenSSL. Make sure pkg-config and openssl are in your path.\n";
660 $config{CERTGEN} ||= 'y';
661 yesno('CERTGEN',"Would you like to generate SSL certificates now?") if ($interactive && ($config{USE_GNUTLS} eq "y" || $config{USE_OPENSSL} eq "y"));
663 if ($config{USE_GNUTLS} eq "y") {
664 unless (-r "src/modules/m_ssl_gnutls.cpp") {
665 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
666 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
668 if ($interactive && $config{CERTGEN} eq 'y')
670 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
671 print "SSL certificates not found, generating.. \n\n
672 *************************************************************
673 * Generating the private key may take some time, once done, *
674 * answer the questions which follow. If you are unsure, *
676 *************************************************************\n\n";
677 $failed = make_gnutls_cert();
679 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
681 print "\nCertificate generation complete, copying to config directory... ";
682 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
683 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
688 print "SSL certificates found, skipping.\n\n";
693 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
697 if ($config{USE_OPENSSL} eq "y") {
698 unless (-r "src/modules/m_ssl_openssl.cpp") {
699 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
700 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
703 if ($interactive && $config{CERTGEN} eq 'y')
705 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
706 print "SSL certificates not found, generating.. \n\n
707 *************************************************************
708 * Generating the certificates may take some time, go grab a *
709 * coffee or something. *
710 *************************************************************\n\n";
712 print "\nCertificate generation complete, copying to config directory... ";
713 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
714 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
715 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
718 print "SSL certificates found, skipping.\n\n"
723 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
726 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
727 print "Skipping SSL certificate generation as SSL support is not available.\n\n";
735 print "To build your server with these settings, please run '\e[1;32mmake\e[0m' now.\n";
736 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
737 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
738 print "modules in your config. This configure script has added those modules to the\n";
739 print "build process. For more info, please refer to:\n";
740 print "\e[1;32mhttp://wiki.inspircd.org/Installation_From_Tarball\e[0m\n";
742 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
743 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
744 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";
747 if ($config{GCCVER} < "3") {
749 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
750 GCC 2.x series compilers only had partial (read as broken) C++ support, and
751 your compile will most likely fail horribly! If you have any problems, do NOT
752 report them to the bugtracker or forums without first upgrading your compiler
753 to a newer 3.x or 4.x (or whatever is available currently) version.
757 ################################################################################
759 ################################################################################
761 # Retrieves the .config.cache file, and loads values into the main config hash.
762 open(CACHE, ".config.cache") or return 0;
765 # Ignore Blank lines, and comments..
768 my ($key, $value) = split("=", $_, 2);
769 $value =~ /^\"(.*)\"$/;
770 # Do something with data here!
778 # Dump the contents of %config
779 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
780 open(FILEHANDLE, ">.config.cache");
781 foreach my $key (keys %config) {
782 print FILEHANDLE "$key=\"$config{$key}\"\n";
788 my ($desc, $hash_key) = @_;
791 print "In what directory $desc?\n";
792 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
793 chomp(my $var = <STDIN>);
795 $var = $config{$hash_key};
797 if ($var =~ /^\~\/(.+)$/) {
798 # Convert it to a full path..
799 $var = resolve_directory($ENV{HOME} . "/" . $1);
801 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
803 # Assume relative Path was given.. fill in the rest.
804 $var = $this . "/$var";
807 $var = resolve_directory($var);
809 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
810 chomp(my $tmp = <STDIN>);
811 if (($tmp eq "") || ($tmp =~ /^y/i)) {
812 # Attempt to Create the Dir..
815 File::Path::mkpath($var, 0, 0777);
818 unless (defined($chk) && -d $var) {
819 print "Unable to create directory. ($var)\n\n";
824 # They said they don't want to create, and we can't install there.
830 # Target exists, but is not a directory.
831 print "File $var exists, but is not a directory.\n\n";
835 # Either Dir Exists, or was created fine.
836 $config{$hash_key} = $var;
844 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
847 my($writeheader) = @_;
848 # First File.. inspircd_config.h
849 chomp(my $incos = `uname -n -s -r`);
850 chomp(my $version = `sh src/version.sh`);
851 chomp(my $revision2 = getrevision());
852 my $branch = "InspIRCd-0.0";
853 if ($version =~ /^(InspIRCd-[0-9]+\.[0-9]+)\.[0-9]+/)
857 if ($writeheader == 1)
859 print "Writing \e[1;32minspircd_config.h\e[0m\n";
860 open(FILEHANDLE, ">include/inspircd_config.h.tmp");
861 print FILEHANDLE <<EOF;
862 /* Auto generated by configure, do not modify! */
863 #ifndef __CONFIGURATION_AUTO__
864 #define __CONFIGURATION_AUTO__
866 /* this is for windows support. */
867 #define CoreExport /**/
868 #define DllExport /**/
870 #define CONFIG_PATH "$config{CONFIG_DIR}"
871 #define DATA_PATH "$config{DATA_DIR}"
872 #define LOG_PATH "$config{LOG_DIR}"
873 #define MOD_PATH "$config{MODULE_DIR}"
874 #define SOMAXCONN_S "$config{_SOMAXCONN}"
875 #define ENTRYPOINT int main(int argc, char** argv)
878 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
880 if ($config{OSNAME} =~ /SunOS/i) {
881 print FILEHANDLE "#define IS_SOLARIS\n";
883 if ($config{OSNAME} =~ /MINGW32/i) {
884 print FILEHANDLE "#define IS_MINGW\n";
886 if ($config{GCCVER} >= 3) {
887 print FILEHANDLE "#define GCC3\n";
889 if ($config{HAS_STRLCPY} eq "true") {
890 print FILEHANDLE "#define HAS_STRLCPY\n";
892 if ($config{HAS_STDINT} eq "true") {
893 print FILEHANDLE "#define HAS_STDINT\n";
895 if ($config{HAS_EVENTFD} eq 'true') {
896 print FILEHANDLE "#define HAS_EVENTFD\n";
898 if ($config{OSNAME} !~ /DARWIN/i) {
899 print FILEHANDLE "#define HAS_CLOCK_GETTIME\n";
902 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
903 print FILEHANDLE "#define USE_KQUEUE\n";
904 $config{SOCKETENGINE} = "socketengine_kqueue";
907 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
908 print FILEHANDLE "#define USE_EPOLL\n";
909 $config{SOCKETENGINE} = "socketengine_epoll";
912 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
913 print FILEHANDLE "#define USE_PORTS\n";
914 $config{SOCKETENGINE} = "socketengine_ports";
917 # user didn't choose either epoll or select for their OS.
918 # default them to USE_SELECT (ewwy puke puke)
920 print "no hi-perf, " . $config{USE_POLL};
921 if ($config{USE_POLL} eq "y")
923 print FILEHANDLE "#define USE_POLL\n";
924 $config{SOCKETENGINE} = "socketengine_poll";
928 print FILEHANDLE "#define USE_SELECT\n";
929 $config{SOCKETENGINE} = "socketengine_select";
932 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
935 open(FILEHANDLE, ">include/inspircd_version.h.tmp");
936 print FILEHANDLE <<EOF;
937 #define BRANCH "$branch"
938 #define VERSION "$version"
939 #define REVISION "$revision2"
940 #define SYSTEM "$incos"
944 for my $file (qw(include/inspircd_config.h include/inspircd_version.h)) {
946 open my $fh1, $file or $diff = 1;
947 open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
951 if (defined($line1) != defined($line2)) {
953 } elsif (!defined $line1) {
956 $diff = ($line1 ne $line2);
961 rename "$file.tmp", $file;
968 # Write all .in files.
971 my $exe = "inspircd";
973 # Do this once here, and cache it in the .*.inc files,
974 # rather than attempting to read src/version.sh from
975 # compiled code -- we might not have the source to hand.
976 # Fix for bug#177 by Brain.
978 chomp($version = `sh ./src/version.sh`);
979 chomp(my $revision = getrevision());
980 $version = "$version(r$revision)";
982 # We can actually parse any file starting with . and ending with .inc,
983 # but right now we only parse .inspircd.inc to form './inspircd'
984 prepare_dynamic_makefile();
986 my @dotfiles = qw(main.mk inspircd);
987 push @dotfiles, 'org.inspircd.plist' if $config{OSNAME} eq 'darwin';
989 foreach my $file (@dotfiles) {
990 open(FILEHANDLE, "make/template/$file") or die "Can't open make/template/$file: $!";
991 $_ = join '', <FILEHANDLE>;
994 $config{BUILD_DIR} ||= resolve_directory($config{ME}."/build");
997 CC SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR DATA_DIR UID
998 STARTSCRIPT DESTINATION SOCKETENGINE LOG_DIR
1000 s/\@$var\@/$config{$var}/g;
1002 s/\@EXECUTABLE\@/$exe/ if defined $exe;
1003 s/\@VERSION\@/$version/ if defined $version;
1005 if ($file eq 'main.mk') {
1006 print "Writing \e[1;32mGNUmakefile\e[0m ...\n";
1009 s/\@IFDEF (\S+)/ifdef $1/g;
1010 s/\@IFNDEF (\S+)/ifndef $1/g;
1011 s/\@IFEQ (\S+) (\S+)/ifeq ($1,$2)/g;
1012 s/\@ELSIFEQ (\S+) (\S+)/else ifeq ($1,$2)/g;
1015 s/ *\@BSD_ONLY .*\n//g;
1017 s/\@DO_EXPORT (.*)/export $1/g;
1018 open MKF, '>GNUmakefile' or die "Can't write to GNUmakefile: $!";
1022 print "Writing \e[1;32mBSDmakefile\e[0m ...\n";
1024 s/\@IFDEF (\S+)/.if defined($1)/g;
1025 s/\@IFNDEF (\S+)/.if !defined($1)/g;
1026 s/\@IFEQ (\S+) (\S+)/.if $1 == $2/g;
1027 s/\@ELSIFEQ (\S+) (\S+)/.elif $1 == $2/g;
1031 s/ *\@GNU_ONLY .*\n//g;
1033 $mk_tmp =~ s#\@DO_EXPORT (.*)#"MAKEENV += ".join ' ', map "$_='\${$_}'", split /\s/, $1#eg;
1034 open MKF, '>BSDmakefile' or die "Can't write to BSDmakefile: $!";
1038 print "Writing \e[1;32m$file\e[0m ...\n";
1039 open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
1040 print FILEHANDLE $_;
1045 chmod 0755, 'inspircd';
1051 for my $mod (@modlist) {
1052 getcompilerflags("src/modules/m_$mod.cpp");
1053 getlinkerflags("src/modules/m_$mod.cpp");
1057 sub prepare_dynamic_makefile
1063 $config{USE_EPOLL} = 0;
1067 $config{USE_KQUEUE} = 0;
1071 $config{USE_PORTS} = 0;
1075 # Routine to list out the extra/ modules that have been enabled.
1076 # Note: when getting any filenames out and comparing, it's important to lc it if the
1077 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1078 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1079 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1080 sub list_extras () {
1083 my $srcdir = File::Spec->catdir("src", "modules");
1084 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1087 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1088 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1091 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1092 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1095 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1097 EXTRA: for my $extra (@extras) {
1098 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1099 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1100 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1101 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1102 if (-l $abs_source) {
1103 # Symlink, is it in the right place?
1104 my $targ = readlink($abs_source);
1105 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1106 if ($abs_targ eq $abs_extra) {
1107 $extras{$extra} = "\e[32;1menabled\e[0m";
1109 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1111 } elsif (-e $abs_source) {
1112 my ($devext, $inoext) = stat($abs_extra);
1113 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1115 if ($devsrc == $devext && $inosrc == $inoext) {
1116 $extras{$extra} = "\e[32;1menabled\e[0m";
1118 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1121 open my $extfd, "<", $abs_extra;
1122 open my $srcfd, "<", $abs_source;
1124 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1125 $extras{$extra} = "\e[32;1menabled\e[0m";
1127 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1131 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1134 # Now let's add dependency info
1135 for my $extra (keys(%extras)) {
1136 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1137 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1138 my @deps = split / +/, getdependencies($abs_extra);
1139 for my $dep (@deps) {
1140 if (exists($extras{$dep})) {
1141 my $ref = \$extras{$dep}; # Take reference.
1142 if ($$ref !~ m/needed by/) {
1143 # First dependency found.
1144 if ($$ref =~ m/enabled/) {
1145 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1147 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1148 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1151 if ($$ref =~ m/enabled/) {
1152 $$ref .= ", \e[32;1m$extra\e[0m";
1154 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1160 for my $extra (sort {$a cmp $b} keys(%extras)) {
1161 my $text = $extras{$extra};
1162 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1163 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1165 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1168 return keys(%extras) if wantarray; # Can be used by manage_extras.
1171 sub enable_extras (@) {
1173 for my $extra (@extras) {
1174 my $extrapath = "src/modules/extra/$extra";
1175 if (!-e $extrapath) {
1176 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1179 my $source = "src/modules/$extra";
1181 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1184 # Get dependencies, and add them to be processed.
1185 my @deps = split / +/, getdependencies($extrapath);
1186 for my $dep (@deps) {
1187 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1188 if (!-e "src/modules/$dep") {
1189 if (-e "src/modules/extra/$dep") {
1190 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1193 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";
1197 print "Enabling $extra ... \n";
1198 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1202 sub disable_extras (@)
1204 opendir my $dd, "src/modules/extra/";
1205 my @files = readdir($dd);
1208 EXTRA: for my $extra (@extras) {
1209 my $extrapath = "src/modules/extra/$extra";
1210 my $source = "src/modules/$extra";
1211 if (!-e $extrapath) {
1212 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1215 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1216 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";
1219 # Check if anything needs this.
1220 for my $file (@files) {
1221 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1222 # File depends on this extra...
1223 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1224 # And is both enabled and not about to be disabled.
1225 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1226 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1232 print "Disabling $extra ... \n";
1233 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";