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