2 # InspIRCd Configuration Script
4 # Copyright 2003 The ChatSpike Development Team
5 # <brain@chatspike.net>
6 # <Craig@chatspike.net>
8 # [14:21] Brain: <matrix impression> i know perl-fu!
12 ########################################
14 chomp($topdir = `pwd`);
15 $this = resolve_directory($topdir); # PWD, Regardless.
16 @modlist = (); # Declare for Module List..
17 %config = (); # Initiate Configuration Hash..
18 $config{ME} = resolve_directory($topdir); # Present Working Directory
19 $config{CONFIG_DIR} = resolve_directory($config{ME}."/conf"); # Configuration Directory
20 $config{MODULE_DIR} = resolve_directory($config{ME}."/modules"); # Modules Directory
21 $config{BINARY_DIR} = resolve_directory($config{ME}."/bin"); # Binary Directory
22 $config{LIBRARY_DIR} = resolve_directory($config{ME}."/lib"); # Library Directory
23 $config{OPTIMITEMP} = "0"; # Default Optimisation Value
24 $config{OPTIMISATI} = "-g"; # Optimisation Flag
25 $config{NICK_LENGT} = "32"; # Default Nick Length
26 $config{CHAN_LENGT} = "64"; # Default Channel Name Length
27 $config{MAX_CHANNE} = "20"; # Default Max. Channels per user..
28 $config{MAXI_MODES} = "20"; # Default Max. Number of Modes set at once.
29 $config{HAS_STRLCPY} = "false"; # strlcpy Check.
30 $config{USE_KQUEUE} = "y"; # kqueue enabled
31 $config{USE_EPOLL} = "y"; # epoll enabled
32 chomp($config{MAX_CLIENT_T} = `sh -c \"ulimit -n\"`); # FD Limit
33 chomp($config{GCCVER} = `gcc -dumpversion | cut -c 1`); # Major GCC Version
34 chomp($config{GCC34} = `gcc -dumpversion | cut -c 3`); # Minor GCC Version
35 chomp($config{OSNAME} = `/bin/uname -s`); # Operating System Name
37 if (!$config{OSNAME}) {
38 chomp($config{OSNAME} = `uname -s`);
39 if (!$config{OSNAME}) {
40 $config{OSNAME} = "Unknown";
44 if (!$config{MAX_CLIENT_T}) {
45 $config{MAX_CLIENT_T} = 1024; # Set a reasonable 'Default'
46 $fd_scan_fail = "true"; # Used Later
49 # Get and Set some important vars..
52 my $arg = $ARGV[0]; # Do Some Argument Checks..
53 if ($arg eq "-clean") { `rm -rf .config.cache`; } # Remove the config.cache file.
55 if ($arg eq "-update") {
56 # Does the cache file exist?
58 # No, No it doesn't.. *BASH*
59 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
62 # We've Loaded the cache file and all our variables..
63 print "Updating Files..\n";
71 print "Checking for cache from previous configure...\n";
73 print "Checking operating system version...\n";
76 if (!$config{MAX_CLIENT}) {
77 # If the cache hasn't set the max clients, copy the variable of MAX_CLIENT_T, this
78 # allows us to keep _T for testing purposes. (ie. "Are you sure you want to go
79 # higher than the found value" :))
80 $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
83 printf "Checking if strlcpy exists... ";
84 # Perform the strlcpy() test..
85 $config{HAS_STRLCPY} = "false";
87 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
90 while (chomp($line = <STRLCPY>))
92 # try and find the delcaration of:
94 if (($line =~ /size_t(\0x9|\s)+strlcpy(\0x9|\s)+\(/) || ($line =~ /size_t(\0x9|\s)+strlcpy\(/))
96 $config{HAS_STRLCPY} = "true";
101 print "yes\n" if $config{HAS_STRLCPY} eq "true";
102 print "no\n" if $config{HAS_STRLCPY} eq "false";
104 printf "Checking if kqueue exists... ";
107 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
110 while (chomp($line = <KQUEUE>))
112 # try and find the delcaration of:
114 if (($line =~ /int(\0x9|\s)+kqueue(\0x9|\s)+\(/) || ($line =~ /int(\0x9|\s)+kqueue\(/))
121 print "yes\n" if $has_kqueue == 1;
122 print "no\n" if $has_kqueue == 0;
124 printf "Checking if epoll exists... ";
127 open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
130 while (chomp($line = <EPOLL>))
132 # try and find the declaration of:
133 # extern int epoll_create (int __size) __THROW;
134 if (($line =~ /int(\0x9|\s)+epoll_create(\0x9|\s)+\(/) || ($line =~ /int(\0x9|\s)+epoll_create\(/))
141 print "yes\n" if $has_epoll == 1;
142 print "no\n" if $has_epoll == 0;
144 ################################################################################
145 # BEGIN INTERACTIVE PART #
146 ################################################################################
150 # Display Splash Logo..
152 chomp($wholeos = `uname -mnr`);
154 # Display Introduction Message..
156 Welcome to the InspIRCd Configuration program!
158 *** If you are unsure of any of these values, leave it blank for ***
159 *** standard settings that will work, and your server will run ***
160 *** using them. If you are running this server as part of a ***
161 *** larger network, you must consult with your network admins ***
162 *** for the proper values to use, or server links will be unstable! ***
164 Press \033[1m<RETURN>\033[0m to accept the default for any option, or enter
165 a new value. Please note: You will \033[1mHAVE\033[0m to read the docs
166 dir, otherwise you won't have a config file!
168 Your operating system is: \033[1;32m$config{OSNAME}\033[0m ($wholeos), fdmax: $config{MAX_CLIENT_T}\n\n";
170 # Directory Settings..
171 dir_check("are the configuration files", "CONFIG_DIR");
172 dir_check("are the modules to be compiled to", "MODULE_DIR");
173 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
174 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
177 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?");
180 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?");
182 $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y"));
185 print "No high-performance socket engines are available, or you chose\n";
186 print "not to enable one. Defaulting to select() engine.\n\n";
189 # File Descriptor Settings..
192 print "Maximum number of clients at any one time ($config{MAX_CLIENT_T})\n";
193 print "[\033[1;32m$config{MAX_CLIENT}\033[0m] -> ";
194 chomp($var = <STDIN>);
195 if ($var eq "") { $var = $config{MAX_CLIENT}; }
196 if ($var =~ /^\d+$/) {
197 if (($var > $config{MAX_CLIENT_T}) && ($fd_scan_failed ne true)) {
198 # Client has entered a larger number than the 'discovered' value
200 print "WARNING: Our scans have indicated that you are attempting
201 to use more sockets than there are avaliable. Are you sure
202 you wish to do this? It may cause the IRCd to malfunction [y/n]
203 [\033[1;32mn\033[0m] -> $c";
204 chomp($tmp = <STDIN>);
206 print "Please enter the correct value.\n\n";
211 print "You must enter a number in this field. Please try again.\n\n";
214 # If we get here, we should be good to go.
215 $config{MAX_CLIENT} = $var;
222 print "What is the Maximum length of nicknames?\n";
223 print "[\033[1;32m$config{NICK_LENGT}\033[0m] -> ";
224 chomp($var = <STDIN>);
225 if ($var eq "") { $var = $config{NICK_LENGT}; }
226 if ($var =~ /^\d+$/) {
227 # We don't care what the number is, set it and be on our way.
228 $config{NICK_LENGT} = $var;
232 print "You must enter a number in this field. Please try again.\n\n";
238 print "What is the Maximum number of mode changes in one line?\n";
239 print "[\033[1;32m$config{MAXI_MODES}\033[0m] -> ";
240 chomp($var = <STDIN>);
241 if ($var eq "") { $var = $config{MAXI_MODES}; }
242 if ($var =~ /^\d+$/) {
243 # We don't care what the number is, set it and be on our way.
244 $config{MAXI_MODES} = $var;
248 print "You must enter a number in this field. Please try again.\n\n";
253 print "Enter the Level Of Binary optimisation. This is a number between 0 and 3 (inclusive)
254 The InspIRCd Team will _NOT_ support any bug reports above 0.
255 Also note, the IRCd behaviour will be different depending on this value.
256 Please read the documentation for more information.
258 The Higher the number, the more optimised your binary will be. This value will default to 0
259 If you either a) Dont enter a number, or b) Enter a value outside the range.\n";
260 print "[\033[1;32m$config{OPTIMITEMP}\033[0m] -> ";
261 chomp($var = <STDIN>);
263 $var = $config{OPTIMITEMP};
267 $config{OPTIMITEMP} = 1;
268 $config{OPTIMISATI} = "-O";
269 } elsif ($var eq "2") {
270 $config{OPTIMITEMP} = 2;
271 $config{OPTIMISATI} = "-O2";
272 } elsif ($var eq "3") {
273 $config{OPTIMITEMP} = 3;
274 $config{OPTIMISATI} = "-O3";
276 $config{OPTIMITEMP} = 0;
277 $config{OPTIMISATI} = "-g";
280 print "\n\033[1;32mPre-build configuration is complete!\033[0m\n\n";
281 print "\033[0mConfig path:\033[1;32m\t\t\t$config{CONFIG_DIR}\n";
282 print "\033[0mModule path:\033[1;32m\t\t\t$config{MODULE_DIR}\n";
283 print "\033[0mMax connections:\033[1;32m\t\t$config{MAX_CLIENT}\n";
284 print "\033[0mMax User Channels\033[1;32m\t\t$config{MAX_CHANNE}\n";
285 print "\033[0mMax nickname length:\033[1;32m\t\t$config{NICK_LENGT}\n";
286 print "\033[0mMax channel length:\033[1;32m\t\t$config{CHAN_LENGT}\n";
287 print "\033[0mMax mode length:\033[1;32m\t\t$config{MAXI_MODES}\n";
288 print "\033[0mGCC Version Found:\033[1;32m\t\t$config{GCCVER}.$config{GCC34}\n";
289 print "\033[0mOptimatizaton Flag:\033[1;32m\t\t$config{OPTIMISATI}\033[0m\n\n";
295 print "To build your server with these settings, please type '\033[1;32m$config{MAKEPROG}\033[0m' now.\n";
296 print "*** \033[1;32mRemember to edit your configuration files!!!\033[0m ***\n\n\n";
298 ################################################################################
300 ################################################################################
302 # Retrieves the .config.cache file, and loads values into the main config hash.
303 open(CACHE, ".config.cache") or return undef;
307 # Ignore Blank lines, and comments..
311 my ($key, $value) = split("=", $_);
312 $value =~ /^\"(.*)\"$/;
313 # Do something with data here!
321 # Dump the contents of %config
322 print "Writing \033[1;32mcache file\033[0m for future ./configures ...\n";
323 open(FILEHANDLE, ">.config.cache");
324 foreach $key (keys %config)
326 print FILEHANDLE "$key=\"$config{$key}\"\n";
332 my ($desc, $hash_key) = @_;
335 print "In what directory $desc?\n";
336 print "[\033[1;32m$config{$hash_key}\033[0m] -> ";
337 chomp($var = <STDIN>);
338 if ($var eq "") { $var = $config{$hash_key}; }
339 if ($var =~ /^\~\/(.+)$/) {
340 # Convert it to a full path..
341 $var = resolve_directory($ENV{HOME} . "/" . $1);
343 if (substr($var,0,1) ne "/")
345 # Assume relative Path was given.. fill in the rest.
346 $var = $this . "/$var";
348 $var = resolve_directory($var);
350 print "$var does not exist. Create it?\n[\033[1;32my\033[0m] ";
351 chomp($tmp = <STDIN>);
352 if (($tmp eq "") || ($tmp =~ /^y/i)) {
353 # Attempt to Create the Dir..
354 $chk = system("mkdir -p \"$var\" >> /dev/null 2>&1") / 256;
356 print "Unable to create directory. ($var)\n\n";
361 # They said they don't want to create, and we can't install there.
367 # Target exists, but is not a directory.
368 print "File $var exists, but is not a directory.\n\n";
372 # Either Dir Exists, or was created fine.
373 $config{$hash_key} = $var;
380 if ($config{OSNAME} =~ /BSD$/) {
381 $config{LDLIBS} = "-Ldl";
382 $config{FLAGS} = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual $config{OPTIMISATI}";
383 $config{MAKEPROG} = "gmake";
385 $config{LDLIBS} = "-ldl";
386 $config{FLAGS} = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual $config{OPTIMISATI}";
387 $config{MAKEPROG} = "make";
389 if ($config{OSNAME} =~ /SunOS/) {
390 # solaris/sunos needs these
391 # socket = bsd sockets api
393 # rt = POSIX realtime extensions
394 # resolv = inet_aton only (why isnt this in nsl?!)
395 $config{LDLIBS} = $config{LDLIBS} . " -lsocket -lnsl -lrt -lresolv";
413 opendir(DIRHANDLE, "src/modules");
414 foreach $name (sort readdir(DIRHANDLE)) {
415 if ($name =~ /^m_(.+)\.cpp$/)
425 print "Writing \033[1;32minspircd_config.h\033[0m\n";
426 # First File.. inspircd_config.h
427 chomp(my $incos = `uname -n -s -r`);
428 chomp(my $version = `sh ./src/version.sh`);
429 open(FILEHANDLE, ">include/inspircd_config.h");
430 print FILEHANDLE <<EOF;
431 /* Auto generated by configure, do not modify! */
432 #define SYSLOG_FACILITY LOG_DAEMON
433 #define SYSLOG_LEVEL LOG_NOTICE
434 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
435 #define MOD_PATH "$config{MODULE_DIR}"
436 #define VERSION "$version"
437 #define MAXCLIENTS $config{MAX_CLIENT}
438 #define NICKMAX $config{NICK_LENGT}
439 #define CHANMAX $config{CHAN_LENGT}
440 #define MAXCHANS $config{MAX_CHANNE}
441 #define MAXMODES $config{MAXI_MODES}
442 #define OPTIMISATION $config{OPTIMITEMP}
443 #define SYSTEM "$incos"
447 if ($config{OSNAME} =~ /SunOS/) {
448 print FILEHANDLE "#define IS_SOLARIS\n";
450 if ($config{GCCVER} > 3) {
451 print FILEHANDLE "#define GCC3\n";
452 print FILEHANDLE "#define GCC34\n";
456 if ($config{GCCVER} == 3) {
457 print FILEHANDLE "#define GCC3\n";
458 if ($config{GCC34} > 3) {
459 print FILEHANDLE "#define GCC34\n";
463 if ($config{HAS_STRLCPY} eq "true") {
464 print FILEHANDLE "#define HAS_STRLCPY\n";
467 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
468 print FILEHANDLE "#define USE_KQUEUE\n";
471 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
472 print FILEHANDLE "#define USE_EPOLL\n";
475 # user didn't choose either epoll or select for their OS.
476 # default them to USE_SELECT (ewwy puke puke)
478 print FILEHANDLE "#define USE_SELECT\n";
482 # Create a Modules List..
484 foreach $i (@modlist)
486 $modules .= "m_".$i.".so ";
488 chomp($modules); # Remove Redundant whitespace..
491 # Write all .in files.
494 opendir(DIRHANDLE, $this);
495 foreach $name (sort readdir(DIRHANDLE)) {
496 if ($name =~ /^\.(.+)\.inc$/)
499 # All .name.inc files need parsing!
501 open(FILEHANDLE, ".$file.inc");
502 while (<FILEHANDLE>) {
507 $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/;
508 $tmp =~ s/\@FLAGS\@/$config{FLAGS}/;
509 $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/;
510 $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/;
511 $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/;
512 $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/;
513 $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/;
514 $tmp =~ s/\@MODULES\@/$modules/;
516 print "Writing \033[1;32m$file\033[0m\n";
517 open(FILEHANDLE, ">$file");
518 print FILEHANDLE $tmp;
523 # Make inspircd executable!
524 chmod 0744, 'inspircd';
527 print "Writing \033[1;32msrc/modules/Makefile\033[0m\n";
528 open(FILEHANDLE, ">src/modules/Makefile");
529 print FILEHANDLE <<EOF;
530 # (C) ChatSpike development team
531 # Makefile by <Craig\@ChatSpike.net>
532 # Many Thanks to Andrew Church <achurch\@achurch.org>
533 # for assisting with making this work right.
535 # Automatically Generated by ./configure to add a modules
536 # please run ./configure --update
542 # Create a Modules List..
545 foreach $i (@modlist)
547 $flags = getcompilerflags("src/modules/m_".$i.".cpp");
548 print FILEHANDLE <<EOCHEESE;
549 m_$i.so: m_$i.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/servers.h ../../include/base.h
550 \$(CC) -pipe -I../../include \$(FLAGS) $flags -export-dynamic -c m_$i.cpp
551 \$(CC) \$(FLAGS) -shared $flags -o m_$i.so m_$i.o
552 cp m_$i.so \$(MODPATH)/
553 chmod 0700 \$(MODPATH)/m_$i.so
559 sub getcompilerflags {
563 if ($_ =~ /^\/\* \$CompileFlags: (.+) \*\/$/) {
573 print "'\033[1;33m####\033[0m:'\033[1;33m##\033[0m::: \033[1;33m##\033[0m::'\033[1;33m######\033[0m::'\033[1;33m########\033[0m::'\033[1;33m####\033[0m:'\033[1;33m########\033[0m:::'\033[1;33m######\033[0m::'\033[1;33m########\033[0m::\n";
574 print ". \033[1;33m##\033[0m:: \033[1;33m###\033[0m:: \033[1;33m##\033[0m:'\033[1;33m##\033[0m... \033[1;33m##\033[0m: \033[1;33m##\033[0m.... \033[1;33m##\033[0m:. \033[1;33m##\033[0m:: \033[1;33m##\033[0m.... \033[1;33m##\033[0m:'\033[1;33m##\033[0m... \033[1;33m##\033[0m: \033[1;33m##\033[0m.... \033[1;33m##\033[0m:\n";
575 print ": \033[1;33m##\033[0m:: \033[1;33m####\033[0m: \033[1;33m##\033[0m: \033[1;33m##\033[0m:::..:: \033[1;33m##\033[0m:::: \033[1;33m##\033[0m:: \033[1;33m##\033[0m:: \033[1;33m##\033[0m:::: \033[1;33m##\033[0m: \033[1;33m##\033[0m:::..:: \033[1;33m##\033[0m:::: \033[1;33m##\033[0m:\n";
576 print ": \033[1;33m##\033[0m:: \033[1;33m##\033[0m \033[1;33m##\033[0m \033[1;33m##\033[0m:. \033[1;33m######\033[0m:: \033[1;33m########\033[0m::: \033[1;33m##\033[0m:: \033[1;33m########\033[0m:: \033[1;33m##\033[0m::::::: \033[1;33m##\033[0m:::: \033[1;33m##\033[0m:\n";
577 print ": \033[1;33m##\033[0m:: \033[1;33m##\033[0m. \033[1;33m####\033[0m::..... \033[1;33m##\033[0m: \033[1;33m##\033[0m.....:::: \033[1;33m##\033[0m:: \033[1;33m##\033[0m.. \033[1;33m##\033[0m::: \033[1;33m##\033[0m::::::: \033[1;33m##\033[0m:::: \033[1;33m##\033[0m:\n";
578 print ": \033[1;33m##\033[0m:: \033[1;33m##\033[0m:. \033[1;33m###\033[0m:'\033[1;33m##\033[0m::: \033[1;33m##\033[0m: \033[1;33m##\033[0m::::::::: \033[1;33m##\033[0m:: \033[1;33m##\033[0m::. \033[1;33m##\033[0m:: \033[1;33m##\033[0m::: \033[1;33m##\033[0m: \033[1;33m##\033[0m:::: \033[1;33m##\033[0m:\n";
579 print "'\033[1;33m####\033[0m: \033[1;33m##\033[0m::. \033[1;33m##\033[0m:. \033[1;33m######\033[0m:: \033[1;33m##\033[0m::::::::'\033[1;33m####\033[0m: \033[1;33m##\033[0m:::. \033[1;33m##\033[0m:. \033[1;33m######\033[0m:: \033[1;33m########\033[0m::\n";
580 print "\033[0m\033[0m....::..::::..:::......:::..:::::::::....::..:::::..:::......:::........:::\n\n";
583 sub resolve_directory {
585 return File::Spec->rel2abs($_[0]);
589 my ($flag,$prompt) = @_;
590 print "$prompt [\033[1;32m$config{$flag}\033[0m] -> ";
591 chomp($tmp = <STDIN>);
592 if ($tmp eq "") { $tmp = $config{$flag} }
594 if (($tmp eq "") || ($tmp =~ /^y/i)) {
595 $config{$flag} = "y";
597 $config{$flag} = "n";