#!/usr/local/bin/perl eval 'exec /usr/local/bin/perl -S $0 ${1+"$@"}' if 0; # not running under some shell # # $Id: fortune,v 1.1.1.1 2001/06/06 08:54:38 sdague Exp $ # # $Log: fortune,v $ # Revision 1.1.1.1 2001/06/06 08:54:38 sdague # initial import # # Revision 1.1.1.1 2001/05/13 19:56:30 sdague # added initial import of PPT work # # # Revision 1.0 1999/04/30 andy murren # Inital Revision # use strict; use FindBin qw($Bin); use File::Basename; use Getopt::Std; $|++; my ($VERSION) = ' $Revision: 1.1.1.1 $ '; my $home = "$Bin/fortunes"; my ($t0, $t1, $main, $find, @seen_file, $found, $wait, @mrtn); my (@dir_list, @text, $text, $dir, %hash, $f, %args, $size); $wait = $size = $found = 0; my (%opts); getopts('adefhilosvwm:', \%opts); my $debug = $opts{'d'}; if ($opts{'v'}) { print "\n\n$0 $VERSION\n\n"; exit 1; } if ($debug) { warn "opts are:\n"; foreach (keys %opts) { warn "$_ == $opts{$_}\n"; } } if ($opts{'h'}) { &print_help; } if ($opts{'m'}) { $find = '(?i)' if $opts{'i'}; $opts{'m'} =~ s%(\W)%\\$1%g; $find .= $opts{'m'}; warn "\$find ==> $find" if $debug; study $find; } if (@ARGV) { if ($debug) { warn "\n\@ARGV:\n"; foreach (@ARGV) { warn "$_\n"; } warn "\n\n"; } my ($ky, $val, $f); $ky = $val = $f = 0; foreach (@ARGV) { if (/^all$/) { $opts{a} = 1; undef @ARGV; last; } elsif (/\d+\%/) { s/(\d+)\%/$1/; $val = $_; $f++; } else { if (($val) && ($f)){ $args{$_} = $val; } $ky = $val = $f = 0; } } } # this is the main routine of the program if ($opts{f}) { &build_file_list; &print_file_list; }else { &build_file_list; my $pfile = &pick_file; my $pick = &pick_fortune($pfile); &print_fortune($pick); } exit 1; # # Sub Routines # sub find_fortune { &new_file_list; my $pfile = &pick_file; my $pick = &pick_fortune($pfile); } # build list the available files # # if -a all files including `obscene' ones are valid # if -o only `offensive' files are valid # if no switch is given only non `offensive' files are valid # if -e is used then all files are considered of equal size # so we put all of the names in an array and randomly select one # if files are specified on the command line only list those sub build_file_list { my $rtn; @dir_list = (); if (@ARGV) { $rtn = &build_w_args; } else { $rtn = &build_wo_args; } return $rtn; } # used if files or directories were given on the cmd line sub build_w_args { if (%args) { while (my ($key,$value) = each %args) { if ($debug) { warn "key = $key, value = $value\n"; } my (@temp, $t, $i); if ($value =~ /^\d+\$/) { $t += $value; $i = $value; } while ($i) { push @temp, "$home/$key"; $i--; } foreach (@temp) { print "$_\n"; } my $dir_c = @temp; my $rand = int (rand $dir_c); my $tmp = $temp[$rand]; if ($debug) { warn "$tmp\n"; } return $tmp; } } } # if no files were specified on the cmd line use this. # gets the list of files and their sizes sub build_wo_args { opendir D, "$home" or die "could not open $home: $!\n"; my @allfiles = readdir D; foreach (@allfiles) { next if /^\./; next if /\..*$/; if ($opts{o}) { next unless /-o$/ || /limerick$/; } elsif (! $opts{a}) { next if /-o$/ || /limerick$/; } next unless -f "$home/$_"; push @dir_list, "$home/$_"; } if ($debug) { warn "\n\@dir_list in build_wo_args\n"; foreach (@dir_list) { warn "$_\n"; } warn "\n"; } } sub pick_file { die "\nCould find no files to open!\n" unless @dir_list; if ($opts{e}) { my $dir_c = @dir_list; my $rand = int (rand $dir_c); my $tmp = $dir_list[$rand]; return $tmp; } else { my (@temp, $t); @temp = (); my $sz = 0; %hash = (); foreach (@dir_list) { $sz = (-s "$_"); $size += $sz; $hash{$_} = $sz; } for $t(keys %hash) { my $r = %hash->{$t}; my $i = int (100 * (($r/$size) + .005)); if ($i < 1) { $i = 1; } while ($i) { push @temp, "$t"; $i--; } } if ($debug) { warn "\n\@temp in pick_file\n"; foreach (@temp) { warn "$_\n"; } } my $dir_c = @temp; my $rand = int (rand $dir_c); my $tmp = $temp[$rand]; warn "\ntmp = $tmp\n" if $debug; return $tmp; } } sub new_file_list { my $t; my %seen = (); my @new_dir_list = (); if ($debug) { warn "\n ++dir_list\n"; foreach (@dir_list) { my $n = basename($_); warn " $n\n"; } warn "\n"; } foreach $t (@seen_file) { $seen{$t} = 1; } foreach $t (@dir_list) { unless ($seen{$t}) { push (@new_dir_list, $t); } } exit unless @new_dir_list; if ($debug) { warn "\n ++new_dir_list\n"; foreach (@new_dir_list) { my $n = basename($_); warn " $n\n"; } warn "\n"; } @dir_list = (); @dir_list = @new_dir_list; if ($debug) { warn "\n ++dir_list\n"; foreach (@dir_list) { my $n = basename($_); warn " $n\n"; } warn "\n"; } } # put all of the fortunes into an array then pick one # that fits the criteria. sub pick_fortune { $/ = "\%\n"; my $file = shift; my $line; my $picked = 0; if ($debug) { warn "\nthe file is $file\n\n"; } my $regex; open F, "< $file" or die "could not open file $file: $!"; while (defined ($line = )) { $line =~ s|\%+\n||g; push @text, $line; } $text = @text; warn "\n\nthe length of \@text is $text\n\n" if $debug; my $num = int (rand $text); warn "\n\$num at the beginning of pick_fortune is $num\n" if $debug; my @rtn; my $not_done = 1; my $wrap = 0; my $hold_num = $num; while ($not_done) { if ($opts{'s'} || $opts{'l'}) { @rtn = &short_long ($num, $not_done); $num = $rtn[0]; $not_done = $rtn[1]; } else { $not_done = 0; $found = 1; } if ($find) { $found = 0; @mrtn = &match($num, $not_done, $text, $wrap, $picked, \$found); $num = $mrtn[0]; $not_done = $mrtn[1]; if ($wrap && ($num >= $text)) { &new_file ($file, \$picked); $picked = 1; last; } } else { $not_done = 0; $found = 1; } } warn "\n\$num at the end of pick_fortune to be returned is $num\n" if $debug; return $num; } sub match { my $num = shift; my $not_done = shift; my $len = shift; my $wrap = shift; my $picked = shift; my $found = shift; if ($text[$num] !~ m|$find|smo) { $num++; $not_done = 1; if ($num > $len) { $num = 0; $wrap++; } } else { $picked = 0; $not_done = 0; $$found = 1; } if ($debug) { warn "match \$find == $find\t\$found == $$found\n"; warn "the text matched is\n\t$text[$num]\n \$num = $num" if $$found; } return $num, $not_done; } sub new_file { warn "\n^^ran out of fortunes in that file, trying another one\n\n" if $debug; my $file = shift; my $picked = shift; push @seen_file, $file; foreach (@seen_file) { warn "seen file => $_\n" if $debug; } $$picked = 1; &find_fortune; } sub short_long { my $num = shift; my $not_done = shift; warn "in short_long\n" if $debug; while ($not_done) { if ($opts{'s'}) { if (length ($text[$num]) > 200) { $num++; next; } else { $not_done = 0; } } elsif ($opts{'l'}) { # that's an ell if ((length ($text[$num]) <= 200)) { $num++; next; } else { $not_done = 0; } } else { ; # this will let us keep looking } } return $num, $not_done; } sub print_fortune { if ($found) { my $num = shift; warn "\n\$num in print_fortune is $num\n" if $debug; if ($opts{w}) { my $tmp = length $text[$num]; $wait = int ($tmp/75); } print "\n\n$text[$num]\n\n"; sleep $wait; } else { print "\nSorry, did not find a match\n\n"; } } sub print_file_list { my $file_name; print "\n"; foreach (@dir_list) { $file_name = basename($_); print "\t$file_name\n"; } print "\n"; } sub print_help { print < was written by Andy Murren, I. =head1 COPYRIGHT and LICENSE This program is covered by the GNU Public License (GPL). See I for complete detail of the license. =cut