X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=configure;h=b380b5700046cad908714e057d3370ae2cc080e4;hb=4ace96e5217e1566b3d4e8f06df98d583fa8a923;hp=6fba700ceb4e4ce4f5043abb0b2ee908ccdc4bb5;hpb=02267976f636e3c4fffc8732a949b4777a771ca2;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/configure b/configure index 6fba700ce..83c11b5d2 100755 --- a/configure +++ b/configure @@ -1,16 +1,19 @@ #!/usr/bin/env perl - # # InspIRCd -- Internet Relay Chat Daemon # -# Copyright (C) 2009-2010 Daniel De Graaf -# Copyright (C) 2007, 2009 Dennis Friis -# Copyright (C) 2003, 2006-2008 Craig Edwards -# Copyright (C) 2006-2008 Robin Burchell +# Copyright (C) 2020 Nicole Kleinhoff +# Copyright (C) 2020 Daniel Vassdal +# Copyright (C) 2019 Matt Schatz +# Copyright (C) 2019 Anatole Denis +# Copyright (C) 2013-2021 Sadie Powell +# Copyright (C) 2012, 2019 Robby +# Copyright (C) 2012 ChrisTX +# Copyright (C) 2010 Daniel De Graaf # Copyright (C) 2008 Thomas Stagner -# Copyright (C) 2007 John Brooks -# Copyright (C) 2006 Oliver Lupton -# Copyright (C) 2003-2006 Craig McLure +# Copyright (C) 2008 Robin Burchell +# Copyright (C) 2007 Dennis Friis +# Copyright (C) 2006-2008 Craig Edwards # # This file is part of InspIRCd. InspIRCd is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public @@ -26,24 +29,43 @@ # -BEGIN { - require 5.8.0; -} - +use v5.10.0; use strict; use warnings FATAL => qw(all); -use File::Copy (); -use File::Spec::Functions qw(rel2abs); -use Cwd; -use Getopt::Long; +use Cwd qw(getcwd); +use File::Basename qw(basename); +use File::Copy (); +use File::Spec::Functions qw(abs2rel catfile catdir rel2abs); +use FindBin qw($RealDir); +use Getopt::Long qw(GetOptions); +use POSIX qw(getgid getuid); +use lib $RealDir; +use make::common; use make::configure; -use make::utilities; - -our ($opt_use_gnutls, $opt_use_openssl, $opt_nointeractive, $opt_socketengine, - $opt_system, $opt_uid, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir, - $opt_data_dir, $opt_log_dir); +use make::console; +use make::directive; + +my ($opt_binary_dir, + $opt_config_dir, + $opt_data_dir, + $opt_development, + $opt_disable_auto_extras, + $opt_disable_interactive, + $opt_distribution_label, + $opt_example_dir, + $opt_gid, + $opt_log_dir, + $opt_manual_dir, + $opt_module_dir, + $opt_portable, + $opt_prefix, + $opt_runtime_dir, + $opt_script_dir, + $opt_socketengine, + $opt_system, + $opt_uid); sub list_extras (); @@ -54,30 +76,39 @@ sub disable_extras (@); my @opt_enableextras; my @opt_disableextras; -GetOptions ( - 'enable-gnutls' => \$opt_use_gnutls, - 'system' => \$opt_system, - 'uid=s' => \$opt_uid, - 'enable-openssl' => \$opt_use_openssl, - 'disable-interactive' => \$opt_nointeractive, - 'socketengine=s' => \$opt_socketengine, - 'prefix=s' => \$opt_base_dir, - 'config-dir=s' => \$opt_config_dir, - 'module-dir=s' => \$opt_module_dir, - 'binary-dir=s' => \$opt_binary_dir, - 'data-dir=s' => \$opt_data_dir, - 'log-dir=s' => \$opt_log_dir, - 'help' => \&cmd_help, +exit 1 unless GetOptions( + 'clean' => \&cmd_clean, + 'help' => \&cmd_help, 'update' => \&cmd_update, - 'clean' => \&cmd_clean, - 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing. - 'enable-extras=s@' => \@opt_enableextras, # ^ - 'disable-extras=s@' => \@opt_disableextras, # ^ + + 'binary-dir=s' => \$opt_binary_dir, + 'config-dir=s' => \$opt_config_dir, + 'data-dir=s' => \$opt_data_dir, + 'development' => \$opt_development, + 'disable-auto-extras' => \$opt_disable_auto_extras, + 'disable-interactive' => \$opt_disable_interactive, + 'distribution-label=s' => \$opt_distribution_label, + 'example-dir=s' => \$opt_example_dir, + 'gid=s' => \$opt_gid, + 'log-dir=s' => \$opt_log_dir, + 'manual-dir=s' => \$opt_manual_dir, + 'module-dir=s' => \$opt_module_dir, + 'portable' => \$opt_portable, + 'prefix=s' => \$opt_prefix, + 'runtime-dir=s' => \$opt_runtime_dir, + 'script-dir=s' => \$opt_script_dir, + 'socketengine=s' => \$opt_socketengine, + 'system' => \$opt_system, + 'uid=s' => \$opt_uid, + + 'disable-extras=s@' => \@opt_disableextras, + 'enable-extras=s@' => \@opt_enableextras, + 'list-extras' => sub { list_extras; exit 0; }, ); if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) { - @opt_enableextras = split /,/, join(',', @opt_enableextras); - @opt_disableextras = split /,/, join(',', @opt_disableextras); + @opt_enableextras = grep { /\S/ } split /[, ]+/, join(',', @opt_enableextras); + @opt_disableextras = grep { /\S/ } split /[, ]+/, join(',', @opt_disableextras); enable_extras(@opt_enableextras); disable_extras(@opt_disableextras); list_extras; @@ -86,450 +117,382 @@ if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) { } our $interactive = !( - (defined $opt_base_dir) || - (defined $opt_config_dir) || - (defined $opt_module_dir) || - (defined $opt_base_dir) || - (defined $opt_binary_dir) || - (defined $opt_data_dir) || - (defined $opt_log_dir) || - (defined $opt_nointeractive) || - (defined $opt_socketengine) || - (defined $opt_use_openssl) || - (defined $opt_system) || - (defined $opt_uid) || - (defined $opt_use_gnutls) + !-t STDIN || + !-t STDOUT || + defined $opt_binary_dir || + defined $opt_config_dir || + defined $opt_data_dir || + defined $opt_development || + defined $opt_disable_auto_extras || + defined $opt_disable_interactive || + defined $opt_distribution_label || + defined $opt_example_dir || + defined $opt_gid || + defined $opt_log_dir || + defined $opt_manual_dir || + defined $opt_module_dir || + defined $opt_portable || + defined $opt_prefix || + defined $opt_runtime_dir || + defined $opt_script_dir || + defined $opt_socketengine || + defined $opt_system || + defined $opt_uid ); -our $topdir = getcwd(); -our %config = read_configure_cache(); - -print "Checking for cache from previous configure... "; -print %config ? "found\n" : "not found\n"; - -$config{BASE_DIR} = $topdir."/run"; - -if (defined $opt_base_dir) { - $config{BASE_DIR} = $opt_base_dir; -} elsif (defined $opt_system) { - $config{BASE_DIR} = '/var/lib/inspircd'; +my %version = get_version $opt_distribution_label; +say console_format "<|BOLD Configuring InspIRCd $version{FULL} on $^O.|>"; + +my %config; +if ($interactive) { + %config = read_config_file(CONFIGURE_CACHE_FILE); + run_test abs2rel(CONFIGURE_CACHE_FILE, $RealDir), %config; + if (!defined $config{VERSION}) { + $config{VERSION} = CONFIGURE_CACHE_VERSION; + } elsif ($config{VERSION} != CONFIGURE_CACHE_VERSION) { + print_warning "ignoring contents of ${\CONFIGURE_CACHE_FILE} as it was generated by an incompatible version of $0!"; + %config = ('VERSION', CONFIGURE_CACHE_VERSION); + } } -if (defined $opt_system) { - $config{UID} = $opt_uid || 'ircd'; - $config{CONFIG_DIR} = '/etc/inspircd'; - $config{MODULE_DIR} = '/usr/lib/inspircd'; - $config{BINARY_DIR} = '/usr/sbin/'; - $config{BUILD_DIR} = $topdir."/build"; - $config{DATA_DIR} = '/var/inspircd'; - $config{LOG_DIR} = '/var/log/inspircd'; -} else { - $config{UID} = $opt_uid || $<; - $config{CONFIG_DIR} = rel2abs($config{BASE_DIR}."/conf"); - $config{MODULE_DIR} = rel2abs($config{BASE_DIR}."/modules"); - $config{BINARY_DIR} = rel2abs($config{BASE_DIR}."/bin"); - $config{BUILD_DIR} = rel2abs($topdir."/build"); - $config{DATA_DIR} = rel2abs($config{BASE_DIR}."/data"); - $config{LOG_DIR} = rel2abs($config{BASE_DIR}."/logs"); +$config{CXX} = find_compiler($config{CXX} // $ENV{CXX}); +unless ($config{CXX}) { + say 'A suitable C++ compiler could not be detected on your system!'; + unless ($interactive) { + say 'Set the CXX environment variable to the path to a C++ compiler binary if this is incorrect.'; + exit 1; + } + until ($config{CXX}) { + my $compiler_path = prompt_string 1, 'Please enter the path to a C++ compiler binary:', 'c++'; + $config{CXX} = find_compiler $compiler_path; + } } +my %compiler = get_compiler_info($config{CXX}); -if (defined $opt_config_dir) { - $config{CONFIG_DIR} = $opt_config_dir; -} -if (defined $opt_module_dir) { - $config{MODULE_DIR} = $opt_module_dir; -} -if (defined $opt_binary_dir) { - $config{BINARY_DIR} = $opt_binary_dir; -} -if (defined $opt_data_dir) { - $config{DATA_DIR} = $opt_data_dir; -} -if (defined $opt_log_dir) { - $config{LOG_DIR} = $opt_log_dir; -} -chomp($config{HAS_GNUTLS} = `pkg-config --modversion gnutls 2>/dev/null`); -chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); - -chomp(our $gnutls_ver = $config{HAS_GNUTLS}); -chomp(our $openssl_ver = $config{HAS_OPENSSL}); -$config{USE_GNUTLS} = "n"; -if (defined $opt_use_gnutls) -{ - $config{USE_GNUTLS} = "y"; # Use gnutls. -} -$config{USE_OPENSSL} = "n"; # Use openssl. -if (defined $opt_use_openssl) -{ - $config{USE_OPENSSL} = "y"; -} +$config{HAS_ARC4RANDOM_BUF} = run_test 'arc4random_buf()', test_file($config{CXX}, 'arc4random_buf.cpp'); +$config{HAS_CLOCK_GETTIME} = run_test 'clock_gettime()', test_file($config{CXX}, 'clock_gettime.cpp', $^O eq 'darwin' ? undef : '-lrt'); +$config{HAS_EVENTFD} = run_test 'eventfd()', test_file($config{CXX}, 'eventfd.cpp'); -$config{STARTSCRIPT} = $^O eq 'darwin' ? 'org.inspircd.plist' : 'inspircd'; +my @socketengines; +push @socketengines, 'epoll' if run_test 'epoll', test_header $config{CXX}, 'sys/epoll.h'; +push @socketengines, 'kqueue' if run_test 'kqueue', test_file $config{CXX}, 'kqueue.cpp'; +push @socketengines, 'poll' if run_test 'poll', test_header $config{CXX}, 'poll.h'; +push @socketengines, 'select'; -$config{CXX} = defined $ENV{CXX} && !system("$ENV{CXX} -v > /dev/null 2>&1") ? $ENV{CXX} : find_compiler(); -if ($config{CXX} eq "") { - print "A C++ compiler could not be detected on your system!\n"; - print "Set the CXX environment variable to the full path if this is incorrect.\n"; - exit 1; +if (defined $opt_socketengine) { + unless (grep { $_ eq $opt_socketengine } @socketengines) { + my $reason = -f "src/socketengines/socketengine_$opt_socketengine.cpp" ? 'is not available on this platform' : 'does not exist'; + print_error "The socket engine you requested ($opt_socketengine) $reason!", + 'Available socket engines are:', + map { " * $_" } @socketengines; + } } - -our %cxx = get_compiler_info($config{CXX}); -if ($cxx{UNSUPPORTED}) { - print "Your C++ compiler is too old to build InspIRCd!\n"; - print "Reason: $cxx{REASON}\n"; - exit 1; +$config{SOCKETENGINE} = $opt_socketengine // $socketengines[0]; + +if (defined $opt_portable) { + print_error '--portable and --system can not be used together!' if defined $opt_system; + $config{DESTDIR} = catfile $RealDir, 'run', ''; + $config{BASE_DIR} = $opt_prefix // ''; + $config{BINARY_DIR} = $opt_binary_dir // 'bin'; + $config{CONFIG_DIR} = $opt_config_dir // 'conf'; + $config{DATA_DIR} = $opt_data_dir // 'data'; + $config{EXAMPLE_DIR} = $opt_example_dir // catdir $config{CONFIG_DIR}, 'examples'; + $config{LOG_DIR} = $opt_log_dir // 'logs'; + $config{MANUAL_DIR} = $opt_manual_dir // 'manuals'; + $config{MODULE_DIR} = $opt_module_dir // 'modules'; + $config{RUNTIME_DIR} = $opt_runtime_dir // $config{DATA_DIR}; + $config{SCRIPT_DIR} = $opt_script_dir // $config{BASE_DIR}; +} elsif (defined $opt_system) { + $config{BASE_DIR} = $opt_prefix // '/'; + $config{BINARY_DIR} = $opt_binary_dir // catdir $config{BASE_DIR}, 'usr/sbin'; + $config{CONFIG_DIR} = $opt_config_dir // catdir $config{BASE_DIR}, 'etc/inspircd'; + $config{DATA_DIR} = $opt_data_dir // catdir $config{BASE_DIR}, 'var/lib/inspircd'; + $config{EXAMPLE_DIR} = $opt_example_dir // catdir $config{BASE_DIR}, 'usr/share/doc/inspircd'; + $config{LOG_DIR} = $opt_log_dir // catdir $config{BASE_DIR}, 'var/log/inspircd'; + $config{MANUAL_DIR} = $opt_manual_dir // catdir $config{BASE_DIR}, 'usr/share/man/man1'; + $config{MODULE_DIR} = $opt_module_dir // catdir $config{BASE_DIR}, 'usr/lib/inspircd'; + $config{RUNTIME_DIR} = $opt_runtime_dir // catdir $config{BASE_DIR}, 'var/run/inspircd'; + $config{SCRIPT_DIR} = $opt_script_dir // catdir $config{BASE_DIR}, 'usr/share/inspircd'; +} else { + $config{BASE_DIR} = rel2abs $opt_prefix // $config{BASE_DIR} // catdir $RealDir, 'run'; + $config{BINARY_DIR} = $opt_binary_dir // $config{BINARY_DIR} // catdir $config{BASE_DIR}, 'bin'; + $config{CONFIG_DIR} = $opt_config_dir // $config{CONFIG_DIR} // catdir $config{BASE_DIR}, 'conf'; + $config{DATA_DIR} = $opt_data_dir // $config{DATA_DIR} // catdir $config{BASE_DIR}, 'data'; + $config{EXAMPLE_DIR} = $opt_example_dir // $config{EXAMPLE_DIR} // catdir $config{CONFIG_DIR}, 'examples'; + $config{LOG_DIR} = $opt_log_dir // $config{LOG_DIR} // catdir $config{BASE_DIR}, 'logs'; + $config{MANUAL_DIR} = $opt_manual_dir // $config{MANUAL_DIR} // catdir $config{BASE_DIR}, 'manuals'; + $config{MODULE_DIR} = $opt_module_dir // $config{MODULE_DIR} // catdir $config{BASE_DIR}, 'modules'; + $config{RUNTIME_DIR} = $opt_runtime_dir // $config{RUNTIME_DIR} // $config{DATA_DIR}; + $config{SCRIPT_DIR} = $opt_script_dir // $config{SCRIPT_DIR} // $config{BASE_DIR}; } -if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)(?:[a-z])?(?:\-[a-z][0-9])?/) { - $config{HAS_OPENSSL} = $1; +# Parse --gid=123 or --gid=foo and extract the group id. +my @group; +if (defined $opt_gid) { + @group = $opt_gid =~ /^\d+$/ ? getgrgid($opt_gid) : getgrnam($opt_gid); + print_error "there is no '$opt_gid' group on this system!" unless @group; } else { - $config{HAS_OPENSSL} = ""; + @group = $opt_system ? getgrnam('irc') : getgrgid($config{GID} // getgid()); + print_error "you need to specify a group to run as using '--gid [id|name]'!" unless @group; + unless ($group[2]) { + print_warning <<"EOW"; +You are building as the privileged $group[0] group and have not specified +an unprivileged group to run InspIRCd as. + +This is almost never what you should do. You should probably either create a new +unprivileged user/group to build and run as or pass the '--gid [id|name]' flag +to specify an unprivileged group to run as. +EOW + if (!prompt_bool $interactive, "Are you sure you want to build as the $group[0] group?", 0) { + # PACKAGERS: You do not need to delete this check. Use `--gid $(id -g)` or `--gid 0` instead. + say STDERR "If you are sure you want to build as the $group[0] group pass the --gid $group[2] flag." unless $interactive; + exit 1; + } + } } - -$config{HAS_CLOCK_GETTIME} = run_test 'clock_gettime()', test_file($config{CXX}, 'clock_gettime.cpp', '-lrt'); -$config{HAS_EVENTFD} = run_test 'eventfd()', test_file($config{CXX}, 'eventfd.cpp'); - -if ($config{HAS_EPOLL} = run_test 'epoll', test_header($config{CXX}, 'sys/epoll.h')) { - $config{SOCKETENGINE} ||= 'epoll'; +$config{GROUP} = $group[0]; +$config{GID} = $group[2]; + +# Parse --uid=123 or --uid=foo and extract the user id. +my @user; +if (defined $opt_uid) { + @user = $opt_uid =~ /^\d+$/ ? getpwuid($opt_uid) : getpwnam($opt_uid); + print_error "there is no '$opt_uid' user on this system!" unless @user; +} else { + @user = $opt_system ? getpwnam('irc') : getpwuid($config{UID} // getuid()); + print_error "you need to specify a user to run as using '--uid [id|name]'!" unless @user; + unless ($user[2]) { + print_warning <<"EOW"; +You are building as the privileged $user[0] user and have not specified +an unprivileged user to run InspIRCd as. + +This is almost never what you should do. You should probably either create a new +unprivileged user/group to build and run as or pass the '--uid [id|name]' flag +to specify an unprivileged user to run as. +EOW + if (!prompt_bool $interactive, "Are you sure you want to build as the $user[0] user?", 0) { + # PACKAGERS: You do not need to delete this check. Use `--uid $(id -u)` or `--uid 0` instead. + say STDERR "If you are sure you want to build as the $user[0] user pass the --uid $user[2] flag." unless $interactive; + exit 1; + } + } } - -if ($config{HAS_KQUEUE} = run_test 'kqueue', test_file($config{CXX}, 'kqueue.cpp')) { - $config{SOCKETENGINE} ||= 'kqueue'; +$config{USER} = $user[0]; +$config{UID} = $user[2]; + +# Warn the user about clock drifting when running on OpenVZ. +if (-e '/proc/user_beancounters' || -e '/proc/vz/vzaquota') { + print_warning <<'EOW'; +You are building InspIRCd inside of an OpenVZ container. If you +plan to use InspIRCd in this container then you should make sure that NTP is +configured on the Hardware Node. Failure to do so may result in clock drifting! +EOW } -if ($config{HAS_PORTS} = run_test 'Solaris IOCP', test_header($config{CXX}, 'port.h')) { - $config{SOCKETENGINE} ||= 'ports'; +# Warn the user about OpenBSD shipping incredibly broken compilers/linkers. +if ($^O eq 'openbsd') { + print_warning <<'EOW'; +You are building InspIRCd on OpenBSD. The C++ compilers and linkers +that OpenBSD ship are incredibly broken. You may have strange linker errors +and crashes. Please consider using a different OS like FreeBSD/NetBSD instead. +EOW } -if ($config{HAS_POLL} = run_test 'poll', test_header($config{CXX}, 'poll.h')) { - $config{SOCKETENGINE} ||= 'poll'; +# Warn about Perl versions that will not be supported in the future. +if ($^V lt 'v5.26.0') { + print_warning <<"EOW"; +You are building InspIRCd with Perl $^V. This is very old and will +not be supported by the next major version of InspIRCd. Please consider updating +to Perl v5.26 or newer. +EOW } -# Select is available on all platforms -$config{HAS_SELECT} = 1; -$config{SOCKETENGINE} ||= "select"; - -if (defined $opt_socketengine) { - my $cfgkey = "HAS_" . uc $opt_socketengine; - if ($config{$cfgkey} && -f "src/socketengines/socketengine_$opt_socketengine.cpp") { - $config{SOCKETENGINE} = $opt_socketengine; - } else { - print "Unable to use a socket engine which is not supported on this platform ($opt_socketengine)!\n"; - print "Available socket engines are:"; - foreach () { - s/src\/socketengines\/socketengine_(\w+)\.cpp/$1/; - print " $1" if $config{"HAS_" . uc $1}; - } - print "\n"; - exit 1; - } +# Warn about compiler versions that will not be supported in the future. +my %future_compilers = ( + AppleClang => version->parse('10.0'), + Clang => version->parse('5.0'), + GCC => version->parse('7.0'), +); +if (exists $future_compilers{$compiler{NAME}} && $compiler{VERSION} lt $future_compilers{$compiler{NAME}}) { + print_warning <<"EOW"; +You are building InspIRCd with $compiler{NAME} v$compiler{VERSION}. This is very old and +will not be supported by the next major version of InspIRCd. Please consider +updating to $compiler{NAME} v$future_compilers{$compiler{NAME}} or newer. +EOW } -print "Checking for libgnutls... "; -if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) { - if (defined($gnutls_ver) && ($gnutls_ver ne "")) { - print "yes\n"; - $config{HAS_GNUTLS} = "y"; - } else { - print "no\n"; - $config{HAS_GNUTLS} = "n"; +# Check that the user actually wants this version. +if (defined $version{REAL_LABEL}) { + print_warning <<'EOW'; +You are building a development version. This contains code which has +not been tested as heavily and may contain various faults which could seriously +affect the running of your server. It is recommended that you use a stable +version instead. + +You can obtain the latest stable version from https://www.inspircd.org or by +running `<|GREEN git checkout $(git describe --abbrev=0 --tags insp3)|>` if you are +installing from Git. +EOW + if (!prompt_bool $interactive, 'I understand this warning and want to continue anyway.', $opt_development // 0) { + say STDERR 'If you understand this warning and still want to continue pass the --development flag.' unless $interactive; + exit 1; } -} else { - print "no\n"; - $config{HAS_GNUTLS} = "n"; } -print "Checking for openssl... "; -if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) { - if (defined($openssl_ver) && ($openssl_ver ne "")) { - print "yes\n"; - $config{HAS_OPENSSL} = "y"; - } else { - print "no\n"; - $config{HAS_OPENSSL} = "n"; +# Configure directory settings. +my $question = <<"EOQ"; +Currently, InspIRCd is configured with the following paths: + +<|BOLD Binary:|> $config{BINARY_DIR} +<|BOLD Config:|> $config{CONFIG_DIR} +<|BOLD Data:|> $config{DATA_DIR} +<|BOLD Log:|> $config{LOG_DIR} +<|BOLD Manual:|> $config{MANUAL_DIR} +<|BOLD Module:|> $config{MODULE_DIR} +<|BOLD Script:|> $config{SCRIPT_DIR} + +Do you want to change these settings? +EOQ +if (prompt_bool $interactive, $question, 0) { + my $original_base_dir = $config{BASE_DIR}; + $config{BASE_DIR} = prompt_dir $interactive, 'In what directory do you wish to install the InspIRCd base?', $config{BASE_DIR}; + for my $key (qw(BINARY_DIR CONFIG_DIR DATA_DIR LOG_DIR MANUAL_DIR MODULE_DIR SCRIPT_DIR)) { + $config{$key} =~ s/^\Q$original_base_dir\E/$config{BASE_DIR}/; } -} else { - print "no\n"; - $config{HAS_OPENSSL} = "n"; + $config{BINARY_DIR} = prompt_dir $interactive, 'In what directory should the InspIRCd binary be placed?', $config{BINARY_DIR}; + $config{CONFIG_DIR} = prompt_dir $interactive, 'In what directory are configuration files to be stored?', $config{CONFIG_DIR}; + $config{DATA_DIR} = prompt_dir $interactive, 'In what directory are variable data files to be stored?', $config{DATA_DIR}; + $config{LOG_DIR} = prompt_dir $interactive, 'In what directory are log files to be stored?', $config{LOG_DIR}; + $config{MANUAL_DIR} = prompt_dir $interactive, 'In what directory are manual pages to be placed?', $config{MANUAL_DIR}; + $config{MODULE_DIR} = prompt_dir $interactive, 'In what directory are modules to be placed?', $config{MODULE_DIR}; + $config{SCRIPT_DIR} = prompt_dir $interactive, 'In what directory are scripts to be placed?', $config{SCRIPT_DIR}; + $config{EXAMPLE_DIR} = $config{CONFIG_DIR} . '/examples'; + $config{RUNTIME_DIR} = $config{DATA_DIR}; } -if ($interactive) -{ - # Clear the screen. - system 'tput', 'clear'; - - my $revision = get_revision(); - chomp(my $version = `sh src/version.sh`); - - # Display Introduction Message.. - print <<"STOP" ; -Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m) -\e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m - -*** If you are unsure of any of these values, leave it blank for *** -*** standard settings that will work, and your server will run *** -*** using them. Please consult your IRC network admin if in doubt. *** - -Press \e[1m\e[0m to accept the default for any option, or enter -a new value. Please note: You will \e[1mHAVE\e[0m to read the docs -dir, otherwise you won't have a config file! - -Your operating system is: \e[1;32m$^O\e[0m -STOP - print "Your InspIRCd version is: \e[1;32m"; - print $revision eq 'release' ? substr($version, 9) : substr($revision, 1); - print "\e[0m\n\n"; - print "The following compiler has been detected: \e[1;32m$cxx{NAME} $cxx{VERSION}\e[0m ($config{CXX})\n\n"; - - # Directory Settings.. - my $tmpbase = $config{BASE_DIR}; - $config{BASE_DIR} = prompt_dir(1, 'What directory do you wish to install the InspIRCd base?', $config{BASE_DIR}); - if ($tmpbase ne $config{BASE_DIR}) { - $config{CONFIG_DIR} = rel2abs($config{BASE_DIR}."/conf"); - $config{MODULE_DIR} = rel2abs($config{BASE_DIR}."/modules"); - $config{DATA_DIR} = rel2abs($config{BASE_DIR}."/data"); - $config{LOG_DIR} = rel2abs($config{BASE_DIR}."/logs"); - $config{BINARY_DIR} = rel2abs($config{BASE_DIR}."/bin"); - } - - $config{BINARY_DIR} = prompt_dir(1, 'In what directory should the InspIRCd binary be placed?', $config{BINARY_DIR}); - $config{CONFIG_DIR} = prompt_dir(1, 'In what directory are the configuration files to be stored?', $config{CONFIG_DIR}); - $config{DATA_DIR} = prompt_dir(1, 'In what directory are variable data files to be stored?', $config{DATA_DIR}); - $config{LOG_DIR} = prompt_dir(1, 'In what directory are log files to be stored?', $config{LOG_DIR}); - $config{MODULE_DIR} = prompt_dir(1, 'In what directory are the modules to be placed?', $config{MODULE_DIR}); - $config{BUILD_DIR} = prompt_dir(1, 'In what directory do you want the build to take place?', $config{BUILD_DIR}); - - my $chose_hiperf = 0; - if ($config{HAS_KQUEUE}) { - $config{USE_KQUEUE} = prompt_bool(1, 'Your operating system has support for the high performance kqueue socket engine. Would you like to enable it?', 1); - if ($config{USE_KQUEUE}) { - $config{SOCKETENGINE} = "kqueue"; - $chose_hiperf = 1; +# Configure module settings. +$question = <<'EOQ'; +Currently, InspIRCd is configured to automatically enable all available extra modules. + +Would you like to enable extra modules manually? +EOQ +if (prompt_bool $interactive, $question, 0) { + for my $extra (<$RealDir/src/modules/extra/m_*.cpp>) { + my $module_name = module_shrink $extra; + if (prompt_bool $interactive, "Would you like to enable the <|BOLD $module_name|> module?", 0) { + enable_extras $module_name; } } - if ($config{HAS_EPOLL}) { - $config{USE_EPOLL} = prompt_bool(1, 'Your operating system has support for the high performance epoll socket engine. Would you like to enable it?', 1); - if ($config{USE_EPOLL}) { - $config{SOCKETENGINE} = "epoll"; - $chose_hiperf = 1; - } - } - if ($config{HAS_PORTS}) { - $config{USE_PORTS} = prompt_bool(1, 'Your operating system has support for the high performance IOCP socket engine. Would you like to enable it?', 1); - if ($config{USE_PORTS}) { - $config{SOCKETENGINE} = "ports"; - $chose_hiperf = 1; +} elsif (!defined $opt_disable_auto_extras) { + my %modules = ( + 'm_argon2.cpp' => 'pkg-config --exists libargon2', + 'm_geo_maxmind.cpp' => 'pkg-config --exists libmaxminddb', + 'm_mysql.cpp' => 'mysql_config --version', + 'm_pgsql.cpp' => 'pg_config --version', + 'm_ldap.cpp' => "echo '#include ' | $config{CXX} -E -", + 'm_regex_pcre.cpp' => 'pcre-config --version', + 'm_regex_posix.cpp' => undef, + 'm_regex_re2.cpp' => 'pkg-config --exists re2', + 'm_regex_stdlib.cpp' => "$config{CXX} -o /dev/null -std=c++11 $RealDir/make/test/compiler.cpp", + 'm_regex_tre.cpp' => 'pkg-config --exists tre', + 'm_sqlite3.cpp' => 'pkg-config --exists sqlite3', + 'm_ssl_gnutls.cpp' => 'pkg-config --exists gnutls', + 'm_ssl_mbedtls.cpp' => "echo '#include ' | $config{CXX} -E -", + 'm_ssl_openssl.cpp' => 'pkg-config --exists openssl', + 'm_sslrehashsignal.cpp' => undef, + ); + while (my ($module, $command) = each %modules) { + unless (defined $command && system "$command 1>/dev/null 2>/dev/null") { + enable_extras $module; } } +} - if (!$chose_hiperf && $config{HAS_POLL}) { - $config{USE_POLL} = prompt_bool(1, 'Your operating system has support for the mid performance poll socket engine. Would you like to enable it?', 1); - if ($config{USE_POLL}) { - $config{SOCKETENGINE} = "poll"; - } - } - unless ($chose_hiperf || $config{USE_POLL}) - { - print "No high-performance socket engines are available, or you chose not to enable one. Defaulting to select() engine.\n\n"; - $config{SOCKETENGINE} = "select"; - } +# Generate SSL certificates. +$question = < be used on a production network. - if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y") - { - print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n"; - print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n"; - - $config{USE_SSL} = prompt_bool(1, 'One or more SSL libraries detected. Would you like to enable SSL support?', 1); - if ($config{USE_SSL}) - { - if ($config{HAS_GNUTLS} eq "y") - { - $config{USE_GNUTLS} = prompt_bool(1, 'Would you like to enable SSL with m_ssl_gnutls (recommended)?', 1); - if ($config{USE_GNUTLS}) - { - print "Using GnuTLS SSL module.\n\n"; - unlink 'src/modules/m_ssl_gnutls.cpp' if -f 'src/modules/m_ssl_gnutls.cpp'; - symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!\n"; - } - } +Note: you can get a <|BOLD free|> CA-signed certificate from Let's Encrypt. See +https://letsencrypt.org/getting-started/ for more details. +EOQ - if ($config{HAS_OPENSSL} eq "y") - { - $config{USE_OPENSSL} = prompt_bool(1, 'Would you like to enable SSL with m_ssl_openssl (recommended)?', 1); - if ($config{USE_OPENSSL}) - { - print "Using OpenSSL SSL module.\n\n"; - unlink 'src/modules/m_ssl_openssl.cpp' if -f 'src/modules/m_ssl_openssl.cpp'; - symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!\n"; - } - } +if (<$RealDir/src/modules/m_ssl_*.cpp>) { + if (prompt_bool $interactive, $question, $interactive) { + create_directory CONFIGURE_DIRECTORY, 0750 or print_error "unable to create ${\CONFIGURE_DIRECTORY}: $!"; + system './tools/genssl', 'auto', CONFIGURE_DIRECTORY; + } else { + my @pems = <${\CONFIGURE_DIRECTORY}/{cert,csr,dhparams,key}.pem>; + $question = < for linking servers. + +Please read the following documentation pages on how to enable SSL support: + +GnuTLS (recommended): https://docs.inspircd.org/3/modules/ssl_gnutls +mbedTLS: https://docs.inspircd.org/3/modules/ssl_mbedtls +OpenSSL: https://docs.inspircd.org/3/modules/ssl_openssl +EOM } -# We are on a POSIX system, we can enable POSIX extras without asking -symlink "extra/m_regex_posix.cpp", "src/modules/m_regex_posix.cpp"; +# Cache the distribution label so that its not lost when --update is run. +$config{DISTRIBUTION} = $opt_distribution_label if $opt_distribution_label; -if (($config{USE_GNUTLS}) && ($config{HAS_GNUTLS} ne "y")) -{ - print "Sorry, but i couldn't detect gnutls. Make sure pkg-config is in your path.\n"; - exit 1; -} -if (($config{USE_OPENSSL}) && ($config{HAS_OPENSSL} ne "y")) -{ - print "Sorry, but i couldn't detect openssl. Make sure pkg-config is in your path.\n"; - exit 1; -} +write_configure_cache %config; +parse_templates \%config, \%compiler, \%version; -if ($config{USE_GNUTLS} || $config{USE_OPENSSL}) { - if (my $val = prompt_bool($interactive, 'Would you like to generate SSL certificates now?', $interactive)) { - unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem" && -r "$config{CONFIG_DIR}/dhparams.pem") { - unless (system './tools/genssl auto') { - print "\nCertificate generation complete, copying to config directory... "; - File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n"; - File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n"; - File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n"; - print "Done.\n\n"; - } - } else { - print "SSL Certificates found, skipping.\n\n" - } - } else { - print "Skipping SSL certificate generation in non-interactive mode.\n\n"; - } -} else { - print "Skipping SSL Certificate generation, SSL support is not available.\n\n"; -} +print console_format <<"EOM"; -print "Writing \e[1;32m.config.cache\e[0m ...\n"; -write_configure_cache(%config); -writefiles(); -dump_hash(); - -print "\n"; -print "To build your server with these settings, please run '\e[1;32mmake\e[0m' now.\n"; -if ($config{USE_GNUTLS} || $config{USE_OPENSSL}) { - print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n"; - print "modules in your config. This configure script has added those modules to the\n"; - print "build process. For more info please refer to:\n"; - print "\e[1;32mhttp://wiki.inspircd.org/Installation_From_Tarball\e[0m\n"; -} -print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n"; - -sub writefiles { - chomp(my $incos = `uname -n -s -r`); - chomp(my $version = `sh src/version.sh`); - my $revision = get_revision(); - my $branch = "InspIRCd-0.0"; - if ($version =~ /^(InspIRCd-[0-9]+\.[0-9]+)\.[0-9]+/) - { - $branch = $1; - } - print "Writing \e[1;32mconfig.h\e[0m\n"; - open(FILEHANDLE, ">include/config.h.tmp"); - print FILEHANDLE < + <|GREEN Binary:|> $config{CXX} + <|GREEN Name:|> $compiler{NAME} + <|GREEN Version:|> $compiler{VERSION} - unlink 'include/config.h'; - rename 'include/config.h.tmp', 'include/config.h'; +<|GREEN Extra Modules:|> +EOM - # Do this once here, and cache it in the .*.inc files, - # rather than attempting to read src/version.sh from - # compiled code -- we might not have the source to hand. +for my $file (<$RealDir/src/modules/m_*>) { + say " * ${\module_shrink $file}" if -l $file; +} - my @dotfiles = qw(main.mk inspircd); - push @dotfiles, 'org.inspircd.plist' if $^O eq 'darwin'; +my @makeargs; +push @makeargs, "-C${\abs2rel $RealDir}" unless getcwd eq $RealDir; +push @makeargs, "-j${\(get_cpu_count() + 1)}"; - foreach my $file (@dotfiles) { - open(FILEHANDLE, "make/template/$file") or die "Can't open make/template/$file: $!"; - $_ = join '', ; - close(FILEHANDLE); +print console_format <<"EOM"; - $config{BUILD_DIR} ||= rel2abs($topdir."/build"); - $config{COMPILER} = lc $cxx{NAME}; - $config{SYSTEM} = lc $^O; +<|GREEN Paths:|> + <|GREEN Binary:|> $config{BINARY_DIR} + <|GREEN Config:|> $config{CONFIG_DIR} + <|GREEN Data:|> $config{DATA_DIR} + <|GREEN Example:|> $config{EXAMPLE_DIR} + <|GREEN Log:|> $config{LOG_DIR} + <|GREEN Manual:|> $config{MANUAL_DIR} + <|GREEN Module:|> $config{MODULE_DIR} + <|GREEN Runtime:|> $config{RUNTIME_DIR} + <|GREEN Script:|> $config{SCRIPT_DIR} - for my $var (qw( - CXX COMPILER SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR DATA_DIR UID - STARTSCRIPT SOCKETENGINE - )) { - s/\@$var\@/$config{$var}/g; - } +<|GREEN Execution Group:|> $config{GROUP} ($config{GID}) +<|GREEN Execution User:|> $config{USER} ($config{UID}) +<|GREEN Socket Engine:|> $config{SOCKETENGINE} - s/\@VERSION\@/$version/ if defined $version; - - if ($file eq 'main.mk') { - print "Writing \e[1;32mGNUmakefile\e[0m ...\n"; - - my $mk_tmp = $_; - s/\@IFDEF (\S+)/ifdef $1/g; - s/\@IFNDEF (\S+)/ifndef $1/g; - s/\@IFEQ (\S+) (\S+)/ifeq ($1,$2)/g; - s/\@IFNEQ (\S+) (\S+)/ifneq ($1,$2)/g; - s/\@ELSIFEQ (\S+) (\S+)/else ifeq ($1,$2)/g; - s/\@ELSE/else/g; - s/\@ENDIF/endif/g; - s/ *\@BSD_ONLY .*\n//g; - s/\@GNU_ONLY //g; - s/\@DO_EXPORT (.*)/export $1/g; - open MKF, '>GNUmakefile' or die "Can't write to GNUmakefile: $!"; - print MKF $_; - close MKF; - - print "Writing \e[1;32mBSDmakefile\e[0m ...\n"; - $_ = $mk_tmp; - s/\@IFDEF (\S+)/.if defined($1)/g; - s/\@IFNDEF (\S+)/.if !defined($1)/g; - s/\@IFEQ (\S+) (\S+)/.if $1 == $2/g; - s/\@IFNEQ (\S+) (\S+)/.if $1 != $2/g; - s/\@ELSIFEQ (\S+) (\S+)/.elif $1 == $2/g; - s/\@ELSE/.else/g; - s/\@ENDIF/.endif/g; - s/\@BSD_ONLY //g; - s/ *\@GNU_ONLY .*\n//g; - $mk_tmp = $_; - $mk_tmp =~ s#\@DO_EXPORT (.*)#"MAKEENV += ".join ' ', map "$_='\${$_}'", split /\s/, $1#eg; - open MKF, '>BSDmakefile' or die "Can't write to BSDmakefile: $!"; - print MKF $mk_tmp; - close MKF; - } else { - print "Writing \e[1;32m$file\e[0m ...\n"; - open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n"); - print FILEHANDLE $_; - close(FILEHANDLE); - } - } +To build with these settings run '<|GREEN make ${\join ' ', @makeargs} install|>' now. - chmod 0750, 'inspircd'; -} +EOM # Routine to list out the extra/ modules that have been enabled. # Note: when getting any filenames out and comparing, it's important to lc it if the @@ -551,7 +514,7 @@ sub list_extras () { my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd)); closedir $dd; undef $dd; - my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0]; + my $maxlen = (sort { $b <=> $a } (map { length module_shrink $_ } (@extras)))[0]; my %extras = (); EXTRA: for my $extra (@extras) { next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra); @@ -594,7 +557,7 @@ EXTRA: for my $extra (@extras) { for my $extra (keys(%extras)) { next unless $extras{$extra} =~ m/enabled/; # only process enabled extras. my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra); - my @deps = split /\s+/, get_property($abs_extra, 'ModDep'); + my @deps = split /\s+/, get_directive($abs_extra, 'ModDep', ''); for my $dep (@deps) { if (exists($extras{$dep})) { my $ref = \$extras{$dep}; # Take reference. @@ -619,76 +582,64 @@ EXTRA: for my $extra (@extras) { for my $extra (sort {$a cmp $b} keys(%extras)) { my $text = $extras{$extra}; if ($text =~ m/needed by/ && $text !~ m/enabled/) { - printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : ""); + printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, module_shrink($extra), $text, ($text =~ m/needed by/ ? ")" : ""); } else { - printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : ""); + printf "%-*s = %s%s\n", $maxlen, module_shrink($extra), $text, ($text =~ m/needed by/ ? "\e[0m)" : ""); } } return keys(%extras) if wantarray; # Can be used by manage_extras. } -sub enable_extras (@) { - my (@extras) = @_; - for my $extra (@extras) { - my $extrapath = "src/modules/extra/$extra"; - if (!-e $extrapath) { - print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n"; - next; - } - my $source = "src/modules/$extra"; - if (-e $source) { - print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n"; - next; +sub enable_extras(@) { + my $moduledir = catdir $RealDir, 'src', 'modules'; + my $extradir = catdir $moduledir, 'extra'; + + for my $extra (@_) { + my $shortname = module_shrink $extra; + my $extrafile = module_expand $extra; + + my $extrapath = catfile $extradir, $extrafile; + if (!-f $extrapath) { + print_error "<|GREEN $extra|> is not an extra module!"; } - # Get dependencies, and add them to be processed. - my @deps = split /\s+/, get_property($extrapath, 'ModDep'); - for my $dep (@deps) { - next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway. - if (!-e "src/modules/$dep" && !-e "include/$dep") { - if (-e "src/modules/extra/$dep") { - print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n"; - push @extras, $dep; - } else { - 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"; - } + + my $modulepath = catfile $moduledir, $extrafile; + if (-l $modulepath) { + if (readlink($modulepath) ne $extrapath) { + unlink $modulepath; # Remove the dead symlink. + } else { + next; # Module is already enabled. } } - print "Enabling $extra ... \n"; - symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n"; + + if (-e $modulepath) { + print_error "unable to symlink <|GREEN ${\abs2rel $modulepath}|> to <|GREEN ${\abs2rel $extrapath}|>: the target exists and is not a symlink."; + } else { + say console_format "Enabling the <|GREEN $shortname|> module ..."; + symlink $extrapath, $modulepath or print_error "unable to symlink <|GREEN ${\abs2rel $modulepath}|> to <|GREEN ${\abs2rel $extrapath}|>: $!"; + } } } -sub disable_extras (@) -{ - opendir my $dd, "src/modules/extra/"; - my @files = readdir($dd); - closedir $dd; - my (@extras) = @_; -EXTRA: for my $extra (@extras) { - my $extrapath = "src/modules/extra/$extra"; - my $source = "src/modules/$extra"; - if (!-e $extrapath) { - print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n"; - next; - } - if ((! -l $source) || readlink($source) ne "extra/$extra") { - 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"; - next; - } - # Check if anything needs this. - for my $file (@files) { - my @deps = split /\s+/, get_property("src/modules/extra/$file", 'ModDep'); - # File depends on this extra... - if (scalar(grep { $_ eq $extra } @deps) > 0) { - # And is both enabled and not about to be disabled. - if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) { - print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n"; - next EXTRA; - } - } +sub disable_extras(@) { + my $moduledir = catdir $RealDir, 'src', 'modules'; + my $extradir = catdir $moduledir, 'extra'; + + for my $extra (@_) { + my $shortname = module_shrink $extra; + my $extrafile = module_expand $extra; + + my $modulepath = catfile $moduledir, $extrafile; + my $extrapath = catfile $extradir, $extrafile; + if (!-e $modulepath && !-e $extrapath) { + print_error "the <|GREEN $shortname|> module does not exist!"; + } elsif (!-e $modulepath && -e $extrapath) { + print_error "the <|GREEN $shortname|> module is not currently enabled!"; + } elsif ((-e $modulepath && !-e $extrapath) || !-l $modulepath) { + print_error "the <|GREEN $shortname|> module is not an extra module!"; + } else { + say console_format "Disabling the <|GREEN $shortname|> module ..."; + unlink $modulepath or print_error "unable to unlink <|GREEN $extrapath|>: $!"; } - # Now remove. - print "Disabling $extra ... \n"; - unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n"; } }