#!/usr/bin/perl

# create-users (Source listing 3)
# Populate the /etc/passwd, /etc/shadow, and /etc/auto_home files
# with userids so they can log onto the system, and set up the 
# corresponding group entries in /etc/group

# Program relies on 2 datafiles, users.dat and groups.dat
#

# users.dat
# ---------
# format
# username:des_passwd:uid:gid:gecos:shell

# groups.dat
# ----------
# format
# groupname:gid

use strict;
use vars qw($UserFile $GroupFile $BASE %OKGroups %RepShell $Users $Groups);

#
# Global Variables
#

$UserFile="$ENV{'SI_CONFIG_DIR'}/files/users.dat";
$GroupFile="$ENV{'SI_CONFIG_DIR'}/files/groups.dat";
$BASE="/a" unless($BASE);

# OKGroups
#
# NOTICE:
# Only users belonging to groups in this array will be built into the 
# /etc files
# Comment out indivudual lines to exclude groups
#
%OKGroups=(
	"50" => 1,	# Administrators
	"51" => 1,	# Engineers
#	"52" => 1,	# Managers
);

# Replacement shells.  Reset the user's shell to something else if it isn't 
# installed on the host system.

%RepShell=(
	"/bin/tcsh" => "/bin/csh",
	"/bin/bash" => "/bin/sh",
);

#
# Subroutines
#

# Load the users file
sub loadUsers
{
my ($file)=@_;
my ($struct,$x,$user,$pw,$uid,$gid,$name,$shell);
open (F, $file) || return(undef);
while ($x=<F>)
{
	next if ($x=~/^#/);
	chop($x);
	($user,$pw,$uid,$gid,$name,$shell)=split(/:/,$x);
	$struct->{$user}->{user}=$user;
	$struct->{$user}->{pw}=$pw;
	$struct->{$user}->{uid}=$uid;
	$struct->{$user}->{gid}=$gid;
	$struct->{$user}->{name}=$name;
	$struct->{$user}->{shell}=$shell;
}
close(F);
return($struct);
}

# Load the groups file
sub loadGroups
{
my ($file)=@_;
my ($struct,$x,$name,$gid);
open (F, $file) || return(undef);
while ($x=<F>)
{
	chop($x);
	($name,$gid)=split(/:/,$x);
	$struct->{$gid}=$name;
}
close(F);
return($struct);
}

# Verify that the shells are correct for the users file
sub checkShells
{
my ($users)=@_;
my ($loop,$tshell);
foreach $loop (keys(%{$users}))
{
	$tshell=$users->{$loop}->{shell};
	if (! -x "$BASE/$tshell")
	{
		print("WARNING: No $tshell for $loop\n");
		if ($RepShell{$tshell})
		{
			$users->{$loop}->{shell}=$RepShell{$tshell};
		} else {
			$users->{$loop}->{shell}="/bin/sh";
		}
	}
}
return();
}

# Build the /etc/passwd file to the jumpstart host
sub buildPassword
{
my ($users)=@_;
my ($target)="$BASE/etc/passwd";
my ($gid,$usr);
open (T, ">>$target") || return(undef);
foreach $gid (keys(%OKGroups))
{
	foreach $usr (keys(%{$users}))
	{
		if ($users->{$usr}->{gid} == $gid)
		{
			print T ($usr.":x"
				.":".$users->{$usr}->{uid}
				.":".$users->{$usr}->{gid}
				.":".$users->{$usr}->{name}
				.":/home/$usr"
				.":".$users->{$usr}->{shell}."\n");
		}
	}
}
close(T);
return();
}

sub buildShadow
{
my ($users)=@_;
my ($target)="$BASE/etc/shadow";
my ($gid,$usr);
open (T, ">>$target") || return(undef);
foreach $gid (keys(%OKGroups))
{
	foreach $usr (keys(%{$users}))
	{
		if ($users->{$usr}->{gid} == $gid)
		{
			print T ($usr.":".$users->{$usr}->{pw}
				.":6445::::::\n");
		}
	}
}
close(T);
return();
}

sub buildGroup
{
my ($groups)=@_;
my ($target)="$BASE/etc/group";
my ($grp);
open (T, ">>$target") || return(undef);
foreach $grp (keys(%{$groups}))
{
	print T ($groups->{$grp}."::".$grp.":\n");
}
close(T);
return();
}

sub buildAutoHome
{
my ($users)=@_;
my ($target)="$BASE/etc/auto_home";
my ($gid,$usr,$fmt,$fsinfo);
$fmt="%-10s%-15s%s\n";
$fsinfo="-fstype=lofs";
open (T, ">>$target") || return(undef);
foreach $gid (keys(%OKGroups))
{
	foreach $usr (keys(%{$users}))
	{
		if ($users->{$usr}->{gid} == $gid)
		{
			printf T ($fmt,$usr,$fsinfo,":/export/home/$usr");
		}
	}
}
return();
}

#
# Main Program Block
#

# Notification Block

print("Populating local user files\n");
print("WARNING:  Disable all non-files based username lookup schemes!\n");
print("NOTICE: shell preferences will be changed if shell is not on host\n");
print("\n");

# Load users.dat

($Users)=&loadUsers($UserFile);

# Load groups.dat
($Groups)=&loadGroups($GroupFile);

# Verify shells

&checkShells($Users);

# Build /etc/passwd file

print("Populating /etc/passwd file\n");
&buildPassword($Users);

# Build /etc/shadow file

print("Populating /etc/shadow file\n");
&buildShadow($Users);

# Build /etc/group file

print("Populating /etc/group file\n");
&buildGroup($Groups);

# Build /etc/auto_home file

print("Populating /etc/auto_home file\n");
&buildAutoHome($Users);
