]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - configure
Temporary fix for HASHMAP_DEPRECATED on clang.
[user/henk/code/inspircd.git] / configure
index ac814035b2e6c5764547325a6a226ad7438f0339..dc7d113916196938c0f5d6c380d57ac292d1b9a6 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,19 +1,45 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 
-# InspIRCd Configuration Script
 #
 #
-# Copyright 2002-2007 The ChatSpike Development Team
-# <brain@chatspike.net>
-# <Craig@chatspike.net>
+# InspIRCd -- Internet Relay Chat Daemon
 #
 #
-# [14:21] Brain: <matrix impression> i know perl-fu!
+#   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
+#   Copyright (C) 2007, 2009 Dennis Friis <peavey@inspircd.org>
+#   Copyright (C) 2003, 2006-2008 Craig Edwards <craigedwards@brainbox.cc>
+#   Copyright (C) 2006-2008 Robin Burchell <robin+git@viroteck.net>
+#   Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
+#   Copyright (C) 2007 John Brooks <john.brooks@dereferenced.net>
+#   Copyright (C) 2006 Oliver Lupton <oliverlupton@gmail.com>
+#   Copyright (C) 2003-2006 Craig McLure <craig@chatspike.net>
 #
 #
-# $Id$
+# 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
+# License as published by the Free Software Foundation, version 2.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 #
-########################################
 
 
 
 
-require 5.6.0;
+BEGIN {
+       require 5.8.0;
+}
+
+use strict;
+use warnings FATAL => qw(all);
+
+use Data::Dumper;
+BEGIN {
+       $Data::Dumper::Sortkeys = 1;
+       $Data::Dumper::Useqq = 1;
+};
+
+use File::Copy ();
 use Socket;
 use Cwd;
 use Getopt::Long;
 use Socket;
 use Cwd;
 use Getopt::Long;
@@ -21,272 +47,257 @@ use Getopt::Long;
 # Utility functions for our buildsystem
 use make::utilities;
 use make::configure;
 # Utility functions for our buildsystem
 use make::utilities;
 use make::configure;
+use make::gnutlscert;
+use make::opensslcert;
+
+###############################################################################################
+#
+#                                 NON-EDITABLE VARIABLES
+#
+###############################################################################################
+
+our ($opt_use_gnutls, $opt_rebuild, $opt_use_openssl, $opt_nointeractive, $opt_ports,
+    $opt_epoll, $opt_kqueue, $opt_noports, $opt_noepoll, $opt_nokqueue,
+    $opt_noipv6, $opt_maxbuf, $opt_disable_debug, $opt_freebsd_port,
+       $opt_system, $opt_uid);
+
+our ($opt_cc, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir, $opt_data_dir, $opt_log_dir);
+
+sub list_extras ();
+
+sub enable_extras (@);
+
+sub disable_extras (@);
+
+my @opt_enableextras;
+my @opt_disableextras;
 
 GetOptions (
        'enable-gnutls' => \$opt_use_gnutls,
        'rebuild' => \$opt_rebuild,
 
 GetOptions (
        'enable-gnutls' => \$opt_use_gnutls,
        'rebuild' => \$opt_rebuild,
+       'system' => \$opt_system,
+       'uid=s' => \$opt_uid,
        'enable-openssl' => \$opt_use_openssl,
        'disable-interactive' => \$opt_nointeractive,
        'enable-openssl' => \$opt_use_openssl,
        'disable-interactive' => \$opt_nointeractive,
-       'with-nick-length=i' => \$opt_nick_length,
-       'with-channel-length=i' => \$opt_chan_length,
-       'with-max-channels=i' => \$opt_maxchans,
-       'with-max-oper-channels=i' => \$opt_opermaxchans,
-       'with-max-clients=i' => \$opt_maxclients,
+       'enable-ports' => \$opt_ports,
        'enable-epoll' => \$opt_epoll,
        'enable-kqueue' => \$opt_kqueue,
        'enable-epoll' => \$opt_epoll,
        'enable-kqueue' => \$opt_kqueue,
+       'disable-ports' => \$opt_noports,
        'disable-epoll' => \$opt_noepoll,
        'disable-kqueue' => \$opt_nokqueue,
        'disable-epoll' => \$opt_noepoll,
        'disable-kqueue' => \$opt_nokqueue,
-       'enable-ipv6' => \$opt_ipv6,
-       'enable-remote-ipv6' => \$opt_ipv6links,
-       'disable-remote-ipv6' => \$opt_noipv6links,
+       'disable-ipv6' => \$opt_noipv6,
        'with-cc=s' => \$opt_cc,
        'with-cc=s' => \$opt_cc,
-       'with-ident-length=i' => \$opt_ident,
-       'with-quit-length=i' => \$opt_quit,
-       'with-topic-length=i' => \$opt_topic,
-       'with-kick-length=i' => \$opt_kick,
-       'with-gecos-length=i' => \$opt_gecos,
-       'with-away-length=i' => \$opt_away,
-       'with-max-modes=i' => \$opt_modes,
+       'with-maxbuf=i' => \$opt_maxbuf,
+       'enable-freebsd-ports-openssl' => \$opt_freebsd_port,
        'prefix=s' => \$opt_base_dir,
        'config-dir=s' => \$opt_config_dir,
        'module-dir=s' => \$opt_module_dir,
        'binary-dir=s' => \$opt_binary_dir,
        'prefix=s' => \$opt_base_dir,
        'config-dir=s' => \$opt_config_dir,
        'module-dir=s' => \$opt_module_dir,
        'binary-dir=s' => \$opt_binary_dir,
-       'library-dir=s' => \$opt_library_dir,
+       'data-dir=s' => \$opt_data_dir,
+       'log-dir=s' => \$opt_log_dir,
        'disable-debuginfo' => sub { $opt_disable_debug = 1 },
        'help'  => sub { showhelp(); },
        'disable-debuginfo' => sub { $opt_disable_debug = 1 },
        'help'  => sub { showhelp(); },
-       'modupdate' => sub { modupdate(); },
        'update' => sub { update(); },
        'update' => sub { update(); },
-       'svnupdate' => sub { svnupdate(); },
        'clean' => sub { clean(); },
        'clean' => sub { 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, # ^
+       'generate-openssl-cert' => sub { make_openssl_cert(); exit(0); },
+       'generate-gnutls-cert' => sub { make_gnutls_cert(); exit(0); }
 );
 
 );
 
-my $non_interactive = (
-       (defined $opt_library_dir) ||
+if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
+       @opt_enableextras = split /,/, join(',', @opt_enableextras);
+       @opt_disableextras = split /,/, join(',', @opt_disableextras);
+       enable_extras(@opt_enableextras);
+       disable_extras(@opt_disableextras);
+       list_extras;
+       print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
+       exit 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_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_nointeractive) ||
-       (defined $opt_away) ||
-       (defined $opt_gecos) ||
-       (defined $opt_kick) ||
-       (defined $opt_maxclients) ||
-       (defined $opt_modes) ||
-       (defined $opt_topic) ||
-       (defined $opt_quit) ||
-       (defined $opt_ident) ||
        (defined $opt_cc) ||
        (defined $opt_cc) ||
-       (defined $opt_ipv6) ||
-       (defined $opt_ipv6links) ||
-       (defined $opt_noipv6links) ||
+       (defined $opt_noipv6) ||
        (defined $opt_kqueue) ||
        (defined $opt_epoll) ||
        (defined $opt_kqueue) ||
        (defined $opt_epoll) ||
-       (defined $opt_maxchans) ||
-       (defined $opt_opermaxchans) ||
-       (defined $opt_chan_length) ||
-       (defined $opt_nick_length) ||
+       (defined $opt_ports) ||
        (defined $opt_use_openssl) ||
        (defined $opt_nokqueue) ||
        (defined $opt_noepoll) ||
        (defined $opt_use_openssl) ||
        (defined $opt_nokqueue) ||
        (defined $opt_noepoll) ||
-       (defined $opt_use_gnutls)
+       (defined $opt_noports) ||
+       (defined $opt_maxbuf) ||
+       (defined $opt_system) ||
+       (defined $opt_uid) ||
+       (defined $opt_use_gnutls) ||
+       (defined $opt_freebsd_port)
 );
 );
-my $interactive = !$non_interactive;
-
 
 
-chomp($topdir = getcwd());
-$this = resolve_directory($topdir);                                            # PWD, Regardless.
-@modlist = ();                                                         # Declare for Module List..
-%config = ();                                                          # Initiate Configuration Hash..
-$config{ME}             = resolve_directory($topdir);                  # Present Working Directory
+chomp(our $topdir = getcwd());
+our $this = resolve_directory($topdir);                                                # PWD, Regardless.
+our @modlist = ();                                                                     # Declare for Module List..
+our %config = ();                                                                      # Initiate Configuration Hash..
+our $cache_loaded = getcache();
+$config{ME} = resolve_directory($topdir);                              # Present Working Directory
 
 
-$config{BASE_DIR}         = $config{ME};
+$config{BASE_DIR} = $config{ME}."/run";
 
 
-if (defined $opt_base_dir)
-{
+if (defined $opt_base_dir) {
        $config{BASE_DIR} = $opt_base_dir;
        $config{BASE_DIR} = $opt_base_dir;
+} elsif (defined $opt_system || defined $opt_uid) {
+       $config{BASE_DIR} = '/var/lib/inspircd';
 }
 
 }
 
-$config{CONFIG_DIR}     = resolve_directory($config{BASE_DIR}."/conf");                # Configuration Directory
-$config{MODULE_DIR}     = resolve_directory($config{BASE_DIR}."/modules");             # Modules Directory
-$config{BINARY_DIR}     = resolve_directory($config{BASE_DIR}."/bin");         # Binary Directory
-$config{LIBRARY_DIR}   = resolve_directory($config{BASE_DIR}."/lib");          # Library Directory
+if (defined $opt_system || defined $opt_uid) {
+       $config{UID} = $opt_uid || 'ircd';
+       $config{CONFIG_DIR}      = '/etc/inspircd';
+       $config{MODULE_DIR}      = '/usr/lib/inspircd';
+       $config{BINARY_DIR}      = '/usr/sbin/';
+       $config{BUILD_DIR}       = resolve_directory($config{ME}."/build");         # Build Directory
+       $config{DATA_DIR}        = '/var/inspircd';
+       $config{LOG_DIR}         = '/var/log/inspircd';
+} else {
+       $config{UID} = $<;
+       $config{CONFIG_DIR}      = resolve_directory($config{BASE_DIR}."/conf");        # Configuration Directory
+       $config{MODULE_DIR}      = resolve_directory($config{BASE_DIR}."/modules");     # Modules Directory
+       $config{BINARY_DIR}      = resolve_directory($config{BASE_DIR}."/bin");         # Binary Directory
+       $config{BUILD_DIR}       = resolve_directory($config{ME}."/build");         # Build Directory
+       $config{DATA_DIR}        = resolve_directory($config{BASE_DIR}."/data");        # Data directory
+       $config{LOG_DIR}         = resolve_directory($config{BASE_DIR}."/logs");        # Log directory
+}
 
 
-if (defined $opt_config_dir)
-{
+if (defined $opt_config_dir) {
        $config{CONFIG_DIR} = $opt_config_dir;
 }
        $config{CONFIG_DIR} = $opt_config_dir;
 }
-if (defined $opt_module_dir)
-{
+if (defined $opt_module_dir) {
        $config{MODULE_DIR} = $opt_module_dir;
 }
        $config{MODULE_DIR} = $opt_module_dir;
 }
-if (defined $opt_binary_dir)
-{
+if (defined $opt_binary_dir) {
        $config{BINARY_DIR} = $opt_binary_dir;
 }
        $config{BINARY_DIR} = $opt_binary_dir;
 }
-if (defined $opt_library_dir)
-{
-       $config{LIBRARY_DIR} = $opt_library_dir;
+if (defined $opt_data_dir) {
+       $config{DATA_DIR} = $opt_data_dir;
 }
 }
-chomp($config{HAS_GNUTLS}   = `libgnutls-config --version 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
-chomp($config{HAS_OPENSSL}  = `openssl version 2>/dev/null`);                  # Openssl version
-$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";
+if (defined $opt_log_dir) {
+       $config{LOG_DIR} = $opt_log_dir;
 }
 }
+chomp($config{HAS_GNUTLS}   = `pkg-config --modversion gnutls 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
 
 
-# no, let's not change these.
-$config{OPTIMITEMP}     = "0";                                 # Default Optimisation Value
-if (!defined $opt_disable_debug)
+if (defined $opt_freebsd_port)
 {
 {
-       $config{OPTIMISATI}      = "-O2 -g1";                           # Optimisation Flag
+       chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`);
+       chomp($config{HAS_OPENSSL_PORT}  = `pkg-config --modversion openssl 2>/dev/null`);
+       $config{USE_FREEBSD_BASE_SSL} = "n";
 }
 else
 {
 }
 else
 {
-       $config{OPTIMISATI}      = "-O2";                               # DEBUGGING OFF!
+       if ($^O eq "freebsd")
+       {
+               # default: use base ssl
+               chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`);                      # OpenSSL version, freebsd specific
+               chomp($config{HAS_OPENSSL_PORT}  = `pkg-config --modversion openssl 2>/dev/null`);      # Port version, may be different
+       }
+       else
+       {
+               chomp($config{HAS_OPENSSL}  = `pkg-config --modversion openssl 2>/dev/null`);           # Openssl version, others
+               $config{HAS_OPENSSL_PORT} = "";
+       }
 }
 
 }
 
-$config{NICK_LENGT}     = "31";                                        # Default Nick Length
-if (defined $opt_nick_length)
-{
-       $config{NICK_LENGT} = $opt_nick_length;
-}
-$config{CHAN_LENGT}     = "64";                                        # Default Channel Name Length
-if (defined $opt_chan_length)
-{
-       $config{CHAN_LENGT} = $opt_chan_length;
-}
-$config{MAX_CHANNE}     = "20";                                        # Default Max. Channels per user
-if (defined $opt_maxchans)
+chomp(our $gnutls_ver = $config{HAS_GNUTLS});
+chomp(our $openssl_ver = $config{HAS_OPENSSL});
+$config{USE_GNUTLS}        = "n";
+if (defined $opt_use_gnutls)
 {
 {
-       $config{MAX_CHANNE} = $opt_maxchans;
+       $config{USE_GNUTLS} = "y";                                      # Use gnutls.
 }
 }
-$config{MAX_OPERCH}     = "60";                                                # Default Max. Channels per oper
-if (defined $opt_opermaxchans)
+$config{USE_OPENSSL}   = "n";                                          # Use openssl.
+if (defined $opt_use_openssl)
 {
 {
-       $config{MAX_OPERCH} = $opt_opermaxchans;
+       $config{USE_OPENSSL} = "y";
 }
 }
-$config{MAXI_MODES}     = "20";                                        # Default Max. Number of Modes set at once.
-if (defined $opt_modes)
-{
-       $config{MAXI_MODES} = $opt_modes;
+
+if (!defined $opt_disable_debug) {
+       $config{OPTIMISATI}      = "-g1";                               # Optimisation Flag
+} else {
+       $config{OPTIMISATI}      = "-O2";
 }
 }
+
 $config{HAS_STRLCPY}   = "false";                                      # strlcpy Check.
 $config{HAS_STRLCPY}   = "false";                                      # strlcpy Check.
-$config{HAS_STDINT}     = "false";                                             # stdint.h check
+$config{HAS_STDINT}     = "false";                                     # stdint.h check
 $config{USE_KQUEUE}     = "y";                                         # kqueue enabled
 $config{USE_KQUEUE}     = "y";                                         # kqueue enabled
-if (defined $opt_kqueue)
-{
-       $config{USE_KQUEUE} = "y";
-}
-if (defined $opt_nokqueue)
-{
+if (defined $opt_nokqueue) {
        $config{USE_KQUEUE} = "n";
 }
        $config{USE_KQUEUE} = "n";
 }
-$config{USE_EPOLL}       = "y";                                                # epoll enabled
-if (defined $opt_epoll)
-{
-       $config{USE_EPOLL} = "y";
-}
+$config{USE_POLL}     = "y";                                   # poll enabled
+$config{USE_EPOLL}       = "y";                                        # epoll enabled
 if (defined $opt_noepoll)
 {
        $config{USE_EPOLL} = "n";
 }
 if (defined $opt_noepoll)
 {
        $config{USE_EPOLL} = "n";
 }
-$config{IPV6}         = "n";                                           # IPv6 support (experimental)
-if (defined $opt_ipv6)
+$config{USE_PORTS}       = "y";                                        # epoll enabled
+if (defined $opt_noports)
 {
 {
-       $config{IPV6} = "y";
+       $config{USE_PORTS} = "n";
 }
 }
-$config{SUPPORT_IP6LINKS}   = "y";                                             # IPv4 supporting IPv6 links (experimental)
-if (defined $opt_ipv6links)
+$config{_SOMAXCONN} = SOMAXCONN;                                       # Max connections in accept queue
+$config{OSNAME}            = $^O;                                      # Operating System Name
+$config{IS_DARWIN}       = "NO";                                       # Is OSX?
+$config{STARTSCRIPT}     = "inspircd";                 # start script?
+$config{DESTINATION}     = "BASE";                             # Is target path.
+if ($config{OSNAME} =~ /darwin/i)
 {
 {
-       $config{SUPPORT_IP6LINKS} = "y";
+       $config{IS_DARWIN} = "YES";
+       $config{STARTSCRIPT}      = "org.inspircd.plist";               # start script for OSX.
+       $config{CC}                 = "xcrun clang++";                                  # C++ compiler for OSX.
 }
 }
-if (defined $opt_noipv6links)
+else
 {
 {
-       $config{SUPPORT_IP6LINKS} = "n";
+       $config{CC}                 = "g++";                                            # C++ compiler
 }
 }
-$config{STATIC_LINK}       = "no";                                             # are doing static modules?
-chomp($config{MAX_CLIENT_T} = `sh -c \"ulimit -n\"`);                  # FD Limit
-chomp($config{MAX_DESCRIPTORS} = `sh -c \"ulimit -n\"`);                       # Hard FD Limit
-chomp($config{GCCVER}       = `g++ -dumpversion | cut -c 1`);                  # Major GCC Version
-$config{_SOMAXCONN} = SOMAXCONN;                                               # Max connections in accept queue
-$config{OSNAME}            = $^O;                                      # Operating System Name
-$config{CC}                = "g++";                                            # C++ compiler
 if (defined $opt_cc)
 {
        $config{CC} = $opt_cc;
 }
 if (defined $opt_cc)
 {
        $config{CC} = $opt_cc;
 }
-$exec = $config{CC} . " -dumpversion | cut -c 1";
-chomp($config{GCCVER}       = `$exec`);                                                # Major GCC Version
-$config{MAKEORDER}         = "ircd mods";                                      # build order
-$config{STATICLIBS}     = "";                                          # library archive path
-$config{MAX_IDENT}       = "12";                                               # max ident size
-$config{MAX_QUIT}         = "255";                                             # max quit message size
-$config{MAX_TOPIC}       = "307";                                              # max topic size
-$config{MAX_KICK}         = "255";                                             # max kick message size
-$config{MAX_GECOS}       = "128";                                              # max GECOS size
-$config{MAX_AWAY}         = "200";                                             # max AWAY size
-if (defined $opt_ident)
-{
-       $config{MAX_IDENT} = $opt_ident;
-}
-if (defined $opt_quit)
-{
-       $config{MAX_QUIT} = $opt_quit;
-}
-if (defined $opt_topic)
-{
-       $config{MAX_TOPIC} = $opt_topic;
-}
-if (defined $opt_kick)
-{
-       $config{MAX_KICK} = $opt_kick;
-}
-if (defined $opt_gecos)
-{
-       $config{MAX_GECOS} = $opt_gecos;
-}
-if (defined $opt_away)
-{
-       $config{MAX_AWAY} = $opt_away;
+our $exec = $config{CC} . " -dumpversion | cut -c 1";
+chomp($config{GCCVER}          = `$exec`);                             # Major GCC Version
+$exec = $config{CC} . " -dumpversion | cut -c 3";
+chomp($config{GCCMINOR}                = `$exec`);
+$config{MAXBUF}                        = "512";                                # Max buffer size
+
+if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/) {
+       $config{HAS_OPENSSL} = $1;
+} else {
+       $config{HAS_OPENSSL} = "";
 }
 
 }
 
-$config{HAS_OPENSSL} =~ /OpenSSL ([-[:digit:].]+)([a-z])?(\-[a-z][0-9])? (\w{3}|[0-9]+) (\w{3}|[0-9]+) [0-9]{4}/;
-$config{HAS_OPENSSL} = $1;
-
-if ($config{GCCVER} eq "") {
-       print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
+if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
+       if ($config{IS_DARWIN} eq "YES") {
+               print $config{CC} . " was not found! You require clang++ (the LLVM C++ compiler, part of the OSX developer tools) to build InspIRCd!\n";
+       } else {
+               print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";         
+       }
        exit;
 }
 
        exit;
 }
 
-# Minihack! Convert Cygwin to 'Cyg-Static' so i can
-# Keep my dynamic module experiments here for later
-# consideration!
-
-if ($config{OSNAME} =~ /CYGWIN/i)
-{
-       $config{OSNAME} = "CYG-STATIC";
-}
-
-if (!$config{MAX_CLIENT_T}) { 
-       $config{MAX_CLIENT_T} = 1024;                            # Set a reasonable 'Default'
-       $fd_scan_fail = "true";                                # Used Later
-}
-
 # Get and Set some important vars..
 getmodules();
 
 sub clean
 {
 # Get and Set some important vars..
 getmodules();
 
 sub clean
 {
-       system("rm -rf .config.cache");
+       unlink(".config.cache");
 }
 
 }
 
+our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
+
 sub update
 {
        eval {
 sub update
 {
        eval {
@@ -300,15 +311,14 @@ sub update
                        exit 0;
                } else {
                        # We've Loaded the cache file and all our variables..
                        exit 0;
                } else {
                        # We've Loaded the cache file and all our variables..
-                       print "Updating Files..\n";
-                       getosflags();
-                       if ($opt_disable_debug == 1)
+                       print "Updating files...\n";
+                       if (defined($opt_disable_debug) && $opt_disable_debug == 1)
                        {
                                print "Disabling debug information (-g).\n";
                                $config{OPTIMISATI} = "";
                        {
                                print "Disabling debug information (-g).\n";
                                $config{OPTIMISATI} = "";
-                               getosflags();
                        }
                        $has_epoll = $config{HAS_EPOLL};
                        }
                        $has_epoll = $config{HAS_EPOLL};
+                       $has_ports = $config{HAS_PORTS};
                        $has_kqueue = $config{HAS_KQUEUE};
                        writefiles(1);
                        makecache();
                        $has_kqueue = $config{HAS_KQUEUE};
                        writefiles(1);
                        makecache();
@@ -323,79 +333,30 @@ sub update
        exit;
 }
 
        exit;
 }
 
-sub modupdate
-{
-       eval {
-               chomp($topdir = getcwd());
-               $this = resolve_directory($topdir);                                          # PWD, Regardless.
-               getmodules();
-               # Does the cache file exist?
-               if (!getcache()) {
-                       # No, No it doesn't.. *BASH*
-                       print "You have not run ./configure before. Please do this before trying to run the update script.\n";
-                       exit 0;
-               } else {
-                       # We've Loaded the cache file and all our variables..
-                       print "Updating Files..\n";
-                       getosflags();
-                       $has_epoll = $config{HAS_EPOLL};
-                       $has_kqueue = $config{HAS_KQUEUE};
-                       writefiles(0);
-                       makecache();
-                       print "Complete.\n";
-                       exit;
-               }
-       };
-       if ($@)
-       {
-               print "Module update failed: $@\n";
-       }
-       exit;
-}
 
 
-
-
-sub svnupdate
-{
+sub test_compile {
+       my $feature = shift;
        my $fail = 0;
        my $fail = 0;
-       open(FH,"<.svn/entries") or $fail = 1;
-       if ($fail) {
-               print "This is not an SVN copy of InspIRCd.\n";
-               exit;
-       }
-       else
-       {
-               close(FH);
-       }
-       system("svn update");
-       system("perl configure -update");
-       if (defined $opt_rebuild) {
-               system("make install");
-       }
-       exit;
+       $fail ||= system "$config{CC} -o test_$feature make/check_$feature.cpp >/dev/null 2>&1";
+       $fail ||= system "./test_$feature";
+       unlink "test_$feature";
+       return !$fail;
 }
 
 print "Running non-interactive configure...\n" unless $interactive;
 print "Checking for cache from previous configure... ";
 }
 
 print "Running non-interactive configure...\n" unless $interactive;
 print "Checking for cache from previous configure... ";
-print ((getcache() eq "true") ? "found\n" : "not found\n");
-print "Checking operating system version... ";
-print getosflags() . "\n";
+print ($cache_loaded ? "found\n" : "not found\n");
+$config{SYSTEM} = lc $^O;
+print "Checking operating system version... $config{SYSTEM}\n";
 
 
-if (defined $opt_maxclients)
-{
-       $config{MAX_CLIENT} = $opt_maxclients;
-}
-
-if (!$config{MAX_CLIENT}) { 
-       # If the cache hasn't set the max clients, copy the variable of MAX_CLIENT_T, this
-       # allows us to keep _T for testing purposes. (ie. "Are you sure you want to go
-       # higher than the found value" :))
-       $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
-}
+$exec = $config{CC} . " -dumpversion | cut -c 1";
+chomp($config{GCCVER}          = `$exec`);                             # Major GCC Version
+$exec = $config{CC} . " -dumpversion | cut -c 3";
+chomp($config{GCCMINOR}                = `$exec`);
 
 printf "Checking if stdint.h exists... ";
 $config{HAS_STDINT} = "true";
 
 printf "Checking if stdint.h exists... ";
 $config{HAS_STDINT} = "true";
-my $fail = 0;
+our $fail = 0;
 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
 if ($config{HAS_STDINT} eq "true") {
        close(STDINT);
 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
 if ($config{HAS_STDINT} eq "true") {
        close(STDINT);
@@ -403,14 +364,14 @@ if ($config{HAS_STDINT} eq "true") {
 print "yes\n" if $config{HAS_STDINT} eq "true";
 print "no\n" if $config{HAS_STDINT} eq "false";
 
 print "yes\n" if $config{HAS_STDINT} eq "true";
 print "no\n" if $config{HAS_STDINT} eq "false";
 
-
 printf "Checking if strlcpy exists... ";
 # Perform the strlcpy() test..
 $config{HAS_STRLCPY} = "false";
 printf "Checking if strlcpy exists... ";
 # Perform the strlcpy() test..
 $config{HAS_STRLCPY} = "false";
-my $fail = 0;
+$fail = 0;
 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
 if (!$fail) {
 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
 if (!$fail) {
-       while (chomp($line = <STRLCPY>)) {
+       while (defined(my $line = <STRLCPY>)) {
+               chomp($line);
                # try and find the delcaration of:
                # size_t strlcpy(...)
                if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
                # try and find the delcaration of:
                # size_t strlcpy(...)
                if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
@@ -422,13 +383,13 @@ if (!$fail) {
 print "yes\n" if $config{HAS_STRLCPY} eq "true";
 print "no\n" if $config{HAS_STRLCPY} eq "false";
 
 print "yes\n" if $config{HAS_STRLCPY} eq "true";
 print "no\n" if $config{HAS_STRLCPY} eq "false";
 
-
 printf "Checking if kqueue exists... ";
 $has_kqueue = 0;
 $fail = 0;
 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
 if (!$fail) {
 printf "Checking if kqueue exists... ";
 $has_kqueue = 0;
 $fail = 0;
 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
 if (!$fail) {
-       while (chomp($line = <KQUEUE>)) {
+       while (defined(my $line = <KQUEUE>)) {
+               chomp($line);
                # try and find the delcaration of:
                # int kqueue(void);
                if ($line =~ /int(\0x9|\s)+kqueue/) {
                # try and find the delcaration of:
                # int kqueue(void);
                if ($line =~ /int(\0x9|\s)+kqueue/) {
@@ -440,49 +401,82 @@ if (!$fail) {
 print "yes\n" if $has_kqueue == 1;
 print "no\n" if $has_kqueue == 0;
 
 print "yes\n" if $has_kqueue == 1;
 print "no\n" if $has_kqueue == 0;
 
-printf "Checking if epoll exists... ";
-$has_epoll = 0;
-$fail = 0;
-open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
-if (!$fail) {
-       $has_epoll = 1;
-       close(EPOLL);
-}
-if ($has_epoll) {
+printf "Checking for epoll support... ";
+$has_epoll = test_compile('epoll');
+print $has_epoll ? "yes\n" : "no\n";
+
+printf "Checking for eventfd support... ";
+$config{HAS_EVENTFD} = test_compile('eventfd') ? 'true' : 'false';
+print $config{HAS_EVENTFD} eq 'true' ? "yes\n" : "no\n";
+
+printf "Checking if Solaris I/O completion ports are available... ";
+$has_ports = 0;
+our $system = `uname -s`;
+chomp ($system);
+$has_ports = 1 if ($system eq "SunOS");
+
+if ($has_ports) {
        my $kernel = `uname -r`;
        chomp($kernel);
        my $kernel = `uname -r`;
        chomp($kernel);
-       if (($kernel =~ /^2\.0\./) || ($kernel =~ /^2\.2\./) || ($kernel =~ /^2\.4\./)) {
-               $has_epoll = 0;
+       if (($kernel !~ /^5\.1./)) {
+               $has_ports = 0;
        }
 }
        }
 }
-print "yes\n" if $has_epoll == 1;
-print "no\n" if $has_epoll == 0;
-
-if (($config{OSNAME} =~ /CYGWIN/) || ($config{OSNAME} eq "CYG-STATIC")) {
-       $config{HAS_STRLCPY} = "true";
-}
+print "yes\n" if $has_ports == 1;
+print "no\n" if $has_ports == 0;
 
 $config{HAS_EPOLL} = $has_epoll;
 
 $config{HAS_EPOLL} = $has_epoll;
-$config{HAS_KQUEUE} = $has_kqueue; 
+$config{HAS_KQUEUE} = $has_kqueue;
 
 printf "Checking for libgnutls... ";
 
 printf "Checking for libgnutls... ";
-if (($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS} >= 1.2) || ($config{HAS_GNUTLS} eq "y"))) {
-       print "yes\n";
-       $config{HAS_GNUTLS} = "y";
+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";
+       }
 } else {
        print "no\n";
        $config{HAS_GNUTLS} = "n";
 }
 
 printf "Checking for openssl... ";
 } else {
        print "no\n";
        $config{HAS_GNUTLS} = "n";
 }
 
 printf "Checking for openssl... ";
-if (($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL} >= 0.8) || ($config{HAS_OPENSSL} eq "y"))) {
-       print "yes\n";
-       $config{HAS_OPENSSL} = "y";
+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";
+       }
 } else {
        print "no\n";
        $config{HAS_OPENSSL} = "n";
 }
 
 } else {
        print "no\n";
        $config{HAS_OPENSSL} = "n";
 }
 
+printf "Checking if you are running an ancient, unsupported OS... ";
+if ($config{OSNAME} =~ /FreeBSD/i)
+{
+       my $version = `uname -r`;
+       if ($version =~ /^4\./)
+       {
+               print "yes.\n";
+               print "FreeBSD 4.x is no longer supported. By ANYONE.\n";
+               print "To build, you will need to add the following to CXXFLAGS:\n";
+               print "\t-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1\n";
+       }
+       else
+       {
+               print "no ($version)\n";
+       }
+}
+else
+{
+       print "no ($config{OSNAME})\n";
+}
+
 ################################################################################
 #                        BEGIN INTERACTIVE PART                              #
 ################################################################################
 ################################################################################
 #                        BEGIN INTERACTIVE PART                              #
 ################################################################################
@@ -490,55 +484,56 @@ if (($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL} >= 0.8) || ($config{HAS_OPE
 # Clear the Screen..
 if ($interactive)
 {
 # Clear the Screen..
 if ($interactive)
 {
-       system("clear");
-       $wholeos = $^O;
+       print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
+       my $wholeos = $^O;
 
        my $rev = getrevision();
        # Display Introduction Message..
 
        my $rev = getrevision();
        # Display Introduction Message..
-       print "
-Welcome to the \033[1mInspIRCd\033[0m Configuration program! (\033[1minteractive mode\033[0m)
-\033[1mPackage maintainers: Type ./configure --help for non-interactive help\033[0m
+       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.  ***
 
 
 *** 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 \033[1m<RETURN>\033[0m to accept the default for any option, or enter
-a new value. Please note: You will \033[1mHAVE\033[0m to read the docs
+Press \e[1m<RETURN>\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!
 
 dir, otherwise you won't have a config file!
 
-Your operating system is: \033[1;32m$config{OSNAME}\033[0m ($wholeos)
-Maximum file descriptors: \033[1;32m$config{MAX_CLIENT_T}\033[0m
-Your InspIRCd revision ID is \033[1;32mr$rev\033[0m";
+Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
+Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
+STOP
        if ($rev eq "r0") {
                print " (Non-SVN build)";
        }
        print ".\n\n";
 
        $config{CHANGE_COMPILER} = "n";
        if ($rev eq "r0") {
                print " (Non-SVN build)";
        }
        print ".\n\n";
 
        $config{CHANGE_COMPILER} = "n";
-       print "I have detected the following compiler: \033[1;32m$config{CC}\033[0m (version \033[1;32m$config{GCCVER}.x\033[0m)\n";
+       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";
 
        while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
 
        while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
-               print "\033[1;32mIMPORTANT!\033[0m A GCC 2.x compiler has been detected, and
+               print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
 should NOT be used. You should probably specify a newer compiler.\n\n";
 should NOT be used. You should probably specify a newer compiler.\n\n";
-               yesno(CHANGE_COMPILER,"Do you want to change the compiler?");
+               yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
                if ($config{CHANGE_COMPILER} =~ /y/i) {
                        print "What command do you want to use to invoke your compiler?\n";
                if ($config{CHANGE_COMPILER} =~ /y/i) {
                        print "What command do you want to use to invoke your compiler?\n";
-                       print "[\033[1;32m$config{CC}\033[0m] -> ";
+                       print "[\e[1;32m$config{CC}\e[0m] -> ";
                        chomp($config{CC} = <STDIN>);
                        if ($config{CC} eq "") {
                                $config{CC} = "g++";
                        }
                        chomp($config{CC} = <STDIN>);
                        if ($config{CC} eq "") {
                                $config{CC} = "g++";
                        }
-                       chomp($foo = `$config{CC} -dumpversion | cut -c 1`);
+                       chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
                        if ($foo ne "") {
                                chomp($config{GCCVER}       = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
                        if ($foo ne "") {
                                chomp($config{GCCVER}       = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
-                               print "Queried compiler: \033[1;32m$config{CC}\033[0m (version \033[1;32m$config{GCCVER}.x\033[0m)\n";
+                               chomp($config{GCCMINOR}     = `$config{CC} -dumpversion | cut -c 3`);
+                               print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
                                if ($config{GCCVER} < 3) {
                                if ($config{GCCVER} < 3) {
-                                       print "\033[1;32mGCC 2.x WILL NOT WORK!\033[0m. Let's try that again, shall we?\n";
+                                       print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
                                }
                        }
                        else {
                                }
                        }
                        else {
-                               print "\033[1;32mWARNING!\033[0m Could not execute the compiler you specified. You may want to try again.\n";
+                               print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
                        }
                }
        }
                        }
                }
        }
@@ -551,85 +546,119 @@ should NOT be used. You should probably specify a newer compiler.\n\n";
        if ($tmpbase ne $config{BASE_DIR}) {
                $config{CONFIG_DIR}      = resolve_directory($config{BASE_DIR}."/conf");           # Configuration Dir
                $config{MODULE_DIR}      = resolve_directory($config{BASE_DIR}."/modules");     # Modules Directory
        if ($tmpbase ne $config{BASE_DIR}) {
                $config{CONFIG_DIR}      = resolve_directory($config{BASE_DIR}."/conf");           # Configuration Dir
                $config{MODULE_DIR}      = resolve_directory($config{BASE_DIR}."/modules");     # Modules Directory
+               $config{DATA_DIR}        = resolve_directory($config{BASE_DIR}."/data");        # Data Directory
+               $config{LOG_DIR}         = resolve_directory($config{BASE_DIR}."/logs");        # Log Directory
                $config{BINARY_DIR}      = resolve_directory($config{BASE_DIR}."/bin");     # Binary Directory
                $config{BINARY_DIR}      = resolve_directory($config{BASE_DIR}."/bin");     # Binary Directory
-               $config{LIBRARY_DIR}    = resolve_directory($config{BASE_DIR}."/lib");      # Library Directory
        }
 
        dir_check("are the configuration files", "CONFIG_DIR");
        dir_check("are the modules to be compiled to", "MODULE_DIR");
        dir_check("is the IRCd binary to be placed", "BINARY_DIR");
        }
 
        dir_check("are the configuration files", "CONFIG_DIR");
        dir_check("are the modules to be compiled to", "MODULE_DIR");
        dir_check("is the IRCd binary to be placed", "BINARY_DIR");
-       dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
-
+       dir_check("are variable data files to be located in", "DATA_DIR");
+       dir_check("are the logs to be stored in", "LOG_DIR");
+       dir_check("do you want the build to take place", "BUILD_DIR");
+               
+       my $chose_hiperf = 0;
        if ($has_kqueue) {
        if ($has_kqueue) {
-               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?");
+               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?");
                print "\n";
                print "\n";
+               if ($config{USE_KQUEUE} eq "y") {
+                       $chose_hiperf = 1;
+               }
        }
        if ($has_epoll) {
        }
        if ($has_epoll) {
-               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?");
+               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?");
                print "\n";
                print "\n";
+               if ($config{USE_EPOLL} eq "y") {
+                       $chose_hiperf = 1;
+               }
        }
        }
-       $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y"));
-       if (!$chose_hiperf) {
-               print "No high-performance socket engines are available, or you chose\n";
-               print "not to enable one. Defaulting to select() engine.\n\n";
+       if ($has_ports) {
+               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?");
+               print "\n";
+               if ($config{USE_PORTS} eq "y") {
+                       $chose_hiperf = 1;
+               }
        }
 
        }
 
-       yesno(IPV6,"Would you like to build InspIRCd with IPv6 support?");
-       print "\n";
+       if (!$chose_hiperf) {
+               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?");
+               if ($config{USE_POLL} ne "y")
+               {
+                       print "No high-performance socket engines are available, or you chose\n";
+                       print "not to enable one. Defaulting to select() engine.\n\n";
+               }
+       }
 
 
-       if ($config{IPV6} eq "y") {
-               print "You have chosen to build an \033[1;32mIPV6-only\033[0m server.\nTo accept IPV4 users, you must use the '::ffff:' notation of addresses.\n\n";
-               $config{SUPPORT_IP6LINKS} = "y";
-       } else {
-               yesno(SUPPORT_IP6LINKS,"You have chosen to build an \033[1;32mIPV4-only\033[0m server.\nWould you like to enable support for linking to IPV6-enabled\nInspIRCd servers which are using '::ffff:' notation?\nIf you are using a recent operating\nsystem and are unsure, answer yes.");
+       $config{USE_FREEBSD_BASE_SSL} = "n";
+       $config{USE_FREEBSD_PORTS_SSL} = "n";
+       if ($config{HAS_OPENSSL_PORT} ne "")
+       {
+               $config{USE_FREEBSD_PORTS_SSL} = "y";
+               print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
+               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";
+               yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
                print "\n";
                print "\n";
-       }
+               $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
 
 
-       if (($config{HAS_GNUTLS} eq "y") && ($config{HAS_OPENSSL} eq "y")) {
-               print "I have detected both GnuTLS and OpenSSL on your system.\n";
-               print "I will default to GnuTLS. If you wish to use OpenSSL\n";
-               print "instead, you should enable the OpenSSL module yourself\n";
-               print "by copying it from src/modules/extra to src/modules.\n\n";
+               if ($config{USE_FREEBSD_BASE_SSL} eq "n")
+               {
+                       # update to port version
+                       $openssl_ver = $config{HAS_OPENSSL_PORT};
+               }
+       }
+       else
+       {
+               $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
        }
 
        }
 
-       if ($config{HAS_GNUTLS} eq "y") {
-               yesno(USE_GNUTLS, "Would you like to enable SSL Support?");
-               if ($config{USE_GNUTLS} eq "y") {
-                       print "\nUsing GnuTLS SSL module.\n";
-               }
-       } elsif ($config{HAS_OPENSSL} eq "y") {
-                       yesno(USE_OPENSSL, "Would you like to enable SSL Support?");
-       if ($config{USE_OPENSSL} eq "y") {
-                       print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
+       $config{USE_SSL} = "n";
+       $config{MODUPDATE} = 'n';
+
+       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";
+
+               yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
+               if ($config{USE_SSL} eq "y")
+               {
+                       if ($config{HAS_GNUTLS} eq "y")
+                       {
+                               yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
+                               if ($config{USE_GNUTLS} eq "y")
+                               {
+                                       print "\nUsing GnuTLS SSL module.\n";
+                               }
+                       }
+
+                       if ($config{HAS_OPENSSL} eq "y")
+                       {
+                               yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
+                               if ($config{USE_OPENSSL} eq "y")
+                               {
+                                       print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
+                               }
+                       }
                }
        }
                }
        }
+       else
+       {
+               print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed and\n";
+               print "is in your path.\n\n";
+       }
 
 
-       print "\nThe following questions will ask you for various figures relating\n";
-       print "To your IRCd install. Please note that these should usually be left\n";
-       print "as defaults unless you have a real reason to change them. If they\n";
-       print "changed, then the values must be identical on all servers on your\n";
-       print "network, or malfunctions and/or crashes may occur, with the exception\n";
-       print "of the 'maximum number of clients' setting which may be different on\n";
-       print "different servers on the network.\n\n";
-
-       # File Descriptor Settings..
-       promptnumeric("number of clients at any one time", "MAX_CLIENT_T");
-       $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
-       $config{MAX_DESCRIPTORS} = $config{MAX_CLIENT_T};
-
-       promptnumeric("length of nicknames", "NICK_LENGT");
-       promptnumeric("length of channel names", "CHAN_LENGT");
-       promptnumeric("number of channels a normal user may join at any one time", "MAX_CHANNE");
-       promptnumeric("number of channels an oper may join at any one time", "MAX_OPERCH");
-       promptnumeric("number of mode changes in one line", "MAXI_MODES");
-       promptnumeric("length of an ident (username)", "MAX_IDENT");
-       promptnumeric("length of a quit message", "MAX_QUIT");
-       promptnumeric("length of a channel topic", "MAX_TOPIC");
-       promptnumeric("length of a kick message", "MAX_KICK");
-       promptnumeric("length of a GECOS (real name)", "MAX_GECOS");
-       promptnumeric("length of an away message", "MAX_AWAY");
+       yesno('MODUPDATE',"Would you like to check for updates to third-party modules?");
+       print "\n";
+       if ($config{MODUPDATE} eq "y") {
+               print "Checking for upgrades to extra and third party modules... ";
+               system "./modulemanager upgrade";
+       }
 }
 
 }
 
+# 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";
+
 dumphash();
 
 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
 dumphash();
 
 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
@@ -642,80 +671,66 @@ if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
        print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
        exit(0);
 }
        print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
        exit(0);
 }
+our $failed = 0;
+
+$config{CERTGEN} ||= 'y';
+yesno('CERTGEN',"Would you like generate SSL certificates now?") if ($interactive && ($config{USE_GNUTLS} eq "y" || $config{USE_OPENSSL} eq "y"));
 
 if ($config{USE_GNUTLS} eq "y") {
 
 if ($config{USE_GNUTLS} eq "y") {
-       $failed = 0;
-       open(TMP, "<src/modules/m_ssl_gnutls.cpp") or $failed = 1;
-       close(TMP);
-       if ($failed) {
+       unless (-r "src/modules/m_ssl_gnutls.cpp") {
                print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
                print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
-               chdir("src/modules");
-               system("ln -s extra/m_ssl_gnutls.cpp");
-               system("ln -s extra/ssl_cert.h");
-               chdir("../..");
+               symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
        }
        }
-       getmodules();
-       if ($interactive)
+       if ($interactive && $config{CERTGEN} eq 'y')
        {
        {
-               $failed = 0;
-               open(TMP, "<$config{CONFIG_DIR}/key.pem") or $failed = 1;
-               close(TMP);
-               open(TMP, "<$config{CONFIG_DIR}/cert.pem") or $failed = 1;
-               close(TMP);
-               if ($failed) {
+               unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
                        print "SSL Certificates Not found, Generating.. \n\n
 *************************************************************
 * Generating the Private Key may take some time, go grab a  *
 * Coffee. Even better, to generate some more entropy if it  *
 * is taking a while, open another console and type du / a   *
                        print "SSL Certificates Not found, Generating.. \n\n
 *************************************************************
 * Generating the Private Key may take some time, go grab a  *
 * Coffee. Even better, to generate some more entropy if it  *
 * is taking a while, open another console and type du / a   *
-* few times and get that HD going :) Then answer the   *
+* few times and get that HD going :) Then answer the        *
 * Questions which follow. If you are unsure, just hit enter *
 *************************************************************\n\n";
 * Questions which follow. If you are unsure, just hit enter *
 *************************************************************\n\n";
-                       system("certtool --generate-privkey --outfile key.pem");
-                       system("certtool --generate-self-signed --load-privkey key.pem --outfile cert.pem");
-                       print "\nCertificate generation complete, copying to config directory... ";
-                       system("mv key.pem $config{CONFIG_DIR}/key.pem");
-                       system("mv cert.pem $config{CONFIG_DIR}/cert.pem");
-                       print "Done.\n\n";
-               } else {
-                       print "SSL Certificates found, skipping.\n\n"
+                       $failed = make_gnutls_cert();
+                       if ($failed) {
+                               print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
+                       } else {
+                               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";
+                               print "Done.\n\n";
+                       }
+               }
+               else {
+                       print "SSL Certificates found, skipping.\n\n";
                }
        }
        else
        {
                print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
        }
                }
        }
        else
        {
                print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
        }
-} elsif ($config{USE_OPENSSL} eq "y") {
-       $failed = 0;
-       open(TMP, "<src/modules/m_ssl_openssl.cpp") or $failed = 1;
-       close(TMP);
-       if ($failed) {
+}
+
+if ($config{USE_OPENSSL} eq "y") {
+       unless (-r "src/modules/m_ssl_openssl.cpp") {
                print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
                print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
-               chdir("src/modules");
-               system("ln -s extra/m_ssl_openssl.cpp");
-               system("ln -s extra/ssl_cert.h");
-               chdir("../..");
+               symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
        }
        }
-       getmodules();
        $failed = 0;
        $failed = 0;
-       if ($interactive)
+       if ($interactive && $config{CERTGEN} eq 'y')
        {
        {
-               open(TMP, "<$config{CONFIG_DIR}/key.pem") or $failed = 1;
-               close(TMP);
-               open(TMP, "<$config{CONFIG_DIR}/cert.pem") or $failed = 1;
-               close(TMP);
-               if ($failed) {
+               unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
                        print "SSL Certificates Not found, Generating.. \n\n
 *************************************************************
 * Generating the certificates may take some time, go grab a *
                        print "SSL Certificates Not found, Generating.. \n\n
 *************************************************************
 * Generating the certificates may take some time, go grab a *
-* coffee, or something.                                     *
+* coffee, or something.                                            *
 *************************************************************\n\n";
 *************************************************************\n\n";
-                       system("openssl req -x509 -nodes -newkey rsa:1024 -keyout key.pem -out cert.pem");
-                       system("openssl dhparam -out dhparams.pem 1024");
+                       make_openssl_cert();
                        print "\nCertificate generation complete, copying to config directory... ";
                        print "\nCertificate generation complete, copying to config directory... ";
-                       system("mv key.pem $config{CONFIG_DIR}/key.pem");
-                       system("mv cert.pem $config{CONFIG_DIR}/cert.pem");
-                       system("mv dhparams.pem $config{CONFIG_DIR}/dhparams.pem");
+                       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"
                        print "Done.\n\n";
                } else {
                        print "SSL Certificates found, skipping.\n\n"
@@ -730,26 +745,26 @@ if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
        print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
 }
 
        print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
 }
 
-getosflags();
+depcheck();
 writefiles(1);
 makecache();
 
 print "\n\n";
 writefiles(1);
 makecache();
 
 print "\n\n";
-print "To build your server with these settings, please type '\033[1;32m$config{MAKEPROG}\033[0m' now.\n";
+print "To build your server with these settings, please run '\e[1;32mmake\e[0m' now.\n";
 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
-       print "Please remember that to enable \033[1;32mSSL support\033[0m you must\n";
-       print "load the required modules in your config. This configure process\n";
-       print "has just prepared these modules to be compiled for you, and has not\n";
-       print "configured them to be compiled into the core of the ircd.\n";
+       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 "*** \033[1;32mRemember to edit your configuration files!!!\033[0m ***\n\n\n";
+print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
-       print "\033[1;32mWARNING!\033[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";
+       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";
 }
 
 if ($config{GCCVER} < "3") {
        print <<FOO2;
 }
 
 if ($config{GCCVER} < "3") {
        print <<FOO2;
-\033[1;32mWARNING!\033[0m You are attempting to compile InspIRCd on GCC 2.x!
+\e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
 GCC 2.x series compilers only had partial (read as broken) C++ support, and
 your compile will most likely fail horribly! If you have any problems, do NOT
 report them to the bugtracker or forums without first upgrading your compiler
 GCC 2.x series compilers only had partial (read as broken) C++ support, and
 your compile will most likely fail horribly! If you have any problems, do NOT
 report them to the bugtracker or forums without first upgrading your compiler
@@ -762,7 +777,7 @@ FOO2
 ################################################################################
 sub getcache {
        # Retrieves the .config.cache file, and loads values into the main config hash.
 ################################################################################
 sub getcache {
        # Retrieves the .config.cache file, and loads values into the main config hash.
-       open(CACHE, ".config.cache") or return undef;
+       open(CACHE, ".config.cache") or return 0;
        while (<CACHE>) {
                chomp;
                # Ignore Blank lines, and comments..
        while (<CACHE>) {
                chomp;
                # Ignore Blank lines, and comments..
@@ -773,15 +788,15 @@ sub getcache {
                # Do something with data here!
                $config{$key} = $1;
        }
                # Do something with data here!
                $config{$key} = $1;
        }
-       close(CONFIG);
-       return "true";
+       close(CACHE);
+       return 1;
 }
 
 sub makecache {
        # Dump the contents of %config
 }
 
 sub makecache {
        # Dump the contents of %config
-       print "Writing \033[1;32mcache file\033[0m for future ./configures ...\n";
+       print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
        open(FILEHANDLE, ">.config.cache");
        open(FILEHANDLE, ">.config.cache");
-       foreach $key (keys %config) {
+       foreach my $key (keys %config) {
                print FILEHANDLE "$key=\"$config{$key}\"\n";
        }
        close(FILEHANDLE);
                print FILEHANDLE "$key=\"$config{$key}\"\n";
        }
        close(FILEHANDLE);
@@ -792,8 +807,8 @@ sub dir_check {
        my $complete = 0;
        while (!$complete) {
                print "In what directory $desc?\n";
        my $complete = 0;
        while (!$complete) {
                print "In what directory $desc?\n";
-               print "[\033[1;32m$config{$hash_key}\033[0m] -> ";
-               chomp($var = <STDIN>);
+               print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
+               chomp(my $var = <STDIN>);
                if ($var eq "") {
                        $var = $config{$hash_key};
                }
                if ($var eq "") {
                        $var = $config{$hash_key};
                }
@@ -806,17 +821,19 @@ sub dir_check {
                        # Assume relative Path was given.. fill in the rest.
                        $var = $this . "/$var";
                }
                        # Assume relative Path was given.. fill in the rest.
                        $var = $this . "/$var";
                }
-               
-               $var = resolve_directory($var); 
+
+               $var = resolve_directory($var);
                if (! -e $var) {
                if (! -e $var) {
-                       print "$var does not exist. Create it?\n[\033[1;32my\033[0m] ";
-                       chomp($tmp = <STDIN>);
+                       print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
+                       chomp(my $tmp = <STDIN>);
                        if (($tmp eq "") || ($tmp =~ /^y/i)) {
                                # Attempt to Create the Dir..
                        if (($tmp eq "") || ($tmp =~ /^y/i)) {
                                # Attempt to Create the Dir..
-                               
-                               system("mkdir -p \"$var\" >> /dev/null 2>&1");
-                               $chk = system("mkdir -p \"$var\" >> /dev/null 2>&1") / 256;
-                               if ($chk != 0) {
+                               my $chk = eval {
+                                       use File::Path ();
+                                       File::Path::mkpath($var, 0, 0777);
+                                       1;
+                               };
+                               unless (defined($chk) && -d $var) {
                                        print "Unable to create directory. ($var)\n\n";
                                        # Restart Loop..
                                        next;
                                        print "Unable to create directory. ($var)\n\n";
                                        # Restart Loop..
                                        next;
@@ -840,767 +857,406 @@ sub dir_check {
        }
 }
 
        }
 }
 
-sub getosflags {
-
-       $config{LDLIBS} = "-lstdc++";
-       $config{FLAGS}  = "-fno-strict-aliasing -fPIC -Wall -Woverloaded-virtual $config{OPTIMISATI}";
-       $config{DEVELOPER} = "-fno-strict-aliasing -fPIC -Wall -Woverloaded-virtual -g";
-       $config{MAKEPROG} = "make";
-
-       if ($config{OSNAME} =~ /OpenBSD/i) {
-               $config{MAKEPROG} = "gmake";
-               chomp($foo = `eg++ -dumpversion | cut -c 1`);
-               # theyre running the package version of gcc (eg++)... detect it and set up its version numbers.
-               # if theyre not running this, configure lets the build continue but they probably wont manage to
-               # compile as this standard version is 2.95.3!
-               if ($foo ne "") {
-                       $config{CC} = "eg++";
-                       chomp($config{GCCVER}       = `eg++ -dumpversion | cut -c 1`); # we must redo these if we change the compiler path
-               }
-               return "OpenBSD";
-       }
-
-       if ($config{OSNAME} =~ /Linux/i) {
-               $config{LDLIBS} = "-ldl -lstdc++";
-               $config{FLAGS}  = "-fno-strict-aliasing -fPIC -Wall -Woverloaded-virtual $config{OPTIMISATI}";
-               $config{FLAGS}  .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
-               $config{MAKEPROG} = "make";
-               if ($config{OSNAME} =~ /CYGWIN/) {
-                       $config{FLAGS}  = "-fno-strict-aliasing -Wall -Woverloaded-virtual $config{OPTIMISATI}";
-                       $config{LDLIBS} = "";
-                       $config{MAKEPROG} = "/usr/bin/make";
-                       $config{MAKEORDER} = "ircd mods";
-                       return "Cygwin";
-               } elsif ($config{OSNAME} eq "CYG-STATIC") {
-                       $config{FLAGS} = "-fno-strict-aliasing -Wall -Woverloaded-virtual $config{OPTIMISATI}";
-                       $config{LDLIBS} = "";
-                       $config{MAKEPROG} = "/usr/bin/make";
-                       $config{MAKEORDER} = "mods ircd";
-                       $config{STATICLIBS} = "modules/mods.a";
-                       $config{STATIC_LINK} = "yes";
-                       return "Cygwin-Static";
-               }
-               $config{FLAGS}  .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
-       }
-       
-       if ($config{OSNAME} =~ /SunOS/i)
-       {
-               # solaris/sunos needs these
-               # socket = bsd sockets api
-               # nsl = dns stuff
-               # rt = POSIX realtime extensions
-               # resolv = inet_aton only (why isnt this in nsl?!)
-               $config{MAKEPROG} = "gmake";
-               $config{LDLIBS} = $config{LDLIBS} . " -lsocket -lnsl -lrt -lresolv";
-               return "Solaris";
-       }
-       
-       if($config{OSNAME} =~ /MINGW32/i)
-       {
-               # All code is position-independent on windows
-               $config{FLAGS} =~ s/-fPIC //;
-               return "MinGW";
-       }
+our $SHARED = "";
 
 
-       return $config{OSNAME};
-}
+my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
 
 sub writefiles {
        my($writeheader) = @_;
        # First File.. inspircd_config.h
        chomp(my $incos = `uname -n -s -r`);
 
 sub writefiles {
        my($writeheader) = @_;
        # First File.. inspircd_config.h
        chomp(my $incos = `uname -n -s -r`);
-       chomp(my $version = `sh ./src/version.sh`);
-       chomp(my $revision = getrevision());
-       $version = "$version(r$revision)";
+       chomp(my $version = `sh src/version.sh`);
        chomp(my $revision2 = getrevision());
        chomp(my $revision2 = getrevision());
+       my $branch = "InspIRCd-0.0";
+       if ($version =~ /^(InspIRCd-[0-9]+\.[0-9]+)\.[0-9]+/)
+       {
+               $branch = $1;
+       }
        if ($writeheader == 1)
        {
        if ($writeheader == 1)
        {
-               print "Writing \033[1;32minspircd_config.h\033[0m\n";
-               open(FILEHANDLE, ">include/inspircd_config.h");
-               my $NL = $config{NICK_LENGT}+1;
-               my $CL = $config{CHAN_LENGT}+1;
+               print "Writing \e[1;32minspircd_config.h\e[0m\n";
+               open(FILEHANDLE, ">include/inspircd_config.h.tmp");
                print FILEHANDLE <<EOF;
 /* Auto generated by configure, do not modify! */
 #ifndef __CONFIGURATION_AUTO__
 #define __CONFIGURATION_AUTO__
 
                print FILEHANDLE <<EOF;
 /* Auto generated by configure, do not modify! */
 #ifndef __CONFIGURATION_AUTO__
 #define __CONFIGURATION_AUTO__
 
-#define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
+/* this is for windows support. */
+#define CoreExport /**/
+#define DllExport /**/
+
+#define CONFIG_PATH "$config{CONFIG_DIR}"
+#define DATA_PATH "$config{DATA_DIR}"
+#define LOG_PATH "$config{LOG_DIR}"
 #define MOD_PATH "$config{MODULE_DIR}"
 #define MOD_PATH "$config{MODULE_DIR}"
-#define VERSION "$version"
-#define REVISION "$revision2"
-#define MAXCLIENTS $config{MAX_CLIENT}
-#define MAXCLIENTS_S "$config{MAX_CLIENT}"
 #define SOMAXCONN_S "$config{_SOMAXCONN}"
 #define SOMAXCONN_S "$config{_SOMAXCONN}"
-#define MAX_DESCRIPTORS $config{MAX_DESCRIPTORS}
-#define NICKMAX $NL
-#define CHANMAX $CL
-#define MAXCHANS $config{MAX_CHANNE}
-#define OPERMAXCHANS $config{MAX_OPERCH}
-#define MAXMODES $config{MAXI_MODES}
-#define IDENTMAX $config{MAX_IDENT}
-#define MAXQUIT $config{MAX_QUIT}
-#define MAXTOPIC $config{MAX_TOPIC}
-#define MAXKICK $config{MAX_KICK}
-#define MAXGECOS $config{MAX_GECOS}
-#define MAXAWAY $config{MAX_AWAY}
-#define OPTIMISATION $config{OPTIMITEMP}
-#define LIBRARYDIR "$config{LIBRARY_DIR}"
-#define SYSTEM "$incos"
-#define MAXBUF 514
+#define ENTRYPOINT int main(int argc, char** argv)
+
 EOF
 EOF
+print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
+
                if ($config{OSNAME} =~ /SunOS/i) {
                        print FILEHANDLE "#define IS_SOLARIS\n";
                }
                if ($config{OSNAME} =~ /SunOS/i) {
                        print FILEHANDLE "#define IS_SOLARIS\n";
                }
-               if ($config{OSNAME} =~ /CYGWIN/i) {
-                       print FILEHANDLE "#define IS_CYGWIN\n";
-                       print FILEHANDLE "#ifndef FD_SETSIZE\n#define FD_SETSIZE        1024\n#endif\n";
-               }
                if ($config{OSNAME} =~ /MINGW32/i) {
                        print FILEHANDLE "#define IS_MINGW\n";
                }
                if ($config{OSNAME} =~ /MINGW32/i) {
                        print FILEHANDLE "#define IS_MINGW\n";
                }
-               if ($config{OSNAME} =~ /CYG-STATIC/i) {
-                       print FILEHANDLE "#ifndef FD_SETSIZE\n#define FD_SETSIZE    1024\n#endif\n";
-               }
-               if ($config{STATIC_LINK} eq "yes") {
-                       print FILEHANDLE "#define STATIC_LINK\n";
-               }
                if ($config{GCCVER} >= 3) {
                        print FILEHANDLE "#define GCC3\n";
                }
                if ($config{GCCVER} >= 3) {
                        print FILEHANDLE "#define GCC3\n";
                }
+               if (
+                       (($config{GCCVER} == 4) && ($config{GCCMINOR} >= 3))
+                               ||
+                       ($config{GCCVER} > 4)
+                               || # HACK: temporary fix for non-GCC (i.e. clang) builds
+                       ($config{CC} !~ /gcc/)
+               ) {
+                       print FILEHANDLE "#define HASHMAP_DEPRECATED\n";
+               }
                if ($config{HAS_STRLCPY} eq "true") {
                        print FILEHANDLE "#define HAS_STRLCPY\n";
                }
                if ($config{HAS_STDINT} eq "true") {
                        print FILEHANDLE "#define HAS_STDINT\n";
                }
                if ($config{HAS_STRLCPY} eq "true") {
                        print FILEHANDLE "#define HAS_STRLCPY\n";
                }
                if ($config{HAS_STDINT} eq "true") {
                        print FILEHANDLE "#define HAS_STDINT\n";
                }
-               if ($config{IPV6} =~ /y/i) {
-                       print FILEHANDLE "#define IPV6\n";
+               if ($config{HAS_EVENTFD} eq 'true') {
+                       print FILEHANDLE "#define HAS_EVENTFD\n";
                }
                }
-               if ($config{SUPPORT_IP6LINKS} =~ /y/i) {
-                       print FILEHANDLE "#define SUPPORT_IP6LINKS\n";
+               if ($config{OSNAME} !~ /DARWIN/i) {
+                       print FILEHANDLE "#define HAS_CLOCK_GETTIME\n";
                }
                my $use_hiperf = 0;
                if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
                        print FILEHANDLE "#define USE_KQUEUE\n";
                }
                my $use_hiperf = 0;
                if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
                        print FILEHANDLE "#define USE_KQUEUE\n";
-                       $se = "socketengine_kqueue";
+                       $config{SOCKETENGINE} = "socketengine_kqueue";
                        $use_hiperf = 1;
                }
                if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
                        print FILEHANDLE "#define USE_EPOLL\n";
                        $use_hiperf = 1;
                }
                if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
                        print FILEHANDLE "#define USE_EPOLL\n";
-                       $se = "socketengine_epoll";
+                       $config{SOCKETENGINE} = "socketengine_epoll";
+                       $use_hiperf = 1;
+               }
+               if (($has_ports) && ($config{USE_PORTS} eq "y")) {
+                       print FILEHANDLE "#define USE_PORTS\n";
+                       $config{SOCKETENGINE} = "socketengine_ports";
                        $use_hiperf = 1;
                }
                # user didn't choose either epoll or select for their OS.
                # default them to USE_SELECT (ewwy puke puke)
                if (!$use_hiperf) {
                        $use_hiperf = 1;
                }
                # user didn't choose either epoll or select for their OS.
                # default them to USE_SELECT (ewwy puke puke)
                if (!$use_hiperf) {
-                       print FILEHANDLE "#define USE_SELECT\n";
-                       $se = "socketengine_select";
+                       print "no hi-perf, " . $config{USE_POLL};
+                       if ($config{USE_POLL} eq "y")
+                       {
+                               print FILEHANDLE "#define USE_POLL\n";
+                               $config{SOCKETENGINE} = "socketengine_poll";
+                       }
+                       else
+                       {
+                               print FILEHANDLE "#define USE_SELECT\n";
+                               $config{SOCKETENGINE} = "socketengine_select";
+                       }
                }
                }
-               print FILEHANDLE "\n#endif\n";
+               print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
                close(FILEHANDLE);
                close(FILEHANDLE);
-       }
 
 
-       if ($writeheader)
-       {
-               open(FILEHANDLE, ">include/inspircd_se_config.h");
+               open(FILEHANDLE, ">include/inspircd_version.h.tmp");
                print FILEHANDLE <<EOF;
                print FILEHANDLE <<EOF;
-/* Auto generated by configure, do not modify or commit to svn! */
-#ifndef __CONFIGURATION_SOCKETENGINE__
-#define __CONFIGURATION_SOCKETENGINE__
-
-#include "$se.h"
-
-#endif
+#define BRANCH "$branch"
+#define VERSION "$version"
+#define REVISION "$revision2"
+#define SYSTEM "$incos"
 EOF
 EOF
-               close(FILEHANDLE);
-       }
-
-
-       # Create a Modules List..
-       my $modules = "";
-       foreach $i (@modlist)
-       {
-               if ($config{STATIC_LINK} eq "yes") {
-                       $modules .= "m_".$i.".o ";
-               }
-               else {
-                       $modules .= "m_".$i.".so ";
-               }
-       }
-       chomp($modules);   # Remove Redundant whitespace..
-
-       opendir(DIRHANDLE, "src/modules");
-       foreach $name (sort readdir(DIRHANDLE)) {
-               if ($name =~ /^m_(.+?)$/) {
-                       if (opendir(MDIRHANDLE, "src/modules/$name") != 0) {
-                               closedir(MDIRHANDLE);
-                               $modules .= "$name.so ";
+               close FILEHANDLE;
+
+               for my $file (qw(include/inspircd_config.h include/inspircd_version.h)) {
+                       my $diff = 0;
+                       open my $fh1, $file or $diff = 1;
+                       open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
+                       while (!$diff) {
+                               my $line1 = <$fh1>;
+                               my $line2 = <$fh2>;
+                               if (defined($line1) != defined($line2)) {
+                                       $diff = 1;
+                               } elsif (!defined $line1) {
+                                       last;
+                               } else {
+                                       $diff = ($line1 ne $line2);
+                               }
+                       }
+                       if ($diff) {
+                               unlink $file;
+                               rename "$file.tmp", $file;
+                       } else {
+                               unlink "$file.tmp";
                        }
                }
        }
                        }
                }
        }
-       closedir(DIRHANDLE);
-
 
        # Write all .in files.
        my $tmp = "";
        my $file = "";
        my $exe = "inspircd";
 
 
        # Write all .in files.
        my $tmp = "";
        my $file = "";
        my $exe = "inspircd";
 
-       if ($config{OSNAME} =~ /CYGWIN/i) {
-               $exe = "inspircd.exe";
-       }
-
-       opendir(DIRHANDLE, $this);
-
        # 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.
        # Fix for bug#177 by Brain.
 
        # 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.
        # Fix for bug#177 by Brain.
 
-       chomp(my $version = `sh ./src/version.sh`);
+       chomp($version = `sh ./src/version.sh`);
        chomp(my $revision = getrevision());
        $version = "$version(r$revision)";
 
        # We can actually parse any file starting with . and ending with .inc,
        # but right now we only parse .inspircd.inc to form './inspircd'
        chomp(my $revision = getrevision());
        $version = "$version(r$revision)";
 
        # We can actually parse any file starting with . and ending with .inc,
        # but right now we only parse .inspircd.inc to form './inspircd'
+       prepare_dynamic_makefile();
 
 
-       foreach $name (sort readdir(DIRHANDLE)) {
-               if ($name =~ /^\.(.+)\.inc$/) {
-                       $file = $1;
-                       # All .name.inc files need parsing!
-                       $tmp = "";
-                       open(FILEHANDLE, ".$file.inc");
-                       while (<FILEHANDLE>) {
-                               $tmp .= $_;
-                       }
-                       close(FILEHANDLE);
-
-                       $tmp =~ s/\@CC\@/$config{CC}/;
-                       $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/;
-                       $tmp =~ s/\@FLAGS\@/$config{FLAGS}/;
-                       $tmp =~ s/\@DEVELOPER\@/$config{DEVELOPER}/;
-                       $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/;
-                       $tmp =~ s/\@BASE_DIR\@/$config{BASE_DIR}/;
-                       $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/;
-                       $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/;
-                       $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/;
-                       $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/;
-                       $tmp =~ s/\@MODULES\@/$modules/;
-                       $tmp =~ s/\@EXECUTABLE\@/$exe/;
-                       $tmp =~ s/\@MAKEORDER\@/$config{MAKEORDER}/;
-                       $tmp =~ s/\@STATICLIBS\@/$config{STATICLIBS}/;
-                       $tmp =~ s/\@VERSION\@/$version/;
-
-                       print "Writing \033[1;32m$file\033[0m\n";
-                       open(FILEHANDLE, ">$file");
-                       print FILEHANDLE $tmp;
-               }
-       }
-       closedir(DIRHANDLE);
-
-       # Make inspircd executable!
-       chmod 0744, 'inspircd';
-
-       if ($config{STATIC_LINK} eq "yes") {
-               print "Writing static-build \033[1;32msrc/Makefile\033[0m\n";
-               write_static_makefile();
-               write_static_modules_makefile();
-       } elsif ($config{OSNAME} =~ /CYGWIN/i) {
-               print "Writing cygwin-build \033[1;32msrc/Makefile\033[0m\n";
-               write_static_makefile();
-               write_dynamic_modules_makefile();
-       } else {
-               print "Writing dynamic-build \033[1;32msrc/Makefile\033[0m\n";
-               write_dynamic_makefile();
-               write_dynamic_modules_makefile();
-       }
-}
+       my @dotfiles = qw(main.mk inspircd);
+       push @dotfiles, 'org.inspircd.plist' if $config{OSNAME} eq 'darwin';
 
 
-sub write_static_modules_makefile {
-       # Modules Makefile..
-       print "Writing \033[1;32msrc/modules/Makefile\033[0m\n";
-       open(FILEHANDLE, ">src/modules/Makefile");
-
-       ###
-       # Module Makefile Header
-       ###
-       print FILEHANDLE <<EOF;
-# (C) ChatSpike development team
-# Makefile by <Craig\@ChatSpike.net>
-# Many Thanks to Andrew Church <achurch\@achurch.org>
-#    for assisting with making this work right.
-#
-# Automatically Generated by ./configure to add a modules
-# please run ./configure --update
+       foreach my $file (@dotfiles) {
+               open(FILEHANDLE, "make/template/$file") or die "Can't open make/template/$file: $!";
+               $_ = join '', <FILEHANDLE>;
+               close(FILEHANDLE);
 
 
-all: \$(MODULES)
+               $config{BUILD_DIR} ||= resolve_directory($config{ME}."/build");
 
 
-EOF
-       ###
-       # End Module Makefile Header
-       ###
-
-       # Create a Modules List..
-       my $modules = "";
-       my $cmflags = "";
-       my $liflags = "";
-
-       open(MODLIST,">include/modlist.h");
-
-       ###
-       # Include File Header
-       ###
-       print MODLIST <<HEADER;
-// Generated automatically by configure. DO NOT EDIT!
-
-#ifndef __SYMBOLS__H_CONFIGURED__
-#define __SYMBOLS__H_CONFIGURED__
-
-HEADER
-       ###
-       # End Include File Header
-       ###
-
-       # Place Module List into Include
-       foreach $i (@modlist) {
-               if ($i !~ /_static$/) {
-                       print MODLIST "extern \"C\" void * $i\_init (void);\n";
+               for my $var (qw(
+                       CC SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR DATA_DIR UID
+                       STARTSCRIPT DESTINATION SOCKETENGINE
+               )) {
+                       s/\@$var\@/$config{$var}/g;
                }
                }
-       }
-       print MODLIST "\nstruct {const char *name; initfunc *value; } modsyms[] = {\n";
-
-       ###
-       # Build Module Crap
-       ###
-       foreach $i (@modlist)
-       {
-               if ($i !~ /_static$/) {
-                       $cmflags = getcompilerflags("src/modules/m_".$i.".cpp");
-                       $liflags = getlinkerflags("src/modules/m_".$i.".cpp");
-                       $deps = getdependencies("src/modules/m_".$i.".cpp");
-
-                       #print "file: $i: cmflags=$cmflags; liflags=$liflags; deps=$deps\n";
-
-                       ###
-                       # Write Entry to the Makefile
-                       ###
-                       print FILEHANDLE <<EOCHEESE;
-m_$i.o: .m_$i\_static.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/base.h $deps
-       \$(CC) -pipe -I../../include \$(FLAGS) $flags -export-dynamic -c .m_$i\_static.cpp
-       mv .m_$i\_static.o ../m_$i.o
-
-EOCHEESE
-                       ###
-                       # End Write Entry to the MakeFile
-                       ###
-                       print "Configuring module [\033[1;32mm_$i.so\033[0m] for static linking... ";
-                       open(MODULE,"<src/modules/m_".$i.".cpp") or die("Could not open m_".$i.".cpp");
-                       open(MUNGED,">src/modules/.m_".$i."_static.cpp") or die("Could not create .m_".$i."_static.cpp");
-                       while (chomp($a = <MODULE>)) { 
-                               $a =~ s/init_module/$i\_init/g;
-                               print MUNGED "$a\n";
-                       }
-                       close(MODULE);
-                       close(MUNGED);
-                       print MODLIST <<EOENT;
-{"m_$i.so",\&$i\_init},
-EOENT
-                       print "done\n";
+               s/\@EXECUTABLE\@/$exe/ if defined $exe;
+               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/\@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/\@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);
                }
        }
 
                }
        }
 
-       print MODLIST "{0}};\n\n#endif\n";
-       close(MODLIST);
+       chmod 0755, 'inspircd';
 }
 
 }
 
-sub write_dynamic_modules_makefile {
-       # Modules Makefile..
-       print "Writing \033[1;32msrc/modules/Makefile\033[0m\n";
-       open(FILEHANDLE, ">src/modules/Makefile");
-       my $extra = "";
-
-       if ($config{OSNAME} =~ /CYGWIN/i) {
-               $extra = "../inspircd.dll.a";
+sub depcheck
+{
+       getmodules();
+       for my $mod (@modlist) {
+               getcompilerflags("src/modules/m_$mod.cpp");
+               getlinkerflags("src/modules/m_$mod.cpp");
        }
        }
+}
 
 
-###
-# Module Makefile Header
-###
-       print FILEHANDLE <<EOF;
-# (C) ChatSpike development team
-# Makefile by <Craig\@ChatSpike.net>
-# Many Thanks to Andrew Church <achurch\@achurch.org>
-#    for assisting with making this work right.
-#
-# Automatically Generated by ./configure to add a modules
-# please run ./configure -update or ./configure -modupdate
-
-all: \$(MODULES)
+sub prepare_dynamic_makefile
+{
+       my $i = 0;
 
 
-EOF
-       ###
-       # End Module Makefile Header
-       ###
-
-       # Create a Modules List..
-       my $modules = "";
-       my $cmflags = "";
-       my $liflags = "";
-       my $crud = "";
-
-       foreach $i (@modlist) {
-               ###
-               # Write Entry to the MakeFile
-               ###
-               $cmflags = getcompilerflags("src/modules/m_".$i.".cpp");
-               $liflags = getlinkerflags("src/modules/m_".$i.".cpp");
-               $deps = getdependencies("src/modules/m_".$i.".cpp");
-       
-               #print "file: $i: cmflags=$cmflags; liflags=$liflags; deps=$deps\n";
-       
-               print FILEHANDLE <<EOCHEESE;
-m_$i.so: m_$i.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/base.h ../../include/inspircd_config.h ../../include/inspircd.h ../../include/configreader.h $deps
-       \$(CC) -pipe -I../../include \$(FLAGS) $cmflags -export-dynamic -c m_$i.cpp
-       \$(CC) -pipe \$(FLAGS) -shared $liflags -o m_$i.so m_$i.o $extra
-
-EOCHEESE
-               $crud = $crud . "       install -m \$(INSTMODE) m_$i.so \$(MODPATH)\n";
-###
-               # End Write Entry to the MakeFile
-               ###
+       if (!$has_epoll)
+       {
+               $config{USE_EPOLL} = 0;
+       }
+       if (!$has_kqueue)
+       {
+               $config{USE_KQUEUE} = 0;
+       }
+       if (!$has_ports)
+       {
+               $config{USE_PORTS} = 0;
        }
        }
+}
 
 
-       opendir(DIRHANDLE, "src/modules");
-       foreach $name (sort readdir(DIRHANDLE)) {
-               if ($name =~ /^m_(.+?)$/) {
-                       $crapola = "";
-                       $crap3 = "";
-                       # A module made of multiple files, in a dir, e.g. src/modules/m_spanningtree/
-                       if (opendir(MDIRHANDLE, "src/modules/$name") != 0) {
-                               print "Composing Makefile rules for directory \033[1;32m$name\033[0m... ";
-                               my $i = 0;
-                               print FILEHANDLE "$name.so: ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/base.h ../../include/inspircd_config.h ../../include/inspircd.h ../../include/configreader.h"; 
-                               foreach $fname (sort readdir(MDIRHANDLE)) {
-                                       if ($fname =~ /\.cpp$/) {
-                                               $cmflags = getcompilerflags("src/modules/$name/$fname");
-                                               $liflags = getlinkerflags("src/modules/$name/$fname");
-                                               $deps = getdependencies("src/modules/$name/$fname");
-                                               $oname = $fname;
-                                               $oname =~ s/\.cpp$/.o/g;
-                                               print FILEHANDLE " $name/$oname";
-                                               $crapola = $crapola .  "$name/$oname: $name/$fname ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/base.h ../../include/inspircd_config.h ../../include/inspircd.h ../../include/configreader.h $deps\n";
-                                               $crapola = $crapola .  "        \$(CC) -pipe -I../../include -I. \$(FLAGS) $cmflags -export-dynamic -o $name/$oname -c $name/$fname\n\n";
-                                               $crap3 = $crap3 . " $name/$oname";
-                                               $i++;
-                                       }
+# 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
+# file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
+# (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
+# configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
+sub list_extras () {
+       use File::Spec;
+       # @_ not used
+       my $srcdir = File::Spec->catdir("src", "modules");
+       my $abs_srcdir = File::Spec->rel2abs($srcdir);
+       local $_;
+       my $dd;
+       opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
+       my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
+       closedir $dd;
+       undef $dd;
+       opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
+       my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
+       closedir $dd;
+       undef $dd;
+       my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
+       my %extras = ();
+EXTRA: for my $extra (@extras) {
+               next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
+               my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
+               my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
+               next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
+               if (-l $abs_source) {
+                       # Symlink, is it in the right place?
+                       my $targ = readlink($abs_source);
+                       my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
+                       if ($abs_targ eq $abs_extra) {
+                               $extras{$extra} = "\e[32;1menabled\e[0m";
+                       } else {
+                               $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
+                       }
+               } elsif (-e $abs_source) {
+                       my ($devext, $inoext) = stat($abs_extra);
+                       my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
+                       if ($lnksrc > 1) {
+                               if ($devsrc == $devext && $inosrc == $inoext) {
+                                       $extras{$extra} = "\e[32;1menabled\e[0m";
+                               } else {
+                                       $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
+                               }
+                       } else {
+                               open my $extfd, "<", $abs_extra;
+                               open my $srcfd, "<", $abs_source;
+                               local $/ = undef;
+                               if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
+                                       $extras{$extra} = "\e[32;1menabled\e[0m";
+                               } else {
+                                       $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
                                }
                                }
-                               print "(\033[1;32m$i files found\033[0m)\n";
-                               print FILEHANDLE "\n    \$(CC) -pipe \$(FLAGS) -shared $liflags -o $name.so $crap3\n";
-                               print FILEHANDLE "\n$crapola\n";
-                               closedir(MDIRHANDLE);
-                               $crud = $crud . "       install -m \$(INSTMODE) $name.so \$(MODPATH)\n";
                        }
                        }
+               } else {
+                       $extras{$extra} = "\e[33;1mdisabled\e[0m";
                }
        }
                }
        }
-       closedir(DIRHANDLE);
-
-       print FILEHANDLE "modinst:\n    \@echo \"Installing modules...\"\n" . $crud;
-}
-
-
-sub write_static_makefile {
-       open(FH,">src/Makefile") or die("Could not write src/Makefile!");
-       my $i = 0;
-       my @cmdlist = ();
-       opendir(DIRHANDLE, "src");
-       foreach $name (sort readdir(DIRHANDLE)) {
-               if ($name =~ /^cmd_(.+)\.cpp$/) {
-                       $cmdlist[$i++] = $1;
+       # Now let's add dependency info
+       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 / +/, getdependencies($abs_extra);
+               for my $dep (@deps) {
+                       if (exists($extras{$dep})) {
+                               my $ref = \$extras{$dep}; # Take reference.
+                               if ($$ref !~ m/needed by/) {
+                                       # First dependency found.
+                                       if ($$ref =~ m/enabled/) {
+                                               $$ref .= " (needed by \e[32;1m$extra\e[0m";
+                                       } else {
+                                               $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
+                                               $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
+                                       }
+                               } else {
+                                       if ($$ref =~ m/enabled/) {
+                                               $$ref .= ", \e[32;1m$extra\e[0m";
+                                       } else {
+                                               $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
+                                       }
+                               }
+                       }
                }
        }
                }
        }
-       closedir(DIRHANDLE);
-       my $cmdobjs = "";
-       my $srcobjs = "";
-       foreach my $cmd (@cmdlist) {
-               $cmdobjs = $cmdobjs . "cmd_$cmd.o ";
-               $srcobjs = $srcobjs . "cmd_$cmd.cpp ";
+       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/ ? ")" : "");
+               } else {
+                       printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
+               }
        }
        }
-       print FH <<EOM;
-# Insp Makefile :p
-#
-# (C) ChatSpike development team
-# Makefile by <Craig\@ChatSpike.net>
-# Makefile version 2 (statically linked core) by <brain\@inspircd.org>
-#
-
-CC = im a cheezeball
-
-CXXFLAGS = -I../include \${FLAGS}
-CPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* //' | grep -v svn)
-RELCPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* /modes\\//' | grep -v svn)
-
-EOM
-
-$se = "socketengine_select";
-if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
-       $se = "socketengine_kqueue";
-}       
-elsif (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
-       $se = "socketengine_epoll";
+       return keys(%extras) if wantarray; # Can be used by manage_extras.
 }
 
 }
 
-       ###
-       # This next section is for cygwin dynamic module builds.
-       # Basically, what we do, is build the inspircd core as a library
-       # then the main executable uses that. the library is capable of
-       # loading / unloading the modules dynamically :)
-       # Massive thanks to the guys on #cygwin @ irc.freenode.net for helping
-       # make this work :)
-       ###
-
-       if ($config{OSNAME} =~ /CYGWIN/i) {
-               print FH <<EOM;
-all: timer.o command_parse.o cull_list.o userprocess.o socketengine.o socket.o hashcomp.o channels.o mode.o xline.o inspstring.o dns.o base.o configreader.o inspsocket.o $cmdobjs commands.o dynamic.o users.o modules.o wildcard.o helperfuncs.o snomasks.o inspircd.exe
-
-inspircd.exe: inspircd.dll.a
-       \$(CC) -o \$@ \$^
-
-inspircd.dll inspircd.dll.a: inspircd.o channels.o mode.o xline.o inspstring.o dns.o base.o configreader.o inspsocket.o $cmdobjs  commands.o dynamic.o users.o modules.o wildcard.o helperfuncs.o hashcomp.o socket.o socketengine.o userprocess.o cull_list.o command_parse.o timer.o snomasks.o
-       \$(CC) -shared -Wl,--out-implib=inspircd.dll.a -o inspircd.dll \$^
-EOM
-       } else {
-               print FH <<EOM;
-all: timer.o command_parse.o cull_list.o userprocess.o socketengine.o socket.o hashcomp.o channels.o mode.o xline.o inspstring.o dns.o base.o configreader.o inspsocket.o $cmdobjs commands.o dynamic.o users.o modules.o wildcard.o helperfuncs.o snomasks.o \$(MODULES) inspircd.exe
-
-inspircd.exe: inspircd.cpp ../include/base.h ../include/channels.h ../include/inspircd.h ../include/channels.h ../include/globals.h ../include/inspircd_config.h ../include/base.h
-       \$(CC) -I../include \$(FLAGS) inspircd.cpp -o inspircd.exe \$(LDLIBS) channels.o mode.o xline.o inspstring.o dns.o base.o inspsocket.o configreader.o $cmdobjs commands.o dynamic.o users.o modules.o wildcard.o helperfuncs.o hashcomp.o socket.o socketengine.o userprocess.o cull_list.o command_parse.o timer.o snomasks.o modes/modeclasses.a \$(MODULES)
-EOM
-       }
-
-       print FH <<EOM;
-
-cull_list.o: cull_list.cpp ../include/base.h ../include/hashcomp.h ../include/globals.h ../include/inspircd_config.h ../include/users.h ../include/channels.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c cull_list.cpp
-
-snomasks.o: snomasks.cpp ../include/base.h ../include/hashcomp.h ../include/inspircd.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/channels.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c snomasks.cpp
-
-command_parse.o: command_parse.cpp ../include/base.h ../include/hashcomp.h ../include/inspircd.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c command_parse.cpp
-
-userprocess.o: userprocess.cpp ../include/base.h ../include/hashcomp.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c userprocess.cpp
-
-socketengine.o: $se.cpp socketengine.cpp ../include/base.h ../include/hashcomp.h ../include/globals.h ../include/inspircd_config.h ../include/$se.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c socketengine.cpp $se.cpp
-
-hashcomp.o: hashcomp.cpp ../include/base.h ../include/hashcomp.h ../include/inspircd.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c hashcomp.cpp
-
-helperfuncs.o: helperfuncs.cpp ../include/base.h ../include/inspircd.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c helperfuncs.cpp
-
-channels.o: channels.cpp ../include/base.h ../include/channels.h ../include/inspircd.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c channels.cpp
-
-mode.o: mode.cpp ../include/base.h ../include/mode.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h \$(RELCPPFILES) modes/modeclasses.a
-       \${MAKE} -C "modes" DIRNAME="src/modes" CC="\$(CC)" \$(MAKEARGS)
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c mode.cpp
-
-xline.o: xline.cpp ../include/base.h ../include/xline.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c xline.cpp
-
-inspstring.o: inspstring.cpp ../include/base.h ../include/inspstring.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c inspstring.cpp
-
-dns.o: dns.cpp ../include/base.h ../include/dns.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/timer.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c dns.cpp
-
-base.o: base.cpp ../include/base.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c base.cpp
-
-configreader.o: configreader.cpp ../include/base.h ../include/configreader.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c configreader.cpp
-
-commands.o: commands.cpp ../include/base.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/timer.h $srcobjs
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c commands.cpp $cmdobjs
-
-dynamic.o: dynamic.cpp ../include/base.h ../include/dynamic.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c dynamic.cpp
-
-users.o: users.cpp ../include/base.h ../include/users.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/timer.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c users.cpp
-
-modules.o: modules.cpp ../include/base.h ../include/modules.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/timer.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c modules.cpp
-
-wildcard.o: wildcard.cpp ../include/base.h ../include/wildcard.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c wildcard.cpp
-
-socket.o: socket.cpp ../include/base.h ../include/inspircd.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c socket.cpp
-       
-inspsocket.o: inspsocket.cpp ../include/base.h ../include/inspircd.h ../include/globals.h ../include/inspircd_config.h ../include/timer.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c inspsocket.cpp
-
-timer.o: timer.cpp ../include/base.h ../include/inspircd.h ../include/globals.h ../include/inspircd_config.h ../include/timer.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c timer.cpp
-
-EOM
-       foreach my $cmd (@cmdlist) {
-               print FH <<ITEM;
-cmd_$cmd.o: cmd_$cmd.cpp ../include/base.h ../include/modules.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/commands/cmd_$cmd.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c cmd_$cmd.cpp
-ITEM
+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;
+               }
+               # Get dependencies, and add them to be processed.
+               my @deps = split / +/, getdependencies($extrapath);
+               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") {
+                               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";
+                               }
+                       }
+               }
+               print "Enabling $extra ... \n";
+               symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
        }
        }
-       close(FH);
 }
 
 }
 
-sub write_dynamic_makefile {
-
-       my $i = 0;
-       my @cmdlist = ();
-       opendir(DIRHANDLE, "src");
-       foreach $name (sort readdir(DIRHANDLE)) {
-               if ($name =~ /^cmd_(.+)\.cpp$/) {
-                       $cmdlist[$i++] = $1;
-               }
-       }
-       closedir(DIRHANDLE);
-
-       my $cmdobjs = "";
-       my $srcobjs = "";
-       foreach my $cmd (@cmdlist) {
-               $cmdobjs = $cmdobjs . "cmd_$cmd.so ";
-               $srcobjs = $srcobjs . "cmd_$cmd.cpp ";
-       }
-
-       $se = "socketengine_select";
-       if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
-               $se = "socketengine_kqueue";
-       }
-       elsif (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
-               $se = "socketengine_epoll";
-       }
-
-       open(FH,">src/Makefile") or die("Could not write src/Makefile");
-       print FH <<EOM;
-# Insp Makefile :p
-#
-# (C) ChatSpike development team
-# Makefile by <Craig\@ChatSpike.net>
-# Makefile version 2 (dynamically linked core) by <brain\@inspircd.org>
-#
-
-CC = im a cheezeball
-
-CXXFLAGS = -I../include \${FLAGS}
-CPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* //' | grep -v svn)
-RELCPPFILES = \$(shell /bin/ls -l modes/ | grep '\\.cpp' | sed 's/^.* /modes\\//' | grep -v svn)
-
-all: libIRCDtimer.so libIRCDcull_list.so libIRCDuserprocess.so libIRCDsocketengine.so libIRCDsocket.so libIRCDhash.so libIRCDchannels.so libIRCDmode.so libIRCDxline.so libIRCDstring.so libIRCDasyncdns.so libIRCDbase.so libIRCDconfigreader.so libIRCDinspsocket.so $cmdobjs libIRCDcommands.so libIRCDdynamic.so libIRCDusers.so libIRCDmodules.so libIRCDwildcard.so libIRCDhelper.so libIRCDcommand_parse.so libIRCDsnomasks.so inspircd
-
-inspircd: inspircd.cpp ../include/base.h ../include/channels.h ../include/inspircd.h ../include/channels.h ../include/globals.h ../include/inspircd_config.h ../include/socket.h libIRCDtimer.so libIRCDcull_list.so libIRCDuserprocess.so libIRCDsocketengine.so libIRCDsocket.so libIRCDhash.so libIRCDchannels.so libIRCDmode.so libIRCDxline.so libIRCDstring.so libIRCDasyncdns.so libIRCDbase.so libIRCDconfigreader.so libIRCDinspsocket.so $cmdobjs libIRCDsnomasks.so libIRCDcommands.so libIRCDdynamic.so libIRCDusers.so libIRCDmodules.so libIRCDwildcard.so libIRCDhelper.so libIRCDcommand_parse.so
-       \$(CC) -pipe -I../include $extra -Wl,--rpath -Wl,$config{LIBRARY_DIR} \$(FLAGS) -rdynamic -L. inspircd.cpp -o inspircd \$(LDLIBS) libIRCDchannels.so libIRCDmode.so libIRCDxline.so libIRCDstring.so libIRCDasyncdns.so libIRCDbase.so libIRCDconfigreader.so libIRCDinspsocket.so libIRCDcommands.so libIRCDdynamic.so libIRCDusers.so libIRCDmodules.so libIRCDwildcard.so libIRCDhelper.so libIRCDhash.so libIRCDsocket.so libIRCDsocketengine.so libIRCDuserprocess.so libIRCDcull_list.so libIRCDcommand_parse.so libIRCDtimer.so libIRCDsnomasks.so
-
-libIRCDsocketengine.so: $se.cpp socketengine.cpp ../include/base.h ../include/hashcomp.h ../include/globals.h ../include/inspircd_config.h ../include/$se.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c socketengine.cpp $se.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDsocketengine.so socketengine.o $se.o
-
-libIRCDsnomasks.so: snomasks.cpp ../include/base.h ../include/hashcomp.h ../include/inspircd.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/channels.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c snomasks.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDsnomasks.so snomasks.o
-
-libIRCDcommand_parse.so: command_parse.cpp ../include/base.h ../include/hashcomp.h ../include/inspircd.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c command_parse.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDcommand_parse.so command_parse.o
-
-libIRCDcull_list.so: cull_list.cpp ../include/base.h ../include/hashcomp.h ../include/globals.h ../include/inspircd_config.h ../include/users.h ../include/channels.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c cull_list.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDcull_list.so cull_list.o
-
-libIRCDuserprocess.so: userprocess.cpp ../include/base.h ../include/hashcomp.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c userprocess.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDuserprocess.so userprocess.o
-
-libIRCDhash.so: hashcomp.cpp ../include/base.h ../include/hashcomp.h ../include/inspircd.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c hashcomp.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDhash.so hashcomp.o
-
-libIRCDhelper.so: helperfuncs.cpp ../include/base.h ../include/inspircd.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c helperfuncs.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDhelper.so helperfuncs.o
-
-libIRCDchannels.so: channels.cpp ../include/base.h ../include/channels.h ../include/inspircd.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c channels.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDchannels.so channels.o
-
-libIRCDmode.so: mode.cpp ../include/base.h ../include/mode.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h \$(RELCPPFILES)
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c mode.cpp
-       \${MAKE} -C "modes" DIRNAME="src/modes" CC="\$(CC)" \$(MAKEARGS) CPPFILES="\$(CPPFILES)"
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDmode.so mode.o modes/modeclasses.a
-
-libIRCDxline.so: xline.cpp ../include/base.h ../include/xline.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/timer.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c xline.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDxline.so xline.o
-
-libIRCDstring.so: inspstring.cpp ../include/base.h ../include/inspstring.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c inspstring.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDstring.so inspstring.o
-
-libIRCDasyncdns.so: dns.cpp ../include/base.h ../include/dns.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/timer.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c dns.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDasyncdns.so dns.o
-
-libIRCDbase.so: base.cpp ../include/base.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c base.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDbase.so base.o
-
-libIRCDconfigreader.so: configreader.cpp ../include/base.h ../include/configreader.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c configreader.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDconfigreader.so configreader.o
-
-libIRCDcommands.so: commands.cpp ../include/base.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/timer.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c commands.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDcommands.so commands.o
-
-libIRCDdynamic.so: dynamic.cpp ../include/base.h ../include/dynamic.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c dynamic.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDdynamic.so dynamic.o
-
-libIRCDusers.so: users.cpp ../include/base.h ../include/users.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/timer.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c users.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDusers.so users.o
-
-libIRCDmodules.so: modules.cpp ../include/base.h ../include/modules.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/timer.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c modules.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDmodules.so modules.o
-
-libIRCDwildcard.so: wildcard.cpp ../include/base.h ../include/wildcard.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c wildcard.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDwildcard.so wildcard.o
-
-libIRCDsocket.so: socket.cpp ../include/base.h ../include/inspircd.h ../include/globals.h ../include/inspircd_config.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c socket.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDsocket.so socket.o
-
-libIRCDinspsocket.so: inspsocket.cpp ../include/base.h ../include/inspircd.h ../include/globals.h ../include/inspircd_config.h ../include/timer.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c inspsocket.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDinspsocket.so inspsocket.o
-
-libIRCDtimer.so: timer.cpp ../include/base.h ../include/inspircd.h ../include/globals.h ../include/inspircd_config.h ../include/timer.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c timer.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o libIRCDtimer.so timer.o
-
-EOM
-       foreach my $cmd (@cmdlist) {
-               print FH <<ITEM;
-cmd_$cmd.so: cmd_$cmd.cpp ../include/base.h ../include/modules.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/commands/cmd_$cmd.h
-       \$(CC) -pipe -I../include \$(FLAGS) -export-dynamic -c cmd_$cmd.cpp
-       \$(CC) -pipe -Wl,--rpath -Wl,$config{LIBRARY_DIR} -shared -o cmd_$cmd.so cmd_$cmd.o
-
-ITEM
+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 / +/, getdependencies("src/modules/extra/$file");
+                       # 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;
+                               }
+                       }
+               }
+               # Now remove.
+               print "Disabling $extra ... \n";
+               unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";
        }
        }
-       close(FH);
 }
 }
-