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