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