#ident "@(#)netatalk 0.7 99/06/22 job@uchicago.edu" /* Netatalk 1.4*/ ##### # User configuration: # # Set timeout for pap($time) and papstatus($time2). both are in seconds. # extraneous if you do not have NETATALKHOME/bin/timeout # set how many times to loop before we just abort entirely ($attempts) # what flags pap is run w/. -c makes pap claim to have been waiting forever ##### time=1800 time2=60 attempts=3 pap_flags="-c" ##### # this should get "fixed" to something like # NETATALKHOME=/opt ; export NETATALKHOME # by the add_netatalk_printer script # # DO NOT use the user's env for this or the PATH above. ##### NETATALKHOME=DEFAULT_NETATALK_HOME ; export NETATALKHOME #NETATALKHOME=/opt ; export NETATALKHOME if [ "${NETATALKHOME}" = "DEFAULT_NETATALK_HOME" ]; then echo "bleah, NETATALKHOME not set, exiting..." ; exit 5 fi ##### # BUGS/TODO: # move all TMP stuff to use a directory for security reasons # run nbplkup to check if the reason we cannot print, is that it's not on # the net # move to "${foo}" from $foo and ${foo} # add debuging info that gets sent to "logger lpd.debug" # if we timeout while printing the banner page, we do not keep trying to print. # perhaps filter_timeout should only complain once per job; like badfile. # check if the timeout messages are duplicated by the lp system # psa will not drop in for pap to use accting. perhaps lp does not need it? # make pap print all the files at once; kill for file in ($files) # move badfile error to printfile function ##### # This File is released under the Perl Artistic Licence. # See http://www.perl.org for details # # Or you can use it under the licence that accompanies Netatalk 1.3 =) ########### ## Netatalk printer interface. Heavily modified from ## /usr/lib/lp/model/standard on Sparc Solaris 2.5.1 (May 97) ## ## Meant to be used w/ add_netatalk_printer ########### ##### # 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 argument(s) is/are the file(s) to print. ##### ##### # # The protocol between the interface program and the Spooler # is fairly simple: # # All standard error output is assumed to indicate a # fault WITH THE REQUEST. The output is mailed to the # user who submitted the print request and the print # request is finished. # # If the interface program sets a zero exit code, # it is assumed that the file printed correctly. # If the interface program sets a non-zero exit code # less than 128, it is assumed that the file did not # print correctly, and the user will be notified. # In either case the print request is finished. # # If the interface program sets an exit code greater # than 128, it is assumed that the file did not print # because of a printer fault. If an alert isn't already # active (see below) one will be activated. (Exit code # 128 should not be used at all. The shell, which executes # this program, turns SIGTERM, used to kill this program # for a cancellation or disabling, into exit 128. The # Spooler thus interpretes 128 as SIGTERM.) # # A message sent to the standard input of the ${LPTELL} # program is assumed to describe a fault WITH THE PRINTER. # The output is used in an alert (if alerts are defined). # If the fault recovery is "wait" or "begin", the printer # is disabled (killing the interface program if need be), # and the print request is left on the queue. # If the fault recovery is "continue", the interface program # is allowed to wait for the printer fault to be cleared so # it can resume printing. # ##### ########################################################################### # # Set up the basic traps. and other important things # ########################################################################### ##### # For the time being, just exit if we are poked. ##### # SIGTERM handler trap 'exit' 15 ##### # We can be clever about getting a hangup or interrupt, though, at least # until the filter runs. Do this early, even though $LPTELL # isn't defined, so that we're covered. ##### trap 'catch_hangup; exit_code=129 exit 129' 1 trap 'catch_interrupt; exit_code=129 exit 129' 2 3 ##### # VARIBLE DECLARED - put here so we don't ever run the trap below w/o # TMPPREFIX defined. We hard code /tmp for the moment, but fix that later # # Use ${TMPPREFIX} as the prefix for all temporary files, so # that cleanup is easy. The prefix may be up to 13 characters # long, so you only have space for one more character to make # a file name. If necessary, make a directory using this prefix # for better management of unique temporary file names. ##### TMPPREFIX=/tmp/`uname -n`$$ ##### # Before exiting, set ${exit_code} to the value with which to exit. # Otherwise, the exit from this script will be 0. ##### trap 'rm -fr ${TMPPREFIX}*; exit ${exit_code}' 0 catch_hangup () { if [ -n "${LPTELL}" ] then echo \ "Humm, we got a SIGHUP. Not sure what it means, but... we'll keep going anyway" \ | ${LPTELL} "${printer}" fi return 0 } catch_interrupt () { if [ -n "${LPTELL}" ] then echo \ "Received an interrupt from the printer. The reason is unknown." \ | ${LPTELL} "${printer}" fi return 0 } ##### # Most of the time we don't want the standard error to be captured # by the Spooler, mainly to avoid "Terminated" messages that the # shell puts out when we get a SIGTERM. We'll save the standard # error channel under another number, so we can use it when it # should be captured. # # Open another channel to the printer port, for use when the # regular standard output won't be directed there, such as in # command substitution (`cmd`). ##### exec 5>&2 2>/dev/null 3>&1 ########################################################################### # # Define local varibles and such # ########################################################################### ##### # There is one more varible set by the shell that execs us. # FILTER The filter to run ; we ignore this directive ##### ##### # Use the user set env, or else default to standard values. ##### : ${SPOOLDIR:=/usr/spool/lp} : ${TMPDIR:=/tmp} ; export TMPDIR : ${LOCALPATH:=${SPOOLDIR}/bin} ; export LOCALPATH PATH="/bin:/usr/bin:${LOCALPATH}:${NETATALKHOME}/bin:${NETATALKHOME}/etc" export PATH TMPPREFIX=${TMPDIR}/`uname -n`$$ ##### # Error levels for the errmsg() func. ##### LP_ERR_LABEL="UX:lp" ; export LP_ERR_LABEL E_IP_ARGS=1 E_IP_OPTS=2 E_IP_UNKNOWN=5 E_IP_BADFILE=6 ##### # Error message formatter: # # Invoke as # # errmsg severity message-number problem help # # where severity is "ERROR" or "WARNING", message-number is # a unique identifier, problem is a short description of the # problem, and help is a short suggestion for fixing the problem. ##### errmsg () { case $1 in ERROR ) sev=" ERROR"; ;; WARNING ) sev="WARNING"; ;; esac echo "${LP_ERR_LABEL}: ${sev}: $3 TO FIX: $4" >&5 } parse () { echo "`expr \"$1\" : \"^[^=]*=\(.*\)\"`" } ##### # die quickly if we do not have the right number of arguments. ##### 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` request_id=$1 # this will formated be machine!username, so we want to split that up... user_name=$2 machine=`echo $user_name | cut -d! -f1` user_name=`echo $user_name | cut -d! -f2` title=$3 copies=$4 option_list=$5 shift 5 files="$*" nobanner="yes" inlist= for i in ${option_list} do case "${inlist}${i}" in nobanner ) nobanner="yes" ;; banner ) nobanner="no" ;; ##### # # If you want to add simple options (e.g. -o simple) # identify them here. ##### # simple ) # simple="yes" ;; ##### # These get ignored, but would matter little anyway since all we see # here is PS anyway. ##### cpi=* ) # cpi=`parse ${i}` ;; true ;; lpi=* ) # lpi=`parse ${i}` ;; true ;; length=* ) # length=`parse ${i}` ;; true ;; width=* ) # width=`parse ${i}` ;; true ;; ##### # If you want to add simple-value options (e.g. -o value=a) # identify them here. ##### #value=* ) # value=`parse ${i}` ;; flist=* ) flist=`parse ${i}` ;; input* ) true ;; * ) errmsg WARNING ${E_IP_OPTS} \ "unrecognized \"-o ${i}\" option" \ "check the option, resubmit if necessary printing continues" ;; esac done ##### # A bit ugly, but grabs the appletalk printer name from the lp system printer # description, so it's right up there in admintool. the appletalk name must # be delimited by [ and ]. # # eg - 'this is the printer [hp-mrsec-l114:lasershared@Research Insitutes] that i use.' ##### PAPDEST="`lpstat -D -p "${printer}" | grep -i descrip | sed 's/.*Description:.*\[//g' | sed 's/\].*//g'`" export PAPDEST ########################################################################### # # Define our local functions (parse is declared above option parsing) # ########################################################################### banner () { echo "##### User: ${user_name}" echo "" echo "##### Machine: ${user_name}" echo "" if [ -n "${title}" ] then echo "##### Title: ${title}" echo "" fi echo "##### Files: ${flist}" echo "" ##### # this should deal w/ the year 2000 ok. But will die in 2038. =) ##### YEAR=`date '+%y'` YEAR=`expr 1900 + ${YEAR}` echo "##### Date: `date '+%a %H:%M %h %d,'` ${YEAR}" echo "" echo "##### Job: ${request_id}" echo "" } print_banner() { if [ -x ${NETATALKHOME}/bin/timeout ] then banner | ${NETATALKHOME}/etc/psf \ | ${NETATALKHOME}/bin/timeout "${time}" ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}" else banner | ${NETATALKHOME}/etc/psf \ | ${NETATALKHOME}/bin/pap -c -p "{PAPDEST}" fi if [ ${?} -ne 0 ] then filter_timeout fi } ##### # ${LPTELL} is the name of a program that will send its # standard input to the Spooler. It is used to forward # the description of a printer fault to the Spooler, # which uses it in an alert to the administrator. ##### 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 ##### # timeout catcher for the printing filter ##### filter_timeout() { cat > ${TMPPREFIX}D <&1 >> ${TMPPREFIX}D paperr=${?} errmsg WARNING ${E_IP_UNKNOWN} "`cat ${TMPPREFIX}D`" "printing continues" ##### # This ought to deal w/ the problem of nonexistent appletalk names, but... # for the moment, it calls filter_death. But it sends the papstatus # info to LPTELL anyhow, so you should be able to see the error. ##### if [ ${paperr} -ne 0 -o ${too_many} = "1" ]; then paperr= filter_death fi paperr= echo "serverdict begin 0 exitserver systemdict /quit get exec" | \ ${NETATALKHOME}/bin/pap -c -p "${PAPDEST}" return 0 } ##### # Death catcher for filter_timeout ##### filter_death() { cat > ${TMPPREFIX}Z <