#!/bin/sh # # adduser - add a new user to the system # # Best used interactively, but can also be invoked with # command line arguments, either with positional parameters, # # adduser [ userid uid gid fullname homedir shell ] # # or with flagged parameters, # # adduser [-d homedir] [-u uid] [-g gid] [-s shell] # [-R "fullname"] [-l userid] userid # # Anything missing will be asked for. # # Requires a Bourne shell that can accept function definitions. # # Works for NIS if /etc/passwd is the master for NIS maps # # Much modified from an original from UT-Austin # :: Modified by Eric Myers, 25 January 1991, UT Austin # :: Modified again by Eric Myers, 9 October 1993 at Vassar College # :: Modified again by Eric Myers, 13 January 1998, at Univ. Michigan # @(#) $Id: adduser,v 3.23 2001/08/16 03:01:22 myers Exp myers $ ###################################################################### # Restrict path to only what is necessary: PATH=/usr/local/bin:/bin:/usr/bin:/usr/sbin:/usr/etc:/usr/ucb export PATH ###################################################################### ## You must be root to run this script... if [ "`whoami`x" != "root"x ]; then echo "You must be root to do $PROG!" exit 1 fi #################### ## Defaults: modify to match your site. First one found is the default. DefaultShellList="/usr/local/bin/tcsh /usr/bin/tcsh /bin/tcsh /bin/bash /bin/csh" for Shell in $DefaultShellList do if [ -x $Shell ]; then DefaultShell=$Shell break fi done UserHome=/home # where to put home directories if [ -f /sdmach ]; then UserHome=/Users # where to put home directories fi TempDir=/usr0/tmp # where to put temp files ## Minimum/Maximum UID & GID MaxUID=2147483647 MinUID=100 MaxGID=2147483647 MinGID=20 ## Other Passwd=/etc/passwd # system password file Shadow=/etc/shadow # shadow passwd file Group=/etc/group # group file SKELDIR=/usr/local/adm/skel # where sample.* startup scripts live Last=/usr/local/adm/.LastUID # last UID assigned PROG=`basename $0` ###################################################################### ## dirname is in SystemV category - so put it herein shdirname() { expr \ ${1-.}'/' : '\(/\)[^/]*//*$' \ \| ${1-.}'/' : '\(.*[^/]\)//*[^/][^/]*//*$' \ \| . } ## BSD / SYSV differences that we care about: X=`( echo -n EC ; echo HO)` if [ "$X" = "ECHO" ]; then BSDNL="-n"; SYSVNL="" # BSD line control GREP="egrep -s" # silent grep on BSD else SYSVNL="\c"; BSDNL="" # System V line control GREP="egrep -q" # quiet grep on SYSV fi ## Echo without new-line for either BSD or SYSV echo_n() { echo ${BSDNL} "$* ${SYSVNL}" } ###################################################################### # Command line arguments can be used in place of asking questions. # # This arrangement of command line arguments matches the HP-UX # system administration manager (sam), and so can be called by sam. gid="" uid="" for param in $* do case $param in -l) UserID=$2; shift 2;; -c) fullname=$2; shift 2;; -d) homedir=$2; shift 2;; -u) uid=$2; shift 2;; -g) gid=$2 ; shift 2;; -s) shell=$2; shift 2;; -p) passwd=$2; shift 2;; -L) office_loc=$2; shift 2;; -H) home_phone=$2; shift 2;; -O) office_phone=$2; shift 2;; # Old/HPUX: -R) fullname=$2; shift 2;; -h) homedir=$2; shift 2;; -v) uid=$2; shift 2;; esac done ###################################################################### ## Get missing arguments and check for validity ## UserID, if none given if [ $# -gt 0 ]; then UserID=$1 ; shift fi while [ "$UserID" = "" ]; do echo " " echo_n "Please enter userid to add: " ; read UserID done if ${GREP} "^${UserID}:" ${Passwd} ; then echo "${PROG}: ERROR: ${UserID} aleady in ${Passwd}"; exit 1; fi ## UID: Get last user ID number and increment if [ -f $Last ]; then read LastUID LastGID < $Last LastUID=`echo $LastUID + 1 | bc` else LastUID=$MinUID; fi ## check uid if [ $# -gt 0 ]; then uid=$1 ; shift fi while [ "$uid" = "" ]; do echo_n "User ID number for ${UserID}? [$LastUID] " ; read junk if [ "$junk" = "" ];then uid=$LastUID else uid=$junk fi if [ $uid -lt $MinUID -o $uid -ge $MaxUID ]; then echo "uid: uid must be greater than $MinUID and less than $MaxUID" uid="" fi done # check if uid already exists if ${GREP} "^.*:.*:${uid}:" ${Passwd} ; then echo "${PROG}: ERROR: ${uid} already in ${Passwd}"; exit 1; fi ## GID: look for "users" group and use it, otherwise use UID LastGID=`awk -F : '$1 ~ /^users/ {print $3}' /etc/group` if [ $LastGID = "" ]; then LastGID=$UID fi if [ "$gid" != "" ]; then LastGID=$gid fi ## Check group ID numbers if [ $LastGID -le 0 ]; then # if no default use the uid as default LastGID=$uid fi if [ $# -gt 0 ]; then gid=$1 ; shift fi while [ "$gid" = "" ]; do echo_n "Group number for ${UserID}? [$LastGID] " ; read junk if [ "$junk" = "" ]; then gid=$LastGID else gid=$junk fi if [ $gid -lt $MinGID -o $gid -gt $MaxGID ]; then echo "gid: gid must be greater than $MinGID and less than $MaxGID" gid="" fi done ## Get full name of user if [ $# -gt 0 ]; then fullname=$1 ; shift fi while [ "$fullname" = "" ] ; do echo_n "User's full name: " ; read fullname done ## Home directory: default to ${UserHome}/${UserID} if no home directory given if [ $# -gt 0 ]; then homedir=$1 ; shift fi while [ "${homedir}" = "" ]; do homedir=${UserHome}/${UserID} echo_n "Home directory for $UserID? [$homedir] " ; read junk if [ "$junk" != "" ]; then homedir=$junk fi ## check if homedir already exists (only a warning) # if [ -f ${homedir} ] ; then echo "${PROG}: WARNING: a file named \"${homedir}\" already exists" echo "and is NOT a directory, pick something else or quite and start" echo "over." homedir="" fi # if [ -d ${homedir} ] ; then echo "${PROG}: WARNING: home directory \"${homedir}\" already exists." fi ## check if all but last path of homedir exits # dir=`shdirname $homedir` if [ ! -d $dir ]; then echo "$dir: does not exist or is not a directory" exit 1 fi ## check if $homedir is local (only a warning if it isn't) dfout=`df $dir | tail -1 |grep /dev` if [ "$dfout" = "" ]; then echo "NOTE: $dir is not on local machine:" df $dir ; echo " " fi done ## Get shell or use default. Be sure the shell exists. if [ $# -gt 0 ]; then shell=$1 ; shift fi while [ "${shell}" = "" ] ; do shell=$DefaultShell echo_n "Login shell for $UserID? [$shell] " ; read junk if [ "$junk" != "" ]; then shell=$junk fi if test ! -x $shell ; then echo "$shell: the program does not exist or is not executable." shell="" fi done ## Acceptance of the information: echo " " echo "Please check and accept this entry:" echo " Username: ${UserID}" echo " uid number: ${uid}" echo " gid number: ${gid}" echo " full name: \"${fullname}\"" echo " home directory: ${homedir}" echo " shell: ${shell}" echo " " echo_n "Shall I create an $Passwd entry with this info (y/n)? " read X if [ "$X" != "y" ]; then if [ "X$X" = "X" ]; then echo "You must answer 'y' to create the $Passwd entry." fi echo Aborted. exit 1 fi #==================== Create the entry in $Passwd ============== GCOS="$fullname,$office_loc,$office_phone,$home_phone" pwent="${UserID}:x:${uid}:${gid}:${GCOS}:${homedir}:${shell}" # copy /etc/passwd (which locks out others from editing it ) cp ${Passwd} /etc/ptmp ( echo '$' ; echo 'i' ; echo "${pwent}" ; echo '.' ; echo 'w' ; echo 'q' ) | ed -s /etc/ptmp > /dev/null 2>&1 if ${GREP} "^${UserID}:" /etc/ptmp ; then if cp /etc/ptmp ${Passwd} ; then echo "Password entry succesfully created for ${UserID} in ${Passwd}." else echo "${PROG}: ERROR: can't install modified ${Passwd}" exit 1 fi else echo "${PROG}: ERROR: password entry didn't go to /etc/ptmp" exit 1 fi # Unlock password file. rm /etc/ptmp # If yp is running then update maps (assumes /etc/passwd is master) YP="" if [ -f /var/run/ypbind.pid ]; then YPPID=`cat /var/run/ypbind.pid` ps $YPPID > /dev/null if [ $? -eq 0 ]; then YP="yes" cd /var/yp echo "Merging password entry into NIS..." make > /dev/null fi fi ## Save the last known uid and gid echo $uid $gid > $Last #========== Create an entry in $Shadow, if it exists if [ -w $Shadow ]; then echo "${UserID}::::::::" >> $Shadow echo "User $UserID added to $Shadow." fi #========== Create an entry in $Group if UID==GID and there is none if [ $gid -eq $uid ]; then if ${GREP} "^.*:.*:${gid}:" ${Group} ; then echo "Group $gid already appears in $Group." else echo "${UserID}::${gid}:${UserID}" >> $Group echo "Added group ${UserID}::$gid to $Group" fi fi #========== Create and fill home directory # echo "Creating home directory for ${UserID}... " mkdir ${homedir} mkdir ${homedir}/Mail mkdir ${homedir}/bin mkdir ${homedir}/.garbage.bin ln -s ${homedir}/.garbage.bin ${homedir}/.wastebasket # Add default user startup files to home directory # If /etc/skel/ exists then use it, otherwise use SKELDIR. # Any file with name sample.* in SKELDIR gets copied to the user's # home directory with the 'sample' removed. echo "Filling the home directory for ${UserID}... " if [ -d /etc/skel ]; then cp -R /etc/skel/* /etc/skel/.??* ${homedir} else cd $SKELDIR INITLIST=`/bin/ls -A1 sample.* | grep -v ~\$` for SAMPLEFILE in $INITLIST do FILENAME=`echo $SAMPLEFILE | sed -e "s/sample//" ` cp $SAMPLEFILE ${homedir}/${FILENAME} done fi ## Put user's full name in ~/.login file sed -e "s/^setenv NAME .*$/setenv NAME \"$fullname\"/" \ $SKELDIR/sample.login >${homedir}/.login ## Make all these belong to the user and user's group chown -R ${uid} ${homedir} chgrp -R ${gid} ${homedir} ## Create TMPDIR temporary directory, if we can if [ -d $TempDir ]; then TMPDIR=$TempDir/${UserID} if [ -d $TMPDIR ]; then echo "Temporary directory $TMPDIR already exists." else echo "Creating temporary directory $TMPDIR..." mkdir $TMPDIR chown ${uid} $TMPDIR chgrp ${gid} $TMPDIR fi fi #========== Now set the passwd echo " " echo $Passwd entry and home directory created for user ${UserID}. echo "Now please set a password for this user." # If yp is in use, then rebuild if [ "$YP" != "" ]; then /usr/bin/yppasswd -p ${UserID} echo "Updating NIS..." cd /var/yp make > /dev/null else /usr/bin/passwd ${UserID} fi exit 0