#!/bin/sh

po_domain="alterator-users"
default_groups="cdwriter cdrom audio proc radio camera floppy xgrp scanner uucp"
default_groups_file=/usr/share/install3/default-groups

#turn off auto expansion
set -f

. alterator-sh-functions
. shell-quote

UID_MIN=$(grep '^UID_MIN' /etc/login.defs 2>/dev/null|sed -r 's,UID_MIN[[:space:]]+,,')
[ -z "$UID_MIN" ] && UID_MIN=500

local_getent()
{
    local re="${2:-.*}"
    grep "^$re:" "/etc/$1"
}

user_list()
{
    local IFS=:

    local_getent passwd|
    while read name password uid gid gecos home shell; do
        [ "$uid" -ge "$UID_MIN" ] || continue
	[ "$shell" == "/sbin/nologin" ] || grep -qs "^$shell$" /etc/shells || continue
	[ -x "$shell" ] || continue
	echo "$name"
    done 2>/dev/null
}

is_defined()
{
	set |grep -qs "^$1="
}

user_args()
{
	local args=
	is_defined "in_gecos" && args="$args -c \"$(quote_shell "$in_gecos")\""
	[ -n "$in_home" ] && args="$args -d \"$(quote_shell "$in_home")\""
	[ -n "$in_shell" ] && args="$args -s \"$in_shell\""
	echo "$args"
}

user_read()
{
    local IFS=:
    local name="$1";shift

    local_getent passwd "$name"|
	(read name password uid gid gecos home shell;
	 write_string_param gecos "$gecos"
	 write_string_param home "$home"
	 write_string_param shell "$shell"

	 ! local_getent group wheel|cut -d: -f4|fgrep -qws "$name"
	 write_bool_param allow_su "$?")
}

user_write_error()
{
    local msg="$(printf "$@")"
    write_error "$msg"
    return 1
}

user_write_retcode()
{
	case "$1" in
		1) write_error "`_ "can't update password file"`" ;;  #'
		2) write_error "`_ "invalid command syntax"`" ;; 
		3) write_error "`_ "invalid argument to option"`" ;; 
		4) write_error "`_ "uid already in use"`" ;; 
		6) write_error "`_ "specified user doesn't exist"`" ;; #'
		8) write_error "`_ "user currently logged in"`" ;;
		9) write_error "`_ "username already in use"`" ;;
		10) write_error "`_  "can't update group file"`" ;; #'
		12) write_error "`_ "can't create or remove home directory"`" ;;#'
		13) write_error "`_ "can't create mail spool"`" ;; #'
		*) write_error "retcode=$1" ;;
	esac
	return "$1"
}

user_chpasswd()
{
    echo "$1:$2"|/usr/sbin/chpasswd ||
	user_write_error "`_ "cannot change password"`"
}

user_new()
{
    /usr/sbin/useradd "$@" ||
	user_write_retcode "$?"
}

user_write()
{
    /usr/sbin/usermod "$@" ||
	user_write_retcode "$?"
}

user_delete()
{
    /usr/sbin/userdel "$1" ||
	user_write_retcode "$?"
}

group_write_retcode()
{
	case "$1" in
		2) write_error "`_ "invalid command syntax"`" ;;
		3) write_error "`_ "invalid group name"`" ;;
		4) write_error "`_ "gid not unique"`" ;; 
		6) write_error "`_ "specified group doesn't exist"`" ;;
		8) write_error "`_ "can't remove user's primary group"`" ;; #'
		9) write_error "`_ "group name not unique"`" ;;
		10) write_error "`_ "can't update group file"`" ;; #'
		*) write_error "retcode=$1" ;;
	esac
	return "$1"
}

group_new()
{
    /usr/sbin/groupadd -f -r "$1" 2>/dev/null ||
	group_write_retcode "$?"
}

group_include()
{
    group_new "$1" || return 1

    /usr/bin/gpasswd -a "$2" "$1" >/dev/null ||
	user_write_error "`_ "unable to add user %s to group %s"`" "$2" "$1"
}

group_include_default()
{
    [ -s "$default_groups_file" ] && default_groups="$(cat "$default_groups_file")"
    for i in $default_groups; do
	group_include "$i" "$1" || return 1
    done
}

group_exclude()
{
    /usr/bin/gpasswd -d "$2" "$1" >/dev/null
}

on_message()
{
	case "$in_action" in
		constraints)
		    echo '('
		    printf 'name (match ("%s" "%s") label "%s")\n' \
			"^[a-z_][a-z0-9_-]*$" \
			"`_ "only small latin letters, digits and '_' allowed"`" \
			"`_ "Name"`"
		    echo ')'
		    ;;
		#object manipulations
		list)
		    echo '('
			case "$in__objects" in
			    avail_shell)
				while read sh; do
				    [ -x "$sh" ] || continue
				    write_enum_item "$sh"
				done </etc/shells
				write_enum_item "/sbin/nologin"
				;;
			    *)
				user_list|write_enum
				;;
			esac
		    echo ')'
		    ;;
		read)
			echo '('
			[ -n "$in_name" ] || in_name="$(user_list|head -n1)"

			write_string_param passwd_auto "$(pwqgen)"
			! test_bool "$in_auto"
			write_bool_param auto "$?"

			[ -n "$in_name" ] || in_name="$(user_list|head -n1)"

			[ -n "$in_name" ] && user_read "$in_name"
			echo ')'
			;;
		write)
			[ -n "$in_name" ] || in_name="$(user_list|head -n1)"
			local args="$(user_args)"

			#main settings
			if [ -n "$args" ];then
			    eval user_write $args "$in_name" || return
			fi

			#password
			if test_bool "$in_auto" && [ -n "$in_passwd_auto" ]; then
			    user_chpasswd "$in_name" "$in_passwd_auto"
			elif ! test_bool "$in_auto" && [ -n "$in_passwd_1" -o -n "$in_passwd_2" ] ; then
			    if [ "$in_passwd_1" != "$in_passwd_2" ]; then
				write_error "`_ "Passwords mismatch"`"
				return
			    else
				user_chpasswd "$in_name" "$in_passwd_1"
			    fi
			fi

			#wheel
			if test_bool "$in_allow_su"; then
				group_include wheel "$in_name" || return
			else
				group_exclude wheel "$in_name"
			fi

			write_nop
			;;
		new)
			if [ -z "$in_name" ];then
			    write_nop
			    return
			fi

			#new
			local args="$(user_args)"
			eval user_new $args "$in_name" || return

			#wheel
			if test_bool "$in_allow_su";then
				group_include wheel "$in_name" || return
			fi

			#default groups
			group_include_default "$in_name" || return

			#password
			if test_bool "$in_auto" && [ -n "$in_passwd_auto" ]; then
			    user_chpasswd "$in_name" "$in_passwd_auto"
			elif ! test_bool "$in_auto" && [ -n "$in_passwd_1" -o -n "$in_passwd_2" ] ; then
			    if [ "$in_passwd_1" != "$in_passwd_2" ]; then
				write_error "`_ "Passwords mismatch"`"
				return
			    else
				user_chpasswd "$in_name" "$in_passwd_1"
			    fi
			fi

			write_nop
			;;
		delete)
			if [ -n "$in_name" ] ;then
			    user_delete "$in_name" || return
			fi
			write_nop
			;;
		*)
			echo '#f'
			;;
	esac
}

message_loop
