#
#  @(#)np-interface.sh  1.46 99/12/08
#  Copyright 1995 Sun Microsystems, Inc.  All Rights Reserved.
#

###########
##
## NeWSprint printer interface program.
##
###########

trap 'log_pagecount;
	kill `cat ${SPOOLDIR}/.serverid` ;
	exit 0' 15

wait_for_handler_exit () {
    handler_process=`cat ${SPOOLDIR}/.handlerid`
    while kill -0 $handler_process 2>/dev/null
    do
        sleep 2
    done
}

catch_hangup () {
	if [ -n "${LPTELL}" ]
	then
# use lp.tell in its original form with no params here.
		echo \
"The connection to the printer dropped; perhaps the printer went off-line?" \
		| ${LPTELL} -l ${printer}
	fi
	return 0
}
catch_interrupt () {
	if [ -n "${LPTELL}" ]
	then
# use lp.tell in its original form with no params here.
		echo \
"Received an interrupt from the printer.  The reason is unknown,
although a common cause is that the baud rate is too high." \
		| ${LPTELL} -l ${printer}
	fi
	return 0
}
trap 'catch_hangup; exit_code=129 exit 129' 1
trap 'catch_interrupt; exit_code=129 exit 129' 2 3

exec 5>&2 2>/dev/null 3>&1

: ${TEMPORARYDIR:=/tmp}
: ${TERMINFO:=/usr/lib/terminfo}
: ${LOCALPATH:=/usr/spool/lp/bin}

PATH="/bin:/usr/bin:${LOCALPATH}"

TMPPREFIX=${TEMPORARYDIR}/`uname -n`$$
TMPERRFILE=${TEMPORARYDIR}/lptell.$$

trap 'rm -fr ${TMPPREFIX}*; rm -fr ${TMPERRFILE}; exit ${exit_code}' 0

#####
# ${LPTELL} 
#####
if [ ! -x "${LPTELL:=${LOCALPATH}/lp.tell}" ]
then
	fake_lptell () {
		header="no"
		while read line
		do
			if [ "no" = "${header}" ]
			then
				errmsg ERROR ${E_IP_UNKNOWN} \
		"unknown printer/interface failure" \
		"consult your system administrator;
		reasons for failure (if any) follow:"
				header=yes
			fi
			echo "${line}" >&2
		done
		return 1
	}
	LPTELL=fake_lptell
fi

#####
# ${DRAIN} 
#####
if [ -x "${LOCALPATH}/drain.output" ]
then
	DRAIN="${LOCALPATH}/drain.output 5"	# wait only five seconds
else
	DRAIN=
fi

#####
# ${LPCAT} 
#####
if [ ! -x "${LPCAT:=${LOCALPATH}/lp.cat}" ]
then
	LPCAT="cat"
fi

TPUT=tput

#####
# Error message formatter:
#####

LP_ERR_LABEL="UX:lp"

E_IP_ARGS=1
E_IP_OPTS=2
#E_IP_FILTER=3
E_IP_STTY=4
E_IP_UNKNOWN=5
E_IP_BADFILE=6
#E_IP_BADCHARSET=7
E_IP_BADCPI=8
E_IP_BADLPI=9
E_IP_BADWIDTH=10
E_IP_BADLENGTH=11
E_IP_ERRORS=12		# (in slow.filter)

errmsg () {
	case $1 in
	ERROR )
		sev="  ERROR";
		;;
	WARNING )
		sev="WARNING";
		;;
	esac
#	tag=`expr "${LP_ERR_LABEL}" : "\(.*\):"``expr "${LP_ERR_LABEL}" : ".*:\(.*\)"`
	echo "${LP_ERR_LABEL}: ${sev}: $3
        TO FIX: $4" >&5
}


###########
##
## Check arguments
###########

parse () {
	echo "`expr \"$1\" : \"^[^=]*=\(.*\)\"`"
}

###########
##
## Prints out error pages
###########
print_errors()
{
	if [ -s $errfile  ] && [ "$PRINTJOBLOG" = "yes" ]
	then
		errfile2=/tmp/err.${i}.$$.${i}
		errfilter $errfile > $errfile2
		echo "User: "${Job_User}'@'${Job_Host} >> $LOGFILE
		date | sed -e 's/^/Date of previous error: /' -e p -e 's/./-/g' >> $LOGFILE
		if [ -s $errfile2 ]
		then
			(  0<${errfile2} eval $PL --r $ERRCMD 2>&1 1>&3
#			   no longer kill the server (4/93)
#			   kill `cat ${SPOOLDIR}/.serverid`
			) | ${LPTELL} -l ${printer}

			if [ -f /tmp/libaio.log ]; then
                                rm -f /tmp/libaio.log
                        fi
		fi
		rm -f $errfile2
	fi

	rm -f $errfile 

}

###########
##
## logs the page count
###########
log_pagecount()
{
        trap 15 'echo >/dev/null' # don't trap here 

        acctfile="${SPOOLDIR}/acct"
        pgcnt="${SPOOLDIR}/.pgcnt"

        if [ ! -f $acctfile ]
        then
                touch $acctfile
                chown lp $acctfile
                chgrp lp $acctfile
                chmod 666 $acctfile
        fi

        wait_for_handler_exit
        if [ -w $acctfile ] && [ -r $pgcnt ]; then
                if [ -z "$Job_Host" ]; then
                        echo "`cat $pgcnt`  $Job_User	$Job_Job	$Job_Printer	$Job_Date" >>$acctfile
                else
                        echo "`cat $pgcnt`  ${Job_Host}:${Job_User}	$Job_Job	$Job_Printer	$Job_Date" >>$acctfile
                fi
                /bin/rm -f $pgcnt
        fi
}
 
###########
##
## gets the directory name 
###########
dir_name()
{
    expr \
      ${1-.}'/' : '\(/\)[^/]*//*$' \
      \| ${1-.}'/' : '\(.*[^/]\)//*[^/][^/]*//*$' \
      \| .
}

PARAM=.param
SPOOLDIR="/etc/lp/printers/`basename $0`"
. ${SPOOLDIR}/$PARAM
ARCH=`$NPHOME/admin/share/binarytype`; export ARCH
# source the printer's .param file in the spool directory
. ${SPOOLDIR}/$PARAM

PATH=$PATH:$NPHOME/pl.$ARCH/bin:$NPHOME/np/bin.$ARCH:$NPHOME/spoolers/lp; export PATH

pl_result=0;

if [ -z "$NPTMP" ];then
        NPTMP="/tmp"
fi

if [ $DEBUGSCRIPTS ];then
        PL='pl --m 3'
        set -x
else
        PL=pl 
fi
 
#####
#
# This program is invoked as
#
# ${SPOOLDIR}/.../printer request-id user title copies options files...
#
# The first three arguments are simply reprinted on the banner page,
# the fourth (copies) is used to control the number of copies to print,
# the fifth (options) is a blank separated list (in a single argument)
# of user or Spooler supplied options (without the -o prefix),
# and the last arguments are the files to print.
#####

if [ $# -lt 5 ]
then
	errmsg ERROR ${E_IP_ARGS} \
		"wrong number of arguments to interface program" \
		"consult your system administrator"
	exit 1
fi

printer=`basename $0`; export printer
request_id=$1; export request_id
user_name=$2; export user_name
title=$3; export title
copies=$4
option_list=$5

shift 5
files="$*"

nobanner="no"; export nobanner
nofilebreak="no"
stty=

inlist=
for i in ${option_list}
do
	case "${inlist}${i}" in


	nobanner )
		nobanner="yes"
		;;

	nofilebreak )
		nofilebreak="yes"
		;;

	#####
	#
	# If you want to add simple options (e.g. -o simple)
	# identify them here.
	#####
#	simple )
#		simple="yes"
#		;;


	cpi=pica )
		cpi=10
		;;
	cpi=elite )
		cpi=12
		;;
	cpi=* )
		cpi=`parse ${i}`
		;;

	lpi=* )
		lpi=`parse ${i}`
		;;

	length=* )
		length=`parse ${i}`
		;;

	width=* )
		width=`parse ${i}`
		;;

	#####
	#
	# If you want to add simple-value options (e.g. -o value=a)
	# identify them here.
	#####
#	value=* )
#		value=`parse ${i}`
#		;;


	#####
	#
	# If you want to add options that, like "stty",
	# take a list (e.g. -o lopt='a b c'), identify
	# them here and below (look for LOPT).
	#####
	stty=* | flist=* | lpd=* )
#LOPT	stty=* | flist=* | lpd=* | lopt=* )

		inlist=`expr "${inlist}${i}" : "^\([^=]*=\)"`
		case "${i}" in
		${inlist}\'*\' )
			item=`expr "${i}" : "^[^=]*='*\(.*\)'\$"`
			;;
		${inlist}\' )
			continue
			;;
		${inlist}\'* )
			item=`expr "${i}" : "^[^=]*='*\(.*\)\$"`
			;;
		${inlist}* )
			item=`expr "${i}" : "^[^=]*=\(.*\)\$"`
			;;
		*\' )
			item=`expr "${i}" : "^\(.*\)'\$"`
			;;
		* )
			item="${i}"
			;;
		esac

		#####
		#
		# We don't dare use "eval" because a clever user could
		# put something in an option value that we'd end up
		# exec'ing.
		#####
		case "${inlist}" in
		stty= )
			stty="${stty} ${item}"
			;;
		flist= )
			flist="${flist} ${item}"
			;;
		lpd= )
			lpd="${lpd} ${item}"
			;;
#LOPT		lopt= )
#LOPT			lopt="${lopt} ${item}"
#LOPT			;;
		esac

		case "${i}" in
		${inlist}\'*\' )
			inlist=
			;;
		${inlist}\'* )
			;;
		*\' | ${inlist}* )
			inlist=
			;;
		esac
		;;

	* )
		errmsg WARNING ${E_IP_OPTS} \
			"unrecognized \"-o ${i}\" option" \
			"check the option, resubmit if necessary
		printing continues"
		;;
	esac
done

#####
#
# Additional ``parameters'' are passed via Shell environment
# variables:
#
#	TERM	The printer type (used for Terminfo access)
#####

#####
# Set defaults for unset variables.
#####

: ${TERM:=unknown}
tput lines 1>/dev/null 2>&1 || TPUT=:

###########
##
## Initialize the printer port
###########

stty1= stty2=
tty 0<&1 1>/dev/null 2>&1 && {

	#####
	#
	# First set the default parameters,
	# then the requested parameters.
	#####

	if [ -n "${stty}" ]
	then
		if stty ${stty} 0<&1 1>/dev/null 2>&5
		then
			:
		else
			errmsg ERROR ${E_IP_STTY} \
				"stty option list failed" \
				"check the \"-o stty\" option you used,
		or consult your system administrator"
			exit 1
		fi
	else
		stty 9600 0<&1 2>/dev/null 1>&2
	fi

	stty \
		-parity \
		ixon -ixany \
		-opost \
			0<&1 2>/dev/null 1>&2
#	stty \
#		cs8 -cstopb -parenb -parodd \
#		ixon -ixany \
#		opost -olcuc onlcr -ocrnl -onocr -onlret -ofill \
#		nl0 cr0 tab0 bs0 vt0 ff0 \
#			0<&1 2>/dev/null 1>&2
}

###########
##
## Initialize the physical printer (Part I).
## Here we bring the printer to a sane state and set the page size.
###########

CR=`${TPUT} cr`
[ -z "${CR}" ] && CR="\r"

FF=`${TPUT} ff`

NL="${CR}\n"

lines=`${TPUT} lines`
[ -z "${lines}" -o 0 -ge "${lines}" ] && lines=66

#####
#
# Some printers need to have the banner page filtered.
#####
case "${TERM}" in

PS | PSR )
	banner_filter="$PL --r :npcomm"
	;;

esac

if [ -n "${banner_filter}" ]
then
	banner_filter="| ${banner_filter}"
fi

#####
#
#this prints out the banner page for cancelled jobs
#trap 'eval canceled ${banner_filter}; exit_code=0 exit' 15
#need to sleep to avoid lp printer fault on open device (job cancel)
#####
#trap 'sleep 10; \
#	kill -9 `cat ${SPOOLDIR}/.handlerid` 1>/dev/null 2>&1; \
#	exit_code=0 exit' 15

# trap 'exit_code=0 exit' 15

###########
##
## Setup the banner page
###########

setup_banner () {

	JOBFILE="${SPOOLDIR}/job.data"

	Job_Printer=`echo ${request_id} | sed 's/\-.*//'` 
	Job_Host=`echo ${user_name} | sed 's/\!.*//'` 
    	Job_User=`echo ${user_name} | sed 's/.*\!//'` 
	if [ "${title}" != "" ]
	then
		Job_Job=`echo "${title}" | sed -n '1p'`
	else
		Job_Job=`echo ${files} | sed 's/ .*//' | sed 's/.*\///'`
	fi
	Job_Date=`date '+%a %h %d %H:%M:%S %Y'`
echo "Printer $Job_Printer
Host $Job_Host
User $Job_User
Job $Job_Job
Date $Job_Date
" > $JOBFILE

	chown lp $JOBFILE
	chgrp lp $JOBFILE
	chmod 666 $JOBFILE

}

###########
##
## Setup the pl call
###########
 
setup_plcall () {

        Job_Id=`echo "${request_id}" | sed 's/.*\-//'`-0
        Jobfile="/var/spool/lp/tmp/${Job_Host}/${Job_Id}"

        if [ -f "${Jobfile}" ]
        then
		content_type=`${NPHOME}/spoolers/lp/getcontent ${Jobfile}`
		if [ -z "$content_type" ]
		then
			content_type="simple"
		fi
        else
                content_type="simple"
        fi

        case $content_type in
                ditroff | otroff | ascii )
                        if [ $nobanner = no ]; then
                                PLCMD="--k $content_type $PLCMD_BANNER"
                        else
                                PLCMD="--k $content_type $PLCMD_NOBANNER"
                        fi
                        ;;
                PS | postscript | ps )
                        if [ $nobanner = no ]; then
                                PLCMD="--k ps $PLCMD_BANNER"
                        else
                                PLCMD="--k ps $PLCMD_NOBANNER"
                        fi
                        ;;
                plot )
                        if [ $nobanner = no ]; then
                                PLCMD="--k $content_type $PLCMD_BANNER"
                        else
                                PLCMD="$PLOTCMD_NOBANNER"
                        fi
                        ;;
                simple )
                        if [ $nobanner = no ]; then
                                PLCMD="$PLCMD_BANNER"
                        else
                                PLCMD="$PLCMD_NOBANNER"
                        fi
                        ;;
                raster | sunras )
                        if [ $nobanner = no ]; then
                                PLCMD="$RASTER_CMD"
                                PLCMD2="$BANNER_CMD"
                        else
                                PLCMD="$RASTER_CMD"
                        fi
                        ;;
                * )
			if [ $nobanner = no ]; then
				PLCMD="--k $content_type $PLCMD_NOBANNER"
				PLCMD2="$BANNER_CMD"
			else
				PLCMD="--k $content_type $PLCMD_NOBANNER"
			fi
                        ;;
        esac
}

###########
##
## Setup the log file 
###########

setup_logfile () {

	LOGFILE="${SPOOLDIR}/log"

        if [ ! -f "$LOGFILE" ]
        then
                touch $LOGFILE
                chown lp $LOGFILE
                chgrp lp $LOGFILE
                chmod 666 $LOGFILE
        fi
}

#if [ "${TERM}" = "PSR" -o "${TERM}" = "PS" ]
#then
#	banner=np_banner
#fi

###########
##
## Print the front page
###########
#if [ "no" = "${nobanner}" -a "${TERM}" != "PSR" ]
#then
#	eval "${banner} ${banner_filter}"
#fi

###########
##
## Print some copies of the file(s)
###########

setup_banner
setup_plcall
setup_logfile

badfileyet=
i=1
while [ $i -le $copies ]
do
	for file in ${files}
	do
		if [ -r "${file}" ]
		then
			EXIT_CODE=${TMPPREFIX}e
			trap '' 1	# Let the filter handle a hangup
			trap '' 2 3	# and interrupts

			errfile=/tmp/err.${i}.$$

			# if STACKORDER = -b means print the banner page last
			# if STACKORDER = -f means print the banner page first

			if [ -f /tmp/libaio.log ]; then
                                rm -f /tmp/libaio.log
                        fi

			if [ "${STACKORDER}" = "-b" ]; then
				( 	0<${file} eval $PL --r $PLCMD 2>&1 1>&3
					if [ -n "$PLCMD2" ] ; then
						0</dev/null eval $PL --r $PLCMD2 2>&1 1>&3
					fi
				)  | tee -a $LOGFILE | tee -a $errfile | ${LPTELL} -l ${printer}
			else
				( 	if [ -n "$PLCMD2" ] ; then
						0</dev/null eval $PL --r $PLCMD2 2>&1 1>&3
					fi
					0<${file} eval $PL --r $PLCMD 2>&1 1>&3
				)  | tee -a $LOGFILE | tee -a $errfile | ${LPTELL} -l ${printer}
			fi

			if [ -f /tmp/libaio.log ]; then
                                rm -f /tmp/libaio.log
                        fi

			trap 'catch_hangup; exit_code=129 exit 129' 1
			trap 'catch_interrupt; exit_code=129 exit 129' 2 3
			exit_code=`cat ${EXIT_CODE}`

			print_errors
			log_pagecount

			if [ -n "${exit_code}" -a 0 -ne "${exit_code}" ]
			then
				trap '' 15  # Avoid dying from disable
				sleep 4	    # Give $LPTELL a chance to tell
				exit_code=129 exit 129
			fi

			#
			# if no filebreaks
			#
			#if [ -n "${FF}" -a "no" = "${nofilebreak}" ]
			#then
			#	echo "${CR}${FF}\c"
			#fi

		else

			#####
			#
			# Don't complain about not being able to read
			# a file on second and subsequent copies, unless
			# we've not complained yet. This removes repeated
			# messages about the same file yet reduces the
			# chance that the user can remove a file and not
			# know that we had trouble finding it.
			#####
			if [ "${i}" -le 1 -o -z "${badfileyet}" ]
			then
				errmsg WARNING ${E_IP_BADFILE} \
					"cannot read file \"${file}\"" \
					"see if the file still exists and is readable,
		or consult your system administrator;
		printing continues"
				badfileyet=yes
			fi

		fi

	done
	i=`expr $i + 1`

done

###########
##
## Print the back page
###########
#if [ "no" = "${nobanner}" -a "${TERM}" = "PSR" ]
#then
#	eval "${banner} ${banner_filter}"
#fi

if [ -n "${exit_code}" -a 0 -ne "${exit_code}" ]
then
	exit ${exit_code}
fi

#####
#
# Always ensure the complete job ends with a ``formfeed'', to
# let the next job start on a new page. (If someone wants to
# concatenate files, they can give them in one job.)
# So, if we haven't been putting out a ``formfeed'' between files,
# it means we haven't followed the last file with a formfeed,
# so we do it here.
#####
#if [ -n "${FF}" -a "yes" = "${nofilebreak}" ]
#then
#	echo "${CR}${FF}\c"
#fi

${DRAIN}

exit_code=0 exit 0
