]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - configure
Added and tested fd crossreference table - improves speed a lot, and fixes one of...
[user/henk/code/inspircd.git] / configure
1 #!/usr/bin/perl
2 # InspIRCd Configuration Script
3 #
4 # Copyright 2003 The ChatSpike Development Team
5 # <brain@chatspike.net>
6 # <Craig@chatspike.net>
7 #
8 # [14:21] Brain: <matrix impression> i know perl-fu!
9 #
10 # $Id$
11 #
12 ########################################
13
14
15 $this = $ENV{PWD};                                              # PWD, Regardless.
16 @modlist = ();                                                  # Declare for Module List..
17 %config = ();                                                   # Initiate Configuration Hash..
18 $config{ME}                 = $ENV{PWD};                        # Present Working Directory
19 $config{CONFIG_DIR}         = $ENV{PWD}."/conf";                # Configuration Directory
20 $config{MODULE_DIR}         = $ENV{PWD}."/modules";             # Modules Directory
21 $config{BINARY_DIR}         = $ENV{PWD}."/bin";                 # Binary Directory
22 $config{OPTIMITEMP}         = "0";                              # Default Optimisation Value
23 $config{OPTIMISATI}         = "-g";                             # Optimisation Flag
24 $config{NICK_LENGT}         = "32";                             # Default Nick Length
25 $config{CHAN_LENGT}         = "64";                             # Default Channel Name Length
26 $config{MAX_CHANNE}         = "20";                             # Default Max. Channels per user..
27 $config{MAXI_MODES}         = "20";                             # Default Max. Number of Modes set at once.
28 $config{HAS_STRLCPY}        = "false";                          # strlcpy Check.
29 chomp($config{MAX_CLIENT_T} = `sh -c \"ulimit -n\"`);           # FD Limit
30 chomp($config{GCCVER}       = `gcc -dumpversion | cut -c 1`);   # Major GCC Version
31 chomp($config{GCC34}        = `gcc -dumpversion | cut -c 3`);   # Minor GCC Version
32 chomp($config{OSNAME}       = `uname -s`);                      # Operating System Name
33
34 if (!$config{OSNAME}) {
35   $config{OSNAME} = "Unknown";                                  # For use when uname fails.
36 }
37
38 if (!$config{MAX_CLIENT_T}) { 
39   $config{MAX_CLIENT_T} = 1024;                                 # Set a reasonable 'Default'
40   $fd_scan_fail = "true";                                       # Used Later
41 }
42
43 # Get and Set some important vars..
44 getosflags();
45 getmodules();
46
47 my $arg = $ARGV[0];                                             # Do Some Argument Checks..
48 if ($arg eq "-clean") { `rm -rf .config.cache`; }               # Remove the config.cache file.
49
50 if ($arg eq "-update") {
51   # Does the cache file exist?
52   if (!getcache()) {
53     # No, No it doesn't.. *BASH*
54     print "You have not run ./configure before. Please do this before trying to run the update script.\n";
55     exit 0;
56   } else {
57     # We've Loaded the cache file and all our variables..
58     print "Updating Files..\n";
59     writefiles();
60     print "Complete.\n";
61     exit;
62   }
63 }
64
65 getcache();                                                      # Load the config.cache file.
66
67 if (!$config{MAX_CLIENT}) { 
68   # If the cache hasn't set the max clients, copy the variable of MAX_CLIENT_T, this
69   # allows us to keep _T for testing purposes. (ie. "Are you sure you want to go
70   # higher than the found value" :))
71   $config{MAX_CLIENT} = $config{MAX_CLIENT_T};
72 }
73
74 # Perform the strlcpy() test..
75 open(STRLCPY, ">.test.cpp");
76 print STRLCPY "#include <string.h>
77 #include <stdio.h>
78 int main() { char a[10]; char b[10]; strlcpy(a,b,10); printf(\"%d\\n\",9); }\n";
79 close(STRLCPY);
80
81 # Build the Binary..
82 system("g++ -o .test .test.cpp 2>&1");
83
84 # Was the build succesful?
85 if (-e ".test") {
86   $config{HAS_STRLCPY} = "true";
87   system("rm -f .test .test.cpp");
88 }
89
90 ################################################################################
91 #                          BEGIN INTERACTIVE PART                              #
92 ################################################################################
93
94 # Clear the Screen..
95 system("clear");
96 # Display Splash Logo..
97 show_splash();
98 chomp($wholeos = `uname -mnr`);
99
100 # Display Introduction Message..
101 print "
102 Welcome to the InspIRCd Configuration program!
103
104 *** If you are unsure of any of these values, leave it blank for    ***
105 *** standard settings that will work, and your server will run      ***
106 *** using them. If you are running this server as part of a         ***
107 *** larger network, you must consult with your network admins       ***
108 *** for the proper values to use, or server links will be unstable! ***
109
110 Press \033[1m<RETURN>\033[0m to accept the default for any option, or enter
111 a new value. Please note: You will \033[1mHAVE\033[0m to read the docs
112 dir, otherwise you won't have a config file!
113
114 Your operating system is: \033[1;32m$config{OSNAME}\033[0m ($wholeos), fdmax: $config{MAX_CLIENT_T}\n\n";
115
116 # Directory Settings..
117 dir_check("are the configuration files", "CONFIG_DIR");
118 dir_check("are the modules to be compiled to", "MODULE_DIR");
119 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
120
121 # File Descriptor Settings..
122 my $continue = 0;
123 while (!$continue) {
124   print "Maximum number of clients at any one time ($config{MAX_CLIENT_T})\n";
125   print "[\033[1;32m$config{MAX_CLIENT}\033[0m] -> ";
126   chomp($var = <STDIN>);
127   if ($var eq "") { $var = $config{MAX_CLIENT}; }
128   if ($var =~ /^\d+$/) {
129     if (($var > $config{MAX_CLIENT_T}) && ($fd_scan_failed ne true)) {
130       # Client has entered a larger number than the 'discovered' value
131       # Confirm.
132       print "WARNING: Our scans have indicated that you are attempting
133 to use more sockets than there are avaliable. Are you sure
134 you wish to do this? It may cause the IRCd to malfunction [y/n]
135 [\033[1;32mn\033[0m] -> $c";
136       chomp($tmp = <STDIN>);
137       if ($tmp ne "y") {
138         print "Please enter the correct value.\n\n";
139         next;
140       }
141     }
142   } else {
143     print "You must enter a number in this field. Please try again.\n\n";
144     next;
145   }
146   # If we get here, we should be good to go.
147   $config{MAX_CLIENT} = $var;
148   $continue = 1;
149   print "\n";
150 }
151
152 my $continue = 0;
153 while (!$continue) {
154   print "What is the Maximum length of nicknames?\n";
155   print "[\033[1;32m$config{NICK_LENGT}\033[0m] -> ";
156   chomp($var = <STDIN>);
157   if ($var eq "") { $var = $config{NICK_LENGT}; }
158   if ($var =~ /^\d+$/) {
159     # We don't care what the number is, set it and be on our way.
160     $config{NICK_LENGT} = $var;
161     $continue = 1;
162     print "\n";
163   } else {
164     print "You must enter a number in this field. Please try again.\n\n";
165   }
166 }
167
168 my $continue = 0;
169 while (!$continue) {
170   print "What is the Maximum number of mode changes in one line?\n";
171   print "[\033[1;32m$config{MAXI_MODES}\033[0m] -> ";
172   chomp($var = <STDIN>);
173   if ($var eq "") { $var = $config{MAXI_MODES}; }
174   if ($var =~ /^\d+$/) {
175     # We don't care what the number is, set it and be on our way.
176     $config{MAXI_MODES} = $var;
177     $continue = 1;
178     print "\n";
179   } else {
180     print "You must enter a number in this field. Please try again.\n\n";
181   }
182 }
183
184 # Code Optimisation
185 print "Enter the Level Of Binary optimisation. This is a number between 0 and 3 (inclusive)
186 The InspIRCd Team will _NOT_ support any bug reports above 0.
187 Also note, the IRCd behaviour will be different depending on this value.
188 Please read the documentation for more information.
189
190 The Higher the number, the more optimised your binary will be. This value will default to 0
191 If you either a) Dont enter a number, or b) Enter a value outside the range.\n";
192 print "[\033[1;32m0\033[0m] -> ";
193 chomp($var = <STDIN>);
194 if ($var == 1) {
195   $config{OPTIMITEMP} = 1;
196   $config{OPTIMISATI} = "-O";
197 } elsif ($var == 2) {
198   $config{OPTIMITEMP} = 2;
199   $config{OPTIMISATI} = "-O2";
200 } elsif ($var == 3) {
201   $config{OPTIMITEMP} = 3;
202   $config{OPTIMISATI} = "-O3";
203 } else {
204   $config{OPTIMITEMP} = 0;
205   $config{OPTIMISATI} = "-g";
206 }
207
208 print "\n\033[1;32mPre-build configuration is complete!\033[0m\n\n";
209 print "\033[0mConfig path:\033[1;32m\t\t\t$config{CONFIG_DIR}\n";
210 print "\033[0mModule path:\033[1;32m\t\t\t$config{MODULE_DIR}\n";
211 print "\033[0mMax connections:\033[1;32m\t\t$config{MAX_CLIENT}\n";
212 print "\033[0mMax User Channels\033[1;32m\t\t$config{MAX_CHANNE}\n";
213 print "\033[0mMax nickname length:\033[1;32m\t\t$config{NICK_LENGT}\n";
214 print "\033[0mMax channel length:\033[1;32m\t\t$config{CHAN_LENGT}\n";
215 print "\033[0mMax mode length:\033[1;32m\t\t$config{MAXI_MODES}\n";
216 print "\033[0mGCC Version Found:\033[1;32m\t\t$config{GCCVER}.$config{GCC34}\n";
217 print "\033[0mOptimatizaton Flag:\033[1;32m\t\t$config{OPTIMISATI}\033[0m\n\n";
218
219 makecache();
220 writefiles();
221
222 print "\n\n";
223 print "To build your server with these settings, please type '\033[1;32m$config{MAKEPROG}\033[0m' now.\n";
224 print "*** \033[1;32mRemember to edit your configuration files!!!\033[0m ***\n\n\n";
225
226 ################################################################################
227 #                              HELPER FUNCTIONS                                #
228 ################################################################################
229 sub getcache {
230   # Retrieves the .config.cache file, and loads values into the main config hash.
231   open(CACHE, ".config.cache") or return undef;
232   while (<CACHE>) {
233     chomp;
234
235     # Ignore Blank lines, and comments..
236     next if /^\s*$/;
237     next if /^\s*#/;
238
239     my ($key, $value) = split("=", $_);
240     $value =~ /^\"(.*)\"$/;
241     # Do something with data here!
242     $config{$key} = $1;
243   }
244   close(CONFIG);
245   return "true";
246 }
247
248 sub makecache {
249   # Dump the contents of %config
250   print "Writing \033[1;32mcache file\033[0m for future ./configures ...\n";
251   open(FILEHANDLE, ">.config.cache");
252   foreach $key (keys %config)
253   {
254     print FILEHANDLE "$key=\"$config{$key}\"\n";
255   }
256   close(FILEHANDLE);
257 }
258
259 sub dir_check {
260   my ($desc, $hash_key) = @_;
261   my $complete = 0;
262   while (!$complete) {
263     print "In what directory $desc?\n";
264     print "[\033[1;32m$config{$hash_key}\033[0m] -> ";
265     chomp($var = <STDIN>);
266     if ($var eq "") { $var = $config{$hash_key}; }
267     if (substr($var,0,1) ne "/")
268     {
269         # Assume relative Path was given.. fill in the rest.
270         $var = $this . "/$var";
271     }
272     if (substr($var, 0, 1) eq "~") {
273         # Convert it to a full path..
274         
275         $var = $this . substr(1,0);
276     } 
277     if (! -e $var) {
278       print "$var does not exist. Create it?\n[\033[1;32my\033[0m] ";
279       chomp($tmp = <STDIN>);
280       if (($tmp eq "") || ($tmp = "y")) {
281         # Attempt to Create the Dir..
282         $chk = system("mkdir -p \"$var\" >> /dev/null 2>&1") / 256;
283         if ($chk != 0) {
284           print "Unable to create directory. ($var)\n\n";
285           # Restart Loop..
286           next;
287         }
288       } else {
289         # They said they don't want to create, and we can't install there.
290         print "\n\n";
291         next;
292       }
293     } else {
294       if (!is_dir($var)) {
295         # Target exists, but is not a directory.
296         print "File $var exists, but is not a directory.\n\n";
297         next;
298       }
299     }
300     # Either Dir Exists, or was created fine.
301     $config{$hash_key} = $var;
302     $complete = 1;
303     print "\n";
304   }
305 }
306
307 sub getosflags {
308   if ($config{OSNAME} eq "FreeBSD") {
309     $config{LDLIBS} = "-Ldl";
310     $config{FLAGS}  = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual -g";
311     $config{MAKEPROG} = "gmake";
312   } else {
313     $config{LDLIBS} = "-ldl";
314     $config{FLAGS}  = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual -g";
315     $config{MAKEPROG} = "make";
316   }
317 }
318
319 sub is_dir {
320   my ($path) = @_;
321   if (chdir($path)) {
322     chdir($this);
323     return 1;
324   } else {
325     # Just in case..
326     chdir($this);
327     return 0;
328   }
329 }
330
331 sub getmodules {
332   my $i = 0;
333   opendir(DIRHANDLE, "src/modules");
334   foreach $name (sort readdir(DIRHANDLE)) {
335     if ($name =~ /^m_(.+)\.cpp$/)
336     {
337       $modlist[$i++] = $1;
338     }
339   }
340   closedir(DIRHANDLE);
341 }
342
343 sub writefiles {
344
345   print "Writing \033[1;32minspircd_config.h\033[0m\n";
346   # First File.. inspircd_config.h
347   chomp(my $incos = `uname -n -s -r`);
348   chomp(my $version = `sh ./src/version.sh`);
349   open(FILEHANDLE, "> include/inspircd_config.h");
350   print FILEHANDLE <<EOF;
351 /* Auto generated by configure, do not modify! */
352 #define SYSLOG_FACILITY LOG_DAEMON
353 #define SYSLOG_LEVEL LOG_NOTICE
354 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
355 #define MOD_PATH "$config{MODULE_DIR}"
356 #define VERSION "$version"
357 #define MAXCLIENTS $config{MAX_CLIENT}
358 #define NICKMAX $config{NICK_LENGT}
359 #define CHANMAX $config{CHAN_LENGT}
360 #define MAXCHANS $config{MAX_CHANNE}
361 #define MAXMODES $config{MAXI_MODES}
362 #define OPTIMISATION $config{OPTIMITEMP}
363 #define SYSTEM "$incos"
364 #define MAXBUF 514
365 EOF
366
367   if ($config{GCCVER} > 3) {
368     print FILEHANDLE "#define GCC3\n";
369     print FILEHANDLE "#define GCC34\n";
370   }
371   else
372   {
373     if ($config{GCCVER} == 3) {
374       print FILEHANDLE "#define GCC3\n";
375       if ($config{GCC34} > 3) {
376         print FILEHANDLE "#define GCC34\n";
377       }
378     }
379   }
380   if ($config{HAS_STRLCPY} eq "true") {
381     print FILEHANDLE "#define HAS_STRLCPY\n";
382   }
383   close(FILEHANDLE);
384
385   # Create a Modules List..
386   my $modules = "";
387   foreach $i (@modlist)
388   {
389     $modules .= "m_".$i.".so ";
390   }
391   chomp($modules);   # Remove Redundant whitespace..
392
393
394   # Write all .in files.
395   my $tmp = "";
396   my $file = "";
397   opendir(DIRHANDLE, $this);
398   foreach $name (sort readdir(DIRHANDLE)) {
399     if ($name =~ /^\.(.+)\.inc$/)
400     {
401       $file = $1;
402       # All .name.inc files need parsing!
403       $tmp = "";
404       open(FILEHANDLE, ".$file.inc");
405       while (<FILEHANDLE>) {
406         $tmp .= $_;
407       }
408       close(FILEHANDLE);
409
410       $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/;
411       $tmp =~ s/\@FLAGS\@/$config{FLAGS}/;
412       $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/;
413       $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/;
414       $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/;
415       $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/;
416       $tmp =~ s/\@MODULES\@/$modules/;
417
418       print "Writing \033[1;32m$file\033[0m\n";
419       open(FILEHANDLE, ">$file");
420       print FILEHANDLE $tmp;
421     }
422   }
423   closedir(DIRHANDLE);
424
425   # Make inspircd executable!
426   chmod 0744, 'inspircd';
427
428   # Modules Makefile..
429   print "Writing \033[1;32msrc/modules/Makefile\033[0m\n";
430   open(FILEHANDLE, ">src/modules/Makefile");
431   print FILEHANDLE <<EOF;
432 # (C) ChatSpike development team
433 # Makefile by <Craig\@ChatSpike.net>
434 # Many Thanks to Andrew Church <achurch@achurch.org>
435 #    for assisting with making this work right.
436 #
437 # Automatically Generated by ./configure to add a modules
438 # please run ./configure --update
439
440 all: \$(MODULES)
441
442 EOF
443
444   # Create a Modules List..
445   my $modules = "";
446   my $flags = "";
447   foreach $i (@modlist)
448   {
449     $flags = getcompilerflags("src/modules/m_".$i.".cpp");
450     print FILEHANDLE <<EOCHEESE;
451 m_$i.so: m_$i.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/servers.h ../../include/base.h
452         \$(CC) -I../../include \$(FLAGS) -shared $flags -o m_$i.so m_$i.cpp
453         \@cp m_$i.so \$(MODPATH)/
454
455 EOCHEESE
456   }
457 }
458
459 sub getcompilerflags {
460   my ($file) = @_;
461   open(FLAGS, $file);
462   while (<FLAGS>) {
463     if ($_ =~ /^\/\* \$CompileFlags: (.+) \*\/$/) {
464       close(FLAGS);
465       return $1;
466     }
467   }
468   close(FLAGS);
469   return undef;
470 }
471
472 sub show_splash {
473   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";
474   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";
475   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";
476   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";
477   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";
478   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";
479   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";
480   print "\033[0m\033[0m....::..::::..:::......:::..:::::::::....::..:::::..:::......:::........:::\n\n";
481 }