#!/bin/sh
##
## useradd(8) wrapper to emulate Red Hat Linux
## Copyright (c) 2008-2009 SATOH Fumiyasu @ OSS Technology Corp.
##               <http://www.osstech.co.jp>
##
## License: GNU General Public License version 2 or later
## Date: 2009-07-03, since 2008-06-10
##

set -u

pinfo()                                                                                                         
{
  echo "$0: INFO: $*" 1>&2
}

perr()
{
  echo "$0: ERROR: $*" 1>&2
}

pdie()
{
  perr "$*"
  exit 1
}

run()
{
  if [ -n "${no_run_f:-}" ]; then
    pinfo "run: $*"
  else
    ${1+"$@"}
  fi
}

## ======================================================================

useradd_cmd="/usr/sbin/useradd"
passwd_cmd="/usr/bin/passwd"

no_run_f=""

uid=""
no_uniq_uid_f=""
group=""
no_user_group_f=""
groups=""
comment=""
home_dir=""
create_home_f=""
no_create_home_f=""
skelton_dir=""
shell=""
system_user_f=""
no_lastlog_f=""

add_user_group_by_groupadd=""

uname=`uname`
case "$uname" in
Linux)
  if [ -f /etc/redhat-release ]; then
    exec "$useradd_cmd" ${1+"$@"}
    exit 1
  elif [ -f /etc/debian_version ]; then
    os="debian"
  fi
  uid_reserved_min="200"
  uid_reserved_max="299"
  uid_system_min="300"
  uid_system_max="399"
  uid_user_min="400"
  uid_user_max="499"
  ;;
SunOS)
  os="solaris"
  uid_reserved_min="200"
  uid_reserved_max="299"
  uid_system_min="300"
  uid_system_max="399"
  uid_user_min="400"
  uid_user_max="499"
  add_user_group_by_groupadd="yes"
  ;;
AIX)
  os="aix"
  uid_reserved_min="300"
  uid_reserved_max="399"
  uid_system_min="400"
  uid_system_max="449"
  uid_user_min="450"
  uid_user_max="499"
  add_user_group_by_groupadd="yes"
  ;;
*)
  pdie "Unknown OS platform: $uname"
  ;;
esac

cmd_usage="Usage: $0 [OPTIONS] LOGIN"

## ----------------------------------------------------------------------

while getopts zu:ong:G:c:d:mk:Ms:rl opt; do
  case "$opt" in
  z)
    no_run_f="yes"
    ;;
  u)
    uid="$OPTARG"
    ;;
  o)
    if [ x"$os" = x"aix" ]; then
      pdie "-$opt option not supported"
    fi
    no_uniq_uid_f="yes"
    ;;
  g)
    group="$OPTARG"
    ;;
  n)
    no_user_group_f="yes"
    ;;
  G)
    groups="$OPTARG"
    ;;
  c)
    comment="$OPTARG"
    ;;
  d)
    home_dir="$OPTARG"
    ;;
  m)
    create_home_f="yes"
    ;;
  M)
    no_create_home_f="yes"
    ;;
  k)
    skelton_dir="$OPTARG"
    ;;
  r)
    system_user_f="yes"
    ;;
  s)
    shell="$OPTARG"
    ;;
  l)
    no_lastlog_f="yes"
    ;;
  *)
    exit 1
    ;;
  esac
done
shift `expr $OPTIND - 1 || :`

if [ $# -ne 1 ]; then
  echo "$cmd_usage"
  exit 1
fi

login="$1"; shift
uid_orig="$uid"

## ----------------------------------------------------------------------

if [ -n "$system_user_f" ]; then
  if [ -n "$uid" ]; then
    uid_min="$uid_reserved_min"
    uid_max="$uid_reserved_max"
  else
    uid_min="$uid_system_min"
    uid_max="$uid_system_max"
  fi
else
  uid_min="$uid_user_min"
  uid_max="$uid_user_max"
fi

if [ -n "$uid" ]; then
  if [ -n "$system_user_f" ]; then
    ## Adjust UID to avoid reserved system UID conflict
    uid_orig="$uid"
    uid=`expr "$uid" + "$uid_reserved_min"`
  fi
  if [ "$uid" -lt "$uid_min" ] || [ "$uid" -gt "$uid_max" ]; then
    pdie "Out of UID range (min. $uid_min - max. $uid_max)"
  fi
else
  uid_test="$uid_min"
  while [ "$uid_test" -le "$uid_max" ]; do
    if getent passwd "$uid_test" >/dev/null; then
      uid_test=`expr "$uid_test" + 1`
      continue
    fi
    uid="$uid_test"
    break
  done
  if [ -z "$uid" ]; then
    pdie "No free UID (min. $uid_min - max. $uid_max)"
  fi
fi

if [ -z "$group" ]; then
  if [ -z "$no_user_group_f" ] && [ -n "$add_user_group_by_groupadd" ]; then
    group="$login"
    if getent group "$group" >/dev/null; then
      : OK
    else
      gid=""
      if [ -n "$uid_orig" ]; then
	getent group "$uid" >/dev/null || gid="$uid_orig"
      fi
      run "`dirname "$0"`/groupadd" \
	${system_user_f:+-r} \
	${gid:+-g} ${gid:+"$gid"} \
	"$group"
    fi
  fi
fi

## Default home directory location
if [ -z "$home_dir" ]; then
  home_dir="/home/$login"
fi

## Create home directory by default if option -r and -M are specified
if [ -z "$system_user_f" ] && [ -z "$no_create_home_f" ]; then
  create_home_f="yes"
fi

shift $#
case "$os" in
debian)
  if [ -z "$group" ]; then
    if [ -n "$no_user_group_f" ]; then
      set -- ${1+"$@"} -N
    else
      set -- ${1+"$@"} -U
    fi
  fi
  [ -n "$no_lastlog_f" ] && set -- ${1+"$@"} -l
  ;;
solaris)
  case "$shell" in
  */nologin)
    ## /sbin/nologin does not exist
    shell="/bin/false"
    ;;
  esac
  ;;
aix)
  ## If $groups (-G option) is omitted, use $group instead because
  ## /usr/sbin/useradd uses 'staff' group to a new user in that case.
  if [ -z "$groups" ] && [ -n "$group" ]; then
    groups="$group"
  fi
  case "$shell" in
  */nologin)
    ## /sbin/nologin does not exist
    shell="/bin/false"
    ;;
  esac
  ;;
esac

## ======================================================================

run "$useradd_cmd" \
  ${uid:+-u} ${uid:+"$uid"} \
  ${no_uniq_uid_f:+-o} \
  ${group:+-g} ${group:+"$group"} \
  ${groups:+-G} ${groups:+"$groups"} \
  ${comment:+-c} ${comment:+"$comment"} \
  ${home_dir:+-d} ${home_dir:+"$home_dir"} \
  ${create_home_f:+-m} \
  ${skelton_dir:+-k} ${skelton_dir:+"$skelton_dir"} \
  ${shell:+-s} ${shell:+"$shell"} \
  ${1+"$@"} \
  "$login"
useradd_ret="$?"
if [ "$useradd_ret" -ne 0 ]; then
  pdie "$useradd_cmd returns error status: $useradd_ret"
fi

if [ x"$os" = x"solaris" ]; then
  ## Unlock the account, but disable password
  run "$passwd_cmd" -N "$login" >/dev/null
  passwd_ret="$?"
  if [ "$passwd_ret" -ne 0 ]; then
    pdie "$passwd_cmd returns error status: $passwd_ret"
  fi
fi

exit 0

