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