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