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