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`); # Operating System Name
37 print "OSN: '" . $config{OSNAME} . "'\n";
39 if (!$config{OSNAME}) {
40 print "Running 2nd uname\n";
41 chomp($config{OSNAME} = `/usr/bin/uname`);
42 print "OSN: '" . $config{OSNAME} . "'\n";
43 if (!$config{OSNAME}) {
44 $config{OSNAME} = "Unknown";
48 if (!$config{MAX_CLIENT_T}) {
49 $config{MAX_CLIENT_T} = 1024; # Set a reasonable 'Default'
50 $fd_scan_fail = "true"; # Used Later
53 # Get and Set some important vars..
56 my $arg = $ARGV[0]; # Do Some Argument Checks..
57 if ($arg eq "-clean") { `rm -rf .config.cache`; } # Remove the config.cache file.
59 if ($arg eq "-update") {
60 # Does the cache file exist?
62 # No, No it doesn't.. *BASH*
63 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
66 # We've Loaded the cache file and all our variables..
67 print "Updating Files..\n";
75 print "Checking for cache from previous configure...\n";
77 print "Checking operating system version...\n";
80 if (!$config{MAX_CLIENT}) {
81 # If the cache hasn't set the max clients, copy the variable of MAX_CLIENT_T, this
82 # allows us to keep _T for testing purposes. (ie. "Are you sure you want to go
83 # higher than the found value" :))
84 $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
87 printf "Checking if strlcpy exists... ";
88 # Perform the strlcpy() test..
89 $config{HAS_STRLCPY} = "false";
91 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
94 while (chomp($line = <STRLCPY>))
96 # try and find the delcaration of:
98 if (($line =~ /size_t(\0x9|\s)+strlcpy(\0x9|\s)+\(/) || ($line =~ /size_t(\0x9|\s)+strlcpy\(/))
100 $config{HAS_STRLCPY} = "true";
105 print "yes\n" if $config{HAS_STRLCPY} eq "true";
106 print "no\n" if $config{HAS_STRLCPY} eq "false";
108 printf "Checking if kqueue exists... ";
111 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
114 while (chomp($line = <KQUEUE>))
116 # try and find the delcaration of:
118 if (($line =~ /int(\0x9|\s)+kqueue(\0x9|\s)+\(/) || ($line =~ /int(\0x9|\s)+kqueue\(/))
125 print "yes\n" if $has_kqueue == 1;
126 print "no\n" if $has_kqueue == 0;
128 printf "Checking if epoll exists... ";
131 open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
134 while (chomp($line = <EPOLL>))
136 # try and find the declaration of:
137 # extern int epoll_create (int __size) __THROW;
138 if (($line =~ /int(\0x9|\s)+epoll_create(\0x9|\s)+\(/) || ($line =~ /int(\0x9|\s)+epoll_create\(/))
145 print "yes\n" if $has_epoll == 1;
146 print "no\n" if $has_epoll == 0;
148 ################################################################################
149 # BEGIN INTERACTIVE PART #
150 ################################################################################
154 # Display Splash Logo..
156 chomp($wholeos = `uname -mnr`);
158 # Display Introduction Message..
160 Welcome to the InspIRCd Configuration program!
162 *** If you are unsure of any of these values, leave it blank for ***
163 *** standard settings that will work, and your server will run ***
164 *** using them. If you are running this server as part of a ***
165 *** larger network, you must consult with your network admins ***
166 *** for the proper values to use, or server links will be unstable! ***
168 Press \033[1m<RETURN>\033[0m to accept the default for any option, or enter
169 a new value. Please note: You will \033[1mHAVE\033[0m to read the docs
170 dir, otherwise you won't have a config file!
172 Your operating system is: \033[1;32m$config{OSNAME}\033[0m ($wholeos), fdmax: $config{MAX_CLIENT_T}\n\n";
174 # Directory Settings..
175 dir_check("are the configuration files", "CONFIG_DIR");
176 dir_check("are the modules to be compiled to", "MODULE_DIR");
177 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
178 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
181 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?");
184 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?");
186 $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y"));
189 print "No high-performance socket engines are available, or you chose\n";
190 print "not to enable one. Defaulting to select() engine.\n\n";
193 # File Descriptor Settings..
196 print "Maximum number of clients at any one time ($config{MAX_CLIENT_T})\n";
197 print "[\033[1;32m$config{MAX_CLIENT}\033[0m] -> ";
198 chomp($var = <STDIN>);
199 if ($var eq "") { $var = $config{MAX_CLIENT}; }
200 if ($var =~ /^\d+$/) {
201 if (($var > $config{MAX_CLIENT_T}) && ($fd_scan_failed ne true)) {
202 # Client has entered a larger number than the 'discovered' value
204 print "WARNING: Our scans have indicated that you are attempting
205 to use more sockets than there are avaliable. Are you sure
206 you wish to do this? It may cause the IRCd to malfunction [y/n]
207 [\033[1;32mn\033[0m] -> $c";
208 chomp($tmp = <STDIN>);
210 print "Please enter the correct value.\n\n";
215 print "You must enter a number in this field. Please try again.\n\n";
218 # If we get here, we should be good to go.
219 $config{MAX_CLIENT} = $var;
226 print "What is the Maximum length of nicknames?\n";
227 print "[\033[1;32m$config{NICK_LENGT}\033[0m] -> ";
228 chomp($var = <STDIN>);
229 if ($var eq "") { $var = $config{NICK_LENGT}; }
230 if ($var =~ /^\d+$/) {
231 # We don't care what the number is, set it and be on our way.
232 $config{NICK_LENGT} = $var;
236 print "You must enter a number in this field. Please try again.\n\n";
242 print "What is the Maximum number of mode changes in one line?\n";
243 print "[\033[1;32m$config{MAXI_MODES}\033[0m] -> ";
244 chomp($var = <STDIN>);
245 if ($var eq "") { $var = $config{MAXI_MODES}; }
246 if ($var =~ /^\d+$/) {
247 # We don't care what the number is, set it and be on our way.
248 $config{MAXI_MODES} = $var;
252 print "You must enter a number in this field. Please try again.\n\n";
257 print "Enter the Level Of Binary optimisation. This is a number between 0 and 3 (inclusive)
258 The InspIRCd Team will _NOT_ support any bug reports above 0.
259 Also note, the IRCd behaviour will be different depending on this value.
260 Please read the documentation for more information.
262 The Higher the number, the more optimised your binary will be. This value will default to 0
263 If you either a) Dont enter a number, or b) Enter a value outside the range.\n";
264 print "[\033[1;32m$config{OPTIMITEMP}\033[0m] -> ";
265 chomp($var = <STDIN>);
267 $var = $config{OPTIMITEMP};
271 $config{OPTIMITEMP} = 1;
272 $config{OPTIMISATI} = "-O";
273 } elsif ($var eq "2") {
274 $config{OPTIMITEMP} = 2;
275 $config{OPTIMISATI} = "-O2";
276 } elsif ($var eq "3") {
277 $config{OPTIMITEMP} = 3;
278 $config{OPTIMISATI} = "-O3";
280 $config{OPTIMITEMP} = 0;
281 $config{OPTIMISATI} = "-g";
284 print "\n\033[1;32mPre-build configuration is complete!\033[0m\n\n";
285 print "\033[0mConfig path:\033[1;32m\t\t\t$config{CONFIG_DIR}\n";
286 print "\033[0mModule path:\033[1;32m\t\t\t$config{MODULE_DIR}\n";
287 print "\033[0mMax connections:\033[1;32m\t\t$config{MAX_CLIENT}\n";
288 print "\033[0mMax User Channels\033[1;32m\t\t$config{MAX_CHANNE}\n";
289 print "\033[0mMax nickname length:\033[1;32m\t\t$config{NICK_LENGT}\n";
290 print "\033[0mMax channel length:\033[1;32m\t\t$config{CHAN_LENGT}\n";
291 print "\033[0mMax mode length:\033[1;32m\t\t$config{MAXI_MODES}\n";
292 print "\033[0mGCC Version Found:\033[1;32m\t\t$config{GCCVER}.$config{GCC34}\n";
293 print "\033[0mOptimatizaton Flag:\033[1;32m\t\t$config{OPTIMISATI}\033[0m\n\n";
299 print "To build your server with these settings, please type '\033[1;32m$config{MAKEPROG}\033[0m' now.\n";
300 print "*** \033[1;32mRemember to edit your configuration files!!!\033[0m ***\n\n\n";
302 ################################################################################
304 ################################################################################
306 # Retrieves the .config.cache file, and loads values into the main config hash.
307 open(CACHE, ".config.cache") or return undef;
311 # Ignore Blank lines, and comments..
315 my ($key, $value) = split("=", $_);
316 $value =~ /^\"(.*)\"$/;
317 # Do something with data here!
325 # Dump the contents of %config
326 print "Writing \033[1;32mcache file\033[0m for future ./configures ...\n";
327 open(FILEHANDLE, ">.config.cache");
328 foreach $key (keys %config)
330 print FILEHANDLE "$key=\"$config{$key}\"\n";
336 my ($desc, $hash_key) = @_;
339 print "In what directory $desc?\n";
340 print "[\033[1;32m$config{$hash_key}\033[0m] -> ";
341 chomp($var = <STDIN>);
342 if ($var eq "") { $var = $config{$hash_key}; }
343 if ($var =~ /^\~\/(.+)$/) {
344 # Convert it to a full path..
345 $var = resolve_directory($ENV{HOME} . "/" . $1);
347 if (substr($var,0,1) ne "/")
349 # Assume relative Path was given.. fill in the rest.
350 $var = $this . "/$var";
352 $var = resolve_directory($var);
354 print "$var does not exist. Create it?\n[\033[1;32my\033[0m] ";
355 chomp($tmp = <STDIN>);
356 if (($tmp eq "") || ($tmp =~ /^y/i)) {
357 # Attempt to Create the Dir..
358 $chk = system("mkdir -p \"$var\" >> /dev/null 2>&1") / 256;
360 print "Unable to create directory. ($var)\n\n";
365 # They said they don't want to create, and we can't install there.
371 # Target exists, but is not a directory.
372 print "File $var exists, but is not a directory.\n\n";
376 # Either Dir Exists, or was created fine.
377 $config{$hash_key} = $var;
384 if ($config{OSNAME} =~ /BSD$/) {
385 $config{LDLIBS} = "-Ldl";
386 $config{FLAGS} = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual $config{OPTIMISATI}";
387 $config{MAKEPROG} = "gmake";
389 $config{LDLIBS} = "-ldl";
390 $config{FLAGS} = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual $config{OPTIMISATI}";
391 $config{MAKEPROG} = "make";
393 if ($config{OSNAME} =~ /SunOS/) {
394 # solaris/sunos needs these
395 # socket = bsd sockets api
397 # rt = POSIX realtime extensions
398 # resolv = inet_aton only (why isnt this in nsl?!)
399 $config{LDLIBS} = $config{LDLIBS} . " -lsocket -lnsl -lrt -lresolv";
417 opendir(DIRHANDLE, "src/modules");
418 foreach $name (sort readdir(DIRHANDLE)) {
419 if ($name =~ /^m_(.+)\.cpp$/)
429 print "Writing \033[1;32minspircd_config.h\033[0m\n";
430 # First File.. inspircd_config.h
431 chomp(my $incos = `uname -n -s -r`);
432 chomp(my $version = `sh ./src/version.sh`);
433 open(FILEHANDLE, ">include/inspircd_config.h");
434 print FILEHANDLE <<EOF;
435 /* Auto generated by configure, do not modify! */
436 #define SYSLOG_FACILITY LOG_DAEMON
437 #define SYSLOG_LEVEL LOG_NOTICE
438 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
439 #define MOD_PATH "$config{MODULE_DIR}"
440 #define VERSION "$version"
441 #define MAXCLIENTS $config{MAX_CLIENT}
442 #define NICKMAX $config{NICK_LENGT}
443 #define CHANMAX $config{CHAN_LENGT}
444 #define MAXCHANS $config{MAX_CHANNE}
445 #define MAXMODES $config{MAXI_MODES}
446 #define OPTIMISATION $config{OPTIMITEMP}
447 #define SYSTEM "$incos"
451 if ($config{OSNAME} =~ /SunOS/) {
452 print FILEHANDLE "#define IS_SOLARIS\n";
454 if ($config{GCCVER} > 3) {
455 print FILEHANDLE "#define GCC3\n";
456 print FILEHANDLE "#define GCC34\n";
460 if ($config{GCCVER} == 3) {
461 print FILEHANDLE "#define GCC3\n";
462 if ($config{GCC34} > 3) {
463 print FILEHANDLE "#define GCC34\n";
467 if ($config{HAS_STRLCPY} eq "true") {
468 print FILEHANDLE "#define HAS_STRLCPY\n";
471 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
472 print FILEHANDLE "#define USE_KQUEUE\n";
475 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
476 print FILEHANDLE "#define USE_EPOLL\n";
479 # user didn't choose either epoll or select for their OS.
480 # default them to USE_SELECT (ewwy puke puke)
482 print FILEHANDLE "#define USE_SELECT\n";
486 # Create a Modules List..
488 foreach $i (@modlist)
490 $modules .= "m_".$i.".so ";
492 chomp($modules); # Remove Redundant whitespace..
495 # Write all .in files.
498 opendir(DIRHANDLE, $this);
499 foreach $name (sort readdir(DIRHANDLE)) {
500 if ($name =~ /^\.(.+)\.inc$/)
503 # All .name.inc files need parsing!
505 open(FILEHANDLE, ".$file.inc");
506 while (<FILEHANDLE>) {
511 $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/;
512 $tmp =~ s/\@FLAGS\@/$config{FLAGS}/;
513 $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/;
514 $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/;
515 $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/;
516 $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/;
517 $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/;
518 $tmp =~ s/\@MODULES\@/$modules/;
520 print "Writing \033[1;32m$file\033[0m\n";
521 open(FILEHANDLE, ">$file");
522 print FILEHANDLE $tmp;
527 # Make inspircd executable!
528 chmod 0744, 'inspircd';
531 print "Writing \033[1;32msrc/modules/Makefile\033[0m\n";
532 open(FILEHANDLE, ">src/modules/Makefile");
533 print FILEHANDLE <<EOF;
534 # (C) ChatSpike development team
535 # Makefile by <Craig\@ChatSpike.net>
536 # Many Thanks to Andrew Church <achurch\@achurch.org>
537 # for assisting with making this work right.
539 # Automatically Generated by ./configure to add a modules
540 # please run ./configure --update
546 # Create a Modules List..
549 foreach $i (@modlist)
551 $flags = getcompilerflags("src/modules/m_".$i.".cpp");
552 print FILEHANDLE <<EOCHEESE;
553 m_$i.so: m_$i.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/servers.h ../../include/base.h
554 \$(CC) -pipe -I../../include \$(FLAGS) $flags -export-dynamic -c m_$i.cpp
555 \$(CC) \$(FLAGS) -shared $flags -o m_$i.so m_$i.o
556 cp m_$i.so \$(MODPATH)/
557 chmod 0700 \$(MODPATH)/m_$i.so
563 sub getcompilerflags {
567 if ($_ =~ /^\/\* \$CompileFlags: (.+) \*\/$/) {
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::\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.... \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:::..:: \033[1;33m##\033[0m:::: \033[1;33m##\033[0m:\n";
580 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";
581 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";
582 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";
583 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";
584 print "\033[0m\033[0m....::..::::..:::......:::..:::::::::....::..:::::..:::......:::........:::\n\n";
587 sub resolve_directory {
589 return File::Spec->rel2abs($_[0]);
593 my ($flag,$prompt) = @_;
594 print "$prompt [\033[1;32m$config{$flag}\033[0m] -> ";
595 chomp($tmp = <STDIN>);
596 if ($tmp eq "") { $tmp = $config{$flag} }
598 if (($tmp eq "") || ($tmp =~ /^y/i)) {
599 $config{$flag} = "y";
601 $config{$flag} = "n";