#! /bin/sh
#
# this gathers all password files into one location
# and records lines that have changed since this was done
#
# USAGE
#	gendict [ options ] [ files ... ]
# generates an alphabetized system dictionary.  Options are:
#	-l n	truncate all entries at n characters
#	-t how	apply the given transformation:
#			identity	as in file
#			cap		all letters capitalized
#			low		all letters lowercase
#			fcap		first letter capitalized
#			0 .. 9		append 0 .. 9
#			reverse		reversed
#			rcap		cap, reversed
#			rlow		low, reversed
#			rfcap		fcap, reversed
#			r0 .. r9	append 0 .. 9, reversed
#	-p	the files following are password files
#	-w	the files following are word list files
#	-o dict	save the dictionary (output) as file dict
#	-P prog	apply prog to each password file, using the file as
#		standard input and putting the standard output into
#		the dictionary
#	-W prog	apply prog to each word list file, using the file as
#		standard input and putting the standard output into
#		the dictionary
#
#################################################################
# Copyright notice.						#
# This software is copyrighted (c) 1991 by Matt Bishop and the	#
# Trustees of Dartmouth College.  All rights reserved.		#
# 								#
# Author:	Matt Bishop					#
# Address:	Department of Mathematics and Computer Science	#
#	 	Dartmouth College				#
# 		Hanover, NH  03755-1831				#
# 		USA						#
# telephone:	+1 603 646 3267					#
# fax:		+1 603 646 1312					#
# internet:	Matt.Bishop@dartmouth.edu			#
# usenet:	...!decvax!dartvax!Matt.Bishop			#
#################################################################
#
# PARAMETERS -- changing these affects how the program works
VERSION="Version GAMMA 6/31/91 Matt.Bishop@dartmouth.edu"	# version
PATH=%%BINDIR%%:/bin:/usr/bin:/usr/ucb	# search path
DICT=					# output dictionary
FORCE=no				# force regeneration if yes
HOW=					# what transformations to apply
LENGTH=8				# number of characters
TMP=gen$$				# temporary file for word lists
WORDPROG=				# apply to word list files
PWDPROG=				# apply to password files
# VARIABLES -- the program will change these
# i=					# temporary in various loops
# x=					# holds part of option after flag
flag=					# for options with args
type=list				# is file pwd or word list?
sedexpr=				# holds RE matching of length LENGTH
lists=					# word lists
pwd=					# password files
remake=no				# do not remake dict unless needed
findlist=				# used to list pwd files
#
# process signals
#
trap "rm -f $TMP.1 $TMP.2; exit 2" 1 2 3 15
#
# process arguments
#
for i in $*
do
	# this is an argument to an option; stuff it and loop
	if test -n "$flag"
	then
		case $flag in
		l)	LENGTH="$i" 	;;	# -l ...
		o)	DICT="$i"   	;;	# -o ...
		P)	PWDPROG="$i"  	;;	# -P ...
		t)	HOW="$i"    	;;	# -t ...
		W)	WORDPROG="$i"  	;;	# -W ...
		esac
		flag=
		continue
	fi
	# this is an option or a file name
	case $i in
	-f)	remake=yes			# force reconstruction
		;;
	-l*)	x=`expr "$i" : '-l\(.*\)'`	# max length
		if test -n "$x"
		then
			LENGTH="$x"
		else
			flag=l
		fi
		;;
	-o*)	x=`expr "$i" : '-o\(.*\)'`	# dictionary name
		if test -n "$x"
		then
			DICT="$x"
		else
			flag=o
		fi
		;;
	-p)	type=pwd			# password file
		;;
	-P*)	x=`expr "$i" : '-P\(.*\)'`	# password file transformer
		if test -n "$x"
		then
			PWDPROG="$x"
		else
			flag=P
		fi
		;;
	-t*)	x=`expr "$i" : '-t\(.*\)'`	# transformation
		if test -n "$x"
		then
			HOW="$x"
		else
			flag=t
		fi
		;;
	-w)	type=list			# word list
		;;
	-W*)	x=`expr "$i" : '-W\(.*\)'`	# word list transformer
		if test -n "$x"
		then
			WORDPROG="$x"
		else
			flag=W
		fi
		;;
	*)	if test "$type" = list		# file
		then
			lists="$lists $i"
		elif test "$type" = pwd
		then
			pwd="$pwd $i"
		fi
		;;
	esac
done
# be sure no outstanding args are required
if test -n "$flag"
then
	echo "$0: option -$flag requires an argument" 1>&2
	exit 1
fi
# be sure length is set to something suitable
if test \( `expr "$LENGTH" : '^[0-9][0-9]*'` -eq 0 \) -o \( "$LENGTH" -le 0 \)
then
	echo "$0: option -l requires a positive, numeric argument" 1>&2
	exit 1
fi
# build the pattern to match strings of length LENGTH
sedexpr=
while test $LENGTH -gt 0
do
	sedexpr=".$sedexpr"
	LENGTH=`expr $LENGTH - 1`
done
#
# now see if we have to rebuild the dictionary
# we do if any of the following hold:
#	1. the dictionary is the standard output
#	2. the dictionary does not exist
#	3. any of the input files have been modified more
#		recently than the dictionary file
if test \( $remake = yes \) -o \( -z "$DICT" \) -o \( ! -f "$DICT" \)
then
	remake=yes
else
	for i in $lists $pwd
	do
		findlist="$findlist -newer $i"
	done
	if test -n "`find $DICT $findlist -print`"
	then
		remake=yes
	fi
fi
if test "$remake" = no
then
	echo "$DICT up to date; to force remake, give -f flag"
	exit 0
fi
#
# now munge the password files into a temporary list file
# we want:	account name
#		UID
#		GID
#		each field of the GECOS structure
#		home directory base name
#
cp /dev/null $TMP.1
for i in $pwd
do
	awk -F: '{ printf "%s\n%s\n%s\n", $1, $3, $4 ; }' < $i >> $TMP.1
	awk -F: '{ print $5 } ' < $i | tr -cs 'A-Za-z0-9.\-' '\012' >> $TMP.1
	awk -F: ' { print $6 } ' < $i | tr -s '/' '\012' >> $TMP.1
	if test -n "$PWDPROG"
	then
		$PWDPROG $i >> $TMP.1
	fi
done
cp /dev/null $TMP.2
for i in $lists
do
	if test -n "$WORDPROG"
	then
		$WORDPROG $i >> $TMP.2
	fi
done
lists="$TMP.1 $TMP.2 $lists"
#
# the heart -- translate everything as requested and 
# save it in a dictionary (or send it to the standard output)
#
if test -n "$DICT"
then
	trans $HOW $lists | \
		sed -e "/^[ 	]*$/d" -e "s/^\($sedexpr\).*$/\1/" | \
			sort | uniq > $DICT
else
	trans $HOW $lists | \
		sed -e "/^[ 	]*$/d" -e "s/^\($sedexpr\).*$/\1/" | \
			sort | uniq
fi
rm -f $TMP.1 $TMP.2
exit 0
