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