]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - configure
86a909b8ea9939f752559b6d64a378de510afc0f
[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 ################################################################################
97 #                          BEGIN INTERACTIVE PART                              #
98 ################################################################################
99
100 # Clear the Screen..
101 system("clear");
102 # Display Splash Logo..
103 show_splash();
104 chomp($wholeos = `uname -mnr`);
105
106 # Display Introduction Message..
107 print "
108 Welcome to the InspIRCd Configuration program!
109
110 *** If you are unsure of any of these values, leave it blank for    ***
111 *** standard settings that will work, and your server will run      ***
112 *** using them. If you are running this server as part of a         ***
113 *** larger network, you must consult with your network admins       ***
114 *** for the proper values to use, or server links will be unstable! ***
115
116 Press \033[1m<RETURN>\033[0m to accept the default for any option, or enter
117 a new value. Please note: You will \033[1mHAVE\033[0m to read the docs
118 dir, otherwise you won't have a config file!
119
120 Your operating system is: \033[1;32m$config{OSNAME}\033[0m ($wholeos), fdmax: $config{MAX_CLIENT_T}\n\n";
121
122 # Directory Settings..
123 dir_check("are the configuration files", "CONFIG_DIR");
124 dir_check("are the modules to be compiled to", "MODULE_DIR");
125 dir_check("is the IRCd binary to be placed", "BINARY_DIR");
126 dir_check("are the IRCd libraries to be placed", "LIBRARY_DIR");
127
128 if ($config{OSNAME} =~ /BSD$/) {
129         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?");
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;32m$config{OPTIMITEMP}\033[0m] -> ";
204 chomp($var = <STDIN>);
205 if ($var eq "") {
206   $var = $config{OPTIMITEMP};
207 }
208
209 if ($var eq "1") {
210   $config{OPTIMITEMP} = 1;
211   $config{OPTIMISATI} = "-O";
212 } elsif ($var eq "2") {
213   $config{OPTIMITEMP} = 2;
214   $config{OPTIMISATI} = "-O2";
215 } elsif ($var eq "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 $config{OPTIMISATI}";
326     $config{MAKEPROG} = "gmake";
327   } else {
328     $config{LDLIBS} = "-ldl";
329     $config{FLAGS}  = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual $config{OPTIMISATI}";
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 "y") {
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 ($flag,$prompt) = @_;
511         print "$prompt [\033[1;32m$config{$flag}\033[0m] -> ";
512         chomp($tmp = <STDIN>);
513         if ($tmp eq "") { $tmp = $config{$flag} }
514
515         if (($tmp eq "") || ($tmp =~ /^y/i)) {
516                 $config{$flag} = "y";
517         } else {
518                 $config{$flag} = "n";
519         }
520         return;
521 }