]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - configure
Blah (ive committed so many times to fix this bug its not worth commenting here)
[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     if ($config{GCC34} > 3) {
370       print FILEHANDLE "#define GCC34\n";
371     }
372   }
373   if ($config{HAS_STRLCPY} eq "true") {
374     print FILEHANDLE "#define HAS_STRLCPY\n";
375   }
376   close(FILEHANDLE);
377
378   # Create a Modules List..
379   my $modules = "";
380   foreach $i (@modlist)
381   {
382     $modules .= "m_".$i.".so ";
383   }
384   chomp($modules);   # Remove Redundant whitespace..
385
386
387   # Write all .in files.
388   my $tmp = "";
389   my $file = "";
390   opendir(DIRHANDLE, $this);
391   foreach $name (sort readdir(DIRHANDLE)) {
392     if ($name =~ /^\.(.+)\.inc$/)
393     {
394       $file = $1;
395       # All .name.inc files need parsing!
396       $tmp = "";
397       open(FILEHANDLE, ".$file.inc");
398       while (<FILEHANDLE>) {
399         $tmp .= $_;
400       }
401       close(FILEHANDLE);
402
403       $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/;
404       $tmp =~ s/\@FLAGS\@/$config{FLAGS}/;
405       $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/;
406       $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/;
407       $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/;
408       $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/;
409       $tmp =~ s/\@MODULES\@/$modules/;
410
411       print "Writing \033[1;32m$file\033[0m\n";
412       open(FILEHANDLE, ">$file");
413       print FILEHANDLE $tmp;
414     }
415   }
416   closedir(DIRHANDLE);
417
418   # Make inspircd executable!
419   chmod 0744, 'inspircd';
420
421   # Modules Makefile..
422   print "Writing \033[1;32msrc/modules/Makefile\033[0m\n";
423   open(FILEHANDLE, ">src/modules/Makefile");
424   print FILEHANDLE <<EOF;
425 # (C) ChatSpike development team
426 # Makefile by <Craig@ChatSpike.net>
427 # Many Thanks to Andrew Church <achurch@achurch.org>
428 #    for assisting with making this work right.
429 #
430 # Automatically Generated by ./configure to add a modules
431 # please run ./configure --update
432
433 all: \$(MODULES)
434
435 EOF
436
437   # Create a Modules List..
438   my $modules = "";
439   my $flags = "";
440   foreach $i (@modlist)
441   {
442     $flags = getcompilerflags("src/modules/m_".$i.".cpp");
443     print FILEHANDLE <<EOCHEESE;
444 m_$i.so: m_$i.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/servers.h ../../include/base.h
445         \$(CC) -I../../include \$(FLAGS) -shared $flags -o m_$i.so m_$i.cpp
446         \@cp m_$i.so \$(MODPATH)/
447
448 EOCHEESE
449   }
450 }
451
452 sub getcompilerflags {
453   my ($file) = @_;
454   open(FLAGS, $file);
455   while (<FLAGS>) {
456     if ($_ =~ /^\/\* \$CompileFlags: (.+) \*\/$/) {
457       close(FLAGS);
458       return $1;
459     }
460   }
461   close(FLAGS);
462   return undef;
463 }
464
465 sub show_splash {
466   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";
467   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";
468   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";
469   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";
470   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";
471   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";
472   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";
473   print "\033[0m\033[0m....::..::::..:::......:::..:::::::::....::..:::::..:::......:::........:::\n\n";
474 }