#! /usr/bin/perl -w
#
# create a script to create a lot of user accounts
#
# Copyright (C) 1996-99  August Hoerandl (hoerandl@elina.htlw16.ac.at)
#                        http://elina.htlw16.ac.at/~hoerandl
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# usage: make-user [options] file ...
#   output: a script to create new users
#
#  file is a list of new users
#    Firstname:Lastname:Group:Passwd
#
#  actions:
#    create user account with useradd
#    set password with newusers
#    set password age with chage
#  
# example
# create accounts from file 5bec-00.txt
#  group is bec00
#  homedir is /home/schueler/<group>/<name>
#  userid start with 1200
#
# ./make-user.pl -c ", Schueler 5BEC 98/99" -gbec00 -d"/home/schueler" \
#    -n 1200 5bec-00.txt | bash
#
#  pipe output into bash (as above) or save to file ( > filename ) and
#  execute after a check
#
# ==========================================================================
# Print the usage information if help requested (-h) or a bad option given.
#
sub usage
{
    die <<"EndUsage";
usage:                                              Version: 0.22
 make-user [options] files ...
    output: a script to create new users from files

  each file includes a list of new users
    # may be used for comments
    Firstname:Lastname:Group:Passwd

  options:
   -c txt    additional text for comment (Firstname Lastname)
   -d dir    directory prefix for login: \$dir/\$loginname
   -g dir    group prefix to path        \$dir/\$group/\$loginname
   -h        print help
   -n num    start uid with num 
   -p passwd default password: Firstname (ignore 4th field)
   -v        verbose output

EndUsage
}

# ==========================================================================
# read /etc/passwd  to users{}
sub read_passwd
{
    open(PASSWD, "/etc/passwd") || die "can not open /etc/passwd: $!\n"; 
    while (<PASSWD>) {
	($login,$passwd,$uid) = split(/:/);
	#$DEBUG && print "$login\n";
	$users{$login} = "old";
	$uids{$uid} = "new";
	$passwd = "";
	if ($uid > $newuid) {
	    $newuid = $uid;
	}
    }
    close PASSWD;
}

sub dump_passwd
{
    print "# current users:\t";
 
    foreach $user (sort keys(%users)) {
	print "$user\t";
    }
    print "\n";
    print "# max used uid = $newuid\n";
}

# ==========================================================================
# read /etc/group  to groups{}

sub read_groups
{
    open(GROUPS, "/etc/group") || die "can not open /etc/group: $!\n"; 
    while (<GROUPS>) {
	($group) = split(/:/);
	#$DEBUG && print "$login\n";
	$groups{$group} = "";
    }
    close GROUPS;
}

sub dump_groups
{
    print "# current groups:\t";
 
    foreach $group (sort keys(%groups)) {
	print "$group\t";
    }
    print "\n";
}


# ==========================================================================
# read file with new users

sub read_file
{
    local($file) = @_;
    $DEBUG && print "# Reading $file\n";

    open(FILE, $file) || die "can not open $file: $!\n"; 
    
    while (<FILE>) {
	next if /^#/;
	next if /^$/;
	chop;
	local($firstname,$lastname,$group,$secret) = split(/:/);
	$secret = "$firstname" unless $secret;

	if ($SECRET) {
	    $secret = $SECRET;
	}

	$DEBUG && print "#  read: $firstname, $lastname, $group\n";
 
	$group =~ y/A-Z/a-z/;

	$login = "#?? NO USERNAME ?? $lastname";
      LOOP:
	for ($lnl=length($lastname); $lnl >=0; $lnl--) {
	    for $ext ("", "1", "2", "3", "4", "5", "6", "7", "8", "9", $group) {
		for $fnl (0 .. length $firstname) {
		    $fn = substr($firstname, 0, $fnl);
		    $ln = substr($lastname, 0, $lnl);

		    $login = substr($fn . $ln . $ext, 0, 8);
		    $login =~ y/A-Z/a-z/;
		    #print "$login\t";
		    
		    last LOOP unless defined $users{$login};
		}
	    }
	}

	$DEBUG && print "#    name: $login\n"; 
	$users{$login} = "new";

	if (! defined $groups{$group}) {
	    #$newgroup{$group} = "";
	    $groups{$group} = "new";
	    $DEBUG && print "#    newgroup: $group\n";
	    print "groupadd $group\n";
	    if ($ADDGRP) {
		print "mkdir $DIRECTORY/$group\n";
	    }
	}
	
	#$newuser{$login}="$login:$firstname:$lastname:$group";
	
	# -g defaultgroup -G other_groups
	$opt_G = "-g $group";
	if ($group ne "users") { $opt_G = " -g $group -G users"; }

	# -d homedirectory
	$opt_b = "";
	if ($DIRECTORY) { $opt_b = "-d $DIRECTORY/$login"; }
	if ($ADDGRP) { $opt_b = "-d $DIRECTORY/$group/$login"; }

	# -c Comment
	$comm ="-c \"$firstname $lastname$COMM\"";

	# password
	$passwd = "";

	# look for unique uid
	do {
	    $newuid++ 
	} while ($uids{$newuid});
	$uids{$newuid} = "new";

	# create account
	print "useradd -m -s /bin/bash $opt_G $opt_b -u $newuid $comm $login \n";
	# change passwd 
	print "echo \"$login\:$secret\:::::\" | newusers\n";
	# set passwd age
	# mindays 0, maxdays 360, inaktiv 90, warning 30 
	print "chage -m 0 -M 360 -I 90 -W 30 $login\n" 
    }
}

# ==========================================================================
# Get the command-line options

$newuid = 0;
$DIRECTORY = "";

require "getopts.pl";

if (!(&Getopts('hvc:d:g:n:p:')) || $opt_h || $#ARGV != 0) { &usage; }
$opt_h = 0;

$DEBUG = 0;
$COMM = "";

if ($opt_v) { $DEBUG = 1; $opt_v = 0; }
if ($opt_d) { $DIRECTORY = $opt_d; }
#if ($opt_g) { $ADDGRP = 1; } #$DIRECTORY = $opt_g;  }
if ($opt_c) { $COMM = $opt_c; }
if ($opt_n) { $newuid = $opt_n - 1; }
if ($opt_p) { $SECRET = $opt_p; }

#$DEBUG = 1;

# ----------------
# start of main

print "set -v\n";

$FILE = $ARGV[0];

$DEBUG && print "# Reading /etc/passwd:\n";
&read_passwd;
$DEBUG && &dump_passwd;

$DEBUG && print "# Reading /etc/group:\n";
&read_groups;
$DEBUG && &dump_groups;

# believe to -n option
if ($opt_n) { $newuid = $opt_n - 1; }

$DEBUG && print "# Opening Input File: $FILE\n";

$DEBUG && print "# DIRECTORY=$DIRECTORY\n";
$DEBUG && print "# ADDGRP=$ADDGRP\n";
$DEBUG && print "# COMM=$COMM\n";
$DEBUG && print "# SECRET=$SECRET\n";

foreach $arg (@ARGV) {
    &read_file($arg);
}


