]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - configure
Fixed kqueue setting not being changed
[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}         = "false";                                          # 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         if (yesno(0,"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                 $config{USE_KQUEUE} = "true";
129         }
130         else
131         {
132                 $config{USE_KQUEUE} = "false";
133         }
134 }
135
136 # File Descriptor Settings..
137 my $continue = 0;
138 while (!$continue) {
139   print "Maximum number of clients at any one time ($config{MAX_CLIENT_T})\n";
140   print "[\033[1;32m$config{MAX_CLIENT}\033[0m] -> ";
141   chomp($var = <STDIN>);
142   if ($var eq "") { $var = $config{MAX_CLIENT}; }
143   if ($var =~ /^\d+$/) {
144     if (($var > $config{MAX_CLIENT_T}) && ($fd_scan_failed ne true)) {
145       # Client has entered a larger number than the 'discovered' value
146       # Confirm.
147       print "WARNING: Our scans have indicated that you are attempting
148 to use more sockets than there are avaliable. Are you sure
149 you wish to do this? It may cause the IRCd to malfunction [y/n]
150 [\033[1;32mn\033[0m] -> $c";
151       chomp($tmp = <STDIN>);
152       if ($tmp ne "y") {
153         print "Please enter the correct value.\n\n";
154         next;
155       }
156     }
157   } else {
158     print "You must enter a number in this field. Please try again.\n\n";
159     next;
160   }
161   # If we get here, we should be good to go.
162   $config{MAX_CLIENT} = $var;
163   $continue = 1;
164   print "\n";
165 }
166
167 my $continue = 0;
168 while (!$continue) {
169   print "What is the Maximum length of nicknames?\n";
170   print "[\033[1;32m$config{NICK_LENGT}\033[0m] -> ";
171   chomp($var = <STDIN>);
172   if ($var eq "") { $var = $config{NICK_LENGT}; }
173   if ($var =~ /^\d+$/) {
174     # We don't care what the number is, set it and be on our way.
175     $config{NICK_LENGT} = $var;
176     $continue = 1;
177     print "\n";
178   } else {
179     print "You must enter a number in this field. Please try again.\n\n";
180   }
181 }
182
183 my $continue = 0;
184 while (!$continue) {
185   print "What is the Maximum number of mode changes in one line?\n";
186   print "[\033[1;32m$config{MAXI_MODES}\033[0m] -> ";
187   chomp($var = <STDIN>);
188   if ($var eq "") { $var = $config{MAXI_MODES}; }
189   if ($var =~ /^\d+$/) {
190     # We don't care what the number is, set it and be on our way.
191     $config{MAXI_MODES} = $var;
192     $continue = 1;
193     print "\n";
194   } else {
195     print "You must enter a number in this field. Please try again.\n\n";
196   }
197 }
198
199 # Code Optimisation
200 print "Enter the Level Of Binary optimisation. This is a number between 0 and 3 (inclusive)
201 The InspIRCd Team will _NOT_ support any bug reports above 0.
202 Also note, the IRCd behaviour will be different depending on this value.
203 Please read the documentation for more information.
204
205 The Higher the number, the more optimised your binary will be. This value will default to 0
206 If you either a) Dont enter a number, or b) Enter a value outside the range.\n";
207 print "[\033[1;32m0\033[0m] -> ";
208 chomp($var = <STDIN>);
209 if ($var == 1) {
210   $config{OPTIMITEMP} = 1;
211   $config{OPTIMISATI} = "-O";
212 } elsif ($var == 2) {
213   $config{OPTIMITEMP} = 2;
214   $config{OPTIMISATI} = "-O2";
215 } elsif ($var == 3) {
216   $config{OPTIMITEMP} = 3;
217   $config{OPTIMISATI} = "-O3";
218 } else {
219   $config{OPTIMITEMP} = 0;
220   $config{OPTIMISATI} = "-g";
221 }
222
223 print "\n\033[1;32mPre-build configuration is complete!\033[0m\n\n";
224 print "\033[0mConfig path:\033[1;32m\t\t\t$config{CONFIG_DIR}\n";
225 print "\033[0mModule path:\033[1;32m\t\t\t$config{MODULE_DIR}\n";
226 print "\033[0mMax connections:\033[1;32m\t\t$config{MAX_CLIENT}\n";
227 print "\033[0mMax User Channels\033[1;32m\t\t$config{MAX_CHANNE}\n";
228 print "\033[0mMax nickname length:\033[1;32m\t\t$config{NICK_LENGT}\n";
229 print "\033[0mMax channel length:\033[1;32m\t\t$config{CHAN_LENGT}\n";
230 print "\033[0mMax mode length:\033[1;32m\t\t$config{MAXI_MODES}\n";
231 print "\033[0mGCC Version Found:\033[1;32m\t\t$config{GCCVER}.$config{GCC34}\n";
232 print "\033[0mOptimatizaton Flag:\033[1;32m\t\t$config{OPTIMISATI}\033[0m\n\n";
233
234 makecache();
235 writefiles();
236
237 print "\n\n";
238 print "To build your server with these settings, please type '\033[1;32m$config{MAKEPROG}\033[0m' now.\n";
239 print "*** \033[1;32mRemember to edit your configuration files!!!\033[0m ***\n\n\n";
240
241 ################################################################################
242 #                              HELPER FUNCTIONS                                #
243 ################################################################################
244 sub getcache {
245   # Retrieves the .config.cache file, and loads values into the main config hash.
246   open(CACHE, ".config.cache") or return undef;
247   while (<CACHE>) {
248     chomp;
249
250     # Ignore Blank lines, and comments..
251     next if /^\s*$/;
252     next if /^\s*#/;
253
254     my ($key, $value) = split("=", $_);
255     $value =~ /^\"(.*)\"$/;
256     # Do something with data here!
257     $config{$key} = $1;
258   }
259   close(CONFIG);
260   return "true";
261 }
262
263 sub makecache {
264   # Dump the contents of %config
265   print "Writing \033[1;32mcache file\033[0m for future ./configures ...\n";
266   open(FILEHANDLE, ">.config.cache");
267   foreach $key (keys %config)
268   {
269     print FILEHANDLE "$key=\"$config{$key}\"\n";
270   }
271   close(FILEHANDLE);
272 }
273
274 sub dir_check {
275   my ($desc, $hash_key) = @_;
276   my $complete = 0;
277   while (!$complete) {
278     print "In what directory $desc?\n";
279     print "[\033[1;32m$config{$hash_key}\033[0m] -> ";
280     chomp($var = <STDIN>);
281     if ($var eq "") { $var = $config{$hash_key}; }
282     if ($var =~ /^\~\/(.+)$/) {
283         # Convert it to a full path..
284         $var = resolve_directory($ENV{HOME} . "/" . $1);
285     }
286     if (substr($var,0,1) ne "/")
287     {
288         # Assume relative Path was given.. fill in the rest.
289         $var = $this . "/$var";
290     }
291     $var = resolve_directory($var); 
292     if (! -e $var) {
293       print "$var does not exist. Create it?\n[\033[1;32my\033[0m] ";
294       chomp($tmp = <STDIN>);
295       if (($tmp eq "") || ($tmp =~ /^y/i)) {
296         # Attempt to Create the Dir..
297         $chk = system("mkdir -p \"$var\" >> /dev/null 2>&1") / 256;
298         if ($chk != 0) {
299           print "Unable to create directory. ($var)\n\n";
300           # Restart Loop..
301           next;
302         }
303       } else {
304         # They said they don't want to create, and we can't install there.
305         print "\n\n";
306         next;
307       }
308     } else {
309       if (!is_dir($var)) {
310         # Target exists, but is not a directory.
311         print "File $var exists, but is not a directory.\n\n";
312         next;
313       }
314     }
315     # Either Dir Exists, or was created fine.
316     $config{$hash_key} = $var;
317     $complete = 1;
318     print "\n";
319   }
320 }
321
322 sub getosflags {
323   if ($config{OSNAME} eq "FreeBSD") {
324     $config{LDLIBS} = "-Ldl";
325     $config{FLAGS}  = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual -g";
326     $config{MAKEPROG} = "gmake";
327   } else {
328     $config{LDLIBS} = "-ldl";
329     $config{FLAGS}  = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual -g";
330     $config{MAKEPROG} = "make";
331   }
332 }
333
334 sub is_dir {
335   my ($path) = @_;
336   if (chdir($path)) {
337     chdir($this);
338     return 1;
339   } else {
340     # Just in case..
341     chdir($this);
342     return 0;
343   }
344 }
345
346 sub getmodules {
347   my $i = 0;
348   opendir(DIRHANDLE, "src/modules");
349   foreach $name (sort readdir(DIRHANDLE)) {
350     if ($name =~ /^m_(.+)\.cpp$/)
351     {
352       $modlist[$i++] = $1;
353     }
354   }
355   closedir(DIRHANDLE);
356 }
357
358 sub writefiles {
359
360   print "Writing \033[1;32minspircd_config.h\033[0m\n";
361   # First File.. inspircd_config.h
362   chomp(my $incos = `uname -n -s -r`);
363   chomp(my $version = `sh ./src/version.sh`);
364   open(FILEHANDLE, "> include/inspircd_config.h");
365   print FILEHANDLE <<EOF;
366 /* Auto generated by configure, do not modify! */
367 #define SYSLOG_FACILITY LOG_DAEMON
368 #define SYSLOG_LEVEL LOG_NOTICE
369 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
370 #define MOD_PATH "$config{MODULE_DIR}"
371 #define VERSION "$version"
372 #define MAXCLIENTS $config{MAX_CLIENT}
373 #define NICKMAX $config{NICK_LENGT}
374 #define CHANMAX $config{CHAN_LENGT}
375 #define MAXCHANS $config{MAX_CHANNE}
376 #define MAXMODES $config{MAXI_MODES}
377 #define OPTIMISATION $config{OPTIMITEMP}
378 #define SYSTEM "$incos"
379 #define MAXBUF 514
380 EOF
381
382   if ($config{GCCVER} > 3) {
383     print FILEHANDLE "#define GCC3\n";
384     print FILEHANDLE "#define GCC34\n";
385   }
386   else
387   {
388     if ($config{GCCVER} == 3) {
389       print FILEHANDLE "#define GCC3\n";
390       if ($config{GCC34} > 3) {
391         print FILEHANDLE "#define GCC34\n";
392       }
393     }
394   }
395   if ($config{HAS_STRLCPY} eq "true") {
396     print FILEHANDLE "#define HAS_STRLCPY\n";
397   }
398   if ($config{USE_KQUEUE} eq "true") {
399     print FILEHANDLE "#define USE_KQUEUE\n";
400   }
401   close(FILEHANDLE);
402
403   # Create a Modules List..
404   my $modules = "";
405   foreach $i (@modlist)
406   {
407     $modules .= "m_".$i.".so ";
408   }
409   chomp($modules);   # Remove Redundant whitespace..
410
411
412   # Write all .in files.
413   my $tmp = "";
414   my $file = "";
415   opendir(DIRHANDLE, $this);
416   foreach $name (sort readdir(DIRHANDLE)) {
417     if ($name =~ /^\.(.+)\.inc$/)
418     {
419       $file = $1;
420       # All .name.inc files need parsing!
421       $tmp = "";
422       open(FILEHANDLE, ".$file.inc");
423       while (<FILEHANDLE>) {
424         $tmp .= $_;
425       }
426       close(FILEHANDLE);
427
428       $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/;
429       $tmp =~ s/\@FLAGS\@/$config{FLAGS}/;
430       $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/;
431       $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/;
432       $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/;
433       $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/;
434       $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/;
435       $tmp =~ s/\@MODULES\@/$modules/;
436
437       print "Writing \033[1;32m$file\033[0m\n";
438       open(FILEHANDLE, ">$file");
439       print FILEHANDLE $tmp;
440     }
441   }
442   closedir(DIRHANDLE);
443
444   # Make inspircd executable!
445   chmod 0744, 'inspircd';
446
447   # Modules Makefile..
448   print "Writing \033[1;32msrc/modules/Makefile\033[0m\n";
449   open(FILEHANDLE, ">src/modules/Makefile");
450   print FILEHANDLE <<EOF;
451 # (C) ChatSpike development team
452 # Makefile by <Craig\@ChatSpike.net>
453 # Many Thanks to Andrew Church <achurch\@achurch.org>
454 #    for assisting with making this work right.
455 #
456 # Automatically Generated by ./configure to add a modules
457 # please run ./configure --update
458
459 all: \$(MODULES)
460
461 EOF
462
463   # Create a Modules List..
464   my $modules = "";
465   my $flags = "";
466   foreach $i (@modlist)
467   {
468     $flags = getcompilerflags("src/modules/m_".$i.".cpp");
469     print FILEHANDLE <<EOCHEESE;
470 m_$i.so: m_$i.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/servers.h ../../include/base.h
471         \$(CC) -pipe -I../../include \$(FLAGS) $flags -export-dynamic -c m_$i.cpp
472         \$(CC) \$(FLAGS) -shared $flags -o m_$i.so m_$i.o
473         cp m_$i.so \$(MODPATH)/
474         chmod 0700 \$(MODPATH)/m_$i.so
475
476 EOCHEESE
477   }
478 }
479
480 sub getcompilerflags {
481   my ($file) = @_;
482   open(FLAGS, $file);
483   while (<FLAGS>) {
484     if ($_ =~ /^\/\* \$CompileFlags: (.+) \*\/$/) {
485       close(FLAGS);
486       return $1;
487     }
488   }
489   close(FLAGS);
490   return undef;
491 }
492
493 sub show_splash {
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::\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... \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:::: \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:\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:::: \033[1;33m##\033[0m:\n";
499   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";
500   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";
501   print "\033[0m\033[0m....::..::::..:::......:::..:::::::::....::..:::::..:::......:::........:::\n\n";
502 }
503
504 sub resolve_directory {
505         use File::Spec;
506         return File::Spec->rel2abs($_[0]);
507 }
508
509 sub yesno {
510         my ($default,$prompt) = @_;
511         if (!$default) {
512                 print "$prompt [\033[1;32mn\033[0m] ";
513                 chomp($tmp = <STDIN>);
514                 return ($tmp =~ /^y/i);
515                 
516         }
517         else {
518                 print "$prompt [\033[1;32my\033[0m] ";
519                 chomp($tmp = <STDIN>);
520                 return (($tmp eq "") || ($tmp =~ /^y/i));
521         }
522         return 0;
523 }