#!/usr/bin/perl -w
##############################################################################
# Dump groups from LDAP into /etc/group
##############################################################################

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

#
# Grab group entries
#
my @group_entries;

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

my $group;
my $gid;
my @members;
while(<CMDOUT>)
{
	if (/^dn: cn=(\w+)/)
	{
		# We've encountered a new group entry, push the previous one
		# onto our list of group entries.
		if ($group && $gid)
		{
			my $memstring = '';
			$memstring = join(',', @members) if (@members);

			#print "$group:x:$gid:$memstring\n";
			push(@group_entries, "$group:x:$gid:$memstring");
			$group = '';
			$gid = '';
			@members = ();
		}

		$group = $1;
	}
	elsif (/^gidNumber: (\d+)/)
	{
		$gid = $1;
	}
	elsif (/^memberUid: (\w+)/)
	{
		push(@members, $1);
	}
}
close(CMDOUT);

# Push the last entry
if ($group && $gid)
{
	my $memstring = '';
	$memstring = join(',', @members) if (@members);

	#print "$group:x:$gid:$memstring\n";
	push(@group_entries, "$group:x:$gid:$memstring");
}

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

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

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

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

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

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

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

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

