]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - configure
Fine-tuning epoll parameters
[user/henk/code/inspircd.git] / configure
1 #!/usr/bin/perl
2 # InspIRCd Configuration Script
3 #
4 # Copyright 2003 The ChatSpike Development Team
5 # <brain@chatspike.net>
6 # <Craig@chatspike.net>
7 #
8 # [14:21] Brain: <matrix impression> i know perl-fu!
9 #
10 # $Id$
11 #
12 ########################################
13
14
15 $this = resolve_directory($ENV{PWD});                                           # PWD, Regardless.
16 @modlist = ();                                                                  # Declare for Module List..
17 %config = ();                                                                   # Initiate Configuration Hash..
18 $config{ME}                 = resolve_directory($ENV{PWD});                     # Present Working Directory
19 $config{CONFIG_DIR}         = resolve_directory($ENV{PWD}."/conf");             # Configuration Directory
20 $config{MODULE_DIR}         = resolve_directory($ENV{PWD}."/modules");          # Modules Directory
21 $config{BINARY_DIR}         = resolve_directory($ENV{PWD}."/bin");              # Binary Directory
22 $config{LIBRARY_DIR}        = resolve_directory($ENV{PWD}."/lib");              # Library Directory
23 $config{OPTIMITEMP}         = "0";                                              # Default Optimisation Value
24 $config{OPTIMISATI}         = "-g";                                             # Optimisation Flag
25 $config{NICK_LENGT}         = "32";                                             # Default Nick Length
26 $config{CHAN_LENGT}         = "64";                                             # Default Channel Name Length
27 $config{MAX_CHANNE}         = "20";                                             # Default Max. Channels per user..
28 $config{MAXI_MODES}         = "20";                                             # Default Max. Number of Modes set at once.
29 $config{HAS_STRLCPY}        = "false";                                          # strlcpy Check.
30 $config{USE_KQUEUE}         = "n";                                              # kqueue enabled
31 $config{USE_EPOLL}          = "n";                                              # 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}       = `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?\nIf you are unsure, answer no.\n\nEnable kqueue?");
175 }
176 if ($has_epoll) {
177         yesno(USE_EPOLL,"You are running a linux operating system, and epoll\nwas detected. Would you like to enable epoll support?\nIf you are unsure, answer no.\n\nEnable epoll?");
178 }
179
180 # File Descriptor Settings..
181 my $continue = 0;
182 while (!$continue) {
183   print "Maximum number of clients at any one time ($config{MAX_CLIENT_T})\n";
184   print "[\033[1;32m$config{MAX_CLIENT}\033[0m] -> ";
185   chomp($var = <STDIN>);
186   if ($var eq "") { $var = $config{MAX_CLIENT}; }
187   if ($var =~ /^\d+$/) {
188     if (($var > $config{MAX_CLIENT_T}) && ($fd_scan_failed ne true)) {
189       # Client has entered a larger number than the 'discovered' value
190       # Confirm.
191       print "WARNING: Our scans have indicated that you are attempting
192 to use more sockets than there are avaliable. Are you sure
193 you wish to do this? It may cause the IRCd to malfunction [y/n]
194 [\033[1;32mn\033[0m] -> $c";
195       chomp($tmp = <STDIN>);
196       if ($tmp ne "y") {
197         print "Please enter the correct value.\n\n";
198         next;
199       }
200     }
201   } else {
202     print "You must enter a number in this field. Please try again.\n\n";
203     next;
204   }
205   # If we get here, we should be good to go.
206   $config{MAX_CLIENT} = $var;
207   $continue = 1;
208   print "\n";
209 }
210
211 my $continue = 0;
212 while (!$continue) {
213   print "What is the Maximum length of nicknames?\n";
214   print "[\033[1;32m$config{NICK_LENGT}\033[0m] -> ";
215   chomp($var = <STDIN>);
216   if ($var eq "") { $var = $config{NICK_LENGT}; }
217   if ($var =~ /^\d+$/) {
218     # We don't care what the number is, set it and be on our way.
219     $config{NICK_LENGT} = $var;
220     $continue = 1;
221     print "\n";
222   } else {
223     print "You must enter a number in this field. Please try again.\n\n";
224   }
225 }
226
227 my $continue = 0;
228 while (!$continue) {
229   print "What is the Maximum number of mode changes in one line?\n";
230   print "[\033[1;32m$config{MAXI_MODES}\033[0m] -> ";
231   chomp($var = <STDIN>);
232   if ($var eq "") { $var = $config{MAXI_MODES}; }
233   if ($var =~ /^\d+$/) {
234     # We don't care what the number is, set it and be on our way.
235     $config{MAXI_MODES} = $var;
236     $continue = 1;
237     print "\n";
238   } else {
239     print "You must enter a number in this field. Please try again.\n\n";
240   }
241 }
242
243 # Code Optimisation
244 print "Enter the Level Of Binary optimisation. This is a number between 0 and 3 (inclusive)
245 The InspIRCd Team will _NOT_ support any bug reports above 0.
246 Also note, the IRCd behaviour will be different depending on this value.
247 Please read the documentation for more information.
248
249 The Higher the number, the more optimised your binary will be. This value will default to 0
250 If you either a) Dont enter a number, or b) Enter a value outside the range.\n";
251 print "[\033[1;32m$config{OPTIMITEMP}\033[0m] -> ";
252 chomp($var = <STDIN>);
253 if ($var eq "") {
254   $var = $config{OPTIMITEMP};
255 }
256
257 if ($var eq "1") {
258   $config{OPTIMITEMP} = 1;
259   $config{OPTIMISATI} = "-O";
260 } elsif ($var eq "2") {
261   $config{OPTIMITEMP} = 2;
262   $config{OPTIMISATI} = "-O2";
263 } elsif ($var eq "3") {
264   $config{OPTIMITEMP} = 3;
265   $config{OPTIMISATI} = "-O3";
266 } else {
267   $config{OPTIMITEMP} = 0;
268   $config{OPTIMISATI} = "-g";
269 }
270
271 print "\n\033[1;32mPre-build configuration is complete!\033[0m\n\n";
272 print "\033[0mConfig path:\033[1;32m\t\t\t$config{CONFIG_DIR}\n";
273 print "\033[0mModule path:\033[1;32m\t\t\t$config{MODULE_DIR}\n";
274 print "\033[0mMax connections:\033[1;32m\t\t$config{MAX_CLIENT}\n";
275 print "\033[0mMax User Channels\033[1;32m\t\t$config{MAX_CHANNE}\n";
276 print "\033[0mMax nickname length:\033[1;32m\t\t$config{NICK_LENGT}\n";
277 print "\033[0mMax channel length:\033[1;32m\t\t$config{CHAN_LENGT}\n";
278 print "\033[0mMax mode length:\033[1;32m\t\t$config{MAXI_MODES}\n";
279 print "\033[0mGCC Version Found:\033[1;32m\t\t$config{GCCVER}.$config{GCC34}\n";
280 print "\033[0mOptimatizaton Flag:\033[1;32m\t\t$config{OPTIMISATI}\033[0m\n\n";
281
282 makecache();
283 writefiles();
284
285 print "\n\n";
286 print "To build your server with these settings, please type '\033[1;32m$config{MAKEPROG}\033[0m' now.\n";
287 print "*** \033[1;32mRemember to edit your configuration files!!!\033[0m ***\n\n\n";
288
289 ################################################################################
290 #                              HELPER FUNCTIONS                                #
291 ################################################################################
292 sub getcache {
293   # Retrieves the .config.cache file, and loads values into the main config hash.
294   open(CACHE, ".config.cache") or return undef;
295   while (<CACHE>) {
296     chomp;
297
298     # Ignore Blank lines, and comments..
299     next if /^\s*$/;
300     next if /^\s*#/;
301
302     my ($key, $value) = split("=", $_);
303     $value =~ /^\"(.*)\"$/;
304     # Do something with data here!
305     $config{$key} = $1;
306   }
307   close(CONFIG);
308   return "true";
309 }
310
311 sub makecache {
312   # Dump the contents of %config
313   print "Writing \033[1;32mcache file\033[0m for future ./configures ...\n";
314   open(FILEHANDLE, ">.config.cache");
315   foreach $key (keys %config)
316   {
317     print FILEHANDLE "$key=\"$config{$key}\"\n";
318   }
319   close(FILEHANDLE);
320 }
321
322 sub dir_check {
323   my ($desc, $hash_key) = @_;
324   my $complete = 0;
325   while (!$complete) {
326     print "In what directory $desc?\n";
327     print "[\033[1;32m$config{$hash_key}\033[0m] -> ";
328     chomp($var = <STDIN>);
329     if ($var eq "") { $var = $config{$hash_key}; }
330     if ($var =~ /^\~\/(.+)$/) {
331         # Convert it to a full path..
332         $var = resolve_directory($ENV{HOME} . "/" . $1);
333     }
334     if (substr($var,0,1) ne "/")
335     {
336         # Assume relative Path was given.. fill in the rest.
337         $var = $this . "/$var";
338     }
339     $var = resolve_directory($var); 
340     if (! -e $var) {
341       print "$var does not exist. Create it?\n[\033[1;32my\033[0m] ";
342       chomp($tmp = <STDIN>);
343       if (($tmp eq "") || ($tmp =~ /^y/i)) {
344         # Attempt to Create the Dir..
345         $chk = system("mkdir -p \"$var\" >> /dev/null 2>&1") / 256;
346         if ($chk != 0) {
347           print "Unable to create directory. ($var)\n\n";
348           # Restart Loop..
349           next;
350         }
351       } else {
352         # They said they don't want to create, and we can't install there.
353         print "\n\n";
354         next;
355       }
356     } else {
357       if (!is_dir($var)) {
358         # Target exists, but is not a directory.
359         print "File $var exists, but is not a directory.\n\n";
360         next;
361       }
362     }
363     # Either Dir Exists, or was created fine.
364     $config{$hash_key} = $var;
365     $complete = 1;
366     print "\n";
367   }
368 }
369
370 sub getosflags {
371   if ($config{OSNAME} eq "FreeBSD") {
372     $config{LDLIBS} = "-Ldl";
373     $config{FLAGS}  = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual $config{OPTIMISATI}";
374     $config{MAKEPROG} = "gmake";
375   } else {
376     $config{LDLIBS} = "-ldl";
377     $config{FLAGS}  = "-fPIC -frtti $OPTIMISATI -Woverloaded-virtual $config{OPTIMISATI}";
378     $config{MAKEPROG} = "make";
379   }
380 }
381
382 sub is_dir {
383   my ($path) = @_;
384   if (chdir($path)) {
385     chdir($this);
386     return 1;
387   } else {
388     # Just in case..
389     chdir($this);
390     return 0;
391   }
392 }
393
394 sub getmodules {
395   my $i = 0;
396   opendir(DIRHANDLE, "src/modules");
397   foreach $name (sort readdir(DIRHANDLE)) {
398     if ($name =~ /^m_(.+)\.cpp$/)
399     {
400       $modlist[$i++] = $1;
401     }
402   }
403   closedir(DIRHANDLE);
404 }
405
406 sub writefiles {
407
408   print "Writing \033[1;32minspircd_config.h\033[0m\n";
409   # First File.. inspircd_config.h
410   chomp(my $incos = `uname -n -s -r`);
411   chomp(my $version = `sh ./src/version.sh`);
412   open(FILEHANDLE, "> include/inspircd_config.h");
413   print FILEHANDLE <<EOF;
414 /* Auto generated by configure, do not modify! */
415 #define SYSLOG_FACILITY LOG_DAEMON
416 #define SYSLOG_LEVEL LOG_NOTICE
417 #define CONFIG_FILE "$config{CONFIG_DIR}/inspircd.conf"
418 #define MOD_PATH "$config{MODULE_DIR}"
419 #define VERSION "$version"
420 #define MAXCLIENTS $config{MAX_CLIENT}
421 #define NICKMAX $config{NICK_LENGT}
422 #define CHANMAX $config{CHAN_LENGT}
423 #define MAXCHANS $config{MAX_CHANNE}
424 #define MAXMODES $config{MAXI_MODES}
425 #define OPTIMISATION $config{OPTIMITEMP}
426 #define SYSTEM "$incos"
427 #define MAXBUF 514
428 EOF
429
430   if ($config{GCCVER} > 3) {
431     print FILEHANDLE "#define GCC3\n";
432     print FILEHANDLE "#define GCC34\n";
433   }
434   else
435   {
436     if ($config{GCCVER} == 3) {
437       print FILEHANDLE "#define GCC3\n";
438       if ($config{GCC34} > 3) {
439         print FILEHANDLE "#define GCC34\n";
440       }
441     }
442   }
443   if ($config{HAS_STRLCPY} eq "true") {
444     print FILEHANDLE "#define HAS_STRLCPY\n";
445   }
446   if ($config{USE_KQUEUE} eq "y") {
447     print FILEHANDLE "#define USE_KQUEUE\n";
448   }
449   if ($config{USE_EPOLL} eq "y") {
450     print FILEHANDLE "#define USE_EPOLL\n";
451   }
452   # user didn't choose either epoll or select for their OS.
453   # default them to USE_SELECT (ewwy puke puke)
454   if (($config{USE_EPOLL} eq "n") && ($config{USE_KQUEUE} eq "n")) {
455     print FILEHANDLE "#define USE_SELECT\n";
456   }
457   close(FILEHANDLE);
458
459   # Create a Modules List..
460   my $modules = "";
461   foreach $i (@modlist)
462   {
463     $modules .= "m_".$i.".so ";
464   }
465   chomp($modules);   # Remove Redundant whitespace..
466
467
468   # Write all .in files.
469   my $tmp = "";
470   my $file = "";
471   opendir(DIRHANDLE, $this);
472   foreach $name (sort readdir(DIRHANDLE)) {
473     if ($name =~ /^\.(.+)\.inc$/)
474     {
475       $file = $1;
476       # All .name.inc files need parsing!
477       $tmp = "";
478       open(FILEHANDLE, ".$file.inc");
479       while (<FILEHANDLE>) {
480         $tmp .= $_;
481       }
482       close(FILEHANDLE);
483
484       $tmp =~ s/\@MAKEPROG\@/$config{MAKEPROG}/;
485       $tmp =~ s/\@FLAGS\@/$config{FLAGS}/;
486       $tmp =~ s/\@LDLIBS\@/$config{LDLIBS}/;
487       $tmp =~ s/\@CONFIG_DIR\@/$config{CONFIG_DIR}/;
488       $tmp =~ s/\@MODULE_DIR\@/$config{MODULE_DIR}/;
489       $tmp =~ s/\@BINARY_DIR\@/$config{BINARY_DIR}/;
490       $tmp =~ s/\@LIBRARY_DIR\@/$config{LIBRARY_DIR}/;
491       $tmp =~ s/\@MODULES\@/$modules/;
492
493       print "Writing \033[1;32m$file\033[0m\n";
494       open(FILEHANDLE, ">$file");
495       print FILEHANDLE $tmp;
496     }
497   }
498   closedir(DIRHANDLE);
499
500   # Make inspircd executable!
501   chmod 0744, 'inspircd';
502
503   # Modules Makefile..
504   print "Writing \033[1;32msrc/modules/Makefile\033[0m\n";
505   open(FILEHANDLE, ">src/modules/Makefile");
506   print FILEHANDLE <<EOF;
507 # (C) ChatSpike development team
508 # Makefile by <Craig\@ChatSpike.net>
509 # Many Thanks to Andrew Church <achurch\@achurch.org>
510 #    for assisting with making this work right.
511 #
512 # Automatically Generated by ./configure to add a modules
513 # please run ./configure --update
514
515 all: \$(MODULES)
516
517 EOF
518
519   # Create a Modules List..
520   my $modules = "";
521   my $flags = "";
522   foreach $i (@modlist)
523   {
524     $flags = getcompilerflags("src/modules/m_".$i.".cpp");
525     print FILEHANDLE <<EOCHEESE;
526 m_$i.so: m_$i.cpp ../../include/modules.h ../../include/users.h ../../include/channels.h ../../include/servers.h ../../include/base.h
527         \$(CC) -pipe -I../../include \$(FLAGS) $flags -export-dynamic -c m_$i.cpp
528         \$(CC) \$(FLAGS) -shared $flags -o m_$i.so m_$i.o
529         cp m_$i.so \$(MODPATH)/
530         chmod 0700 \$(MODPATH)/m_$i.so
531
532 EOCHEESE
533   }
534 }
535
536 sub getcompilerflags {
537   my ($file) = @_;
538   open(FLAGS, $file);
539   while (<FLAGS>) {
540     if ($_ =~ /^\/\* \$CompileFlags: (.+) \*\/$/) {
541       close(FLAGS);
542       return $1;
543     }
544   }
545   close(FLAGS);
546   return undef;
547 }
548
549 sub show_splash {
550   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";
551   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";
552   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";
553   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";
554   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";
555   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";
556   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";
557   print "\033[0m\033[0m....::..::::..:::......:::..:::::::::....::..:::::..:::......:::........:::\n\n";
558 }
559
560 sub resolve_directory {
561         use File::Spec;
562         return File::Spec->rel2abs($_[0]);
563 }
564
565 sub yesno {
566         my ($flag,$prompt) = @_;
567         print "$prompt [\033[1;32m$config{$flag}\033[0m] -> ";
568         chomp($tmp = <STDIN>);
569         if ($tmp eq "") { $tmp = $config{$flag} }
570
571         if (($tmp eq "") || ($tmp =~ /^y/i)) {
572                 $config{$flag} = "y";
573         } else {
574                 $config{$flag} = "n";
575         }
576         return;
577 }