#! /usr/local/bin/perl

$debug = 0;
$print = 0;
$ls = 0;
$modtime = 0;
$now = time;
$type = '';
$name = '';

@DoW = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
@MoY = ('Jan','Feb','Mar','Apr','May','Jun',
        'Jul','Aug','Sep','Oct','Nov','Dec');

sub usage {
	print STDERR "usage: $0 base_dir commands...\n";
	exit 1;
}

sub unbuffer_output {
        select((select(STDOUT), $| = 1)[0]);    # unbuffer output
        select((select(STDERR), $| = 1)[0]);    # unbuffer output
}

&unbuffer_output;

&usage if ($ARGV[0] eq '');

$base_dir = $ARGV[0]; shift;

while ($_ = $ARGV[0], /^-/) {
	##print "$_\n";
	shift;
	if (/^-debug/) { $debug = 1; next; }
	if (/^-print$/) { $print = 1; next; }
	if (/^-ls$/) { $ls = 1; next; }
	if (/^-mtime$/) { $modtime = $ARGV[0]; shift; next; }
	if (/^-type$/) { $type = $ARGV[0]; shift; next; }
	if (/^-name$/) { $name = $ARGV[0]; shift; next; }
	&usage;
}

if ($name ne '') {
	$name =~ s/\\//g;
	$name =~ s/'//g;
	$s = '';
	for ($i = 0; $i < length($name); ++$i) {
		if (substr($name, $i, 1) ne '*') {
			$s .= '\\';
		} else {
			$s .= '.';
		}
		$s .= substr($name, $i, 1);
	}
	$name = $s;
	$name = '^' . $name . '$';
}

if ($type ne '') {
	if ($type ne 'f' && $type ne 'd') {
		print STDERR "$0: -type must be 'f' or 'd'!\n";
		exit 1;
	}
}

##$time = timegm($sec,$min,$hours,$mday,$mon,$year);
##use POSIX;
##$time_t = POSIX::mktime( 0, 30, 10, 12, 11, 95 );

&dofile($base_dir);
exit 0;

sub dofile {
	local($file) = @_;

	if ( -d $file ) {
		&dodir($file);
	} else {
		if ($type ne 'd') {
			&show($file);
		}
	}
}

sub show {
	local($file) = @_;
	local($ss, $s, $ts, $isdir);
	local($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks);

	if (-d $file) { $isdir = 1; } else { $isdir = 0; }

	if ($name ne '') {
		$ss = $file;
		$ss =~ s/.*\///;
		##print "$ss $name "; exit if (!$isdir);
		return if ($ss !~ /$name/i);
	}

	($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,
			$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($file);
	$ts = &ctime($mtime);
	if ($modtime) {
		$cutoff = $now - ($modtime * 24 * 60 * 60);
		return if ($mtime < $cutoff);
	}
	$s = $file;
	if ($isdir) {
		$ss = 'drwxrwxrwx';
	} else {
		$ss = '-rwxrwxrwx';
	}
	$s .= "/" if ($isdir && ! $file =~ /\\$/);
	if ($print) {
		print $file . "\n";
	} elsif ($ls) {
		printf("%s  %8d  %s  %s\n", $ss, $size, $ts, $s);
	} else {
		print $file . "\n";
	}
}

sub dodir {
	local($dir) = @_;
	local(@files, $file);

	if ($type ne 'f') {
		&show($dir);
	}
	if (opendir(D, "$dir"))  {
		@files = readdir(D);
		closedir(D);
	} else {
		print "Can't open $dir/!\n";
	}
	foreach $file (@files) {
		next if ($file eq '.');
		next if ($file eq '..');
		$dir .= '/' if ($dir !~ /\/$/);
		##print "$dir$file\n"; next;
		if ($type ne '') {
			if (($type eq 'd') && !(-d "$dir$file")) {
				next;
			}
		}
		&dofile("$dir$file");
	}
}

sub loctime  {
	($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(@_[0]);

	$monx = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')[$mon];
	$wdayx = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat')[$wday];
	# Wed, 01 Feb 1998 22:05:53 GMT
	return sprintf("%s, %s %02d, %04d %02d:%02d:%02d",$wdayx,$monx,$mday,$year+1900,$hour,$min,$sec);
}


sub ctime {
    ##package ctime;

    local($time) = @_;
    local($[) = 0;
    local($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);

    # Determine what time zone is in effect.
    # Use GMT if TZ is defined as null, local time if TZ undefined.
    # There's no portable way to find the system default timezone.

    $TZ = defined($ENV{'TZ'}) ? ( $ENV{'TZ'} ? $ENV{'TZ'} : 'GMT' ) : '';
    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
        ($TZ eq 'GMT') ? gmtime($time) : localtime($time);

    # Hack to deal with 'PST8PDT' format of TZ
    # Note that this can't deal with all the esoteric forms, but it
    # does recognize the most common: [:]STDoff[DST[off][,rule]]

    if($TZ=~/^([^:\d+\-,]{3,})([+-]?\d{1,2}(:\d{1,2}){0,2})([^\d+\-,]{3,})?/){
        $TZ = $isdst ? $4 : $1;
    }
    $TZ .= ' ' unless $TZ eq '';

    $year += 1900;
    sprintf("%s %s %2d %2d:%02d:%02d %s%4d",
      $DoW[$wday], $MoY[$mon], $mday, $hour, $min, $sec, $TZ, $year);
}
