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