*BSD News Article 34688


Return to BSD News archive

Newsgroups: comp.os.386bsd.questions
Path: sserve!newshost.anu.edu.au!harbinger.cc.monash.edu.au!bunyip.cc.uq.oz.au!munnari.oz.au!constellation!news.uoknor.edu!ns1.nodak.edu!netnews.nwnet.net!reuter.cse.ogi.edu!cs.uoregon.edu!usenet.ee.pdx.edu!fastrac.llnl.gov!lll-winken.llnl.gov!sol.ctr.columbia.edu!spool.mu.edu!cass.ma02.bull.com!as02.bull.oz.au!melb.bull.oz.au!zen!sjg
From: sjg@zen.void.oz.au (Simon J. Gerraty)
Subject: Re: ADD USER utility for BSDI
Message-ID: <1994Aug21.003437.12382@zen.void.oz.au>
Organization: Zen programming...
Date: Sun, 21 Aug 1994 00:34:37 GMT
References: <Brad-1808941518300001@btmedia.mankato.mn.us>
Lines: 336

Brad@BTMedia.Mankato.MN.US (Brad Theissen) writes:
>We are using the BSDI product, and are growing weary of the process of
>adding new users (editing pwrd file, making directories, changing
>ownership, etc.). We made a little mistake last night that forced us to
>rebuild the router from scratch!

I once wrote a mega complex adduser script, but these days I just use
this one.  I've used it on NetBSD, SunOS, Solaris and HP-UX.  You
should have little trouble on other *BSD flavours.

#!/bin/sh
# This is a shell archive.
# remove everything above the "#!/bin/sh" line
# and feed to /bin/sh
# Use -c option to overwrite existing files
#
# Contents: 
#	adduser.sh
#
# packed by: <sjg@zen.void.oz.au> on Sun Aug 21 10:25:30 EST 1994
#
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f adduser.sh -a x$1 != x-c ; then
  echo shar: Will not over-write existing file \"adduser.sh\"
else
  echo shar: Extracting \"adduser.sh\" \(6443 characters\)
  sed 's/^X//' >adduser.sh << '!EOF'
X:
X#
X# NAME:
X#	adduser.sh - portable add user script
X#
X# SYNOPSIS:
X#	
X#	adduser.sh [-G "Group"] [-H "Homes"] [-S "Shell"] [-u "uid"] \\
X#		[-p "encrypted"] [-P "cleartext"] [-l]
X#
X# DESCRIPTION:
X#	Simply adds users and their home directory.  It prompts for a
X#	"username" and "fullname" which become part of the passwd file
X#	entry for the new user.  It adds "username" to "Group"
X#	(creating it if necessary) and uses "uid" or the 'gid' of
X#	"Group" as a starting point for its search for an unused
X#	'uid'.  By default it will prompt for a passwd after adding
X#	each user, but '-p' can be used to set a pre-encrypted password
X#	or '-P' can be used to give a clear text password which the
X#	script will encrypt and then use for each new "username".
X#
X#	Most of the variables used are obvious.  "Homes" is the parent
X#	directory of new users home directories.
X#	
X#	The '-l' option causes the script to show the default values
X#	for the variables that it uses.  Most if not all can be set on
X#	a per machine basis by creating a file '.adduserrc' in the
X#	super users home directory or in the directory where
X#	'adduser.sh' is found.  If "Homes"/.adduserrc exists it will
X#	be processed after any others, so can be used to set defaults
X#	on a per project basis.
X#	
X# NOTES:
X#	The script handles shadow password files on Solaris 2.3, other
X#	machines may break.  It has been tested on NetBSD, SunOS,
X#	Solaris and HP-UX.
X#	
X# AUTHOR:
X#	Simon J. Gerraty <sjg@zen.void.oz.au>
X#
X
X# RCSid:
X#	$Id: adduser.sh,v 1.2 1994/05/08 22:54:04 sjg Exp sjg $
X#
X#	@(#) Copyright (c) 1993 Simon J. Gerraty
X#
X#	This file is provided in the hope that it will
X#	be of use.  There is absolutely NO WARRANTY.
X#	Permission to copy, redistribute or otherwise
X#	use this file is hereby granted provided that 
X#	the above copyright notice and this notice are
X#	left intact. 
X#      
X#	Please send copies of changes and bug-fixes to:
X#	sjg@zen.void.oz.au
X#
X
XMyname=`basename $0 .sh`
XMydir=`dirname $0`
Xcase $Mydir in
X.)	Mydir=`pwd`;;
Xesac
X
XETC=/etc
X# for testing only
X#ETC=/tmp
X#VIPW="ed $ETC/passwd"
X
X# thinks that the rc file may override.
Xhost=`hostname 2>/dev/null`
XHomes=/home/${host:-`uname -n`}
XShell=/bin/csh
X[ -x /bin/ksh ] && Shell=/bin/ksh
XGroup=users
XPasswd='**'
X
X# look for an rc file
Xfor d in $HOME $Mydir 
Xdo
X  [ -s $d/.${Myname}rc ] && { . $d/.${Myname}rc; break; }
Xdone
X
XEXF=/tmp/e$$
XTF=/tmp/u$$
XTF2=/tmp/uu$$
X
Xcase `echo -n .` in
X-n*)	N=;C="\c";;
X*)	N=-n;C=;;
Xesac
X
XOS=`uname -s`
X
Xadd_path () { [ -d $1 ] && eval ${2:-PATH}="\$${2:-PATH}:$1"; }
X
Xget_id()
X{
X  file=$1
X  name=$2
X  min=${3:-1000}
X  max=`expr $min + ${4:-999}`
X  > $EXF
X  
X  id=`grep "^$name:" $file | cut -d: -f3`
X  case "$id" in
X  "")
X    # missing, must add it
X    i=$min
X    while [ $i -lt $max ]
X    do
X      n=`cut -d: -f1,3 $file | grep ":$i\$"`
X      case "$n" in
X      "")
X        # an empty slot - use it
X        id=$i
X        break;;
X      esac
X      i=`expr $i + 1`
X  done
X  ;;
X  *)
X    echo $id > $EXF;;
X  esac
X  echo $id
X}
X
Xmkdirs()
X{
X  case $1 in
X  /*)	pp=/;;
X  *)	pp=;;
X  esac
X  for p in `echo $1 | tr / " "`
X  do
X    case "$pp" in
X    "")	pp=$p;;
X    /)	pp=/$p;;
X    *)	pp=$pp/$p;;
X    esac
X    [ -d $pp ] || mkdir $pp || exit 1
X  done
X}
X
X
Xadd_group()
X{
X  echo "adding $1:*:$2: to $ETC/group"
X  echo "$1:*:$2:" >> $ETC/group
X}
X
Xupd_group()
X{
X  [ "$mygroup" ] || mygroup=`grep "^$1:" /etc/group | cut -d: -f4`
X  case ",$mygroup," in
X  ",,")				# empty
X    add=$2;;
X  *,$2,*)			# already there
X    add=;;
X  *)				# missing
X    add=,$2;;
X  esac
X  [ "$add" ] && sed "/^$1:/s/\$/$add/" $ETC/group > $ETC/group.$$ &&
X  	mv $ETC/group.$$ $ETC/group
X}
X
Xupd_passwd()
X{
X  EDITOR=ed
X  VISUAL=ed
X  export EDITOR VISUAL
X
X  didit=
X  
X  echo "adding $1:$2:$3:$4:$5:$6:$7 to $ETC/passwd"
X  case "$OS" in
X  SunOS)
X    if test -f /etc/shadow; then
X      # we are assuming its Solaris
X      echo "$1:x:$3:$4:$5:$6:$7" > $TF
X      echo "$1:$2:6445::::::" > $TF2
X      didit=yes
X    fi
X    ;;
X  *BSD)	  # NetBSD at least
X    echo "$1:$2:$3:$4::0:0:$5:$6:$7" > $TF
X    didit=yes
X    ;;
X  esac
X  # most OS's just want this.
X  test "$didit" || echo "$1:$2:$3:$4:$5:$6:$7" > $TF
X
X  line=`grep -n '^+:' $ETC/passwd | cut -d: -f1`
X  ( sleep 1; echo ${line}-1r $TF; echo w; echo q;
X    if test -f /etc/shadow && test "$OS" = SunOS
X    then
X      # this is a crok...
X      sleep 5
X      echo e
X      sleep 5
X      echo '$r' $TF2
X      echo w
X      echo q
X    fi
X  ) | ${VIPW:-vipw} 
X}
X
Xadd_user() 
X{
X  group=$1; shift
X  
X  eval set -- `echo "'$*'" | sed "s/:/' '/g"`
X  
X  gid=`get_id $ETC/group $group $4 256`
X  if [ "$gid" ]; then
X    [ -s $EXF ] || add_group $group $gid 
X    uid=`get_id $ETC/passwd $1 $3 1024`
X    if [ "$uid" ]; then
X      [ -s $EXF ] || upd_passwd "$1" "$2" "$uid" "$gid" "$5" "$6" "$7"; upd_group $group $1
X      [ -d $6 ] || { mkdirs $6 && chown $1 $6 && chgrp $group $6 && chmod 2775 $6; }
X    else
X      echo "can't add user $1" >&2; exit 1
X    fi
X  else
X    echo "can't add group $group" >&2; exit 1
X  fi
X}
X
Xrm_user()
X{
X  ( echo /^$1:/d; echo w; echo q ) | ${VIPW:-vipw}
X}
X
X# needs perl
Xencrypt() {
X  for d in /usr/libexec /usr/lib
X  do
X    [ -x $d/makekey ] && { makekey=$d/makekey; break; }
X  done
X  perl -e "print pack('a8a2', '$1', '${2:-$$}')" | ${makekey:-makekey}
X}
X
X# ok, time to get to work...
Xset -- `getopt H:S:G:u:p:P:l $*`
X
Xadd_path /sbin
Xadd_path /usr/sbin
Xadd_path /usr/ucb
Xadd_path /usr/etc
X
Xfor i in $*
Xdo
X  case "$i" in
X  --)	shift; break;;
X  -H)	Homes=$2; shift 2;
X	# pick up group defaults...
X	test -s $Homes/.${Myname}rc && . $Homes/.${Myname}rc
X        ;;
X  -S)	Shell=$2; shift 2;;
X  -G)	Group=$2; shift 2;;
X  -u)	uid=$2; shift 2;;
X  -p)	Passwd="$2"; shift 2;;
X  -P)	Passwd=`encrypt $2`; shift 2;;
X  -l)	list=yes;;
X  esac
Xdone
X
Xgid=`get_id $ETC/group $Group 100 1000`
X[ "$uid" ] || uid=$gid
X
Xcase "$Passwd" in
X""|none)	Passwd=;;
Xnologin)	Passwd='*';;
Xesac
X
Xif [ "$list" = yes ]; then
X  echo "Defaults:"
X  for v in Group Homes Shell
X  do
X    eval echo "\	$v=\$$v"
X  done
X  [ "x$Passwd" = "x*" ] && echo "	Passwd=prompt" || echo "	Passwd=$Passwd"
X  [ "$uid" ] && echo "	Initial uid=$uid"
X  echo
Xfi
Xecho Enter username and fullname - spaces in fullname are ok, no quotes needed.
Xecho An empty line terminates input.
Xecho
X
Xecho $N "username fullname: $C"
Xwhile read uname fname
Xdo
X  [ "$uname" ] || exit 0
X  add_user $Group "$uname:$Passwd:$uid:$gid:$fname:$Homes/$uname:$Shell"
X  [ "x$Passwd" = "x**" ] && passwd $uname
X  echo $N "username fullname: $C"
Xdone
!EOF
  if test 6443 -ne `wc -c < adduser.sh`; then
    echo shar: \"adduser.sh\" unpacked with wrong size!
  fi
  chmod +x adduser.sh
fi
exit 0

 
-- 
Simon J. Gerraty        <sjg@zen.void.oz.au>

#include <disclaimer>   /* imagine something _very_ witty here */