Return to BSD News archive
Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!munnari.OZ.AU!news.Hawaii.Edu!news.lava.net!news.pixi.com!news.dod.hawaii.gov!paf-news.hqpacaf.af.mil!wrdiss1.robins.af.mil!news.sgi.com!howland.erols.net!news.mathworks.com!uunet!in1.uu.net!192.109.159.3!news.gtn.com!news.netuse.de!tpki.toppoint.de!rimki.toppoint.de!chrimek Date: 04 Jan 1997 21:51:00 +0100 From: chrimek@rimki.toppoint.de (Christoph Rimek) Newsgroups: comp.unix.bsd.netbsd.misc Message-ID: <6OD1p0qZo$B@rimki.toppoint.de> References: <none-ya023480001912962244220001@news.infi.net> <mason-ya023380002012960019340001@news.four.net> <none-ya023480002012962112290001@news.infi.net> <x7zpz8wnxt.fsf@dumbcat.codewright.com> <3a13e94547@emw4maba.slip.gp.fht-esslingen.de> Subject: Re: Why no addusr? X-Newsreader: CrossPoint v3.11 R/C6513 Organization: Toppoint Mailbox e.V. Reply-To: chrimek@toppoint.de Lines: 366 Xref: euryale.cc.adfa.oz.au comp.unix.bsd.netbsd.misc:5057 Hello In article <3a13e94547@emw4maba.slip.gp.fht-esslingen.de>, emw4maba (emw4maba@gp.fht-esslingen.de) wrote: > In article <x7zpz8wnxt.fsf@dumbcat.codewright.com> > Marco S Hyman <marc@dumbcat.codewright.com> wrote: > > > Because ask 25 admins the "best" way to set up users and you will > > get at least 30 answers! Addusr scripts tend to implement policy, > > and every site is almost guaranteed to have policies that differ > > from that which the script implements. Some examples: > > > > where do home directories go? > > what is the initial password for a new user? > > do all users get the same dot files? > > how are mail aliases handled? > > > > This answer drives me up the wall, really. > Replies like this make us NetBSD users look like a bunch of snobs. > :-((( > > This is a bad argument [....] > > I repeat: The fact that there is no ideal solution is no argument not > to provide anything. Any solution is better than nothing! > This applies to other things in NetBSD, too. > Here is my suggestion, far from being ideal, but it works for our needs. The original is the script found under point 4.4 of the BSD-FAQ. You may use this script freely if it is of any value to you. If anyone has better solutions for parts of its text please let me know. This script is /usr/local/sbin/mkuser for our system "servus" which is mailserver for a small department (some 80 users). It has a compagnion file "mkuser.default" in the same directory that specifies some of the system dependent default settings, and there is a collection of configuration files for new users in /usr/share/skel. You will get a short help screen if you either read the text or call the script with any argument that is not an option. Try "mkuser help". --------------------------cut here (start)----------------------------- #!/bin/sh # # NAME: # mkuser[.sh] - interactive make user script # # SYNOPSIS: # # mkuser [-G "Group"] [-H "Homes"] [-S "Shell"] \\ # [-u "min_uid[,max_uid]"] [-f] [-e] [-p] [-q] [text] # # AUTHOR: # Simon J. Gerraty <sjg@zen.void.oz.au> # Please send copies of changes and bug-fixes to: # sjg@zen.void.oz.au # # HISTORY: # BSD-FAQ, Q 4.4: Where is the 'adduser' program? A: Here. # This copy modified to serve our local needs (NetBSD). # Modifications made by Ch. Rimek: # chrimek@toppoint.de or chrimek@psychologie.uni-kiel.de # # Enter "mkuser {anytext}" for HELP screen. ################################################ # # Variables, Settings # Myname=`basename $0 .sh` Mydir=`dirname $0` [ "$Mydir" = "." ] && Mydir=`pwd` Defaults="${Myname}.default" SKEL=/usr/share/skel ETC=/etc GF=${ETC}/group PF=${ETC}/passwd SF=${ETC}/shells # things that the defaults file may override. host=`hostname -s 2>/dev/null` Homes=/home/${host:-`uname -n | cut -d. -f1 -s`} Shell=/bin/sh Group=users UIDrange=100 # look for a defaults file, stop after first one found. for d in $HOME $Mydir do [ -s $d/$Defaults ] && { . $d/$Defaults; break; } done # define temporary files' names #EXF=/tmp/${Myname}.e$$ TF=/tmp/${Myname}.u$$ # check capabilities of echo command case `echo -n .` in -n*) N=;C="\c";; *) N=-n;C=;; esac ################################################ # Function declarations # ################################################ mk_dirs() { # check whether absolute or relative pathname specified case $1 in /*) pp=/;; *) pp=;; esac # replace "/" with " " in argument(s) to separate all parts of full path for p in `echo $1 | tr / " "` do # build directory tree successively case "$pp" in "") pp=$p;; /) pp=/$p;; *) pp=$pp/$p;; esac # make directoy, if it does not exist [ -d $pp ] || mkdir $pp || exit 5 done } upd_passwd() { # set the local environment for vipw EDITOR=ed VISUAL=ed export EDITOR VISUAL # for user information, show /etc/passwd entries, line format is: # "username:passwd:uid:gid:Gecos:home:shell" echo "adding $1:*:$2:$3:$4:$5:$6" # vipw uses /etc/master.passwd as file, line format is: # "username:passwd:uid:gid:class:change:expire:Gecos:home:shell" echo "$1:*:$2:$3::0:0:$4:$5:$6" > $TF # find line number of NIS-entry, if any. line=`grep -n '^+:' $PF | cut -d: -f1` # insert line from TF one line before $line or current (usually last) ( sleep 1; echo ${line}-1r $TF; echo w; echo q; ) | ${VIPW:-vipw} } get_uid() { # read ID bounds from parameters min=$1 max=$2 # preset return value rv=-1 if [ $first ]; then # # option "first" selected: return first unused UID within given range. # i=$min while [ $i -le $max ] do [ "`cut -d: -f3 $PF | grep -w "$i"`" ] || { rv=$i; break; } i=`expr $i + 1` done else # # option "first" not set, use standard method: # return first UID one above highest UID used in given range. # i=$max while [ $i -ge $min ] do [ "`cut -d: -f3 $PF | grep -w "$i"`" ] && break rv=$i i=`expr $i - 1` done fi echo $rv } ################################################ # the main program # ################################################ set -- `getopt H:S:G:u:fepq $*` for i in $* do case "$i" in --) shift; break;; -H) Homes=$2; shift 2;; -S) Shell=$2; shift 2;; -G) Group=$2; shift 2;; -u) rawUID=$2; shift 2;; -f) first=first; shift;; -e) empty=empty; shift;; -p) pword=pword; shift;; -q) quiet=quiet; shift;; esac done # give HELP screen if any non-option parameter given. if [ $* ]; then clear echo "${Myname} HELP screen -- interactive make user script" echo "" echo "Syntax: ${Myname} [options] [text]" echo "" echo "Options:" echo " -G \"Group\" name of new user's group" echo " -H \"Homes\" base for user login directory" echo " -S \"Shell\" user login shell" echo " -u \"min[,max]\" UID range (default= GID..(GID+100))" echo " -f first: take first unused UID (default=last)" echo " -e empty: do not copy configuration sample files" echo " -p pword: prompt for passwords" echo " -q quiet: do not display default settings" echo "" echo "Any text other than these options leads to this HELP screen." echo "" echo "Error conditions (return values):" echo " error 1: user not root user" echo " error 2: specified group does not exist" echo " error 3: specified shell not in /etc/shells file" echo " error 4: shell file non-existent or not executable" echo " error 5: no UID available in specified range" echo "" exit 0 fi # # test for error conditions # # Make sure only the super user uses this utility. if [ `id -un` != "root" ]; then echo "${Myname}: error 1: only the root user may create new user accounts." exit 1 fi # get ID of $Group, exit with error if non-existent GID=`grep "^$Group:" $GF | cut -d: -f3 -s` if [ -z "$GID" ]; then echo "${Myname}: error 2: group \"$Group\" does not exist." exit 2 fi # check $Shell parameter if [ -z `grep "^$Shell$" $SF` ]; then echo "${Myname}: error 3: specified shell not in trusted shell database." exit 3 fi # check $Shell file if [ ! -x $Shell ]; then echo "${Myname}: error 4: specified shell file not existent/executable." exit 4 fi # set up range of User IDs # if "rawUID" (raw User ID range) given, separate (and order) Min and Max, if [ $rawUID ]; then minUID=`echo $rawUID | cut -d, -f1` maxUID=`echo $rawUID | cut -d, -f2 -s` fi [ $minUID ] || minUID=$GID [ $maxUID ] || maxUID=`expr $minUID + $UIDrange` if [ $minUID -gt $maxUID ]; then tmpUID=$minUID; minUID=$maxUID; maxUID=$tmpUID fi if [ ! $quiet ]; then echo "${Myname} settings:" for v in Group Homes Shell do eval echo "\ $v = \$$v" done echo " UID range = ${minUID}..${maxUID}" echo "" fi echo "Interactive make user script - for help type \"${Myname} help\"" echo "Enter username and fullname, no quotes needed for spaced fullname." echo "An empty line (no username) terminates input." # # the main program loop # while true do # Get actual UID # Call get_uid, parameter minUID maxUID (one single UID, if equal) # return actUID: may be any valid number in range [minUID..maxUID] # if return value = 0 (root) or negative then no UID found -> exit. actUID=`get_uid $minUID $maxUID` if [ $actUID -lt 0 ]; then echo "${Myname}: error 5: no UID available in specified range." exit 5 fi # the prompt line echo "" echo $N "($actUID) login [realname]: $C" read Login Gecos [ "$Login" ] || exit 0 # here comes the real job: call upd_passwd. upd_passwd "$Login" "$actUID" "$GID" "$Gecos" "$Homes/$Login" "$Shell" # make home directory, if not already exists if [ ! -d $Homes/$Login ]; then mk_dirs $Homes/$Login && \ chown $Login $Homes/$Login && \ chgrp $Group $Homes/$Login && \ chmod 2755 $Homes/$Login fi # copy standard configuration files to user's home directory if [ -z $empty ]; then cp $SKEL/* $Homes/$Login chown $Login $Homes/$Login/* fi # if option p specified, inquire password for new user [ $pword ] && passwd $Login # process next user done # finally remove the temporary stuff rm -f $TF ## end. --------------------------cut here (end)------------------------------- The "mkuser.default" file for our system has the following three lines: Group=users Homes=/home/servus Shell=/bin/sh -cr -- Christoph Rimek, Kiel, Germany (+49 431 57601) chrimek@toppoint.de