2 ###################################################
3 # InspIRCd Configuration Script
5 # Copyright 2002-2010 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,
48 $opt_system, $opt_uid);
50 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 'system' => \$opt_system,
66 'enable-openssl' => \$opt_use_openssl,
67 'disable-interactive' => \$opt_nointeractive,
68 'enable-ports' => \$opt_ports,
69 'enable-epoll' => \$opt_epoll,
70 'enable-kqueue' => \$opt_kqueue,
71 'disable-ports' => \$opt_noports,
72 'disable-epoll' => \$opt_noepoll,
73 'disable-kqueue' => \$opt_nokqueue,
74 'disable-ipv6' => \$opt_noipv6,
75 'with-cc=s' => \$opt_cc,
76 'with-maxbuf=i' => \$opt_maxbuf,
77 'enable-freebsd-ports-openssl' => \$opt_freebsd_port,
78 'prefix=s' => \$opt_base_dir,
79 'config-dir=s' => \$opt_config_dir,
80 'module-dir=s' => \$opt_module_dir,
81 'binary-dir=s' => \$opt_binary_dir,
82 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
83 'help' => sub { showhelp(); },
84 'update' => sub { update(); },
85 'svnupdate' => sub { svnupdate(); },
86 'clean' => sub { clean(); },
87 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
88 'enable-extras=s@' => \@opt_enableextras, # ^
89 'disable-extras=s@' => \@opt_disableextras, # ^
90 'generate-openssl-cert' => sub { make_openssl_cert(); exit(0); },
91 'generate-gnutls-cert' => sub { make_gnutls_cert(); exit(0); }
94 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
95 @opt_enableextras = split /,/, join(',', @opt_enableextras);
96 @opt_disableextras = split /,/, join(',', @opt_disableextras);
97 enable_extras(@opt_enableextras);
98 disable_extras(@opt_disableextras);
100 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
104 our $interactive = !(
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_system) ||
122 (defined $opt_uid) ||
123 (defined $opt_use_gnutls) ||
124 (defined $opt_freebsd_port)
127 chomp(our $topdir = getcwd());
128 our $this = resolve_directory($topdir); # PWD, Regardless.
129 our @modlist = (); # Declare for Module List..
130 our %config = (); # Initiate Configuration Hash..
131 $config{ME} = resolve_directory($topdir); # Present Working Directory
133 $config{BASE_DIR} = $config{ME}."/run";
135 if (defined $opt_base_dir) {
136 $config{BASE_DIR} = $opt_base_dir;
137 } elsif (defined $opt_system || defined $opt_uid) {
138 $config{BASE_DIR} = '/var/lib/inspircd';
141 if (defined $opt_system || defined $opt_uid) {
142 $config{UID} = $opt_uid || 'ircd';
143 $config{CONFIG_DIR} = '/etc/inspircd';
144 $config{MODULE_DIR} = '/usr/lib/inspircd';
145 $config{BINARY_DIR} = '/usr/sbin/';
146 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
149 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
150 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
151 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
152 $config{BUILD_DIR} = resolve_directory($config{ME}."/build"); # Build Directory
155 if (defined $opt_config_dir) {
156 $config{CONFIG_DIR} = $opt_config_dir;
158 if (defined $opt_module_dir) {
159 $config{MODULE_DIR} = $opt_module_dir;
161 if (defined $opt_binary_dir) {
162 $config{BINARY_DIR} = $opt_binary_dir;
164 chomp($config{HAS_GNUTLS} = `pkg-config --modversion gnutls 2>/dev/null | cut -c 1,2,3`); # GNUTLS Version.
166 if (defined $opt_freebsd_port)
168 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`);
169 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`);
170 $config{USE_FREEBSD_BASE_SSL} = "n";
174 if ($^O eq "freebsd")
176 # default: use base ssl
177 chomp($config{HAS_OPENSSL} = `openssl version | cut -d ' ' -f 2`); # OpenSSL version, freebsd specific
178 chomp($config{HAS_OPENSSL_PORT} = `pkg-config --modversion openssl 2>/dev/null`); # Port version, may be different
182 chomp($config{HAS_OPENSSL} = `pkg-config --modversion openssl 2>/dev/null`); # Openssl version, others
183 $config{HAS_OPENSSL_PORT} = "";
187 chomp(our $gnutls_ver = $config{HAS_GNUTLS});
188 chomp(our $openssl_ver = $config{HAS_OPENSSL});
189 $config{USE_GNUTLS} = "n";
190 if (defined $opt_use_gnutls)
192 $config{USE_GNUTLS} = "y"; # Use gnutls.
194 $config{USE_OPENSSL} = "n"; # Use openssl.
195 if (defined $opt_use_openssl)
197 $config{USE_OPENSSL} = "y";
200 if (!defined $opt_disable_debug) {
201 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
203 $config{OPTIMISATI} = "-O2";
206 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
207 $config{HAS_STDINT} = "false"; # stdint.h check
208 $config{USE_KQUEUE} = "y"; # kqueue enabled
209 if (defined $opt_nokqueue) {
210 $config{USE_KQUEUE} = "n";
212 $config{USE_POLL} = "y"; # poll enabled
213 $config{USE_EPOLL} = "y"; # epoll enabled
214 if (defined $opt_noepoll)
216 $config{USE_EPOLL} = "n";
218 $config{USE_PORTS} = "y"; # epoll enabled
219 if (defined $opt_noports)
221 $config{USE_PORTS} = "n";
223 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
224 $config{OSNAME} = $^O; # Operating System Name
225 $config{IS_DARWIN} = "NO"; # Is OSX?
226 $config{STARTSCRIPT} = "inspircd"; # start script?
227 $config{DESTINATION} = "BASE"; # Is target path.
228 $config{EXTRA_DIR} = ""; # Is empty.
229 if ($config{OSNAME} =~ /darwin/i)
231 $config{IS_DARWIN} = "YES";
232 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
234 $config{CC} = "g++"; # C++ compiler
237 $config{CC} = $opt_cc;
239 our $exec = $config{CC} . " -dumpversion | cut -c 1";
240 chomp($config{GCCVER} = `$exec`); # Major GCC Version
241 $exec = $config{CC} . " -dumpversion | cut -c 3";
242 chomp($config{GCCMINOR} = `$exec`);
243 $config{MAXBUF} = "512"; # Max buffer size
245 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/) {
246 $config{HAS_OPENSSL} = $1;
248 $config{HAS_OPENSSL} = "";
251 if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
252 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
256 # Get and Set some important vars..
261 unlink(".config.cache");
264 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
269 chomp($topdir = getcwd());
270 $this = resolve_directory($topdir); # PWD, Regardless.
272 # Does the cache file exist?
274 # No, No it doesn't.. *BASH*
275 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
278 # We've Loaded the cache file and all our variables..
279 print "Updating files...\n";
280 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
282 print "Disabling debug information (-g).\n";
283 $config{OPTIMISATI} = "";
285 $has_epoll = $config{HAS_EPOLL};
286 $has_ports = $config{HAS_PORTS};
287 $has_kqueue = $config{HAS_KQUEUE};
296 print "Configure update failed: $@\n";
304 open(FH,"<.svn/entries") or $fail = 1;
306 print "This is not an SVN copy of InspIRCd.\n";
313 open my $fd, "-|", "svn update";
314 my $configurechanged = 0; # Needs ./configure -update
315 my $rootincchanged = 0;
317 while (defined(my $line = <$fd>))
321 $line =~ m/^([ADUCG])\s+(.*)$/ or next;
322 ($action, $file) = ($1, $2);
325 push @conflicted, $file;
326 if ($file eq "configure")
328 $configurechanged = 1;
330 elsif ($file =~ m/^\..*\.inc$/)
335 elsif ($action eq "U" || $action eq "G")
337 if ($file eq "configure")
339 $configurechanged = 1;
341 elsif ($file =~ m/^\..*\.inc$/)
347 unless (close $fd) # close() waits for exit and returns false if the command failed
351 print STDERR "Problem updating from SVN, please check above for errors\n";
355 print STDERR "Failed to run SVN: $!\n";
359 if (scalar(@conflicted) > 0)
361 print STDERR "\e[0;33;1mERROR:\e[0m You have local modifications which conflicted with the updates from SVN\n";
362 print STDERR "Configure is not able to complete the update. Please resolve these conflicts, then run ./configure -update\n";
363 print "Conflicted files: " . join ", ", @conflicted . "\n";
366 if ($configurechanged)
368 system("perl configure -update");
372 print "No need to update Makefiles.\n";
374 if (defined $opt_rebuild) {
375 system("make install");
383 $fail ||= system "$config{CC} -o test_$feature make/check_$feature.cpp >/dev/null 2>&1";
384 $fail ||= system "./test_$feature";
385 unlink "test_$feature";
389 print "Running non-interactive configure...\n" unless $interactive;
390 print "Checking for cache from previous configure... ";
391 print ((!getcache()) ? "not found\n" : "found\n");
392 $config{SYSTEM} = lc $^O;
393 print "Checking operating system version... $config{SYSTEM}\n";
395 $exec = $config{CC} . " -dumpversion | cut -c 1";
396 chomp($config{GCCVER} = `$exec`); # Major GCC Version
397 $exec = $config{CC} . " -dumpversion | cut -c 3";
398 chomp($config{GCCMINOR} = `$exec`);
400 printf "Checking if stdint.h exists... ";
401 $config{HAS_STDINT} = "true";
403 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
404 if ($config{HAS_STDINT} eq "true") {
407 print "yes\n" if $config{HAS_STDINT} eq "true";
408 print "no\n" if $config{HAS_STDINT} eq "false";
410 printf "Checking if strlcpy exists... ";
411 # Perform the strlcpy() test..
412 $config{HAS_STRLCPY} = "false";
414 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
416 while (defined(my $line = <STRLCPY>)) {
418 # try and find the delcaration of:
419 # size_t strlcpy(...)
420 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
421 $config{HAS_STRLCPY} = "true";
426 print "yes\n" if $config{HAS_STRLCPY} eq "true";
427 print "no\n" if $config{HAS_STRLCPY} eq "false";
429 printf "Checking if kqueue exists... ";
432 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
434 while (defined(my $line = <KQUEUE>)) {
436 # try and find the delcaration of:
438 if ($line =~ /int(\0x9|\s)+kqueue/) {
444 print "yes\n" if $has_kqueue == 1;
445 print "no\n" if $has_kqueue == 0;
447 printf "Checking for epoll support... ";
448 $has_epoll = test_compile('epoll');
449 print $has_epoll ? "yes\n" : "no\n";
451 printf "Checking for eventfd support... ";
452 $config{HAS_EVENTFD} = test_compile('eventfd') ? 'true' : 'false';
453 print $config{HAS_EVENTFD} eq 'true' ? "yes\n" : "no\n";
455 printf "Checking if Solaris I/O completion ports are available... ";
457 our $system = `uname -s`;
459 $has_ports = 1 if ($system eq "SunOS");
462 my $kernel = `uname -r`;
464 if (($kernel !~ /^5\.1./)) {
468 print "yes\n" if $has_ports == 1;
469 print "no\n" if $has_ports == 0;
471 $config{HAS_EPOLL} = $has_epoll;
472 $config{HAS_KQUEUE} = $has_kqueue;
474 printf "Checking for libgnutls... ";
475 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
476 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
478 $config{HAS_GNUTLS} = "y";
481 $config{HAS_GNUTLS} = "n";
485 $config{HAS_GNUTLS} = "n";
488 printf "Checking for openssl... ";
489 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
490 if (defined($openssl_ver) && ($openssl_ver ne "")) {
492 $config{HAS_OPENSSL} = "y";
495 $config{HAS_OPENSSL} = "n";
499 $config{HAS_OPENSSL} = "n";
502 printf "Checking if you are running an ancient, unsupported OS... ";
503 if ($config{OSNAME} =~ /FreeBSD/i)
505 my $version = `uname -r`;
506 if ($version =~ /^4\./)
509 print "FreeBSD 4.x is no longer supported. By ANYONE.\n";
510 print "To build, you will need to add the following to CXXFLAGS:\n";
511 print "\t-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1\n";
515 print "no ($version)\n";
520 print "no ($config{OSNAME})\n";
523 ################################################################################
524 # BEGIN INTERACTIVE PART #
525 ################################################################################
530 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
533 my $rev = getrevision();
534 # Display Introduction Message..
536 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
537 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
539 *** If you are unsure of any of these values, leave it blank for ***
540 *** standard settings that will work, and your server will run ***
541 *** using them. Please consult your IRC network admin if in doubt. ***
543 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
544 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
545 dir, otherwise you won't have a config file!
547 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
548 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
551 print " (Non-SVN build)";
555 $config{CHANGE_COMPILER} = "n";
556 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";
558 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
559 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
560 should NOT be used. You should probably specify a newer compiler.\n\n";
561 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
562 if ($config{CHANGE_COMPILER} =~ /y/i) {
563 print "What command do you want to use to invoke your compiler?\n";
564 print "[\e[1;32m$config{CC}\e[0m] -> ";
565 chomp($config{CC} = <STDIN>);
566 if ($config{CC} eq "") {
569 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
571 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
572 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
573 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
574 if ($config{GCCVER} < 3) {
575 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
579 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
586 # Directory Settings..
587 my $tmpbase = $config{BASE_DIR};
588 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
589 if ($tmpbase ne $config{BASE_DIR}) {
590 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
591 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
592 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
595 dir_check("are the configuration files", "CONFIG_DIR");
596 dir_check("are the modules to be compiled to", "MODULE_DIR");
597 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
598 dir_check("do you want the build to take place", "BUILD_DIR");
600 my $chose_hiperf = 0;
602 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?");
604 if ($config{USE_KQUEUE} eq "y") {
609 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?");
611 if ($config{USE_EPOLL} eq "y") {
616 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?");
618 if ($config{USE_PORTS} eq "y") {
623 if (!$chose_hiperf) {
624 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?");
625 if ($config{USE_POLL} ne "y")
627 print "No high-performance socket engines are available, or you chose\n";
628 print "not to enable one. Defaulting to select() engine.\n\n";
632 $config{USE_FREEBSD_BASE_SSL} = "n";
633 $config{USE_FREEBSD_PORTS_SSL} = "n";
634 if ($config{HAS_OPENSSL_PORT} ne "")
636 $config{USE_FREEBSD_PORTS_SSL} = "y";
637 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
638 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";
639 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
641 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
643 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
645 # update to port version
646 $openssl_ver = $config{HAS_OPENSSL_PORT};
651 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
654 $config{USE_SSL} = "n";
655 $config{MODUPDATE} = 'n';
657 if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
659 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
660 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
662 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
663 if ($config{USE_SSL} eq "y")
665 if ($config{HAS_GNUTLS} eq "y")
667 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
668 if ($config{USE_GNUTLS} eq "y")
670 print "\nUsing GnuTLS SSL module.\n";
674 if ($config{HAS_OPENSSL} eq "y")
676 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
677 if ($config{USE_OPENSSL} eq "y")
679 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
686 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed if\n";
687 print "you intend to use OpenSSL, or that GnuTLS is in your path if you intend\nto use GnuTLS.\n\n";
690 yesno('MODUPDATE',"Would you like to check for updates to third-party modules?");
692 if ($config{MODUPDATE} eq "y") {
693 print "Checking for upgrades to extra and third party modules... ";
694 system "./modulemanager upgrade";
700 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
702 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
705 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
707 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
712 $config{CERTGEN} ||= 'y';
713 yesno('CERTGEN',"Would you like generate SSL certificates now?") if ($interactive && ($config{USE_GNUTLS} eq "y" || $config{USE_OPENSSL} eq "y"));
715 if ($config{USE_GNUTLS} eq "y") {
716 unless (-r "src/modules/m_ssl_gnutls.cpp") {
717 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
718 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.cpp" or print STDERR "Symlink failed: $!";
720 if ($interactive && $config{CERTGEN} eq 'y')
722 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
723 print "SSL Certificates Not found, Generating.. \n\n
724 *************************************************************
725 * Generating the Private Key may take some time, go grab a *
726 * Coffee. Even better, to generate some more entropy if it *
727 * is taking a while, open another console and type du / a *
728 * few times and get that HD going :) Then answer the *
729 * Questions which follow. If you are unsure, just hit enter *
730 *************************************************************\n\n";
731 $failed = make_gnutls_cert();
733 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
735 print "\nCertificate generation complete, copying to config directory... ";
736 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
737 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
742 print "SSL Certificates found, skipping.\n\n";
747 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
751 if ($config{USE_OPENSSL} eq "y") {
752 unless (-r "src/modules/m_ssl_openssl.cpp") {
753 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
754 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
757 if ($interactive && $config{CERTGEN} eq 'y')
759 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
760 print "SSL Certificates Not found, Generating.. \n\n
761 *************************************************************
762 * Generating the certificates may take some time, go grab a *
763 * coffee, or something. *
764 *************************************************************\n\n";
766 print "\nCertificate generation complete, copying to config directory... ";
767 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
768 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
769 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
772 print "SSL Certificates found, skipping.\n\n"
777 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
780 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
781 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
789 print "To build your server with these settings, please run '\e[1;32mmake\e[0m' now.\n";
790 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
791 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
792 print "modules in your config. This configure script has added those modules to the\n";
793 print "build process. For more info please refer to:\n";
794 print "\e[1;32mhttp://wiki.inspircd.org/Installation_From_Tarball\e[0m\n";
796 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
797 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
798 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";
801 if ($config{GCCVER} < "3") {
803 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
804 GCC 2.x series compilers only had partial (read as broken) C++ support, and
805 your compile will most likely fail horribly! If you have any problems, do NOT
806 report them to the bugtracker or forums without first upgrading your compiler
807 to a newer 3.x or 4.x (or whatever is available currently) version.
811 ################################################################################
813 ################################################################################
815 # Retrieves the .config.cache file, and loads values into the main config hash.
816 open(CACHE, ".config.cache") or return 0;
819 # Ignore Blank lines, and comments..
822 my ($key, $value) = split("=", $_, 2);
823 $value =~ /^\"(.*)\"$/;
824 # Do something with data here!
832 # Dump the contents of %config
833 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
834 open(FILEHANDLE, ">.config.cache");
835 foreach my $key (keys %config) {
836 print FILEHANDLE "$key=\"$config{$key}\"\n";
842 my ($desc, $hash_key) = @_;
845 print "In what directory $desc?\n";
846 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
847 chomp(my $var = <STDIN>);
849 $var = $config{$hash_key};
851 if ($var =~ /^\~\/(.+)$/) {
852 # Convert it to a full path..
853 $var = resolve_directory($ENV{HOME} . "/" . $1);
855 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
857 # Assume relative Path was given.. fill in the rest.
858 $var = $this . "/$var";
861 $var = resolve_directory($var);
863 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
864 chomp(my $tmp = <STDIN>);
865 if (($tmp eq "") || ($tmp =~ /^y/i)) {
866 # Attempt to Create the Dir..
869 File::Path::mkpath($var, 0, 0777);
872 unless (defined($chk) && -d $var) {
873 print "Unable to create directory. ($var)\n\n";
878 # They said they don't want to create, and we can't install there.
884 # Target exists, but is not a directory.
885 print "File $var exists, but is not a directory.\n\n";
889 # Either Dir Exists, or was created fine.
890 $config{$hash_key} = $var;
898 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
901 my($writeheader) = @_;
902 # First File.. inspircd_config.h
903 chomp(my $incos = `uname -n -s -r`);
904 chomp(my $version = `sh src/version.sh`);
905 chomp(my $revision2 = getrevision());
906 if ($writeheader == 1)
908 print "Writing \e[1;32minspircd_config.h\e[0m\n";
909 open(FILEHANDLE, ">include/inspircd_config.h.tmp");
910 print FILEHANDLE <<EOF;
911 /* Auto generated by configure, do not modify! */
912 #ifndef __CONFIGURATION_AUTO__
913 #define __CONFIGURATION_AUTO__
915 /* this is for windows support. */
916 #define CoreExport /**/
917 #define DllExport /**/
919 #define MOD_PATH "$config{MODULE_DIR}"
920 #define SOMAXCONN_S "$config{_SOMAXCONN}"
921 #define ENTRYPOINT int main(int argc, char** argv)
924 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
926 if ($config{OSNAME} =~ /SunOS/i) {
927 print FILEHANDLE "#define IS_SOLARIS\n";
929 if ($config{OSNAME} =~ /MINGW32/i) {
930 print FILEHANDLE "#define IS_MINGW\n";
932 if ($config{GCCVER} >= 3) {
933 print FILEHANDLE "#define GCC3\n";
936 (($config{GCCVER} == 4) && ($config{GCCMINOR} >= 3))
938 ($config{GCCVER} > 4)
940 print FILEHANDLE "#define HASHMAP_DEPRECATED\n";
942 if ($config{HAS_STRLCPY} eq "true") {
943 print FILEHANDLE "#define HAS_STRLCPY\n";
945 if ($config{HAS_STDINT} eq "true") {
946 print FILEHANDLE "#define HAS_STDINT\n";
948 if ($config{HAS_EVENTFD} eq 'true') {
949 print FILEHANDLE "#define HAS_EVENTFD\n";
952 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
953 print FILEHANDLE "#define USE_KQUEUE\n";
954 $config{SOCKETENGINE} = "socketengine_kqueue";
957 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
958 print FILEHANDLE "#define USE_EPOLL\n";
959 $config{SOCKETENGINE} = "socketengine_epoll";
962 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
963 print FILEHANDLE "#define USE_PORTS\n";
964 $config{SOCKETENGINE} = "socketengine_ports";
967 # user didn't choose either epoll or select for their OS.
968 # default them to USE_SELECT (ewwy puke puke)
970 print "no hi-perf, " . $config{USE_POLL};
971 if ($config{USE_POLL} eq "y")
973 print FILEHANDLE "#define USE_POLL\n";
974 $config{SOCKETENGINE} = "socketengine_poll";
978 print FILEHANDLE "#define USE_SELECT\n";
979 $config{SOCKETENGINE} = "socketengine_select";
982 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
985 open(FILEHANDLE, ">include/inspircd_version.h.tmp");
986 print FILEHANDLE <<EOF;
987 #define VERSION "$version"
988 #define REVISION "$revision2"
989 #define SYSTEM "$incos"
993 for my $file (qw(include/inspircd_config.h include/inspircd_version.h)) {
995 open my $fh1, $file or $diff = 1;
996 open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
1000 if (defined($line1) != defined($line2)) {
1002 } elsif (!defined $line1) {
1005 $diff = ($line1 ne $line2);
1010 rename "$file.tmp", $file;
1017 # Write all .in files.
1020 my $exe = "inspircd";
1022 # Do this once here, and cache it in the .*.inc files,
1023 # rather than attempting to read src/version.sh from
1024 # compiled code -- we might not have the source to hand.
1025 # Fix for bug#177 by Brain.
1027 chomp($version = `sh ./src/version.sh`);
1028 chomp(my $revision = getrevision());
1029 $version = "$version(r$revision)";
1031 # We can actually parse any file starting with . and ending with .inc,
1032 # but right now we only parse .inspircd.inc to form './inspircd'
1033 prepare_dynamic_makefile();
1035 my @dotfiles = qw(main.mk inspircd);
1036 push @dotfiles, 'org.inspircd.plist' if $config{OSNAME} eq 'darwin';
1038 foreach my $file (@dotfiles) {
1039 open(FILEHANDLE, "make/template/$file") or die "Can't open make/template/$file: $!";
1040 $_ = join '', <FILEHANDLE>;
1043 $config{BUILD_DIR} ||= resolve_directory($config{ME}."/build");
1046 CC SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR UID
1047 STARTSCRIPT DESTINATION EXTRA_DIR SOCKETENGINE
1049 s/\@$var\@/$config{$var}/g;
1051 s/\@EXECUTABLE\@/$exe/ if defined $exe;
1052 s/\@VERSION\@/$version/ if defined $version;
1054 if ($file eq 'main.mk') {
1055 print "Writing \e[1;32mGNUmakefile\e[0m ...\n";
1058 s/\@IFDEF (\S+)/ifdef $1/g;
1059 s/\@IFNDEF (\S+)/ifndef $1/g;
1060 s/\@IFEQ (\S+) (\S+)/ifeq ($1,$2)/g;
1061 s/\@ELSIFEQ (\S+) (\S+)/else ifeq ($1,$2)/g;
1064 s/ *\@BSD_ONLY .*\n//g;
1066 s/\@DO_EXPORT (.*)/export $1/g;
1067 open MKF, '>GNUmakefile' or die "Can't write to GNUmakefile: $!";
1071 print "Writing \e[1;32mBSDmakefile\e[0m ...\n";
1073 s/\@IFDEF (\S+)/.if defined($1)/g;
1074 s/\@IFNDEF (\S+)/.if !defined($1)/g;
1075 s/\@IFEQ (\S+) (\S+)/.if $1 == $2/g;
1076 s/\@ELSIFEQ (\S+) (\S+)/.elif $1 == $2/g;
1080 s/ *\@GNU_ONLY .*\n//g;
1082 $mk_tmp =~ s#\@DO_EXPORT (.*)#"MAKEENV += ".join ' ', map "$_='\${$_}'", split /\s/, $1#eg;
1083 open MKF, '>BSDmakefile' or die "Can't write to BSDmakefile: $!";
1087 print "Writing \e[1;32m$file\e[0m ...\n";
1088 open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
1089 print FILEHANDLE $_;
1094 chmod 0755, 'inspircd';
1100 for my $mod (@modlist) {
1101 getcompilerflags("src/modules/m_$mod.cpp");
1102 getlinkerflags("src/modules/m_$mod.cpp");
1106 sub prepare_dynamic_makefile
1112 $config{USE_EPOLL} = 0;
1116 $config{USE_KQUEUE} = 0;
1120 $config{USE_PORTS} = 0;
1124 # Routine to list out the extra/ modules that have been enabled.
1125 # Note: when getting any filenames out and comparing, it's important to lc it if the
1126 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1127 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1128 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1129 sub list_extras () {
1132 my $srcdir = File::Spec->catdir("src", "modules");
1133 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1136 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1137 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1140 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1141 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1144 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1146 EXTRA: for my $extra (@extras) {
1147 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1148 next if ($extra eq '.svn');
1149 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1150 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1151 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1152 if (-l $abs_source) {
1153 # Symlink, is it in the right place?
1154 my $targ = readlink($abs_source);
1155 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1156 if ($abs_targ eq $abs_extra) {
1157 $extras{$extra} = "\e[32;1menabled\e[0m";
1159 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1161 } elsif (-e $abs_source) {
1162 my ($devext, $inoext) = stat($abs_extra);
1163 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1165 if ($devsrc == $devext && $inosrc == $inoext) {
1166 $extras{$extra} = "\e[32;1menabled\e[0m";
1168 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1171 open my $extfd, "<", $abs_extra;
1172 open my $srcfd, "<", $abs_source;
1174 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1175 $extras{$extra} = "\e[32;1menabled\e[0m";
1177 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1181 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1184 # Now let's add dependency info
1185 for my $extra (keys(%extras)) {
1186 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1187 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1188 my @deps = split / +/, getdependencies($abs_extra);
1189 for my $dep (@deps) {
1190 if (exists($extras{$dep})) {
1191 my $ref = \$extras{$dep}; # Take reference.
1192 if ($$ref !~ m/needed by/) {
1193 # First dependency found.
1194 if ($$ref =~ m/enabled/) {
1195 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1197 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1198 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1201 if ($$ref =~ m/enabled/) {
1202 $$ref .= ", \e[32;1m$extra\e[0m";
1204 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1210 for my $extra (sort {$a cmp $b} keys(%extras)) {
1211 my $text = $extras{$extra};
1212 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1213 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1215 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1218 return keys(%extras) if wantarray; # Can be used by manage_extras.
1221 sub enable_extras (@) {
1223 for my $extra (@extras) {
1224 my $extrapath = "src/modules/extra/$extra";
1225 if (!-e $extrapath) {
1226 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1229 my $source = "src/modules/$extra";
1231 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1234 # Get dependencies, and add them to be processed.
1235 my @deps = split / +/, getdependencies($extrapath);
1236 for my $dep (@deps) {
1237 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1238 if (!-e "src/modules/$dep") {
1239 if (-e "src/modules/extra/$dep") {
1240 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1243 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";
1247 print "Enabling $extra ... \n";
1248 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1252 sub disable_extras (@)
1254 opendir my $dd, "src/modules/extra/";
1255 my @files = readdir($dd);
1258 EXTRA: for my $extra (@extras) {
1259 my $extrapath = "src/modules/extra/$extra";
1260 my $source = "src/modules/$extra";
1261 if (!-e $extrapath) {
1262 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1265 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1266 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";
1269 # Check if anything needs this.
1270 for my $file (@files) {
1271 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1272 # File depends on this extra...
1273 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1274 # And is both enabled and not about to be disabled.
1275 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1276 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1282 print "Disabling $extra ... \n";
1283 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";