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 print "OSN: '" . $config{OSNAME} . "'\n";
39 if (!$config{OSNAME}) {
40 chomp($config{OSNAME} = `/usr/bin/uname -s`);
41 if ($config{OSNAME}) {
42 $config{OSNAME} = "Unknown";
46 if (!$config{MAX_CLIENT_T}) {
47 $config{MAX_CLIENT_T} = 1024; # Set a reasonable 'Default'
48 $fd_scan_fail = "true"; # Used Later
51 # Get and Set some important vars..
54 my $arg = $ARGV[0]; # Do Some Argument Checks..
55 if ($arg eq "-clean") { `rm -rf .config.cache`; } # Remove the config.cache file.
57 if ($arg eq "-update") {
58 # Does the cache file exist?
60 # No, No it doesn't.. *BASH*
61 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
64 # We've Loaded the cache file and all our variables..
65 print "Updating Files..\n";
73 print "Checking for cache from previous configure...\n";
75 print "Checking operating system version...\n";
78 if (!$config{MAX_CLIENT}) {
79 # If the cache hasn't set the max clients, copy the variable of MAX_CLIENT_T, this
80 # allows us to keep _T for testing purposes. (ie. "Are you sure you want to go
81 # higher than the found value" :))
82 $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
85 printf "Checking if strlcpy exists... ";
86 # Perform the strlcpy() test..
87 $config{HAS_STRLCPY} = "false";
89 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
92 while (chomp($line = <STRLCPY>))
94 # try and find the delcaration of:
96 if (($line =~ /size_t(\0x9|\s)+strlcpy(\0x9|\s)+\(/) || ($line =~ /size_t(\0x9|\s)+strlcpy\(/))
98 $config{HAS_STRLCPY} = "true";
103 print "yes\n" if $config{HAS_STRLCPY} eq "true";
104 print "no\n" if $config{HAS_STRLCPY} eq "false";
106 printf "Checking if kqueue exists... ";
109 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
112 while (chomp($line = <KQUEUE>))
114 # try and find the delcaration of:
116 if (($line =~ /int(\0x9|\s)+kqueue(\0x9|\s)+\(/) || ($line =~ /int(\0x9|\s)+kqueue\(/))
123 print "yes\n" if $has_kqueue == 1;
124 print "no\n" if $has_kqueue == 0;
126 printf "Checking if epoll exists... ";
129 open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
132 while (chomp($line = <EPOLL>))
134 # try and find the declaration of:
135 # extern int epoll_create (int __size) __THROW;
136 if (($line =~ /int(\0x9|\s)+epoll_create(\0x9|\s)+\(/) || ($line =~ /int(\0x9|\s)+epoll_create\(/))
143 print "yes\n" if $has_epoll == 1;
144 print "no\n" if $has_epoll == 0;
146 ################################################################################
147 # BEGIN INTERACTIVE PART #
148 ################################################################################
152 # Display Splash Logo..
154 chomp($wholeos = `uname -mnr`);
156 # Display Introduction Message..
158 Welcome to the InspIRCd Configuration program!
160 *** If you are unsure of any of these values, leave it blank for ***
161 *** standard settings that will work, and your server will run ***
162 *** using them. If you are running this server as part of a ***
163 *** larger network, you must consult with your network admins ***
164 *** for the proper values to use, or server links will be unstable! ***
166 Press \033[1m<RETURN>\033[0m to accept the default for any option, or enter
167 a new value. Please note: You will \033[1mHAVE\033[0m to read the docs
168 dir, otherwise you won't have a config file!
170 Your operating system is: \033[1;32m$config{OSNAME}\033[0m ($wholeos), fdmax: $config{MAX_CLIENT_T}\n\n";
172 # Directory Settings..
173 dir_check("are the configuration files", "CONFIG_DIR");
174 dir_check("are the modules to be compiled to", "MODULE_DIR");
175 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
176 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
179 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?");
182 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?");
184 $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y"));
187 print "No high-performance socket engines are available, or you chose\n";
188 print "not to enable one. Defaulting to select() engine.\n\n";
191 # File Descriptor Settings..
194 print "Maximum number of clients at any one time ($config{MAX_CLIENT_T})\n";
195 print "[\033[1;32m$config{MAX_CLIENT}\033[0m] -> ";
196 chomp($var = <STDIN>);
197 if ($var eq "") { $var = $config{MAX_CLIENT}; }
198 if ($var =~ /^\d+$/) {
199 if (($var > $config{MAX_CLIENT_T}) && ($fd_scan_failed ne true)) {
200 # Client has entered a larger number than the 'discovered' value
202 print "WARNING: Our scans have indicated that you are attempting
203 to use more sockets than there are avaliable. Are you sure
204 you wish to do this? It may cause the IRCd to malfunction [y/n]
205 [\033[1;32mn\033[0m] -> $c";
206 chomp($tmp = <STDIN>);
208 print "Please enter the correct value.\n\n";
213 print "You must enter a number in this field. Please try again.\n\n";
216 # If we get here, we should be good to go.
217 $config{MAX_CLIENT} = $var;
224 print "What is the Maximum length of nicknames?\n";
225 print "[\033[1;32m$config{NICK_LENGT}\033[0m] -> ";
226 chomp($var = <STDIN>);
227 if ($var eq "") { $var = $config{NICK_LENGT}; }
228 if ($var =~ /^\d+$/) {
229 # We don't care what the number is, set it and be on our way.
230 $config{NICK_LENGT} = $var;
234 print "You must enter a number in this field. Please try again.\n\n";
240 print "What is the Maximum number of mode changes in one line?\n";
241 print "[\033[1;32m$config{MAXI_MODES}\033[0m] -> ";
242 chomp($var = <STDIN>);
243 if ($var eq "") { $var = $config{MAXI_MODES}; }
244 if ($var =~ /^\d+$/) {
245 # We don't care what the number is, set it and be on our way.
246 $config{MAXI_MODES} = $var;
250 print "You must enter a number in this field. Please try again.\n\n";
255 print "Enter the Level Of Binary optimisation. This is a number between 0 and 3 (inclusive)
256 The InspIRCd Team will _NOT_ support any bug reports above 0.
257 Also note, the IRCd behaviour will be different depending on this value.
258 Please read the documentation for more information.
260 The Higher the number, the more optimised your binary will be. This value will default to 0
261 If you either a) Dont enter a number, or b) Enter a value outside the range.\n";
262 print "[\033[1;32m$config{OPTIMITEMP}\033[0m] -> ";
263 chomp($var = <STDIN>);
265 $var = $config{OPTIMITEMP};
269 $config{OPTIMITEMP} = 1;
270 $config{OPTIMISATI} = "-O";
271 } elsif ($var eq "2") {
272 $config{OPTIMITEMP} = 2;
273 $config{OPTIMISATI} = "-O2";
274 } elsif ($var eq "3") {
275 $config{OPTIMITEMP} = 3;
276 $config{OPTIMISATI} = "-O3";
278 $config{OPTIMITEMP} = 0;
279 $config{OPTIMISATI} = "-g";
282 print "\n\033[1;32mPre-build configuration is complete!\033[0m\n\n";
283 print "\033[0mConfig path:\033[1;32m\t\t\t$config{CONFIG_DIR}\n";
284 print "\033[0mModule path:\033[1;32m\t\t\t$config{MODULE_DIR}\n";
285 print "\033[0mMax connections:\033[1;32m\t\t$config{MAX_CLIENT}\n";
286 print "\033[0mMax User Channels\033[1;32m\t\t$config{MAX_CHANNE}\n";
287 print "\033[0mMax nickname length:\033[1;32m\t\t$config{NICK_LENGT}\n";
288 print "\033[0mMax channel length:\033[1;32m\t\t$config{CHAN_LENGT}\n";
289 print "\033[0mMax mode length:\033[1;32m\t\t$config{MAXI_MODES}\n";
290 print "\033[0mGCC Version Found:\033[1;32m\t\t$config{GCCVER}.$config{GCC34}\n";
291 print "\033[0mOptimatizaton Flag:\033[1;32m\t\t$config{OPTIMISATI}\033[0m\n\n";
297 print "To build your server with these settings, please type '\033[1;32m$config{MAKEPROG}\033[0m' now.\n";
298 print "*** \033[1;32mRemember to edit your configuration files!!!\033[0m ***\n\n\n";
300 ################################################################################
302 ################################################################################
304 # Retrieves the .config.cache file, and loads values into the main config hash.
305 open(CACHE, ".config.cache") or return undef;
309 # Ignore Blank lines, and comments..
313 my ($key, $value) = split("=", $_);
314 $value =~ /^\"(.*)\"$/;
315 # Do something with data here!
323 # Dump the contents of %config
324 print "Writing \033[1;32mcache file\033[0m for future ./configures ...\n";
325 open(FILEHANDLE, ">.config.cache");
326 foreach $key (keys %config)
328 print FILEHANDLE "$key=\"$config{$key}\"\n";
334 my ($desc, $hash_key) = @_;
337 print "In what directory $desc?\n";
338 print "[\033[1;32m$config{$hash_key}\033[0m] -> ";
339 chomp($var = <STDIN>);
340 if ($var eq "") { $var = $config{$hash_key}; }
341 if ($var =~ /^\~\/(.+)$/) {
342 # Convert it to a full path..
343 $var = resolve_directory($ENV{HOME} . "/" . $1);
345 if (substr($var,0,1) ne "/")
347 # Assume relative Path was given.. fill in the rest.
348 $var = $this . "/$var";
350 $var = resolve_directory($var);
352 print "$var does not exist. Create it?\n[\033[1;32my\033[0m] ";
353 chomp($tmp = <STDIN>);
354 if (($tmp eq "") || ($tmp =~ /^y/i)) {
355 # Attempt to Create the Dir..
356 $chk = system("mkdir -p \"$var\" >> /dev/null 2>&1") / 256;
358 print "Unable to create directory. ($var)\n\n";
363 # They said they don't want to create, and we can't install there.
369 # Target exists, but is not a directory.
370 print "File $var exists, but is not a directory.\n\n";
374 # Either Dir Exists, or was created fine.
375 $config{$hash_key} = $var;
382 if ($config{OSNAME} =~ /BSD$/) {
383 $config{LDLIBS} = "-Ldl";
384 $config{FLAGS} = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual $config{OPTIMISATI}";
385 $config{MAKEPROG} = "gmake";
387 $config{LDLIBS} = "-ldl";
388 $config{FLAGS} = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual $config{OPTIMISATI}";
389 $config{MAKEPROG} = "make";
391 if ($config{OSNAME} =~ /SunOS/) {
392 # solaris/sunos needs these
393 # socket = bsd sockets api
395 # rt = POSIX realtime extensions
396 # resolv = inet_aton only (why isnt this in nsl?!)
397 $config{LDLIBS} = $config{LDLIBS} . " -lsocket -lnsl -lrt -lresolv";
415 opendir(DIRHANDLE, "src/modules");
416 foreach $name (sort readdir(DIRHANDLE)) {
417 if ($name =~ /^m_(.+)\.cpp$/)
427 print "Writing \033[1;32minspircd_config.h\033[0m\n";
428 # First File.. inspircd_config.h
429 chomp(my $incos = `uname -n -s -r`);
430 chomp(my $version = `sh ./src/version.sh`);
431 open(FILEHANDLE, ">include/inspircd_config.h");
432 print FILEHANDLE <<EOF;
433 /* Auto generated by configure, do not modify! */
434 #define SYSLOG_FACILITY LOG_DAEMON
435 #define SYSLOG_LEVEL LOG_NOTICE
436 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
437 #define MOD_PATH "$config{MODULE_DIR}"
438 #define VERSION "$version"
439 #define MAXCLIENTS $config{MAX_CLIENT}
440 #define NICKMAX $config{NICK_LENGT}
441 #define CHANMAX $config{CHAN_LENGT}
442 #define MAXCHANS $config{MAX_CHANNE}
443 #define MAXMODES $config{MAXI_MODES}
444 #define OPTIMISATION $config{OPTIMITEMP}
445 #define SYSTEM "$incos"
449 if ($config{OSNAME} =~ /SunOS/) {
450 print FILEHANDLE "#define IS_SOLARIS\n";
452 if ($config{GCCVER} > 3) {
453 print FILEHANDLE "#define GCC3\n";
454 print FILEHANDLE "#define GCC34\n";
458 if ($config{GCCVER} == 3) {
459 print FILEHANDLE "#define GCC3\n";
460 if ($config{GCC34} > 3) {
461 print FILEHANDLE "#define GCC34\n";
465 if ($config{HAS_STRLCPY} eq "true") {
466 print FILEHANDLE "#define HAS_STRLCPY\n";
469 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
470 print FILEHANDLE "#define USE_KQUEUE\n";
473 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
474 print FILEHANDLE "#define USE_EPOLL\n";
477 # user didn't choose either epoll or select for their OS.
478 # default them to USE_SELECT (ewwy puke puke)
480 print FILEHANDLE "#define USE_SELECT\n";
484 # Create a Modules List..
486 foreach $i (@modlist)
488 $modules .= "m_".$i.".so ";
490 chomp($modules); # Remove Redundant whitespace..
493 # Write all .in files.
496 opendir(DIRHANDLE, $this);
497 foreach $name (sort readdir(DIRHANDLE)) {
498 if ($name =~ /^\.(.+)\.inc$/)
501 # All .name.inc files need parsing!
503 open(FILEHANDLE, ".$file.inc");
504 while (<FILEHANDLE>) {
509 $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/;
510 $tmp =~ s/\@FLAGS\@/$config{FLAGS}/;
511 $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/;
512 $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/;
513 $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/;
514 $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/;
515 $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/;
516 $tmp =~ s/\@MODULES\@/$modules/;
518 print "Writing \033[1;32m$file\033[0m\n";
519 open(FILEHANDLE, ">$file");
520 print FILEHANDLE $tmp;
525 # Make inspircd executable!
526 chmod 0744, 'inspircd';
529 print "Writing \033[1;32msrc/modules/Makefile\033[0m\n";
530 open(FILEHANDLE, ">src/modules/Makefile");
531 print FILEHANDLE <<EOF;
532 # (C) ChatSpike development team
533 # Makefile by <Craig\@ChatSpike.net>
534 # Many Thanks to Andrew Church <achurch\@achurch.org>
535 # for assisting with making this work right.
537 # Automatically Generated by ./configure to add a modules
538 # please run ./configure --update
544 # Create a Modules List..
547 foreach $i (@modlist)
549 $flags = getcompilerflags("src/modules/m_".$i.".cpp");
550 print FILEHANDLE <<EOCHEESE;
551 m_$i.so: m_$i.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/servers.h ../../include/base.h
552 \$(CC) -pipe -I../../include \$(FLAGS) $flags -export-dynamic -c m_$i.cpp
553 \$(CC) \$(FLAGS) -shared $flags -o m_$i.so m_$i.o
554 cp m_$i.so \$(MODPATH)/
555 chmod 0700 \$(MODPATH)/m_$i.so
561 sub getcompilerflags {
565 if ($_ =~ /^\/\* \$CompileFlags: (.+) \*\/$/) {
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::\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... \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:::: \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:\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:\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: \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::\n";
582 print "\033[0m\033[0m....::..::::..:::......:::..:::::::::....::..:::::..:::......:::........:::\n\n";
585 sub resolve_directory {
587 return File::Spec->rel2abs($_[0]);
591 my ($flag,$prompt) = @_;
592 print "$prompt [\033[1;32m$config{$flag}\033[0m] -> ";
593 chomp($tmp = <STDIN>);
594 if ($tmp eq "") { $tmp = $config{$flag} }
596 if (($tmp eq "") || ($tmp =~ /^y/i)) {
597 $config{$flag} = "y";
599 $config{$flag} = "n";