#!/usr/bin/perl -w
##############################################################################
# Dump users from LDAP into /etc/passwd
##############################################################################

use IPC::Open3;
use File::Copy;

#
# Grab passwd entries
#
my @passwd_entries;

# Use open3 so stderr goes away
my $pid = open3(\*CMDIN, \*CMDOUT, \*CMDERR,
	'ldapsearch', '-x',
	'objectClass=posixAccount');
close(CMDIN);
close(CMDERR);

my $user;
my $uid;
my $gid;
my $gecos;
my $homedir;
my $shell;
while(<CMDOUT>)
{
	if (/^dn: uid=(\w+)/)
	{
		# We've encountered a new user entry, push the previous one
		# onto our list of passwd entries.
		if ($user && $uid && $gid && $gecos && $homedir && $shell)
		{
			#print "$user:x:$uid:$gid:$gecos:$homedir:$shell\n";
			push(@passwd_entries, "$user:x:$uid:$gid:$gecos:$homedir:$shell");
			$user = '';
			$uid = '';
			$gid = '';
			$gecos = '';
			$homedir = '';
			$shell = '';
		}

		$user = $1;
	}
	elsif (/^uidNumber: (\d+)/)
	{
		$uid = $1;
	}
	elsif (/^gidNumber: (\d+)/)
	{
		$gid = $1;
	}
	elsif (/^cn: (.+)/)
	{
		$gecos = $1;
	}
	elsif (/^homeDirectory: (.+)/)
	{
		$homedir = $1;
	}
	elsif (/^loginShell: (.+)/)
	{
		$shell = $1;
	}
}
close(CMDOUT);

# Push the last entry
if ($user && $uid && $gid && $gecos && $homedir && $shell)
{
	#print "$user:x:$uid:$gid:$gecos:$homedir:$shell\n";
	push(@passwd_entries, "$user:x:$uid:$gid:$gecos:$homedir:$shell");
}

if (scalar @passwd_entries == 0)
{
    die "No users retrieved from LDAP";
}

#
# Starting with the current /etc/passwd, remove any old entries that
# we added, then add the new entries based on the information we retrieved.
# This is used to build a passwd.ldap working file.
#

my $START = "# Users from LDAP start here\n";
my $END = "# Users from LDAP end here\n";

my $skipping;
open(PASSWD, '< /etc/passwd') || die;
open(NEWPASSWD, '> /etc/passwd.ldap') || die;
while(<PASSWD>)
{
	if ($_ eq $START)
	{
		$skipping = 1;
	}
	elsif ($_ eq $END)
	{
		$skipping = 0;
	}
	else
	{
		print NEWPASSWD $_ unless ($skipping);
	}
}
close(PASSWD);

print NEWPASSWD $START;
foreach my $entry (@passwd_entries)
{
	print NEWPASSWD "$entry\n";
}
print NEWPASSWD $END;
close(NEWPASSWD);

# Now some sanity checks to make sure we've written out a valid file
if (! -s '/etc/passwd.ldap')
{
	die "/etc/passwd.ldap is empty";
}

#
# Now make a backup copy of the current passwd file and move our working
# copy into place.
#

copy('/etc/passwd', '/etc/passwd.bak');
move('/etc/passwd.ldap', '/etc/passwd');

