Subject: Re: Questions with i386 1.1
To: None <kpekarek@hertz.elee.calpoly.edu>
From: Tom Swiss <tms@tis.com>
List: netbsd-help
Date: 03/06/1996 10:25:29
>1. Is there an adduser script/program?

     It's not part of the distribution, but yes, there is; I think it's on
the WWW site. I've appended a copy.

>2. How do I set up name service (remote computer is nameserver)

     /etc/resolv.conf gets a line "nameserver xxx.xxx.xxx.xxx". Do a "man 5
resolv.conf" for more info.


-----<cut here>-----
:
#
# NAME:
#	adduser.sh - portable add user script
#
# SYNOPSIS:
#	
#	adduser.sh [-G "Group"] [-H "Homes"] [-S "Shell"] [-u "uid"] \\
#		[-p "encrypted"] [-P "cleartext"] [-l]
#
# DESCRIPTION:
#	Simply adds users and their home directory.  It prompts for a
#	"username" and "fullname" which become part of the passwd file
#	entry for the new user.  It adds "username" to "Group"
#	(creating it if necessary) and uses "uid" or the 'gid' of
#	"Group" as a starting point for its search for an unused
#	'uid'.  By default it will prompt for a passwd after adding
#	each user, but '-p' can be used to set a pre-encrypted password
#	or '-P' can be used to give a clear text password which the
#	script will encrypt and then use for each new "username".
#
#	Most of the variables used are obvious.  "Homes" is the parent
#	directory of new users home directories.
#	
#	The '-l' option causes the script to show the default values
#	for the variables that it uses.  Most if not all can be set on
#	a per machine basis by creating a file '.adduserrc' in the
#	super users home directory or in the directory where
#	'adduser.sh' is found.  If "Homes"/.adduserrc exists it will
#	be processed after any others, so can be used to set defaults
#	on a per project basis.
#	
# NOTES:
#	The script handles shadow password files on Solaris 2.3, other
#	machines may break.  It has been tested on NetBSD, SunOS,
#	Solaris and HP-UX.
#	
# AUTHOR:
#	Simon J. Gerraty <sjg@zen.void.oz.au>
#

# RCSid:
#	$Id: adduser.sh,v 1.2 1994/05/08 22:54:04 sjg Exp sjg $
#
#	@(#) Copyright (c) 1993 Simon J. Gerraty
#
#	This file is provided in the hope that it will
#	be of use.  There is absolutely NO WARRANTY.
#	Permission to copy, redistribute or otherwise
#	use this file is hereby granted provided that 
#	the above copyright notice and this notice are
#	left intact. 
#      
#	Please send copies of changes and bug-fixes to:
#	sjg@zen.void.oz.au
#

Myname=`basename $0 .sh`
Mydir=`dirname $0`
case $Mydir in
.)	Mydir=`pwd`;;
esac

ETC=/etc
# for testing only
#ETC=/tmp
#VIPW="ed $ETC/passwd"

# thinks that the rc file may override.
host=`hostname 2>/dev/null`
Homes=/home/${host:-`uname -n`}
Shell=/bin/csh
[ -x /bin/ksh ] && Shell=/bin/ksh
Group=users
Passwd='**'

# look for an rc file
for d in $HOME $Mydir 
do
  [ -s $d/.${Myname}rc ] && { . $d/.${Myname}rc; break; }
done

EXF=/tmp/e$$
TF=/tmp/u$$
TF2=/tmp/uu$$

case `echo -n .` in
-n*)	N=;C="\c";;
*)	N=-n;C=;;
esac

OS=`uname -s`

add_path () { [ -d $1 ] && eval ${2:-PATH}="\$${2:-PATH}:$1"; }

get_id()
{
  file=$1
  name=$2
  min=${3:-1000}
  max=`expr $min + ${4:-999}`
  > $EXF
  
  id=`grep "^$name:" $file | cut -d: -f3`
  case "$id" in
  "")
    # missing, must add it
    i=$min
    while [ $i -lt $max ]
    do
      n=`cut -d: -f1,3 $file | grep ":$i\$"`
      case "$n" in
      "")
        # an empty slot - use it
        id=$i
        break;;
      esac
      i=`expr $i + 1`
  done
  ;;
  *)
    echo $id > $EXF;;
  esac
  echo $id
}

mkdirs()
{
  case $1 in
  /*)	pp=/;;
  *)	pp=;;
  esac
  for p in `echo $1 | tr / " "`
  do
    case "$pp" in
    "")	pp=$p;;
    /)	pp=/$p;;
    *)	pp=$pp/$p;;
    esac
    [ -d $pp ] || mkdir $pp || exit 1
  done
}


add_group()
{
  echo "adding $1:*:$2: to $ETC/group"
  echo "$1:*:$2:" >> $ETC/group
}

upd_group()
{
  [ "$mygroup" ] || mygroup=`grep "^$1:" /etc/group | cut -d: -f4`
  case ",$mygroup," in
  ",,")				# empty
    add=$2;;
  *,$2,*)			# already there
    add=;;
  *)				# missing
    add=,$2;;
  esac
  [ "$add" ] && sed "/^$1:/s/\$/$add/" $ETC/group > $ETC/group.$$ &&
  	mv $ETC/group.$$ $ETC/group
}

upd_passwd()
{
  EDITOR=ed
  VISUAL=ed
  export EDITOR VISUAL

  didit=
  
  echo "adding $1:$2:$3:$4:$5:$6:$7 to $ETC/passwd"
  case "$OS" in
  SunOS)
    if test -f /etc/shadow; then
      # we are assuming its Solaris
      echo "$1:x:$3:$4:$5:$6:$7" > $TF
      echo "$1:$2:6445::::::" > $TF2
      didit=yes
    fi
    ;;
  *BSD)	  # NetBSD at least
    echo "$1:$2:$3:$4::0:0:$5:$6:$7" > $TF
    didit=yes
    ;;
  esac
  # most OS's just want this.
  test "$didit" || echo "$1:$2:$3:$4:$5:$6:$7" > $TF

  line=`grep -n '^+:' $ETC/passwd | cut -d: -f1`
  ( sleep 1; echo ${line}-1r $TF; echo w; echo q;
    if test -f /etc/shadow && test "$OS" = SunOS
    then
      # this is a crok...
      sleep 5
      echo e
      sleep 5
      echo '$r' $TF2
      echo w
      echo q
    fi
  ) | ${VIPW:-vipw} 
}

add_user() 
{
  group=$1; shift
  
  eval set -- `echo "'$*'" | sed "s/:/' '/g"`
  
  gid=`get_id $ETC/group $group $4 256`
  if [ "$gid" ]; then
    [ -s $EXF ] || add_group $group $gid 
    uid=`get_id $ETC/passwd $1 $3 1024`
    if [ "$uid" ]; then
      [ -s $EXF ] || upd_passwd "$1" "$2" "$uid" "$gid" "$5" "$6" "$7"; upd_group $group $1
      [ -d $6 ] || { mkdirs $6 && chown $1 $6 && chgrp $group $6 && chmod 2775 $6; }
    else
      echo "can't add user $1" >&2; exit 1
    fi
  else
    echo "can't add group $group" >&2; exit 1
  fi
}

rm_user()
{
  ( echo /^$1:/d; echo w; echo q ) | ${VIPW:-vipw}
}

# needs perl
encrypt() {
  for d in /usr/libexec /usr/lib
  do
    [ -x $d/makekey ] && { makekey=$d/makekey; break; }
  done
  perl -e "print pack('a8a2', '$1', '${2:-$$}')" | ${makekey:-makekey}
}

# ok, time to get to work...
set -- `getopt H:S:G:u:p:P:l $*`

add_path /sbin
add_path /usr/sbin
add_path /usr/ucb
add_path /usr/etc

for i in $*
do
  case "$i" in
  --)	shift; break;;
  -H)	Homes=$2; shift 2;
	# pick up group defaults...
	test -s $Homes/.${Myname}rc && . $Homes/.${Myname}rc
        ;;
  -S)	Shell=$2; shift 2;;
  -G)	Group=$2; shift 2;;
  -u)	uid=$2; shift 2;;
  -p)	Passwd="$2"; shift 2;;
  -P)	Passwd=`encrypt $2`; shift 2;;
  -l)	list=yes;;
  esac
done

gid=`get_id $ETC/group $Group 100 1000`
[ "$uid" ] || uid=$gid

case "$Passwd" in
""|none)	Passwd=;;
nologin)	Passwd='*';;
esac

if [ "$list" = yes ]; then
  echo "Defaults:"
  for v in Group Homes Shell
  do
    eval echo "\	$v=\$$v"
  done
  [ "x$Passwd" = "x*" ] && echo "	Passwd=prompt" || echo "	Passwd=$Passwd"
  [ "$uid" ] && echo "	Initial uid=$uid"
  echo
fi
echo Enter username and fullname - spaces in fullname are ok, no quotes needed.
echo An empty line terminates input.
echo

echo $N "username fullname: $C"
while read uname fname
do
  [ "$uname" ] || exit 0
  add_user $Group "$uname:$Passwd:$uid:$gid:$fname:$Homes/$uname:$Shell"
  [ "x$Passwd" = "x**" ] && passwd $uname
  echo $N "username fullname: $C"
done