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
36 $config{CC} = "g++"; # C++ compiler
38 if ((!$config{OSNAME}) || ($config{OSNAME} eq "")) {
39 chomp($config{OSNAME} = `/usr/bin/uname`);
40 if ((!$config{OSNAME}) || ($config{OSNAME} eq "")){
41 $config{OSNAME} = "Unknown";
45 if (!$config{MAX_CLIENT_T}) {
46 $config{MAX_CLIENT_T} = 1024; # Set a reasonable 'Default'
47 $fd_scan_fail = "true"; # Used Later
50 # Get and Set some important vars..
53 my $arg = $ARGV[0]; # Do Some Argument Checks..
54 if ($arg eq "-clean") { `rm -rf .config.cache`; } # Remove the config.cache file.
56 if ($arg eq "-update") {
57 # Does the cache file exist?
59 # No, No it doesn't.. *BASH*
60 print "You have not run ./configure before. Please do this before trying to run the update script.\n";
63 # We've Loaded the cache file and all our variables..
64 print "Updating Files..\n";
72 print "Checking for cache from previous configure...\n";
74 print "Checking operating system version...\n";
77 if (!$config{MAX_CLIENT}) {
78 # If the cache hasn't set the max clients, copy the variable of MAX_CLIENT_T, this
79 # allows us to keep _T for testing purposes. (ie. "Are you sure you want to go
80 # higher than the found value" :))
81 $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
84 printf "Checking if strlcpy exists... ";
85 # Perform the strlcpy() test..
86 $config{HAS_STRLCPY} = "false";
88 open(STRLCPY, "</usr/include/string.h") or $fail = 1;
91 while (chomp($line = <STRLCPY>))
93 # try and find the delcaration of:
95 if ($line =~ /size_t(\0x9|\s)+strlcpy/)
97 $config{HAS_STRLCPY} = "true";
102 print "yes\n" if $config{HAS_STRLCPY} eq "true";
103 print "no\n" if $config{HAS_STRLCPY} eq "false";
105 printf "Checking if kqueue exists... ";
108 open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
111 while (chomp($line = <KQUEUE>))
113 # try and find the delcaration of:
115 if (($line =~ /int(\0x9|\s)+kqueue(\0x9|\s)+\(/) || ($line =~ /int(\0x9|\s)+kqueue\(/))
122 print "yes\n" if $has_kqueue == 1;
123 print "no\n" if $has_kqueue == 0;
125 printf "Checking if epoll exists... ";
128 open(EPOLL, "</usr/include/sys/epoll.h") or $fail = 1;
131 while (chomp($line = <EPOLL>))
133 # try and find the declaration of:
134 # extern int epoll_create (int __size) __THROW;
135 if (($line =~ /int(\0x9|\s)+epoll_create(\0x9|\s)+\(/) || ($line =~ /int(\0x9|\s)+epoll_create\(/))
142 print "yes\n" if $has_epoll == 1;
143 print "no\n" if $has_epoll == 0;
145 ################################################################################
146 # BEGIN INTERACTIVE PART #
147 ################################################################################
151 # Display Splash Logo..
153 chomp($wholeos = `uname -mnr`);
155 # Display Introduction Message..
157 Welcome to the InspIRCd Configuration program!
159 *** If you are unsure of any of these values, leave it blank for ***
160 *** standard settings that will work, and your server will run ***
161 *** using them. If you are running this server as part of a ***
162 *** larger network, you must consult with your network admins ***
163 *** for the proper values to use, or server links will be unstable! ***
165 Press \033[1m<RETURN>\033[0m to accept the default for any option, or enter
166 a new value. Please note: You will \033[1mHAVE\033[0m to read the docs
167 dir, otherwise you won't have a config file!
169 Your operating system is: \033[1;32m$config{OSNAME}\033[0m ($wholeos), fdmax: $config{MAX_CLIENT_T}\n\n";
171 # Directory Settings..
172 dir_check("are the configuration files", "CONFIG_DIR");
173 dir_check("are the modules to be compiled to", "MODULE_DIR");
174 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
175 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
178 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?");
181 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?");
183 $chose_hiperf = (($config{USE_EPOLL} eq "y") || ($config{USE_KQUEUE} eq "y"));
186 print "No high-performance socket engines are available, or you chose\n";
187 print "not to enable one. Defaulting to select() engine.\n\n";
190 # File Descriptor Settings..
193 print "Maximum number of clients at any one time ($config{MAX_CLIENT_T})\n";
194 print "[\033[1;32m$config{MAX_CLIENT}\033[0m] -> ";
195 chomp($var = <STDIN>);
196 if ($var eq "") { $var = $config{MAX_CLIENT}; }
197 if ($var =~ /^\d+$/) {
198 if (($var > $config{MAX_CLIENT_T}) && ($fd_scan_failed ne true)) {
199 # Client has entered a larger number than the 'discovered' value
201 print "WARNING: Our scans have indicated that you are attempting
202 to use more sockets than there are avaliable. Are you sure
203 you wish to do this? It may cause the IRCd to malfunction [y/n]
204 [\033[1;32mn\033[0m] -> $c";
205 chomp($tmp = <STDIN>);
207 print "Please enter the correct value.\n\n";
212 print "You must enter a number in this field. Please try again.\n\n";
215 # If we get here, we should be good to go.
216 $config{MAX_CLIENT} = $var;
223 print "What is the Maximum length of nicknames?\n";
224 print "[\033[1;32m$config{NICK_LENGT}\033[0m] -> ";
225 chomp($var = <STDIN>);
226 if ($var eq "") { $var = $config{NICK_LENGT}; }
227 if ($var =~ /^\d+$/) {
228 # We don't care what the number is, set it and be on our way.
229 $config{NICK_LENGT} = $var;
233 print "You must enter a number in this field. Please try again.\n\n";
239 print "What is the Maximum number of mode changes in one line?\n";
240 print "[\033[1;32m$config{MAXI_MODES}\033[0m] -> ";
241 chomp($var = <STDIN>);
242 if ($var eq "") { $var = $config{MAXI_MODES}; }
243 if ($var =~ /^\d+$/) {
244 # We don't care what the number is, set it and be on our way.
245 $config{MAXI_MODES} = $var;
249 print "You must enter a number in this field. Please try again.\n\n";
254 print "Enter the Level Of Binary optimisation. This is a number between 0 and 3 (inclusive)
255 The InspIRCd Team will _NOT_ support any bug reports above 0.
256 Also note, the IRCd behaviour will be different depending on this value.
257 Please read the documentation for more information.
259 The Higher the number, the more optimised your binary will be. This value will default to 0
260 If you either a) Dont enter a number, or b) Enter a value outside the range.\n";
261 print "[\033[1;32m$config{OPTIMITEMP}\033[0m] -> ";
262 chomp($var = <STDIN>);
264 $var = $config{OPTIMITEMP};
268 $config{OPTIMITEMP} = 1;
269 $config{OPTIMISATI} = "-O";
270 } elsif ($var eq "2") {
271 $config{OPTIMITEMP} = 2;
272 $config{OPTIMISATI} = "-O2";
273 } elsif ($var eq "3") {
274 $config{OPTIMITEMP} = 3;
275 $config{OPTIMISATI} = "-O3";
277 $config{OPTIMITEMP} = 0;
278 $config{OPTIMISATI} = "-g";
281 print "\n\033[1;32mPre-build configuration is complete!\033[0m\n\n";
282 print "\033[0mConfig path:\033[1;32m\t\t\t$config{CONFIG_DIR}\n";
283 print "\033[0mModule path:\033[1;32m\t\t\t$config{MODULE_DIR}\n";
284 print "\033[0mMax connections:\033[1;32m\t\t$config{MAX_CLIENT}\n";
285 print "\033[0mMax User Channels\033[1;32m\t\t$config{MAX_CHANNE}\n";
286 print "\033[0mMax nickname length:\033[1;32m\t\t$config{NICK_LENGT}\n";
287 print "\033[0mMax channel length:\033[1;32m\t\t$config{CHAN_LENGT}\n";
288 print "\033[0mMax mode length:\033[1;32m\t\t$config{MAXI_MODES}\n";
289 print "\033[0mGCC Version Found:\033[1;32m\t\t$config{GCCVER}.$config{GCC34}\n";
290 print "\033[0mOptimatizaton Flag:\033[1;32m\t\t$config{OPTIMISATI}\033[0m\n";
291 print "\033[0mCompiler program:\033[1;32m\t\t$config{CC}\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";
299 if (($config{OSNAME} eq "OpenBSD") && ($config{CC} ne "eg++")) {
300 print "\033[1;32mWARNING!\033[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";
303 ################################################################################
305 ################################################################################
307 # Retrieves the .config.cache file, and loads values into the main config hash.
308 open(CACHE, ".config.cache") or return undef;
312 # Ignore Blank lines, and comments..
316 my ($key, $value) = split("=", $_);
317 $value =~ /^\"(.*)\"$/;
318 # Do something with data here!
326 # Dump the contents of %config
327 print "Writing \033[1;32mcache file\033[0m for future ./configures ...\n";
328 open(FILEHANDLE, ">.config.cache");
329 foreach $key (keys %config)
331 print FILEHANDLE "$key=\"$config{$key}\"\n";
337 my ($desc, $hash_key) = @_;
340 print "In what directory $desc?\n";
341 print "[\033[1;32m$config{$hash_key}\033[0m] -> ";
342 chomp($var = <STDIN>);
343 if ($var eq "") { $var = $config{$hash_key}; }
344 if ($var =~ /^\~\/(.+)$/) {
345 # Convert it to a full path..
346 $var = resolve_directory($ENV{HOME} . "/" . $1);
348 if (substr($var,0,1) ne "/")
350 # Assume relative Path was given.. fill in the rest.
351 $var = $this . "/$var";
353 $var = resolve_directory($var);
355 print "$var does not exist. Create it?\n[\033[1;32my\033[0m] ";
356 chomp($tmp = <STDIN>);
357 if (($tmp eq "") || ($tmp =~ /^y/i)) {
358 # Attempt to Create the Dir..
359 $chk = system("mkdir -p \"$var\" >> /dev/null 2>&1") / 256;
361 print "Unable to create directory. ($var)\n\n";
366 # They said they don't want to create, and we can't install there.
372 # Target exists, but is not a directory.
373 print "File $var exists, but is not a directory.\n\n";
377 # Either Dir Exists, or was created fine.
378 $config{$hash_key} = $var;
385 if ($config{OSNAME} =~ /BSD$/) {
386 $config{LDLIBS} = "-Ldl";
387 $config{FLAGS} = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual $config{OPTIMISATI}";
388 $config{MAKEPROG} = "gmake";
389 if ($config{OSNAME} eq "OpenBSD") {
390 chomp($foo = `eg++ -dumpversion | cut -c 1`);
391 # theyre running the package version of gcc (eg++)... detect it and set up its version numbers.
392 # if theyre not running this, configure lets the build continue but they probably wont manage to
393 # compile as this standard version is 2.95.3!
395 $config{CC} = "eg++";
396 chomp($config{GCCVER} = `eg++ -dumpversion | cut -c 1`); # we must redo these if we change
397 chomp($config{GCC34} = `eg++ -dumpversion | cut -c 3`); # the compiler path
401 $config{LDLIBS} = "-ldl";
402 $config{FLAGS} = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual $config{OPTIMISATI}";
403 $config{MAKEPROG} = "make";
405 if ($config{OSNAME} =~ /SunOS/) {
406 # solaris/sunos needs these
407 # socket = bsd sockets api
409 # rt = POSIX realtime extensions
410 # resolv = inet_aton only (why isnt this in nsl?!)
411 $config{LDLIBS} = $config{LDLIBS} . " -lsocket -lnsl -lrt -lresolv";
429 opendir(DIRHANDLE, "src/modules");
430 foreach $name (sort readdir(DIRHANDLE)) {
431 if ($name =~ /^m_(.+)\.cpp$/)
441 print "Writing \033[1;32minspircd_config.h\033[0m\n";
442 # First File.. inspircd_config.h
443 chomp(my $incos = `uname -n -s -r`);
444 chomp(my $version = `sh ./src/version.sh`);
445 open(FILEHANDLE, ">include/inspircd_config.h");
446 print FILEHANDLE <<EOF;
447 /* Auto generated by configure, do not modify! */
448 #define SYSLOG_FACILITY LOG_DAEMON
449 #define SYSLOG_LEVEL LOG_NOTICE
450 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
451 #define MOD_PATH "$config{MODULE_DIR}"
452 #define VERSION "$version"
453 #define MAXCLIENTS $config{MAX_CLIENT}
454 #define NICKMAX $config{NICK_LENGT}
455 #define CHANMAX $config{CHAN_LENGT}
456 #define MAXCHANS $config{MAX_CHANNE}
457 #define MAXMODES $config{MAXI_MODES}
458 #define OPTIMISATION $config{OPTIMITEMP}
459 #define SYSTEM "$incos"
463 if ($config{OSNAME} =~ /SunOS/) {
464 print FILEHANDLE "#define IS_SOLARIS\n";
466 if ($config{GCCVER} > 3) {
467 print FILEHANDLE "#define GCC3\n";
468 print FILEHANDLE "#define GCC34\n";
472 if ($config{GCCVER} == 3) {
473 print FILEHANDLE "#define GCC3\n";
474 if ($config{GCC34} > 3) {
475 print FILEHANDLE "#define GCC34\n";
479 if ($config{HAS_STRLCPY} eq "true") {
480 print FILEHANDLE "#define HAS_STRLCPY\n";
483 if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
484 print FILEHANDLE "#define USE_KQUEUE\n";
487 if (($has_epoll) && ($config{USE_EPOLL} eq "y")) {
488 print FILEHANDLE "#define USE_EPOLL\n";
491 # user didn't choose either epoll or select for their OS.
492 # default them to USE_SELECT (ewwy puke puke)
494 print FILEHANDLE "#define USE_SELECT\n";
498 # Create a Modules List..
500 foreach $i (@modlist)
502 $modules .= "m_".$i.".so ";
504 chomp($modules); # Remove Redundant whitespace..
507 # Write all .in files.
510 opendir(DIRHANDLE, $this);
511 foreach $name (sort readdir(DIRHANDLE)) {
512 if ($name =~ /^\.(.+)\.inc$/)
515 # All .name.inc files need parsing!
517 open(FILEHANDLE, ".$file.inc");
518 while (<FILEHANDLE>) {
523 $tmp =~ s/\@CC\@/$config{CC}/;
524 $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/;
525 $tmp =~ s/\@FLAGS\@/$config{FLAGS}/;
526 $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/;
527 $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/;
528 $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/;
529 $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/;
530 $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/;
531 $tmp =~ s/\@MODULES\@/$modules/;
533 print "Writing \033[1;32m$file\033[0m\n";
534 open(FILEHANDLE, ">$file");
535 print FILEHANDLE $tmp;
540 # Make inspircd executable!
541 chmod 0744, 'inspircd';
544 print "Writing \033[1;32msrc/modules/Makefile\033[0m\n";
545 open(FILEHANDLE, ">src/modules/Makefile");
546 print FILEHANDLE <<EOF;
547 # (C) ChatSpike development team
548 # Makefile by <Craig\@ChatSpike.net>
549 # Many Thanks to Andrew Church <achurch\@achurch.org>
550 # for assisting with making this work right.
552 # Automatically Generated by ./configure to add a modules
553 # please run ./configure --update
559 # Create a Modules List..
562 foreach $i (@modlist)
564 $flags = getcompilerflags("src/modules/m_".$i.".cpp");
565 print FILEHANDLE <<EOCHEESE;
566 m_$i.so: m_$i.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/servers.h ../../include/base.h
567 \$(CC) -pipe -I../../include \$(FLAGS) $flags -export-dynamic -c m_$i.cpp
568 \$(CC) \$(FLAGS) -shared $flags -o m_$i.so m_$i.o
569 cp m_$i.so \$(MODPATH)/
570 chmod 0700 \$(MODPATH)/m_$i.so
576 sub getcompilerflags {
580 if ($_ =~ /^\/\* \$CompileFlags: (.+) \*\/$/) {
590 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";
591 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";
592 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";
593 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";
594 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";
595 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";
596 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";
597 print "\033[0m\033[0m....::..::::..:::......:::..:::::::::....::..:::::..:::......:::........:::\n\n";
600 sub resolve_directory {
602 return File::Spec->rel2abs($_[0]);
606 my ($flag,$prompt) = @_;
607 print "$prompt [\033[1;32m$config{$flag}\033[0m] -> ";
608 chomp($tmp = <STDIN>);
609 if ($tmp eq "") { $tmp = $config{$flag} }
611 if (($tmp eq "") || ($tmp =~ /^y/i)) {
612 $config{$flag} = "y";
614 $config{$flag} = "n";