#!/bin/sh
# $Id: sudo-add.in,v 1.18 2011/04/15 18:35:30 rhansen Exp $

usage() {
    cat <<EOF
Usage:

  $0 [options] [--] <user> [<user>...]

Description:

  Adds the given users to the sudoers file, allowing them to run any
  program with superuser privileges.

  When <user> is added, the first line in sudoers beginning with
  <user> is modified (to preserve the order of entries in sudoers).
  All other lines beginning with <user> are removed.  If <user> isn't
  in sudoers, a new line is added at the end of the file.

Options:

  -h, --help
    Display this usage message and exit.

  -n
    Add 'NOPASSWD:' to the entry so that <user> does not have to enter
    a password to obtain superuser privileges.

  -r
    Remove all lines beginning with <user> from sudoers.

  --
    Stop processing options.  All remaining arguments will be treated
    as usernames.
EOF
}

myname=$(basename "$0") || myname=$0
log() { printf '%s\n' "${myname}: $*"; }
error() { log "ERROR: $*" >&2; }
fatal() { error "$*"; exit 1; }
usage_fatal() { error "$*"; usage >&2; exit 1; }

# parse arguments
unset nopw
unset remove
while [ "$#" -gt 0 ]; do
    case $1 in
        -h|--help) usage; exit 0;;
        -n) nopw="NOPASSWD:";;
        -r) remove=t;;
        --) shift; break;;
        *) break;;
    esac
    shift
done
[ $# -ge 1 ] || usage_fatal "no users given"

visudo=/usr/pkg/sbin/visudo

# Different sudo versions use different variables.
export VISUAL="ed -s"
export EDITOR="ed -s"

# iterate over remaining arguments, which should be usernames
while [ $# -ge 1 ]; do
  u=$1


  if [ x$remove = x ]; then
    log "Adding $u..."
    # the complicated ed script ensures that if the user is already in
    # sudoers, the user's entry isn't moved (order is significant).
    # it also removes any existing entries belonging to the user.  if
    # the user isn't already in sudoers, the user is added at the end.
    ${visudo} <<EOF || fatal "failed to add user ${u}"
\$a
${u}	dummy to make sure there's a match
.
/^${u}[[:space:]]/a
____dummy before____
.
kx
a
${u}	ALL=(ALL) ${nopw} ALL
.
ky
a
____dummy after____
.
kz
1,'xg/^${u}[[:space:]]/d
'z,\$g/^${u}[[:space:]]/d
'xd
'zd
w
EOF
  else
      log "Removing $u..."
      (echo "g/^$u[[:space:]]/d"; echo "w") | $visudo \
          || fatal "failed to remove user ${u}"
  fi
  shift
done
log "done"
