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