xref: /dflybsd-src/usr.sbin/adduser/adduser.sh (revision d749dd6edb2825677c25756e5ea70325ce1fd125)
18d20e303SChris Pressey#!/bin/sh
28d20e303SChris Pressey#
38d20e303SChris Pressey# Copyright (c) 2002-2004 Michael Telahun Makonnen. All rights reserved.
48d20e303SChris Pressey#
58d20e303SChris Pressey# Redistribution and use in source and binary forms, with or without
68d20e303SChris Pressey# modification, are permitted provided that the following conditions
78d20e303SChris Pressey# are met:
88d20e303SChris Pressey# 1. Redistributions of source code must retain the above copyright
98d20e303SChris Pressey#    notice, this list of conditions and the following disclaimer.
108d20e303SChris Pressey# 2. Redistributions in binary form must reproduce the above copyright
118d20e303SChris Pressey#    notice, this list of conditions and the following disclaimer in the
128d20e303SChris Pressey#    documentation and/or other materials provided with the distribution.
138d20e303SChris Pressey#
148d20e303SChris Pressey# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
158d20e303SChris Pressey# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
168d20e303SChris Pressey# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
178d20e303SChris Pressey# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
188d20e303SChris Pressey# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
198d20e303SChris Pressey# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
208d20e303SChris Pressey# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
218d20e303SChris Pressey# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228d20e303SChris Pressey# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
238d20e303SChris Pressey# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248d20e303SChris Pressey#
258d20e303SChris Pressey#       Email: Mike Makonnen <mtm@FreeBSD.Org>
268d20e303SChris Pressey#
279ed5bb8aSSascha Wildner# $FreeBSD: src/usr.sbin/adduser/adduser.sh,v 1.33 2010/01/14 22:04:08 joel Exp $
288d20e303SChris Pressey#
298d20e303SChris Pressey
308d20e303SChris Pressey# err msg
318d20e303SChris Pressey#	Display $msg on stderr, unless we're being quiet.
328d20e303SChris Pressey#
338d20e303SChris Presseyerr() {
348d20e303SChris Pressey	if [ -z "$quietflag" ]; then
358d20e303SChris Pressey		echo 1>&2 ${THISCMD}: ERROR: $*
368d20e303SChris Pressey	fi
378d20e303SChris Pressey}
388d20e303SChris Pressey
398d20e303SChris Pressey# info msg
408d20e303SChris Pressey#	Display $msg on stdout, unless we're being quiet.
418d20e303SChris Pressey#
428d20e303SChris Presseyinfo() {
438d20e303SChris Pressey	if [ -z "$quietflag" ]; then
448d20e303SChris Pressey		echo ${THISCMD}: INFO: $*
458d20e303SChris Pressey	fi
468d20e303SChris Pressey}
478d20e303SChris Pressey
488d20e303SChris Pressey# get_nextuid
498d20e303SChris Pressey#	Output the value of $_uid if it is available for use. If it
508d20e303SChris Pressey#	is not, output the value of the next higher uid that is available.
518d20e303SChris Pressey#	If a uid is not specified, output the first available uid, as indicated
528d20e303SChris Pressey#	by pw(8).
538d20e303SChris Pressey#
548d20e303SChris Presseyget_nextuid () {
558d20e303SChris Pressey	_uid=$1
568d20e303SChris Pressey	_nextuid=
578d20e303SChris Pressey
588d20e303SChris Pressey	if [ -z "$_uid" ]; then
598d20e303SChris Pressey		_nextuid="`${PWCMD} usernext | cut -f1 -d:`"
608d20e303SChris Pressey	else
618d20e303SChris Pressey		while : ; do
628d20e303SChris Pressey			${PWCMD} usershow $_uid > /dev/null 2>&1
638d20e303SChris Pressey			if [ ! "$?" -eq 0 ]; then
648d20e303SChris Pressey				_nextuid=$_uid
658d20e303SChris Pressey				break
668d20e303SChris Pressey			fi
678d20e303SChris Pressey			_uid=$(($_uid + 1))
688d20e303SChris Pressey		done
698d20e303SChris Pressey	fi
708d20e303SChris Pressey	echo $_nextuid
718d20e303SChris Pressey}
728d20e303SChris Pressey
738d20e303SChris Pressey# show_usage
748d20e303SChris Pressey#	Display usage information for this utility.
758d20e303SChris Pressey#
768d20e303SChris Presseyshow_usage() {
778d20e303SChris Pressey	echo "usage: ${THISCMD} [options]"
788d20e303SChris Pressey	echo "  options may include:"
798d20e303SChris Pressey	echo "  -C		save to the configuration file only"
808d20e303SChris Pressey	echo "  -D		do not attempt to create the home directory"
818d20e303SChris Pressey	echo "  -E		disable this account after creation"
828d20e303SChris Pressey	echo "  -G		additional groups to add accounts to"
838d20e303SChris Pressey	echo "  -L		login class of the user"
849ed5bb8aSSascha Wildner	echo "  -M		file permission for home directory"
858d20e303SChris Pressey	echo "  -N		do not read configuration file"
868d20e303SChris Pressey	echo "  -S		a nonexistent shell is not an error"
878d20e303SChris Pressey	echo "  -d		home directory"
888d20e303SChris Pressey	echo "  -f		file from which input will be received"
898d20e303SChris Pressey	echo "  -g		default login group"
908d20e303SChris Pressey	echo "  -h		display this usage message"
918d20e303SChris Pressey	echo "  -k		path to skeleton home directory"
928d20e303SChris Pressey	echo "  -m		user welcome message file"
938d20e303SChris Pressey	echo "  -q		absolute minimal user feedback"
948d20e303SChris Pressey	echo "  -s		shell"
958d20e303SChris Pressey	echo "  -u		uid to start at"
968d20e303SChris Pressey	echo "  -w		password type: no, none, yes or random"
978d20e303SChris Pressey}
988d20e303SChris Pressey
998d20e303SChris Pressey# valid_shells
1008d20e303SChris Pressey#	Outputs a list of valid shells from /etc/shells. Only the
1018d20e303SChris Pressey#	basename of the shell is output.
1028d20e303SChris Pressey#
1038d20e303SChris Presseyvalid_shells() {
1048d20e303SChris Pressey	_prefix=
1058d20e303SChris Pressey	cat ${ETCSHELLS} |
1068d20e303SChris Pressey	while read _path _junk ; do
1078d20e303SChris Pressey		case $_path in
1088d20e303SChris Pressey		\#*|'')
1098d20e303SChris Pressey			;;
1108d20e303SChris Pressey		*)
1118d20e303SChris Pressey			echo -n "${_prefix}`basename $_path`"
1128d20e303SChris Pressey			_prefix=' '
1138d20e303SChris Pressey			;;
1148d20e303SChris Pressey		esac
1158d20e303SChris Pressey	done
1168d20e303SChris Pressey
1174f4826d5SMatthias Schmidt	# /sbin/nologin is a special case
1188d20e303SChris Pressey	[ -x "${NOLOGIN_PATH}" ] && echo -n " ${NOLOGIN}"
1198d20e303SChris Pressey}
1208d20e303SChris Pressey
1218d20e303SChris Pressey# fullpath_from_shell shell
1228d20e303SChris Pressey#	Given $shell, which is either the full path to a shell or
1238d20e303SChris Pressey#	the basename component of a valid shell, get the
1248d20e303SChris Pressey#	full path to the shell from the /etc/shells file.
1258d20e303SChris Pressey#
1268d20e303SChris Presseyfullpath_from_shell() {
1278d20e303SChris Pressey	_shell=$1
1288d20e303SChris Pressey	[ -z "$_shell" ] && return 1
1298d20e303SChris Pressey
1304f4826d5SMatthias Schmidt	# /sbin/nologin is a special case; it needs to be handled
1314f4826d5SMatthias Schmidt	# before the cat | while loop, since a 'return' from within
1324f4826d5SMatthias Schmidt	# a subshell will not terminate the function's execution, and
1334f4826d5SMatthias Schmidt	# the path to the nologin shell might be printed out twice.
1344f4826d5SMatthias Schmidt	#
1354f4826d5SMatthias Schmidt	if [ "$_shell" = "${NOLOGIN}" -o \
1364f4826d5SMatthias Schmidt	    "$_shell" = "${NOLOGIN_PATH}" ]; then
1374f4826d5SMatthias Schmidt		echo ${NOLOGIN_PATH}
1384f4826d5SMatthias Schmidt		return 0;
1394f4826d5SMatthias Schmidt	fi
1404f4826d5SMatthias Schmidt
1418d20e303SChris Pressey	cat ${ETCSHELLS} |
1428d20e303SChris Pressey	while read _path _junk ; do
1438d20e303SChris Pressey		case "$_path" in
1448d20e303SChris Pressey		\#*|'')
1458d20e303SChris Pressey			;;
1468d20e303SChris Pressey		*)
1478d20e303SChris Pressey			if [ "$_path" = "$_shell" -o \
1488d20e303SChris Pressey			    "`basename $_path`" = "$_shell" ]; then
1498d20e303SChris Pressey				echo $_path
1508d20e303SChris Pressey				return 0
1518d20e303SChris Pressey			fi
1528d20e303SChris Pressey			;;
1538d20e303SChris Pressey		esac
1548d20e303SChris Pressey	done
1558d20e303SChris Pressey
1568d20e303SChris Pressey	return 1
1578d20e303SChris Pressey}
1588d20e303SChris Pressey
1598d20e303SChris Pressey# shell_exists shell
1608d20e303SChris Pressey#	If the given shell is listed in ${ETCSHELLS} or it is
1618d20e303SChris Pressey#	the nologin shell this function will return 0.
1628d20e303SChris Pressey#	Otherwise, it will return 1. If shell is valid but
1638d20e303SChris Pressey#	the path is invalid or it is not executable it
1648d20e303SChris Pressey#	will emit an informational message saying so.
1658d20e303SChris Pressey#
1669ed5bb8aSSascha Wildnershell_exists() {
1678d20e303SChris Pressey	_sh="$1"
1688d20e303SChris Pressey	_shellchk="${GREPCMD} '^$_sh$' ${ETCSHELLS} > /dev/null 2>&1"
1698d20e303SChris Pressey
1708d20e303SChris Pressey	if ! eval $_shellchk; then
1718d20e303SChris Pressey		# The nologin shell is not listed in /etc/shells.
1728d20e303SChris Pressey		if [ "$_sh" != "${NOLOGIN_PATH}" ]; then
1738d20e303SChris Pressey			err "Invalid shell ($_sh) for user $username."
1748d20e303SChris Pressey			return 1
1758d20e303SChris Pressey		fi
1768d20e303SChris Pressey	fi
1778d20e303SChris Pressey	! [ -x "$_sh" ] &&
1788d20e303SChris Pressey	    info "The shell ($_sh) does not exist or is not executable."
1798d20e303SChris Pressey
1808d20e303SChris Pressey	return 0
1818d20e303SChris Pressey}
1828d20e303SChris Pressey
1838d20e303SChris Pressey# save_config
1848d20e303SChris Pressey#	Save some variables to a configuration file.
1858d20e303SChris Pressey#	Note: not all script variables are saved, only those that
1868d20e303SChris Pressey#	      it makes sense to save.
1878d20e303SChris Pressey#
1888d20e303SChris Presseysave_config() {
1898d20e303SChris Pressey	echo "# Configuration file for adduser(8)."     >  ${ADDUSERCONF}
1908d20e303SChris Pressey	echo "# NOTE: only *some* variables are saved." >> ${ADDUSERCONF}
1918d20e303SChris Pressey	echo "# Last Modified on `${DATECMD}`."		>> ${ADDUSERCONF}
1928d20e303SChris Pressey	echo ''				>> ${ADDUSERCONF}
1939ed5bb8aSSascha Wildner	echo "defaultHomePerm=$uhomeperm" >> ${ADDUSERCONF}
1948d20e303SChris Pressey	echo "defaultLgroup=$ulogingroup" >> ${ADDUSERCONF}
1958d20e303SChris Pressey	echo "defaultclass=$uclass"	>> ${ADDUSERCONF}
1968d20e303SChris Pressey	echo "defaultgroups=$ugroups"	>> ${ADDUSERCONF}
1978d20e303SChris Pressey	echo "passwdtype=$passwdtype" 	>> ${ADDUSERCONF}
1988d20e303SChris Pressey	echo "homeprefix=$homeprefix" 	>> ${ADDUSERCONF}
1998d20e303SChris Pressey	echo "defaultshell=$ushell"	>> ${ADDUSERCONF}
2008d20e303SChris Pressey	echo "udotdir=$udotdir"		>> ${ADDUSERCONF}
2018d20e303SChris Pressey	echo "msgfile=$msgfile"		>> ${ADDUSERCONF}
2028d20e303SChris Pressey	echo "disableflag=$disableflag" >> ${ADDUSERCONF}
2034f4826d5SMatthias Schmidt	echo "uidstart=$uidstart"       >> ${ADDUSERCONF}
2048d20e303SChris Pressey}
2058d20e303SChris Pressey
2068d20e303SChris Pressey# add_user
2078d20e303SChris Pressey#	Add a user to the user database. If the user chose to send a welcome
2088d20e303SChris Pressey#	message or lock the account, do so.
2098d20e303SChris Pressey#
2108d20e303SChris Presseyadd_user() {
2118d20e303SChris Pressey
2128d20e303SChris Pressey	# Is this a configuration run? If so, don't modify user database.
2138d20e303SChris Pressey	#
2148d20e303SChris Pressey	if [ -n "$configflag" ]; then
2158d20e303SChris Pressey		save_config
2168d20e303SChris Pressey		return
2178d20e303SChris Pressey	fi
2188d20e303SChris Pressey
2198d20e303SChris Pressey	_uid=
2208d20e303SChris Pressey	_name=
2218d20e303SChris Pressey	_comment=
2228d20e303SChris Pressey	_gecos=
2238d20e303SChris Pressey	_home=
2248d20e303SChris Pressey	_group=
2258d20e303SChris Pressey	_grouplist=
2268d20e303SChris Pressey	_shell=
2278d20e303SChris Pressey	_class=
2288d20e303SChris Pressey	_dotdir=
2298d20e303SChris Pressey	_expire=
2308d20e303SChris Pressey	_pwexpire=
2318d20e303SChris Pressey	_passwd=
2328d20e303SChris Pressey	_upasswd=
2338d20e303SChris Pressey	_passwdmethod=
2348d20e303SChris Pressey
2358d20e303SChris Pressey	_name="-n '$username'"
2368d20e303SChris Pressey	[ -n "$uuid" ] && _uid='-u "$uuid"'
2378d20e303SChris Pressey	[ -n "$ulogingroup" ] && _group='-g "$ulogingroup"'
2388d20e303SChris Pressey	[ -n "$ugroups" ] && _grouplist='-G "$ugroups"'
2398d20e303SChris Pressey	[ -n "$ushell" ] && _shell='-s "$ushell"'
2408d20e303SChris Pressey	[ -n "$uclass" ] && _class='-L "$uclass"'
2418d20e303SChris Pressey	[ -n "$ugecos" ] && _comment='-c "$ugecos"'
2428d20e303SChris Pressey	[ -n "$udotdir" ] && _dotdir='-k "$udotdir"'
2438d20e303SChris Pressey	[ -n "$uexpire" ] && _expire='-e "$uexpire"'
2448d20e303SChris Pressey	[ -n "$upwexpire" ] && _pwexpire='-p "$upwexpire"'
2458d20e303SChris Pressey	if [ -z "$Dflag" -a -n "$uhome" ]; then
2468d20e303SChris Pressey		# The /nonexistent home directory is special. It
2478d20e303SChris Pressey		# means the user has no home directory.
2488d20e303SChris Pressey		if [ "$uhome" = "$NOHOME" ]; then
2498d20e303SChris Pressey			_home='-d "$uhome"'
2508d20e303SChris Pressey		else
2519ed5bb8aSSascha Wildner			# Use home directory permissions if specified
2529ed5bb8aSSascha Wildner			if [ -n "$uhomeperm" ]; then
2539ed5bb8aSSascha Wildner				_home='-m -d "$uhome" -M "$uhomeperm"'
2549ed5bb8aSSascha Wildner			else
2558d20e303SChris Pressey				_home='-m -d "$uhome"'
2568d20e303SChris Pressey			fi
2579ed5bb8aSSascha Wildner		fi
2588d20e303SChris Pressey	elif [ -n "$Dflag" -a -n "$uhome" ]; then
2598d20e303SChris Pressey		_home='-d "$uhome"'
2608d20e303SChris Pressey	fi
2618d20e303SChris Pressey	case $passwdtype in
2628d20e303SChris Pressey	no)
2638d20e303SChris Pressey		_passwdmethod="-w no"
2648d20e303SChris Pressey		_passwd="-h -"
2658d20e303SChris Pressey		;;
2668d20e303SChris Pressey	yes)
2678d20e303SChris Pressey		# Note on processing the password: The outer double quotes
2688d20e303SChris Pressey		# make literal everything except ` and \ and $.
2698d20e303SChris Pressey		# The outer single quotes make literal ` and $.
2708d20e303SChris Pressey		# We can ensure the \ isn't treated specially by specifying
2718d20e303SChris Pressey		# the -r switch to the read command used to obtain the input.
2728d20e303SChris Pressey		#
2738d20e303SChris Pressey		_passwdmethod="-w yes"
2748d20e303SChris Pressey		_passwd="-h 0"
2758d20e303SChris Pressey		_upasswd='echo "$upass" |'
2768d20e303SChris Pressey		;;
2778d20e303SChris Pressey	none)
2788d20e303SChris Pressey		_passwdmethod="-w none"
2798d20e303SChris Pressey		;;
2808d20e303SChris Pressey	random)
2818d20e303SChris Pressey		_passwdmethod="-w random"
2828d20e303SChris Pressey		;;
2838d20e303SChris Pressey	esac
2848d20e303SChris Pressey
2858d20e303SChris Pressey	_pwcmd="$_upasswd ${PWCMD} useradd $_uid $_name $_group $_grouplist $_comment"
2868d20e303SChris Pressey	_pwcmd="$_pwcmd $_shell $_class $_home $_dotdir $_passwdmethod $_passwd"
2878d20e303SChris Pressey	_pwcmd="$_pwcmd $_expire $_pwexpire"
2888d20e303SChris Pressey
2898d20e303SChris Pressey	if ! _output=`eval $_pwcmd` ; then
2908d20e303SChris Pressey		err "There was an error adding user ($username)."
2918d20e303SChris Pressey		return 1
2928d20e303SChris Pressey	else
2938d20e303SChris Pressey		info "Successfully added ($username) to the user database."
2948d20e303SChris Pressey		if [ "random" = "$passwdtype" ]; then
2958d20e303SChris Pressey			randompass="$_output"
2968d20e303SChris Pressey			info "Password for ($username) is: $randompass"
2978d20e303SChris Pressey		fi
2988d20e303SChris Pressey	fi
2998d20e303SChris Pressey
3008d20e303SChris Pressey	if [ -n "$disableflag" ]; then
3018d20e303SChris Pressey		if ${PWCMD} lock $username ; then
3028d20e303SChris Pressey			info "Account ($username) is locked."
3038d20e303SChris Pressey		else
3048d20e303SChris Pressey			info "Account ($username) could NOT be locked."
3058d20e303SChris Pressey		fi
3068d20e303SChris Pressey	fi
3078d20e303SChris Pressey
3088d20e303SChris Pressey	_line=
3098d20e303SChris Pressey	_owner=
3108d20e303SChris Pressey	_perms=
3118d20e303SChris Pressey	if [ -n "$msgflag" ]; then
3128d20e303SChris Pressey		[ -r "$msgfile" ] && {
3138d20e303SChris Pressey			# We're evaluating the contents of an external file.
3148d20e303SChris Pressey			# Let's not open ourselves up for attack. _perms will
3158d20e303SChris Pressey			# be empty if it's writeable only by the owner. _owner
3168d20e303SChris Pressey			# will *NOT* be empty if the file is owned by root.
3178d20e303SChris Pressey			#
3188d20e303SChris Pressey			_dir="`dirname $msgfile`"
3198d20e303SChris Pressey			_file="`basename $msgfile`"
3208d20e303SChris Pressey			_perms=`/usr/bin/find $_dir -name $_file -perm +07022 -prune`
3218d20e303SChris Pressey			_owner=`/usr/bin/find $_dir -name $_file -user 0 -prune`
3228d20e303SChris Pressey			if [ -z "$_owner" -o -n "$_perms" ]; then
3238d20e303SChris Pressey				err "The message file ($msgfile) may be writeable only by root."
3248d20e303SChris Pressey				return 1
3258d20e303SChris Pressey			fi
3268d20e303SChris Pressey			cat "$msgfile" |
3278d20e303SChris Pressey			while read _line ; do
3288d20e303SChris Pressey				eval echo "$_line"
3298d20e303SChris Pressey			done | ${MAILCMD} -s"Welcome" ${username}
3308d20e303SChris Pressey			info "Sent welcome message to ($username)."
3318d20e303SChris Pressey		}
3328d20e303SChris Pressey	fi
3338d20e303SChris Pressey}
3348d20e303SChris Pressey
3358d20e303SChris Pressey# get_user
3368d20e303SChris Pressey#	Reads username of the account from standard input or from a global
3378d20e303SChris Pressey#	variable containing an account line from a file. The username is
3388d20e303SChris Pressey#	required. If this is an interactive session it will prompt in
3398d20e303SChris Pressey#	a loop until a username is entered. If it is batch processing from
3408d20e303SChris Pressey#	a file it will output an error message and return to the caller.
3418d20e303SChris Pressey#
3428d20e303SChris Presseyget_user() {
3438d20e303SChris Pressey	_input=
3448d20e303SChris Pressey
3458d20e303SChris Pressey	# No need to take down user names if this is a configuration saving run.
3468d20e303SChris Pressey	[ -n "$configflag" ] && return
3478d20e303SChris Pressey
3488d20e303SChris Pressey	while : ; do
3498d20e303SChris Pressey		if [ -z "$fflag" ]; then
3508d20e303SChris Pressey			echo -n "Username: "
3518d20e303SChris Pressey			read _input
3528d20e303SChris Pressey		else
3538d20e303SChris Pressey			_input="`echo "$fileline" | cut -f1 -d:`"
3548d20e303SChris Pressey		fi
3558d20e303SChris Pressey
3564f4826d5SMatthias Schmidt		# There *must* be a username, and it must not exist. If
3574f4826d5SMatthias Schmidt		# this is an interactive session give the user an
3584f4826d5SMatthias Schmidt		# opportunity to retry.
3598d20e303SChris Pressey		#
3608d20e303SChris Pressey		if [ -z "$_input" ]; then
3618d20e303SChris Pressey			err "You must enter a username!"
3628d20e303SChris Pressey			[ -z "$fflag" ] && continue
3638d20e303SChris Pressey		fi
3644f4826d5SMatthias Schmidt		${PWCMD} usershow $_input > /dev/null 2>&1
3654f4826d5SMatthias Schmidt		if [ "$?" -eq 0 ]; then
3664f4826d5SMatthias Schmidt			err "User exists!"
3674f4826d5SMatthias Schmidt			[ -z "$fflag" ] && continue
3684f4826d5SMatthias Schmidt		fi
3698d20e303SChris Pressey		break
3708d20e303SChris Pressey	done
3718d20e303SChris Pressey	username="$_input"
3728d20e303SChris Pressey}
3738d20e303SChris Pressey
3748d20e303SChris Pressey# get_gecos
3758d20e303SChris Pressey#	Reads extra information about the user. Can be used both in interactive
3768d20e303SChris Pressey#	and batch (from file) mode.
3778d20e303SChris Pressey#
3788d20e303SChris Presseyget_gecos() {
3798d20e303SChris Pressey	_input=
3808d20e303SChris Pressey
3818d20e303SChris Pressey	# No need to take down additional user information for a configuration run.
3828d20e303SChris Pressey	[ -n "$configflag" ] && return
3838d20e303SChris Pressey
3848d20e303SChris Pressey	if [ -z "$fflag" ]; then
3858d20e303SChris Pressey		echo -n "Full name: "
3868d20e303SChris Pressey		read _input
3878d20e303SChris Pressey	else
3888d20e303SChris Pressey		_input="`echo "$fileline" | cut -f7 -d:`"
3898d20e303SChris Pressey	fi
3908d20e303SChris Pressey	ugecos="$_input"
3918d20e303SChris Pressey}
3928d20e303SChris Pressey
3938d20e303SChris Pressey# get_shell
3948d20e303SChris Pressey#	Get the account's shell. Works in interactive and batch mode. It
3958d20e303SChris Pressey#	accepts either the base name of the shell or the full path.
3968d20e303SChris Pressey#	If an invalid shell is entered it will simply use the default shell.
3978d20e303SChris Pressey#
3988d20e303SChris Presseyget_shell() {
3998d20e303SChris Pressey	_input=
4008d20e303SChris Pressey	_fullpath=
4018d20e303SChris Pressey	ushell="$defaultshell"
4028d20e303SChris Pressey
4038d20e303SChris Pressey	# Make sure the current value of the shell is a valid one
4048d20e303SChris Pressey	if [ -z "$Sflag" ]; then
4058d20e303SChris Pressey		if ! shell_exists $ushell ; then
4068d20e303SChris Pressey			info "Using default shell ${defaultshell}."
4078d20e303SChris Pressey			ushell="$defaultshell"
4088d20e303SChris Pressey		fi
4098d20e303SChris Pressey	fi
4108d20e303SChris Pressey
4118d20e303SChris Pressey	if [ -z "$fflag" ]; then
4128d20e303SChris Pressey		echo -n "Shell ($shells) [`basename $ushell`]: "
4138d20e303SChris Pressey		read _input
4148d20e303SChris Pressey	else
4158d20e303SChris Pressey		_input="`echo "$fileline" | cut -f9 -d:`"
4168d20e303SChris Pressey	fi
4178d20e303SChris Pressey	if [ -n "$_input" ]; then
4188d20e303SChris Pressey		if [ -n "$Sflag" ]; then
4198d20e303SChris Pressey			ushell="$_input"
4208d20e303SChris Pressey		else
4218d20e303SChris Pressey			_fullpath=`fullpath_from_shell $_input`
4228d20e303SChris Pressey			if [ -n "$_fullpath" ]; then
4238d20e303SChris Pressey				ushell="$_fullpath"
4248d20e303SChris Pressey			else
4258d20e303SChris Pressey				err "Invalid shell ($_input) for user $username."
4268d20e303SChris Pressey				info "Using default shell ${defaultshell}."
4278d20e303SChris Pressey				ushell="$defaultshell"
4288d20e303SChris Pressey			fi
4298d20e303SChris Pressey		fi
4308d20e303SChris Pressey	fi
4318d20e303SChris Pressey}
4328d20e303SChris Pressey
4338d20e303SChris Pressey# get_homedir
4348d20e303SChris Pressey#	Reads the account's home directory. Used both with interactive input
4358d20e303SChris Pressey#	and batch input.
4368d20e303SChris Pressey#
4378d20e303SChris Presseyget_homedir() {
4388d20e303SChris Pressey	_input=
4398d20e303SChris Pressey	if [ -z "$fflag" ]; then
4408d20e303SChris Pressey		echo -n "Home directory [${homeprefix}/${username}]: "
4418d20e303SChris Pressey		read _input
4428d20e303SChris Pressey	else
4438d20e303SChris Pressey		_input="`echo "$fileline" | cut -f8 -d:`"
4448d20e303SChris Pressey	fi
4458d20e303SChris Pressey
4468d20e303SChris Pressey	if [ -n "$_input" ]; then
4478d20e303SChris Pressey		uhome="$_input"
4488d20e303SChris Pressey		# if this is a configuration run, then user input is the home
4498d20e303SChris Pressey		# directory prefix. Otherwise it is understood to
4508d20e303SChris Pressey		# be $prefix/$user
4518d20e303SChris Pressey		#
4528d20e303SChris Pressey		[ -z "$configflag" ] && homeprefix="`dirname $uhome`" || homeprefix="$uhome"
4538d20e303SChris Pressey	else
4548d20e303SChris Pressey		uhome="${homeprefix}/${username}"
4558d20e303SChris Pressey	fi
4568d20e303SChris Pressey}
4578d20e303SChris Pressey
4589ed5bb8aSSascha Wildner# get_homeperm
4599ed5bb8aSSascha Wildner#	Reads the account's home directory permissions.
4609ed5bb8aSSascha Wildner#
4619ed5bb8aSSascha Wildnerget_homeperm() {
4629ed5bb8aSSascha Wildner	uhomeperm=$defaultHomePerm
4639ed5bb8aSSascha Wildner	_input=
4649ed5bb8aSSascha Wildner	_prompt=
4659ed5bb8aSSascha Wildner
4669ed5bb8aSSascha Wildner	if [ -n "$uhomeperm" ]; then
4679ed5bb8aSSascha Wildner		_prompt="Home directory permissions [${uhomeperm}]: "
4689ed5bb8aSSascha Wildner	else
4699ed5bb8aSSascha Wildner		_prompt="Home directory permissions (Leave empty for default): "
4709ed5bb8aSSascha Wildner	fi
4719ed5bb8aSSascha Wildner	if [ -z "$fflag" ]; then
4729ed5bb8aSSascha Wildner		echo -n "$_prompt"
4739ed5bb8aSSascha Wildner		read _input
4749ed5bb8aSSascha Wildner	fi
4759ed5bb8aSSascha Wildner
4769ed5bb8aSSascha Wildner	if [ -n "$_input" ]; then
4779ed5bb8aSSascha Wildner		uhomeperm="$_input"
4789ed5bb8aSSascha Wildner	fi
4799ed5bb8aSSascha Wildner}
4809ed5bb8aSSascha Wildner
4818d20e303SChris Pressey# get_uid
4828d20e303SChris Pressey#	Reads a numeric userid in an interactive or batch session. Automatically
4838d20e303SChris Pressey#	allocates one if it is not specified.
4848d20e303SChris Pressey#
4858d20e303SChris Presseyget_uid() {
4868d20e303SChris Pressey	uuid=${uidstart}
4878d20e303SChris Pressey	_input=
4888d20e303SChris Pressey	_prompt=
4898d20e303SChris Pressey
4908d20e303SChris Pressey	if [ -n "$uuid" ]; then
491*d749dd6eSAaron LI		uuid=`get_nextuid $uuid`
4928d20e303SChris Pressey		_prompt="Uid [$uuid]: "
4938d20e303SChris Pressey	else
4948d20e303SChris Pressey		_prompt="Uid (Leave empty for default): "
4958d20e303SChris Pressey	fi
4968d20e303SChris Pressey	if [ -z "$fflag" ]; then
4978d20e303SChris Pressey		echo -n "$_prompt"
4988d20e303SChris Pressey		read _input
4998d20e303SChris Pressey	else
5008d20e303SChris Pressey		_input="`echo "$fileline" | cut -f2 -d:`"
5018d20e303SChris Pressey	fi
5028d20e303SChris Pressey
5038d20e303SChris Pressey	[ -n "$_input" ] && uuid=$_input
5048d20e303SChris Pressey	uuid=`get_nextuid $uuid`
5058d20e303SChris Pressey	uidstart=$uuid
5068d20e303SChris Pressey}
5078d20e303SChris Pressey
5088d20e303SChris Pressey# get_class
5098d20e303SChris Pressey#	Reads login class of account. Can be used in interactive or batch mode.
5108d20e303SChris Pressey#
5118d20e303SChris Presseyget_class() {
5128d20e303SChris Pressey	uclass="$defaultclass"
5138d20e303SChris Pressey	_input=
5148d20e303SChris Pressey	_class=${uclass:-"default"}
5158d20e303SChris Pressey
5168d20e303SChris Pressey	if [ -z "$fflag" ]; then
5178d20e303SChris Pressey		echo -n "Login class [$_class]: "
5188d20e303SChris Pressey		read _input
5198d20e303SChris Pressey	else
5208d20e303SChris Pressey		_input="`echo "$fileline" | cut -f4 -d:`"
5218d20e303SChris Pressey	fi
5228d20e303SChris Pressey
5238d20e303SChris Pressey	[ -n "$_input" ] && uclass="$_input"
5248d20e303SChris Pressey}
5258d20e303SChris Pressey
5268d20e303SChris Pressey# get_logingroup
5278d20e303SChris Pressey#	Reads user's login group. Can be used in both interactive and batch
5288d20e303SChris Pressey#	modes. The specified value can be a group name or its numeric id.
5298d20e303SChris Pressey#	This routine leaves the field blank if nothing is provided and
5308d20e303SChris Pressey#	a default login group has not been set. The pw(8) command
5318d20e303SChris Pressey#	will then provide a login group with the same name as the username.
5328d20e303SChris Pressey#
5338d20e303SChris Presseyget_logingroup() {
5348d20e303SChris Pressey	ulogingroup="$defaultLgroup"
5358d20e303SChris Pressey	_input=
5368d20e303SChris Pressey
5378d20e303SChris Pressey	if [ -z "$fflag" ]; then
5388d20e303SChris Pressey		echo -n "Login group [${ulogingroup:-$username}]: "
5398d20e303SChris Pressey		read _input
5408d20e303SChris Pressey	else
5418d20e303SChris Pressey		_input="`echo "$fileline" | cut -f3 -d:`"
5428d20e303SChris Pressey	fi
5438d20e303SChris Pressey
5448d20e303SChris Pressey	# Pw(8) will use the username as login group if it's left empty
5458d20e303SChris Pressey	[ -n "$_input" ] && ulogingroup="$_input"
5468d20e303SChris Pressey}
5478d20e303SChris Pressey
5488d20e303SChris Pressey# get_groups
5498d20e303SChris Pressey#	Read additional groups for the user. It can be used in both interactive
5508d20e303SChris Pressey#	and batch modes.
5518d20e303SChris Pressey#
5528d20e303SChris Presseyget_groups() {
5538d20e303SChris Pressey	ugroups="$defaultgroups"
5548d20e303SChris Pressey	_input=
5558d20e303SChris Pressey	_group=${ulogingroup:-"${username}"}
5568d20e303SChris Pressey
5578d20e303SChris Pressey	if [ -z "$configflag" ]; then
5588d20e303SChris Pressey		[ -z "$fflag" ] && echo -n "Login group is $_group. Invite $username"
5598d20e303SChris Pressey		[ -z "$fflag" ] && echo -n " into other groups? [$ugroups]: "
5608d20e303SChris Pressey	else
5618d20e303SChris Pressey		[ -z "$fflag" ] && echo -n "Enter additional groups [$ugroups]: "
5628d20e303SChris Pressey	fi
5638d20e303SChris Pressey	read _input
5648d20e303SChris Pressey
5658d20e303SChris Pressey	[ -n "$_input" ] && ugroups="$_input"
5668d20e303SChris Pressey}
5678d20e303SChris Pressey
5688d20e303SChris Pressey# get_expire_dates
5698d20e303SChris Pressey#	Read expiry information for the account and also for the password. This
5708d20e303SChris Pressey#	routine is used only from batch processing mode.
5718d20e303SChris Pressey#
5728d20e303SChris Presseyget_expire_dates() {
5738d20e303SChris Pressey	upwexpire="`echo "$fileline" | cut -f5 -d:`"
5748d20e303SChris Pressey	uexpire="`echo "$fileline" | cut -f6 -d:`"
5758d20e303SChris Pressey}
5768d20e303SChris Pressey
5778d20e303SChris Pressey# get_password
5788d20e303SChris Pressey#	Read the password in batch processing mode. The password field matters
5798d20e303SChris Pressey#	only when the password type is "yes" or "random". If the field is empty and the
5808d20e303SChris Pressey#	password type is "yes", then it assumes the account has an empty passsword
5818d20e303SChris Pressey#	and changes the password type accordingly. If the password type is "random"
5828d20e303SChris Pressey#	and the password field is NOT empty, then it assumes the account will NOT
5838d20e303SChris Pressey#	have a random password and set passwdtype to "yes."
5848d20e303SChris Pressey#
5858d20e303SChris Presseyget_password() {
5868d20e303SChris Pressey	# We may temporarily change a password type. Make sure it's changed
5878d20e303SChris Pressey	# back to whatever it was before we process the next account.
5888d20e303SChris Pressey	#
5898d20e303SChris Pressey	[ -n "$savedpwtype" ] && {
5908d20e303SChris Pressey		passwdtype=$savedpwtype
5918d20e303SChris Pressey		savedpwtype=
5928d20e303SChris Pressey	}
5938d20e303SChris Pressey
5948d20e303SChris Pressey	# There may be a ':' in the password
5958d20e303SChris Pressey	upass=${fileline#*:*:*:*:*:*:*:*:*:}
5968d20e303SChris Pressey
5978d20e303SChris Pressey	if [ -z "$upass" ]; then
5988d20e303SChris Pressey		case $passwdtype in
5998d20e303SChris Pressey		yes)
6008d20e303SChris Pressey			# if it's empty, assume an empty password
6018d20e303SChris Pressey			passwdtype=none
6028d20e303SChris Pressey			savedpwtype=yes
6038d20e303SChris Pressey			;;
6048d20e303SChris Pressey		esac
6058d20e303SChris Pressey	else
6068d20e303SChris Pressey		case $passwdtype in
6078d20e303SChris Pressey		random)
6088d20e303SChris Pressey			passwdtype=yes
6098d20e303SChris Pressey			savedpwtype=random
6108d20e303SChris Pressey			;;
6118d20e303SChris Pressey		esac
6128d20e303SChris Pressey	fi
6138d20e303SChris Pressey}
6148d20e303SChris Pressey
6158d20e303SChris Pressey# input_from_file
6168d20e303SChris Pressey#	Reads a line of account information from standard input and
6178d20e303SChris Pressey#	adds it to the user database.
6188d20e303SChris Pressey#
6198d20e303SChris Presseyinput_from_file() {
6208d20e303SChris Pressey	_field=
6218d20e303SChris Pressey
6228d20e303SChris Pressey	while read -r fileline ; do
6238d20e303SChris Pressey		case "$fileline" in
6248d20e303SChris Pressey		\#*|'')
6258d20e303SChris Pressey			;;
6264f4826d5SMatthias Schmidt		*)
6278d20e303SChris Pressey			get_user || continue
6288d20e303SChris Pressey			get_gecos
6298d20e303SChris Pressey			get_uid
6308d20e303SChris Pressey			get_logingroup
6318d20e303SChris Pressey			get_class
6328d20e303SChris Pressey			get_shell
6338d20e303SChris Pressey			get_homedir
6349ed5bb8aSSascha Wildner			get_homeperm
6358d20e303SChris Pressey			get_password
6368d20e303SChris Pressey			get_expire_dates
6374f4826d5SMatthias Schmidt			ugroups="$defaultgroups"
6388d20e303SChris Pressey
6398d20e303SChris Pressey			add_user
6404f4826d5SMatthias Schmidt			;;
6414f4826d5SMatthias Schmidt		esac
6428d20e303SChris Pressey	done
6438d20e303SChris Pressey}
6448d20e303SChris Pressey
6458d20e303SChris Pressey# input_interactive
6468d20e303SChris Pressey#	Prompts for user information interactively, and commits to
6478d20e303SChris Pressey#	the user database.
6488d20e303SChris Pressey#
6498d20e303SChris Presseyinput_interactive() {
6508d20e303SChris Pressey	_disable=
6518d20e303SChris Pressey	_pass=
6528d20e303SChris Pressey	_passconfirm=
6538d20e303SChris Pressey	_random="no"
6548d20e303SChris Pressey	_emptypass="no"
6558d20e303SChris Pressey	_usepass="yes"
6568d20e303SChris Pressey	_logingroup_ok="no"
6578d20e303SChris Pressey	_groups_ok="no"
6588d20e303SChris Pressey	case $passwdtype in
6598d20e303SChris Pressey	none)
6608d20e303SChris Pressey		_emptypass="yes"
6618d20e303SChris Pressey		_usepass="yes"
6628d20e303SChris Pressey		;;
6638d20e303SChris Pressey	no)
6648d20e303SChris Pressey		_usepass="no"
6658d20e303SChris Pressey		;;
6668d20e303SChris Pressey	random)
6678d20e303SChris Pressey		_random="yes"
6688d20e303SChris Pressey		;;
6698d20e303SChris Pressey	esac
6708d20e303SChris Pressey
6718d20e303SChris Pressey	get_user
6728d20e303SChris Pressey	get_gecos
6738d20e303SChris Pressey	get_uid
6748d20e303SChris Pressey
6758d20e303SChris Pressey	# The case where group = user is handled elsewhere, so
6768d20e303SChris Pressey	# validate any other groups the user is invited to.
6778d20e303SChris Pressey	until [ "$_logingroup_ok" = yes ]; do
6788d20e303SChris Pressey		get_logingroup
6798d20e303SChris Pressey		_logingroup_ok=yes
6808d20e303SChris Pressey		if [ -n "$ulogingroup" -a "$username" != "$ulogingroup" ]; then
6818d20e303SChris Pressey			if ! ${PWCMD} show group $ulogingroup > /dev/null 2>&1; then
6828d20e303SChris Pressey				echo "Group $ulogingroup does not exist!"
6838d20e303SChris Pressey				_logingroup_ok=no
6848d20e303SChris Pressey			fi
6858d20e303SChris Pressey		fi
6868d20e303SChris Pressey	done
6878d20e303SChris Pressey	until [ "$_groups_ok" = yes ]; do
6888d20e303SChris Pressey		get_groups
6898d20e303SChris Pressey		_groups_ok=yes
6908d20e303SChris Pressey		for i in $ugroups; do
6918d20e303SChris Pressey			if [ "$username" != "$i" ]; then
6928d20e303SChris Pressey				if ! ${PWCMD} show group $i > /dev/null 2>&1; then
6938d20e303SChris Pressey					echo "Group $i does not exist!"
6948d20e303SChris Pressey					_groups_ok=no
6958d20e303SChris Pressey				fi
6968d20e303SChris Pressey			fi
6978d20e303SChris Pressey		done
6988d20e303SChris Pressey	done
6998d20e303SChris Pressey
7008d20e303SChris Pressey	get_class
7018d20e303SChris Pressey	get_shell
7028d20e303SChris Pressey	get_homedir
7039ed5bb8aSSascha Wildner	get_homeperm
7048d20e303SChris Pressey
7058d20e303SChris Pressey	while : ; do
7068d20e303SChris Pressey		echo -n "Use password-based authentication? [$_usepass]: "
7078d20e303SChris Pressey		read _input
7088d20e303SChris Pressey		[ -z "$_input" ] && _input=$_usepass
7098d20e303SChris Pressey		case $_input in
7108d20e303SChris Pressey		[Nn][Oo]|[Nn])
7118d20e303SChris Pressey			passwdtype="no"
7128d20e303SChris Pressey			;;
7138d20e303SChris Pressey		[Yy][Ee][Ss]|[Yy][Ee]|[Yy])
7148d20e303SChris Pressey			while : ; do
7158d20e303SChris Pressey				echo -n "Use an empty password? (yes/no) [$_emptypass]: "
7168d20e303SChris Pressey				read _input
7178d20e303SChris Pressey				[ -n "$_input" ] && _emptypass=$_input
7188d20e303SChris Pressey				case $_emptypass in
7198d20e303SChris Pressey				[Nn][Oo]|[Nn])
7208d20e303SChris Pressey					echo -n "Use a random password? (yes/no) [$_random]: "
7218d20e303SChris Pressey					read _input
7228d20e303SChris Pressey					[ -n "$_input" ] && _random="$_input"
7238d20e303SChris Pressey					case $_random in
7248d20e303SChris Pressey					[Yy][Ee][Ss]|[Yy][Ee]|[Yy])
7258d20e303SChris Pressey						passwdtype="random"
7268d20e303SChris Pressey						break
7278d20e303SChris Pressey						;;
7288d20e303SChris Pressey					esac
7298d20e303SChris Pressey					passwdtype="yes"
7308d20e303SChris Pressey					[ -n "$configflag" ] && break
7318d20e303SChris Pressey					trap 'stty echo; exit' 0 1 2 3 15
7328d20e303SChris Pressey					stty -echo
7338d20e303SChris Pressey					echo -n "Enter password: "
73472764df0SAaron LI					IFS= read -r upass
7358d20e303SChris Pressey					echo''
7368d20e303SChris Pressey					echo -n "Enter password again: "
73772764df0SAaron LI					IFS= read -r _passconfirm
7388d20e303SChris Pressey					echo ''
7398d20e303SChris Pressey					stty echo
7408d20e303SChris Pressey					# if user entered a blank password
7418d20e303SChris Pressey					# explicitly ask again.
7428d20e303SChris Pressey					[ -z "$upass" -a -z "$_passconfirm" ] \
7438d20e303SChris Pressey					    && continue
7448d20e303SChris Pressey					;;
7458d20e303SChris Pressey				[Yy][Ee][Ss]|[Yy][Ee]|[Yy])
7468d20e303SChris Pressey					passwdtype="none"
7478d20e303SChris Pressey					break;
7488d20e303SChris Pressey					;;
7498d20e303SChris Pressey				*)
7508d20e303SChris Pressey					# invalid answer; repeat the loop
7518d20e303SChris Pressey					continue
7528d20e303SChris Pressey					;;
7538d20e303SChris Pressey				esac
7548d20e303SChris Pressey				if [ "$upass" != "$_passconfirm" ]; then
7558d20e303SChris Pressey					echo "Passwords did not match!"
7568d20e303SChris Pressey					continue
7578d20e303SChris Pressey				fi
7588d20e303SChris Pressey				break
7598d20e303SChris Pressey			done
7608d20e303SChris Pressey			;;
7618d20e303SChris Pressey		*)
7628d20e303SChris Pressey			# invalid answer; repeat loop
7638d20e303SChris Pressey			continue
7648d20e303SChris Pressey			;;
7658d20e303SChris Pressey		esac
7668d20e303SChris Pressey		break;
7678d20e303SChris Pressey	done
7688d20e303SChris Pressey	_disable=${disableflag:-"no"}
7698d20e303SChris Pressey	while : ; do
7708d20e303SChris Pressey		echo -n "Lock out the account after creation? [$_disable]: "
7718d20e303SChris Pressey		read _input
7728d20e303SChris Pressey		[ -z "$_input" ] && _input=$_disable
7738d20e303SChris Pressey		case $_input in
7748d20e303SChris Pressey		[Nn][Oo]|[Nn])
7758d20e303SChris Pressey			disableflag=
7768d20e303SChris Pressey			;;
7778d20e303SChris Pressey		[Yy][Ee][Ss]|[Yy][Ee]|[Yy])
7788d20e303SChris Pressey			disableflag=yes
7798d20e303SChris Pressey			;;
7808d20e303SChris Pressey		*)
7818d20e303SChris Pressey			# invalid answer; repeat loop
7828d20e303SChris Pressey			continue
7838d20e303SChris Pressey			;;
7848d20e303SChris Pressey		esac
7858d20e303SChris Pressey		break
7868d20e303SChris Pressey	done
7878d20e303SChris Pressey
7888d20e303SChris Pressey	# Display the information we have so far and prompt to
7898d20e303SChris Pressey	# commit it.
7908d20e303SChris Pressey	#
7918d20e303SChris Pressey	_disable=${disableflag:-"no"}
7928d20e303SChris Pressey	[ -z "$configflag" ] && printf "%-10s : %s\n" Username $username
7938d20e303SChris Pressey	case $passwdtype in
7948d20e303SChris Pressey	yes)
7958d20e303SChris Pressey		_pass='*****'
7968d20e303SChris Pressey		;;
7978d20e303SChris Pressey	no)
7988d20e303SChris Pressey		_pass='<disabled>'
7998d20e303SChris Pressey		;;
8008d20e303SChris Pressey	none)
8018d20e303SChris Pressey		_pass='<blank>'
8028d20e303SChris Pressey		;;
8038d20e303SChris Pressey	random)
8048d20e303SChris Pressey		_pass='<random>'
8058d20e303SChris Pressey		;;
8068d20e303SChris Pressey	esac
8078d20e303SChris Pressey	[ -z "$configflag" ] && printf "%-10s : %s\n" "Password" "$_pass"
8088d20e303SChris Pressey	[ -n "$configflag" ] && printf "%-10s : %s\n" "Pass Type" "$passwdtype"
8098d20e303SChris Pressey	[ -z "$configflag" ] && printf "%-10s : %s\n" "Full Name" "$ugecos"
8108d20e303SChris Pressey	[ -z "$configflag" ] && printf "%-10s : %s\n" "Uid" "$uuid"
8118d20e303SChris Pressey	printf "%-10s : %s\n" "Class" "$uclass"
8128d20e303SChris Pressey	printf "%-10s : %s %s\n" "Groups" "${ulogingroup:-$username}" "$ugroups"
8138d20e303SChris Pressey	printf "%-10s : %s\n" "Home" "$uhome"
8149ed5bb8aSSascha Wildner	printf "%-10s : %s\n" "Home Mode" "$uhomeperm"
8158d20e303SChris Pressey	printf "%-10s : %s\n" "Shell" "$ushell"
8168d20e303SChris Pressey	printf "%-10s : %s\n" "Locked" "$_disable"
8178d20e303SChris Pressey	while : ; do
8188d20e303SChris Pressey		echo -n "OK? (yes/no): "
8198d20e303SChris Pressey		read _input
8208d20e303SChris Pressey		case $_input in
8218d20e303SChris Pressey		[Nn][Oo]|[Nn])
8228d20e303SChris Pressey			return 1
8238d20e303SChris Pressey			;;
8248d20e303SChris Pressey		[Yy][Ee][Ss]|[Yy][Ee]|[Yy])
8258d20e303SChris Pressey			add_user
8268d20e303SChris Pressey			;;
8278d20e303SChris Pressey		*)
8288d20e303SChris Pressey			continue
8298d20e303SChris Pressey			;;
8308d20e303SChris Pressey		esac
8318d20e303SChris Pressey		break
8328d20e303SChris Pressey	done
8338d20e303SChris Pressey	return 0
8348d20e303SChris Pressey}
8358d20e303SChris Pressey
8364f4826d5SMatthias Schmidt#### END SUBROUTINE DEFINITION ####
8378d20e303SChris Pressey
8388d20e303SChris PresseyTHISCMD=`/usr/bin/basename $0`
8398d20e303SChris PresseyDEFAULTSHELL=/bin/sh
8408d20e303SChris PresseyADDUSERCONF="${ADDUSERCONF:-/etc/adduser.conf}"
8418d20e303SChris PresseyPWCMD="${PWCMD:-/usr/sbin/pw}"
8428d20e303SChris PresseyMAILCMD="${MAILCMD:-mail}"
8438d20e303SChris PresseyETCSHELLS="${ETCSHELLS:-/etc/shells}"
8448d20e303SChris PresseyNOHOME="/nonexistent"
8458d20e303SChris PresseyNOLOGIN="nologin"
8464f4826d5SMatthias SchmidtNOLOGIN_PATH="/sbin/nologin"
8478d20e303SChris PresseyGREPCMD="/usr/bin/grep"
8488d20e303SChris PresseyDATECMD="/bin/date"
8498d20e303SChris Pressey
8508d20e303SChris Pressey# Set default values
8518d20e303SChris Pressey#
8528d20e303SChris Presseyusername=
8538d20e303SChris Presseyuuid=
8548d20e303SChris Presseyuidstart=
8558d20e303SChris Presseyugecos=
8568d20e303SChris Presseyulogingroup=
8578d20e303SChris Presseyuclass=
8588d20e303SChris Presseyuhome=
8599ed5bb8aSSascha Wildneruhomeperm=
8608d20e303SChris Presseyupass=
8618d20e303SChris Presseyushell=
8628d20e303SChris Presseyudotdir=/usr/share/skel
8638d20e303SChris Presseyugroups=
8648d20e303SChris Presseyuexpire=
8658d20e303SChris Presseyupwexpire=
8668d20e303SChris Presseyshells="`valid_shells`"
8678d20e303SChris Presseypasswdtype="yes"
8688d20e303SChris Presseymsgfile=/etc/adduser.msg
8698d20e303SChris Presseymsgflag=
8708d20e303SChris Presseyquietflag=
8718d20e303SChris Presseyconfigflag=
8728d20e303SChris Presseyfflag=
8738d20e303SChris Presseyinfile=
8748d20e303SChris Presseydisableflag=
8758d20e303SChris PresseyDflag=
8768d20e303SChris PresseySflag=
8778d20e303SChris Presseyreadconfig="yes"
8788d20e303SChris Presseyhomeprefix="/home"
8798d20e303SChris Presseyrandompass=
8808d20e303SChris Presseyfileline=
8818d20e303SChris Presseysavedpwtype=
8828d20e303SChris Presseydefaultclass=
8838d20e303SChris PresseydefaultLgroup=
8848d20e303SChris Presseydefaultgroups=
8858d20e303SChris Presseydefaultshell="${DEFAULTSHELL}"
8869ed5bb8aSSascha WildnerdefaultHomePerm=
8878d20e303SChris Pressey
8888d20e303SChris Pressey# Make sure the user running this program is root. This isn't a security
8890d6742a3SPeter Avalos# measure as much as it is a useful method of reminding the user to
8908d20e303SChris Pressey# 'su -' before he/she wastes time entering data that won't be saved.
8918d20e303SChris Pressey#
8928d20e303SChris Presseyprocowner=${procowner:-`/usr/bin/id -u`}
8938d20e303SChris Presseyif [ "$procowner" != "0" ]; then
8948d20e303SChris Pressey	err 'you must be the super-user (uid 0) to use this utility.'
8958d20e303SChris Pressey	exit 1
8968d20e303SChris Presseyfi
8978d20e303SChris Pressey
8988d20e303SChris Pressey# Overide from our conf file
8998d20e303SChris Pressey# Quickly go through the commandline line to see if we should read
9008d20e303SChris Pressey# from our configuration file. The actual parsing of the commandline
9018d20e303SChris Pressey# arguments happens after we read in our configuration file (commandline
9028d20e303SChris Pressey# should override configuration file).
9038d20e303SChris Pressey#
9048d20e303SChris Presseyfor _i in $* ; do
9058d20e303SChris Pressey	if [ "$_i" = "-N" ]; then
9068d20e303SChris Pressey		readconfig=
9078d20e303SChris Pressey		break;
9088d20e303SChris Pressey	fi
9098d20e303SChris Presseydone
9108d20e303SChris Presseyif [ -n "$readconfig" ]; then
9118d20e303SChris Pressey	# On a long-lived system, the first time this script is run it
9128d20e303SChris Pressey	# will barf upon reading the configuration file for its perl predecessor.
9138d20e303SChris Pressey	if ( . ${ADDUSERCONF} > /dev/null 2>&1 ); then
9148d20e303SChris Pressey		[ -r ${ADDUSERCONF} ] && . ${ADDUSERCONF} > /dev/null 2>&1
9158d20e303SChris Pressey	fi
9168d20e303SChris Presseyfi
9178d20e303SChris Pressey
91836e1ae1aSSascha Wildner# Process command-line options
9198d20e303SChris Pressey#
9208d20e303SChris Presseyfor _switch ; do
9218d20e303SChris Pressey	case $_switch in
9228d20e303SChris Pressey	-L)
9238d20e303SChris Pressey		defaultclass="$2"
9248d20e303SChris Pressey		shift; shift
9258d20e303SChris Pressey		;;
9268d20e303SChris Pressey	-C)
9278d20e303SChris Pressey		configflag=yes
9288d20e303SChris Pressey		shift
9298d20e303SChris Pressey		;;
9308d20e303SChris Pressey	-D)
9318d20e303SChris Pressey		Dflag=yes
9328d20e303SChris Pressey		shift
9338d20e303SChris Pressey		;;
9348d20e303SChris Pressey	-E)
9358d20e303SChris Pressey		disableflag=yes
9368d20e303SChris Pressey		shift
9378d20e303SChris Pressey		;;
9388d20e303SChris Pressey	-k)
9398d20e303SChris Pressey		udotdir="$2"
9408d20e303SChris Pressey		shift; shift
9418d20e303SChris Pressey		;;
9428d20e303SChris Pressey	-f)
9438d20e303SChris Pressey		[ "$2" != "-" ] && infile="$2"
9448d20e303SChris Pressey		fflag=yes
9458d20e303SChris Pressey		shift; shift
9468d20e303SChris Pressey		;;
9478d20e303SChris Pressey	-g)
9488d20e303SChris Pressey		defaultLgroup="$2"
9498d20e303SChris Pressey		shift; shift
9508d20e303SChris Pressey		;;
9518d20e303SChris Pressey	-G)
9528d20e303SChris Pressey		defaultgroups="$2"
9538d20e303SChris Pressey		shift; shift
9548d20e303SChris Pressey		;;
9558d20e303SChris Pressey	-h)
9568d20e303SChris Pressey		show_usage
9578d20e303SChris Pressey		exit 0
9588d20e303SChris Pressey		;;
9598d20e303SChris Pressey	-d)
9608d20e303SChris Pressey		homeprefix="$2"
9618d20e303SChris Pressey		shift; shift
9628d20e303SChris Pressey		;;
9638d20e303SChris Pressey	-m)
9648d20e303SChris Pressey		case "$2" in
9658d20e303SChris Pressey		[Nn][Oo])
9668d20e303SChris Pressey			msgflag=
9678d20e303SChris Pressey			;;
9688d20e303SChris Pressey		*)
9698d20e303SChris Pressey			msgflag=yes
9708d20e303SChris Pressey			msgfile="$2"
9718d20e303SChris Pressey			;;
9728d20e303SChris Pressey		esac
9738d20e303SChris Pressey		shift; shift
9748d20e303SChris Pressey		;;
9759ed5bb8aSSascha Wildner	-M)
9769ed5bb8aSSascha Wildner		defaultHomePerm=$2
9779ed5bb8aSSascha Wildner		shift; shift
9789ed5bb8aSSascha Wildner		;;
9798d20e303SChris Pressey	-N)
9808d20e303SChris Pressey		readconfig=
9818d20e303SChris Pressey		shift
9828d20e303SChris Pressey		;;
9838d20e303SChris Pressey	-w)
9848d20e303SChris Pressey		case "$2" in
9858d20e303SChris Pressey		no|none|random|yes)
9868d20e303SChris Pressey			passwdtype=$2
9878d20e303SChris Pressey			;;
9888d20e303SChris Pressey		*)
9898d20e303SChris Pressey			show_usage
9908d20e303SChris Pressey			exit 1
9918d20e303SChris Pressey			;;
9928d20e303SChris Pressey		esac
9938d20e303SChris Pressey		shift; shift
9948d20e303SChris Pressey		;;
9958d20e303SChris Pressey	-q)
9968d20e303SChris Pressey		quietflag=yes
9978d20e303SChris Pressey		shift
9988d20e303SChris Pressey		;;
9998d20e303SChris Pressey	-s)
10008d20e303SChris Pressey		defaultshell="`fullpath_from_shell $2`"
10018d20e303SChris Pressey		shift; shift
10028d20e303SChris Pressey		;;
10038d20e303SChris Pressey	-S)
10048d20e303SChris Pressey		Sflag=yes
10058d20e303SChris Pressey		shift
10068d20e303SChris Pressey		;;
10078d20e303SChris Pressey	-u)
10088d20e303SChris Pressey		uidstart=$2
10098d20e303SChris Pressey		shift; shift
10108d20e303SChris Pressey		;;
10118d20e303SChris Pressey	esac
10128d20e303SChris Presseydone
10138d20e303SChris Pressey
10148d20e303SChris Pressey# If the -f switch was used, get input from a file. Otherwise,
10158d20e303SChris Pressey# this is an interactive session.
10168d20e303SChris Pressey#
10178d20e303SChris Presseyif [ -n "$fflag" ]; then
10188d20e303SChris Pressey	if [ -z "$infile" ]; then
10198d20e303SChris Pressey		input_from_file
10208d20e303SChris Pressey	elif [ -n "$infile" ]; then
10218d20e303SChris Pressey		if [ -r "$infile" ]; then
10228d20e303SChris Pressey			input_from_file < $infile
10238d20e303SChris Pressey		else
10248d20e303SChris Pressey			err "File ($infile) is unreadable or does not exist."
10258d20e303SChris Pressey		fi
10268d20e303SChris Pressey	fi
10278d20e303SChris Presseyelse
10288d20e303SChris Pressey	input_interactive
10298d20e303SChris Pressey	while : ; do
10308d20e303SChris Pressey		if [ -z "$configflag" ]; then
10318d20e303SChris Pressey			echo -n "Add another user? (yes/no): "
10328d20e303SChris Pressey		else
10338d20e303SChris Pressey			echo -n "Re-edit the default configuration? (yes/no): "
10348d20e303SChris Pressey		fi
10358d20e303SChris Pressey		read _input
10368d20e303SChris Pressey		case $_input in
10378d20e303SChris Pressey		[Yy][Ee][Ss]|[Yy][Ee]|[Yy])
10388d20e303SChris Pressey			uidstart=`get_nextuid $uidstart`
10398d20e303SChris Pressey			input_interactive
10408d20e303SChris Pressey			continue
10418d20e303SChris Pressey			;;
10428d20e303SChris Pressey		[Nn][Oo]|[Nn])
10438d20e303SChris Pressey			echo "Goodbye!"
10448d20e303SChris Pressey			;;
10458d20e303SChris Pressey		*)
10468d20e303SChris Pressey			continue
10478d20e303SChris Pressey			;;
10488d20e303SChris Pressey		esac
10498d20e303SChris Pressey		break
10508d20e303SChris Pressey	done
10518d20e303SChris Presseyfi
1052