#
# I'm not sure how or why, but something is racy here...
#

package ldaputils;

sub get_next_id($$$) {
    my $ldap_server = shift;
    my $ldap_base_dn = shift;
    my $attribute = shift;
    my $tries = 0;
    my $next_uid_mesg;
    my $nextuid;
    do {
	$next_uid_mesg = $ldap_server->search(
				       base => $ldap_base_dn,
				       filter => "(objectClass=sambaUnixIdPool)",
				       scope => "base"
				       );
	$next_uid_mesg->code && die "Error looking for next uid";
	if ($next_uid_mesg->count != 1) {
	    die "Could not find base dn, to get next uid";
	}
	my $entry = $next_uid_mesg->entry(0);
	    
	$nextuid = $entry->get_value($attribute);
	if ($ldap_server->modify( $ldap_base_dn,
			changes => [
				    delete => [ $attribute => $nextuid ],
				    add => [ $attribute => $nextuid + 1 ]
				    ]
			))
	    {
		my $check_uid_mesg = $ldap_server->search(
				      base => $ldap_base_dn,
				      filter => "($attribute=$nextuid)",
				      );
		$check_uid_mesg->code && die "Cannot confirm $attribute $nextuid is free";
		if ($check_uid_mesg->count == 0) {
		    return $nextuid;
		}
	    }
	    $tries++;
    } while ($tries < 5);

	die "Could not allocate $attribute!";
}

sub get_next_uid($$) {
    my $ldap_server = shift;
    my $ldap_base_dn = shift;
    return get_next_id($ldap_server, $ldap_base_dn, "uidNumber");
}
sub get_next_gid($$) {
    my $ldap_server = shift;
    my $ldap_base_dn = shift;
    return get_next_id($ldap_server, $ldap_base_dn, "gidNumber");
}

sub get_admin_dn($$) {
    my $admin_uid;
    if ($ENV{'SUDO_USER'}) {
	$admin_uid = $ENV{'SUDO_USER'};
    } else {
	$admin_uid = $ENV{'LOGNAME'};
    }

    my $ldap = shift;
    my $ldap_base_dn = shift;
    my $admin_dn;
    my $admin_mesg = $ldap->search(
				   base => $ldap_base_dn,
				   filter => '(&(objectClass=posixAccount)(uid='.$admin_uid.'))',
				   );
    $admin_mesg->code == 0 || die "";
    if ($admin_mesg->count > 1 ) {
	die "More than one admin user entry for $admin_uid ??..\n";
    } elsif ($admin_mesg->count < 1 ) {
	die "No admin user entry for $admin_uid ??..\n";
    } else {
	my $entry = $admin_mesg->entry(0);
	$admin_dn = $entry->dn;
    }
    return $admin_dn;
}                                                                                                                                                             

sub get_admin_pw($) {
    my $admin_dn = shift;
# Initial password prompt
    system "stty -echo";
    print "Admin Password for $admin_dn: ";
    my $admin_pw;
    chop($admin_pw = <STDIN>);
    print "\n";
    system "stty echo";

    return $admin_pw;
}
                                                                                                                                                             


1;
