#!/bin/sh
#echo "<$*>" > /tmp/hp
#exec 2> /tmp/ee
#set -x
#
# hp4laser-3.20:
# -------------
#
#	System V lp model interface and/or BSD lpd filter for HP LaserJet
#	Series IIIsi and IV (and probably later LaserJets as well).
#
#	Yes, its a floor wax AND a desert topping.
#
#	I hope this is the end-all of HP LaserJet printer scripts.  The ones
#	that come with every Unix I have seen are pure garbage.
#
#	With the Adobe Postscript SIMM installed, this script will auto-detect
#	postscript files (by looking for %! as the first characters in the
#	file), and switch the printer mode as needed.  Don't be fooled
#	by printer manufacturer claims of auto-switch capability - to
#	do it *right* you must explicity switch modes.
#
#	The script will also autodetect HP-GL files.  The first few bytes
#	of the file must be "IN;", "BP;", ESC %-1B, ESC %0B, or ESC %1B.
#
#	This script probably works with LJ II's and III's without postscript
#	support.  Set ps_simm=no and pjl=no in the CONFIGURATION SECTION.
#
#	See the USAGE SUMMARY below to see what options are accepted,
#	*or* install this script and do "lp -ohelp any-file-name."
#	Also, note cute display of job owner on printer display.
#
#	See the CONFIGURATION SECTION below to adjust for your site.
#
#	-Rick Richardson, rick@remotepoint.com, 03/22/94 - 11/13/00.
#
#	http://home.mn.rr.com/richardsons/
#
#
# Copyright and LICENSE
# ---------------------
#
#	Copyright 1993-2000 Rick Richardson.  All Rights Reserved.
#
#	This software is licensed with a "BSD" style license which
#	appears below.
#
#	Redistribution and use in source and binary forms, with or without
#	modification, are permitted provided that the following conditions
#	are met:
#	1. Redistributions of source code must retain the above copyright
#	   notice, this list of conditions and the following disclaimer.
#	2. My name cannot be used to endorse or promote products derived
#	   from this software without specific prior written permission.
#
#	THIS SOFTWARE IS PROVIDED BY RICK RICHARDSON AND CONTRIBUTORS ``AS IS''
#	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
#	THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#	PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL RICK RICHARDSON OR
#	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
#	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
#	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
#	OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
#	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
# Script configuration:
# ---------------------
#
#	Go down to the section marked BEGIN CONFIGURATION SECTION and adjust
#	the values to agree with your printer.
#
#
# Testing:
# --------
#
#	After configuring the stuff below, you can test this script without
#	actually installing it into the "lp" or "lpr" system one of these
#	typical commands:
#		./hp4laser - < FILE > DEVICE
#		./hp4laser 9999 rick title 1 "" FILE > DEVICE
#	Where FILE is a file to print, and DEVICE is the device you use, e.g.
#	/dev/ttyi1A, /dev/lp0, or /dev/dfax0lp.  You have to be root.
#
#
# Installation for System V "lp":
# -------------------------------
#
#	System V lp model Installation:
#		Now, install a copy of this script as a printer "model",
#		which is the prototype used for creating new printer
#		"interfaces".  I've made this part easy for SCO and UnixWare
#		users - just type (as root):
#			./hp4laser install
#		For other Unixes, snoop around and see where models go.
#
#	System V Printer Installation:
#		To create a new printer on UnixWare, use the Desktop manager:
#			Select System_Setup -> Printer_Setup
#				-> Printer -> New, etc.
#			Choose the printer type as HP LaserJet IV (hp4laser),
#			and follow the usual procedure for creatng a printer
#			on UnixWare.
#
#		To create a new printer without using the desktop,
#		run these commands:
#			/usr/lib/lpshut
#			/usr/lib/lpadmin -p ${name} -v ${dev} -m ${model}
#			/usr/lib/lpsched
#			lpstat -r
#			/usr/lib/accept ${name}
#			enable ${name}
#			/usr/lib/lpadmin -d${name}
#		Where ${name} is the name you want for your printer,
#		${dev} is the device name, and ${model} is the name
#		of this file.
#	Permissions:
#		Once you have created new printers, make sure that the interface
#		script is readable by all.  The -ohelp feature depends on this.
#		If your printer is named "laser", check /etc/lp/interfaces/laser
#		on SVR4, and /usr/spool/lp/admins/lp/interfaces/laser on SVR3.
#
#
# Installation for BSD "lpr" and LPRng:
# -------------------------------------
#
#	Copy this script (hp4laser) to /usr/local/bin and make it executable.
#
#	Set the input filter for your printer in /etc/printcap to:
#		if=/usr/local/bin/hp4laser:
#
#	If you want to be able to pass in options on the "lpr" command line,
#	you must get and install LPRng if you don't already have it.  If
#	you have only stock BSD "lpr", you can still specify static options
#	by using the "af" /etc/printcap capability to specify the options, i.e.
#		af=manualfeed:
#
#	Here are some BSD "lpr" /etc/printcap entries, showing use of "af":
#
#		##PRINTTOOL## LOCAL PostScript 600x600 letter {}
#		lp|PostScript:\
#		        :sd=/var/spool/lpd/lp:\
#		        :mx#0:\
#		        :lp=/dev/lp0:\
#		        :if=/usr/local/bin/hp4laser:\
#		        :af=:\
#		        :sh:
#		##PRINTTOOL## LOCAL PostScript 600x600 letter {}
#		hp4manual:\
#		        :sd=/var/spool/lpd/lp:\
#		        :mx#0:\
#		        :lp=/dev/lp0:\
#		        :if=/usr/local/bin/hp4laser:\
#		        :af=manualfeed:\
#		        :sh:
#		hp4duplex:\
#		        :sd=/var/spool/lpd/lp:\
#		        :mx#0:\
#		        :lp=/dev/lp0:\
#		        :if=/usr/local/bin/hp4laser:\
#		        :af=duplex:\
#		        :sh:
#
#	LPRng users can use multiple printer definitions as above, or you
#	can pass the options using the "-Z" flag to the "lpr" command.
#	The -Z flag is used just like the -o flag for SVR4 "lp".  LPRng
#	is found in Redhat 7.0 and later.
#
#
# USAGE (DO NOT DELETE THIS LINE - -ohelp uses it)
# ------------------------------------------------
#
# OPTION SUMMARY FOR PRINTER MODEL hp4laser:
#
# General options are:
#	-opcl		#Force use of PCL mode (else, autodetect)
#	-ops		#Force use of PS mode (else, autodetect)
#	-ogl		#Force use of HPGL mode (else, autodetect)
#	-orfc4		#Pretty print RFC text files 4-up
#	-onobanner	#Force no banner
#	-obanner	#Force banner
#	-onofilebreak	#Force no file break (no page eject between files)
#	-ohelp		#Print list of options; also mail it to requester
#
# Options used for plain text or PCL files:
#	-oland		#Landscape orientation for unformatted text
#	-oport		#Portrait orientation for unformatted text
#	-o2on1		#Two pages on one page for unformatted text
#	-oi		#Indent 8 characters for unformatted text
#	-o17cpi		#17 CPI for unformatted text
#	-oindent=N	#Offset page by N characters
#
# Options used for Postscript files (requires installed psutils):
#	-o2on1		#Two pages on one page
#	-o2up		#Two pages on one page
#	-o4on1		#Four pages on one page
#	-o4up		#Four pages on one page
#	-o2land		#Two landscape pages on one portrait page
#			#needed only when paper is punched!
#
# Options usable only if printer can do PJL (LaserJet IV, or later):
#	-opjl="string"	#Send arbitrary PJL string to printer, just before
#			#printer personality is selected.  Use _ for a blank
#			#in string because lp can't handle blanks in options
#			#I.E. -opjl="set_copies=2"
#	-obinding=STR	#Which side of paper to bind on (longedge,shortedge)
#	-ocopies=N	#Set number of uncollated copies (1 to 999)
#	-oduplex	#Turn on duplexer
#	-opunched	#Alias for -omediatype=prepunched
#	-opaper=STR	#Set paper type - STR is letter, legal, a4, executive,
#			#ledger, com10, monarch, c5, dl, or b5
#	-oformlines=N	#Set number of lines/page - N is 5 to 128
#	-omanualfeed	#Manual feed mode (also, =on, =off)
#	-oret=N		#Res. enhancement - N is light, medium, dark, or off
#	-omediasource=STR
#			#Select paper tray
#	-omediatype=STR
#			#Select paper type: plain, prepunched, etc.
#	-opageprotect=N	#Page protection - N is letter, legal, a4, or off
#	-oresolution=N	#Page resolution - N is 300 or 600
#	-otimeout=N	#I/O timeout - N is 5 to 300 seconds
#	-oprtpserrs	#Print Postscript errors (also, =on, =off)
#	-ostart=N	#Start printing on page N
#	-oend=N		#End printing on page N
#	-oopmsg="STR"	#Display "STR" on printer display, and take printer
#			#off-line.  Use _ for a blank in STR.
#			#I.E. -oopmsg="Load_Letterhead"
#
# Obsolete options:
#	These options are accepted, but are not needed.  This filter
#	*always* runs the port in "raw" mode, and uses the LaserJet's
#	internal NL -> CR/NL feature to handle plain text, which is a
#	much smarter idea than using 'stty' (and foolproof).
#	-otroff		#No cr/lf mapping (for JetRoff, etc.)	[Obsolete]
#	-oraw		#Same					[Obsolete]
#	-og		#Same (SCO's naming convention)		[Obsolete]
#
# Options not yet implemented (and of limited use, anyway):
#	-ocpi=pica	10 CPI
#	-ocpi=elite	12 CPI
#	-ocpi=		Other CPI
#	-olpi=		LPI
#	-olength=
#	-owidth=
#
# Debugging options:
#	-ops_simm=STR	Force value of ps_simm variable to no or yes
#	-oidlemode=STR	Force value of idlemode variable to pcl or ps
#
# LPRng users:
#	You can use "lp" with the options specified using -o as above, or
#	you can use the -Z option on "lpr".  When using -Z, specify the
#	options like this in this example:
#		lpr -Z "manualfeed nobanner opmsg=Load_Letterhead" file
#
# BSD lpr users:
#	You are screwed.  You can't use any of these options.  Your
#	system administrator will have to set up special print queues
#	in order to provide access to these options.
#

#
# BEGIN CONFIGURATION SECTION (adjust these as needed)
#
speed=parallel	#Serial interface speed (e.g. 38400), or "parallel"
banner=no	#Enable printing of banner page ("yes" or "no")
ps_simm="yes"	#Have Adobe Postscript SIMM installed ("yes" or "no")
idlemode="pcl"	#Idle printer in "pcl" mode or "ps" mode (when ps_simm=yes)
pjl="yes"	#It knows PJL ("yes" or "no")
paper="letter"	#Default paper type (letter, a4, legal)
res=600		#Printer resolution (300 or 600)
#
# END CONFIGURATION SECTION
#
# ENDUSAGE (DO NOT DELETE THIS LINE)

#
#	Figure out what kind of echo we have
#
if [ "`echo -e`" = -e ]; then
	echo="echo"	# System V style echo
else
	echo="echo -e"	# GNU style echo
fi

#
#	See if this script wants to be "installed"
#
if [ install = "$1" ]; then
	SVR3DIR=/usr/spool/lp/model
	SVR4DIR=/usr/lib/lp/model
	UWDATA=/usr/X/desktop/PrintMgr/Printers
	if [ -d $SVR3DIR ]; then
		cp $0 $SVR3DIR
		chmod 755 $SVR3DIR/$0
		chmod +x /usr/spool/lp/admins
		chmod +x /usr/spool/lp/admins/lp
		chmod +x /usr/spool/lp/admins/lp/interfaces
		echo "--- hp4laser printer model installed in $SVR3DIR"
	fi
	if [ -d $SVR4DIR ]; then
		cp $0 $SVR4DIR
		chmod 755 $SVR4DIR/$0
		echo "--- hp4laser printer model installed in $SVR4DIR"
	fi
	if [ -f $UWDATA ]; then
		cat <<-EOF >>$UWDATA
		entry: hp4laser
		name: HP LaserJet IV (hp4laser)
		terminfo: unknown
		interface: hp4laser
		contents: simple, pcl, PS

		EOF
		echo "--- UnixWare desktop data installed in $UWDATA"
	fi
	cp $0 /usr/local/bin
	echo "--- hp4laser model installation complete"
	exit 0
fi

#
#	Give names to the command line arguments
#
#	Handle three cases:
#		1) We are being called by BSD "lpr" or LPRng
#		2) We are being called as a standalone filter
#		3) We are being called as a System V "lp" printer model
#
printer=`basename $0`
standalone=0
rmfiles=
options=

case "$1" in
'-?' | -help | --help)
	sed -e '1,/^# USAGE/d' -e '/^# ENDUSAGE/,$d' < $0
	exit
	;;

-[a-zA-Z]*)
	#
	#	Linux/BSD lpd interface filter
	#
	#	BSD lpr:
	#		Use "af" capability in /etc/printcap to specify options
	#		There is no way to pass them in on the "lpr" command
	#		line.
	#
	#		The command line we get will look like this:
	#		-w132 -l66 -i0 -n rick -h ipcroe.xyzzy.com "options"
	#
	#	LPRng:
	#		Use lpr -Z"option=val option option" to pass options
	#		to this script.
	#
	#		The command line we get will look like this:
	#		-CA -Ff -Hpepper.xyzzy.com -J/etc/group -Lrick -Plp
	#		-Zaaa=ccc bbb ccc
	#		-d/var/spool/lpd/hp4/cfA323pepper.xyzzy.com
	#		-e/var/spool/lpd/hp4/dfA323pepper.xyzzy.com -f/etc/group
	#		-hpepper.xyzzy.com -j323 -kcfA323pepper.xyzzy.com -l66
	#		-nrick -sstatus -w80 -x0 -y0 < file
	#
	request_id=
	title=

	set -- `getopt "A:C:D:F:H:J:L:N:P:Q:Z:a:b:d:e:f:h:i:j:k:l:n:p:r:s:t:w:x:y:" $*`
	for c
	do
		case $c in
		-f)	title="$2"; shift; shift;;
		-n)	user_name="$2"; shift; shift;;
		-h)	host_name="$2"; shift; shift;;
		-Z)	options="$options $2"; shift; shift;;
		-P)	printer="$2"; shift; shift;;
		-j)	request_id="$2"; shift; shift;;
		--)	shift; break;;
		-*)	shift; shift;;
		esac
	done

	if [ "" = "$options" -a "$#" != 0 ]; then
		#
		#	Provide kludgy way to set options with stock BSD lpr
		#
		options="$1"
	fi

	options=`echo "$options" | tr ',' ' '`

	copies=1
	files=/tmp/hp4laser$$
	nfiles=1
	rmfiles="$files"
	# set >> /tmp/cmd
	# exit
	cat > $files
	;;

-)
	#
	#	Running as standalone filter, i.e.
	#	hp4laser - "option=xxx option=yyy" < file
	#
	standalone=1
	request_id=666
	user_name=$USER
	host_name=`uname -n`
	title="filter"
	copies=1
	options=$2
	files=/tmp/hp4laser$$
	nfiles=1
	rmfiles="$files"
	cat > $files
	;;

*)
	#
	#	Running as a standard System V printer model
	#
	#	Use "lp -o option=val -o option -o option" to pass options
	#	to this script.
	#
	#	The command line we get is:
	#	request-id user-name title copies printer-options file ...
	#	$1         $2        $3    $4     $5		  $6 ...
	#
	request_id=$1
	case "$2" in
	*!*)
		host_name=`echo "$2" | sed 's/!.*//'`
		user_name=`echo "$2" | sed 's/.*!//'`
		;;
	*@*)
		user_name=`echo "$2" | sed 's/@.*//'`
		host_name=`echo "$2" | sed 's/.*@//'`
		;;
	*)
		user_name="$2"
	esac
	title="$3"
	copies=$4
	options=$5
	shift 5
	files="$*"
	nfiles=$#
	;;
esac

full_name="$user_name@$host_name"

#
#	Turn off output postprocessing and set port speed (if needed)
#
if [ "$speed" = "parallel" ]
then
	# Parallel port - turn off postprocessing
	stty -opost <&1 >/dev/null 2>&1
	# Hack for old Digi PC/8emp parallel port drivers
	if [ -x /usr/bin/ditty ]; then ditty forcedcd <&1 >/dev/null 2>&1; fi
else
	# Serial port - set speed and turn off postprocessing
	stty $speed clocal cs8 ixon ixoff -ixany -parenb onlcr -tabs -opost <&1
fi

#
#	Define some shorthand for PCL sequences
#
NORAW="\033&k2G"		#Translate LF to CR+LF and FF to CR+FF
RAW="\033&k0G"			#Do not translate CR, LF, or FF

LETTER="\033&l2A"		#Select letter paper
RESETJOB="\033E"		#Reset printer, eject if any printing on page
RESETPAGE="\033E"		#Reset printer, eject if any printing on page
UEL="\033%-12345X"		#Universal exit language command
PSMODE="$UEL@PJL enter language=postscript\n"	# Switch to PS
PCLMODE="$UEL@PJL enter language=pcl\n"		# Switch to PCL
GLMODE="\033%0B"				# Switch to HP-GL (from PCL)
DUPLEXMODE="\033&l1S"		# Select duplexing

#
#	getarg <arg>:	given an <arg> of the form "x=y", return the "y"
#
getarg () {
	echo "`expr \"$1\" : \"[^=]*=\(.*\)\"`"
}

#
#	Return the filetype (ps, gl, or pcl) of a file
#
filetype () {
	case "$force" in
	pcl)	echo pcl
		;;
	ps)	echo ps
		;;
	gl)	echo gl
		;;
	rfc4)	echo rfc4
		;;
	*)
		ctrl_d=`$echo "\004\c"`
		esc=`$echo "\033\c"`
		read a <$1
		case "$a" in
		%!*)
			# A well formatted Postscript file
			echo ps
			;;

		"$ctrl_d"%!*)
			# A PS file, but with Apple Laserwriter job control
			# in it, probably from a broken Microsoft product.
			# Only a print spooler (like this filter is run from)
			# should generate job control.  Not applications.
			echo ps
			;;

		"$esc%-1B"* | "$esc%0B"* | "$esc%1B"* | "IN;" | "BP;" )
			# Probably an HP-GL or HP-GL/2 file
			echo gl;;

		"$esc%-12345X@PJL"*)
			# Hmm, probably more brain-dead Microsoft output, with
			# PJL already in it.  Could be PS or PCL, lets see..
			if grep -q "ENTER LANGUAGE = POSTSCRIPT" $file; then
				# Its bogus postscript, will need filtering
				# if it is to pass thru ghostscript or psnup.
				echo badps;
			else
				echo pcl;
			fi
			;;

		*)	
			# Assume its PCL, then
			echo pcl
			;;
		esac
		;;
	esac
}

#
#	HP PCL banner page
#
pcl_banner () {
	PDEFAULT="\033(3@"
	PTIMES="\033(0U\033(s1p68v0s2b4101T"
	GRAY="\033*c200a3300b20g2P"
	UL_LOC="\033*p0x0Y"
	UR_LOC="\033*p2200x0Y"

	$echo "$RESETJOB$NORAW"
	$echo "$PTIMES\n\n\n\n"
	$echo "    $user_name"
	$echo "$PDEFAULT$UL_LOC$GRAY$UR_LOC$GRAY\n\n\n\n\n\n\n"

	# banner "  $user_name"
	$echo "\n"
	real_name=`grep "^$user_name:" /etc/passwd | line | cut -d: -f5`
	if [ -n "$real_name" ]
	then
		$echo "            User: $real_name\n"
	else
		$echo "            User: $full_name\n"
	fi
	$echo "            Title: $title\n"
	$echo "            Request id: $request_id\n"
	$echo "            Printer: $printer\n"
	$echo "            Options: $options\n"
	$echo "            Printed: `date`"
	$echo "\n"
	if [ -n "$title" ]
	then
		banner $title
	fi
	$echo "$RESETJOB\c"
exit
}

#
#	Postscript banner page
#
ps_banner () {
	if [ -z "${title}" ]
	then
		title="<untitled>"
	fi
	cat <<EOF
	/banner {
		/saveobj save def
		erasepage initgraphics

		/#copies 1 def
		/inch {72 mul} bind def
		/pagebbox [clippath pathbbox newpath] def

		/font /Helvetica def
		/size 20 def
		/height pagebbox 3 get def
		/width pagebbox 2 get .09 mul def

		.92 setgray
		pagebbox 0 get pagebbox 1 get moveto
		width 0 rlineto 0 height rlineto width neg 0 rlineto
			closepath eofill
		pagebbox 2 get pagebbox 1 get moveto
		width neg 0 rlineto 0 height rlineto width 0 rlineto
			closepath eofill
		0 setgray

		font findfont size scalefont setfont
		/linesp size size .15 mul add neg def
		/tab (Destination) stringwidth pop 1.5 mul def
		/nextline
			{0 0 moveto show tab 0 moveto show 0 linesp translate}
			def

		pagebbox 0 get 1.5 width mul add
		pagebbox 3 get 2.0 width mul sub translate

		font findfont 68 scalefont setfont
		0 0 moveto show 0 linesp translate
		0 linesp translate
		font findfont size scalefont setfont

		(User:) nextline
		(Title:) nextline
		(Job-Id:) nextline
		(Printer:) nextline
		(Options:) nextline
		(Printed:) nextline
		showpage
		saveobj restore
	} bind def
EOF
	echo "(`date '+%a %H:%M %h %d, 19%y'`)"
	echo "($options)"
	echo "($printer)"
	echo "($request_id)"
	echo "($title)"
	echo "($full_name)"
	echo "($user_name)"
	echo "banner"
}

#
#	Select paper in PS Level 2.  PJL doesn't seem to work for this
#	in PS mode.  Oddly, though, manualfeed PJL does work.
#
ps_paper () {
	case "$1" in
	letter)		xy="612  792";;
	legal)		xy="612 1008";;
	a4)		xy="595  842";;
	ledger)		xy="792 1224";;
	executive)	xy="522  756";;
	com10)		xy="297  684";;
	monarch)	xy="279  540";;
	c5)		xy="459  649";;
	dl)		xy="312  624";;
	b5)		xy="499  708";;
	*)		xy="612  792";;
	esac

	# Is this ugly, or what???
	echo "<</Policies <</PageSize 2 /MediaType 0 >> >>"
	echo "setpagedevice"
	echo "<</PageSize [$xy]"
	echo ">> setpagedevice"
}

ps_mediatype () {
	case "$1" in
	[Pp][Rr][Ee][Pp][Uu][Nn][Cc][Hh][Ee][Dd])
		echo "<</MediaType (Prepunched)>> setpagedevice";;
	esac
}

#
#	Switch to PS mode
#
ps_mode () {
	$echo "$PSMODE"
	$echo "\r\004\c"

	# Set paper size
	ps_paper $newpaper
	ps_mediatype $mediatype
}

#
#	Switch to HP PCL mode
#
pcl_mode () {
	$echo "$PCLMODE\c"
	$echo "$RESETJOB\c"
	# $echo "$LETTER\c"
}

#
#	Switch to HP GL mode
#
gl_mode () {
	$echo "$PCLMODE\c"
	$echo "$RESETJOB\c"
	$echo "$GLMODE\c"
}

#
#	Start job PJL
#
start_job() {
	if [ $pjl = no ]; then return; fi

	$echo "$UEL@PJL"				# Into PJL mode
	echo "@PJL JOB NAME=\"$request_id\" $start $end" # Start Job
	echo "@PJL RDYMSG DISPLAY=\"$user_name\""	# Username on display
	echo "@PJL SET PAPER=$paper"			# Set default paper
	$echo "$opmsg\c"				# Operator message
	$echo "$pjlstr\c"				# Overrides
	$echo "$UEL\c"					# Exit PJL mode
}

#
#	End of job PJL
#
end_job() {
	if [ "$rmfiles" != "" ]; then
		rm -f $rmfiles
	fi

	if [ $pjl = no ]; then return; fi

	$echo "$UEL@PJL"			# Into PJL mode
	echo "@PJL SET PAPER=$paper"		# Restore default paper
	echo "@PJL RDYMSG DISPLAY = \"\""	# Restore READY message
	echo "@PJL EOJ NAME=\"$request_id\""	# End of Job
	$echo "$UEL\c"				# Exit PJL mode
}

#
#	Hooks to allow user-specified actions on start of session
#	and end of session.  In my case, these scripts cause an X10
#	controller to power up/down the printer.
#
start_hook() {
	if [ $standalone = 1 ]; then
		return;
	fi
	if [ -x /usr/local/bin/hp4laser.start ]; then
		/usr/local/bin/hp4laser.start
	fi
}

end_hook() {
	if [ $standalone = 1 ]; then
		return;
	fi
	stty -ixany 0<&1 >/dev/null 2>&1
	if [ -x /usr/local/bin/hp4laser.end ]; then
		nohup /usr/local/bin/hp4laser.end >/dev/null 2>&1
	fi
}


#
#	Handle a Postscript File
#
do_ps() {
	if [ "$ps_simm" = no ]; then
		#
		# Printer can't handle postscript, so use
		# ghostscript to convert it to PCL
		#
		pcl_mode
		$echo "$SET$CRMODE\c"

		#
		# It is tricky to use Ghostscript before
		# version 5.something in a filter situation,
		# because there is no way to redirect the
		# stdout of PostScript itself separately
		# from the stdout of the device driver.
		# Thus, we play games with subshells and
		# fd 3 to work around this problem.  Otherwise,
		# output from a very popular operating system
		# will get progress messages intermingled into
		# the PCL.
		#
		$ps_prefilter $1 |
			(gs -q -sDEVICE=ljet4 $gs_res \
				-sPAPERSIZE=$paper \
				-dNOPAUSE -dSAFER \
				-sOutputFile="|cat 1>&3" \
				- >/dev/null) 3>&1
		if [ $filebreak = yes ]; then
			$echo "$RESETPAGE\c";
		fi
	else
		#
		# Printer can handle postscript
		#
		ps_mode
		$ps_prefilter $1
	fi
}

#
#	Handle a "bad" Postscript File
#
do_badps() {
	# Eliminate crap before and after the genuine postscript.
	sed -n -e '/^%!/,/%%EOF/p' $1 | do_ps -
}

#
#	Handle a PCL File
#
do_pcl() {
	pcl_mode
	$echo "$SET$CRMODE\c"
	if [ $two_on_one = yes ]
	then
		expand "$1" | sed "s/^/| /" | pr -2 -w175 -t
	else
		cat "$1"
	fi
	if [ $filebreak = yes ]; then $echo "$RESETPAGE\c"; fi
}

#
#	Handle a GL file
#
do_gl() {
	gl_mode
	cat $1
	if [ $filebreak = yes ]; then $echo "$RESETPAGE\c"; fi
}

#
#	Handle an RFC file
#
do_rfc4() {
	case $duplex in
	yes)	aopt=8;;
	*)	aopt=4;;
	esac

	tail +3 $1 \
	|
	nenscript -q -p- --fancy-header=emacs \
			-j -A$aopt -U4 --margins=40:40 -f Courier11.3 \
	|
	do_ps -
}

#
#	Process user options
#
raw=no
orient=port
cpi=10
lpi=6
indent=0
length=0
width=0
filebreak=yes
two_on_one=no
force=no
duplex=no
pjlstr=
start=""
end=""
opmsg=""
mediasource=
mediatype=
newpaper="$paper"
ps_prefilter=cat

for o in $options
do
	case $o in
	raw|troff|g)	raw=yes;;
	land)		orient=land;;
	port)		orient=port;;
	17cpi)		cpi=16.66;;
	i)		indent=8;;
	2on1|2up)
			two_on_one=yes;
			ps_prefilter="psnup -d2 -2 -p$paper"
			;;
	4on1|4up)
			ps_prefilter="psnup -d2 -4 -m.5in -p$paper"
			;;
	2land)
		case "$paper" in
		letter)	scale=.647;;
		a4)	scale=.707;;
		esac
		ps_prefilter="pstops -p$paper 2:1R@$scale(0,0.5h)+0R@$scale(0,1h)"
		;;
	cpi=pica)	cpi=10;;
	cpi=elite)	cpi=12;;
	cpi=*)		cpi=`getarg ${o}`;;
	indent=*)	indent=`getarg ${o}`;;
	length=*)	length=`getarg ${o}`;;
	width=*)	width=`getarg ${o}`;;
	lpi=*)		lpi=`getarg ${o}`;;
	banner)		banner=yes;;
	nobanner)	banner=no;;
	nofilebreak)	filebreak=no;;
	ps_simm=*)	ps_simm=`getarg ${o}`;;
	idlemode=*)	idlemode=`getarg ${o}`;;
	ps)		force="ps";;
	pcl)		force="pcl";;
	gl)		force="gl";;
	rfc4)		force="rfc4";;
# PJL options
	copies=*)	pjlstr="$pjlstr@PJL SET COPIES=`getarg $o`\n";;
	orientation=*)	pjlstr="$pjlstr@PJL SET ORIENTATION=`getarg $o`\n";;
	formlines=*)	pjlstr="$pjlstr@PJL SET FORMLINES=`getarg $o`\n";;
	manualfeed=*)	pjlstr="$pjlstr@PJL SET MANUALFEED=`getarg $o`\n";;
	manual*)	pjlstr="$pjlstr@PJL SET MANUALFEED=ON\n";;
	mediasource=*)
			mediasource=`getarg ${o}`
			pjlstr="$pjlstr@PJL SET MEDIASOURCE=`getarg $o`\n"
			;;
	punched)
			mediatype=prepunched
			pjlstr="$pjlstr@PJL SET MEDIATYPE=$mediatype\n"
			;;
	mediatype=*)
			mediatype=`getarg ${o}`
			pjlstr="$pjlstr@PJL SET MEDIATYPE=$mediatype\n"
			;;
	duplex)		duplex=yes; pjlstr="$pjlstr@PJL SET DUPLEX=ON\n";;
	binding=*)	pjlstr="$pjlstr@PJL SET BINDING=`getarg $o`\n";;
	ret=*)		pjlstr="$pjlstr@PJL SET RET=`getarg $o`\n";;
	pageprotect=*)	pjlstr="$pjlstr@PJL SET PAGEPROTECT=`getarg $o`\n";;
	resolution=*)
		res="`getarg $o`"
		case "$res" in
		300|600)	pjlstr="$pjlstr@PJL SET RESOLUTION=$res\n";;
		esac
		;;
	timeout=*)	pjlstr="$pjlstr@PJL SET TIMEOUT=`getarg $o`\n";;
	start=*)	start="START=`getarg $o`";;
	end=*)		end="END=`getarg $o`";;
	opmsg=*)	opmsg="@PJL OPMSG DISPLAY=\"`getarg $o|tr _ ' '`\"\n";;
	paper=*)
		newpaper="`getarg $o`"
		pjlstr="$pjlstr@PJL SET PAPER=$newpaper\n"
		;;
	prtpserrs=*)
		pjlstr="$pjlstr@PJL SET LPARM:POSTSCRIPT PRTPSERRS=`getarg $o`\n"
		;;
	prtpserrs)
		pjlstr="$pjlstr@PJL SET LPARM:POSTSCRIPT PRTPSERRS=ON\n"
		;;
	pjl=*)
		# lp doesn't allow blanks, translate _ to blank
		# I.E. -opjl="set_copies=2"
		pjlstr="$pjlstr@PJL `expr "$o" : 'pjl=\(.*\)' | tr _ ' '`\n"
		;;
# Help message
	help|'?')
		if [ -r "$0" ]; then
			sed -e '1,/^# USAGE/d' -e '/^# ENDUSAGE/,$d' \
				< $0 > /tmp/hp4use
			files=/tmp/hp4use; force=pcl; two_on_one=yes;
			mail -s "hp4laser lp model usage" "$user_name" \
				< /tmp/hp4use >/dev/null 2>&1
		else
			mail -s "Permissions Wrong" root $user_name <<-EOF
			The file $0 must have read permission for everybody
			in order for lp -ohelp to work.  Please correct this.
			EOF
			exit 1;
		fi
		;;
	esac
done

#
#	Set some additional variables based on the above option settings
#
case "$res" in
300|600)	gs_res="-r${res}x${res}";;
*)		gs_res=;;
esac

#
#	Set mode switching variables
#
if [ $pjl = no ]; then
	pjlstr=
fi

#
#	Init the printer, set exit traps
#
if [ $ps_simm = no ]; then
	# force PCL only operation
	PCLMODE=
	idlemode=pcl
fi

start_hook

start_job

case $idlemode in
pcl)	cur_mode=pcl; pcl_mode; $echo "$RESETJOB\c"
	trap 'end_job; pcl_mode; end_hook; exit' 0 2 3 15
	;;
ps)	cur_mode=ps; ps_mode;
	trap 'end_job; ps_mode; end_hook; exit' 0 2 3 15
	;;
esac

#
#	Get printer banner page out in portrait, courier
#
if [ $banner = yes ]
then
	case $idlemode in
	pcl)	pcl_banner;;
	ps)	ps_banner;;
	esac
fi

#
#	Set variables to use when file is printed in PCL mode
#
SET=
SET="$SET\033(s${cpi}H"
SET="$SET\033&a${indent}L"
if [ $raw = yes ]; then CRMODE=$RAW; else CRMODE=$NORAW; fi
if [ $orient = "land" ]; then
	SET="$SET\033&l1O\033(s16.66H\033&l5.4C\033&l6E\033&a0R\033&l66F"
fi
if [ $two_on_one = yes ]; then
	SET="$SET\033&l1O\033(s16.66H\033&l5.4C\033&l6E\033&a0R\033&l66F"
fi
if [ $duplex = yes ]; then
	SET="$SET$DUPLEXMODE"
fi
case "$mediasource" in
[Tt][Rr][Aa][Yy]*1)	SET="$SET\033&l2H";;
[Tt][Rr][Aa][Yy]*2)	SET="$SET\033&l1H";;
[Tt][Rr][Aa][Yy]*3)	SET="$SET\033&l5H";;
[Tt][Rr][Aa][Yy]*4)	SET="$SET\033&l8H";;
esac
case "$mediatype" in
[Pp][Rr][Ee][Pp][Uu][Nn][Cc][Hh][Ee][Dd])	SET="$SET\033&n11WdPrepunched";;
esac

#
#	Loop for each copy, and then for each file
#
copy=1
while [ $copy -le $copies ]
do
	for file in $files
	do
		type=`filetype $file`
		case "$type" in
		ps)		do_ps $file ;;
		badps)		do_badps $file ;;
		gl)		do_gl $file ;;
		rfc4)		do_rfc4 $file ;;
		*)		do_pcl $file ;;
		esac
	done
	copy=`expr $copy + 1`
done
#
#	Make sure all output is flushed before exitting.  Some device
#	drivers have a timeout in the close routine.  If the printer
#	is slow or off-line, the timeout in close() can trip and
#	printer data could be lost.
#
stty -ixany 0<&1 >/dev/null 2>&1

exit 0
