#!/bin/sh
##
## UNIX group account admin script to provide a common interface
## Copyright (c) 2008 SATOH Fumiyasu @ OSS Technology Co., Ltd.
##
## Licese: GNU General Public License version 2
## Date: 2008-02-27, since 2008-02-25
##

## FIXME: Test on Solaris
## FIXME: Add support smbldap-tools?
## FIXME: `useradd -K KEY=VALUE` is not supported on RHEL4

set -u
umask 0022

LC_ALL=C
PATH="/opt/osstech/bin:/opt/osstech/sbin:/usr/sbin:/usr/bin:/bin:/sbin"
export LC_ALL PATH

## Functions
## ======================================================================

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

pwarn()
{
  echo "$0: WARNING: $1" 1>&2
}

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

pdie()
{
  perr "$1"
  exit ${2-1}
}

run()
{
  [ "$#" -gt 0 ] && [ -n "${flag_verbose-}" ] && pinfo "run: $*"
  [ -z "$flag_run" ] && return 0
  ${1+"$@"}
  return $?
}

run_or_die()
{
  run ${1+"$@"}
  _run_status="$?"
  [ "$_run_status" -ne 0 ] && pdie "command failed ($_run_status): $*"
}

## Groups of a user except the primary group
groups()
{
  LC_ALL=C /usr/bin/id -a "$1" \
  |/bin/sed -n 's/^.* groups=//p' \
  |/bin/sed 's/[0-9]*(\([^)]*\))/\1/g' \
  |/usr/bin/tr ',' '\n' \
  |/bin/sed '1d'
}

## Options
## ======================================================================

flag_verbose=""
flag_run="yes"

gid=""
gid_min=""
gid_max=""
add_members=""
delete_members=""
flag_print_gid=""

cmd_usage="Usage: $0 OPERATION [OPTIONS] GROUP"

## Command-line options
## ----------------------------------------------------------------------

if [ $# -lt 2 ]; then
  echo "$cmd_usage"
  exit 0
fi
op_name="$1"; shift

getopts_want_arg()
{
  if [ "$1" -eq 0 ]; then
    pdie "option requires an argument: $2" 1>&2
  fi
}

while test "$#" -gt 0; do
  opt="$1"; shift
  case "$opt" in
  -v|--verbose)
    flag_verbose="yes"
    ;;
  --no-run)
    flag_run=""
    ;;
  -g|--gid)
    getopts_want_arg "$#" "$opt"
    gid="$1"; shift
    ;;
  --gid-min)
    getopts_want_arg "$#" "$opt"
    gid_min="$1"; shift
    ;;
  --gid-max)
    getopts_want_arg "$#" "$opt"
    gid_max="$1"; shift
    ;;
  -m|--add-members)
    getopts_want_arg "$#" "$opt"
    add_members="$1"; shift
    ;;
  -x|--delete-members)
    getopts_want_arg "$#" "$opt"
    delete_members="$1"; shift
    ;;
  -p|--print-gid)
    flag_print_gid="yes"
    ;;
  --)
    break
    ;;
  -*)
    pdie "invalid option: $opt" 1>&2
    exit 1
    ;;
  *)
    set -- "$opt" ${1+"$@"}
    break
    ;;
  esac
done

if [ $# -ne 1 ]; then
  echo "$cmd_usage"
  exit 0
fi
group="$1"; shift

case "$op_name" in
add)
  run_or_die /usr/sbin/groupadd \
    ${gid:+-g "$gid"} \
    ${gid_min:+-K GID_MIN="$gid_min"} \
    ${gid_max:+-K GID_MAX="$gid_max"} \
    "$group"
  if [ -n "$flag_print_gid" ]; then
    /usr/bin/getent group "$group" |cut -d : -f 3
  fi
  ;;
modify)
  echo "$add_members" |tr ',' '\n' \
  |while read login; do
    id "$login" >/dev/null 2>&1 || continue
    groups_new="`groups "$login" |grep -v "^$group$" |tr '\n' ','`$group"
    run_or_die /usr/sbin/usermod -G "$groups_new" "$login"
  done || exit 1
  echo "$delete_members" |tr ',' '\n' \
  |while read login; do
    id "$login" >/dev/null 2>&1 || continue
    groups_new="`groups "$login" |grep -v "^$group$" |tr '\n' ',' |sed 's/,$//'`"
    run_or_die /usr/sbin/usermod -G "$groups_new" "$login"
  done || exit 1
  run_or_die /usr/sbin/groupmod \
    ${gid:+-g "$gid"} \
    "$group"
  ;;
delete)
  run_or_die /usr/sbin/groupdel \
    "$group"
  ;;
*)
  pdie "invalid operation name: $op_name"
  ;;
esac

exit 0

