#!/bin/bash
#
# Copyright (c) 1999 Thorsten Kukuk
# Author: Thorsten Kukuk <kukuk@suse.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#

#
# initialize variables and options
#
init ()
{
    umask 22

    VERB='> /dev/null 2>1'
    ECHO="eval"
    BACKUP=no_nisplus
    DOMAIN=`nisdefaults -d`
    NODOT=`echo $DOMAIN | sed -e "s/\.$//"`
    SECURE_LEVEL=x
    PAS=""
    DEFSEC=x
    OWRITE="false"
    #
    # The following files need special handling:
    # - they must be backed up and removed before initializing the client.
    #   These files are automatically generated by nisinit and keylogin.
    #   during the initialization process.
    # - during the restore process, these files must be removed if the
    #   backup files are not found.
    #
    DEL_REST_FILES="/var/nis/NIS_COLD_START /etc/.rootkey"
    #
    # The following file needs to be removed before the initialization
    # and restoring process.  There is no need to backup this file because
    # this file is generated by the nis_cachemgr automatically.
    #
    DELETE_FILES="/var/nis/NIS_SHARED_DIRCACHE /var/nis/.pref_servers"
    #
    # RESTORE_FILES variable contains a list of files that need to
    # be restored if the backup file exists.  Otherwise, the current
    # file should be left alone.
    #
    RESTORE_FILES="/etc/nsswitch.conf /etc/rc.config"
    #
    # Set the PATH Variable to NIS+ and YP programs
    PATH=/usr/lib/nis:/usr/sbin:/usr/bin:/usr/lib/yp:$PATH; export PATH

    if [ -x /usr/bin/expr.new ]
    then
	EXPR=/usr/bin/expr.new
    else
	EXPR=/usr/bin/expr
    fi
    #
    # Set Variable where hosts is
    if [ -f /etc/inet/hosts ]
    then
	HOSTS_FILE=/etc/inet/hosts
    else
	HOSTS_FILE=/etc/hosts
    fi
}

#
# get_ans(): gets an asnwer from the user.
#		$1  instruction/comment/description/question
#		$2  default value
#
get_ans()
{
    if [ -z "$2" ]
    then
	echo -n -e "$1 "
    else
	echo -n -e "$1 [$2] "
    fi
    read ANS
    if [ -z "$ANS" ]
    then
	ANS=$2
    fi
}

#
#  get_yesno constants:
#
#  There are two very common phrases passed to get_yesno:
#   These have been parameterized to provide "ease of use".
#	 Thus, there are three message "types" which are possible:
#	 --$CONTINUE:  "Do you want to continue? (type 'y' to continue, 'n' to exit this script)"
#   --$CONFIRM:   "Is this information correct? (type 'y' to accept, 'n' to change)"
#   --actual string is passed.
#
#	If the message is $CONTINUE, get_yesno will exit if the response is no.
#
CONTINUE=2
CONFIRM=1
#
# get_yesno(): get the yes or no answer.
#		$1  message type  or message.
#
get_yesno()
{
    ANS="X"

    case $1 in
	$CONTINUE )
	    INFOTEXT="Do you want to continue? (type 'y' to continue, 'n' to exit this script)"
	    ;;
	$CONFIRM )
	    INFOTEXT="Is this information correct? (type 'y' to accept, 'n' to change)"
	    ;;
    *) INFOTEXT="$1"
	    ;;
    esac

    while [ "$ANS" != "y" -a "$ANS" != "n" -a "$ANS" != "Y" -a "$ANS" != "N" ]
    do
	get_ans "$INFOTEXT" ""
    done

    if [ "$1" = "$CONTINUE" ]; then
	if [ $ANS = "n" -o $ANS = "N" ]
	then
	    exit
	fi
    fi
}

#
# print_more(): print the usage message.
#
print_more()
{
    less << EOF
USAGE:
  o to create credentials for NIS+ client or NIS+ principals:
	$PROG  -c  [-o]  [-v]  [-x]  [-l <NIS+_password>] [-d <NIS+_domain>]
		<name> ...

  o to initialize NIS+ client machines:
	$PROG  -i  [-S 0|2]  [-v]  [-x]  -h <NIS+_server_host>
		[-a <NIS+_server_addr>]  [-d <NIS+_domain>]

  o to initialize NIS+ users:
	$PROG -u  [-v]  [-x]

  o to restore the network service environment:
	$PROG -r

OPTIONS:
     -a <NIS+_server_addr>
	 specifies the IP address for the NIS+ server.  This option is
	 *ONLY* used with the "-i" option.

     -c  adds DES credentials for NIS+ principals.

     -d <NIS+_domain>
	 specifies the NIS+ domain where the credential should be created
	 when used in conjuction with the -c option.  It specifies the
	 name for the new NIS+ domain when used in conjuction with the
	 -i option.  The default is your current domain name.

     -h <NIS+_server_host>
	 specifies the NIS+ server's hostname.  This option is *ONLY*
	 used with the "-i" option.

     -i  initializes a NIS+ client machine.  Also see the -S option.

     -l <network_password>
	 specifies the network password for the clients.  This option is
	 *ONLY* used with the "-c" option.  If this option is not specified,
	 this script will prompt you for the network password.

     -o  overwrite existing credential entries.  The default is not
	 to overwrite.  This is *ONLY* used with the "-c" option.

     -r  restores the network service environment.

     -S 0|2
	 specifies the authentication level for the NIS+ client.  Level 0 is
	 for unauthenticated clients and level 2 is for authenticated (DES)
	 clients.  The default is to set up with level 2 authentication.
	 This option is *ONLY* used with -i option.  nisclient always uses
	 level 2 authentication (DES) for both -c and -u options.  There is
	 no need to run nisclient with -u and -c for level 0 authentication.

     -u  initializes a NIS+ user.

     -v  runs this script in verbose mode.

     -x  turns the "echo" mode on.  This script just prints the commands
	 that it would have executed.  The commands are printed with
	 leading "+++".  Note that the commands are not actually executed.
	 The default is off.

EOF
}

#
# print_usage(): ask user if they want to see detailed usage msg.
#
print_usage()
{
    echo
    get_yesno "  Do you want to see more information on this command? \\n\
    (type 'y' to get a detailed description, 'n' to exit)"
    if [ $ANS = "n" -o $ANS = "N" ]
    then
	echo
	return 1
    else
	print_more
    fi
    exit 1
}

print_ciru_usage()
{
    if [ "$ERRciru_OPTION" = "$ciru_OPTION" ]
    then
	echo "**WARNING: You have specified the '$ciru_OPTION' option twice."
	return 0
    fi
    echo
    echo "**ERROR: You have specified the '$ERRciru_OPTION' option after"
    echo "         having selected the '$ciru_OPTION' option."
    echo "Please select only one of these options: '-c', '-i', '-r' or '-u'."
    print_usage
    exit 1
}

#
# parse_arg(): parses the input arguments.
# It returns the number to be shift in the argument list.
#
parse_arg()
{
    while getopts "a:cd:g:h:il:orS:uvx" ARG
    do
	case $ARG in
	    a) ADDR=$OPTARG;;
	    c) if [ -z "$ACTION" ]
	       then
		    ACTION="create"
		    ciru_OPTION="-c"
	       else
		    ERRciru_OPTION="-c"
		    print_ciru_usage
	       fi;;
	    d) if [ "`echo $OPTARG | sed -e 's/.*\(.\)$/\1/'`" != "." ]
	       then
		    NODOT=$OPTARG
		    DOMAIN=${NODOT}.
	       else
		    DOMAIN=$OPTARG
		    NODOT=`echo $DOMAIN | sed -e "s/\.$//"`
	       fi;;
	    h)	HOST=$OPTARG;;
	    i)	if [ -z "$ACTION" ]
		then
		    ACTION="init"
		    ciru_OPTION="-i"
		else
		    ERRciru_OPTION="-i"
		    print_ciru_usage
		fi;;
	    l)	PAS=$OPTARG;;
	    o)	OWRITE="";;
	    r)	if [ -z "$ACTION" ]
		then
		    ACTION="restore"
		    ciru_OPTION="-r"
		else
		    ERRciru_OPTION="-r"
		    print_ciru_usage
		fi;;
	    S)	VALUE=`$EXPR "$OPTARG" : "\([02]\)"`
		if [ -z "$VALUE" ]
            	then
		    echo "**ERROR: invalid security level."
		    echo "	It must be either 0 or 2."
		    exit 1
		fi
            	SECURE_LEVEL=$VALUE;;
	    v)	VERB="";;
	    u)	if [ -z "$ACTION" ]
		then
		    ACTION="user"
		    ciru_OPTION="-u"
		else
		    ERRciru_OPTION="-u"
		    print_ciru_usage
		fi;;
	    x)	ECHO="echo +++";;
	    \?)	print_usage
		exit 1;;
	    *)	echo "**ERROR: Should never get to this point!!!!!"
		print_usage
		exit 1;;
	esac
    done
    return `$EXPR $OPTIND - 1`
}

########### RESTORE #########################################
#
# restore_domain(): resets the "domainname" according to "/etc/defaultdomain".
#
restore_domain()
{
    . /etc/rc.config

    echo "restoring domain to $YP_DOMAINNAME..."
        if [ "${YP_DOMAINNAME}." != `nisdefaults -d` ]
        then
                $ECHO domainname ${YP_DOMAINNAME}
        fi
        echo ""
}
#
# restore_switch(): restarts the switch if necessary.
# restarts nscd to ensure that it tracks the switch
#
restore_switch()
{
    if [ -f /sbin/init.d/nscd ]
    then
	eval "echo stopping nscd ... $VERB"
	$ECHO /sbin/init.d/nscd stop
    fi
    eval "echo '' $VERB"
    $ECHO killproc -TERM /usr/sbin/keyserv
    $ECHO startproc /usr/sbin/keyserv
    if [ -f /sbin/init.d/nscd ]
    then
	eval "echo starting nscd ... $VERB"
	$ECHO /sbin/init.d/nscd start
    fi
}

#
# mv_file(): moves file.$BACKUP to file.
#		$1  file name to be moved.
#
mv_file()
{
    $ECHO "mv -f $1.$BACKUP $1 > /dev/null"
}

#
# restore_file(): restores the file specified.
#		$1  the file to be restored
# This routine will restore any file that has the backup file <file>.$BACKUP.
# The following table shows which backup files are created when the nisclient
# script is run based on the previous name service setup.
#
#	Files	 |  NIS -> NIS+	|  NIS+ -> NIS+
#     -----------+---------------+----------------
#     rootkey	 |	no	|	yes
#     coldstart  |	no	|	yes
#     client_info|	no	|	yes
#     switch	 |	yes	|	maybe
#     hosts	 |	maybe	|	maybe
#     domain	 |	maybe	|	maybe
#
# Based on this table, those special files defined in $DEL_REST_FILES need to
# be restored if any files from $RESTORE_FILES were restored (specially switch),
# or if backup files for all the files in $DEL_REST_FILES were found.
#
restore_file()
{
    for FILE in $RESTORE_FILES
    do
	if [ -f $FILE.$BACKUP ]
	then
	    if mv_file $FILE;
	    then
		RESTORE=TRUE
		echo "	File $FILE restored!"
	    else
		echo "**ERROR: could not restore file $FILE"
		exit 1
	    fi
	fi
    done

    # ... check if the backup files exist for the special files in
    # $DEL_REST_FILES
    if [ "$RESTORE" != "TRUE" ]
    then
	for FILE in $DEL_REST_FILES
	do
	    if [ ! -f $FILE.$BACKUP ]
	    then
		return
	    fi
	done
    fi

    # ... restore special files: coldstart and rootkey
    # If the backup file exists, then restore.  Otherwise, remove
    # the file.
    #
    for FILE in $DEL_REST_FILES
    do
	if [ -f $FILE.$BACKUP ]
	then
	    if mv_file $FILE;
	    then
		RESTORE="TRUE"
		echo "	File $FILE restored!"
	    else
		echo "**ERROR: could not restore file $FILE"
		exit 1
	    fi
	else
	    if [ -f $FILE ]
	    then
		$ECHO "/bin/rm -f $FILE 2> /dev/null"
	    fi
	fi
    done
}

#
# restore_nis(): removes the cache files: NIS_SHARED_DIRCACHE and
#	.pref_servers.
#
restore_nis()
{
    # ... remove the dircache file
    for CACHE in $DELETE_FILES
    do
	if [ -f $CACHE ]
	then
	    $ECHO "/bin/rm -f $CACHE 2> /dev/null"
	fi
    done
}

#
# restore_service(): starts ypbind by checking the switch file.
# If NIS+ service is to be restored, it will start nis_cachemgr.
#
restore_service()
{
    SWITCH=`grep "^[a-z]*:" /etc/nsswitch.conf`

    echo $SWITCH | grep -s "\<nisplus\>" >/dev/null
    if [ $? -eq 0 ]
    then
	echo "restarting nis_cachemgr process..."
	$ECHO killproc -TERM /usr/sbin/nis_cachemgr
	$ECHO startproc /usr/sbin/nis_cachemgr
    else
	$ECHO killproc -TERM /usr/sbin/nis_cachemgr
    fi

    echo $SWITCH | grep -s "\<nis\>" >/dev/null
    if [ $? -eq 0 ]
    then
	echo "restarting NIS (YP) process..."
	$ECHO killproc -TERM /usr/sbin/ypbind
	$ECHO startproc /usr/sbin/ypbind
    fi
}

#
# restore(): restores the previous network information service.
#
restore()
{
    WHO=`id | sed -e "s/uid=[0-9]*(\([^ )]*\)).*/\1/"`
    if [ $WHO != "root" ]
    then
	echo "This script must be run as root ..."
	exit 1
    fi

    echo "This script will restore the previous network information"
    echo "service.  It recovers all the files with the no_nisplus "
    echo "extension and restarts either NIS+ or NIS client processes"
    echo "according to the /etc/nsswitch.conf configuration file."
    echo ""
    echo "Once restore is done, you will need to reboot your machine."
    get_yesno $CONTINUE

    $ECHO killproc -TERM /usr/sbin/rpc.nisd
    $ECHO killproc -TERM /usr/sbin/nis_cachemgr
    $ECHO killproc -TERM /usr/sbin/ypbind
    $ECHO killproc -TERM /usr/sbin/rpc.nispasswdd

    restore_file

    if [ "$RESTORE" = "TRUE" ]
    then
	restore_domain

	restore_switch

	restore_service

	echo "Client files restored!"
	echo "Please reboot your machine for changes to take effect."
    else
	echo "Nothing to restore from!"
	echo "This script can only restore from NIS+ setup done with"
	echo "nisclient command."
    fi
}

#
# restore_here(): same as restore() except it's called from init_client()
# when it fails to initialize a client.
#
restore_here()
{
    echo ""
    echo "Restoring your network service..."
    echo ""

    $ECHO killproc /usr/sbin/rpc.nisd
    $ECHO killproc /usr/sbin/nis_cachemgr
    $ECHO killproc /usr/sbin/ypbind

    restore_file

    if [ "$RESTORE" = "TRUE" ]
    then
	restore_domain

	restore_switch

	restore_service

	echo "Client files restored!"
    fi
    restore_tmp
    exit 1
}

#
# restore_tmp(): restores temporary backup files for previous backups.
#
restore_tmp()
{
    # ... restore from temporary backup files for previous backup
    for FILE in $RESTORE_FILES $DEL_REST_FILES
    do
	if [ -f $FILE.$BACKUP.$$ ]
	then
	    eval "echo restoring the temporary backup file for $FILE... $VERB"
	    $ECHO mv -f $FILE.$BACKUP.$$ $FILE.$BACKUP > /dev/null
	fi
    done
    exit 1
}

#
# remove_tmp(): remove the backup files for the previous backups
#
remove_tmp()
{
    for FILE in $RESTORE_FILES $DEL_REST_FILES
    do
	if [ -f $FILE.$BACKUP.$$ ]
	then
	    eval "echo removing the temporary backup file for $FILE... $VERB"
	    $ECHO "/bin/rm -f $FILE.$BACKUP.$$"
	fi
    done
}

################ SETUP #########################################
#
# setup_backup(): backup all the files specfied in variable $RESTORE_FILES
# to <file>.$BACKUP and save a temporary copy of previous backup.
#
setup_backup()
{
    eval "echo setting up backup files... $VERB"

    trap restore_tmp 2

    # ... save a copy of current backup copies
    for FILE in $RESTORE_FILES $DEL_REST_FILES
    do
	if [ -f $FILE.$BACKUP ]
	then
	    $ECHO mv $FILE.$BACKUP $FILE.$BACKUP.$$ > /dev/null &
	fi
    done

    # ... save a copy of these special files: coldstart and rootkey
    for FILE in $DEL_REST_FILES
    do
	if [ -f $FILE ]
	then
	    eval "echo saving a copy of $FILE... $VERB"
	    $ECHO cp $FILE $FILE.$BACKUP
	fi
    done

    trap restore_here 2
}

#
# setup_server(): adds server information into /etc/hosts file.
# Initializes $ADDR & $HOST (addr & name of place to get COLDSTART file)
#
setup_server()
{
    eval "echo setting up NIS+ server information... $VERB"
    while [ -z "$HOST" ]
    do
	get_ans "Type server's hostname:" ""
	HOST=$ANS
    done
    ENTRY=`grep -v "^#" $HOSTS_FILE | grep -s -i "\<$HOST\>"`
    if [ $? -eq 0 ]
    then
	if [ -z "$ADDR" ]
	then
	    eval "echo $HOST is already in the /etc/hosts file. $VERB"
	    echo ""
	    ADDR=`echo $ENTRY | awk '{print $1}'`
	    return
	else
	    OLD_ADDR=`echo $ENTRY | awk '{print $1}'`
	    $ECHO "cp $HOSTS_FILE $HOSTS_FILE.$BACKUP"
	    $ECHO "sed -e \"/$ENTRY/s/^$OLD_ADDR/$ADDR/\" \
				$HOSTS_FILE > /tmp/hosts.$$"
	    $ECHO mv /tmp/hosts.$$ $HOSTS_FILE > /dev/null
	    return
	fi
    elif [ -z "$ADDR" ]
    then
	DEFADDR=""
	PROC=`pidof ypbind`
	if [ ! -z "$PROC" ]
	then
	    # ... try yp maps
	    DEFADDR=`ypmatch $HOST hosts 2> /dev/null | cut -d' ' -f1`
	else
	    # ... try nisplus tables
	    if [ -f /var/nis/NIS_COLD_START ]
	    then
		DEFADDR=`nismatch -P $HOST hosts.org_dir 2> /dev/null | cut -d' ' -f3`
	    fi
	fi
	while [ -z "$ADDR" ]
	do
	    get_ans "Type server ${HOST}'s IP address:" "$DEFADDR"
	    ADDR=$ANS
	done
    fi

    $ECHO "cp $HOSTS_FILE $HOSTS_FILE.$BACKUP"
    $ECHO "echo $ADDR  $HOST >> $HOSTS_FILE"
    eval "echo $VERB"
}

#
# setup_domain(): sets up "domainname" and "rc.config" with the specified
# domain information.
#
setup_domain()
{
    echo "setting up domain information \"$DOMAIN\"..."
    if [ `nisdefaults -d` != ${DOMAIN} ]
    then
	$ECHO domainname $NODOT
    fi

    # We cannot assume that the /etc/rc.config is set to the
    # same value as the domainname is.
    . /etc/rc.config
    if [ "$YP_DOMAINNAME" != $NODOT ]
    then
	$ECHO "cp /etc/rc.config /etc/rc.config.$BACKUP > /dev/null"
	RC_SEARCH=`grep YP_DOMAINNAME= /etc/rc.config`
	if [ ! -z "$RC_SEARCH" ]
	then
	    RC_REPLACE='YP_DOMAINNAME="'${NODOT}'"'
	    $ECHO sed 's/${RC_SEARCH}/${RC_REPLACE}/' < /etc/rc.config.$BACKUP > /etc/rc.config
	fi
    fi
    echo ""
}
#
# setup_switch(): copies the nisplus switch configuration file
#
setup_switch()
{
    echo "setting up the name service switch information..."
    $ECHO "/bin/rm -f /etc/.rootkey 2> /dev/null"
    diff /etc/nsswitch.conf /etc/nsswitch.nisplus > /dev/null
    if [ $? -eq 0 ]
    then
	eval "echo The switch configuration file is already set to use NISPLUS. $VERB"
	echo ""
	killproc -TERM /usr/sbin/keyserv
	startproc /usr/sbin/keyserv
        return
    fi

    $ECHO "cp /etc/nsswitch.conf /etc/nsswitch.conf.$BACKUP"
    $ECHO "cp /etc/nsswitch.nisplus /etc/nsswitch.conf"

    killproc -TERM /usr/sbin/keyserv
    startproc /usr/sbin/keyserv
    echo ""
}
#
# setup_security(): runs chkey to change the network password same as the
# login passwd.
#               $1  specifies root or user setup
#
setup_security()
{
    if [ $1 = "root" ]
    then
	MESS="root"
    else
        MESS="user"
    fi
    eval "echo setting up security information for $1... $VERB"
    echo "At the prompt below, type the network password (also known"
    echo "as the Secure-RPC password) that you obtained either"
    echo "from your administrator or from running the nispopulate script."
    $ECHO "chkey -p > /dev/null"
    if [ $? -ne 0 ]
    then
	echo "**ERROR: chkey failed."
        echo ""
        echo "The network password that you have entered is invalid."
        echo "If this machine was initialized before as a NIS+ client,"
        echo "please enter the $MESS login password as the network"
        echo "password."
        echo "Or re-type the network password that your administrator"
        echo "gave you."
        echo ""

	$ECHO "chkey -p > /dev/null"
        if [ $? -ne 0 ]
	then
	    echo "**ERROR: chkey failed again."
	    echo "Please contact your network administrator to verify your network password."
	    if [ $1 = "root" ]
	    then
		restore_here
	    fi
	fi
    fi
    echo ""
    echo "Your network password has been changed to your login one."
    echo "Your network and login passwords are now the same."
    echo ""
}
#
################# init client ####################################
#
# init_client(): initializes client
#
init_client()
{
    eval "echo initializing client machine... $VERB"
    WHO=`id | sed -e "s/uid=[0-9]*(\([^ )]*\)).*/\1/"`
    if [ $WHO != "root" ]
    then
	echo "**ERROR: You must be root to use the -i option."
	exit 1
    fi

    echo ""
    echo "Initializing client `uname -n` for domain \"$DOMAIN\"."

    if [ -d /var/nis/data ]
    then
	echo ""
	echo "WARNING: this machine serves NIS+ directories. Once this script is"
	echo "executed, you will not be able to restore the existing NIS+ server"
	echo "environment. Are you sure you want to proceed?"
	get_yesno "(type 'y' to continue, 'n' to exit this script)"
	if [ $ANS = "n" -o $ANS = "N" ]
	then
	    exit
	fi
	echo "Once initialization is done, you will need to reboot your"
	echo "machine."
	echo ""
    else
	echo "Once initialization is done, you will need to reboot your"
	echo "machine."
	echo ""
	get_yesno $CONTINUE
	echo ""
    fi

    eval "echo killing NIS and/or NIS+ processes... $VERB"
    $ECHO killproc -TERM /usr/sbin/ypbind
    $ECHO killproc -TERM /usr/sbin/nis_cachemgr
    if [ -f /sbin/init.d/nscd ]
    then
	eval "echo stopping nscd ... $VERB"
	$ECHO /sbin/init.d/nscd stop
    fi
    eval "echo '' $VERB"

    if [ -d /var/nis/data ]
    then
	$ECHO killproc -TERM /usr/sbin/rpc.nispasswdd
	$ECHO killproc -TERM /usr/sbin/rpc.nisd
        $ECHO "rm -f /var/nis/trans.log > /dev/null"
        $ECHO "rm -f /var/nis/data.dict* > /dev/null"
        $ECHO "rm -rf /var/nis/data > /dev/null"
    fi

    setup_backup

    setup_server

    setup_domain

    setup_switch

    eval "echo running nisinit command ... $VERB"
    $ECHO "/bin/rm -f $DELETE_FILES 2> /dev/null"
    $ECHO "mv -f /var/nis/NIS_COLD_START /var/nis/NIS_COLD_START.$BACKUP 2> /dev/null"

    eval "echo nisinit -c -H $ADDR ... $VERB"
    $ECHO "nisinit -c -H $ADDR > /dev/null"
    if [ $? -ne 0 ]
    then
	echo "**ERROR: nisinit failed."
	restore_here
    fi
    echo ""

    if [ "$SECURE_LEVEL" = "2" ]
    then
	eval "echo -S 2 option specified, setting up security... $VERB"
	setup_security root
    elif [ "$SECURE_LEVEL" = "x" ]
    then
	if nistest '[cname='`nisdefaults -h`'],cred.org_dir'.$DOMAIN;
	then
	    eval "echo credential exists for setting up security... $VERB"
	    setup_security root
	fi
    fi

    $ECHO killproc -TERM /usr/sbin/nis_cachemgr
    $ECHO startproc /usr/sbin/nis_cachemgr
    if [ -f /sbin/init.d/nscd ]
    then
	eval "echo starting nscd ... $VERB"
	$ECHO /sbin/init.d/nscd start
    fi
    remove_tmp

    echo "Client initialization completed!!"
    echo "Please reboot your machine for changes to take effect."
}
#
################# restore client ####################################
#
# restore(): restores the previous network information service.
#
restore()
{
    WHO=`id | sed -e "s/uid=[0-9]*(\([^ )]*\)).*/\1/"`
    if [ $WHO != "root" ]
    then
	echo "This script must be run as root ..."
	exit 1
    fi

    echo "This script will restore the previous network information"
    echo "service.  It recovers all the files with the no_nisplus "
    echo "extension and restarts either NIS+ or NIS client processes"
    echo "according to the /etc/nsswitch.conf configuration file."
    echo ""
    echo "Once restore is done, you will need to reboot your machine."
    get_yesno $CONTINUE

    killproc -TERM /usr/sbin/rpc.nisd
    killproc -TERM /usr/sbin/nis_cachemgr
    killproc -TERM /usr/sbin/ypbind
    killproc -TERM /usr/sbin/rpc.nispasswdd

    restore_file

    if [ "$RESTORE" = "TRUE" ]
    then
	restore_domain

	restore_switch

	restore_service

	echo "Client files restored!"
	echo "Please reboot your machine for changes to take effect."
    else
	echo "Nothing to restore from!"
	echo "This script can only restore from NIS+ setup done with"
	echo "nisclient command."
    fi
}
#
####### Insert Credentials ########
#
# check_domain(): checks if it's a valid domain and get the server's info.
#
check_domain()
{
#    if [ "$ECHO" = "echo" ]
#    then
#	return
#    fi

    echo "checking $DOMAIN domain..."
    if nistest -t D $DOMAIN;
    then
	:
    else
	echo "**ERROR: Don't know about the domain \"$DOMAIN\"."
	echo "   Please check the domain name."
	exit 1
    fi

    SERVER=`(niscat -o $DOMAIN) | sed -n '/^[[:space:]]*[Nn]ame[[:space:]]*:[[:space:]]*\(.*\.\)[[:space:]]*$/{
    s//\1/p
    q
    }'`
    SER_NAME=`echo $SERVER | cut -d. -f1`
    SER_DOM=`echo $SERVER | cut -d. -f2-`
    if [ $SER_DOM = $SER_NAME ]
    then
	SER_DOM=$DOMAIN
    fi

    DUMMY=`nismatch -P $SER_NAME hosts.org_dir.$SER_DOM`
    if [ $? -eq 0 ]
    then
	SERVER=`echo $DUMMY | sed -n -e "1p"`
	SER_ADDR=`echo $SERVER | cut -d" " -f3`
    else
	DUMMY=`grep -v "^#" $HOSTS_FILE | grep -i -s $SER_NAME`
	if [ $? -eq 0 ]
	then
	    SERVER=`echo $DUMMY | sed -e "s/        / /g"`
	    SER_ADDR=`echo $SERVER | cut -d" " -f1`
	else
	    echo "**ERROR: Couldn't get the server ${SER_NAME}'s address."
	    exit 1
	fi
    fi
    echo ""
}
#
# check_perm(): checks if we have write permission to the NIS+ table
# This should be replaced with nisaccess command when it's available
#               $1  the table to be checked.
#
check_perm()
{
    if [ "$ECHO" = "echo" ]
    then
	return
    fi

    echo "checking $1 permission..."
    MYPRINC=`nisdefaults -p`
    if [ $MYPRINC = "nobody" ]
    then
	if nistest -a n=c $1;
	then
	    return
	else
	    return 1
	fi
    fi

    DUMMY=`nisls -ld $1`
    if [ $? -ne 0 ]
    then
	exit 1
    fi
    OWN=`echo $DUMMY | cut -d" " -f3`
    if [ "$OWN" = $MYPRINC ]
    then
	if nistest -a o=c $1;
	then
	    return
	else
	    return 1
	fi
    fi

    DUMMY=`nisls -ldg $1`
    if [ $? -ne 0 ]
    then
	exit 1
    fi
    OWN=`echo $DUMMY | cut -d" " -f3`
    if [ ! -z "$OWN" ]
    then
	if nisgrpadm -t -s "$OWN" $MYPRINC;
	then
	    if nistest -a g=c $1;
	    then
		return
	    else
		return 1
	    fi
	fi
    fi

    if nistest -a w=c $1;
    then
	return
    else
	return 1
    fi
}
#
# Check if we add a user or a host or if something is wrong
#
check_type()
{
    eval "echo checking info type for $NAME... $VERB"
    UTYPE="FALSE"
    HTYPE="FALSE"
    ARG=$1
    LARG=$1
    NEWNAME=""
    DUM1=`nismatch -P name=$ARG hosts.org_dir.$DOMAIN`;
    if [ $? -eq 0 ]
    then
	H_NAME=`echo $DUM1 | cut -d' ' -f1`
	H_ALIAS=`echo $DUM1 | cut -d' ' -f2`
	if [ "`tolower $H_NAME`" != "`tolower $H_ALIAS`" ]
	then
	    echo "**WARNING: $H_ALIAS is an alias name for host $H_NAME."
	    echo "You cannot create credential for host alias."
	    get_yesno "Do you want to create the credential for $H_NAME?"
	    if [ $ANS = "y" -o $ANS = "Y" ]
	    then
		NEWNAME=$H_NAME
		LARG=$H_NAME
		HTYPE="TRUE"
	    else
		HTYPE="SKIP"    # for error message handling
	    fi
	else
	    HTYPE="TRUE"
	fi
    fi

    if nistest '[name='$LARG'],passwd.org_dir.'$DOMAIN;
    then
	if [ $HTYPE = "TRUE" ]
	then
	    echo "**ERROR: this name \"$LARG\" is in both the passwd and hosts tables."
	    echo "  You cannot have an username same as the hostname."
	    return 1
	fi
	UTYPE="TRUE"
    fi

    if [ $UTYPE = "TRUE" ]
    then
	TYPE="user"
    elif [ $HTYPE = "TRUE" ]
    then
	TYPE="host"
    else
	if [ $HTYPE != "SKIP" ]
	then
	    echo "**ERROR: invalid name \"$LARG\"."
	    echo "  It is neither an host nor an user name."
	fi
	return 1
    fi
}
#
# add_LOCALcred(): adds the LOCAL credential into the credential table.
#
add_LOCALcred()
{
    echo "adding LOCAL credential for $1..."

    DUMMY=`nismatch -P name=$1 passwd.org_dir.$DOM`
    if [ $? -ne 0 ]
    then
	return 1
    fi
    UID=`echo $DUMMY | cut -d: -f3`

    if [ $? -ne 0 ]
    then
	return 1
    fi
    $ECHO nisaddcred -p $UID -P $1.$DOM local $DOM
    return $?
}
#
# add_cred(): adds the credential.
#               $*  names to be added.
#
add_cred()
{
    while [ $# -ne 0 ]
    do
	NAME=$1
	check_type $NAME

	if [ $? -eq 0 ]
	then
	    if [ ! -z "$NEWNAME" ]
	    then
		NAME=$NEWNAME
	    fi

	    DUMMY=`nismatch $NAME.$DOMAIN cred.org_dir.$DOMAIN > /dev/null`
	    if [ $? -eq 0 ]
	    then
		if [ -z "$OWRITE" ]
		then
		    echo ... overwriting the existing entry for principal $NAME!
		else
		    echo ... principal $NAME already exist -- skipped!
		    shift
		    continue
		fi
	    fi

	    if [ $TYPE = "user" ]
	    then
		if add_LOCALcred $NAME;
		then
		    eval echo ... added LOCAL credential for $NAME. $VERB
		else
		    eval "echo ... could not add LOCAL credential for $NAME. $VERB"
		    TYPE="fail"
		fi
	    fi

	    if [ $TYPE != "fail" ]
	    then
		echo "adding DES credential for $1..."
		if [ -z $PASS ]
		then
		    LPASS="-l $PASS"
		else
		    LPASS=""
		fi
		if [ $TYPE = "user" ]
		then
		    $ECHO nisaddcred $LPASS -p unix.${UID}@$NODOT -P $NAME.$DOMAIN des $DOMAIN
		else
		    $ECHO nisaddcred $LPASS -p unix.$NAME@$NODOT -P $NAME.$DOMAIN des $DOMAIN
		fi
		if [ $? -eq 0 ]
		then
		    eval "echo ... added DES credential for $NAME. $VERB"
		else
		    eval "echo ... could not add DES credential for $NAME. $VERB"
		    TYPE="fail"
		fi
	    fi
	    echo ""

	    if [ $TYPE = "host" ]
            then
		DOIT=DOIT
	    elif [ $TYPE = "user" ]
	    then
		USERDOIT=DOIT
	    fi

	fi
	shift
    done
}

#
# insert_cred(): adds NIS+ client or principals credentials
#
insert_cred()
{
    if [ $# -eq 0 ]
    then
	echo "**ERROR: missing hostnames or usernames."
	print_usage
	exit 1
    fi

    if [ "$SECURE_LEVEL" = "0" ]
    then
	echo "**WARNING: it is not necessary to create NIS+ credentials"
	echo "  for unauthenticated users."
	return
    fi
    if [ "$SECURE_LEVEL" != "2" -a "$SECURE_LEVEL" != "x" ]
    then
	echo "**ERROR: invalid security level $SECURE_LEVEL."
    fi
    SECURE_LEVEL=2
    echo ""
    echo "You will be adding DES credentials in domain $DOMAIN for"
    echo $*
    echo ""
    if [ -z "$OWRITE" ]
    then
	echo "** nisclient will overwrite existing entries in the credential"
        echo "** table for hosts and users spedified above."
    else
	echo "** nisclient will not overwrite any existing entries in the"
	echo "** credential table."
    fi
    echo ""
    get_yesno $CONTINUE
    echo ""

    check_domain

    check_perm cred.org_dir.$DOMAIN
    if [ $? -ne 0 ]
    then
	echo "Sorry, no permission to create credentials!"
	exit 1
    fi
    echo ""

    add_cred $*

    if [ "$DOIT" = "DOIT" ]
    then
	if [ $GEN = "TRUE" ]
	then
	    $ECHO "echo '#!/bin/sh' > $GENFILE"
	    $ECHO "echo '#' > $GENFILE"
	    $ECHO "echo '' > $GENFILE"
	    $ECHO "echo "nisclient -i -h $SER_NAME -a $SER_ADDR -d $DOMAIN" > $GENFILE"
	fi
	echo "For all new NIS+ clients added, you will need to run the"
	echo "following on the client's machine:"
	echo "nisclient -i -h $SER_NAME -a $SER_ADDR -d $DOMAIN"
    fi

    if [ "$USERDOIT" = "DOIT" ]
    then
	echo ""
	echo "For all new NIS+ users added, you will need to update"
	echo "their keys on all machines that they are currently logged"
	echo "in by running keylogin(1), chkey(1), or nisclient(8)."
    fi
}
#
####### Init User #################
#
# init_user(): initializes user
#
init_user()
{
    eval "echo initializing user information... $VERB"
    WHO=`id | sed -e "s/uid=[0-9]*(\([^ )]*\)).*/\1/"`
    if [ $WHO = "root" ]
    then
	echo "**ERROR: You cannot use the -u option as a root user."
        print_usage
	exit 1
    fi

    if [ "$SECURE_LEVEL" = "2" ]
    then
	eval "echo -S 2 option specified, setting up security... $VERB"
	setup_security user
	eval "echo User initialization completed!! $VERB"
    elif [ "$SECURE_LEVEL" = "0" ]
    then
	echo "**WARNING: it is not necessary to initialize NIS+ users"
	echo "  for unauthenticated users."
    elif [ "$SECURE_LEVEL" = "x" ]
    then
	WHO=`id | sed -e "s/uid=[0-9]*(\([^ )]*\)).*/\1/"`
	if nistest '[cname='$WHO.$DOMAIN'],cred.org_dir'.$DOMAIN;
	then
	    eval "echo credential exists for setting up security... $VERB"
	    setup_security user
	    eval "echo User initialization completed!! $VERB"
	else
	    echo "**WARNING: you do not have NIS+ credentials."
	    echo "  You can either use NIS+ service as an unauthenticated user"
	    echo "  or ask your network administrator to create a credentital for you."
	fi
    fi
}
#
# check_domainname(): check validity of a domain name.  Currently we check
#       that it has at least two components.
#               $1  the domain name to be checked
#
check_domainname()
{
    if [ ! -z "$1" ]
    then
	t=`$EXPR "$1" : '[^.]\{1,\}[.][^.]\{1,\}'`
	if [ "$t" = 0 ]
	then
	    echo '**ERROR: invalid domain name ('$1')'
	    echo '  It must have at least two components.'
	    echo '  For example, "company.com.".'
	    print_usage
	    exit 1
	fi
    fi
}
#
####### Main function #############
#
init

parse_arg $*
shift $?

check_domainname "$DOMAIN"

case $ACTION in
"init")
    init_client;;
"user")
    init_user;;
"create")
    insert_cred $*;;
"restore")
    restore;;
*)
    echo "**ERROR: you must specify one of the these options: -c, -i, -u, -r."
    print_usage
    exit 1
esac
