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 $config{OSNAME} = "Unknown"; # For use when uname fails.
41 if (!$config{MAX_CLIENT_T}) {
42 $config{MAX_CLIENT_T} = 1024; # Set a reasonable 'Default'
43 $fd_scan_fail = "true"; # Used Later
46 # Get and Set some important vars..
49 my $arg = $ARGV[0]; # Do Some Argument Checks..
50 if ($arg eq "-clean") { `rm -rf .config.cache`; } # Remove the config.cache file.
52 if ($arg eq "-update") {
53 # Does the cache file exist?
55 # No, No it doesn't.. *BASH*
56 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
59 # We've Loaded the cache file and all our variables..
60 print "Updating Files..\n";
68 print "Checking for cache from previous configure...\n";
70 print "Checking operating system version...\n";
73 if (!$config{MAX_CLIENT}) {
74 # If the cache hasn't set the max clients, copy the variable of MAX_CLIENT_T, this
75 # allows us to keep _T for testing purposes. (ie. "Are you sure you want to go
76 # higher than the found value" :))
77 $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
80 printf "Checking if strlcpy exists... ";
81 # Perform the strlcpy() test..
82 $config{HAS_STRLCPY} = "false";
84 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
87 while (chomp($line = <STRLCPY>))
89 # try and find the delcaration of:
91 if (($line =~ /size_t(\0x9|\s)+strlcpy(\0x9|\s)+\(/) || ($line =~ /size_t(\0x9|\s)+strlcpy\(/))
93 $config{HAS_STRLCPY} = "true";
98 print "yes\n" if $config{HAS_STRLCPY} eq "true";
99 print "no\n" if $config{HAS_STRLCPY} eq "false";
101 printf "Checking if kqueue exists... ";
104 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
107 while (chomp($line = <KQUEUE>))
109 # try and find the delcaration of:
111 if (($line =~ /int(\0x9|\s)+kqueue(\0x9|\s)+\(/) || ($line =~ /int(\0x9|\s)+kqueue\(/))
118 print "yes\n" if $has_kqueue == 1;
119 print "no\n" if $has_kqueue == 0;
121 printf "Checking if epoll exists... ";
124 open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
127 while (chomp($line = <EPOLL>))
129 # try and find the declaration of:
130 # extern int epoll_create (int __size) __THROW;
131 if (($line =~ /int(\0x9|\s)+epoll_create(\0x9|\s)+\(/) || ($line =~ /int(\0x9|\s)+epoll_create\(/))
138 print "yes\n" if $has_epoll == 1;
139 print "no\n" if $has_epoll == 0;
141 ################################################################################
142 # BEGIN INTERACTIVE PART #
143 ################################################################################
147 # Display Splash Logo..
149 chomp($wholeos = `uname -mnr`);
151 # Display Introduction Message..
153 Welcome to the InspIRCd Configuration program!
155 *** If you are unsure of any of these values, leave it blank for ***
156 *** standard settings that will work, and your server will run ***
157 *** using them. If you are running this server as part of a ***
158 *** larger network, you must consult with your network admins ***
159 *** for the proper values to use, or server links will be unstable! ***
161 Press \033[1m<RETURN>\033[0m to accept the default for any option, or enter
162 a new value. Please note: You will \033[1mHAVE\033[0m to read the docs
163 dir, otherwise you won't have a config file!
165 Your operating system is: \033[1;32m$config{OSNAME}\033[0m ($wholeos), fdmax: $config{MAX_CLIENT_T}\n\n";
167 # Directory Settings..
168 dir_check("are the configuration files", "CONFIG_DIR");
169 dir_check("are the modules to be compiled to", "MODULE_DIR");
170 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
171 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
174 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?");
177 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?");
179 $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y"));
182 print "No high-performance socket engines are available, or you chose\n";
183 print "not to enable one. Defaulting to select() engine.\n\n";
186 # File Descriptor Settings..
189 print "Maximum number of clients at any one time ($config{MAX_CLIENT_T})\n";
190 print "[\033[1;32m$config{MAX_CLIENT}\033[0m] -> ";
191 chomp($var = <STDIN>);
192 if ($var eq "") { $var = $config{MAX_CLIENT}; }
193 if ($var =~ /^\d+$/) {
194 if (($var > $config{MAX_CLIENT_T}) && ($fd_scan_failed ne true)) {
195 # Client has entered a larger number than the 'discovered' value
197 print "WARNING: Our scans have indicated that you are attempting
198 to use more sockets than there are avaliable. Are you sure
199 you wish to do this? It may cause the IRCd to malfunction [y/n]
200 [\033[1;32mn\033[0m] -> $c";
201 chomp($tmp = <STDIN>);
203 print "Please enter the correct value.\n\n";
208 print "You must enter a number in this field. Please try again.\n\n";
211 # If we get here, we should be good to go.
212 $config{MAX_CLIENT} = $var;
219 print "What is the Maximum length of nicknames?\n";
220 print "[\033[1;32m$config{NICK_LENGT}\033[0m] -> ";
221 chomp($var = <STDIN>);
222 if ($var eq "") { $var = $config{NICK_LENGT}; }
223 if ($var =~ /^\d+$/) {
224 # We don't care what the number is, set it and be on our way.
225 $config{NICK_LENGT} = $var;
229 print "You must enter a number in this field. Please try again.\n\n";
235 print "What is the Maximum number of mode changes in one line?\n";
236 print "[\033[1;32m$config{MAXI_MODES}\033[0m] -> ";
237 chomp($var = <STDIN>);
238 if ($var eq "") { $var = $config{MAXI_MODES}; }
239 if ($var =~ /^\d+$/) {
240 # We don't care what the number is, set it and be on our way.
241 $config{MAXI_MODES} = $var;
245 print "You must enter a number in this field. Please try again.\n\n";
250 print "Enter the Level Of Binary optimisation. This is a number between 0 and 3 (inclusive)
251 The InspIRCd Team will _NOT_ support any bug reports above 0.
252 Also note, the IRCd behaviour will be different depending on this value.
253 Please read the documentation for more information.
255 The Higher the number, the more optimised your binary will be. This value will default to 0
256 If you either a) Dont enter a number, or b) Enter a value outside the range.\n";
257 print "[\033[1;32m$config{OPTIMITEMP}\033[0m] -> ";
258 chomp($var = <STDIN>);
260 $var = $config{OPTIMITEMP};
264 $config{OPTIMITEMP} = 1;
265 $config{OPTIMISATI} = "-O";
266 } elsif ($var eq "2") {
267 $config{OPTIMITEMP} = 2;
268 $config{OPTIMISATI} = "-O2";
269 } elsif ($var eq "3") {
270 $config{OPTIMITEMP} = 3;
271 $config{OPTIMISATI} = "-O3";
273 $config{OPTIMITEMP} = 0;
274 $config{OPTIMISATI} = "-g";
277 print "\n\033[1;32mPre-build configuration is complete!\033[0m\n\n";
278 print "\033[0mConfig path:\033[1;32m\t\t\t$config{CONFIG_DIR}\n";
279 print "\033[0mModule path:\033[1;32m\t\t\t$config{MODULE_DIR}\n";
280 print "\033[0mMax connections:\033[1;32m\t\t$config{MAX_CLIENT}\n";
281 print "\033[0mMax User Channels\033[1;32m\t\t$config{MAX_CHANNE}\n";
282 print "\033[0mMax nickname length:\033[1;32m\t\t$config{NICK_LENGT}\n";
283 print "\033[0mMax channel length:\033[1;32m\t\t$config{CHAN_LENGT}\n";
284 print "\033[0mMax mode length:\033[1;32m\t\t$config{MAXI_MODES}\n";
285 print "\033[0mGCC Version Found:\033[1;32m\t\t$config{GCCVER}.$config{GCC34}\n";
286 print "\033[0mOptimatizaton Flag:\033[1;32m\t\t$config{OPTIMISATI}\033[0m\n\n";
292 print "To build your server with these settings, please type '\033[1;32m$config{MAKEPROG}\033[0m' now.\n";
293 print "*** \033[1;32mRemember to edit your configuration files!!!\033[0m ***\n\n\n";
295 ################################################################################
297 ################################################################################
299 # Retrieves the .config.cache file, and loads values into the main config hash.
300 open(CACHE, ".config.cache") or return undef;
304 # Ignore Blank lines, and comments..
308 my ($key, $value) = split("=", $_);
309 $value =~ /^\"(.*)\"$/;
310 # Do something with data here!
318 # Dump the contents of %config
319 print "Writing \033[1;32mcache file\033[0m for future ./configures ...\n";
320 open(FILEHANDLE, ">.config.cache");
321 foreach $key (keys %config)
323 print FILEHANDLE "$key=\"$config{$key}\"\n";
329 my ($desc, $hash_key) = @_;
332 print "In what directory $desc?\n";
333 print "[\033[1;32m$config{$hash_key}\033[0m] -> ";
334 chomp($var = <STDIN>);
335 if ($var eq "") { $var = $config{$hash_key}; }
336 if ($var =~ /^\~\/(.+)$/) {
337 # Convert it to a full path..
338 $var = resolve_directory($ENV{HOME} . "/" . $1);
340 if (substr($var,0,1) ne "/")
342 # Assume relative Path was given.. fill in the rest.
343 $var = $this . "/$var";
345 $var = resolve_directory($var);
347 print "$var does not exist. Create it?\n[\033[1;32my\033[0m] ";
348 chomp($tmp = <STDIN>);
349 if (($tmp eq "") || ($tmp =~ /^y/i)) {
350 # Attempt to Create the Dir..
351 $chk = system("mkdir -p \"$var\" >> /dev/null 2>&1") / 256;
353 print "Unable to create directory. ($var)\n\n";
358 # They said they don't want to create, and we can't install there.
364 # Target exists, but is not a directory.
365 print "File $var exists, but is not a directory.\n\n";
369 # Either Dir Exists, or was created fine.
370 $config{$hash_key} = $var;
377 if ($config{OSNAME} =~ /BSD$/) {
378 $config{LDLIBS} = "-Ldl";
379 $config{FLAGS} = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual $config{OPTIMISATI}";
380 $config{MAKEPROG} = "gmake";
382 $config{LDLIBS} = "-ldl";
383 $config{FLAGS} = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual $config{OPTIMISATI}";
384 $config{MAKEPROG} = "make";
386 if ($config{OSNAME} =~ /SunOS/) {
387 # solaris/sunos needs these
388 # socket = bsd sockets api
390 # rt = POSIX realtime extensions
391 # resolv = inet_aton only (why isnt this in nsl?!)
392 $config{LDLIBS} = $config{LDLIBS} . " -lsocket -lnsl -lrt -lresolv";
410 opendir(DIRHANDLE, "src/modules");
411 foreach $name (sort readdir(DIRHANDLE)) {
412 if ($name =~ /^m_(.+)\.cpp$/)
422 print "Writing \033[1;32minspircd_config.h\033[0m\n";
423 # First File.. inspircd_config.h
424 chomp(my $incos = `uname -n -s -r`);
425 chomp(my $version = `sh ./src/version.sh`);
426 open(FILEHANDLE, ">include/inspircd_config.h");
427 print FILEHANDLE <<EOF;
428 /* Auto generated by configure, do not modify! */
429 #define SYSLOG_FACILITY LOG_DAEMON
430 #define SYSLOG_LEVEL LOG_NOTICE
431 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
432 #define MOD_PATH "$config{MODULE_DIR}"
433 #define VERSION "$version"
434 #define MAXCLIENTS $config{MAX_CLIENT}
435 #define NICKMAX $config{NICK_LENGT}
436 #define CHANMAX $config{CHAN_LENGT}
437 #define MAXCHANS $config{MAX_CHANNE}
438 #define MAXMODES $config{MAXI_MODES}
439 #define OPTIMISATION $config{OPTIMITEMP}
440 #define SYSTEM "$incos"
444 if ($config{OSNAME} =~ /SunOS/) {
445 print FILEHANDLE "#define IS_SOLARIS\n";
447 if ($config{GCCVER} > 3) {
448 print FILEHANDLE "#define GCC3\n";
449 print FILEHANDLE "#define GCC34\n";
453 if ($config{GCCVER} == 3) {
454 print FILEHANDLE "#define GCC3\n";
455 if ($config{GCC34} > 3) {
456 print FILEHANDLE "#define GCC34\n";
460 if ($config{HAS_STRLCPY} eq "true") {
461 print FILEHANDLE "#define HAS_STRLCPY\n";
464 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
465 print FILEHANDLE "#define USE_KQUEUE\n";
468 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
469 print FILEHANDLE "#define USE_EPOLL\n";
472 # user didn't choose either epoll or select for their OS.
473 # default them to USE_SELECT (ewwy puke puke)
475 print FILEHANDLE "#define USE_SELECT\n";
479 # Create a Modules List..
481 foreach $i (@modlist)
483 $modules .= "m_".$i.".so ";
485 chomp($modules); # Remove Redundant whitespace..
488 # Write all .in files.
491 opendir(DIRHANDLE, $this);
492 foreach $name (sort readdir(DIRHANDLE)) {
493 if ($name =~ /^\.(.+)\.inc$/)
496 # All .name.inc files need parsing!
498 open(FILEHANDLE, ".$file.inc");
499 while (<FILEHANDLE>) {
504 $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/;
505 $tmp =~ s/\@FLAGS\@/$config{FLAGS}/;
506 $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/;
507 $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/;
508 $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/;
509 $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/;
510 $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/;
511 $tmp =~ s/\@MODULES\@/$modules/;
513 print "Writing \033[1;32m$file\033[0m\n";
514 open(FILEHANDLE, ">$file");
515 print FILEHANDLE $tmp;
520 # Make inspircd executable!
521 chmod 0744, 'inspircd';
524 print "Writing \033[1;32msrc/modules/Makefile\033[0m\n";
525 open(FILEHANDLE, ">src/modules/Makefile");
526 print FILEHANDLE <<EOF;
527 # (C) ChatSpike development team
528 # Makefile by <Craig\@ChatSpike.net>
529 # Many Thanks to Andrew Church <achurch\@achurch.org>
530 # for assisting with making this work right.
532 # Automatically Generated by ./configure to add a modules
533 # please run ./configure --update
539 # Create a Modules List..
542 foreach $i (@modlist)
544 $flags = getcompilerflags("src/modules/m_".$i.".cpp");
545 print FILEHANDLE <<EOCHEESE;
546 m_$i.so: m_$i.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/servers.h ../../include/base.h
547 \$(CC) -pipe -I../../include \$(FLAGS) $flags -export-dynamic -c m_$i.cpp
548 \$(CC) \$(FLAGS) -shared $flags -o m_$i.so m_$i.o
549 cp m_$i.so \$(MODPATH)/
550 chmod 0700 \$(MODPATH)/m_$i.so
556 sub getcompilerflags {
560 if ($_ =~ /^\/\* \$CompileFlags: (.+) \*\/$/) {
570 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";
571 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";
572 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";
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::::::: \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:\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:::: \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::\n";
577 print "\033[0m\033[0m....::..::::..:::......:::..:::::::::....::..:::::..:::......:::........:::\n\n";
580 sub resolve_directory {
582 return File::Spec->rel2abs($_[0]);
586 my ($flag,$prompt) = @_;
587 print "$prompt [\033[1;32m$config{$flag}\033[0m] -> ";
588 chomp($tmp = <STDIN>);
589 if ($tmp eq "") { $tmp = $config{$flag} }
591 if (($tmp eq "") || ($tmp =~ /^y/i)) {
592 $config{$flag} = "y";
594 $config{$flag} = "n";