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_ipv6, $opt_ipv6links, $opt_noipv6links, $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 'enable-ipv6' => \$opt_ipv6,
73 'enable-remote-ipv6' => \$opt_ipv6links,
74 'disable-remote-ipv6' => \$opt_noipv6links,
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 'library-dir=s' => \$opt_library_dir,
83 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
84 'help' => sub { showhelp(); },
85 'update' => sub { update(); },
86 'svnupdate' => sub { svnupdate(); },
87 'clean' => sub { clean(); },
88 'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
89 'enable-extras=s@' => \@opt_enableextras, # ^
90 'disable-extras=s@' => \@opt_disableextras, # ^
91 'generate-openssl-cert' => sub { make_openssl_cert(); exit(0); },
92 'generate-gnutls-cert' => sub { make_gnutls_cert(); exit(0); }
95 if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
96 @opt_enableextras = split /,/, join(',', @opt_enableextras);
97 @opt_disableextras = split /,/, join(',', @opt_disableextras);
98 enable_extras(@opt_enableextras);
99 disable_extras(@opt_disableextras);
101 print "Remember: YOU are responsible for making sure any libraries needed have been installed!\n";
105 our $non_interactive = (
106 (defined $opt_library_dir) ||
107 (defined $opt_base_dir) ||
108 (defined $opt_config_dir) ||
109 (defined $opt_module_dir) ||
110 (defined $opt_base_dir) ||
111 (defined $opt_binary_dir) ||
112 (defined $opt_nointeractive) ||
114 (defined $opt_ipv6) ||
115 (defined $opt_ipv6links) ||
116 (defined $opt_noipv6links) ||
117 (defined $opt_kqueue) ||
118 (defined $opt_epoll) ||
119 (defined $opt_ports) ||
120 (defined $opt_use_openssl) ||
121 (defined $opt_nokqueue) ||
122 (defined $opt_noepoll) ||
123 (defined $opt_noports) ||
124 (defined $opt_maxbuf) ||
125 (defined $opt_use_gnutls) ||
126 (defined $opt_freebsd_port)
128 our $interactive = !$non_interactive;
130 chomp(our $topdir = getcwd());
131 our $this = resolve_directory($topdir); # PWD, Regardless.
132 our @modlist = (); # Declare for Module List..
133 our %config = (); # Initiate Configuration Hash..
134 $config{ME} = resolve_directory($topdir); # Present Working Directory
136 $config{BASE_DIR} = $config{ME};
138 if (defined $opt_base_dir)
140 $config{BASE_DIR} = $opt_base_dir;
143 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Directory
144 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
145 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
146 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
148 if (defined $opt_config_dir)
150 $config{CONFIG_DIR} = $opt_config_dir;
152 if (defined $opt_module_dir)
154 $config{MODULE_DIR} = $opt_module_dir;
156 if (defined $opt_binary_dir)
158 $config{BINARY_DIR} = $opt_binary_dir;
160 if (defined $opt_library_dir)
162 $config{LIBRARY_DIR} = $opt_library_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 # no, let's not change these.
201 $config{OPTIMITEMP} = "0"; # Default Optimisation Value
202 if (!defined $opt_disable_debug)
204 $config{OPTIMISATI} = "-g1"; # Optimisation Flag
208 $config{OPTIMISATI} = "-O2"; # DEBUGGING OFF!
211 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
212 $config{HAS_STDINT} = "false"; # stdint.h check
213 $config{USE_KQUEUE} = "y"; # kqueue enabled
214 if (defined $opt_kqueue)
216 $config{USE_KQUEUE} = "y";
218 if (defined $opt_nokqueue)
220 $config{USE_KQUEUE} = "n";
222 $config{USE_POLL} = "y"; # poll enabled
223 $config{USE_EPOLL} = "y"; # epoll enabled
224 if (defined $opt_epoll)
226 $config{USE_EPOLL} = "y";
228 if (defined $opt_noepoll)
230 $config{USE_EPOLL} = "n";
232 $config{USE_PORTS} = "y"; # epoll enabled
233 if (defined $opt_ports)
235 $config{USE_PORTS} = "y";
237 if (defined $opt_noports)
239 $config{USE_PORTS} = "n";
241 $config{IPV6} = "n"; # IPv6 support (experimental)
242 if (defined $opt_ipv6)
246 $config{SUPPORT_IP6LINKS} = "y"; # IPv4 supporting IPv6 links (experimental)
247 if (defined $opt_ipv6links)
249 $config{SUPPORT_IP6LINKS} = "y";
251 if (defined $opt_noipv6links)
253 $config{SUPPORT_IP6LINKS} = "n";
255 chomp($config{GCCVER} = `g++ -dumpversion | cut -c 1`); # Major GCC Version
256 chomp($config{GCCMINOR} = `g++ -dumpversion | cut -c 3`);
257 $config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
258 $config{OSNAME} = $^O; # Operating System Name
259 $config{IS_DARWIN} = "NO"; # Is OSX?
260 $config{STARTSCRIPT} = "inspircd"; # start script?
261 $config{DESTINATION} = "BASE"; # Is target path.
262 $config{EXTRA_DIR} = ""; # Is empty.
263 if ($config{OSNAME} =~ /darwin/i)
265 $config{IS_DARWIN} = "YES";
266 $config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
267 $config{DESTINATION} = "LAUNCHDPATH"; # Is OSX target.
268 $config{EXTRA_DIR} = " launchd_dir"; # Is OSX specific path.
270 $config{CC} = "g++"; # C++ compiler
273 $config{CC} = $opt_cc;
275 our $exec = $config{CC} . " -dumpversion | cut -c 1";
276 chomp($config{GCCVER} = `$exec`); # Major GCC Version
277 $exec = $config{CC} . " -dumpversion | cut -c 3";
278 chomp($config{GCCMINOR} = `$exec`);
279 $config{MAXBUF} = "512"; # Max buffer size
281 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)([a-z])?(\-[a-z][0-9])?$/) {
282 $config{HAS_OPENSSL} = $1;
284 $config{HAS_OPENSSL} = "";
287 if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
288 print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
292 # Get and Set some important vars..
297 unlink(".config.cache");
300 our ($has_epoll, $has_ports, $has_kqueue) = (0, 0, 0);
305 chomp($topdir = getcwd());
306 $this = resolve_directory($topdir); # PWD, Regardless.
308 # Does the cache file exist?
310 # No, No it doesn't.. *BASH*
311 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
314 # We've Loaded the cache file and all our variables..
315 print "Updating files...\n";
317 if (defined($opt_disable_debug) && $opt_disable_debug == 1)
319 print "Disabling debug information (-g).\n";
320 $config{OPTIMISATI} = "";
323 $has_epoll = $config{HAS_EPOLL};
324 $has_ports = $config{HAS_PORTS};
325 $has_kqueue = $config{HAS_KQUEUE};
334 print "Configure update failed: $@\n";
342 open(FH,"<.svn/entries") or $fail = 1;
344 print "This is not an SVN copy of InspIRCd.\n";
351 open my $fd, "-|", "svn update";
352 my $configurechanged = 0; # Needs ./configure -update
353 my $rootincchanged = 0;
355 while (defined(my $line = <$fd>))
359 $line =~ m/^([ADUCG])\s+(.*)$/ or next;
360 ($action, $file) = ($1, $2);
363 push @conflicted, $file;
364 if ($file eq "configure")
366 $configurechanged = 1;
368 elsif ($file =~ m/^\..*\.inc$/)
373 elsif ($action eq "U" || $action eq "G")
375 if ($file eq "configure")
377 $configurechanged = 1;
379 elsif ($file =~ m/^\..*\.inc$/)
385 unless (close $fd) # close() waits for exit and returns false if the command failed
389 print STDERR "Problem updating from SVN, please check above for errors\n";
393 print STDERR "Failed to run SVN: $!\n";
397 if (scalar(@conflicted) > 0)
399 print STDERR "\e[0;33;1mERROR:\e[0m You have local modifications which conflicted with the updates from SVN\n";
400 print STDERR "Configure is not able to complete the update. Please resolve these conflicts, then run ./configure -update\n";
401 print "Conflicted files: " . join ", ", @conflicted . "\n";
404 if ($configurechanged)
406 system("perl configure -update");
410 print "No need to update Makefiles.\n";
412 if (defined $opt_rebuild) {
413 system("make install");
421 $fail ||= system "$config{CC} -o test_$feature make/check_$feature.cpp >/dev/null 2>&1";
422 $fail ||= system "./test_$feature";
423 unlink "test_$feature";
427 print "Running non-interactive configure...\n" unless $interactive;
428 print "Checking for cache from previous configure... ";
429 print ((!getcache()) ? "not found\n" : "found\n");
430 print "Checking operating system version... ";
431 print getosflags() . "\n";
433 printf "Checking if stdint.h exists... ";
434 $config{HAS_STDINT} = "true";
436 open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
437 if ($config{HAS_STDINT} eq "true") {
440 print "yes\n" if $config{HAS_STDINT} eq "true";
441 print "no\n" if $config{HAS_STDINT} eq "false";
443 printf "Checking if strlcpy exists... ";
444 # Perform the strlcpy() test..
445 $config{HAS_STRLCPY} = "false";
447 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
449 while (defined(my $line = <STRLCPY>)) {
451 # try and find the delcaration of:
452 # size_t strlcpy(...)
453 if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
454 $config{HAS_STRLCPY} = "true";
459 print "yes\n" if $config{HAS_STRLCPY} eq "true";
460 print "no\n" if $config{HAS_STRLCPY} eq "false";
462 printf "Checking if kqueue exists... ";
465 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
467 while (defined(my $line = <KQUEUE>)) {
469 # try and find the delcaration of:
471 if ($line =~ /int(\0x9|\s)+kqueue/) {
477 print "yes\n" if $has_kqueue == 1;
478 print "no\n" if $has_kqueue == 0;
480 printf "Checking for epoll support... ";
481 $has_epoll = test_compile('epoll');
482 print $has_epoll ? "yes\n" : "no\n";
484 printf "Checking for eventfd support... ";
485 $config{HAS_EVENTFD} = test_compile('eventfd') ? 'true' : 'false';
486 print $config{HAS_EVENTFD} eq 'true' ? "yes\n" : "no\n";
488 printf "Checking if Solaris I/O completion ports are available... ";
490 our $system = `uname -s`;
492 $has_ports = 1 if ($system eq "SunOS");
495 my $kernel = `uname -r`;
497 if (($kernel !~ /^5\.1./)) {
501 print "yes\n" if $has_ports == 1;
502 print "no\n" if $has_ports == 0;
504 $config{HAS_EPOLL} = $has_epoll;
505 $config{HAS_KQUEUE} = $has_kqueue;
507 printf "Checking for libgnutls... ";
508 if (defined($config{HAS_GNUTLS}) && (($config{HAS_GNUTLS}) || ($config{HAS_GNUTLS} eq "y"))) {
509 if (defined($gnutls_ver) && ($gnutls_ver ne "")) {
511 $config{HAS_GNUTLS} = "y";
514 $config{HAS_GNUTLS} = "n";
518 $config{HAS_GNUTLS} = "n";
521 printf "Checking for openssl... ";
522 if (defined($config{HAS_OPENSSL}) && (($config{HAS_OPENSSL}) || ($config{HAS_OPENSSL} eq "y"))) {
523 if (defined($openssl_ver) && ($openssl_ver ne "")) {
525 $config{HAS_OPENSSL} = "y";
528 $config{HAS_OPENSSL} = "n";
532 $config{HAS_OPENSSL} = "n";
535 printf "Checking if you are running an ancient, unsupported OS... ";
536 if ($config{OSNAME} =~ /FreeBSD/i)
538 my $version = `uname -r`;
539 if ($version =~ /^4\./)
541 my $foundit = `ls -l /usr/local/lib/libgnugetopt* | wc -l`;
544 # ICKY ICKY ICK, FREEBSD 4.x! GET AN UPGRADE!
545 $config{CRAQ} = "-L/usr/local/lib -lgnugetopt -DHAVE_DECL_GETOPT=1";
546 print "yes (upgrade ffs, freebsd 4 is *way* out of date)\n";
550 print "\n\nERROR: You require libgnugetopt (from ports or packages) to build InspIRCd on FreeBSD 4.11.\n";
556 print "no ($version)\n";
562 print "no ($config{OSNAME})\n";
565 print "Checking for upgrades to extra and third party modules... ";
566 system "./modulemanager upgrade";
568 ################################################################################
569 # BEGIN INTERACTIVE PART #
570 ################################################################################
575 print "\e[2J\e[0G\e[0d"; # J = Erase in Display, 2 = Entire Screen, (G, d) = Move cursor to (..,..)
578 my $rev = getrevision();
579 # Display Introduction Message..
581 Welcome to the \e[1mInspIRCd\e[0m Configuration program! (\e[1minteractive mode\e[0m)
582 \e[1mPackage maintainers: Type ./configure --help for non-interactive help\e[0m
584 *** If you are unsure of any of these values, leave it blank for ***
585 *** standard settings that will work, and your server will run ***
586 *** using them. Please consult your IRC network admin if in doubt. ***
588 Press \e[1m<RETURN>\e[0m to accept the default for any option, or enter
589 a new value. Please note: You will \e[1mHAVE\e[0m to read the docs
590 dir, otherwise you won't have a config file!
592 Your operating system is: \e[1;32m$config{OSNAME}\e[0m ($wholeos)
593 Your InspIRCd revision ID is \e[1;32mr$rev\e[0m
596 print " (Non-SVN build)";
600 $config{CHANGE_COMPILER} = "n";
601 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";
603 while (($config{GCCVER} < 3) || ($config{GCCVER} eq "")) {
604 print "\e[1;32mIMPORTANT!\e[0m A GCC 2.x compiler has been detected, and
605 should NOT be used. You should probably specify a newer compiler.\n\n";
606 yesno('CHANGE_COMPILER',"Do you want to change the compiler?");
607 if ($config{CHANGE_COMPILER} =~ /y/i) {
608 print "What command do you want to use to invoke your compiler?\n";
609 print "[\e[1;32m$config{CC}\e[0m] -> ";
610 chomp($config{CC} = <STDIN>);
611 if ($config{CC} eq "") {
614 chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
616 chomp($config{GCCVER} = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
617 chomp($config{GCCMINOR} = `$config{CC} -dumpversion | cut -c 3`);
618 print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
619 if ($config{GCCVER} < 3) {
620 print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
624 print "\e[1;32mWARNING!\e[0m Could not execute the compiler you specified. You may want to try again.\n";
631 # Directory Settings..
632 my $tmpbase = $config{BASE_DIR};
633 dir_check("do you wish to install the InspIRCd base", "BASE_DIR");
634 if ($tmpbase ne $config{BASE_DIR}) {
635 $config{CONFIG_DIR} = resolve_directory($config{BASE_DIR}."/conf"); # Configuration Dir
636 $config{MODULE_DIR} = resolve_directory($config{BASE_DIR}."/modules"); # Modules Directory
637 $config{BINARY_DIR} = resolve_directory($config{BASE_DIR}."/bin"); # Binary Directory
638 $config{LIBRARY_DIR} = resolve_directory($config{BASE_DIR}."/lib"); # Library Directory
641 dir_check("are the configuration files", "CONFIG_DIR");
642 dir_check("are the modules to be compiled to", "MODULE_DIR");
643 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
644 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
646 my $chose_hiperf = 0;
648 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?");
650 if ($config{USE_KQUEUE} eq "y") {
655 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?");
657 if ($config{USE_EPOLL} eq "y") {
662 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?");
664 if ($config{USE_PORTS} eq "y") {
669 if (!$chose_hiperf) {
670 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?\n");
671 if ($config{USE_POLL} ne "y")
673 print "No high-performance socket engines are available, or you chose\n";
674 print "not to enable one. Defaulting to select() engine.\n\n";
678 yesno('IPV6',"Would you like to build InspIRCd with IPv6 support?");
681 if ($config{IPV6} eq "y") {
682 print "You have chosen to build an \e[1;32mIPV6-enabled\e[0m server.\nTo accept IPV4 users, you can still use IPV4 addresses\nin your port bindings..\n\n";
683 $config{SUPPORT_IP6LINKS} = "y";
685 yesno('SUPPORT_IP6LINKS',"You have chosen to build an \e[1;32mIPV4-only\e[0m server.\nWould you like to enable support for linking to IPV6-enabled\nInspIRCd servers? If you are using a recent operating system and are\nunsure, answer yes. If you answer 'no' here, your InspIRCd server will\nbe unable to parse IPV6 addresses (e.g. for CIDR bans)\n\nEnable linking to servers which have IPV6 enabled?");
689 $config{USE_FREEBSD_BASE_SSL} = "n";
690 $config{USE_FREEBSD_PORTS_SSL} = "n";
691 if ($config{HAS_OPENSSL_PORT} ne "")
693 $config{USE_FREEBSD_PORTS_SSL} = "y";
694 print "I have detected the OpenSSL FreeBSD port installed on your system,\n";
695 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";
696 yesno('USE_FREEBSD_PORTS_SSL', "Do you want to use the FreeBSD ports version?");
698 $config{USE_FREEBSD_BASE_SSL} = "y" if ($config{USE_FREEBSD_PORTS_SSL} eq "n");
700 if ($config{USE_FREEBSD_BASE_SSL} eq "n")
702 # update to port version
703 $openssl_ver = $config{HAS_OPENSSL_PORT};
708 $config{USE_FREEBSD_BASE_SSL} = "y" if ($^O eq "freebsd");
711 $config{USE_SSL} = "n";
713 if ($config{HAS_GNUTLS} eq "y" || $config{HAS_OPENSSL} eq "y")
715 print "Detected GnuTLS version: \e[1;32m" . $gnutls_ver . "\e[0m\n";
716 print "Detected OpenSSL version: \e[1;32m" . $openssl_ver . "\e[0m\n\n";
718 yesno('USE_SSL', "One or more SSL libraries detected. Would you like to enable SSL support?");
719 if ($config{USE_SSL} eq "y")
721 if ($config{HAS_GNUTLS} eq "y")
723 yesno('USE_GNUTLS',"Would you like to enable SSL with m_ssl_gnutls? (recommended)");
724 if ($config{USE_GNUTLS} eq "y")
726 print "\nUsing GnuTLS SSL module.\n";
730 if ($config{HAS_OPENSSL} eq "y")
732 yesno('USE_OPENSSL', "Would you like to enable SSL with m_ssl_openssl?");
733 if ($config{USE_OPENSSL} eq "y")
735 print "\nUsing OpenSSL SSL module.\nYou will get better performance if you move to GnuTLS in the future.\n";
742 print "\nCould not detect OpenSSL or GnuTLS. Make sure pkg-config is installed if\n";
743 print "you intend to use OpenSSL, or that GnuTLS is in your path if you intend\nto use GnuTLS.\n\n";
749 if (($config{USE_GNUTLS} eq "y") && ($config{HAS_GNUTLS} ne "y"))
751 print "Sorry, but i couldn't detect gnutls. Make sure gnutls-config is in your path.\n";
754 if (($config{USE_OPENSSL} eq "y") && ($config{HAS_OPENSSL} ne "y"))
756 print "Sorry, but i couldn't detect openssl. Make sure openssl is in your path.\n";
761 $config{CERTGEN} ||= 'y';
762 yesno('CERTGEN',"Would you like generate SSL certificates now?") if ($interactive && ($config{USE_GNUTLS} eq "y" || $config{USE_OPENSSL} eq "y"));
764 if ($config{USE_GNUTLS} eq "y") {
765 unless (-r "src/modules/m_ssl_gnutls.cpp") {
766 print "Symlinking src/modules/m_ssl_gnutls.cpp from extra/\n";
767 symlink "extra/m_ssl_gnutls.cpp", "src/modules/m_ssl_gnutls.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 Private Key may take some time, go grab a *
775 * Coffee. Even better, to generate some more entropy if it *
776 * is taking a while, open another console and type du / a *
777 * few times and get that HD going :) Then answer the *
778 * Questions which follow. If you are unsure, just hit enter *
779 *************************************************************\n\n";
780 $failed = make_gnutls_cert();
782 print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
784 print "\nCertificate generation complete, copying to config directory... ";
785 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
786 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
791 print "SSL Certificates found, skipping.\n\n";
796 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
800 if ($config{USE_OPENSSL} eq "y") {
801 unless (-r "src/modules/m_ssl_openssl.cpp") {
802 print "Symlinking src/modules/m_ssl_openssl.cpp from extra/\n";
803 symlink "extra/m_ssl_openssl.cpp", "src/modules/m_ssl_openssl.cpp" or print STDERR "Symlink failed: $!";
806 if ($interactive && $config{CERTGEN} eq 'y')
808 unless (-r "$config{CONFIG_DIR}/key.pem" && -r "$config{CONFIG_DIR}/cert.pem") {
809 print "SSL Certificates Not found, Generating.. \n\n
810 *************************************************************
811 * Generating the certificates may take some time, go grab a *
812 * coffee, or something. *
813 *************************************************************\n\n";
815 print "\nCertificate generation complete, copying to config directory... ";
816 File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
817 File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
818 File::Copy::move("dhparams.pem", "$config{CONFIG_DIR}/dhparams.pem") or print STDERR "Could not copy dhparams.pem!\n";
821 print "SSL Certificates found, skipping.\n\n"
826 print "Skipping SSL certificate generation\nin non-interactive mode.\n\n";
829 if (($config{USE_GNUTLS} eq "n") && ($config{USE_OPENSSL} eq "n")) {
830 print "Skipping SSL Certificate generation, SSL support is not available.\n\n";
838 print "To build your server with these settings, please type '\e[1;32m$config{MAKEPROG}\e[0m' now.\n";
839 if (($config{USE_GNUTLS} eq "y") || ($config{USE_OPENSSL} eq "y")) {
840 print "Please note: for \e[1;32mSSL support\e[0m you will need to load required\n";
841 print "modules in your config. This configure script has added those modules to the\n";
842 print "build process. For more info please refer to:\n";
843 print "\e[1;32mhttp://wiki.inspircd.org/Installation_From_Tarball\e[0m\n";
845 print "*** \e[1;32mRemember to edit your configuration files!!!\e[0m ***\n\n\n";
846 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
847 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";
850 if ($config{GCCVER} < "3") {
852 \e[1;32mWARNING!\e[0m You are attempting to compile InspIRCd on GCC 2.x!
853 GCC 2.x series compilers only had partial (read as broken) C++ support, and
854 your compile will most likely fail horribly! If you have any problems, do NOT
855 report them to the bugtracker or forums without first upgrading your compiler
856 to a newer 3.x or 4.x (or whatever is available currently) version.
860 ################################################################################
862 ################################################################################
864 # Retrieves the .config.cache file, and loads values into the main config hash.
865 open(CACHE, ".config.cache") or return 0;
868 # Ignore Blank lines, and comments..
871 my ($key, $value) = split("=", $_, 2);
872 $value =~ /^\"(.*)\"$/;
873 # Do something with data here!
881 # Dump the contents of %config
882 print "Writing \e[1;32mcache file\e[0m for future ./configures ...\n";
883 open(FILEHANDLE, ">.config.cache");
884 foreach my $key (keys %config) {
885 print FILEHANDLE "$key=\"$config{$key}\"\n";
891 my ($desc, $hash_key) = @_;
894 print "In what directory $desc?\n";
895 print "[\e[1;32m$config{$hash_key}\e[0m] -> ";
896 chomp(my $var = <STDIN>);
898 $var = $config{$hash_key};
900 if ($var =~ /^\~\/(.+)$/) {
901 # Convert it to a full path..
902 $var = resolve_directory($ENV{HOME} . "/" . $1);
904 elsif ((($config{OSNAME} =~ /MINGW32/i) and ($var !~ /^[A-Z]{1}:\\.*/)) and (substr($var,0,1) ne "/"))
906 # Assume relative Path was given.. fill in the rest.
907 $var = $this . "/$var";
910 $var = resolve_directory($var);
912 print "$var does not exist. Create it?\n[\e[1;32my\e[0m] ";
913 chomp(my $tmp = <STDIN>);
914 if (($tmp eq "") || ($tmp =~ /^y/i)) {
915 # Attempt to Create the Dir..
918 File::Path::mkpath($var, 0, 0777);
921 unless (defined($chk) && -d $var) {
922 print "Unable to create directory. ($var)\n\n";
927 # They said they don't want to create, and we can't install there.
933 # Target exists, but is not a directory.
934 print "File $var exists, but is not a directory.\n\n";
938 # Either Dir Exists, or was created fine.
939 $config{$hash_key} = $var;
949 # Beware: Linux sets it's own cflags below for some retarded reason
950 $config{LDLIBS} = "-pthread -lstdc++";
951 $config{FLAGS} = "-pipe -fPIC -Woverloaded-virtual -Wshadow -Wformat=2 -Wmissing-format-attribute -Wall $config{OPTIMISATI}";
952 $config{DEVELOPER} = "-pipe -fPIC -Woverloaded-virtual -Wshadow -Wall -Wformat=2 -Wmissing-format-attribute -g";
953 $SHARED = "-shared -export-dynamic";
954 $config{MAKEPROG} = "make";
956 if ($config{OSNAME} =~ /darwin/i) {
957 $config{FLAGS} = "-pipe -DDARWIN -frtti -fPIC -Wall $config{OPTIMISATI}";
958 $SHARED = "-bundle -twolevel_namespace -undefined dynamic_lookup";
959 $config{LDLIBS} = "-ldl -pthread -lstdc++";
962 if ($config{OSNAME} =~ /OpenBSD/i) {
963 $config{MAKEPROG} = "gmake";
964 # apparantly (Dagonet says) that this causes problems, so let's try without it.
965 # $config{LDLIBS} = $config{LDLIBS} . " -lunwind";
966 chomp(my $foo = `eg++ -dumpversion | cut -c 1`);
967 # theyre running the package version of gcc (eg++)... detect it and set up its version numbers.
968 # if theyre not running this, configure lets the build continue but they probably wont manage to
969 # compile as this standard version is 2.95.3!
971 $config{CC} = "eg++";
972 chomp($config{GCCVER} = `eg++ -dumpversion | cut -c 1`); # we must redo these if we change the compiler path
973 chomp($config{GCCMINOR} = `eg++ -dumpversion | cut -c 3`);
978 if ($config{OSNAME} =~ /Linux/i) {
979 $config{LDLIBS} = "-ldl -lstdc++ -pthread";
980 # $config{FLAGS} = "-fPIC -Woverloaded-virtual -Wshadow -Wall $config{OPTIMISATI}";
981 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
982 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
983 $config{LDLIBS} .= " " . $ENV{LDFLAGS} if exists($ENV{LDFLAGS});
984 $config{MAKEPROG} = "make";
987 if ($config{OSNAME} =~ /FreeBSD/i) {
988 $config{FLAGS} .= " " . $ENV{CXXFLAGS} if exists($ENV{CXXFLAGS});
989 $config{LDLIBS} .= " " . $ENV{LDLIBS} if exists($ENV{LDLIBS});
990 $config{LDLIBS} .= " " . $ENV{LDFLAGS} if exists($ENV{LDFLAGS});
993 if ($config{OSNAME} =~ /SunOS/i or $config{OSNAME} =~ /solaris/i)
995 # solaris/sunos needs these
996 # socket = bsd sockets api
998 # rt = POSIX realtime extensions
999 # resolv = inet_aton only (why isnt this in nsl?!)
1000 $config{MAKEPROG} = "gmake";
1001 $config{LDLIBS} .= " -lsocket -lnsl -lrt -lresolv -pthread";
1005 if($config{OSNAME} =~ /MINGW32/i)
1007 # All code is position-independent on windows
1008 $config{FLAGS} =~ s/-fPIC //;
1012 return $config{OSNAME};
1015 my ($mliflags, $mfrules, $mobjs, $mfcount) = ("", "", "", 0);
1018 my($writeheader) = @_;
1019 # First File.. inspircd_config.h
1020 chomp(my $incos = `uname -n -s -r`);
1021 chomp(my $version = `sh src/version.sh`);
1022 chomp(my $revision2 = getrevision());
1023 if ($writeheader == 1)
1025 print "Writing \e[1;32minspircd_config.h\e[0m\n";
1026 open(FILEHANDLE, ">include/inspircd_config.h.tmp");
1027 print FILEHANDLE <<EOF;
1028 /* Auto generated by configure, do not modify! */
1029 #ifndef __CONFIGURATION_AUTO__
1030 #define __CONFIGURATION_AUTO__
1032 /* this is for windows support. */
1033 #define CoreExport /**/
1034 #define DllExport /**/
1036 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
1037 #define MOD_PATH "$config{MODULE_DIR}"
1038 #define SOMAXCONN_S "$config{_SOMAXCONN}"
1039 #define OPTIMISATION $config{OPTIMITEMP}
1040 #define LIBRARYDIR "$config{LIBRARY_DIR}"
1041 #define ENTRYPOINT int main(int argc, char** argv)
1044 print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
1046 if ($config{OSNAME} =~ /SunOS/i) {
1047 print FILEHANDLE "#define IS_SOLARIS\n";
1049 if ($config{OSNAME} =~ /MINGW32/i) {
1050 print FILEHANDLE "#define IS_MINGW\n";
1052 if ($config{GCCVER} >= 3) {
1053 print FILEHANDLE "#define GCC3\n";
1056 (($config{GCCVER} == 4) && ($config{GCCMINOR} >= 3))
1058 ($config{GCCVER} > 4)
1060 print FILEHANDLE "#define HASHMAP_DEPRECATED\n";
1062 if ($config{HAS_STRLCPY} eq "true") {
1063 print FILEHANDLE "#define HAS_STRLCPY\n";
1065 if ($config{HAS_STDINT} eq "true") {
1066 print FILEHANDLE "#define HAS_STDINT\n";
1068 if ($config{IPV6} =~ /y/i) {
1069 print FILEHANDLE "#define IPV6\n";
1071 if ($config{SUPPORT_IP6LINKS} =~ /y/i) {
1072 print FILEHANDLE "#define SUPPORT_IP6LINKS\n";
1074 if ($config{HAS_EVENTFD} eq 'true') {
1075 print FILEHANDLE "#define HAS_EVENTFD\n";
1078 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
1079 print FILEHANDLE "#define USE_KQUEUE\n";
1080 $config{SOCKETENGINE} = "socketengine_kqueue";
1083 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
1084 print FILEHANDLE "#define USE_EPOLL\n";
1085 $config{SOCKETENGINE} = "socketengine_epoll";
1088 if (($has_ports) && ($config{USE_PORTS} eq "y")) {
1089 print FILEHANDLE "#define USE_PORTS\n";
1090 $config{SOCKETENGINE} = "socketengine_ports";
1093 # user didn't choose either epoll or select for their OS.
1094 # default them to USE_SELECT (ewwy puke puke)
1096 print "no hi-perf, " . $config{USE_POLL};
1097 if ($config{USE_POLL} eq "y")
1099 print FILEHANDLE "#define USE_POLL\n";
1100 $config{SOCKETENGINE} = "socketengine_poll";
1104 print FILEHANDLE "#define USE_SELECT\n";
1105 $config{SOCKETENGINE} = "socketengine_select";
1108 print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
1111 open(FILEHANDLE, ">include/inspircd_se_config.h.tmp");
1112 print FILEHANDLE <<EOF;
1113 /* Auto generated by configure, do not modify or commit to svn! */
1114 #ifndef __CONFIGURATION_SOCKETENGINE__
1115 #define __CONFIGURATION_SOCKETENGINE__
1117 #include "socketengines/$config{SOCKETENGINE}.h"
1123 open(FILEHANDLE, ">include/inspircd_version.h.tmp");
1124 print FILEHANDLE <<EOF;
1125 #define VERSION "$version"
1126 #define REVISION "$revision2"
1127 #define SYSTEM "$incos"
1131 for my $file (qw(include/inspircd_config.h include/inspircd_se_config.h include/inspircd_version.h)) {
1133 open my $fh1, $file or $diff = 1;
1134 open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
1138 if (defined($line1) != defined($line2)) {
1140 } elsif (!defined $line1) {
1143 $diff = ($line1 ne $line2);
1148 rename "$file.tmp", $file;
1155 # Write all .in files.
1158 my $exe = "inspircd";
1160 # Do this once here, and cache it in the .*.inc files,
1161 # rather than attempting to read src/version.sh from
1162 # compiled code -- we might not have the source to hand.
1163 # Fix for bug#177 by Brain.
1165 chomp($version = `sh ./src/version.sh`);
1166 chomp(my $revision = getrevision());
1167 $version = "$version(r$revision)";
1169 # We can actually parse any file starting with . and ending with .inc,
1170 # but right now we only parse .inspircd.inc to form './inspircd'
1171 prepare_dynamic_makefile();
1173 print "Writing \e[1;32mMakefiles\e[0m\n";
1175 opendir(DIRHANDLE, $this);
1177 foreach my $name (sort readdir(DIRHANDLE)) {
1178 if ($name =~ /^\.(.+)\.inc$/) {
1181 # Bug #353, omit this on non-darwin
1182 next if (($config{OSNAME} !~ /darwin/) && ($file eq "org.inspircd.plist"));
1184 # All .name.inc files need parsing!
1185 open(FILEHANDLE, ".$file.inc") or die ("Can't open .$file.inc");
1186 $_ = join '', <FILEHANDLE>;
1189 print "Writing \e[1;32m$file\e[0m ...\n";
1191 CC FLAGS DEVELOPER LDLIBS BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR LIBRARY_DIR
1192 STARTSCRIPT DESTINATION EXTRA_DIR SOCKETENGINE CORE_FLAGS
1194 s/\@$var\@/$config{$var}/g;
1196 s/\@EXECUTABLE\@/$exe/ if defined $exe;
1197 s/\@VERSION\@/$version/ if defined $version;
1199 if ($file eq 'Makefile') {
1201 s/\@IFDEF (\S+)/ifdef $1/g;
1202 s/\@IFNDEF (\S+)/ifndef $1/g;
1205 s/ *\@BSD_ONLY .*\n//g;
1207 s/\@DO_EXPORT (.*)/export $1/g;
1208 open MKF, '>GNUmakefile' or die "Can't write to GNUmakefile: $!";
1212 s/\@IFDEF (\S+)/.if defined($1)/g;
1213 s/\@IFNDEF (\S+)/.if !defined($1)/g;
1217 s/ *\@GNU_ONLY .*\n//g;
1219 $mk_tmp =~ s#\@DO_EXPORT (.*)#"MAKEENV += ".join ' ', map "$_='\${$_}'", split /\s/, $1#eg;
1220 open MKF, '>BSDmakefile' or die "Can't write to BSDmakefile: $!";
1224 open(FILEHANDLE, ">$file") or die("Can't write to $file: $!\n");
1225 print FILEHANDLE $_;
1230 closedir(DIRHANDLE);
1232 # Make inspircd executable!
1233 chmod 0744, 'inspircd';
1236 sub prepare_dynamic_makefile
1242 $config{USE_EPOLL} = 0;
1246 $config{USE_KQUEUE} = 0;
1250 $config{USE_PORTS} = 0;
1253 if ($config{IS_DARWIN} eq "YES")
1255 $config{CORE_FLAGS} = '-dynamic -bind_at_load -L.';
1259 $config{CORE_FLAGS} = (defined $config{CRAQ} ? $config{CRAQ}. ' ' : "").'-rdynamic -L.'
1263 # Routine to list out the extra/ modules that have been enabled.
1264 # Note: when getting any filenames out and comparing, it's important to lc it if the
1265 # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
1266 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
1267 # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
1268 sub list_extras () {
1271 my $srcdir = File::Spec->catdir("src", "modules");
1272 my $abs_srcdir = File::Spec->rel2abs($srcdir);
1275 opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
1276 my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1279 opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
1280 my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
1283 my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
1285 EXTRA: for my $extra (@extras) {
1286 next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
1287 next if ($extra eq '.svn');
1288 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1289 my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
1290 next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
1291 if (-l $abs_source) {
1292 # Symlink, is it in the right place?
1293 my $targ = readlink($abs_source);
1294 my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
1295 if ($abs_targ eq $abs_extra) {
1296 $extras{$extra} = "\e[32;1menabled\e[0m";
1298 $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
1300 } elsif (-e $abs_source) {
1301 my ($devext, $inoext) = stat($abs_extra);
1302 my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
1304 if ($devsrc == $devext && $inosrc == $inoext) {
1305 $extras{$extra} = "\e[32;1menabled\e[0m";
1307 $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
1310 open my $extfd, "<", $abs_extra;
1311 open my $srcfd, "<", $abs_source;
1313 if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
1314 $extras{$extra} = "\e[32;1menabled\e[0m";
1316 $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
1320 $extras{$extra} = "\e[33;1mdisabled\e[0m";
1323 # Now let's add dependency info
1324 for my $extra (keys(%extras)) {
1325 next unless $extras{$extra} =~ m/enabled/; # only process enabled extras.
1326 my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
1327 my @deps = split / +/, getdependencies($abs_extra);
1328 for my $dep (@deps) {
1329 if (exists($extras{$dep})) {
1330 my $ref = \$extras{$dep}; # Take reference.
1331 if ($$ref !~ m/needed by/) {
1332 # First dependency found.
1333 if ($$ref =~ m/enabled/) {
1334 $$ref .= " (needed by \e[32;1m$extra\e[0m";
1336 $$ref =~ s/\e\[.*?m//g; # Strip out previous coloring. Will be set in bold+red+blink later.
1337 $$ref .= " (needed by \e[0;32;1;5m$extra\e[0;31;1;5m";
1340 if ($$ref =~ m/enabled/) {
1341 $$ref .= ", \e[32;1m$extra\e[0m";
1343 $$ref .= ", \e[0;32;1;5m$extra\e[0;31;1;5m";
1349 for my $extra (sort {$a cmp $b} keys(%extras)) {
1350 my $text = $extras{$extra};
1351 if ($text =~ m/needed by/ && $text !~ m/enabled/) {
1352 printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
1354 printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
1357 return keys(%extras) if wantarray; # Can be used by manage_extras.
1360 sub enable_extras (@) {
1362 for my $extra (@extras) {
1363 my $extrapath = "src/modules/extra/$extra";
1364 if (!-e $extrapath) {
1365 print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in src/modules/extra\n";
1368 my $source = "src/modules/$extra";
1370 print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in src/modules exists (might already be enabled?)\n";
1373 # Get dependencies, and add them to be processed.
1374 my @deps = split / +/, getdependencies($extrapath);
1375 for my $dep (@deps) {
1376 next if scalar(grep { $_ eq $dep } (@extras)) > 0; # Skip if we're going to be enabling it anyway.
1377 if (!-e "src/modules/$dep") {
1378 if (-e "src/modules/extra/$dep") {
1379 print STDERR "Will also enable extra \e[32;1m$dep\e[0m (needed by \e[32;1m$extra\e[0m)\n";
1382 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";
1386 print "Enabling $extra ... \n";
1387 symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
1391 sub disable_extras (@)
1393 opendir my $dd, "src/modules/extra/";
1394 my @files = readdir($dd);
1397 EXTRA: for my $extra (@extras) {
1398 my $extrapath = "src/modules/extra/$extra";
1399 my $source = "src/modules/$extra";
1400 if (!-e $extrapath) {
1401 print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
1404 if ((! -l $source) || readlink($source) ne "extra/$extra") {
1405 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";
1408 # Check if anything needs this.
1409 for my $file (@files) {
1410 my @deps = split / +/, getdependencies("src/modules/extra/$file");
1411 # File depends on this extra...
1412 if (scalar(grep { $_ eq $extra } @deps) > 0) {
1413 # And is both enabled and not about to be disabled.
1414 if (-e "src/modules/$file" && scalar(grep { $_ eq $file } @extras) < 1) {
1415 print STDERR "Cannot disable \e[32;1m$extra\e[0m : is needed by \e[32;1m$file\e[0m\n";
1421 print "Disabling $extra ... \n";
1422 unlink "src/modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";