2 FreeBSD handbook中文版 11 打印 高级打印机设置 A.过滤器

=============================================================
11.4 高级打印机设置
=============================================================

这一节我们要讨论的是处理特定文件格式的过滤程序、header pages、用网络打印机打
印以及打印机访问权限及打印情况统计的设置方式 。
11.4.1 过滤器
虽然LPD 负责处理网络通讯设定、队列、访问权限控制、以及其它许多打印相关的工作,
但最重要的工作还是由过滤程序来做 。过滤程序是负责与打印机沟通、处理设备依存关系、
以及一些其它特殊的需求 。我们在之前设置打印机时安装了一个最简单,但是可以和配合大
部分打印机工作的文字过滤程序(请阅读安装文字过滤程序这一节) 。
然而,如果我们想要更方便地转换格式、统计打印机使用情况、打印特别的打印机字体
等等,我们应该先了解过滤程序是如何运作的 。这些事情都是由过滤程序处理的 。不幸的是,
通常你得自己提供特定的过滤程序 。不过值得庆幸的是,有很多一般用途的过滤程序可以用,
如果没有的话,要自己做应该也很容易 。
FreeBSD 提供了一个过滤程序/usr/libexec/lpr/lpf 。这个过滤程序可以让大部分的打
印机可以打印纯文本(它只处理文件中的倒退字符以及TAB 字符,并不做统计等工作) 。在
FreeBSD 的ports 里也搜集了许多种不同的过滤程序 。
在这一节里,我们将要讨论下面这些东西:
1. 过滤程序的运作方式这一节将告诉你过滤程序在打印过程中所扮演的角色 。你可以了
解在LPD 使用过滤程序时做了哪些动作 。这些知识也能让你将来遇到过滤程序相关的问
题时能找出问题的针结 。
2. LPD 将所有的打印机都视为可以直接打印纯文本 。因此使用PostScript (以及使用其它
语言) 的打印机就无法直接打出纯文本 。在PostScript 打印机上打印纯文本这一节将
告诉你该怎么做才能解决这个问题 。如果你有PostScript 打印机,那么我建议你看看
这一节 。
第22 页FreeBSD 使用手册
3. PostScript 是一种受欢迎的输出格式 。有些人(包括我)直接撰写PostScript 的程序代
码 。但是PostScript 打印机很贵 。用非PostScript 打印机仿真PostScript 打印机这
一节告诉你如何进一步修改打印机的文字过滤程序使得非PostScript 打印机也能打印
PostScript 的资料 。如果你没有PostScript 打印机,我建议你看看这一节 。
4. 转换用的过滤程序这一节说明如何让特殊的文件格式转换自动化,比如将图形或排版
的资料转换成你的打印机所能了解的 。读完这一节后,你应该可以用lpr -t 命令打印
troff 资料,或是用lpr -d 命令打印TeX DVI 资料,或是用lpr -v 命令打印raster
影像资料,等等 。我建议阅读这一节 。
5. 输出用的过滤程序这一节说明一个LPD 不常用的功能:输出用的过滤程序 。除非你要
打印header pages(请阅读Header Pages),不然你可以略过这一节 。
6. 文字过滤程序:lpf 这一节介绍lpf 命令 。这是由FreeBSD 提供给一般的行式打印机(或
类似行式打印机的激光打印机)使用的简单文字过滤程序 。如果你希望可以快速的设置
打印机对打印纯文本的使用情况的统计,或是你想要消除打印机对倒退字符的错误打
印,那么你应该考虑使用lpf 命令 。
11.4.1.1 过滤器如何工作
上面曾经提到,过滤程序是一个由LPD 运行处理打印机与通讯端口间沟通的程序 。
当LPD 要打印文件时,它会执行过滤程序,同时从过滤程序的标准输入要打印的文件,而将
过滤程序的标准输出给打印机打印,并将过滤程序的错误记录下来(在/etc/printcap 以lf
关键词设置,或是使用默认的/dev/console) 。
LPD 要使用哪个过滤程序或是要给过滤程序哪些参数是由/etc/printcap 文件以及使用
者给lpr 命令的参数决定的 。举例来说,如果使用者输入lpr -t,那么LPD 将会使用由tf
关键词为特定打印机所指定的troff 过滤程序 。如果使用者想打印的是纯文本,那么LPD
将会使用由if 所指定的(大部分的时候是这样子的,详情请阅读输出用的过滤程序这一
节 。
在/etc/printcap 文件里你可以设置三种不同种类的过滤程序:
1. 文字过滤程序,在LPD 的文件中常称为输入用过滤程序 。通常将它作为默认的过滤程序,
负责处理一般的文字打印 。LPD 将所有打印机都视为可以直接打印纯文本,所以这个过
滤程序的任务就是将打印机无法处理的字符及格式,转换为打印机所能处理的 。如果你
第23 页FreeBSD 使用手册
需要做打印情况的统计,那么过滤程序必需要计算总行数及每页行数来统计页数 。使用
文字过滤程序的方式为:
filter-name [-c] -wwidth -llength -iindent -n login -h host acct-file
其中
-c
如果工作以lpr -l 命令送出,那么就会有这个参数
width
值是由/etc/printcap 文件中的pw (每页的字符宽度)关键词所指定的 。默认为
132 。
length
是由pl(每页的行数)关键词所指定,默认为66 。
indent
是由lpr -i 命令所指定的缩进字数,默认是0 。
login
是打印该文件的使用者帐户名称 。
host
是送出工作的机器名称 。
acct-file
是由af 关键词所指定的统计数据文件名称 。
2. 转换用的过滤程序负责将指定文件格式转换成打印机可以打出的格式 。举例来说
ditroff 排版资料无法直接交由打印机打印,不过你可以安装负责转换ditroff 文件的
过滤程序将ditroff 资料转换成打印机可以打印及处理的格式 。转换用的过滤程序这一
节将会有更详细的说明 。如果你需要做打印情况的统计,那么转换用的过滤程序也需要
做统计的工作 。使用转换用的过滤程序的方式为:
filter-name -xpixel-width -ypixel-height -n login -h host acct-file
其中pixel-width 是由px 关键词所指定(默认为0) 而pixel-height 是由py 关键词所
指定(默认为0) 。
第24 页FreeBSD 使用手册
3. 输出用过滤程序是当你没有文字过滤程序,或是要打印header pages 时才使用 。在我
的经验里,输出用过滤程序是很少用到的 。输出用的过滤程序这一节将介绍这些过滤
程序 。输出用过滤程序只接收两个参数,如下所示:
filter-name -wwidth -llength
参数-w 和-l 的意思和文字过滤程序中的意思是一样的 。
而过滤程序也应该要以下列的结束码结束程序:
exit 0
如果过滤程序成功地把文件打出 。
exit 1
如果过滤程序打印失败了而想要让LPD 再呼叫一次过滤程序重新打印,那么就以这
个值结束 。LPD 收到这个值之后,就会再重试打印 。
exit 2
如果过滤程序打印失败且不想再尝试了,那么就以这个值结束 。LPD 收到这个值将
不会再重试同时放弃打印这个文件 。
FreeBSD 里提供的过滤程序:/usr/libexec/lpr/lpf 利用每页字符宽度及每页行数来判
断什么时候要送出form feed 字符以及统计打印机打印情况 。而以使用者帐户、机器以及统
计资料文件来记录打印的情况 。
如果你想要购买过滤程序,得先了解它们是否兼容于LPD 。如果要兼容的话,它们必需
能处理上面所列的参数 。如果你想要自己写过滤程序来用,那么它们一样要处理上面所列的
参数以及程序结束码 。
11.4.1.2 在postscript 打印机上打印纯文本
如果你的计算机只有你一个人在用而且你使用的是PostScript (或是其它的打印机语
言)打印机,你也确定你决不会将纯文本的资料交给你的打印机打印,且你不会使用其它会
将纯文本送给你的打印机的程序,那么你就不需要阅读这一节 。
但是,如果你需要能处理PostScript 及纯文本的资料,那么你就得对你的打印机再做
一番设置 。我们首先要有一个文字过滤程序可以查出送过来的资料是纯文本还是
PostScript 。所有的PostScript 文件都是%! (对于其它的打印机语言,请参考你的打印机
手册) 如果一份工作的最前面两个字符是这样的话,我们收到的就是PostScript 的工作,
第25 页FreeBSD 使用手册
而我们可以直接把这份工作交给打印机处理 。如果不是的话,那么过滤程序就得把这些文字
转换成PostScript 然后再打印这些结果 。
那我们要怎么设置呢?
如果你是用串行端口上的打印机,有一个好方法就是安装lprps 。lprps 是给PostScript
打印机用的过滤程序,它负责做打印机的双向沟通 。它会将打印机的状态详细的更新到记录
文件里,如此使用者及管理者都可以清楚地看到打印机的状态 。(如果说“toner low”或是
“卡纸”) 。更重要的是,它还包括了一个叫做psif 的程序,如果查出输入的工作是纯文本,
则呼叫textps 这个程序(这是由lprps 所提供的)将纯文本转换成PostScript 。最后,它会
呼叫lprps 将工作送给打印机打印 。
你可以在FreeBSD ports 里找到lprps(请阅读The Ports Collection 这一节) 。当然,
你可以自己取得、编译及安装 。安装lprps 之后,只要指定psif (lprps 的程序之一) 的路
径即可 。如果你从ports 里安装了lprps,那么在/etc/printcap 文件里为串口的PostScript
打印机设置:
:if=/usr/local/libexec/psif:
你应该要使用rw 关键词以告诉LPD 将打印机打开为读写模式 。
如果你是使用接在并口的PostScript 打印机(因此无法使用lprps 和打印机双向沟通),
那么你可以使用下列的shell script 作为文字过滤程序:
#!/bin/sh
#
# psif - Print PostScript or plain text on a PostScript printer
# Script version; NOT the version that comes with lprps
# Installed in /usr/local/libexec/psif
#
read first_line
first_two_chars=‘expr “$first_line” : ‘(..)"‘
if [ “$first_two_chars” = “%!” ]; then
#
# PostScript job, print it.
第26 页FreeBSD 使用手册
#
echo “$first_line” && cat && printf “04” && exit 0
exit 2
else
#
# Plain text, convert it, then print it.
#
( echo “$first_line”; cat ) | /usr/local/bin/textps && printf “04” && exit
0
exit 2
fi
在上面的script 里,textps 这个命令是我们个别安装来将纯文本转成PostScript 的程
序 。你可以使用任何将文字转换成PostScript 程序 。FreeBSD ports 里(请阅读The Ports
Collection) 有一个叫做a2ps 的程序能做文字转成PostScript 的工作,你也许可以试试看 。
11.4.1.3 在没有postscript 的打印机上模拟postscript
PostScript 是高品质打印的de facto 标准 。然而,PostScript 也是一个昂贵的标准 。
值得庆幸的是,在FreeBSD 下有个叫做Ghostscript 的程序能仿真PostScript 工作,这是
由Alladin Enterprises 所发展的免费程序 。Ghostscript 可以读取大部分PostScript 文
件并且将其结果输出至许多不同的设备上,包括许多非PostScript 的打印机 。只要安装
Ghostscript 并为打印机设置一个特殊的文字过滤程序,你可以让你的非PostScript 打印
机接收PostScript 的命令 。
如果你从FreeBSD ports 里安装Ghostscript,那么你一样也可以很快的取得、编译并
安装它 。
要仿真PostScript,我们要有一个过滤程序来判断我们要打印的是不是PostScript 文
件 。如果不是,那么这个文件就直接交由打印机处理;否则,我们得先用Ghostscript 将文
件转换成打印机可以处理的 。
这里有一个例子:下面的script 是给Hewlett Packard DeskJet 500 打印机用的文字
过滤程序 。如果是其它的打印机,将gs (Ghostscript)命令的-sDEVICE 参数换成你能使用
的设备即可 。(你可以用gs -h 这个命令得到目前系统安装的Ghostscript 支持哪些设备) 。
第27 页FreeBSD 使用手册
#!/bin/sh
#
# ifhp - Print Ghostscript-simulated PostScript on a DeskJet 500
# Installed in /usr/local/libexec/hpif
#
# Treat LF as CR LF:
#
printf “33&k2G” || exit 2
#
# Read first two characters of the file
#
read first_line
first_two_chars=‘expr “$first_line” : ‘(..)"‘
if [ “$first_two_chars” = “%!” ]; then
#
# It is PostScript; use Ghostscript to scan-convert and print it.
#
# note that PostScript files are actually interpreted programs,
# and those programs are allowed to write to stdout, which will
# mess up the printed output. So, we redirect stdout to stderr
# and then make descriptor 3 go to stdout, and have Ghostscript
# write its output there. Exercise for the clever reader:
# capture the stderr output from Ghostscript and mail it back to
# the user originating the print job.
#
exec 3>&1 1>&2
/usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500
第28 页sOutputFile=/dev/fd/3 - && exit 0 ·
#
/usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 -sOutputFile=- -
&& exit 0
else
#
# Plain text or HP/PCL, so just print it directly; print a form
# at the end to eject the last page.
#
echo $first_line && cat && printf “33&l0H” && exit 0
fi
exit 2
最后,你需要用if 关键词指定这个过滤程序:
:if=/usr/local/libexec/hpif:
这么一来,你可以输入lpr plain.text 和lpr whatever.ps 而这两者应该都要可以正
确打印 。
11.4.1.4 转换用的过滤程序
在完成上面简单的打印机设置这一节所介绍的设置后,下面要做的就是为我们还想要
使用的文件格式(除了ASCII 纯文本外)安装转换用的过滤程序 。
11.4.1.4.1 为什么要安装转换用的过滤器?
转换用的过滤程序让打印不同格式的文件变得很简单 。举例来说,如果我们常常用TeX
来产生文件,但是我们的打印机是PostScript 的 。因此我们不能直接将由TeX 产生的DVI
文件由打印机打出,而要先转换成PostScript 的格式才能输出 。这些转换的命令如下:
% dvips seaweed-analysis.dvi
% lpr seaweed-analysis.ps
如果我们安装了DVI 文件的转换程序,那么我们每次要打印时就可以省去自己转换格式
的动作,而交由LPD 自己转 。因此,我们要打印DVI 文件时只要这一步就可以了:
% lpr -d seaweed-analysis.dvi
FreeBSD 使用手册
第29 页FreeBSD 使用手册
只要在使用LPD 时加上-d 参数,LPD 就会将DVI 文件转换后再正确的打出 。输出格式及
转换的参数这一节里有详细的列出转换用的参数 。
对于每一个转换用的参数,我们必需为打印机安装合适的转换用过滤程序,同时在
/etc/printcap 文件里指定该过滤程序 。转换用的过滤程序和文字过滤程序很相似(请阅读
安装文字过滤程序这一节),除了它不是打印纯文本而是将文件转换成打印机可以处理的格
式 。
11.4.1.4.2 我应该如何使用转换用的过滤程序?
你应该安装你想使用的转换用过滤程序 。如果你要打印DVI 资料,那么你应该要安装
DVI 过滤程序 。如果你要打印troff 资料,那么你应该要安装troff 过滤程序 。
下面这张表整理出可以配合LPD 工作的过滤程序和它们在要设置在/etc/printcap 里的
关键词为何,以及要使用这些过滤程序时在使用lpr 时要加什么参数:
文件格式/etc/printcap 里的关键词lpr 下的参数
cifplot cf
DVI df
plot gf
ditroff nf
FORTRAN text rf
troff rf
raster vf
if plain text
在我们的例子里,使用lpr -d 意思就是说打印机会需要用到/etc/printcap 文件里由
df 关键词所指定的过滤程序 。
不管别人怎么说,像FORTRAN 或是plot 的资料可能都已经用不到了 。在你的机器上,
你可以安装其它格式的过滤程序,如此一来你就可以将那些转换用的参数用来转换其它的
格式 。举例来说,你希望可以直接打印Printerleaf 文件(由Interleaf desktop publishing
program 产生的),而你用不到plot 文件 。那么你可以用gf 关键词指定Printerleaf 的转
第30 页
-c
-d
-g
-n
-f
-f
-v
none, -p 或-l FreeBSD 使用手册
换用过滤程序 。同时告诉你的使用者lpr -g 命令就是“打印Printerleaf 文件” 。
11.4.1.4.3 安装转换用的过滤程序
转换用过滤程序不属于FreeBSD 本身的程序,因此它们可能被放在/usr/local 目录下 。
通常我们可以将它们放在/usr/local/libexec 目录下,因为这些程序是专门给LPD 运行的,
一般使用者并不会需要去直接执行它们 。
要使用转换用过滤程序,只要将过滤程序的路径放在/etc/printcap 设置文件里用合适
的关键词指定即可 。
在我们的例子里,我们将为名为bamboo 的打印机设置一个DVI 转换过滤程序 。以下是
/etc/printcap 这个文件,其中打印机bamboo 使用了df 关键词 。
#
# /etc/printcap for host rose - added df filter for bamboo
#
rattan|line|diablo|lp|Diablo 630 Line Printer:
:sh:sd=/var/spool/lpd/rattan:
:lp=/dev/lpt0:
:if=/usr/local/libexec/if-simple:
bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:
:sh:sd=/var/spool/lpd/bamboo:
:lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:
:if=/usr/local/libexec/psif:
:df=/usr/local/libexec/psdf:
而DVI 过滤程序是一个shell script:/usr/local/libexec/psdf 。以下是它的原始代
码:
#!bin/sh
#
第31 页FreeBSD 使用手册
# psdf - DVI to PostScript printer filter
# Installed in /usr/local/libexec/psdf
#
# Invoked by lpd when user runs lpr -d
#
exec /usr/local/bin/dvips -f | /usr/local/libexec/lprps “$@”
这个script 以过滤模式执行dvips (参数-f) 在标准输入读入要打印的工作以处理 。
然后激活PostScrpt 打印机文字过滤程序lprps 同时也将LPD 传给这个script 的参数传给
该过滤程序(请阅读在PostScript 打印机上打印纯文本)这一节 。lprps 将根据这些参数来
统计打印的页数情况 。
11.4.1.4.4 更多转换用的过滤程序的例子
因为安装过滤程序没有特别固定的方式,所以我们将举多一点例子来说明 。这些例子也
许可以作为日后你自己做过滤程序时的参考,或是如果合适的话,你也可以直接拿来用 。
下面这个例子是一个将raster 资料(嗯,其实只能给GIF 文件使用)转成Hewlett
Packard LaserJet III-Si 打印机所能处理的过滤程序:
#!/bin/sh
#
# hpvf - Convert GIF files into HP/PCL, then print
# Installed in /usr/local/libexec/hpvf
PATH=/usr/X11R6/bin:$PATH; export PATH
giftopnm | ppmtopgm | pgmtopbm | pbmtolj -resolution 300
&& exit 0
|| exit 2
它先将GIF 格式转成portable anymap,然后再转成portable graymap,接着再转成
portable bitmap,最后再转成与LaserJet/PCL 兼容的资料 。
第32 页FreeBSD 使用手册
下面是使用这个过滤程序的/etc/printcap 例子:
#
# /etc/printcap for host orchid
#
teak|hp|laserjet|Hewlett Packard LaserJet 3Si:
:lp=/dev/lpt0:sh:sd=/var/spool/lpd/teak:mx#0:
:if=/usr/local/libexec/hpif:
:vf=/usr/local/libexec/hpvf:
下面的转换用过滤程序是将由grpff 排版系统所产生的troff 资料转成让PostScript
打印机bamboo 所能打印的格式:
#!/bin/sh
#
# pstf - Convert groff"s troff data into PS, then print.
# Installed in /usr/local/libexec/pstf
#
exec grops | /usr/local/libexec/lprps “$@”
上面的script 再一次使用lprps 与打印机沟通 。如果我们的打印机接在并口上,那么
我们可以用下面这个script 取代上面的script:
#!/bin/sh
#
# pstf - Convert groff"s troff data into PS, then print.
# Installed in /usr/local/libexec/pstf
#
exec grops
而如果要使这个过滤程序,我们在/etc/printcap 里的设置:
第33 页FreeBSD 使用手册
:tf=/usr/local/libexec/pstf:
这里有一个让熟悉FORTRAN 的老手惭愧的例子 。这是一个让所有可以打印纯文本的打印
机打出FORTRAN-text 的过滤程序 。我们将在teak 这台打印机上安装:
#!/bin/sh
#
# hprf - FORTRAN text filter for LaserJet 3si:
# Installed in /usr/local/libexec/hprf
#
printf “33&k2G” && fpr && printf “33&l0H” && exit 0
exit 2
我们只要将这个过滤程序在/etc/printcap 文件里指定给teak 这台打印机即可:
:rf=/usr/local/libexec/hprf:
最后一个有点复杂的例子 。我们要为先前提到的teak 这台打印机新增一个可以将DVI
转成激光打印机能处理的格式 。首先,先修改/etc/printcap 文件中关于DVI 过滤程序的位
置:
:df=/usr/local/libexec/hpdf:
然后,我们要做出这个过滤程序 。我们需要一个能将DVI 转成激光打印机PCL 格式的程
序 。FreeBSD port 里(请参考The Ports Collection 这一节)有一个:dvi2xx 是这个程序的
名称 。安装这个程序能提供我们dvilj2p 这个能将DVI 转成LaserJet IIp、LaserJet III
以及LaserJet 2000 兼容的格式 。
dvilj2p 这个程序使得hpdf 这个过滤程序变得十分的复杂,因为dvilj2p 无法从标准
输入取得资料 。它得从文件中读资料 。最糟糕的是,这个文件还必需以.dvi 结尾,所以用
/dev/fd/0 作为标准输入是不行的 。我们可以用symblic link 产生一个暂时的文件名
(以.dvi 结尾)指向/dev/fd/0,然后强迫dvilj2p 从标准输入读取资料 。
第34 页FreeBSD 使用手册
另一个问题就是我们无法用/tmp 来存放我们暂时的连接 。Symbolic links 的使用者及
群组为bin 。而过滤程序是以使用者daemon 的身份在执行 。又/tmp 目录设置了sticky bit 。
因此虽然过滤程序建立了连接,但是因为这个连接属于其它的使用者而无法删除 。
因此,过滤程序将会把symbolic link 建立在目前的目录下,也就是spooling 目录(由
/etc/printcap 文件中的sd 关键词所指定) 。这是让过滤程序来做这件事最好的地方,因为
(通常)这里的可用空间会比/tmp 下来得多 。
所以,这个过滤程序应该要这么写:
#!/bin/sh
#
# hpdf - Print DVI data on HP/PCL printer
# Installed in /usr/local/libexec/hpdf
PATH=/usr/local/bin:$PATH; export PATH
#
# Define a function to clean up our temporary files. These exist
# in the current Directory, which will be the spooling directory
# for the printer.
#
cleanup() {
rm -f hpdf$$.dvi
}
#
# Define a function to handle fatal errors: print the given message
# and exit 2. Exiting with 2 tells LPD to do not try to reprint the
# job.
#
第35 页FreeBSD 使用手册
fatal() {
echo “$@” 1>&2
cleanup
exit 2
}
#
# If user removes the job, LPD will send SIGINT, so trap SIGINT
# (and a few other signals) to clean up after ourselves.
#
trap cleanup 1 2 15
#
# Make sure we are not colliding with any existing files.
#
cleanup
#
# Link the DVI input file to standard input (the file to print).
#
ln -s /dev/fd/0 hpdf$$.dvi || fatal “Cannot symlink /dev/fd/0”
#
# Make LF = CR LF
#
printf “33&k2G” || fatal “Cannot initialize printer”
#
# Convert and print. Return value from dvilj2p does not seem to be
# reliable, so we ignore it.
第36 页#
dvilj2p -M1 -q -e- dfhp$$.dvi
#
# Clean up and exit
#
cleanup
exit 0
11.4.1.4.5 自动转换:用过滤程序转换外的另一种选择
上面这些过滤程序完整地建立了你的打印环境,但是使用者们必需自己决定要使用哪一
个过滤程序(对lpr 命令下的参数) 。如果你的使用者们并不擅长于使用计算机,要它们自己
选择适当的过滤程序来使用可能会造成它们的困扰 。更严重的是,万一使用到不正确的过滤
程序来转换格式,那么可能会让你的打印机浪费许多不必要纸 。
除了安装所有的转换用过滤程序外,你也许会想要试试文字过滤程序(默认的过滤程序)
自动扫描要打印的文件格式,同时自动呼叫其它的转换用过滤程序做适当的转换 。像file
这样的工具对于这方面可能对这会有些帮助 。然而,要区分出某些文件格式可能会有点困难
—当然,你也可以提供专门转换这些格式的过滤程序 。
FreeBSD ports 里有一个叫做apsfilter 的文字过滤程序可以做文件类型的自动扫描及
转换 。它可以分辨出纯文本、PostScript 以及DVI 文件,然后做适当的格式转换后再打出 。
11.4.1.5 输出用的过滤程序
LPD spooling 系统还支持一种我们还未介绍的过滤程序:输出用过滤程序 。输出用过滤
程序和文字过滤程序一样,只有打印纯文本才使用的,但是它简单多了 。如果你用了输出用
过滤程序但是没有用文字过滤程序,那么:
1. LPD 在一份工作里将只执行一次输出用过滤程序,而不是为每一个文件都执行一
次 。
2. LPD 不会提供任何辨认文件开始或结束的信息给输出用的过滤程序 。
FreeBSD 使用手册
第37 页FreeBSD 使用手册
3. LPD 不会将使用者的帐户及机器名称传给过滤程序,因此它不能做统计的动作 。事
实上,它只有得到两个参数:
filter-name -wwidth -llength
其中width 是由打印机设置里的pw 关键词所设置的,而length 是由pl 关键词所设置
的 。请不要被输出用过滤程序简单的特性误导了 。如果你想要用输出用过滤程序让一份工作
里每个文件都重新的一页开始打印,那是行不通的 。你应该用的是文字过滤程序(也称为输
入用过滤程序),请参考安装文字过滤程序这一节 。严格的说,输出用过滤程序实际上是较
复杂的,因为它必需检查送给它的数据是否含有特殊的字符,并代替LPD 送信号给自己 。
如果你需要打印header pages 或是需要送控制字符等其它的初始化字符串使得可以打印
header page,那么一个输出用过滤程序是必要的 。(但是如果你是为了要向使用者收取打印
header page 的费用的话,那么这是没有用的 。因为LPD 不会将任何使用者及机器的信息传
给输出用过滤程序 。)
LPD 允许一台打印机上同时拥有输出用过滤程序和文字过滤程序 。在这个情况下,LPD
会执行输出用过滤程序打印header page(请阅读Header Pages 这一节),然后LPD 会送2 个
字节给这个过滤程序:ASCII 031 以及ASCII 001 时期望输出用过滤程序将自己停下来 。当
输出用过滤程序看到这两个字节(031,001)时,它应该要送SIGSTOP 这个信号给自己 。当
LPD 运行完其它的过滤程序后,会送SIGCONT 这个信号将输出用过滤程序重新激活 。
如果只有输出用过滤程序但没有文字过滤程序,且LPD 是要打印纯文本,那么LPD 将
会用输出用过滤程序来做这些工作 。输出用过滤程序将会直将的将打印工作中的文件序输出
到打印机而不会送出form feed 或是其它控制纸张移动的命令 。因此这些结果可能不是你想
要的 。几乎在所有的情况下,你都需要一个文字过滤程序 。
我们以前介给过lpf 程序,不但可以作为文字过滤程序,也可以当作输出用过滤程序使
用 。如果你需要快速的设置好输出用过滤程序,但你不想自己写扫描资料字符及发送信号的
程序代码,那么你可以试试lpf 。你也可以在shell script 中使用lpf 将必要的初始化句
柄送给打印机 。
11.4.1.6 lpf:文字过滤程序
FreeBSD 里附带的/usr/libexec/lpr/lpf 是一个文字过滤程序(输入用过滤程序) 。它可
以处理缩进(命令lpr -i)、原封不动地打出资料(以lpr -l 命令送出的工作)、根据倒退字
第38 页FreeBSD 使用手册
符及TAB 字符调整打印的位置,以及统计打印张数 。它也可以拿来当作输出用过滤程序 。
lpf 适合在许多打印环境下使用 。虽然它无法送初始化句柄给打印机,但是我们可以很容易
的写一个shell script 送出需要的初始化句柄后再执行lpf 。
为了让lpf 可以正确的做打印张数统计,我们需要在/etc/printcap 文件里为pw 及pl
关键词填入适当的值 。它根据这些值来计算一张纸上可以打多少字,以及打印使用者的工作
需要用几张纸 。关于打印机的统计问题,请阅读统计打印机使用情况里更详细的说明 。