#!/bin/sh

#
# User password script
# Copyright 1989, Frame Technology Corporation
#

#
# checkdate date
#	Ask the date a few routine questions.
#	Return 0 if it's OK, print diagnostic and return nonzero otherwise.
#
checkdate() {
	case $1 in
	[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])
		;;
	*)
		echo "Invalid date: $1"
		return 1
		;;
	esac
	dd=`expr $1 : '\(..\).*'`
	mm=`expr $1 : '..\(..\).*'`
	yy=`expr $1 : '....\(....\)'`
	if [ $yy -lt 1989 -o $yy -gt 2222 ]; then
		echo "Invalid year: $yy"
		return 1
	fi
	case $mm in
	02)		# leap year checking
		case `expr $yy % 4 = 0 \& $yy % 100 != 0 \| $yy % 400 = 0` in
		0) upb=28;;
		*) upb=29;;
		esac
		;;
	0[13578]|1[02])
		upb=31
		;;
	0[469]|11)
		upb=30
		;;
	*)
		echo "Invalid month: $mm"
		return 1
		;;
	esac
	if [ $dd -lt 1 -o $dd -gt $upb ]; then
		echo "Invalid day of month $mm: $dd"
		return 1
	fi
	return 0
}


# Remove temporary files.
cleanup() {
	[ $TF$TF1$XF$PFLCK ] && {
		rm -f $TF $TF1 $XF $PFLCK
		TF= TF1= XF= PFLCK=
	}
}


#
# get variable prompt
#	Prompt user, then read variable
#	Return
#		2	EOF
#		1	empty line
#		0	anything else
#
get() {
	eval $1=
	echo -n "$2: "
	if read getTMP; then
		if [ ! -z "$getTMP" ]; then
			eval $1="'$getTMP'"
			return 0
		fi
		return 1
	fi
	return 2
}


#
# Establish the password file that we'll be editing.
#
getPF() {
	# Loop around trying to find a password file.
	# Each time we try and fail, we call getPFstrike().
	# After 2 strikes (2 being the number of different
	# framepasswd files), we're out.
	PF= PFLCK=
	strikes=2
	until [ $PF ]; do
		if [ ! -d $HOME/.fminit2.0 ]; then
			boojum=$FMHOME/.fminit2.0/$FPASS
			getPFstrike
			echo "Using $boojum"
		else
			getPFprompt; read boojum || quit
			case $boojum in
			1) boojum=$HOME/.fminit2.0/$FPASS;;
			2) boojum=$FMHOME/.fminit2.0/$FPASS;;
			q) PF= PFLCK=; quit;;
			*) continue;;
			esac
		fi
		# Set $PF and check its plausibility.
		PF=$boojum
		PFLCK=$PF.lck
		if [ -f $PF ]; then
			if [ ! -r $PF ]; then
				echo "You don't have permission to read $PF"
				PF= PFLCK=
				getPFstrike
				continue
			fi
			if [ ! -w $PF ]; then
				echo "You don't have permission to write $PF"
				PF= PFLCK=
				getPFstrike
				continue
			fi
		fi
		# Check existing lock.
		if [ -f $PFLCK ]; then
			echo "$PF is currently locked another user."
			ls -l $PFLCK
			PF= PFLCK=
			getPFstrike
			continue
		fi
		# Try to lock $PF.
		>$PFLCK || {
			echo "Unable to lock $PF."
			PF= PFLCK=
			getPFstrike
			continue
		}
		chmod 0600 $PFLCK
	done
}


getPFprompt() {
	echo -n "Enter
1	to edit your personal $FPASS file
	($HOME/.fminit2.0/$FPASS)
2	to edit the installation-wide file
	($FMHOME/.fminit2.0/$FPASS)
q	to quit
Selection: "
}


getPFstrike() {
	strikes=`expr $strikes - 1`
	[ $strikes -le 0 ] && {
		echo "Can't establish a $FPASS file, exiting."
		exit 3
	}
}


getPRODUCT() {
	echo "Enter the product name, which should be one of
	maker
	imaker
	viewer
	writer"
	PRODUCT=
	until [ $PRODUCT ]; do
		echo -n "Product name [maker]: "; read boojum || quit
		case $boojum in
		''|[Mm][Aa][Kk][Ee][Rr]) PRODUCT=maker;;
		[Ii][Mm][Aa][Kk][Ee][Rr]) PRODUCT=imaker;;
		[Vv][Ii][Ee][Ww][Ee][Rr]) PRODUCT=viewer;;
		[Ww][Rr][Ii][Tt][Ee][Rr]) PRODUCT=writer;;
		esac
	done
	PRODUCT=`mapc $PRODUCT`
}


getPT() {
	echo "Enter the password type, which should be either
	P	permanent password
	T	temporary password"
	PT=
	until [ $PT ]; do
		echo -n "Password type (P/T) [P]: "; read boojum || quit
		case $boojum in
		''|[Pp]*) PT=P;;
		[Tt]*) PT=T;;
		esac
	done
}


getSDATE() {
	SDATE=
	case $PT in
	P)
		echo "Enter the license's support (SUP) date."
		dt=Support
		;;
	T)
		echo "Enter the license's expiration date."
		dt=Expiration
		;;
	esac
	until [ $SDATE ]; do
		echo -n "$dt date (ddmmyyyy): "; read boojum || quit
		checkdate $boojum && SDATE=$boojum
	done
	SDATE=`mapc $SDATE`
}


greetuser() {
	echo "
-----------------------------------------------------------------------
This script adds entries to the fixed-licensing password file,
$FPASS.  Each entry in the file contains
	a license type (either permanent or temporary);
	a product name (maker, imaker, etc.);
	the expiration/support date of the license;
	the host ID to which the license belongs;
	the password.
First, the script will ask you whether you want to modify the
$FPASS in your local directory (~/.fminit2.0/$FPASS)
or the system-wide one in
$FMHOME/.fminit2.0/$FPASS.
Next, it will prompt you to determine the license type,
product name and support date.
Finally, it will ask you for a series of hostids and passwords.
Each of these hostid/password pairs will be used to create a
license file entry with the given type, product name, and support date.
-----------------------------------------------------------------------
"
}


#
# mapc arg
#	Replicate the password character mapping scheme
#
mapc() {
	echo $1 | tr abcdefghijklmnopqrstuvwxyzO/ ABCDEFGHIJKLMN0PQRSTUVWXYZ0.
}


#
# merge
#	Merge the hostid/product pairs from $XF into $TF
#	Kind of a dumb algorithm, but |$XF| should be small, we hope.
#
merge() {
	echo -n "Merging password files... "
	(
		while read hostid password; do
			# Replace all hostid/product pairs.
			setA $hostid $password
			( grep -v '^[PT]'/$hostid/$PRODUCT < $TF; echo $A ) > $TF1
			mv $TF1 $TF
		done
	) < $XF
	echo "done."
}


#
# printPF
#	Print out all of $PF's password entries for the current host
#
printPF() {
	echo "
The hostid for this machine (`hostname`) is $MHID"
	grep -v '^#' $PF | grep $MHID >$TF1
	if [ -s $TF1 ]; then (
		echo "
$PF password entries for host $MHID:"
		exec 0<$TF1
		while read printPFa; do
			oIFS="$IFS"; IFS=' /
';
			set -$- $printPFa
			IFS="$oIFS"
			printPFent $*
		done
	)
	fi
	echo " "
}


#
# printPFent $PT hostid $PRODUCT $SDATE password
#	Show user the PT, PRODUCT, and SDATE from a single password entry
#
printPFent() {
	echo -n "	Product $3 -- "
	case $1 in
	P)
		echo -n "permanent license: support ";;
	T)
		echo -n "temporary license: expiration ";;
	esac
	echo "date $4"
}


quit() {
	echo "
Bye!"
	exit 2
}


#
# Read hostid/password pairs from the user until done.
# The file $XF will contain lines of the form
#		hostid password
#
readpairs() {
	XF=/tmp/fm_passw$$
	>$XF
	echo "Now give the host IDs and passwords that you want to license.
Type control-D or a blank line when you're done."
	while get hostid "Host ID" && get password "Password"; do
		mapc "$hostid $password" >> $XF
	done
	echo "    "
}


#
# setA hostid password
#	Set the global variable A with the value of a line to be written into
#	the password file.
#
setA() {
	A="$PT/$1/$PRODUCT/$SDATE/$2/"
}


verifyconstants() {
	echo "
You are editing the $FPASS file
$PF, adding passwords for"
	printPFent $PT . $PRODUCT $SDATE .
	yes "OK to continue" y
}


#
# yes prompt def
#	Print prompt and get yes/no answer from user.
#	If he hits carriage return, use default value.
#
yes() {
	echo -n "$1? (y/n/q) [$2]: "
	read boojum || quit
	[ -z "$boojum" ] && boojum="$2"
	case $boojum in
	[Yy]*)	return 0 ;;
	[Qq]*)	quit ;;
	*)		return 1 ;;
	esac
}


##
## Main program.
##

Program=`basename $0`
FPASS=framepasswd
HID=`hostid`
MHID=`mapc $HID`
trap 'exit 1' 1 2 3 15
trap cleanup 0

while :; do
	TF=/tmp/pwjunk$$ TF1=/tmp/1pwjunk$$
	greetuser

	#
	# Which file are you editing?
	#
	getPF
	if [ -f $PF ]; then
		cp $PF $TF
	else
		>$TF
	fi

	printPF

	# Set up the "constants":
	getPT			#	PT	password type (permanent/temporary)
	getPRODUCT		#	PRODUCT
	getSDATE		#	SDATE	relevant date

	# Let user check his work.
	if verifyconstants; then
		break
	else
		cleanup
	fi
done

#
# Read hostid/password pairs from user and stow them in $XF.
#
readpairs

#
# Merge $XF back into $TF.
# Then establish a new $PF
#
merge
trap '' 1 2 3 15				# disable signals
[ -f $PF ] && mv $PF $PF.BAC	# take a backup
mv $TF $PF
exit 0
