#/usr/local/bin/perl
#
#  Usage: suidfind.pl [-n] [-s secure_dir] [search_starting_directory]
#

require "getopts.pl";

die $usage unless &getopts'Getopts('n');

# Do NFS stuff?  Yes unless opt:
if (defined($opt_n)) { $skip_nfs = $opt_n; }
else { $skip_nfs = 0; }

if (@ARGV > 1) { die $usage; }
elsif (@ARGV == 1) { $start_dir = shift; }

# these may be terribly rash assumptions....
$start_dir="/" unless defined $start_dir;

@rwx = ('---','--x','-w-','-wx','r--','r-x','rw-','rwx');
@moname = (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec);

while (($name, $pw, $uid) = getpwent) {
    $user{$uid} = $name unless $user{$uid};
}

while (($name, $pw, $gid) = getgrent) {
    $group{$gid} = $name unless $group{$gid};
}

require "find.pl";

# Traverse desired filesystems

&find($start_dir);

exit;

sub wanted {
    (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
    -d _ &&
    (  $skip_nfs &&
       ($dev < 0 || $dev >= 16384) &&
       ($prune = 1)
    )
    ||
    -f _ &&
    (
       ($mode & 04000) == 04000
       ||
       ($mode & 02000) == 02000
    ) &&
    &ls;
}

sub ls {
    ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$sizemm,
      $atime,$mtime,$ctime,$blksize,$blocks) = lstat(_);

    $pname = $name;

    if (defined $blocks) {
       $blocks = int(($blocks + 1) / 2);
    }
    else {
       $blocks = int(($size + 1023) / 1024);
    }

    if    (-f _) { $perms = '-'; }
    elsif (-d _) { $perms = 'd'; }
    elsif (-c _) { $perms = 'c'; $sizemm = &sizemm; }
    elsif (-b _) { $perms = 'b'; $sizemm = &sizemm; }
    elsif (-p _) { $perms = 'p'; }
    elsif (-S _) { $perms = 's'; }
    else         { $perms = 'l'; $pname .= ' -> ' . readlink($_); }

    $tmpmode = $mode;
    $tmp = $rwx[$tmpmode & 7];
    $tmpmode >>= 3;
    $tmp = $rwx[$tmpmode & 7] . $tmp;
    $tmpmode >>= 3;
    $tmp = $rwx[$tmpmode & 7] . $tmp;
    substr($tmp,2,1) =~ tr/-x/Ss/ if -u _;
    substr($tmp,5,1) =~ tr/-x/Ss/ if -g _;
    substr($tmp,8,1) =~ tr/-x/Tt/ if -k _;
    $perms .= $tmp;

    $user = $user{$uid} || $uid;
    $group = $group{$gid} || $gid;

    ($sec,$min,$hour,$mday,$mon,$year) = localtime($mtime);
    $moname = $moname[$mon];
    if (-M _ > 365.25 / 2) {
       $timeyear = '19' . $year;
    }
    else {
       $timeyear = sprintf("%02d:%02d", $hour, $min);
    }

    printf "%5lu %4ld %-10s %2d %-8s %-8s %8s %s %2d %5s %s\n",
           $ino,
                $blocks,
                     $perms,
                           $nlink,
                               $user,
                                    $group,
                                         $sizemm,
                                             $moname,
                                                $mday,
                                                    $timeyear,
                                                        $pname;
    1;
}

sub sizemm {
    sprintf("%3d, %3d", ($rdev >> 8) & 255, $rdev & 255);
}