#!/usr/bin/perl
##
## getent(1) clone
## Copyright (c) 2007-2011 SATOH Fumiyasu @ OSS Technology Corp.
##               <http://www.osstech.co.jp>
##
## License: GNU General Public License version 2 or later
## Date: 2011-07-11, since 2007-07-14
##

use strict;
use warnings;
use English qw(-no_match_vars);
use IO::File;

my $getent_by_db = {
  'passwd' => {
    'enum' =>		sub { getpwent; },
    'by_name' =>	sub { getpwnam(shift); },
    'by_id' =>		sub { getpwuid(shift); },
    'filter' =>		sub { $_[1] = 'x'; splice(@_, 4, 2); @_; },
  },
  'group' => {
    'enum' =>		sub { getgrent; },
    'by_name' =>	sub { getgrnam(shift); },
    'by_id' =>		sub { getgrgid(shift); },
    'filter' =>		sub { $_[3] =~ s/ /,/g; @_; },
  },
};

my ($db, $key) = @ARGV;

unless ($db) {
  print "Usage: $0 DATABASE [KEY]\n";
  exit(1);
}

my $getent = $getent_by_db->{$db};
unless (defined($getent)) {
  STDERR->print("$0: ERROR: Unknown database: $db\n");
  exit(1);
}

my $filter = $getent->{'filter'} || sub { @_ };
my $separator = $getent->{'separator'} || ':';

unless (defined($key)) {
  my @enums = ($getent->{'enum'});

  if ($OSNAME eq 'aix') {
    open(my $methods_fh, '/usr/lib/security/methods.cfg')
      || die "$0: ERROR: Cannot open /usr/lib/security/methods.cfg: $OS_ERROR\n";
    my $ldap = undef;
    while (!$methods_fh->eof) {
      my $methods_line = $methods_fh->getline;
      $ldap = 1 if ($methods_line =~ /^LDAP:/);
    }

    if ($ldap) {
      my $enum_fh = undef;
      my $getent_by_name = undef;
      if ($db eq 'passwd') {
	open($enum_fh, '-|', qw(/usr/sbin/lsuser -R LDAP -a id ALL))
	  || die "$0: ERROR: Cannot run /usr/sbin/lsuser: $OS_ERROR\n";
	$getent_by_name = sub { getpwnam($_[0]); };
      }
      elsif ($db eq 'group') {
	open($enum_fh, '-|', qw(/usr/sbin/lsgroup -R LDAP -a id ALL))
	  || die "$0: ERROR: Cannot run /usr/sbin/lsgroup: $OS_ERROR\n";
	$getent_by_name = sub { getgrnam($_[0]); };
      }

      if ($enum_fh) {
	push(@enums, sub {
	  return () if ($enum_fh->eof);
	  my $name = $enum_fh->getline;
	  $name =~ s/ id=\d+$//;
	  return $getent_by_name->($name);
	});
      }
    }
  }

  for my $enum (@enums) {
    while (my @ent = $enum->()) {
      print join($separator, $filter->(@ent)), "\n";
    }
  }

  exit(0);
}

my @ent = ($key =~ /^\d+$/)
  ? $getent->{'by_id'}->($key)
  : $getent->{'by_name'}->($key);
unless (@ent) {
  exit(2);
}

print join($separator, @ent), "\n";
exit(0);

