#!/bin/tcsh -f
# JLdL 04Jul07.
#
# Copyright (C) 2005-2007 by Jorge L. deLyra <delyra@fma.if.usp.br>.
# This program may be copied and/or distributed freely. See the
# _ terms and conditions in /usr/share/doc/<package>/copyright.
#
# This program recovers the complete set of members of a NIS netgroup
# _ or set of netgroups, including the members of possible component
# _ sub-netgroups included as members of the original netgroups; the
# _ program will recurse until it has resolved all the netgroups into
# _ non-netgroup members; by default it returns the hostnames, but
# _ it may also return the usernames of the netgroup members.
#
# Record the name this script was called with.
set name = `basename $0`
#
# The default is to return hostnames.
set mode = byhost
#
# There is no default netgroup.
set grps = ""
#
# Process the command-line arguments.
foreach cla ( $* )
    #
    # Detect options.
    if ( "`echo -n $cla | cut -c 1`" == "-" ) then
	#
	# Now process the options.
	switch ( "$cla" )
	case --help:
	    #
	    # Print a usage message.
	    echo "usage: $name [(-h|--host)|(-u|--user)] <netgroup> ..."
	    echo "       -h: return the list of hostnames of the members;"
	    echo "       -u: return the list of usernames of the members;"
	    echo "       list the members of one ore more NIS netgroups;"
	    echo "       each <netgroup> must be an existing netgroup;"
	    echo "       in order to get the details run 'man $name'"
	    exit 0
	    breaksw
	case -h:
	case --host:
	    #
	    # Set the mode to return hostnames.
	    set mode = byhost
	    breaksw
	case -u:
	case --user:
	    #
	    # Set the mode to return usernames.
	    set mode = byuser
	    breaksw
	default:
	    #
	    # Print an error message.
	    echo "${name}: ERROR: unknown option $cla; try --help to get help"
	    exit 1
	    breaksw
	endsw
    #
    # Process non-option arguments.
    else
	#
	# Get the arguments of the program.
	set grps = ( $grps $cla )
    endif
end
#
# Check whether NIS is available and running.
ypwhich >& /dev/null
if ( $status != 0 ) then
    echo "${name}: ERROR: the NIS system is not responding"
    exit 1
endif
#
# Sort and unique the argument list.
set grps = ( `echo $grps | tr " " "\n" | sort -u` )
#
# Check for the necessary netgroup argument(s).
if ( "$grps" == "" ) then
    echo "${name}: ERROR: argument(s) needed: netgroup(s)"
    exit 1
endif
#
# Step 1: iterate in order to find all the component netgroups.
#
# Raise the outer-loop flag.
set goon = 1
#
# Initialize a variable for the increasing set of netgroups.
set adon = ( $grps )
#
# Loop while the flag is up.
while ( $goon )
    #
    # Loop over the current set of netgroups.
    foreach grp ( $grps )
	#
	# Check for an incorrect netgroup name.
	ypmatch $grp netgroup > /dev/null
	set errstt = $status
	if ( $errstt != 0 ) then
	    echo "${name}: ERROR above in ypmatch"
	    exit $errstt
	endif
	#
	# Select the members of the current netgroup which are not
	# _ within parenthesis, they are the component netgroups.
	set temp = `ypmatch $grp netgroup | tr " " "\n" | grep -v '(.*)'`
	#
	# If there are any, then add the netgroups found in this
	# _ instance of the inner loop to the list of netgroups.
	if ( "$temp" != "" ) then
	    set adon = ( $adon $temp )
	endif
    end
    #
    # We must sort and unique the list here or there may be an
    # _ "word too long" error in the "if" statement below.
    set adon = ( `echo $adon | tr " " "\n" | sort -u` )
    #
    # Verify whether the list of netgroups has increased.
    if ( "$adon" != "$grps" ) then
	#
	# If it has, then pass it back to the original variable.
	set grps = ( $adon )
    else
	#
	# If it has not, then lower the loop flag,
	# _ in order to stop the outer loop.
	set goon = 0
    endif
end
#
# Step 2: find all the members of all netgroups and component netgroups.
#
# Initialize the list of members.
set mbrs = ""
#
# Loop over the complete set of netgroups and component netgroups.
foreach grp ( $grps )
    #
    # Select the members of the current netgroup which are within
    # _ parenthesis, they are the non-netgroup members.
    set temp = `ypmatch $grp netgroup | tr " " "\n" | grep '(.*)'`
    #
    # If there are any, then add the set to the list of members.
    if ( "$temp" != "" ) then
	set mbrs = ( $mbrs $temp )
    endif
end
#
# Sort and unique the list of members.
set mbrs = ( `echo $mbrs | tr " " "\n" | sort -u` )
#
# Cut out the relevant information.
if ( "$mode" == "byhost" ) then
    #
    # Cut out the hostnames.
    set mbrs = ( `echo $mbrs | tr " " "\n" | cut -d\( -f2 | cut -d, -f1` )
else
    #
    # Cut out the usernames.
    set mbrs = ( `echo $mbrs | tr " " "\n" | cut -d\( -f2 | cut -d, -f2` )
endif
#
# Return the list of members.
echo $mbrs | tr " " "\n"
