#!/bin/sh
#
-# Copyright (c) 2002, 2003 Michael Telahun Makonnen. All rights reserved.
+# Copyright (c) 2002-2004 Michael Telahun Makonnen. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
-# Email: Mike Makonnen <mtm@identd.net>
+# Email: Mike Makonnen <mtm@FreeBSD.Org>
#
# $FreeBSD$
#
echo "usage: ${THISCMD} [options]"
echo " options may include:"
echo " -C save to the configuration file only"
+ echo " -D do not attempt to create the home directory"
echo " -E disable this account after creation"
echo " -G additional groups to add accounts to"
echo " -L login class of the user"
echo " -N do not read configuration file"
+ echo " -S a nonexistent shell is not an error"
echo " -d home directory"
echo " -f file from which input will be received"
echo " -g default login group"
;;
esac
done
+
+ # /usr/sbin/nologin is a special case
+ [ -x "${NOLOGIN_PATH}" ] && echo -n " ${NOLOGIN}"
}
# fullpath_from_shell shell
-# Given $shell, the basename component of a valid shell, get the
+# Given $shell, which is either the full path to a shell or
+# the basename component of a valid shell, get the
# full path to the shell from the /etc/shells file.
#
fullpath_from_shell() {
_shell=$1
[ -z "$_shell" ] && return 1
+ # /usr/sbin/nologin is a special case; it needs to be handled
+ # before the cat | while loop, since a 'return' from within
+ # a subshell will not terminate the function's execution, and
+ # the path to the nologin shell might be printed out twice.
+ #
+ if [ "$_shell" = "${NOLOGIN}" -o \
+ "$_shell" = "${NOLOGIN_PATH}" ]; then
+ echo ${NOLOGIN_PATH}
+ return 0;
+ fi
+
cat ${ETCSHELLS} |
while read _path _junk ; do
case "$_path" in
\#*|'')
;;
*)
- if [ "`basename $_path`" = "$_shell" ]; then
+ if [ "$_path" = "$_shell" -o \
+ "`basename $_path`" = "$_shell" ]; then
echo $_path
return 0
fi
;;
esac
done
+
return 1
}
+# shell_exists shell
+# If the given shell is listed in ${ETCSHELLS} or it is
+# the nologin shell this function will return 0.
+# Otherwise, it will return 1. If shell is valid but
+# the path is invalid or it is not executable it
+# will emit an informational message saying so.
+#
+shell_exists()
+{
+ _sh="$1"
+ _shellchk="${GREPCMD} '^$_sh$' ${ETCSHELLS} > /dev/null 2>&1"
+
+ if ! eval $_shellchk; then
+ # The nologin shell is not listed in /etc/shells.
+ if [ "$_sh" != "${NOLOGIN_PATH}" ]; then
+ err "Invalid shell ($_sh) for user $username."
+ return 1
+ fi
+ fi
+ ! [ -x "$_sh" ] &&
+ info "The shell ($_sh) does not exist or is not executable."
+
+ return 0
+}
+
# save_config
# Save some variables to a configuration file.
# Note: not all script variables are saved, only those that
[ -n "$ulogingroup" ] && _group='-g "$ulogingroup"'
[ -n "$ugroups" ] && _grouplist='-G "$ugroups"'
[ -n "$ushell" ] && _shell='-s "$ushell"'
- [ -n "$uhome" ] && _home='-m -d "$uhome"'
[ -n "$uclass" ] && _class='-L "$uclass"'
[ -n "$ugecos" ] && _comment='-c "$ugecos"'
[ -n "$udotdir" ] && _dotdir='-k "$udotdir"'
[ -n "$uexpire" ] && _expire='-e "$uexpire"'
[ -n "$upwexpire" ] && _pwexpire='-p "$upwexpire"'
+ if [ -z "$Dflag" -a -n "$uhome" ]; then
+ # The /nonexistent home directory is special. It
+ # means the user has no home directory.
+ if [ "$uhome" = "$NOHOME" ]; then
+ _home='-d "$uhome"'
+ else
+ _home='-m -d "$uhome"'
+ fi
+ elif [ -n "$Dflag" -a -n "$uhome" ]; then
+ _home='-d "$uhome"'
+ fi
case $passwdtype in
no)
_passwdmethod="-w no"
# get_shell
# Get the account's shell. Works in interactive and batch mode. It
-# accepts only the base name of the shell, NOT the full path.
+# accepts either the base name of the shell or the full path.
# If an invalid shell is entered it will simply use the default shell.
#
get_shell() {
ushell="$defaultshell"
# Make sure the current value of the shell is a valid one
- _shellchk="${GREPCMD} '^$ushell$' ${ETCSHELLS} > /dev/null 2>&1"
- eval $_shellchk || {
- err "Invalid shell ($ushell). Using default shell ${defaultshell}."
- ushell="$defaultshell"
- }
+ if [ -z "$Sflag" ]; then
+ if ! shell_exists $ushell ; then
+ info "Using default shell ${defaultshell}."
+ ushell="$defaultshell"
+ fi
+ fi
if [ -z "$fflag" ]; then
echo -n "Shell ($shells) [`basename $ushell`]: "
_input="`echo "$fileline" | cut -f9 -d:`"
fi
if [ -n "$_input" ]; then
- _fullpath=`fullpath_from_shell $_input`
- if [ -n "$_fullpath" ]; then
- ushell="$_fullpath"
+ if [ -n "$Sflag" ]; then
+ ushell="$_input"
else
- err "Invalid shell selection. Using default shell ${defaultshell}."
- ushell="$defaultshell"
+ _fullpath=`fullpath_from_shell $_input`
+ if [ -n "$_fullpath" ]; then
+ ushell="$_fullpath"
+ else
+ err "Invalid shell ($_input) for user $username."
+ info "Using default shell ${defaultshell}."
+ ushell="$defaultshell"
+ fi
fi
fi
}
while read -r fileline ; do
case "$fileline" in
\#*|'')
- return 0
;;
esac
read -r upass
echo''
echo -n "Enter password again: "
- read _passconfirm
+ read -r _passconfirm
echo ''
stty echo
# if user entered a blank password
return 0
}
-#### END SUBROUTINE DEFENITION ####
+#### END SUBROUTINE DEFINITION ####
THISCMD=`/usr/bin/basename $0`
DEFAULTSHELL=/bin/sh
PWCMD="${PWCMD:-/usr/sbin/pw}"
MAILCMD="${MAILCMD:-mail}"
ETCSHELLS="${ETCSHELLS:-/etc/shells}"
+NOHOME="/nonexistent"
+NOLOGIN="nologin"
+NOLOGIN_PATH="/usr/sbin/nologin"
GREPCMD="/usr/bin/grep"
DATECMD="/bin/date"
fflag=
infile=
disableflag=
+Dflag=
+Sflag=
readconfig="yes"
homeprefix="/home"
randompass=
savedpwtype=
defaultclass=
defaultLgroup=
-defaultgoups=
+defaultgroups=
defaultshell="${DEFAULTSHELL}"
# Make sure the user running this program is root. This isn't a security
configflag=yes
shift
;;
+ -D)
+ Dflag=yes
+ shift
+ ;;
-E)
disableflag=yes
shift
defaultshell="`fullpath_from_shell $2`"
shift; shift
;;
+ -S)
+ Sflag=yes
+ shift
+ ;;
-u)
uidstart=$2
shift; shift