2 ###################################################
3 # InspIRCd Configuration Script
5 # Copyright 2002-2009 The InspIRCd Development Team
6 # http://wiki.inspircd.org/Credits
8 # Licensed under GPL, please see the COPYING file
13 ###################################################
20 use warnings FATAL => qw(all);
24 $Data::Dumper::Sortkeys = 1;
25 $Data::Dumper::Useqq = 1;
33 # Utility functions for our buildsystem
37 use make::opensslcert;
39 ###############################################################################################
41 # NON-EDITABLE VARIABLES
43 ###############################################################################################
45 our ($opt_use_gnutls, $opt_rebuild, $opt_use_openssl, $opt_nointeractive, $opt_ports,
46 $opt_epoll, $opt_kqueue, $opt_noports, $opt_noepoll, $opt_nokqueue,
47 $opt_noipv6, $opt_maxbuf, $opt_disable_debug, $opt_freebsd_port);
49 our ($opt_cc, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir,
54 sub enable_extras (@);
56 sub disable_extras (@);
59 my @opt_disableextras;
62 'enable-gnutls' => \$opt_use_gnutls,
63 'rebuild' => \$opt_rebuild,
64 'enable-openssl' => \$opt_use_openssl,
65 'disable-interactive' => \$opt_nointeractive,
66 'enable-ports' => \$opt_ports,
67 'enable-epoll' => \$opt_epoll,
68 'enable-kqueue' => \$opt_kqueue,
69 'disable-ports' => \$opt_noports,
70 'disable-epoll' => \$opt_noepoll,
71 'disable-kqueue' => \$opt_nokqueue,
72 'disable-ipv6' => \$opt_noipv6,
73 'with-cc=s' => \$opt_cc,
74 'with-maxbuf=i' => \$opt_maxbuf,
75 'enable-freebsd-ports-openssl' => \$opt_freebsd_port,
76 'prefix=s' => \$opt_base_dir,
77 'config-dir=s' => \$opt_config_dir,
78 'module-dir=s' => \$opt_module_dir,
79 'binary-dir=s' => \$opt_binary_dir,
80 'library-dir=s' => \$opt_library_dir,
81 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
82 'help' => sub { showhelp(); },
83 'update' => sub { update(); },
84 'svnupdate' => sub { svnupdate(); },
85 'clean' => sub { clean(); },
86 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
87 'enable-extras=s@' => \@opt_enableextras, # ^
88 'disable-extras=s@' => \@opt_disableextras, # ^
89 'generate-openssl-cert' => sub { make_openssl_cert(); exit(0); },
90 'generate-gnutls-cert' => sub { make_gnutls_cert(); exit(0); }
93 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
94 @opt_enableextras = split /,/, join(',', @opt_enableextras);
95 @opt_disableextras = split /,/, join(',', @opt_disableextras);
96 enable_extras(@opt_enableextras);
97 disable_extras(@opt_disableextras);
99 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
103 our $non_interactive = (
104 (defined $opt_library_dir) ||
105 (defined $opt_base_dir) ||
106 (defined $opt_config_dir) ||
107 (defined $opt_module_dir) ||
108 (defined $opt_base_dir) ||
109 (defined $opt_binary_dir) ||
110 (defined $opt_nointeractive) ||
112 (defined $opt_noipv6) ||
113 (defined $opt_kqueue) ||
114 (defined $opt_epoll) ||
115 (defined $opt_ports) ||
116 (defined $opt_use_openssl) ||
117 (defined $opt_nokqueue) ||
118 (defined $opt_noepoll) ||
119 (defined $opt_noports) ||
120 (defined $opt_maxbuf) ||
121 (defined $opt_use_gnutls) ||
122 (defined $opt_freebsd_port)
124 our $interactive = !$non_interactive;
126 chomp(our $topdir = getcwd());
127 our $this = resolve_directory($topdir); # PWD, Regardless.
128 our @modlist = (); # Declare for Module List..
129 our %config = (); # Initiate Configuration Hash..
130 $config{ME} = resolve_directory($topdir); # Present Working Directory
132 $config{BASE_DIR} = $config{ME};
134 if (defined $opt_base_dir)
136 $config{BASE_DIR} = $opt_base_dir;
139 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
140 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
141 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
142 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
144 if (defined $opt_config_dir)
146 $config{CONFIG_DIR} = $opt_config_dir;
148 if (defined $opt_module_dir)
150 $config{MODULE_DIR} = $opt_module_dir;
152 if (defined $opt_binary_dir)
154 $config{BINARY_DIR} = $opt_binary_dir;
156 chomp($config{HAS_GNUTLS} = `pkg-config --modversion gnutls 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
158 if (defined $opt_freebsd_port)
160 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`);
161 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`);
162 $config{USE_FREEBSD_BASE_SSL} = "n";
166 if ($^O eq "freebsd")
168 # default: use base ssl
169 chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`); # OpenSSL version, freebsd specific
170 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`); # Port version, may be different
174 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version, others
175 $config{HAS_OPENSSL_PORT} = "";
179 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
180 chomp(our $openssl_ver = $config{HAS_OPENSSL});
181 $config{USE_GNUTLS} = "n";
182 if (defined $opt_use_gnutls)
184 $config{USE_GNUTLS} = "y"; # Use gnutls.
186 $config{USE_OPENSSL} = "n"; # Use openssl.
187 if (defined $opt_use_openssl)
189 $config{USE_OPENSSL} = "y";
192 # no, let's not change these.
193 $config{OPTIMITEMP} = "0"; # Default Optimisation Value
194 if (!defined $opt_disable_debug)
196 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
200 $config{OPTIMISATI} = "-O2"; # DEBUGGING OFF!
203 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
204 $config{HAS_STDINT} = "false"; # stdint.h check
205 $config{USE_KQUEUE} = "y"; # kqueue enabled
206 if (defined $opt_kqueue)
208 $config{USE_KQUEUE} = "y";
210 if (defined $opt_nokqueue)
212 $config{USE_KQUEUE} = "n";
214 $config{USE_POLL} = "y"; # poll enabled
215 $config{USE_EPOLL} = "y"; # epoll enabled
216 if (defined $opt_epoll)
218 $config{USE_EPOLL} = "y";
220 if (defined $opt_noepoll)
222 $config{USE_EPOLL} = "n";
224 $config{USE_PORTS} = "y"; # epoll enabled
225 if (defined $opt_ports)
227 $config{USE_PORTS} = "y";
229 if (defined $opt_noports)
231 $config{USE_PORTS} = "n";
233 $config{IPV6} = "y"; # IPv6 support
234 if (defined $opt_noipv6)
238 chomp($config{GCCVER} = `g++ -dumpversion | cut -c 1`); # Major GCC Version
239 chomp($config{GCCMINOR} = `g++ -dumpversion | cut -c 3`);
240 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
241 $config{OSNAME} = $^O; # Operating System Name
242 $config{IS_DARWIN} = "NO"; # Is OSX?
243 $config{STARTSCRIPT} = "inspircd"; # start script?
244 $config{DESTINATION} = "BASE"; # Is target path.
245 $config{EXTRA_DIR} = ""; # Is empty.
246 if ($config{OSNAME} =~ /darwin/i)
248 $config{IS_DARWIN} = "YES";
249 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
250 $config{DESTINATION} = "LAUNCHDPATH"; # Is OSX target.
251 $config{EXTRA_DIR} = " launchd_dir"; # Is OSX specific path.
253 $config{CC} = "g++"; # C++ compiler
256 $config{CC} = $opt_cc;
258 our $exec = $config{CC} . " -dumpversion | cut -c 1";
259 chomp($config{GCCVER} = `$exec`); # Major GCC Version
260 $exec = $config{CC} . " -dumpversion | cut -c 3";
261 chomp($config{GCCMINOR} = `$exec`);
262 $config{MAXBUF} = "512"; # Max buffer size
264 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/) {
265 $config{HAS_OPENSSL} = $1;
267 $config{HAS_OPENSSL} = "";
270 if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
271 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
275 # Get and Set some important vars..
280 unlink(".config.cache");
283 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
288 chomp($topdir = getcwd());
289 $this = resolve_directory($topdir); # PWD, Regardless.
291 # Does the cache file exist?
293 # No, No it doesn't.. *BASH*
294 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
297 # We've Loaded the cache file and all our variables..
298 print "Updating files...\n";
299 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
301 print "Disabling debug information (-g).\n";
302 $config{OPTIMISATI} = "";
304 $has_epoll = $config{HAS_EPOLL};
305 $has_ports = $config{HAS_PORTS};
306 $has_kqueue = $config{HAS_KQUEUE};
315 print "Configure update failed: $@\n";
323 open(FH,"<.svn/entries") or $fail = 1;
325 print "This is not an SVN copy of InspIRCd.\n";
332 open my $fd, "-|", "svn update";
333 my $configurechanged = 0; # Needs ./configure -update
334 my $rootincchanged = 0;
336 while (defined(my $line = <$fd>))
340 $line =~ m/^([ADUCG])\s+(.*)$/ or next;
341 ($action, $file) = ($1, $2);
344 push @conflicted, $file;
345 if ($file eq "configure")
347 $configurechanged = 1;
349 elsif ($file =~ m/^\..*\.inc$/)
354 elsif ($action eq "U" || $action eq "G")
356 if ($file eq "configure")
358 $configurechanged = 1;
360 elsif ($file =~ m/^\..*\.inc$/)
366 unless (close $fd) # close() waits for exit and returns false if the command failed
370 print STDERR "Problem updating from SVN, please check above for errors\n";
374 print STDERR "Failed to run SVN: $!\n";
378 if (scalar(@conflicted) > 0)
380 print STDERR "\e[0;33;1mERROR:\e[0m You have local modifications which conflicted with the updates from SVN\n";
381 print STDERR "Configure is not able to complete the update. Please resolve these conflicts, then run ./configure -update\n";
382 print "Conflicted files: " . join ", ", @conflicted . "\n";
385 if ($configurechanged)
387 system("perl configure -update");
391 print "No need to update Makefiles.\n";
393 if (defined $opt_rebuild) {
394 system("make install");
402 $fail ||= system "$config{CC} -o test_$feature make/check_$feature.cpp >/dev/null 2>&1";
403 $fail ||= system "./test_$feature";
404 unlink "test_$feature";
408 print "Running non-interactive configure...\n" unless $interactive;
409 print "Checking for cache from previous configure... ";
410 print ((!getcache()) ? "not found\n" : "found\n");
411 $config{SYSTEM} = lc $^O;
412 print "Checking operating system version... $config{SYSTEM}\n";
414 printf "Checking if stdint.h exists... ";
415 $config{HAS_STDINT} = "true";
417 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
418 if ($config{HAS_STDINT} eq "true") {
421 print "yes\n" if $config{HAS_STDINT} eq "true";
422 print "no\n" if $config{HAS_STDINT} eq "false";
424 printf "Checking if strlcpy exists... ";
425 # Perform the strlcpy() test..
426 $config{HAS_STRLCPY} = "false";
428 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
430 while (defined(my $line = <STRLCPY>)) {
432 # try and find the delcaration of:
433 # size_t strlcpy(...)
434 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
435 $config{HAS_STRLCPY} = "true";
440 print "yes\n" if $config{HAS_STRLCPY} eq "true";
441 print "no\n" if $config{HAS_STRLCPY} eq "false";
443 printf "Checking if kqueue exists... ";
446 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
448 while (defined(my $line = <KQUEUE>)) {
450 # try and find the delcaration of:
452 if ($line =~ /int(\0x9|\s)+kqueue/) {
458 print "yes\n" if $has_kqueue == 1;
459 print "no\n" if $has_kqueue == 0;
461 printf "Checking for epoll support... ";
462 $has_epoll = test_compile('epoll');
463 print $has_epoll ? "yes\n" : "no\n";
465 printf "Checking for eventfd support... ";
466 $config{HAS_EVENTFD} = test_compile('eventfd') ? 'true' : 'false';
467 print $config{HAS_EVENTFD} eq 'true' ? "yes\n" : "no\n";
469 printf "Checking if Solaris I/O completion ports are available... ";
471 our $system = `uname -s`;
473 $has_ports = 1 if ($system eq "SunOS");
476 my $kernel = `uname -r`;
478 if (($kernel !~ /^5\.1./)) {
482 print "yes\n" if $has_ports == 1;
483 print "no\n" if $has_ports == 0;
485 $config{HAS_EPOLL} = $has_epoll;
486 $config{HAS_KQUEUE} = $has_kqueue;
488 printf "Checking for libgnutls... ";
489 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
490 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
492 $config{HAS_GNUTLS} = "y";
495 $config{HAS_GNUTLS} = "n";
499 $config{HAS_GNUTLS} = "n";
502 printf "Checking for openssl... ";
503 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
504 if (defined($openssl_ver) && ($openssl_ver ne "")) {
506 $config{HAS_OPENSSL} = "y";
509 $config{HAS_OPENSSL} = "n";
513 $config{HAS_OPENSSL} = "n";
516 printf "Checking if you are running an ancient, unsupported OS... ";
517 if ($config{OSNAME} =~ /FreeBSD/i)
519 my $version = `uname -r`;
520 if ($version =~ /^4\./)
523 print "FreeBSD 4.x is no longer supported. By ANYONE.\n";
524 print "To build, you will need to add the following to CXXFLAGS:\n";
525 print "\t-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1\n";
529 print "no ($version)\n";
534 print "no ($config{OSNAME})\n";
537 print "Checking for upgrades to extra and third party modules... ";
538 system "./modulemanager upgrade";
540 ################################################################################
541 # BEGIN INTERACTIVE PART #
542 ################################################################################
547 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
550 my $rev = getrevision();
551 # Display Introduction Message..
553 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
554 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
556 *** If you are unsure of any of these values, leave it blank for ***
557 *** standard settings that will work, and your server will run ***
558 *** using them. Please consult your IRC network admin if in doubt. ***
560 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
561 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
562 dir, otherwise you won't have a config file!
564 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
565 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
568 print " (Non-SVN build)";
572 $config{CHANGE_COMPILER} = "n";
573 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";
575 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
576 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
577 should NOT be used. You should probably specify a newer compiler.\n\n";
578 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
579 if ($config{CHANGE_COMPILER} =~ /y/i) {
580 print "What command do you want to use to invoke your compiler?\n";
581 print "[\e[1;32m$config{CC}\e[0m] -> ";
582 chomp($config{CC} = <STDIN>);
583 if ($config{CC} eq "") {
586 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
588 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
589 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
590 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
591 if ($config{GCCVER} < 3) {
592 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
596 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
603 # Directory Settings..
604 my $tmpbase = $config{BASE_DIR};
605 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
606 if ($tmpbase ne $config{BASE_DIR}) {
607 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
608 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
609 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
612 dir_check("are the configuration files", "CONFIG_DIR");
613 dir_check("are the modules to be compiled to", "MODULE_DIR");
614 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
615 dir_check("do you want the build to take place", "BUILD_DIR");
617 my $chose_hiperf = 0;
619 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?");
621 if ($config{USE_KQUEUE} eq "y") {
626 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?");
628 if ($config{USE_EPOLL} eq "y") {
633 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?");
635 if ($config{USE_PORTS} eq "y") {
640 if (!$chose_hiperf) {
641 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?");
642 if ($config{USE_POLL} ne "y")
644 print "No high-performance socket engines are available, or you chose\n";
645 print "not to enable one. Defaulting to select() engine.\n\n";
649 yesno('IPV6',"Would you like to build InspIRCd with IPv6 support?\nYou can still use IPv4 addresses in your port bindings.\n\nEnable IPv6?");
652 $config{USE_FREEBSD_BASE_SSL} = "n";
653 $config{USE_FREEBSD_PORTS_SSL} = "n";
654 if ($config{HAS_OPENSSL_PORT} ne "")
656 $config{USE_FREEBSD_PORTS_SSL} = "y";
657 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
658 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";
659 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
661 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
663 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
665 # update to port version
666 $openssl_ver = $config{HAS_OPENSSL_PORT};
671 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
674 $config{USE_SSL} = "n";
676 if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
678 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
679 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
681 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
682 if ($config{USE_SSL} eq "y")
684 if ($config{HAS_GNUTLS} eq "y")
686 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
687 if ($config{USE_GNUTLS} eq "y")
689 print "\nUsing GnuTLS SSL module.\n";
693 if ($config{HAS_OPENSSL} eq "y")
695 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
696 if ($config{USE_OPENSSL} eq "y")
698 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
705 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed if\n";
706 print "you intend to use OpenSSL, or that GnuTLS is in your path if you intend\nto use GnuTLS.\n\n";
712 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
714 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
717 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
719 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
724 $config{CERTGEN} ||= 'y';
725 yesno('CERTGEN',"Would you like generate SSL certificates now?") if ($interactive && ($config{USE_GNUTLS} eq "y" || $config{USE_OPENSSL} eq "y"));
727 if ($config{USE_GNUTLS} eq "y") {
728 unless (-r "src/modules/m_ssl_gnutls.cpp") {
729 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
730 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
732 if ($interactive && $config{CERTGEN} eq 'y')
734 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
735 print "SSL Certificates Not found, Generating.. \n\n
736 *************************************************************
737 * Generating the Private Key may take some time, go grab a *
738 * Coffee. Even better, to generate some more entropy if it *
739 * is taking a while, open another console and type du / a *
740 * few times and get that HD going :) Then answer the *
741 * Questions which follow. If you are unsure, just hit enter *
742 *************************************************************\n\n";
743 $failed = make_gnutls_cert();
745 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
747 print "\nCertificate generation complete, copying to config directory... ";
748 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
749 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
754 print "SSL Certificates found, skipping.\n\n";
759 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
763 if ($config{USE_OPENSSL} eq "y") {
764 unless (-r "src/modules/m_ssl_openssl.cpp") {
765 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
766 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
769 if ($interactive && $config{CERTGEN} eq 'y')
771 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
772 print "SSL Certificates Not found, Generating.. \n\n
773 *************************************************************
774 * Generating the certificates may take some time, go grab a *
775 * coffee, or something. *
776 *************************************************************\n\n";
778 print "\nCertificate generation complete, copying to config directory... ";
779 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
780 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
781 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
784 print "SSL Certificates found, skipping.\n\n"
789 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
792 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
793 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
801 print "To build your server with these settings, please run '\e[1;32mmake\e[0m' now.\n";
802 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
803 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
804 print "modules in your config. This configure script has added those modules to the\n";
805 print "build process. For more info please refer to:\n";
806 print "\e[1;32mhttp://wiki.inspircd.org/Installation_From_Tarball\e[0m\n";
808 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
809 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
810 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";
813 if ($config{GCCVER} < "3") {
815 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
816 GCC 2.x series compilers only had partial (read as broken) C++ support, and
817 your compile will most likely fail horribly! If you have any problems, do NOT
818 report them to the bugtracker or forums without first upgrading your compiler
819 to a newer 3.x or 4.x (or whatever is available currently) version.
823 ################################################################################
825 ################################################################################
827 # Retrieves the .config.cache file, and loads values into the main config hash.
828 open(CACHE, ".config.cache") or return 0;
831 # Ignore Blank lines, and comments..
834 my ($key, $value) = split("=", $_, 2);
835 $value =~ /^\"(.*)\"$/;
836 # Do something with data here!
844 # Dump the contents of %config
845 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
846 open(FILEHANDLE, ">.config.cache");
847 foreach my $key (keys %config) {
848 print FILEHANDLE "$key=\"$config{$key}\"\n";
854 my ($desc, $hash_key) = @_;
857 print "In what directory $desc?\n";
858 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
859 chomp(my $var = <STDIN>);
861 $var = $config{$hash_key};
863 if ($var =~ /^\~\/(.+)$/) {
864 # Convert it to a full path..
865 $var = resolve_directory($ENV{HOME} . "/" . $1);
867 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
869 # Assume relative Path was given.. fill in the rest.
870 $var = $this . "/$var";
873 $var = resolve_directory($var);
875 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
876 chomp(my $tmp = <STDIN>);
877 if (($tmp eq "") || ($tmp =~ /^y/i)) {
878 # Attempt to Create the Dir..
881 File::Path::mkpath($var, 0, 0777);
884 unless (defined($chk) && -d $var) {
885 print "Unable to create directory. ($var)\n\n";
890 # They said they don't want to create, and we can't install there.
896 # Target exists, but is not a directory.
897 print "File $var exists, but is not a directory.\n\n";
901 # Either Dir Exists, or was created fine.
902 $config{$hash_key} = $var;
910 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
913 my($writeheader) = @_;
914 # First File.. inspircd_config.h
915 chomp(my $incos = `uname -n -s -r`);
916 chomp(my $version = `sh src/version.sh`);
917 chomp(my $revision2 = getrevision());
918 if ($writeheader == 1)
920 print "Writing \e[1;32minspircd_config.h\e[0m\n";
921 open(FILEHANDLE, ">include/inspircd_config.h.tmp");
922 print FILEHANDLE <<EOF;
923 /* Auto generated by configure, do not modify! */
924 #ifndef __CONFIGURATION_AUTO__
925 #define __CONFIGURATION_AUTO__
927 /* this is for windows support. */
928 #define CoreExport /**/
929 #define DllExport /**/
931 #define MOD_PATH "$config{MODULE_DIR}"
932 #define SOMAXCONN_S "$config{_SOMAXCONN}"
933 #define ENTRYPOINT int main(int argc, char** argv)
936 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
938 if ($config{OSNAME} =~ /SunOS/i) {
939 print FILEHANDLE "#define IS_SOLARIS\n";
941 if ($config{OSNAME} =~ /MINGW32/i) {
942 print FILEHANDLE "#define IS_MINGW\n";
944 if ($config{GCCVER} >= 3) {
945 print FILEHANDLE "#define GCC3\n";
948 (($config{GCCVER} == 4) && ($config{GCCMINOR} >= 3))
950 ($config{GCCVER} > 4)
952 print FILEHANDLE "#define HASHMAP_DEPRECATED\n";
954 if ($config{HAS_STRLCPY} eq "true") {
955 print FILEHANDLE "#define HAS_STRLCPY\n";
957 if ($config{HAS_STDINT} eq "true") {
958 print FILEHANDLE "#define HAS_STDINT\n";
960 if ($config{IPV6} =~ /y/i) {
961 print FILEHANDLE "#define IPV6\n";
963 if ($config{HAS_EVENTFD} eq 'true') {
964 print FILEHANDLE "#define HAS_EVENTFD\n";
967 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
968 print FILEHANDLE "#define USE_KQUEUE\n";
969 $config{SOCKETENGINE} = "socketengine_kqueue";
972 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
973 print FILEHANDLE "#define USE_EPOLL\n";
974 $config{SOCKETENGINE} = "socketengine_epoll";
977 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
978 print FILEHANDLE "#define USE_PORTS\n";
979 $config{SOCKETENGINE} = "socketengine_ports";
982 # user didn't choose either epoll or select for their OS.
983 # default them to USE_SELECT (ewwy puke puke)
985 print "no hi-perf, " . $config{USE_POLL};
986 if ($config{USE_POLL} eq "y")
988 print FILEHANDLE "#define USE_POLL\n";
989 $config{SOCKETENGINE} = "socketengine_poll";
993 print FILEHANDLE "#define USE_SELECT\n";
994 $config{SOCKETENGINE} = "socketengine_select";
997 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
1000 open(FILEHANDLE, ">include/inspircd_se_config.h.tmp");
1001 print FILEHANDLE <<EOF;
1002 /* Auto generated by configure, do not modify or commit to svn! */
1003 #ifndef __CONFIGURATION_SOCKETENGINE__
1004 #define __CONFIGURATION_SOCKETENGINE__
1006 #include "socketengines/$config{SOCKETENGINE}.h"
1012 open(FILEHANDLE, ">include/inspircd_version.h.tmp");
1013 print FILEHANDLE <<EOF;
1014 #define VERSION "$version"
1015 #define REVISION "$revision2"
1016 #define SYSTEM "$incos"
1020 for my $file (qw(include/inspircd_config.h include/inspircd_se_config.h include/inspircd_version.h)) {
1022 open my $fh1, $file or $diff = 1;
1023 open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
1027 if (defined($line1) != defined($line2)) {
1029 } elsif (!defined $line1) {
1032 $diff = ($line1 ne $line2);
1037 rename "$file.tmp", $file;
1044 # Write all .in files.
1047 my $exe = "inspircd";
1049 # Do this once here, and cache it in the .*.inc files,
1050 # rather than attempting to read src/version.sh from
1051 # compiled code -- we might not have the source to hand.
1052 # Fix for bug#177 by Brain.
1054 chomp($version = `sh ./src/version.sh`);
1055 chomp(my $revision = getrevision());
1056 $version = "$version(r$revision)";
1058 # We can actually parse any file starting with . and ending with .inc,
1059 # but right now we only parse .inspircd.inc to form './inspircd'
1060 prepare_dynamic_makefile();
1062 print "Writing \e[1;32mMakefiles\e[0m\n";
1064 opendir(DIRHANDLE, $this);
1066 foreach my $name (sort readdir(DIRHANDLE)) {
1067 if ($name =~ /^\.(.+)\.inc$/) {
1070 # Bug #353, omit this on non-darwin
1071 next if (($config{OSNAME} !~ /darwin/) && ($file eq "org.inspircd.plist"));
1073 # All .name.inc files need parsing!
1074 open(FILEHANDLE, ".$file.inc") or die ("Can't open .$file.inc");
1075 $_ = join '', <FILEHANDLE>;
1078 print "Writing \e[1;32m$file\e[0m ...\n";
1080 $config{BUILD_DIR} ||= resolve_directory($config{ME}."/build");
1083 CC SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR
1084 STARTSCRIPT DESTINATION EXTRA_DIR SOCKETENGINE
1086 s/\@$var\@/$config{$var}/g;
1088 s/\@EXECUTABLE\@/$exe/ if defined $exe;
1089 s/\@VERSION\@/$version/ if defined $version;
1091 if ($file eq 'Makefile') {
1093 s/\@IFDEF (\S+)/ifdef $1/g;
1094 s/\@IFNDEF (\S+)/ifndef $1/g;
1095 s/\@IFEQ (\S+) (\S+)/ifeq ($1,$2)/g;
1096 s/\@ELSIFEQ (\S+) (\S+)/else ifeq ($1,$2)/g;
1099 s/ *\@BSD_ONLY .*\n//g;
1101 s/\@DO_EXPORT (.*)/export $1/g;
1102 open MKF, '>GNUmakefile' or die "Can't write to GNUmakefile: $!";
1106 s/\@IFDEF (\S+)/.if defined($1)/g;
1107 s/\@IFNDEF (\S+)/.if !defined($1)/g;
1108 s/\@IFEQ (\S+) (\S+)/.if $1 == $2/g;
1109 s/\@ELSIFEQ (\S+) (\S+)/.elif $1 == $2/g;
1113 s/ *\@GNU_ONLY .*\n//g;
1115 $mk_tmp =~ s#\@DO_EXPORT (.*)#"MAKEENV += ".join ' ', map "$_='\${$_}'", split /\s/, $1#eg;
1116 open MKF, '>BSDmakefile' or die "Can't write to BSDmakefile: $!";
1120 open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
1121 print FILEHANDLE $_;
1126 closedir(DIRHANDLE);
1128 # Make inspircd executable!
1129 chmod 0744, 'inspircd';
1135 for my $mod (@modlist) {
1136 getcompilerflags("src/modules/m_$mod.cpp");
1137 getlinkerflags("src/modules/m_$mod.cpp");
1141 sub prepare_dynamic_makefile
1147 $config{USE_EPOLL} = 0;
1151 $config{USE_KQUEUE} = 0;
1155 $config{USE_PORTS} = 0;
1159 # Routine to list out the extra/ modules that have been enabled.
1160 # Note: when getting any filenames out and comparing, it's important to lc it if the
1161 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1162 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1163 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1164 sub list_extras () {
1167 my $srcdir = File::Spec->catdir("src", "modules");
1168 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1171 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1172 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1175 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1176 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1179 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1181 EXTRA: for my $extra (@extras) {
1182 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1183 next if ($extra eq '.svn');
1184 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1185 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1186 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1187 if (-l $abs_source) {
1188 # Symlink, is it in the right place?
1189 my $targ = readlink($abs_source);
1190 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1191 if ($abs_targ eq $abs_extra) {
1192 $extras{$extra} = "\e[32;1menabled\e[0m";
1194 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1196 } elsif (-e $abs_source) {
1197 my ($devext, $inoext) = stat($abs_extra);
1198 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1200 if ($devsrc == $devext && $inosrc == $inoext) {
1201 $extras{$extra} = "\e[32;1menabled\e[0m";
1203 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1206 open my $extfd, "<", $abs_extra;
1207 open my $srcfd, "<", $abs_source;
1209 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1210 $extras{$extra} = "\e[32;1menabled\e[0m";
1212 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1216 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1219 # Now let's add dependency info
1220 for my $extra (keys(%extras)) {
1221 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1222 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1223 my @deps = split / +/, getdependencies($abs_extra);
1224 for my $dep (@deps) {
1225 if (exists($extras{$dep})) {
1226 my $ref = \$extras{$dep}; # Take reference.
1227 if ($$ref !~ m/needed by/) {
1228 # First dependency found.
1229 if ($$ref =~ m/enabled/) {
1230 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1232 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1233 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1236 if ($$ref =~ m/enabled/) {
1237 $$ref .= ", \e[32;1m$extra\e[0m";
1239 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1245 for my $extra (sort {$a cmp $b} keys(%extras)) {
1246 my $text = $extras{$extra};
1247 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1248 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1250 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1253 return keys(%extras) if wantarray; # Can be used by manage_extras.
1256 sub enable_extras (@) {
1258 for my $extra (@extras) {
1259 my $extrapath = "src/modules/extra/$extra";
1260 if (!-e $extrapath) {
1261 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1264 my $source = "src/modules/$extra";
1266 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1269 # Get dependencies, and add them to be processed.
1270 my @deps = split / +/, getdependencies($extrapath);
1271 for my $dep (@deps) {
1272 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1273 if (!-e "src/modules/$dep") {
1274 if (-e "src/modules/extra/$dep") {
1275 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1278 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";
1282 print "Enabling $extra ... \n";
1283 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1287 sub disable_extras (@)
1289 opendir my $dd, "src/modules/extra/";
1290 my @files = readdir($dd);
1293 EXTRA: for my $extra (@extras) {
1294 my $extrapath = "src/modules/extra/$extra";
1295 my $source = "src/modules/$extra";
1296 if (!-e $extrapath) {
1297 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1300 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1301 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";
1304 # Check if anything needs this.
1305 for my $file (@files) {
1306 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1307 # File depends on this extra...
1308 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1309 # And is both enabled and not about to be disabled.
1310 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1311 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1317 print "Disabling $extra ... \n";
1318 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";