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