#! /bin/sh
#
#  apsfilter	Line Printer Input Filter
#  Version:     S.u.S.E.-0.1
#
#  Copyright 1996 S.u.S.E. GmbH
#  Author:   Werner Fink  <werner@suse.de>
#
#  Heavily based on apsfilter-4.9
#
#
# chanded 31.12.1997 by Peter Sobisch
# for directly support of CMY CMY+K for color printers.
#
#

##	Copyright by Andreas Klemm <andreas@knobel.gun.de> 1993, 1994, 1995
##	co-author: Thomas Bueschgens <sledge@hammer.oche.de>
##
##	You are permitted to modify and distribute apsfilter in the
##	terms of the GNU Public License (GPL) see below.
##
##	For Unix Systems With BSD Alike Print Mechanism (lpd, /etc/printcap)
##
##	Supports The Following File Types:
##
##		Ascii, DVI, PS, Data (PCL,...), GIFF, TIFF, PBM, 
##		Sun Raster, X11 Bitmap
##
##	Supports The Following Compression Types:
##
##		Compress, Gzip, Freeze
##
##	and various contributors

#
#  Fore debugging --- see for stderr in /var/spool/.../log
#  for output see under /tmp/ in aps_out.<num>
#
#set -x
#REMOTE_PRINTER="true"
#PRINT_TO_FILE="true"

#
#  Global environment 
#
PATH=/bin:/usr/bin:/usr/local/bin
PATH=${PATH}:/usr/bin/TeX:/usr/X11R6/bin
PATH=${PATH}:/sbin:/usr/sbin
export PATH

     NOTIFY=root
   FAULTMSG="apsfilter: printer fault"
      MAILX=mailx
      XDOTS=0
      YDOTS=0
      SPOOL=/var/spool
  APSFILTER=/var/lib/apsfilter
REWINDSTDIN=${APSFILTER}/rewindstdin
   GIFTOPXM=giftopnm
    SUNRAST=pnm

   TMP_FILE=/tmp/aps.$$
trap "rm -f $TMP_FILE" 0 1 2 3 5 9 10 13 15

if      [ -f /usr/lib/teTeX/texmf.cnf ] ; then
    TETEXDIR=/usr/lib/teTeX
elif    [ -f /usr/lib/TeX/texmf.cnf ] ; then
    TETEXDIR=/usr/lib/TeX
elif    [ -f /usr/lib/tex/texmf.cnf ] ; then
    TETEXDIR=/usr/lib/tex
elif    [ -f /usr/local/TeX/texmf.cnf ] ; then
    TETEXDIR=/usr/local/TeX
elif    [ -f /usr/local/tex/texmf.cnf ] ; then
    TETEXDIR=/usr/local/tex
elif    [ -f /usr/teTeX/texmf.cnf ] ; then
    TETEXDIR=/usr/teTeX
elif    [ -f /usr/TeX/texmf.cnf ] ; then
    TETEXDIR=/usr/TeX
elif    [ -f /usr/tex/texmf.cnf ] ; then
    TETEXDIR=/usr/tex
fi
[ -n "$TETEXDIR" ] && export TETEXDIR

#
#  Load some handler
#
. ${APSFILTER}/handler/functions

#
#  Why not use the options given by lpd or plp (LPRng?)?
#  Parse options given by the printer Daemon!
#
while [ -n "$1" ] ; do
    case $1 in
	-P*)   PRNAME=`striptwo ${1}` ; shift ;; # Ignored
	-c)  CTRLCHAR="yes"           ; shift ;; # Ignored
	-w*)    WIDTH=`striptwo ${1}` ; shift ;; # Ignored
	-l*)   LENGTH=`striptwo ${1}` ; shift ;; # Ignored
	-i*)   INDENT=`striptwo ${1}` ; shift ;; # Ignored
	-x*)    XDOTS=`striptwo ${1}` ; shift ;; # Ignored
	-y*)    YDOTS=`striptwo ${1}` ; shift ;; # Ignored
	-N*)     NAME=`striptwo ${1}` ; shift ;; # Same as JOB
	-S*)  COMMENT=`striptwo ${1}` ; shift    # Ignored
	    while true ; do
		case $1 in
		    -*) break ;;
		    *)  COMMENT="${COMMENT} ${1}" ; shift ;;
		esac
	    done ;;
	-Y*)    PERML=`striptwo ${1}` ; shift ;; # Ignored
	-J*)      JOB=`striptwo ${1}` ; shift ;; # Used if set
	-C*) PRIORITY=`striptwo ${1}` ; shift ;; # Ignored
	-n*)   PERSON=`striptwo ${1}` ; shift ;; # Used if set
	-h*)     HOST=`striptwo ${1}` ; shift ;; # Used if set
	-F*)     TODO=`striptwo ${1}` ; shift ;; # Ignored
	-*)                             shift ;; # Ignored
	*)   ACCTFILE=${1}            ; shift ;; # Should be ACCTFILE
    esac
done

#
#  if apsfilter is called as:
#
#	djet500-a4-{auto,ascii,raw}-{color,mono}-dpi
#	  $1    $2        $3             $4       $5
#	then we get printer type and papersize from the apsfilter call itself
#	METHOD=auto	enables filetype auto recognition
#	METHOD=ascii	force printing method print ascii
#	METHOD=raw	write to print device unfiltered ....
#	COLOR=color	use color-postscript
# 	COLOR=mono	transform color to b&w postscript... so one is
# 			able to save colored pens on a colorprinter
#	DPI=<NUM>x<NUM>
#	DPI=<NUM>	Resolution of the printer type
#
set -- `basename $0 | tr '-' ' '`

: ${compat="false"}
[ "$1" = "aps" ] && { shift; compat=true; }

PRINTER="$1"; PAPERSIZE="$2"; METHOD="$3"; COLOR="$4"; DPI="$5"

#
#  Do we have arguments given by the daemon?
#
if [ -z "$JOB" -o -z "$PERSON" -o -z "$HOST" ] ; then
    if [ ! -f $ACCTFILE ] ; then
	if [ "$compat" = "true" ] ; then
	    LOCK="${SPOOL}/${PRINTER}-${PAPERSIZE}-${METHOD}-${COLOR}/lock"
	    [ "$METHOD" = "raw" ] && LOCK="${SPOOL}/${PRINTER}-raw/lock"
	else
	    LOCK="${SPOOL}/lpd/${PRINTER}-${PAPERSIZE}-${METHOD}-${COLOR}-${DPI}/lock"
	    [ "$METHOD" = "raw" ] && LOCK="${SPOOL}/lpd/${PRINTER}-${PAPERSIZE}-raw/lock"
	fi
    else
	LOCK="`dirname ${ACCTFILE}`/lock"
    fi
      CF=`tail -1 ${LOCK}`
     JOB=`grep -E '^J' ${CF} | tail +2c`
  PERSON=`grep -E '^P' ${CF} | tail +2c`
    HOST=`grep -E '^H' ${CF} | tail +2c`
fi
[ "$DPI" = "default" ] && DPI=""
#
# Users home dir ... check nis domain
# if there is a nis domain we will use yp interface
# Note: domainname gives NOT dns domain but nis domain,
#       this is a common rule under UNIX[tm]!
#
YPD="`domainname`"
YPS="`tail -1 /etc/passwd|head -1c`"

if [ -n "$YPD" -a "$YPS" = "+" ] ; then
    set -- `ypcat passwd|(cat /etc/passwd -)|grep "^$PERSON:"|cut -d':' -f6`
else
    set -- `grep "^$PERSON:" /etc/passwd |cut -d':' -f6`
fi
HOMEDIR="$1"

#
#  The user should know what's happen
#
[ "$PERSON" != "$NOTIFY" ] && NOTIFY="-c $NOTIFY $PERSON"

#
#  FILE TYPE AUTO_RECOGNITION
#    first set output of the ``file'' command to new script arguments:
#    $1, $2, ..., $n ; then throw away $1 and $2 since that is the 
#    "file name" = "standard input:" ; the rest is a "string" which
#    consist of one or multiple words describing the file type. 
#    For example: "Korn Shell Script"
#
  FILE_TYPE=""
HAVE_UNPACK=""
 DECOMPRESS=""

set_type () { (grep -Ev '^$' 2>/dev/null |file - |tr 'A-Z' 'a-z'); }
#
case $METHOD in
	ascii|auto)
		set -- `set_type; $REWINDSTDIN`
		shift ; shift
		FILE_TYPE="$*"
		#
		# check if we have to uncompress something
		case "$FILE_TYPE" in
		    *gzip*)	{ . ${APSFILTER}/unpack/gzip ;     }	;;
		    *compress*)	{ . ${APSFILTER}/unpack/compress ; }	;;
		    *frozen*)	{ . ${APSFILTER}/unpack/melt ;     }	;;
		    *packed*)	{ . ${APSFILTER}/unpack/gzip ;     }	;;
		    *)		# it's not compressed !
		esac ;;
	*)	# raw method: nothing to do
esac
#
#  For method auto we want to known file type of contents
#
if [ -n "$HAVE_UNPACK" ] ; then
	set_type () { ($HAVE_UNPACK|grep -Ev '^$' 2>/dev/null |file - |tr 'A-Z' 'a-z'); }
	case  $METHOD in
		auto)
			set -- `set_type; $REWINDSTDIN`
			shift ; shift
			FILE_TYPE="$*"
			DECOMPRESS="eval $HAVE_UNPACK|" ;;
		*)
			DECOMPRESS="eval $HAVE_UNPACK|" ;;
	esac
fi

#
#  No color in ascii method!
#
[ "$METHOD" = "ascii" ] && COLOR="mono"

# If COLOR=CTY or CTY+K then lied them directly to gs
# changed by Peter Sobisch
#
case $COLOR in
	color)	# color-mode! set some options so color makes it to
		# the postscript-printer!
		RAS2PS_OPTS="-C"
		DJPEG_OPTS="-colors 256"
		;;
	mono)	# mono-printer or mono-mode
		# Unset all color-dependent flags
		GS_FEATURES="-dBitsPerPixel=1"
		DJPEG_OPTS="-grayscale"
		;;
	*)	# HP Color Mode ! mode lied directly to gs
		# and the color flags too
		GS_FEATURES=$GS_FEATURES" -sColourMode="$COLOR
                RAS2PS_OPTS="-C"
                DJPEG_OPTS="-colors 256"
		;;
esac

#
#  Set some usefull(?) defaults for printing and then read
#  the systemwide resource file /etc/apsfilterrc
#
[ "$REMOTE_PRINTER" != "true" ] && REMOTE_PRINTER=""
DVIPS_MODE=""
  GS_RESOL="$DPI"
[ "$compat" = "true" ] && GS_RESOL=""

case $PRINTER in
	hpdj|cdj*|*desk*|[dl]jet*|laserjet|lj4*|dnj*|paintjet|pj*)
		#Translate LF to CR+LF and FF to CR+FF
		CRLF='\033&k2G'
		# Perforation Skip Mode off (DIN A4: 66 lines/page)
		SKIPOFF='\033&l0L'
		PRINT_RAW_SETUP_PRINTER="${CRLF}${SKIPOFF}"
		;;
	*)
		# Anybody knows some good initialisation for some
		# printers ?
		PRINT_RAW_SETUP_PRINTER=""
		;;
esac

#
#  Here we are: the systemwide resource file
#  Note: Maybe we need some special setups for special printers.
#  Therefore a /etc/apsfilterrc.${PRINTER} is usefull!?
#
[ -f /etc/apsfilterrc ]            && { . /etc/apsfilterrc ; }
[ -f /etc/apsfilterrc.${PRINTER} ] && { . /etc/apsfilterrc.${PRINTER} ; }

#
# The user apsfilterrc setup ... parsing and reading only allowed syntax
#
userrc=$HOMEDIR/.apsfilterrc
if [ -n "$HOMEDIR" -a -r $userrc ] ; then
    #
    # We only allow this few VARIABLES in user space
    #
    allowed="TEXINPUTS|PRINT_DVI|GS_FEATURES|USE_RECODE_NOT_A2PS"
    allowed="$allowed|FEATURE|A2PS_OPTS|DVIPS_MODE|GS_RESOL"

    #
    # $badchar contains the forbidden characters ... those
    # maybe break this script or fore instance make it insecure
    # notation is given in manual ascii(7)
    #
    badchar="$(echo -e ' \000\003\b\t\n\r\033')"
    extract=$(grep -E "^($allowed)\=[^$badchar]+$" $userrc)

    for line in $extract; do
	eval "$line"
    done
    unset badchar extract line allowed
fi
unset userrc

#
# If TEXINPUTS is set we have to export it
#
[ -n "$TEXINPUTS" ] && { export TEXINPUTS ; }

#
#  Options for dvips
#
#	-M		Don't create fonts automatically using MakeTeXPK
#	   		since there is a bug in it causing apsfilter to exit
#	   		after creating the first missing Font.
#	-q		Quiet mode
#	-r		Print last page first
#	-t <papertype>	Have a look into /usr/lib/teTeX/texmf/dvips/config.ps
#			And use command texconfig for default
#	-D <num>	Horizontal and vertical resolution in dpi
#	-D <X>x<Y>	Horizontal resolution, vertical resolution in dpi 
#	-P <name> 	Alternated config file
#			/usr/lib/teTeX/texmf/dvips/config.<name>
#	-X <num>	Horizontal resolution in dpi 
#	-Y <num>	Vertical   resolution in dpi 
#	-Z		Compress bitmap fonts
#

setres ()
{
	if [ -z "$GS_RESOL" ]; then
		# $1 is resolution
		RES="-D $*"
	else
		# ignore default resolution
		# use the argument given by our link name
		shift
		RES="-D $GS_RESOL $*"
	fi
}

case $PRINTER in
	PS_*dpi)
	    RES="-D `echo ${PRINTER}|sed 's@PS_@@;s@dpi@@'`"
	    [ `echo $RES|grep -cE '^([0-9]+|[0-9]+x[0-9]+)$'` -eq 0 ] && RES=300
	    [ -n "$DPI" ] && RES="$DPI"
	    ;;
	PS_*)			setres 300        ;;
	cdj*|*desk*|djet*)	setres 300 -r     ;;
	dnj*c)			setres 300 -r     ;;
	hpdj)			setres 300 -r     ;;
	ljet4l)			setres 300        ;;
	ljet4)			setres 600        ;;
	lj4dith)		setres 600        ;;
	laserjet|ljet[23]*)	setres 300        ;;
	paintjet|pj*)		setres 300        ;;
	necp6)			setres 360        ;;
	bj10e|bj200|bjc[68]00)	setres 360 -r     ;;
	stcolor|st800)		setres 360 -r     ;;
	eps9*)			setres 240x216 -r ;;
	epson)			setres 360x180 -r ;;
	epsonc)			setres 360x180 -r ;;
	*)			setres 300 -r     ;;
esac

#
#  The light version of ljet4 acts like a ljet4 at 300dpi
#
[ "$PRINTER" = "ljet4l" ] && PRINTER=ljet4

#
#  Quiet (-q) and compresssed fonts (-Z) set to default
#
DVIPS_OPTS="-q -Z $DVIPS_MODE $RES"
case $PAPERSIZE in
	letter|legal|ledger)	DVIPS_OPTS="$DVIPS_OPTS -t $PAPERSIZE"	;;
	11x17)			DVIPS_OPTS="$DVIPS_OPTS -t Tabloid"	;;
	a3)			DVIPS_OPTS="$DVIPS_OPTS -t A3"		;;
	a4)			DVIPS_OPTS="$DVIPS_OPTS -t A4"		;;
	*)			DVIPS_OPTS="$DVIPS_OPTS -t Letter"	;;
esac
[ "$PAPERSIZE" = "tabloid" ] && PAPERSIZE=11x17

#
#  Now let's see how to print PostScript
#
case $PRINTER in
	PS_*)
		# our printer is a PS printer...	
		PRINT_PS="cat -"
		;;
	*)	# we have a nice non ps printer
		findfilter gs GS
		if [ -n "$GS_RESOL" ] ; then
			GS_RESOL="-r${GS_RESOL}"
		fi
		PRINT_PS="$HAVE_GS -q -sDEVICE=${PRINTER}   ${GS_RESOL}    \
				   -sPAPERSIZE=${PAPERSIZE} ${GS_FEATURES} \
			   	   -dNOPAUSE -dSAFER -sOutputFile=- - "
		;;
	esac

#
#  Debugging or remote printer
#
[ "$PRINT_TO_FILE"  = "true" ] && PRINT_PS="(cat 1> /tmp/aps_out.$$)"
##if [ -z "$BASH_VERSION" ] ; then
    [ "$REMOTE_PRINTER" = "true" ] && PRINT_PS="$PRINT_PS |lpr -Premote"
##else
##    [ "$REMOTE_PRINTER" = "true" ] && PRINT_PS="$PRINT_PS > >(lpr -Premote)"
##fi

#
#  And now ... we print
#
case $METHOD in
	raw)	{ . $APSFILTER/filter/raw   ; } ; print_stdin ;;
	ascii)	{ . $APSFILTER/filter/ascii ; } ; print_stdin ;;
	auto)
		#
		# Maybe we should do this dynamical
		# for f in $APSFILTER/filter/* ; do ... done
		#
		case "$FILE_TYPE" in
			*fig*)
				{ . $APSFILTER/filter/fig ;        } ; print_stdin ;;
			*tiff*)
				{ . $APSFILTER/filter/tiff ;       } ; print_stdin ;;
			*gif*)
				{ . $APSFILTER/filter/gif ;        } ; print_stdin ;;
			*jpeg*)
				{ . $APSFILTER/filter/jpeg ;       } ; print_stdin ;;
			*pnm*|*pbm*|*ppm*)
				{ . $APSFILTER/filter/pnm ;        } ; print_stdin ;;
			*sun*raster*)
				{ . $APSFILTER/filter/sunraster ;  } ; print_stdin ;;
			postscript*)
				{ . $APSFILTER/filter/postscript ; } ; print_stdin ;;
			*pdf*document*)
				{ . $APSFILTER/filter/pdf ;        } ; print_stdin ;;
			*dvi*)
				{ . $APSFILTER/filter/dvi ;        } ; print_stdin ;;
			*data*|*escape*)
				# that's certainly not critical,
				# you're on your own ;-)
				{ . $APSFILTER/filter/data ;       } ; print_stdin ;;
			*troff*)
				{ . $APSFILTER/filter/troff ;      } ; print_stdin ;;
			*ascii*|*text*|*english*|*script*)
				{ . $APSFILTER/filter/ascii ;      } ; print_stdin ;;
 			*)		
				# data we - I'm so sorry - don't know
				fault_filetype
				exit 1 ;;
		esac ;;
	*)
		fault_method
		exit 1 ;;
esac

#
# Puh ... done
#
exit 0

