#!/usr/bin/ksh - # Instead of straight lpr, lpq or lprm, # to go to right printer and with right options. # Also clones lpc, lpstat, lp and cancel; it even does ifilter. # Allows sloppy printer names (like ao) and names with room numbers (like # c728 or L728) instead of real names (like aolw); may take printer name # from command name (invoke with names like pao or pq728). # If printer is not specified, will use 'nearest' printer. Use options # -lab or -nolab to restrict search to lab printers, or to go outside. # The option -nolab is default for staff (even if actually in a lab), # otherwise (for undergrads) it is -lab. # The options -laser, -nolaser or -dotmatrix are obsolete and ignored # (since we do not have dotmatrix printers any more); -laser is default # for staff (even if actually in a lab), otherwise it is -nolaser. # We may run a2ps (or mpage) for printers that can only print PostScript; # we may run gs for printers that do not understand it. # Also check nearest printers as set up later. # 'Named' printers are also listed with their room numbers, and re-routed later. # (But note that non-LPRng machines may send jobs to other queues: beware salw.) # We keep historical names aolw=r7lw and f5lw=r5lw. known_printers='aolw r7lw c728 p6lw c612 fylw c520 lklw mslw c823 salw otlw c524 rzlw c722 solw c531 djlw c532 f5lw r5lw c533 c534 pglw c807 gllw c813 njlw c522 dclw c620 colw stlw' Epson_printers= text_printers="$Epson_printers" PS_printers='aolw r7lw p6lw fylw lklw mslw salw otlw rzlw solw djlw f5lw r5lw pglw gllw njlw dclw colw stlw' duplex_printers='aolw r7lw p6lw fylw lklw mslw otlw rzlw solw djlw f5lw r5lw pglw gllw njlw colw stlw' staple_printers='aolw r7lw p6lw fylw lklw f5lw r5lw stlw' colourps_printers='colw gllw rzlw solw njlw' PJL_printers='aolw r7lw p6lw fylw lklw mslw salw otlw rzlw solw djlw f5lw r5lw pglw gllw njlw dclw colw stlw' # Some printers have a (16-character) * (2-line) display; # some have (20-character) * (4-line) ... char20_printers='aolw p6lw stlw mslw f5lw colw otlw fylw solw gllw rzlw njlw pglw' ### PCL printing allowed on 12 Nov 99: Jonathan Huang 15353 (from ITS) has difficulties with UNIX and PS printing PCL_printers='salw otlw' ## PDF printing works fine with @PJL ENTER LANGUAGE = PDF ## but HP LaserJets use letter size, even with @PJL SET PAPER = A4 ... ## Despite advertising blurb, our LJ4350 printers (mslw) cannot do. PDF_printers='aolw r7lw f5lw r5lw' # Personal printers without page/size limits unlimited_printers='njlw gllw rzlw dclw' PSpgcnt_printers='aolw r7lw p6lw fylw lklw mslw salw otlw rzlw solw djlw f5lw r5lw pglw gllw njlw dclw colw stlw' mpagecnt_printers= bytecnt_printers= BJC_printers= # Permissions are only checked in lpd.perms. (Would like neater error # messages, but too hard to keep in sync.) Except we need to know about # staff groups (for setting of class, and default -lab or not): staff_groups='amstaff amvisitor amodd ampgrad amfour pmstaff pmtsd pmvisitor pmother pmgrad pmfour ststaff stvisitor stother stgrad stfour vacsch staff daemon' # Should have page limits, not bytes or lines. But how to count pages? # I suppose we could use 'pr | wc -l' for text files, but we do not. # We use mpage for PS files (which we do, again, for printers that cannot # 'talk back' to report pagecounts). # What about Epson and BJC files? # These limits are a means of "self-preservation" only (so as not to use # ridiculous resources for checking and rejecting): we have print quotas. # Print quotas (as of now) do not have limits on single jobs; but do we # care whether they blow their allocation on a single large job or several # small ones? Anyway, many weekly quotas are smaller than any sensible # limits we might put here. # (They are also a limit for those PS jobs that the printer interprets as PCL, # printing many blank pages only...) BYTE_LIMIT_text_staff=100000 LINE_LIMIT_text_staff=2500 BYTE_LIMIT_text_studt=32000 LINE_LIMIT_text_studt=720 BYTE_LIMIT_text_unlim=1000000 LINE_LIMIT_text_unlim=10000 BYTE_LIMIT_ps_staff=145000000 LINE_LIMIT_ps_staff=9500000 PAGE_LIMIT_ps_staff=500 BYTE_LIMIT_ps_studt=40000000 LINE_LIMIT_ps_studt=2000000 PAGE_LIMIT_ps_studt=40 BYTE_LIMIT_ps_unlim=250000000 LINE_LIMIT_ps_unlim=15000000 PAGE_LIMIT_ps_unlim=1500 PAGE_LIMIT_pdf_staff=500 PAGE_LIMIT_pdf_studt=40 PAGE_LIMIT_pdf_unlim=1500 BYTE_LIMIT_epson_staff=400000 BYTE_LIMIT_epson_studt=400000 BYTE_LIMIT_epson_unlim=1000000 BYTE_LIMIT_bjc_staff=4000000 BYTE_LIMIT_bjc_studt=1000000 BYTE_LIMIT_bjc_unlim=10000000 BYTE_LIMIT_pcl_staff=400000 # Some PeopleSoft files are rather large... BYTE_LIMIT_pcl_studt=32000 BYTE_LIMIT_pcl_unlim=1000000 # The real lpr and friends do not like an ugly environment, # fix up common stuff-ups. (Beware: ifilter may have empty PATH.) PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/sms/bin:/usr/sms/sbin export PATH unset LD_LIBRARY_PATH LD_PRELOAD # both used in matlab R2008b unset TEXMACS_FILE_PATH TEXMACS_STYLE_PATH GUILE_LOAD_PATH # Any other long environment variables? long="$(printenv | perl -ne 'print "$1 " if m/^(\w+)=.{200}/')" if [ -n "$long" ]; then #print "Unsetting: $long" unset $long fi # We use mpage, might be upset by funny options unset MPAGE MPAGE_LIB # Now that /tmp is 'larger' (at least on rome/milan/turin), we use that in # preference to /usr/tmp (which is subject to disk quotas). TMPD=/tmp/lpr.$$ TMPFN=0 # Set safe umask for those tmp files umask 077 # Remove any possible temp files on exit. Could be included in error() for # genuine errors, but trap also works for ctrl-C. (Is not this overkill?) trap "rm -rf $TMPD" EXIT set -f function warn { print -u2 -R "?($PRF_NAME) Warning/Info: $1 (PSz/queue manager)" } function error { case "$mode" in ifilter ) print -u2 -R "$(date '+%Y/%m/%d %T (%a)') $*: <$QUE> <$USR> <$HST> <$NAM>"; exit;; * ) print -u2 -R "?($PRF_NAME) $1 (PSz/queue manager)"; exit 1;; esac } function error_file { error "${TF_done}File '$1' is $2 - cannot be printed" } function mktmpfile { if [ "$TMPFN" = 0 ]; then if [ -e "$TMPD" -o -L "$TMPD" ]; then error "Internal error (temp dir $TMPD exists). Sorry"; fi mkdir -m 700 "$TMPD" status="$?" if [ "$status" != 0 ]; then error "Internal error (cannot mkdir $TMPD). Sorry" fi TMPFN=1 fi if [ ! -d "$TMPD" ]; then error "Internal error (temp dir $TMPD does not exist after mkdir). Sorry"; fi if [ \( ! "$TMPFN" -ge 1 \) -o \( ! "$TMPFN" -le 20 \) ]; then error "Internal error (bad TMPFN $TMPFN). Sorry"; fi TMPF="$TMPD/tmp$TMPFN" (( TMPFN = $TMPFN + 1 )) if [ -e "$TMPF" -o -L "$TMPF" ]; then error "Internal error (temp file $TMPF exists). Sorry"; fi touch "$TMPF" if [ ! -f "$TMPF" ]; then error "Internal error (temp file $TMPF does not exist after touch). Sorry"; fi if [ -s "$TMPF" ]; then error "Internal error (temp file $TMPF is not empty after touch). Sorry"; fi if [ -b "$TMPF" -o -c "$TMPF" -o -d "$TMPF" -o -g "$TMPF" -o -k "$TMPF" -o -L "$TMPF" -o -p "$TMPF" -o -S "$TMPF" -o -u "$TMPF" ]; then error "Internal error (temp file $TMPF is bad type or has bad permissions). Sorry" fi } function list_txt_file # List PS or text file: strip out common un-printables. Unless # $1 is '-test', also remove any other rubbish in 'cat -v' style: # allow through TAB, NL and DEL characters only (not even BS or FF, # but DEL is used in PS generated by acroread). # Strip out PJL encapsulation: ensure that our commands get through, # prevent shenanigans like http://www.phenoelit.de/hp/ . # With '-nonl' option, we skip leading empty lines and ctrl-D # characters: mpage does not like them before a %! on PS files... ### Maybe we should have separate list_txt_file, list_ps_file and ### even a list_pcl_file routines?? ## We want rubbish stripped out, but want to be nice and allow ## for common non-printables (mostly in PC, mostly PS files): ## SOH/CR at end of line (in PCL files for SUHRF from oberon.ucc) ## CR at end of line ## ctrl-D: often last, but sometimes first, character in file ## ctrl-T at \010000 = 8^4 = 2^12 = 4kB ## long line with embedded CR (some crest files have a single 60kB line) ## null bytes in front of comments (in PS generated by acroread) ## four null bytes at beginning of line (in PS generated by acroread) ## strip out any PJL command sequences ## we do nothing about (in Pscript_Win_Utils 2.0 0): ## %%BeginFeature: *Levels of Gray PrinterM-^Rs Current Setting ## %%BeginFeature: *Resolution Enhancement PrinterM-^Rs Current Setting ## we do nothing about (in PS generated by acroread): ## 72 500 moveto (Select M-*Level 1M-: in the PostScript options section) show ## We strip out PS non-duplex commands as it is default on PCs. ## We strip out PS manualfeed commands as we control that. (Is there a way ## to ensure that printer will NOT take paper from manualfeed tray?) ## We replace letter [612 792] size by A4 [595 842]: ## StarOffice 6.0 documents set to letter in (Format, Page, Paper format), ## even with A4 in (PrinterSetup or Print, Properties, Paper), generate ## <> setpagedevice ## and most of our printers give the error: ## %%[ Error: configurationerror; OffendingCommand: setpagedevice; ErrorInfo: PageSize --nostringval-- ]%% ## (error on ao ms dj ot f5 co: LJ4050, LJ4100 and some LJ4000; OK on ## nj gl fy: LJ2200 and one LJ4000; is that error on duplex printers, ## OK on those without a duplexer accessory?; printers in Nov 2002). ## Also, Janet's PC generates ## 2 dict dup /PageSize [612 792] put dup /ImagingBBox null put setpagedevice ## though all settings I could see were for A4... ## Matlab R2006b generates (when set to default letter in File Print PageSetup (not in File PageSetup)): ## << /PageSize [612.0 792.0] /ImagingBBox null /ManualFeed false >> setpagedevice ## Georg's laptop (though set to A4) generated (for landscape maybe?): ## <> setpagedevice ## sed dies when confronted with very long lines; perl seems to cope better. { perlprg=' $test = $ARGV[0] eq "test"; $nonl = $ARGV[0] eq "nonl"; while() { s/\x01\r\n?/\n/g; s/\r\n?/\n/g; s/[\cd\ct]//g; s/^\x00+%/%/; s/^\x00{4}//; if (/\e%-12345X/) { do { $_ = ; } while /^\@PJL/; redo; } if ($nonl) { s/\x04//; next if /^\r?$/; $nonl = 0; } unless ($test) { s/([\x00-\x08\x0b-\x1f\x80-\xff])/ sprintf "", ord $1 /eg; s/<<\s*\/Duplex\s+false\s*(\/Tumble\s+false\s*)?>>\s*setpagedevice//; s/<<\s*\/ManualFeed\s+(true|false)\s*(\/MediaPosition\s+\d+\s*)?>>\s*setpagedevice//; s/\s*false\s+setduplexmode\s*/ /; s/1\s+dict\s+dup\s+\/Duplex\s+false\s+put\s+setpagedevice//; s/(<<\/PageSize) \[\s*612\s+792\s*\] (.*>> setpagedevice)/$1 [595 842] $2/; s/(<<\s*\/PageSize) \[612\.0 792\.0\] (.*>> setpagedevice)/$1 [595 842] $2/; s/(dup \/PageSize) \[ ?612 792 ?\] (put)/$1 [595 842] $2/; s/(<<\/PageSize) \[\s*792\s+612\s*\] (.*>> setpagedevice)/$1 [842 595] $2/; s/(<<\s*\/PageSize) \[792\.0 612\.0\] (.*>> setpagedevice)/$1 [842 595] $2/; s/(dup \/PageSize) \[ ?792 612 ?\] (put)/$1 [842 595] $2/; } print; } ' if [ "$1" = '-test' ]; then perl -e "$perlprg" test elif [ "$1" = '-nonl' ]; then perl -e "$perlprg" nonl else perl -e "$perlprg" # Show that file... fi } function ftransform # Transform file $1 as specified by TF_command { typeset trnf="$1" mktmpfile realfile="$TMPF" if [ "$debug" = true ]; then print -u2 -R "About to do: $TF_command <$trnf >$realfile" fi if [ -n "$TF_warn" ]; then print -u2 -R "$TF_warn" fi eval $TF_command < "$trnf" > "$realfile" status="$?" if [ "$status" != 0 ]; then rm -f "$realfile" error "The run of $TF_reason failed" fi if [ ! -s "$realfile" ]; then rm -f "$realfile" error "The run of $TF_reason did not produce any output" fi case "$TF_command" in a2ps* ) TF_hdr=true;; esac # No need for banner } function chk_ftype # Checks type of file $1, attempts to match it to printer type. # If there is a mismatch, will set TF_command and TF_reason with command # and reason to transform, or maybe quits with error. Sets FTYPE to # expected type of transformed file. { typeset chkf="$1" TF_command= TF_reason= TF_warn= FTYPE= pages_mp=1 if [ -d "$chkf" ]; then error "${TF_done}Name '$chkf' is a directory - cannot be printed"; fi if [ ! -f "$chkf" ]; then error "${TF_done}File '$chkf' does not exist - cannot be printed"; fi if [ ! -s "$chkf" ]; then error_file "$chkf" 'empty'; fi if [ ! -r "$chkf" ]; then error_file "$chkf" 'not readable'; fi set -- $(ls -lL "$chkf") case "$1" in -* ) ;; * ) typeset -L1 type type="$1" error_file "$chkf" "type $type" ;; esac if [ "$class" = unchecked ]; then FTYPE=unchecked; return; fi # Do not check anything else ... bytes_ls="$5" bytes_ls="${bytes_ls##*[a-z]}" ### Bug (feature?): ls runs together long group names and large byte sizes set -- $(wc -lc "$chkf") lines_wc="$1" bytes_wc="$2" set -- $(od -c -N 16 "$chkf" | sed -e 's/^0000000 //' -e 's/ / sp/g' -e q) if [ "$debug" = true ]; then print -u2 -R "Shown by od: $*" fi case "$*" in '037 235 '* | '037 213 '* | '037 036 '* ) FTYPE=Unknown if [ "$debug" = true ]; then case "$*" in '037 235 '* ) FTYPE="Compressed";; '037 213 '* ) FTYPE="gzip compressed";; '037 036 '* ) FTYPE="packed";; esac print -u2 -R "File type: $FTYPE" fi # Compressed, of kind that gunzip understands if [ "$bytes_ls" -gt $BYTE_LIMIT_ps ]; then error_file "$chkf" "$FTYPE, $bytes_ls (over $BYTE_LIMIT_ps) bytes long"; fi if [ "$bytes_wc" -gt $BYTE_LIMIT_ps ]; then error_file "$chkf" "$FTYPE, $bytes_wc (over $BYTE_LIMIT_ps) bytes long"; fi TF_command='gzip -cd' TF_reason='gzcat (needed to uncompress)' return ;; '033 @ 033 P '* | '033 @ 033 t '* ) if [ "$debug" = true ]; then print -u2 -R "File type: Epson ESC/P native" fi # Epson native. Files processed by gs have # '033 @ 033 P 033 l \0 \r 033 Q W 033 J 006 033 *' # while Windows files seem to have # '033 @ 033 t 001 033 6 033 R \0 033 r \0 033 U 001' # Should we test for all that? Used to test for just '033 @ '. if [ "$bytes_ls" -gt $BYTE_LIMIT_epson ]; then error_file "$chkf" "Epson native, $bytes_ls (over $BYTE_LIMIT_epson) bytes long"; fi if [ "$bytes_wc" -gt $BYTE_LIMIT_epson ]; then error_file "$chkf" "Epson native, $bytes_wc (over $BYTE_LIMIT_epson) bytes long"; fi if [ "$can_do_Epson" = true ]; then FTYPE=Epson else error_file "$chkf" 'for Epson printers only' fi return ;; '033 [ K 002 '* ) if [ "$debug" = true ]; then print -u2 -R "File type: Canon BJC native" fi # BJC native. Files produced by gs have # '033 [ K 002 \0 \0 017 033 ( a 001 \0 001 033 ( g' # while Windows files seem to have # '033 [ K 002 \0 \0 017 033 ( b 001 \0 001 033 ( m' # Maybe we could test for # '033 [ K 002 \0 \0 017 033 ( '[ab]' 001 \0 001 033 ( '[gm] if [ "$bytes_ls" -gt $BYTE_LIMIT_bjc ]; then error_file "$chkf" "BJC native, $bytes_ls (over $BYTE_LIMIT_bjc) bytes long"; fi if [ "$bytes_wc" -gt $BYTE_LIMIT_bjc ]; then error_file "$chkf" "BJC native, $bytes_wc (over $BYTE_LIMIT_bjc) bytes long"; fi if [ "$can_do_BJC" = true ]; then FTYPE=BJC else error_file "$chkf" 'for Canon BJC printers only' fi return ;; '% P D F - '[0-9]' . '[0-9]' \n '* | '% P D F - '[0-9]' . '[0-9]' sp \n '* | '% P D F - '[0-9]' . '[0-9]' \r '* ) if [ "$debug" = true ]; then print -u2 -R "File type: PDF (Adobe PortableDocumentFormat)" fi # PDF (Adobe PortableDocumentFormat). # Use PS limits (no need for separate PDF limits: mostly we convert to PS anyway), # except for separate PAGE_LIMIT_pdf (because it is hard to split up PDF files). if [ "$bytes_ls" -gt $BYTE_LIMIT_ps ]; then error_file "$chkf" "PDF, $bytes_ls (over $BYTE_LIMIT_ps) bytes long"; fi if [ "$bytes_wc" -gt $BYTE_LIMIT_ps ]; then error_file "$chkf" "PDF, $bytes_wc (over $BYTE_LIMIT_ps) bytes long"; fi if [ "$lines_wc" -gt $LINE_LIMIT_ps ]; then error_file "$chkf" "PDF, $lines_wc (over $LINE_LIMIT_ps) lines long"; fi if [ "$can_do_PDF" = true ]; then # Some printers can directly to PDF. We assume that all such can do PS also e.g. in printquota if [ -n "$(whence pdfinfo)" ]; then set -- $(pdfinfo "$chkf" 2>&1 | grep '^Pages') pages_mp="$2" case "$pages_mp" in '' | *[!0-9]* ) error_file "$chkf" "PDF, but pdfinfo shows: $*";; esac if [ "$debug" = true ]; then print -u2 -R "pdfinfo count: $pages_mp ($*)" fi if [ "$pages_mp" -gt $PAGE_LIMIT_pdf ]; then error_file "$chkf" "PDF, $pages_mp (over $PAGE_LIMIT_pdf) pages long"; fi else if [ "$debug" = true ]; then print -u2 -R '(No pdfinfo, cannot measure)' fi fi FTYPE=PDF elif [ "$can_do_PS" = true ]; then # acroread or similar PDF-to-PS converter (use "acroread -helpall" for more options) #TF_command='acroread -toPostScript -size a4' #TF_reason='acroread (needed to produce PS)' #TF_warn='Using acroread to convert PDF to PS ... may take a while ...' ## The above worked fine for acroread 7.0.9, but they broke it at 8.1.1: ## does not produce any output (though "acroread -help" says it should ## work). Would need command ## acroread -toPostScript -size a4 -pairs PDFFILE - > PSFILE ## (which is not a filter as we use things), and would anyway create a ## bogus zero-length file named "-". ### convert (ImageMagick) or similar PDF-to-PS converter (produces humungous files) ##TF_command='convert pdf:- ps:-' ##TF_reason='convert' ##F_warn='Using convert to convert PDF to PS ... may take a while ...' #if [ -z "$DISPLAY" ]; then # gs or similar PDF-to-PS converter # Generally acroread is better than gs (often succeeds where gs fails), # but acroread does not work without a DISPLAY setting (even though it # does not need to show anything). TF_command='gs -q -dNOPAUSE -dSAFER -dPARANOIDSAFER -dBATCH -sDEVICE=pswrite -sOutputFile=- -c save pop -f -' TF_reason='acroread or gs (needed to produce PS)' TF_warn='Using gs to convert PDF to PS ... may take a while ...' #fi FTYPE=PS elif [ "$can_do_Epson" = true ]; then # gs or similar PDF-to-native, or maybe PDF-to-text, converter TF_command='gs -q -dNOPAUSE -dSAFER -dPARANOIDSAFER -sDEVICE=epson -sOutputFile=- -' TF_reason='gs (needed to produce Epson-compatible data)' TF_warn='Using gs to convert PDF to Epson-compatible ... may take a while ...' FTYPE=Epson elif [ "$can_do_BJC" = true ]; then # gs or similar PDF-to-native converter TF_command='gs -q -dNOPAUSE -dSAFER -dPARANOIDSAFER -sDEVICE=bjc800 -r600 -sOutputFile=- -' TF_reason='gs (needed to produce BJC-compatible data)' TF_warn='Using gs to convert PDF to BJC-compatible ... may take a while ...' FTYPE=BJC else error_file "$chkf" 'PDF (use acroread or gs to view?)' fi return ;; '367 002 '* ) if [ "$debug" = true ]; then print -u2 -R "File type: DVI" fi # DVI (TeX et al) if [ "$bytes_ls" -gt $BYTE_LIMIT_ps ]; then error_file "$chkf" "DVI, $bytes_ls (over $BYTE_LIMIT_ps) bytes long"; fi if [ "$bytes_wc" -gt $BYTE_LIMIT_ps ]; then error_file "$chkf" "DVI, $bytes_wc (over $BYTE_LIMIT_ps) bytes long"; fi # if [ "$can_do_PS" = true ]; then # dvips or similar DVI-to-PS converter TF_command='dvips -f -R -q' TF_reason='dvips (needed to produce PS)' TF_warn='Using dvips to convert DVI to PS ... may take a while ...' FTYPE=PS # else # error_file "$chkf" 'DVI (use xdvi to view?)' # fi return ;; '320 317 021 340 241 261 032 341 '* | \ '376 067 \0 043 '* | \ '333 245 - \0 \0 \0 '* ) error_file "$chkf" 'MS Office document (use openoffice to view and print?)' ;; *[!\ ][0-9]* ) # Has some binary stuff, remove common un-printables and # PJL encapsulation set -- $(list_txt_file -test < "$chkf" | od -c -N 16 | sed -e 's/^0000000 //' -e 's/ / sp/g' -e q) if [ "$debug" = true ]; then print -u2 -R "Shown by od: $*" fi ;; esac case "$*" in '033 E 033 ( '* | '033 E 033 E 033 ( '* | '033 E 033 & l '* ) if [ "$debug" = true ]; then print -u2 -R "File type: PCL5" fi # PCL file. Files coming for SUHRF from oberon.ucc have # '033 E 033 ( 0 N 033 & l [01] O 033 ': should we test for all that? # while in Aug 2001 files coming from gaius.ucc have double RESET: # '033 E 033 E 033 ( 0 N 033 & l 1 O 033 & l': so we accept that too... # while (some?) Windows files have # '033 E 033 & l 2 6 A 033 & l 0 o 0 l 0' if [ "$bytes_ls" -gt $BYTE_LIMIT_pcl ]; then error_file "$chkf" "PCL, $bytes_ls (over $BYTE_LIMIT_pcl) bytes long"; fi if [ "$bytes_wc" -gt $BYTE_LIMIT_pcl ]; then error_file "$chkf" "PCL, $bytes_wc (over $BYTE_LIMIT_pcl) bytes long"; fi if [ "$can_do_PCL" = true ]; then FTYPE=PCL else error_file "$chkf" 'for PCL printers only (use pcl2txt or pcl2ps?)' fi return ;; *[!\ ][0-9]* ) error_file "$chkf" "binary ($*)" ;; '% ! P S '* | '004 % ! P S '* | '\n % ! P S '* | '% ! \n % '* ) if [ "$debug" = true ]; then print -u2 -R "File type: PostScript" fi # PostScript. Though we must have removed that ctrl-D already... if [ "$bytes_ls" -gt $BYTE_LIMIT_ps ]; then error_file "$chkf" "PostScript, $bytes_ls (over $BYTE_LIMIT_ps) bytes long"; fi if [ "$bytes_wc" -gt $BYTE_LIMIT_ps ]; then error_file "$chkf" "PostScript, $bytes_wc (over $BYTE_LIMIT_ps) bytes long"; fi if [ "$lines_wc" -gt $LINE_LIMIT_ps ]; then error_file "$chkf" "PostScript, $lines_wc (over $LINE_LIMIT_ps) lines long"; fi if [ -n "$(whence mpage)" ]; then set -- $({ list_txt_file -nonl < "$chkf" | mpage -1ov -P- >/dev/null; } 2>&1) pages_mp="$2" case "$pages_mp" in '' | *[!0-9]* ) error_file "$chkf" "PostScript, but mpage shows: $*";; esac if [ "$debug" = true ]; then print -u2 -R "mpage count: $pages_mp ($*)" fi if [ "$pages_mp" -gt $PAGE_LIMIT_ps ]; then error_file "$chkf" "PostScript, $pages_mp (over $PAGE_LIMIT_ps) pages long"; fi elif [ -n "$(whence mpage-ANCIENT)" ]; then set -- $({ list_txt_file -nonl < "$chkf" | mpage-ANCIENT -1b -P >/dev/null; } 2>&1) pages_mp="$2" case "$pages_mp" in '' | *[!0-9]* ) error_file "$chkf" "PostScript, but mpage-ANCIENT shows: $*";; esac if [ "$debug" = true ]; then print -u2 -R "mpage count: $pages_mp ($*)" fi if [ "$pages_mp" -gt $PAGE_LIMIT_ps ]; then error_file "$chkf" "PostScript, $pages_mp (over $PAGE_LIMIT_ps) pages long"; fi else if [ "$debug" = true ]; then print -u2 -R '(No mpage, cannot measure)' fi fi if [ "$can_do_PS" = true ]; then FTYPE=PS elif [ "$can_do_Epson" = true ]; then # gs or similar PS-to-native, or maybe PS-to-text, converter TF_command='gs -q -dNOPAUSE -dSAFER -dPARANOIDSAFER -sDEVICE=epson -sOutputFile=- -' TF_reason='gs (needed to produce Epson-compatible data)' FTYPE=Epson elif [ "$can_do_BJC" = true ]; then # gs or similar PS-to-native converter TF_command='gs -q -dNOPAUSE -dSAFER -dPARANOIDSAFER -sDEVICE=bjc800 -r600 -sOutputFile=- -' TF_reason='gs (needed to produce BJC-compatible data)' FTYPE=BJC else error_file "$chkf" 'for PostScript printers only' fi ;; *[0-9][0-9]* ) error_file "$chkf" 'binary' ;; ') sp H P - P C L sp X L ; '* ) error_file "$chkf" 'PCL6 (PCLXL) and we do not support that, not even on PCL printers' ;; * ) if [ "$debug" = true ]; then print -u2 -R "File type: plain-text" fi # Plain text if [ "$bytes_ls" -gt $BYTE_LIMIT_text ]; then error_file "$chkf" "plain-text, $bytes_ls (over $BYTE_LIMIT_text) bytes long"; fi if [ "$bytes_wc" -gt $BYTE_LIMIT_text ]; then error_file "$chkf" "plain-text, $bytes_wc (over $BYTE_LIMIT_text) bytes long"; fi if [ "$lines_wc" -gt $LINE_LIMIT_text ]; then error_file "$chkf" "plain-text, $lines_wc (over $LINE_LIMIT_text) lines long"; fi if [ "$can_do_text" = true ]; then FTYPE=text elif [ "$can_do_PS" = true ]; then ### Do we need to protect colour printers from bein wasted for plain-text jobs? ###if [ "$can_do_colourps" = true ]; then error "Printer '$printer' is for colour PostScript jobs only"; fi # a2ps or mpage or similar text-to-PS converter # (Some external machines may not have a2ps) if [ -n "$(whence a2ps)" ]; then J="$chkf" if [ -n "$jname" ]; then J="$jname" fi a2pspg='-2' case "$mode" in lpr | lp ) # Do not waste time otherwise... or compromise ifilter a2psp1='-1' lines_per_sheet=68 # 68 for 'a2ps -1', only 65 for 'a2ps -2' chars_per_line=80 set -- $(perl -ne 'chomp; 1 while s/\t+/" " x (length($&)*8 - length($`)%8)/e; push @x, length; END { @x = sort {$b <=> $a} @x; print "$x[0] $x[2+$#x/100] $x[$#x/5]"; }' "$chkf") 0 0 0 if [ "$debug" = true ]; then print -u2 -R "Line length: max $1, $2 at 99% and $3 at 80% of lines" fi if [ "$1" -gt 80 -a "$2" -gt 80 ]; then if [ "$1" -le 255 ]; then (( dummy = $3 + $3 / 4 )) if [ "$1" -le "$dummy" ]; then if [ "$1" -lt 115 ]; then a2psp1="-1 -r -l115" lines_per_sheet=45 chars_per_line=115 a2pspg="-1 -l115" elif [ "$1" -lt 164 ]; then a2psp1="-1 -r -l$1" lines_per_sheet=65 # Or less than that, no need to be exact chars_per_line=$1 a2pspg="-1 -r -l164" else a2psp1="-1 -r -l$1" lines_per_sheet=101 # Or less than that, no need to be exact, in fact does not matter at all chars_per_line=$1 a2pspg="-1 -r -l$1" fi else if [ "$debug" = true ]; then print -u2 -R "Wide file, up to $1 characters (but non-uniform widths)" fi fi else if [ "$debug" = true ]; then print -u2 -R "Very wide file, up to $1 characters (too wide to handle)" fi fi fi if [ "$a2ps1" = true ]; then a2pspg="$a2psp1" fi if [ "$a2psp1" = "$a2pspg" ]; then if [ "$debug" = true ]; then print -u2 -R "Using 'a2ps $a2psp1' regardless of file length" fi else (( bytes_per_sheet = $lines_per_sheet * $chars_per_line )) if [ "$can_do_duplex" = true -a "$dplx" != false ]; then (( lines_per_sheet = 2 * $lines_per_sheet )) (( bytes_per_sheet = 2 * $bytes_per_sheet )) fi if [ "$lines_wc" -le $lines_per_sheet -a "$bytes_wc" -le $bytes_per_sheet ]; then # Using # set -- $(fold "$chkf" | wc -l) # is fast, but does not handle embedded FormFeed very well. # Use a2ps: we may end up running it twice, no big waste. set -- $( { a2ps $a2psp1 --delegate=no -B -o- --left-title='%a on %D{%a %e %b %y}' --center-title="$J" --right-title='%Q' "$chkf" >/dev/null; } 2>&1 ) if [ "$debug" = true ]; then print -u2 -R "'a2ps -1': $*" fi case "$*" in *' [Total: 1 page on 1 sheet]'* ) a2pspg="$a2psp1" if [ "$debug" = true ]; then print -u2 -R "Single-page file, can use 'a2ps $a2psp1'" fi ;; *' [Total: 2 pages on 2 sheets]'* ) if [ "$can_do_duplex" = true -a "$dplx" != false ]; then a2pspg="$a2psp1" if [ "$debug" = true ]; then print -u2 -R "Two-page file, can use 'a2ps $a2psp1' on duplex printer" fi fi ;; esac else if [ "$debug" = true ]; then print -u2 -R "Long file ($lines_wc lines, $bytes_wc bytes), not checking length with a2ps" fi fi fi ;; esac TF_command="a2ps $a2pspg --delegate=no -B -q -o- --left-title='%a on %D{%a %e %b %y}' --center-title='$J' --right-title='%Q'" TF_reason='a2ps (needed to produce PostScript)' FTYPE=PS elif [ -n "$(whence mpage)" ]; then TF_command='mpage -1o -P-' TF_reason='mpage (needed to produce PostScript)' FTYPE=PS elif [ -n "$(whence mpage-ANCIENT)" ]; then TF_command='mpage-ANCIENT -1bs -P' TF_reason='mpage (needed to produce PostScript)' FTYPE=PS else error_file "$chkf" 'text, and we do not have a2ps or mpage' fi else error_file "$chkf" 'for text printers only' fi ;; esac } function printer_can_do # What can this printer do? { can_do_Epson=false can_do_text=false can_do_PS=false can_do_duplex=false can_do_staple=false can_do_colourps=false can_do_PJL=false can_do_PCL=false can_do_PDF=false can_do_PSpgcnt=false can_do_mpagecnt=false can_do_bytecnt=false can_do_BJC=false can_do_char20=false can_do_unlimited=false case " $Epson_printers " in *" $printer "* ) can_do_Epson=true ;; esac case " $text_printers " in *" $printer "* ) can_do_text=true ;; esac case " $PS_printers " in *" $printer "* ) can_do_PS=true ;; esac case " $duplex_printers " in *" $printer "* ) can_do_duplex=true ;; esac case " $staple_printers " in *" $printer "* ) can_do_staple=true ;; esac case " $colourps_printers " in *" $printer "* ) can_do_colourps=true ;; esac case " $PJL_printers " in *" $printer "* ) can_do_PJL=true ;; esac case " $PCL_printers " in *" $printer "* ) can_do_PCL=true ;; esac case " $PDF_printers " in *" $printer "* ) can_do_PDF=true ;; esac case " $PSpgcnt_printers " in *" $printer "* ) can_do_PSpgcnt=true ;; esac case " $mpagecnt_printers " in *" $printer "* ) can_do_mpagecnt=true ;; esac case " $bytecnt_printers " in *" $printer "* ) can_do_bytecnt=true ;; esac case " $BJC_printers " in *" $printer "* ) can_do_BJC=true ;; esac case " $char20_printers " in *" $printer "* ) can_do_char20=true ;; esac case " $unlimited_printers " in *" $printer "* ) can_do_unlimited=true ;; esac if [ "$can_do_text" = false -a "$can_do_PS" = false -a "$can_do_BJC" = false ]; then error "Printer '$printer' not known" fi typeset kind ARG case "$class" in unlimited ) kind=unlim;; unrestricted ) kind=unlim;; student ) kind=studt;; * ) kind=staff;; esac if [ "$can_do_unlimited" = true ]; then if [ "$debug" = true -a "$kind" != unlim ]; then print -u2 -R "Printer '$printer' is unlimited anyway..." fi kind=unlim fi if [ "$debug" = true ]; then print -u2 -R "Setting limits for $class ($kind) ..." fi for ARG in \ BYTE_LIMIT_text LINE_LIMIT_text \ BYTE_LIMIT_ps LINE_LIMIT_ps PAGE_LIMIT_ps \ PAGE_LIMIT_pdf \ BYTE_LIMIT_epson \ BYTE_LIMIT_bjc \ BYTE_LIMIT_pcl \ ; do eval "$ARG=\$${ARG}_$kind" # if [ "$debug" = true ]; then # eval print -u2 -R "Have set $ARG to \$$ARG" # fi done } function printquota # Check or update print quotas { typeset usr="$1" typeset cmd="$2" typeset pgs="$3" typeset http='http://rome/ub/webquota/printquota' typeset pq pq2 typeset typ if [ "$can_do_PS" = true ]; then typ=Laser; fi if [ "$can_do_colourps" = true ]; then typ=Color; fi if [ -z "$typ" ]; then if [ "$debug" = true -o "$quotaonly" = true ]; then print -u2 -R "No printquota for this printer" fi return fi if [ -z "$usr" ]; then return; fi if [ -z "$cmd" ]; then return; fi if [ -z "$pgs" ]; then return; fi pq="$(myhaul -p "$http?$usr:$typ:$cmd:$pgs")" if [ "$debug" = true ]; then print -u2 -R "printquota?$usr:$typ:$cmd:$pgs shows:" print -u2 -R "$pq" fi case "$pq" in *'Sorry, cannot identify you, bad identd response'*'printquota can only be used from the School'?'s UNIX machines'*'Please try again'* ) pq="$(myhaul -p "$http?$usr:$typ:$cmd:$pgs")" if [ "$debug" = true ]; then print -u2 -R "printquota failed, re-try." print -u2 -R "printquota?$usr:$typ:$cmd:$pgs shows:" print -u2 -R "$pq" fi ;; esac case "$pq" in *%* ) pq2="$(echo "$pq" | grep %)";; * ) pq2="$pq" esac case "$pq" in *'printquota OK' ) ;; * ) if [ "$cmd" = used ]; then error "printquota: $pq2" fi print -u2 -R "printquota:" print -u2 -R "$pq2" print -u2 -R print -u2 -R "For more info, see also" print -u2 -R "$http" error "printquota problem - quitting" ;; esac if [ "$quotaonly" = true ]; then print -u2 -R "printquota:" print -u2 -R "$pq2" print -u2 -R print -u2 -R "For more info, see also" print -u2 -R "$http" elif [ "$cmd" != used ]; then case "$pq2" in *[789][0-9]%* | *100%* ) print -u2 -R "Warning: printquota about to expire:" print -u2 -R "$pq2" print -u2 -R print -u2 -R "For more info, see also" print -u2 -R "$http" ;; esac fi } # LPDIR=/usr/bin LPDIR=/usr/local/lib/LPRng/bin if [ ! -d "$LPDIR" ]; then LPDIR=/usr/local/share/LPRng/bin fi if [ ! -d "$LPDIR" ]; then LPDIR=/usr/sms/share/LPRng/bin fi LPR=$LPDIR/lpr LPQ=$LPDIR/lpq LPM=$LPDIR/lprm LPC=$LPDIR/lpc LPS=$LPDIR/lpstat # if [ $LPC = /usr/bin/lpc ]; then LPC=/usr/sbin/lpc; fi mode=lpr laser= lab= quotaonly= printer="${LPDEST:-}" if [ -z "$printer" ]; then printer="${PRINTER:-}"; fi hdr= wide= dplx= staple= mnlfd= a2ps1= remove= jname= files= read= cancel= debug= class= if [ $0 != '' ]; then PRF_NAME="${0##*/}" fi #####----- case "$PRF_NAME" in *filter* ) mode=ifilter # ifilter mode is an input filter to use with lpd for all printers. # For Epsons: # Put up banner # Reset printer # Select CPI # For Apple LaserWriters: # (Do no put up banner) # For HP LaserJet printers: # Set duplex mode # (Do not RESET, nor INITIALIZE: does not seem effective) # (Do no put up banner) # Set cute DISPLAY="xx" messages # Show PJL USTATUS page counts # For PostScript printers (including Apple LaserWriters and HP LaserJets) # that can talk back (serial lines and direct network connections, but # not on parallel ports): # Show PS page counts PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/sms/bin:/usr/sms/sbin export PATH function mess # Put message in /usr/adm/lperr (?) file. { print -u2 -R "$(date '+%Y/%m/%d %T (%a)') $*: <$QUE> <$USR> <$HST> <$NAM>" case "$1" in Bad* ) print -u2 -R " (Bad) options: $ORIG"; exit 0;; esac } function bannerpage { print '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++' print # print 'Banner page generated by:' # print "$0 $ORIG" | fold -w 76 | sed -e 's/^/ /' # print # print print "Print job for user:" print if [ ${#USR} -lt 10 ]; then banner "$USR" else print " $USR" fi print print if [ -n "$USU" -a "$USU" != "$USR" ]; then print "(who would pretend to be $USU)" # print "who would pretend to be:" # print # if [ ${#USU} -lt 10 ]; then # banner "$USU" # else # print " $USU" # fi print print fi print "Job name:" print if [ ${#NAM} -lt 10 ]; then banner "$NAM" else print " $NAM" fi print print print "Job sent from host:" print if [ ${#HST} -lt 10 ]; then banner "$HST" else print " $HST" fi print print print "Printing on $(date)" print print '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++' } function ps_page_count # Spit out commands for PS page counting, for message in $1 # ('starting' or 'finished'), or maybe use mpage and put result # in separate log file /usr/adm/ps$printer.mpg.log . { if [ "$can_do_PSpgcnt" = true ]; then # Note that both the Apple LaserWriter and HP JaserJet printers are # "multi-processing", and process this PS code and report the pagecount # while the printing engine is still busy churning out pages; thus using # the difference between the start and finish count is unreliable. # We also use USTATUS for LaserJet printers; that seems more reliable # (except for always returning an even number when using duplex printing) # but is not perfect either. # Lexmark printers have the 'setenginesync' command. Could we mimic that # on LaserJet printers with # -12345X@PJL # @PJL ENTER LANGUAGE = PCL # &r1F <--- Flush all pages: should this be *s1F ? # E # -12345X # ? Works fine on LJ4000 and LJ2200 printers, but it does not work on # the newer LJ4100 or LJ4550 printers. (The LJ4100 and LJ4550 are so # "strongly asynchronous" that, while one job is printing, they may # process and complete the next job, including sending "JOB START" and # "JOB END" messages for it; then when the printing job finishes it # sends its "JOB END" message. - I seen some references to 'TEOJ=ON', # but it does not seem to work on the LJ4100 or LJ4550.) print "%!PS-Adobe" print "statusdict begin" print "/str 20 string def" print "(Pagecount = ) print" print "pagecount str cvs print" print "( when $1 for user $USR@$HST$UTAG\\n) print" print "flush" print "end" print -n "\004" elif [ "$can_do_mpagecnt" = true -a "$1" = starting ]; then if [ "$FTYPE" = PS ]; then if [ -n "$(whence mpage)" ]; then MPG="$({ list_txt_file -nonl < $FIL | mpage -1ov -P- >/dev/null; } 2>&1)" MPG="${MPG#\[}" MPG="${MPG%,\ on\ \\]}" elif [ -n "$(whence mpage-ANCIENT)" ]; then MPG="$({ list_txt_file -nonl < $FIL | mpage-ANCIENT -1b -P >/dev/null; } 2>&1)" MPG="${MPG#\[}" MPG="${MPG%,\ on\ \\]}" else MPG='(No mpage, cannot measure)' fi else MPG="(Cannot measure file of type $FTYPE)" fi if [ -w /usr/adm/ps$printer.mpg.log ]; then print -R "$(date '+%Y/%m/%d %T') $USR@$HST $MPG" >> /usr/adm/ps$printer.mpg.log else mess "No /usr/adm/ps$printer.mpg.log file: $MPG" fi fi } function byte_count # Spit job byte size and put result # in separate log file /usr/adm/ps$printer.byte.log . { if [ "$can_do_bytecnt" = true ]; then if [ -w /usr/adm/ps$printer.byte.log ]; then print -R "$(date '+%Y/%m/%d %T') $USR@$HST type $FTYPE, $bytes_wc bytes, $lines_wc lines" >> /usr/adm/ps$printer.byte.log else mess "No /usr/adm/ps$printer.byte.log file" fi fi } set -f ORIG="$*" OPT= typeset -L1 L1 for ARG; do case "$ARG" in -[A-Za-z]* ) L1="${ARG#-}" R2="${ARG#-?}" # Protect against quotes in R2 (but it should not have any) R2="${R2%%\'*}" if [ -z "$R2" ]; then R2=BLANK; fi # print -u2 -R "L1 is $L1, R2 is $R2" eval "$L1='$R2'" ;; * ) OPT="$OPT $ARG";; esac done # for ARG in A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z; do # eval print -u2 -R "\"key $ARG - value \$$ARG\"" # done # ## The options values are supposed to be: ## ## Key Value ## a Accounting file (printcap 'af') ## b Job size, i.e. total data file size, in bytes ## c if binary (format 'l') expands to -c ## d Control directory ## e job data file ## f original print file name (== N) ## h hostname (as looked up from connecting IP address) ## i indent (== I) ## j job number from control file name ## k Control file name ## l printcap Page length (pl) value ## m printcap Cost factor (co) value ## n user logname (== P, also == L??) ## p Remote Printer name for forwarded jobs (== P ??) ## r Remote Host name for forwarded jobs ## s printer Status file (ps) value ## t current time in simple format ## w printcap Page width (pw) value ## x printcap x dimension (px) value ## y printcap y dimension (py) value ## C class ## F data file format character ## H hostname (as claimed by connecting host) ## J jobname ## L username (?) ## P Printer name ## S printcap Comment tag (cm) value ## 0-9 control file line starting with digit ## A-Z control file line starting with letter. These seem to be (in ## conflict with stuff above): ## A Job identifier controlled by the use_identifier variable. ## C Class String to be used for the class line on the burst page. ## H Host Name. Name of the machine where lpr was invoked. ## I Indent. The number of characters to indent the output by (in ascii). ## J Job Name. String to be used for the job name on the burst page. ## L Banner user name. Information for banner page. ## P Person. Login name of the person who invoked lpr. This is used to verify ownership by lprm. ## M Send mail to the specified user when the current print job completes. ## N File name. The original name of a data file which is in the job. ## T Title. String to be used as the title for pr(1) when the LPR -p option was specified. ## U Unlink. Job file to remove when printing completed. ## W Width. The page width (in characters) to used for printing. ## Z zoptions. Options passed by lpr -Zzoptions. These are passed to output filters to aid in printing. ## ## An example: ## ## key A - value ## key B - value ## key C - value stuff_with_-C_option ## key D - value ## key E - value ## key F - value f ## key G - value ## key H - value milan.maths.usyd.edu.au ## key I - value ## key J - value stuff_with_-J_option ## key K - value ## key L - value stuff_with_-U_option ## key M - value ## key N - value ## key O - value ## key P - value qc610 ## key Q - value c610 ## key R - value ## key S - value ## key T - value ## key U - value ## key V - value ## key W - value ## key X - value ## key Y - value ## key Z - value ## key a - value ## key b - value 66 ## key c - value ## key d - value /var/spool/LPRng/qc610/ ## key e - value /var/spool/LPRng/qc610/dfA439milan.maths.usyd.edu.au ## key f - value /users/amstaff/psz/.prtest ## key g - value ## key h - value milan.maths.usyd.edu.au ## key i - value ## key j - value 439 ## key k - value /var/spool/LPRng/qc610/cfA439milan.maths.usyd.edu.au ## key l - value 66 ## key m - value 20 ## key n - value psz ## key o - value ## key p - value ## key q - value ## key r - value ## key s - value status ## key t - value 1998-06-03-05:40:51.000 ## key u - value ## key v - value ## key w - value 80 ## key x - value 0 ## key y - value 0 ## key z - value USU="$L" USR="$n" HST="$h" NAM="$J"; if [ -z "$NAM" ]; then NAM="$f"; fi QUE="$Q" DIR="$d" FIL="$e" class="$C" printer="${QUE%%-*}" if [ -z "$printer" ]; then printer="$QUE"; fi case "$printer" in salw ) printer=otlw;; esac # We have some printers redirected, and should not complain # about mismatched names... print2r="$printer" case "$printer" in aolw ) print2r=r7lw;; r7lw ) print2r=aolw;; f5lw ) print2r=r5lw;; r5lw ) print2r=f5lw;; fylw ) print2r=lklw;; lklw ) print2r=fylw;; esac if [ -n "$OPT" ]; then mess "Weird option(s) $OPT" fi # Be friendly to the SUHRF people case "$USR" in 'daemon ('*')' ) case "$HST" in *.ucc.usyd.edu.au ) USR=daemon;; esac;; esac case "$QUE" in '' | *[!a-zA-Z0-9._-]* ) mess 'Bad queuename';; esac case "$QUE" in q* ) mess 'Bad q-queuename';; esac case "$USR" in '' | *[!a-zA-Z0-9._-]* ) mess 'Bad username';; esac case "$HST" in '' | *[!a-zA-Z0-9._]* ) mess 'Bad hostname';; esac HST="${HST%.maths.usyd.edu.au}" case "$HST" in '' | *[!a-zA-Z0-9._]* ) mess 'Bad hostname';; esac case "$NAM" in '' | *[!a-zA-Z0-9._-:/]* ) NAM='Not specified';; esac case "$USU" in '' | *[!a-zA-Z0-9._-]* ) USU="$USR";; esac case "$USR" in root ) USR="$USU";; esac # At LPRng-3.6.26 we get 'plain' filenames case "$FIL" in */* ) ;; * ) FIL="$DIR/$FIL";; esac dummy="$HST" case "$dummy" in white.admin ) dummy=admin1;; pc627 | vis?.pc ) dummy=;; # Some visitor Macs send dfA682localhost.local and similar esac case "$FIL" in '' | *[!/a-zA-Z0-9._-]* ) mess "Bad filename $FIL";; /var/spool/LPRng/*/*/* ) mess "Bad // filename $FIL";; /var/spool/LPRng/q$printer/df[A-Z][0-9][0-9][0-9]${HST%%.*}* ) ;; /var/spool/LPRng/q$printer/df[A-Z][0-9][0-9][0-9]$dummy* ) ;; /var/spool/LPRng/q$printer/df[A-Z][0-9][0-9][0-9]* ) ;; # mess "Weird host in filename $FIL";; /var/spool/LPRng/q$print2r/df[A-Z][0-9][0-9][0-9]${HST%%.*}* ) ;; /var/spool/LPRng/q$print2r/df[A-Z][0-9][0-9][0-9]$dummy* ) ;; /var/spool/LPRng/q$print2r/df[A-Z][0-9][0-9][0-9]* ) ;; # mess "Weird host in filename $FIL";; /var/spool/LPRng/*/df[A-Z][0-9][0-9][0-9]* ) mess "Weird queue in filename $FIL";; /var/spool/LPRng/*/df[A-Z]* ) mess "Weird filename $FIL";; * ) mess "Bad non-spool filename $FIL";; esac # Many other things we could (should?) check: if [ "$F" != f ]; then mess "Weird format $F"; fi if [ "$P" != "q$printer" -a "$P" != "q$print2r" ]; then mess "Mismatched queues $P and $Q"; fi # if [ "$printer" = fylw -a "$USR" = janet ]; then # case "$HST" in *.ucc.* ) # { # cp -i "$FIL" /tmp/lpr.$$.prn # print "File /tmp/lpr.$$.prn saved for debugging:" # print "USU = L = $L" # print "USR = n = $n" # print "HST = h = $h" # print "NAM = J = $J" # print "NAM2 = f = $f" # print "QUE = Q = $Q" # print "DIR = d = $d" # print "FIL = e = $e" # print "class = C = $C" # } | mailx -s 'Print debug' psz # ;; esac # fi #case "$printer" in # aolw | r7lw | f5lw | r5lw ) # mkdir -p /tmp/lprng # cp $FIL "/tmp/lprng/$printer-$(date '+%Y.%m.%d-%T')-${FIL##*/}" # ;; #esac printer_can_do chk_ftype "$FIL" if [ -n "$TF_command" ]; then error "Please run $TF_reason" fi printquota "$USR" used "$pages_mp" # mess 'Printing' if [ "$can_do_Epson" = true ]; then BANNER=true case "$QUE" in *-h* ) BANNER=false ;; esac CPI="\033P" # 10cpi case "$QUE" in *-w* ) CPI="\033M" # 12cpi ;; esac print -n "\033@" # Reset print -n "\033x\000" # No letter quality print -n "\033p\000" # No proportional mode print -n "\033+\074" # 6lpi (spacing is 60 units of 1/360 inch) print -n "\033C\000\013" # Paper length 11 inches print -n "$CPI" # 10cpi or 12cpi print -n "\033l\000" # Left margin if [ "$BANNER" != false ]; then bannerpage print -n "\f" # Formfeed fi byte_count case "$FTYPE" in Epson | unchecked ) cat "$FIL" # Show that file... ;; text ) list_txt_file < "$FIL" ;; * ) error "Bad file type '$FTYPE', cannot print" ;; esac print -n "\f" # Formfeed print -n "\033@" # Reset elif [ "$can_do_PS" = true ]; then BANNER=false DUPLEX= BINDING=LONGEDGE STAPLE=NONE MANUALFEED=OFF if [ "$can_do_duplex" = true ]; then case "$QUE" in *-1* ) DUPLEX=OFF;; *-2* ) DUPLEX=ON;; *-s* ) DUPLEX=ON; BINDING=SHORTEDGE;; *-m* ) MANUALFEED=ON; DUPLEX=OFF;; esac fi if [ "$MANUALFEED" = OFF ]; then case "$QUE" in *-x* ) STAPLE=STAPLE;; esac fi if [ -z "$DUPLEX" ]; then case "$QUE" in *colw* | *salw* ) DUPLEX=OFF;; * ) DUPLEX=ON;; esac fi case "$QUE" in stlw | stlw-2-x ) DUPLEX=ON; STAPLE=STAPLE; BANNER=true;; stlw-h ) DUPLEX=ON; STAPLE=STAPLE; BANNER=false;; esac # Some printers have a (16-character) * (2-line) display; # some have (20-character) * (4-line) ... FILL= if [ "$can_do_char20" = true ]; then FILL=' ' fi UTAG= if [ "$can_do_PJL" = true ]; then # Tag USTATUS and PS page count messages with a unique(?), # monotonically increasing tag to enable better matching. UTAG=" tag $(date '+%Y/%m/%d %T')" print "\033%-12345X@PJL" # print "@PJL RESET" # print "@PJL INITIALIZE" print "@PJL JOB NAME=\"$USR@$HST$UTAG\" DISPLAY=\"Printing for $FILL$USR@$HST\"" ## Do not use date/time in DISPLAY="xx" messages: they are the time that ## the job gets through lpd, not the time it goes through the printer. ##print "@PJL JOB NAME=\"$USR@$HST\" DISPLAY=\"Job at $(date +%H:%M) for$USR@$HST\"" ##print "@PJL JOB NAME=\"$USR@$HST\" DISPLAY=\"Started at $(date +%H:%M)* $USR@$HST\"" ## Is it safe to momentarily turn USTATUS off: can we be sure that ## no status message is being sent at that time? # print "@PJL USTATUSOFF" print "@PJL USTATUS JOB=ON" print "@PJL DEFAULT CPLOCK=ON" PW=0 while [ $PW -lt 1 -o $PW -gt 65534 ]; do ((PW = $RANDOM)) ((PW = $PW + $RANDOM)) done print "@PJL DEFAULT PASSWORD=$PW" print "@PJL DEFAULT ECONOMODE=OFF" print "@PJL DEFAULT COPIES=1" print "@PJL DEFAULT POWERSAVE=ON" print "@PJL DEFAULT POWERSAVETIME=15" print "@PJL DEFAULT DUPLEX=ON" print "@PJL DEFAULT BINDING=LONGEDGE" print "@PJL DEFAULT OUTBIN=UPPER" print "@PJL DEFAULT FINISH=NONE" print "@PJL DEFAULT MANUALFEED=OFF" # DEFAULT is for future jobs; need SET for current one print "@PJL SET DUPLEX=$DUPLEX" print "@PJL SET BINDING=$BINDING" if [ "$STAPLE" = STAPLE -a "$can_do_staple" = true ]; then print "@PJL SET OUTBIN=OPTIONALOUTBIN1" print "@PJL SET FINISH=STAPLE" print "@PJL SET STAPLEOPTION=ONE" # For Ricoh print "@PJL SET STAPLE = LEFTTOPSLANTPORT" else print "@PJL SET OUTBIN=UPPER" print "@PJL SET FINISH=NONE" fi print "@PJL SET MANUALFEED=$MANUALFEED" print "@PJL ENTER LANGUAGE = POSTSCRIPT" fi # print -n "\004" # End-of-job ps_page_count starting if [ "$BANNER" != false ]; then if [ -n "$(whence mpage)" ]; then bannerpage | mpage -1o -P- print -n "\004" elif [ -n "$(whence mpage-ANCIENT)" ]; then bannerpage | mpage-ANCIENT -1bs -P print -n "\004" fi fi case "$FTYPE" in unchecked ) cat "$FIL" # Show that file... print -n "\004" # End-of-job ;; PS ) list_txt_file < "$FIL" print -n "\004" # End-of-job ;; PDF ) # We assume that PDF printers can also do PS if [ "$can_do_PDF" = true ]; then if [ "$can_do_PJL" = true ]; then print "\033%-12345X@PJL" print "@PJL ENTER LANGUAGE = PDF" # PDF files are often binary, cannot strip anything. We hope there is no embedded PJL in there... cat "$FIL" print "\033%-12345X@PJL" print "@PJL ENTER LANGUAGE = POSTSCRIPT" else error "Do not know how to do PDF on non-PJL printers, cannot print" fi else error "Bad file type '$FTYPE', cannot print" fi ;; PCL ) # We assume that PCL printers can also do PS if [ "$can_do_PCL" = true ]; then if [ "$can_do_PJL" = true ]; then print "\033%-12345X@PJL" print "@PJL ENTER LANGUAGE = PCL" list_txt_file -test < "$FIL" print "\033%-12345X@PJL" print "@PJL ENTER LANGUAGE = POSTSCRIPT" else error "Do not know how to do PCL on non-PJL printers, cannot print" # The following may work on an AppleLaserWriter to put it into PCL mode # (this seems to come from John Dodson): # %-% This ... is valid for ... a LaserwriterIIg (only) ! # %-% change into HP-LaserJet mode & take stdin # %-% Level 2 PostScript # currentfile /LaserJetIIP statusdict /emulate get exec # %-% Level 1 PostScript was... # %-% statusdict begin hplj fi else error "Bad file type '$FTYPE', cannot print" fi ;; * ) error "Bad file type '$FTYPE', cannot print" ;; esac if [ "$can_do_PJL" = true ]; then # Make those pagecounts count (see comments with ps_page_count) print "\033%-12345X@PJL" print "@PJL ENTER LANGUAGE = PCL" print -n "\033&r1F" print "\033%-12345X@PJL" print "@PJL ENTER LANGUAGE = POSTSCRIPT" fi # The Ricoh copiers (r5lw and r7lw) sometime get stuck. # Is that a timing issue? # sleep 5 # Wait until our output is drained? But on Linux, # the pipes /dev/ps*lw always appear empty. # perl -e ' # $x = `lsof -p $$`; # #print STDERR "lsof is $x\n"; # ( $p ) = $x =~ m: 1w .*?(/.*)$:m; # #print STDERR "Pipe is $p\n"; # exit unless $p; # while (1) # { # $x = -s $p; # $x and print STDERR "'"$USR"'\@'"$HST$UTAG"': Size of $p is $x\n"; # sleep 5; # $x or last; # } # ' ps_page_count finished if [ "$can_do_PJL" = true ]; then print "\033%-12345X@PJL" print "@PJL EOJ NAME=\"$USR@$HST$UTAG\"" ## Do not turn USTATUS JOB off: the message may not be ready for some time... ##print "@PJL USTATUSOFF" print "@PJL RDYMSG DISPLAY=\"Ready - done for$FILL$USR@$HST\"" ##print "@PJL RDYMSG DISPLAY=\"Done - $(date +%H:%M) for$USR@$HST\"" ##print "@PJL RDYMSG DISPLAY=\"Ready - at $(date +%H:%M)* $USR@$HST\"" print -n "\033%-12345X" fi elif [ "$can_do_BJC" = true ]; then case "$FTYPE" in BJC | unchecked ) cat "$FIL" # Show that file... ;; * ) error "Bad file type '$FTYPE', cannot print" ;; esac else error "Bad kind of printer" fi exit 0 ;; esac # #####----- case "$PRF_NAME" in '' ) PRF_NAME=prf;; *q* ) mode=lpq;; lprm ) mode=lprm;; lp ) mode=lp;; cancel ) mode=cancel;; lpc ) mode=lpc # Special for matlab that uses 'lpc status nearest' and we cannot easily "translate" that. # From version R2006b or so, matlab may try both 'lpc status' and 'lpc -a status' instead, # see comments in matlab_with_path . case "$*" in 'status nearest' | 'status' | '-a status' ) $LPC status all@rome | grep -v '^q'; echo 'nearest@rome enabled enabled 0 none none' exit #set -- status all@rome ;; esac exec $LPC "$@"; exit;; # No option checking for lpc lpstat ) mode=lpstat; exec $LPS "$@"; exit;; # No option checking for lpstat lprquota ) quotaonly=true;; # Shorthand for 'lpr -quota', but probably no such command (symlink in /usr/sms/bin) esac # So that it can be invoked through things like 'p730' # (that should be a hard or soft link to prf), to do 'prf -Pc730', # without the need for aliases. for i in $known_printers; do j="${i#c}" k="${i%lw}" case "$PRF_NAME" in *$i | *$j | *$k ) printer="$i"; break;; esac done for i in $known_printers; do case "$PRF_NAME" in *$i ) printer="$i"; break;; esac done ## Apollo prf re-parses its options; but we don't; # we only record them to show with debug option. OPTIONS="$*" # set -- $OPTIONS while [ $# -gt 0 ]; do case "$mode" in lpr ) # Special for nedit print menu, choose number of copies (used as first argument) case "$1" in '-#' ) if [ $# -ge 2 ]; then case "$2" in '' | *[!0-9]* ) ;; * ) warn "Option '$1 $2' ignored"; shift; shift; continue;; esac fi ;; esac case "$2" in # Special for matlab, uses '-JMATLAB Command Window' (as second argument after -Pprinter) '-J'*' '* ) i="$1" j="$2" while :; do case "$j" in *' '* ) j="${j%%\ *}${j#*\ }";; * ) break;; esac done shift; shift; set -- "$i" "$j" "$@" ;; esac ;; esac case "$1" in '' ) shift; continue;; *[!a-zA-Z0-9.,:/@%^_=+~-]* | [~]* ) error "Argument/option(1) '$1' has strange characters - quitting";; esac case "$2" in *[!a-zA-Z0-9.,:/@%^_=+~-]* | [~]* ) error "Argument/option(2) '$2' has strange characters - quitting";; esac case "$1" in -debug ) debug=true; shift; continue;; -laser ) laser=true; shift; continue;; -nolaser | -dotmatrix ) laser=false; shift; continue;; -lab ) lab=true; shift; continue;; -nolab ) lab=false; shift; continue;; -quota ) quotaonly=true; shift; continue;; esac case "$mode" in lpq ) case "$1" in -D | -t ) if [ $# -ge 2 ]; then warn "Option '$1 $2' ignored"; shift; else warn "Option '$1' ignored"; fi;; -A | -D* | -V | -a | -l | -s | -t* ) warn "Option '$1' ignored";; +* ) warn "Option '$1' ignored";; -P ) if [ $# -ge 2 ]; then printer="$2"; shift; fi;; -P* ) printer="${1#-P}";; -* ) error "Unknown option '$1'";; * ) read="$read $1";; esac ;; lprm ) case "$1" in -D ) if [ $# -ge 2 ]; then warn "Option '$1 $2' ignored"; shift; else warn "Option '$1' ignored"; fi;; -A | -D* | -V | -a ) warn "Option '$1' ignored";; -P ) if [ $# -ge 2 ]; then printer="$2"; shift; fi;; -P* ) printer="${1#-P}";; -* ) error "Unknown option '$1'";; * ) cancel="$cancel $1";; esac ;; lp ) case "$1" in -D | -H | -P | -S | -T | -f | -n | -o | -q | -y ) if [ $# -ge 2 ]; then warn "Option '$1 $2' ignored"; shift; else warn "Option '$1' ignored"; fi;; -A | -D* | -c | -m | -p | -r | -s | -w ) warn "Option '$1' ignored";; -d ) if [ $# -ge 2 ]; then printer="$2"; shift; fi;; -d* ) printer="${1#-d}";; -t ) if [ $# -ge 2 ]; then jname="$2"; shift; fi;; -t* ) jname="${1#-t}";; -* ) error "Unknown option '$1'";; * ) files="$files $1";; esac ;; cancel ) case "$1" in -D ) if [ $# -ge 2 ]; then warn "Option '$1 $2' ignored"; shift; else warn "Option '$1' ignored"; fi;; -D* ) warn "Option '$1' ignored";; -d | -P ) if [ $# -ge 2 ]; then printer="$2"; shift; fi;; -P* ) printer="${1#-P}";; -d* ) printer="${1#-d}";; -* ) error "Unknown option '$1'";; * ) cancel="$cancel $1";; esac ;; * ) case "$1" in -D | -F | -R | -T | -U | -Z | -i | -m | -w | -1 | -2 | -3 | -4 ) if [ $# -ge 2 ]; then warn "Option '$1 $2' ignored"; shift; else warn "Option '$1' ignored"; fi;; -A | -D* | -I* | -N* | -O* | -Q | -V | -b | -c | -d | -f | -g | -j | -k | -l | -m | -n | -o* | -p | -s | -t | -v | -w* | -x | -\#* ) warn "Option '$1' ignored";; -P ) if [ $# -ge 2 ]; then printer="$2"; shift; fi;; -P* ) printer="${1#-P}";; -r ) remove=' -r';; -h ) hdr=true;; -C ) if [ $# -ge 2 ]; then class="$2"; shift; fi;; -J ) if [ $# -ge 2 ]; then jname="$2"; shift; fi;; -J* ) jname="${1#-J}";; ### While '-K1' was the DEC way of saying single-sided, LPRng uses it as number of copies -K1 | -Kone_sided | -Kone_sided_simplex ) dplx=false;; -K2 | -Ktwo_sided | -Ktwo_sided_duplex ) dplx=true;; ## -w ) wide=true;; # We might want this to be symmetric with -h, but -wN is an lpr option (that we do not allow) -a2ps1 ) a2ps1=true;; -* ) error "Unknown option '$1'";; * ) files="$files $1";; esac ;; esac shift done if [ "$debug" = true ]; then print -u2 -R "Command $PRF_NAME, command line: $0 $OPTIONS" fi # Find out who we really are (while USER is in environment, PROJECT isn't). unset USER USER="$(id -urn)" PROJECT="$(id -grn)" staff_person=false case " $staff_groups " in *" $PROJECT "* ) staff_person=true;; esac if [ "$debug" = true ]; then print -u2 -R "Working for $USER.$PROJECT: staff_person is $staff_person" fi # Some special printer names case "$printer" in PostScript ) printer=;; # mpage may use PostScript, do not want to confuse with stlw nearest | nearest@* | near* ) printer=;; # might also be confused with stlw lab | lab@* | lab* ) printer=; lab=true;; esac if [ -z "$printer" ]; then # No printer specified, try for nearest one for i in DISPLAY 'who -M am i' 'who -m am i' 'who -M' 'who -m'; do if [ -n "$printer" ]; then break; fi case "$i" in [A-Z]* ) if [ "$debug" = true ]; then print -u2 -R "Attempting to determine nearest printer from \$$i" fi eval "printer=\"\${$i:-}\"" if [ "$debug" = true ]; then print -u2 -R " that shows: $printer" fi ;; * ) if [ "$debug" = true ]; then print -u2 -R "Attempting to determine nearest printer from '$i'" fi eval "printer=\"\$($i 2>/dev/null)\"" if [ "$debug" = true ]; then print -u2 -R " that shows: $printer" fi case "$printer" in *'('*')'* ) printer="${printer##*\(}"; printer="${printer%%\)*}";; * ) printer=;; esac ;; esac case "$printer" in :[0-9]* ) printer="$(hostname -s)" if [ "$debug" = true ]; then print -u2 -R " that assumes hostname: $printer" fi ;; [1-9]* ) # Seem to have got an IP address, not hostname (as GDM at lenny does...) dummy=$(perl -e ' use Socket; $ip = "'"$printer"'"; $ip =~ m/^(\d+\.\d+\.\d+\.\d+)([:\.].*)?$/ or exit; $ip = $1; $name = gethostbyaddr( inet_aton($ip), AF_INET ) and print $name; ') if [ "$debug" = true ]; then if [ -n "$dummy" ]; then print -u2 -R " that seems IP address that shows: $dummy" else print -u2 -R " that seems IP address but shows nothing" fi fi if [ -n "$dummy" ]; then printer="$dummy" fi ;; esac printer="${printer%%[.:]*}" case "$printer" in [cdpxy][0-9]* ) ;; * ) if [ "$debug" = true ]; then print -u2 -R " but that does not reveal location ..." fi printer= ;; esac if [ -n "$printer" ]; then break; fi done if [ -z "$printer" ]; then error 'Must specify printer to use (cannot find nearest)'; fi #if [ ${#printer} -eq 6 ]; then printer="${printer%??}"; fi #if [ ${#printer} -eq 5 ]; then printer="${printer%?}"; fi while [ ${#printer} -ge 5 ]; do printer="${printer%?}"; done if [ -z "$laser" ]; then # For staff we use laser printers even when sitting in a lab if [ "$staff_person" = true ]; then laser=true fi fi if [ -z "$lab" ]; then # For staff we search outside of lab, otherwise restrict to lab printers if [ "$staff_person" = true ]; then lab=false else lab=true fi fi if [ "$lab" = true ]; then printer=stlw else #if [ "$laser" = true ]; then case "$printer" in ### Beware of machines that have moved rooms but retained their ### old (now wrong) names, see also ~psz/sym/dig/Make-hubs . p522 ) printer=c612;; p523 ) printer=c728;; p524 ) printer=c522;; p529 ) printer=c612;; p531 ) printer=c728;; p821 ) printer=c728;; [cdpxy]4?? ) printer=c533;; [cdpxy]520 ) printer=c520;; [cdpxy]521 ) printer=c520;; [cdpxy]522 ) printer=c522;; [cdpxy]523 ) printer=c524;; [cdpxy]524 ) printer=c524;; [cdpxy]531 ) printer=c531;; [cdpxy]532 ) printer=c532;; [cdpxy]5?? ) printer=c533;; [cdpxy]620 ) printer=c620;; [cdpxy]6?? ) printer=c612;; [cdpxy]722 ) printer=c722;; [cdpxy]813 ) printer=c813;; [cdpxy]807 ) printer=c807;; [cdpxy]813 ) printer=c813;; [cdpxy]8?? ) printer=c823;; * ) printer=r7lw;; esac #else # printer=c610;; #fi fi if [ "$debug" = true ]; then print -u2 -R "Nearest printer chosen is $printer" fi fi case "$printer" in *[!a-zA-Z0-9.,:/@%^_=+~-]* | [-~]* ) error "Printer name '$printer' has strange characters - quitting";; esac # Figure out options: maybe more than one case "$printer" in *-* ) dummy="${printer#*-}" while :; do case "$dummy" in '' ) break;; h* ) hdr=true;; w* ) wide=true;; u* ) class=unlimited;; 1* ) dplx=false;; 2* ) dplx=true;; s* ) dplx=shortedge;; x* ) staple=true;; m* ) mnlfd=true;; esac dummy="${dummy#?}" done ;; esac # Allow sloppy printer names dummy="$printer" for i in $known_printers; do j="${i#c}" k="${i%lw}" case "$dummy" in *$i* | *$j* | *$k* ) printer="$i"; break;; esac done for i in $known_printers; do case "$dummy" in *$i* ) printer="$i"; break;; esac done # Printer re-routing, to fix up sloppy names and some 'good' names. case "$printer" in c520 ) printer=lklw;; c522 ) printer=njlw;; c524 ) printer=otlw;; c531 ) printer=solw;; c532 ) printer=djlw;; c533 ) printer=r5lw;; c534 ) printer=r5lw;; c612 ) printer=p6lw;; c620 ) printer=dclw;; c722 ) printer=rzlw;; c728 ) printer=r7lw;; c807 ) printer=pglw;; c813 ) printer=gllw;; c823 ) printer=mslw;; salw ) printer=otlw;; esac #zzzzz Breakdowns. zzzzz. #case "$printer" in # p6lw ) print -u2 -R 'Printer p6lw in 612 is dead, using aolw in 728 instead'; printer=aolw;; #esac case "$printer" in aolw ) print -u2 -R 'aolw jobs now go to r7lw the Ricoh photocopier in 728 (bottom tray)'; printer=r7lw;; f5lw ) print -u2 -R 'f5lw jobs now go to r5lw the Ricoh photocopier in 533 (bottom tray)'; printer=r5lw;; fylw ) print -u2 -R 'fylw jobs now go to lklw the Kyocera photocopier in 520'; printer=lklw;; esac #case "$printer" in # r5lw ) print -u2 -R 'Room 533 is being refurbished, using r7lw in 728 instead'; printer=r7lw;; #esac case "$mode" in lpq ) ### A dirty bit of cheating... if [ "$printer" = all ]; then printer=all@rome; fi ### # print -u2 -R "Print queue $printer:" if [ "$debug" = true ]; then print -u2 -R "About to do: $LPQ -P$printer $read" fi $LPQ "-P$printer" $read # Not needed, no bounce queues: ... | sed -e 's/ (bounce [^)]*)//' -e 's/ (dest [^)]*)//' ### This was a problem with DEC lpd, cured with LPRng # # The 'I do not talk to myself' problem... # typeset -uL1 L1 # L1="$printer" # realprinter="$L1${printer#?}" # if [ -d "/usr/spool/lpd/$realprinter" ]; then # host="$(hostname -s)" # print -u2 -R "Print queue ${realprinter}-${host}:" # if [ "$debug" = true ]; then # print -u2 -R "About to do: $LPQ -P${realprinter}-${host} $read" # fi # $LPQ "-P${realprinter}-${host}" $read # fi if [ "$debug" = true ]; then exit 1 # Exit with failure: some callers show output only then... fi exit ;; lprm | cancel ) ## Seems that lprm can remove current job if none specified # if [ -z "$cancel" ]; then error "Must specify job to remove"; fi if [ "$debug" = true ]; then print -u2 -R "Not doing: $LPM -P$printer $cancel" else $LPM "-P$printer" $cancel fi ### This may have been a problem with DEC lpd, cured with LPRng # # The 'I do not talk to myself' problem... # typeset -uL1 L1 # L1="$printer" # realprinter="$L1${printer#?}" # if [ -d "/usr/spool/lpd/$realprinter" ]; then # host="$(hostname -s)" # if [ "$debug" = true ]; then # print -u2 -R "Not doing: $LPM -P${realprinter}-${host} $cancel" # else # $LPM "-P${realprinter}-${host}" $cancel # fi # fi if [ "$debug" = true ]; then exit 1 # Exit with failure: some callers show output only then... fi exit ;; esac if [ "$staff_person" = true ]; then if [ -z "$class" ]; then class=staff; fi else class=student fi printer_can_do if [ -z "$dplx" ]; then case "$printer" in stlw ) dplx=true; staple=true;; *colw* | *salw* ) dplx=false;; * ) dplx=true;; esac fi realprinter="$printer" if [ "$can_do_Epson" = true ]; then if [ "$hdr" = true ]; then realprinter="${realprinter}-h" fi if [ "$wide" = true ]; then realprinter="${realprinter}-w" fi elif [ "$can_do_PJL" = true -a "$mnlfd" = true ]; then realprinter="${realprinter}-m" elif [ "$can_do_duplex" = true ]; then if [ "$dplx" = false ]; then realprinter="${realprinter}-1" elif [ "$dplx" = true ]; then realprinter="${realprinter}-2" elif [ "$dplx" = shortedge ]; then realprinter="${realprinter}-s" fi if [ "$staple" = true ]; then realprinter="${realprinter}-x" fi fi if [ "$quotaonly" = true ]; then printquota "$USER" check 0 exit fi TF_done= if [ -z "$files" ]; then if [ -z "$jname" ]; then jname=STDIN; fi # Make a temp file (so we can check what kind it is) mktmpfile files="$TMPF" remove=true if tty -s; then print -u2 -R 'Printing from standard input (keyboard) ... end with [ctrl][d]' fi if [ "$debug" = true ]; then print -u2 -R "About to collect stdin: cat >$files" fi cat > "$files" status="$?" if [ "$status" != 0 ]; then rm -f "$files" error 'Failed to collect data (cannot read standard input)' fi if [ ! -s "$files" ]; then rm -f "$files" error 'No data collected (nothing read from standard input)' fi TF_done='After collecting standard input into file, ' fi for file in $files; do TF_hdr= TF_count=0 realfile="$file" while :; do chk_ftype "$realfile" if [ -z "$TF_command" ]; then break fi (( TF_count = $TF_count + 1 )) if [ $TF_count -ge 9 ]; then error "Loop? $TF_done we still need $TF_reason ??" fi ftransform "$realfile" TF_done="${TF_done}After doing $TF_reason, " # Check again: we may have exceeded size limits; # or we may need more transformations done printquota "$USER" check "$pages_mp" if [ -z "$realprinter" ]; then error 'Internal error (no realprinter). Sorry'; fi if [ -z "$realfile" ]; then error 'Internal error (no realfile). Sorry'; fi realpr="$realprinter" if [ "$realpr" = stlw-2-x ]; then if [ "$hdr" = true -o "$TF_hdr" = true ]; then realpr=stlw-h fi fi J= if [ -n "$jname" ]; then J="-J $jname " elif [ "$file" != "$realfile" ]; then J="-J $file " fi if [ "$debug" = true ]; then #print -u2 -R "Not doing: $LPR -P$realprinter -C $class $J$realfile" print -u2 -R "Not doing: $LPR -P$realpr -C $class $J$realfile" case "$FTYPE" in text | PS ) dummy="$(list_txt_file < $realfile | diff -h $realfile - | cat -v)" if [ -n "$dummy" ]; then print -u2 -R "Beware: we would strip out:" print -u2 -R "$dummy" fi ;; PCL ) ## Likely to have CR-LF at end of each line ... #dummy="$(list_txt_file -test < $realfile | diff -h $realfile - | cat -v)" #if [ -n "$dummy" ]; then # print -u2 -R "Beware: we would strip out:" # print -u2 -R "$dummy" #fi ;; esac if [ -n "$remove" ]; then print -u2 -R "Not doing: rm -f $file" fi else trap '' HUP INT QUIT KILL #$LPR "-P$realprinter" -C "$class" $J "$realfile" $LPR "-P$realpr" -C "$class" $J "$realfile" status="$?" trap - HUP INT QUIT KILL if [ "$status" = 0 ]; then print -R "Job queued to printer $printer." if [ -n "$remove" ]; then rm -f "$file" fi else print -u2 -R 'It seems that your print request has failed.' fi fi if [ "$file" != "$realfile" ]; then if [ "$debug" = true ]; then print -u2 -R "Rm tmp file: rm -f $realfile" fi rm -f "$realfile" fi done if [ "$debug" = true ]; then exit 1 # Exit with failure: some callers show output only then... fi exit #