#!/bin/sh

alterator_api_version=1

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

##
# $ALTERATOR_DESTDIR - exported by installer.
#
# XXX: works only for: "add new user"
#

DESTDIR="/"
CHROOT_EXE=""

if [ -d "${ALTERATOR_DESTDIR:-}" ]; then
    DESTDIR="$ALTERATOR_DESTDIR"
    CHROOT_EXE="chroot $DESTDIR"
fi

#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_getent passwd|
    while IFS=':' 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 name="$1";shift

    local_getent passwd "$name"|
	(IFS=':' 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"| $CHROOT_EXE /usr/sbin/chpasswd ||
	user_write_error "`_ "cannot change password"`"
}

user_new()
{
    $CHROOT_EXE /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()
{
    $CHROOT_EXE /usr/sbin/groupadd -f -r "$1" 2>/dev/null ||
	group_write_retcode "$?"
}

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

    $CHROOT_EXE /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 "$DESTDIR/$default_groups_file" ] && default_groups="$(cat "$DESTDIR/$default_groups_file")"
    for i in $default_groups; do
	group_include "$i" "$1" || return 1
    done
}

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

on_message()
{
	case "$in_action" in
		type)
			write_type_item name system-account-name
			write_type_item new_name system-account-name
			;;
		list)
			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
			;;
		generate)
			write_string_param passwd_auto "$(pwqgen)"
			;;
		read)
			[ -z "$in_name" ] || user_read "$in_name"
			;;
		write)
			[ -n "$in_name" ] || return

			#main settings
			local args="$(user_args)"
			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" || return
			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" || return
			    fi
			fi

			#wheel
			if test_bool "$in_allow_su"; then
				group_include wheel "$in_name" || return
			else
				group_exclude wheel "$in_name"
			fi
			;;
		new)
			[ -n "$in_new_name" ] || return

			#prepare password
			local password=
			if test_bool "$in_auto" && [ -n "$in_passwd_auto" ]; then
			    password="$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
				password="$in_passwd_1"
			    fi
			fi

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

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

			#default groups
			group_include_default "$in_new_name" || return

			#password
			if [ -n "$password" ]; then
			    user_chpasswd "$in_new_name" "$password" || return
			fi
			;;
		delete)
			[ -z "$in_name" ] || user_delete "$in_name"
			;;
	esac
}

message_loop
