この節では, 特殊な形式のファイルを印字するためのフィルタ, ヘッ ダページ, ネットワーク越しのプリンタへの印字, そして, プリンタ 使用の制限や課金について説明しています.
LPD では, ネットワークプロトコル, キュー, アクセス制御, そ して, 印字のためのその他の側面について扱いますが, 実際の 作業のほとんどは フィルタ によっておこなわれています. フィルタ は, プリンタと通信し, プリンタのデバイス依存性や特殊な要求を扱 うプログラムです. 簡単なプリンタ設定では, プレインテキストのた めのフィルタをインストールしました. このプレインテキストフィル タは, ほとんどのプリンタで機能する極めて単純なものでした. (「 テキストフィルタのインストール」を参照)
しかしながら, 形式変換やプリンタ課金, 特定のプリンタの癖, など をうまく利用するためには, フィルタがどのように機能するかという ことを理解しておくべきです. これらの側面を扱うためには, 最終的 には, フィルタの責任であるからです. そして, これは悪い情報です が, ほとんどの場合において, あなた自身がフィルタを供給す る必要があるということです. また都合のよいことには, たくさんのフィルタが 一般的に利用できるということです. もしフィルタがなかったとし ても, 普通は, フィルタを作るのは簡単です.
FreeBSD にも, プレインテキストを印字させることができる /usr/libexec/lpr/lpf というフィルタが1つ付いています. (このフィルタはファイルに含まれるバックスペースやタブを扱いま す. また, 課金をすることもできますが, できることはこれだけしか ありません.) いくつかのフィルタとフィルタの構成要素が FreeBSD の ポート集にもあります.
この節で述べることは次の通りです.
「 フィルタはどのように機能しているか」では, 印字の過程におけ るフィルタの役割を概説します. この節を読むことで, LPD がフィルタを使うときに, ``見えないところで''何が起こっている かが理解できるでしょう. このことを知っておくと, プリン タそれぞれに様々なフィルタをインストールしたときに遭遇 するかもしれない問題を予期したり, デバッグするときに役 立つでしょう.
LPD では, すべてのプリンタからデフォルトでプレインテ キストを印字できることを期待しています. このことは, プ レインテキストを直接印字できない PostScript (また は他の言語用の) プリンタでは問題を引き起こします. 「 プレインテキストのジョブを PostScript プリンタで印字する」 で, この問題を克服する方法について述べます. PostScript プリンタをお持ちの方は, この節をお読みになること をお薦めします.
PostScript は様々なプログラムのための有名な出 力形式です. ある人たちは (著者自身を含めて) PostScript のコードさえも直接書いてしまいます. しかし, PostScript プリンタは高価です. 「非 PostScript プリンタで PostScript をシミュレートする」では, PostScript データを非 PostScript プリンタに受けつけさせ, 印字させるために, どのようにしてプリンタ用のテキストフィルタをさらに変更 すればよいのか, ということについて述べます. PostScript プリンタを持っていない方は, この節をお読みになる ことをお薦めします.
「 変換フィルタ」では, 図形や組版データといっ た特定のファイル形式を, プリンタが理解できる形式へ変換 する作業を自動的におこなわせる方法について述べます. この節 を読むと, troff のデータを印字するには lpr -t, または, TeX DVI を印字するには lpr -d, ラスタイ メージデータを印字するには lpr -v, などといったよ うにユーザが入力することができるようにプリンタの設定を おこなうことができます. この節もお読みになることをお薦めし ます.
「出力フィルタ」 では, あまり使われない LPD の機能のすべて, すなわち, 出力フィルタに関することが記述されています. ヘッダページ (「 ヘッダページ」参照) を印字させていない場合は, 多分, この節は飛ばしても構わないでしょう.
「テキストフィルタ lpf」では, lpf についての説明が, ほぼ完全におこなわれています. これは FreeBSD に付属するラ インプリンタ (または, ラインプリンタのように動作するレー ザプリンタ) のための, 単純なテキストフィルタです. プレ インテキストを印字したことに対して課金をおこなう方法が至急 必要な場合, もしくは, バックスペース文字を印字しようと すると煙を発するプリンタを持っている場合は, 絶対に lpf を検討するべきです.
既に言及したように, フィルタとは, プリンタにデータを送る 際に, デバイスに依存した部分を取り扱うために LPD によって起動 される実行プログラムです.
LPD がジョブ中のファイルを印字しようとするとき, LPD はフィル タプログラムを起動します. このとき, フィルタの標準入力を印字す るファイルに, 標準出力をプリンタに, そして, 標準エラー出力をエ ラーログファイル (/etc/printcap 内の lf 項目で指 定されたファイル, または, 指定されていない場合は, デフォルトと して /dev/console) にセットします.
LPD が起動するフィルタと, その引数が何であるかは, /etc/printcap ファイルの内容と, ジョブの起動時に ユーザが指定した lpr(1) コマンドの引数に依存しています. 例え ば, ユーザが lpr -t と入力した場合は, LPD は出力先のプリ ンタ用の tf 項目で指定されている troff 用のフィルタを起動 させるでしょう. ユーザがプレインテキストの印字を指示したときは, if で指定されたフィルタが 起動されるでしょう (このことはほ とんどの場合にあてはまります. 詳細については, 「 出力フィルタ」をご覧ください).
/etc/printcap で指定可能なフィルタは次の3種類がありま す.
テキストフィルタ (LPD のドキュメントでは紛ら わしいことに 入力フィルタと呼んでいますが) は一般の テキストの印字を扱います. これはデフォルトのフィルタと 考えてください. LPD では, すべてのプリンタに対して, デフォ ルトでプレインテキストが印字できることを期待しています. さらに, バックスペースやタブを正しく扱い, また, 他の特 殊な文字が入力されてもプリンタに混乱を来さないようにす るのはテキストフィルタの仕事であると考えています. プリンタの使用に対して課金をしなくてはならない環境にあ るときは, テキストフィルタが印字したページ数を数える作 業もしなくてはなりません. この作業は, 通常, 印字した行 数を数え, これをプリンタが1ページ当たりに印字できる行 数と比較することでおこなわれます. テキストフィルタは, 次のような引数を付けて起動されます.
filter-name [-c] -wwidth -llength -iindent -n login -h host acct-file
ここで,lpr -l によってジョブが入力されたときに与 えられます.
/etc/printcap で指定された pw (page width) 項目の値が与えられます. デフォル トは, 132です.
pl (page length) 項目で指定された値が与え られます. デフォルトは66です.
lpr -i によって与えられた字下げの量で, デ フォルトは0です.
ファイルを印字したユーザのアカウント名が 与えら れます.
ジョブが入力されたホスト名が 与えられます.
af 項目で指定されている課金データファイル の名前が与えられます.
変換フィルタは, 特定のファイル形式をプリンタ が紙に印字できるようなものに変換します. 例えば, プリン タで ditroff 組版データを直接印字することはできません. しかし, ditroff データをプリンタが消化し, 印字するこ とができる形式へ変換するために, ditroff ファイル用フィ ルタをインストールすることができます. 「 変換フィルタ」 で, これらに関するすべてについて説明します. プリンタの課金をする必要がある場合は, 変換フィルタでも 印字ページを数える作業が必要となります. 変換フィルタは次の引数をとって起動されます.
filter-name -xpixel-width -ypixel-height -n login -h host acct-file
ここで, pixel-width は, px 項目で指定され た値 (デフォルトは0), pixel-height は, py 項 目で指定された値 (デフォルトは0) です.出力フィルタは, テキストフィルタが指定されて おらず, かつ, ヘッダページの出力が許可されている場合に のみ使われます. 「 出力フィルタ」で, これらのことについて説明し ます. アウトプットフィルタに対する引数は次の2つだけです.
filter-name -wwidth -llength
ここで, -w と -l は, テキストフィルタの場合 と同じです.フィルタは, 次に示すの終了状態をもってプログラムを exit するべきです.
フィルタがファイルを正常に印字した場合.
フィルタはファイルの印字に失敗したが, LPD に再度ファ イルの印字を試みて欲しい場合. この終了状態で終了した場 合, LPD はフィルタを再スタートします.
フィルタはファイルの印字に失敗し, かつ, LPD に再出力 を試みて欲しくない場合. この場合, LPD はそのファイル を放棄します.
FreeBSD に付属するテキストフィルタ /usr/libexec/lpr/lpf は, FROM FEED 文字が送られたと きやプリンタ使用に対する課金をどのようにするかを 決定するために, ページ幅やページ長の引数を利用します. また, 課金用のエントリを 作成するため, ログイン名, ホスト名, 課金ファイル名の引数を利用 します.
もし, フィルタの購入を検討しているならば, LPD と互換性がある かどうかを確認してください. もしそうならば, 上述の引数リストをサ ポートしていなければなりません. 一般向けの使用のためにフィルタ を作成する計画をしている場合は, 同じ引数リストと終了コードをサ ポートしてください.
コンピュータと PostScript (または, 他の言語に対応し た) プリンタをあなたしか使用しない場合は, プリンタにプレ インテキストを絶対に送らない, そして, プリンタにプレインテキス トを送りたがっている様々なプログラムの機能を決して 使わないこと にしてください. そうすれば, この節に書かれたことに心を煩わせる必 要はまったくなくなります.
しかし, PostScript とプレインテキストの両方のジョブをプリン タへ送りたいと思っている場合は, プリンタ設定についての要求が増 えるでしょう. 両者をプリンタへ送信するためには, 到着 したジョブがプレインテキストであるか PostScript であるかを 検出するテキストフィルタが必要です. PostScript のジョブは すべて %! で始まらなければならないことになっています (他のプリンタ言語に関しては, プリンタのドキュメントをご覧くだ さい). ジョブの最初の2文字がこれならば, PostScript である ことが分かります. したがって, ジョブのそれ以降の部分をプリンタに直 接送ることができます (訳注:PostScript では, % 以降はコメントとして扱われるので, 最初の %! の行を 読み捨てても問題はない). 最初の2文字が %! でない場 合は, フィルタはテキストを PostScript に変換し, その結果を 使って印字をおこないます.
この作業をどうやってやればよいのでしょうか.
シリアルポートにプリンタを接続した場合は, lprps をインス トールすることをお勧めします. lprps は PostScript 用のフィルタで, プリンタとの双方向通信をおこないます. このフィルタでは, プリンタか らの冗長な情報を得ることで, プリンタの状況を示すファイルが更新 されていきます. したがって, ユーザや管理者は (トナー残量少や 紙詰まりといった) プリンタの状況を正確に知ることができます. しかし, もっと重要なことは, psif と呼ばれるプログラムが 含まれているということです. このプログラムは, 入力されたジョブ がプレインテキストかどうかを検出し, これを PostScript に変 換するために, textps (lprps に付属する別のプログラ ム) を呼び出します. そして, このジョブをプリンタに送るために, lprps が使われます.
lprps は FreeBSD のポート集に含まれています (「 ポートコレクション」を参照してください). もちろん,自分自身でプログラムを取ってきて, コンパイルし, インストールす ることもできます. lprps をインストールした後は, lprps の一部である psif プログラムのパス名を指定する だけです. ポート集から lprps をインストールしたときは, /etc/printcap の中のシリアル接続した PostScript プリンタのエントリに対して, 次を使ってください.
:if=/usr/local/libexec/psif:
LPD にプリンタをリード・ライトモードでオープンさせるために, rw 項目も指定すべきです.
パラレルポートに接続したプリンタの場合 (すなわち, lprps が 必要としているプリンタとの双方向通信ができない), テキストフィ ルタとして次のシェルスクリプトを使うことができます.
#!/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. # echo "$first_line" && cat && printf "\004" && exit 0 exit 2 else # # Plain text, convert it, then print it. # ( echo "$first_line"; cat ) | /usr/local/bin/textps && printf "\004" && exit 0 exit 2 fi
上記のスクリプトにおいて, textps はプレインテキストから PostScript へ変換するために別にインストールしたプログラム です. テキストから PostScript へ変換するのには, お好みのどんなプロ グラムでも使うことができます. FreeBSD の ポート集 (「ポートコレクション」 を参照してください) には, a2ps と呼ばれるテキストから PostScript に変換するプログラムが 入っています.
Note: 訳注: 上記スクリプトでは, 先頭の行を読み込むために read を使っていますが, 困ったことに, read は読み込んだ文字列の先頭 の空白文字を取り除いてしまいます. 従って, これらの空白文字は印 字されないことになり, 印字結果がファイルのイメージと異なる場合 が出てきます. この事情は csh を利用した場合でも変わりません. 仮に, 先頭の空白文字を除去しない read コマンドを作ったとしても, 「echo $first_line」の $first_line 変数の内容をシェルが展開す る際に $first_line の先頭の空白文字が失われるため, 問題の解決 にはなりません. 残念ながら, 訳者はこの問題をシェルプログラムだ けで解決する方法をしりません. perl か C 言語の力を借りないと解 決できないと思います.
PostScript は質の高い組版と印字をおこなうための事実 上の標準です. しかしながら, PostScript は, 高価な標 準です. ありがたいことに, Alladin Enterprises から Ghostscript と呼ばれる, PostScript 互換の動作をするフリー のプログラムが出されていて, FreeBSDで動きます. Ghostscript はほとんどの PostScript ファイルを読むことができ, これらの 各ページをたくさんのブランドの非 PostScript プリンタを含む 様々なデバイス用に変換することができます. Ghostscript をイン ストールし, プリンタ用の特別なテキストフィルタを使うことによっ て, 非 PostScript プリンタをあたかも本物の PostScript プリンタであるかのように動作させることができます.
Ghostscript はポート集に入っていますので, そこからインストール することができます. また, 自分でソースプログラムを持ってきて, コンパイルし, インストー ルすることもできます. この作業はとても簡単にできます.
PostScript プリンタをシミュレートさせる場合は, テキストフィ ルタに PostScript ファイルを印字しようとしているかどうかを 検出させます. PostScript ファイルでない場合は, フィルタは そのファイルを直接プリンタに送ります (訳注:テキストファイルを直 接印字できない場合は, もちろん, 変換フィルタを通す必要がありま す). PostScript の場合は, まず, Ghostscript を使い, ファ イルをそのプリンタが理解できる形式へ変換します.
次の例のスクリプトは, Hewlett Packard DeskJet 500 プリンタ用 のテキストフィルタです. 他のプリンタで用いるときは, -sDEVICE 引数を gs (Ghostscript) コマンドに変えてくだ さい. (gs -h と入力すると, 現在インストールされている Ghostscript でサポートされているデバイスのリストが得られます).
#!/bin/sh # # ifhp - Print Ghostscript-simulated PostScript on a DeskJet 500 # Installed in /usr/local/libexec/hpif # # Treat LF as CR+LF: # printf "\033&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 # /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 "\f" && exit 0 fi exit 2
最後に, if 項目を通して, LPD にこのフィルタを教えてやる 必要があります.
:if=/usr/local/libexec/hpif:
これでおしまいです. lpr plain.text とか lpr whatever.ps と入力してみましょう. どちらも正常に印字されるは ずです.
Note: 訳注: 日本語を印字する場合は, 日本語対応の Ghostscript が必要で す. 日本語対応版の Ghostscript もポート集に入っているはずです.
「プリンタ設定導入編」 に書かれた簡単な設定が完了したら, 最初に, やってみたいと思 うことは, 多分(プレイン ASCII テキストに加えて) 好みのファイル形式 のための変換フィルタをインストールすることでしょう.
変換フィルタによって, 様々な種類のファイルを印字するこ とが簡単になります. 例えば, TeX 組版システムでたくさんの仕事 をしたと仮定しましょう. そして, PostScript プリンタが接続 されているとします. すると, TeX で DVI ファイルを作成する度に, DVI ファイルを印字するために, これを PostScript ファイルに 変換する必要があります. このコマンドは次のようになるでしょう.
% dvips seaweed-analysis.dvi % lpr seaweed-analysis.ps
DVI ファイル用の変換フィルタがインストールしてあると, LPD に 変換を肩代わりさせることで毎回毎回 おこなわなければならなかった面倒 な変換作業を省くことができます. つまり, DVI を生成したら, 次のような1回のコマンド入力だけで, これが印字されます.
% lpr -d seaweed-analysis.dvi
LPD に DVI ファイルの変換をさせるためには, -d オプション を指定します. 変換オプションのリストは「 整形と変換に関するオプション」 に載せてあります.
変化のオプションのそれぞれをプリンタに サポートさせるためには, 変換フィルタをインストールし, そのパス名を /etc/printcap の中で指定しなくてはなりません. 変換フィ ルタは, プレインテキストを印字する代わりに, フィルタはファイル をプリンタが理解できる形式に変換するところを除けば, 「プリンタ の簡単な設定」で説明したテキストファイル (「 テキストフィルタのインストール」 を見て下さい) に似ています.
使いたいと思う変換フィルタをインストールすべきです. DVI のデータを頻繁に印字するならば, DVI 変換フィルタ をインストールするのが適切でしょう. 印字しなくてはなら ない troff を大量に抱えている場合は, 多分, troff フィ ルタが欲しくなるはずです.
次の表は, LPD で動作するフィルタと, /etc/printcap ファイルでのエントリする項目, そして, lpr コマンドで呼び出す方法をまとめたもの です.
ファイル形式 | /etc/printcap項目 | lpr オプション |
---|---|---|
cifplot | cf | -c |
DVI | df | -d |
plot | gf | -g |
ditroff | nf | -n |
FORTRAN text | rf | -f |
troff | tf | -t |
raster | vf | -v |
プレインテキスト | if | なし, -p, または -l |
先の例のように, lpr -d を使うためには, 出力先の プリンタの /etc/printcap 内のエントリで, df 項目が必要であることが分かります.
反論はあるかも知れませんが, FORTRAN テキストや plot のような形式は, 多分, 廃れ てていくでしょう. あなたのサイトで, 自前のフィルタをイ ンストールするだけで, プリントオプションのいくつか, あ るいは, 全部に新しい意味を与えることができます. 例えば, Prinerleaf ファイル (Interleaf デスクトップパブリッシン グプログラムによるファイル) を直接印字したいとします. そして, Printerleaf 用の変換フィルタを gf 項目で 指定したパスにインストールすれば, lpr -g の意味 は``Printerleaf ファイルを印字する''意味だとユーザに教 えることができます.
変換フィルタは FreeBSD の基本システムのインストールとは別 にインストールするプログラムなので, 変換フィルタは, 多 分, /usr/local ディレクトリの下に置くべ きです. フィルタは LPD だけが実行する特別なプログラム, すなわち, 一般ユーザが実行する必要すらない プログラムなので, /usr/local/libexec ディレ クトリに置くのが普通です.
変換フィルタを使用可能にするためには, /etc/printcap の目的のプリンタの適切な項目に フィルタがあるパス名を指定します.
DVI 変換フィルタをプリンタ bamboo のエントリに加 えてみましょう. プリンタ bamboo の df 項目を 新たに加えた/etc/printcap ファイルの例を以下 に再掲します.
# # /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 フィルタは /usr/local/libexec/psdf という 名前のシェルスクリプトです. このスクリプトは次のように なっています.
#!bin/sh # # 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 "$@"
このスクリプトでは, dvips をフィルタモード (引数 -f) で, 標準入力上で起動しています. 標準入力は印字 するジョブです. それから, PostScript プリンタ用フィ ルタ lprps (これについては「 プレインテキストのジョブを PostScript プリンタで印字する」 を参照してください) を LPD に与えられた引数を付けて起動 します. lprps はこれらの引数を印字されたページ分 の課金をおこなうために使われます.
変換フィルタのインストールには決まったステップがないの で, その代わりに, 例をもっと挙げることにします. これを, 自分でフィルタを作る際のガイドにしてください. 適当な例が あったら, それをそのまま使ってください.
次のスクリプト例は, Hewlett Packard LaserJet III-Si の ための, raster (ええと・・実は, GIF ファイル) 用の変 換フィルタです.
#!/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 ファイルから PNM (portable anymap) 形式 に変換し, 次に PGM (portable graymap) 形式に変換してか ら, LaserJet/PCL-互換データに変換しています.
上記のフィルタを使うプリンタのためのエントリを付け加え た /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:
次のスクリプトは, PostScript プリンタ bamboo のための groff 組版システムの troff データのための変換 フィルタです.
#!/bin/sh # # pstf - Convert groff's troff data into PS, then print. # Installed in /usr/local/libexec/pstf # exec grops | /usr/local/libexec/lprps "$@"
上記のスクリプトではプリンタとの通信をおこなうため, lprps をまた利用しています. プリンタがパラレルポー トに接続されている場合は, 代わりに, 次のスクリプトを使 うかもしれません.
#!/bin/sh # # pstf - Convert groff's troff data into PS, then print. # Installed in /usr/local/libexec/pstf # exec grops
これで完成しました. 次に, フィルタを使用可能にするため に /etc/printcap に加える必要があるエントリを 示します.
:tf=/usr/local/libexec/pstf:
次の例をみたら, FORTRAN のベテランは赤面するかもしれ ません. この FORTRAN テキストフィルタは, プレインテキ ストを直接印字できるすべてのプリンタで利用できます. この フィルタをプリンタ teak にインストールすることに しましょう.
#!/bin/sh # # hprf - FORTRAN text filter for LaserJet 3si: # Installed in /usr/local/libexec/hprf # printf "\033&k2G" && fpr && printf "\f" && exit 0 exit 2
そして, このフィルタを使用可能にするため, 以下の行を /etc/printcap のプリンタ teak のエントリ に加えます.
:rf=/usr/local/libexec/hprf:
これが最後の, そして, 若干複雑な例です. 前に紹介した LaserJet プリンタ teak に, DVI フィルタを加える ことにしましょう. 最初に, 簡単な部分をおこないます. すなわ ち, DVI フィルタの位置を /etc/printcap に書 き加えます.
:df=/usr/local/libexec/hpdf:
さて, 難しい部分であるフィルタの作成をおこないます. このた めに, DVI から LaserJet/PCL への変換プログラムが必要 です. FreeBSD のポート集 (「ポートコレクション」 を参照してください) には, それがあ ります. dvi2xx というのがそのパッケージの名前で す. これをインストールすると, 必要なプログラム dvilj2p が使えます. このプログラムは DVI を LaserJet IIp, LaserJet III, そして LaserJet 2000 の互 換コードへ変換してくれます.
dvilj2p はフィルタ hpdf を極めて複雑にしてい ます. なぜなら, dvilj2p は標準入力からデータを読 み込むことができないからです. このプログラムを働かせる ためには, ファイル名が必要です. もっと悪いことに, ファ イル名は .dvi で終わっている必要があり, 標準入力 の代わりに, /dev/fd/0 を使うのは問題がありま す. この問題は, (.dvi で終わる) 一時的なファイル名 から/dev/fd/0 に (シンボリックな) リンクを張る ことで回避することができます. これで, dvilj2p に 強制的に標準入力からデータを 読み込ませることができます.
もう1つの問題は, 一時的なリンクを張るために /tmp ディ レクトリを使うことができないという事実です. シンボリッ クリンクはユーザ, グループが bin であるユーザに所 有されています. フィルタはユーザ daemon として起 動します. そして, /tmp ディレクトリはスティッ キービットが立っています. フィルタはリンクを作ることが できます. しかし, リンクは別のユーザに所有されているた め, 作業が終了したとき, このリンクを削除することができ ません.
その代わりに, シンボリックリンクは現在の作業ディレクト リ, すなわち, スプーリングディレクトリ (/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. # 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 "\033&k2G" || fatal "Cannot initialize printer" # # Convert and print. Return value from dvilj2p does not seem to be # reliable, so we ignore it. # dvilj2p -M1 -q -e- dfhp$$.dvi # # Clean up and exit # cleanup exit 0
ここまでに述べてきたフィルタによって, 印字環境の能率が 上がったことと思います. しかし, これはどのフィルタを使 うかを ( lpr(1) のコマンドライン上で) ユーザが指定しな くてはならないという代価を支払って実現されています. コ ンピュータの事情にあまり詳しくないユーザにとって, フィ ルタのオプションを指定させられるということはいらいらさ せられるものになるでしょう. 更に悪いことに, 間違ったフィ ルタオプションを指定されると, 間違った形式のファイルが そのフィルタに適用されることになり, その結果, 何百枚も の紙を掃き出すことになるかもしれません.
そのような結果になるならば, 変換フィルタをインストール するよりもむしろ, テキストフィルタ (これがデフォルトフィ ルタなので) に印字するよう要求されたファイルの形式を検 出させ, 自動的に, 適切な変換フィルタを起動するようにし たいと思うかもしれません. ここでは file コマンド のようなツールを役立たせることができます. もちろん, いくつかの ファイル形式の違いを見分けることは難しい ことでしょう. そして, もちろん, それらのファイルに対し ては, 変換フィルタを提供するだけで済ますこともできるの です.
FreeBSD のポート集には, apsfilter と呼ばれる自 動変換をおこなうテキストフィルタがあります. このフィルタは プレインテキスト, PostScript, DVI ファイルを検 出し, 適当な変換をおこなった後, データを印字することができ ます.
LPD スプーリングシステムでは, ここまでにまだ取り上げていな いフィルタ形式, 出力フィルタをサポートしています. 出力 フィルタは, テキストフィルタのように, プレインテキスト のみを印字するために意図されたものですが, 非常に簡単化 されています. テキストフィルタを用いずに, 出力フィルタ を使っている場合は, 次のようになります.
LPD はジョブ中の各ファイルに一度ではなく, ジョブ 全体に対して一度だけ出力フィルタを起動します.
LPD は出力フィルタに対し, ジョブ中のファイルの先 頭や末尾を特定するための対策を一切 おこなっていません.
LPD はユーザのログイン名やホスト名をフィルタに渡 しません. したがって, 課金の処理をおこなうことは考えてい ません. 実際, 出力フィルタには, 以下2つの引数しか与え られません.
filter-name -wwidth -llength
ここで, width は対象となるプリンタの pw 項 目, length は pl 項目に指定された数です.
出力フィルタの簡便さに誘惑されてはいけません. もし, ジョ ブ中のそれぞれのファイルに別のページ番号を付加しようと しても, 出力フィルタはうまく動作しないでしょう. そのような動作を期待しているならば, (入力フィルタとし ても知られている) テキストフィルタを使ってください. 詳 しくは, 「 テキストフィルタのインストール」をご覧ください. さらに, 出力 フィルタは, 実のところ, もっと複雑になっています. まず, 特殊なフラグ文字を検出するために, フィルタに送ら れてくるバイトストリームを検査する必要があります. また, LPD に代わって, 自分自身にシグナルを送らなければなりま せん.
しかしながら, ヘッダページの印字をおこないたい場合, また, エスケープシーケンスやヘッダページを印字できるようにす るその他の初期化文字列を送信する必要がある場合, 出力ファ イルが必要です.
1台のプリンタに対し, LPD では出力フィルタとテキスト, または, 他のフィルタを両方使うことができます. このよう な場合, LPD はヘッダページ (「 ヘッダページ」 を参照してください) だけを印字させるために, 出 力フィルタを起動させます. それから LPD では, アウトプッ トフィルタに2バイトの文字 (ASCII 031 の次に ASCII 001) を送ることで, 出力フィルタが自力で停止することを 期待しています. 2バイト (031, 001) が出力フィルタに送られ たとき, 出力フィルタは自分自身にシグナル SIGSTOP を送 ることによって停止するべきです. LPD がその他のフィル タの起動を完了したとき, LPD は出力フィルタにシグナル SIGCONT を送ることで, 出力フィルタを再起動させます.
出力フィルタがあり, テキストフィルタがない場合, LPD はプレインテキストのジョブをおこなう際に, 出力フィル タを使います. 前述したように, 出力フィルタでは, ジョブ 中の各ファイルの並びの間に FROM FEED 文字や紙を排出す る他の文字を入れることはしません. この動作は多分, あな たが求めているものとは 異なっているでしょう. ほと んどすべての場合において, テキストフィルタが必要とされる はずです.
プログラム lpf は, テキストフィルタの項で既に紹介 しましたが, 出力フィルタとしても動作させることができま す. もし, 簡便で極悪な出力フィルタが必要で, かつ, バイ トストリームを検査したりシグナルを送るコードを書きたく ないときには, lpf をお試しください. あるいは, プ リントが要求する初期化コードを送るために, lpf を シェルスクリプトに包んで使うこともできます.
プログラム /usr/libexec/lpr/lpf は, FreeBSD の バイナリ配布に付属しているテキストフィルタ (入力フィル タ) で, 出力を字下げしたり (lpr -i でジョブが入力さ れたとき), 文字を未処理のままプリンタに送ったり (lpr -l でジョブが入力されたとき), ジョブ中のバッ クスペースやタブの印字位置を調節したり, 印字したページ に対して課金したりすることができます. また, このフィル タは出力フィルタとしても動作させることができます.
lpf は多くの印字環境において使用することに適して います. このフィルタには, プリンタに初期化文字列を送る 機能はありませんが, 必要とされる初期化をおこない, それから lpf を実行させるためのシェルスクリプトを作成する のはたやすいことです.
lpf に対して, 印字ページへの課金を正確におこなわせる ためには, /etc/printcap ファイルの中の pw と pl の項目に正確な値を入れておく必要が あります. これらの値は, どのくらいの量のテキストがペー ジにフィットするか, また, ユーザのジョブが何ページある のかを調べるために使われます. プリンタの課金についての 詳しい情報については, 「 プリンタの利用に対する課金」をご覧ください.
あなたが管理するシステムのユーザが たくさんおり, ユー ザ全員が様々なプリンタを使用する場合, 多分, 必要悪である ヘッダページ を印字させることを検討したいと思うかもしれま せん.
ヘッダページは, バナー とか バーストページ としても知ら れていますが, 出力されたジョブが誰によるものなのかを特定させる 働きがあります. 印字結果の山の中において, ユーザのジョブによっ て印字された本物のドキュメント部分よりも際立たせるために, ヘッ ダページは, 通常, 多分, 縁が装飾されている大きな太文字で印字さ れます. ヘッダページにより, ユーザは自分が出したジョブがどこに あるのかをすばやく見つけることができます. ヘッダページの欠点は, 明らかに, すべてのジョブに対して, 紙が1枚余分に印字されるという ことです. この紙の有効期間は短く, 2〜3 分も続きません. 最終的に, これらの紙は再利用紙入れの中か くずの山に入れられることでしょう. (ヘッダページはジョブ中の各ファイル毎に印字されるのではなく, ジョブ毎に印字されるということに注意してください. したがって, 紙の 消費はそれほどひどくはないかもしれません).
もし, プリンタがプレインテキストを直接印字できるならば, LPD システムは印字物に対して自動的にヘッダページを付けることが できます. PostScript プリンタを使っている場合は, ヘッダペー ジを生成する外部プログラムが必要になります. これについては, 「 PostScript プリンタでのヘッダページ」をご覧ください.
「プリンタ設定導入編 」 では, /etc/printcap ファイルの sh (``suppress header'' : ``ヘッダを供給しない'' という意味) を指定して, ヘッダペー ジの印字を止めていました. プリンタでのヘッダページの印字を許可 するには, sh 項目を取り除くだけよい訳です.
とても簡単そうに見えるけど, 本当かな?
それは本当です. プリンタに初期化文字列を送るための出力フィ ルタを用意しなくてはならないかもしれません. 次に, Hewlett Packard PCL 互換プリンタの例を挙げます.
#!/bin/sh # # hpof - Output filter for Hewlett Packard PCL-compatible printers # Installed in /usr/local/libexec/hpof printf "\033&k2G" || exit 2 exec /usr/libexec/lpr/lpf
of 項目に出力フィルタのパス名を指定してください. 詳細につ いては, 「出力フィルタ」 をご覧ください.
次に, 以前紹介したプリンタ teak のための /etc/printcap ファイルの例を示します. ここでは, ヘッ ダページの印字を許可し, 上記の出力フィルタを追加しました.
# # /etc/printcap for host orchid # teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\ :lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:\ :if=/usr/local/libexec/hpif:\ :vf=/usr/local/libexec/hpvf:\ :of=/usr/local/libexec/hpof:
さて, ユーザが
teak
からジョブを印字させたとき, それぞれ のジョブ毎にヘッダページが印字されます. もし, ユーザが印字物を 探すのに時間を費やしたいと思うなら, lpr -h によってジョ ブを入力することで, ヘッダページの印字を止めることができます. これ以外の lpr(1) のオプションについては, 「 ヘッダページ用オプション」 をご覧ください.Note: LPD では, ヘッダページの最後に, FROM FEED 文字が印 字されます. プリンタに紙排出をさせるために, 別な文字, もしくは, 別な文字列が利用されている場合は, /etc/printcap 中の ff 項目で指定することができます.
ヘッダページの印字が許可されていると, LPD は 長いヘッ ダを作ります. これには, 紙全面に大きな文字でユーザ名, ホスト 名, ジョブ名が書かれています. 次に, このヘッダページの例を示 します (kelly が ジョブ名 outline を rose というホストから印字 された場合).
k ll ll k l l k l l k k eeee l l y y k k e e l l y y k k eeeeee l l y y kk k e l l y y k k e e l l y yy k k eeee lll lll yyy y y y y yyyy ll t l i t l oooo u u ttttt l ii n nnn eeee o o u u t l i nn n e e o o u u t l i n n eeeeee o o u u t l i n n e o o u uu t t l i n n e e oooo uuu u tt lll iii n n eeee r rrr oooo ssss eeee rr r o o s s e e r o o ss eeeeee r o o ss e r o o s s e e r oooo ssss eeee Job: outline Date: Sun Sep 17 11:04:58 1995
LPD はこのテキストの終わりに FROM FEED 文字を加えます ので, ジョブは新しいページから開始されます (ただし, /etc/printcap で出力先のプリンタのエントリに sf (suppress form feeds) が指定されているときはこ の限りではありません).
お望みならば, LPD に短いヘッダページを出力させる こともできます. この場合は, /etc/printcap ファ イルの中で sb (short banner) を指定してください. ヘッダページは次のようになります.
rose:kelly Job: outline Date: Sun Sep 17 11:07:51 1995
デフォルトでは, LPD はヘッダページを最初に印字し, 次 にジョブの印字をおこないます. この順番を逆にするときは, /etc/printcap で hl (header last) を指定 してください.
LPD に備わっているヘッダページ出力機能を使うと, 入力され たジョブに対して課金をおこなうことができても, ヘッダページは無 料で提供しなくてはならない, という特有のやり方を強要されます.
なぜでしょうか.
出力フィルタは単なる外部プログラムなので, 課金をするための制御 をおこなうとすれば, それはヘッダページを印字するときですが, 出力フィ ルタには, ユーザ名とホスト名 の情報や課金情報を格納するファ イルがどれな のかということが知らされません. それゆえ, 出力ファイルには, 誰 にプリンタ利用の課金をおこなえばよいのかが分からないのです. テキス トフィルタやその他の変換フィルタ (これらのフィルタはユーザやホ ストの情報が知らされます) が出力ページの枚数に``1ページ分水増し する''だけでは十分ではありません. なぜなら, ユーザは lpr -h に よってヘッダページの出力を止めることができるからです. やみくも に1ページを水増しすると, 印字されてもいないヘッダページに対する 料金をとることになります. 基本的に, lpr -h は環境に優し い心を持つユーザに好まれるオプションですが, これを使うように奨 励することもできません.
各々のフィルタに独自のヘッダページを生成させる (その結果, ヘッ ダページに課金することができる) という方法でも十分であると はいえません. この場合, LPD はフィルタに -h の情報を送 りませんので, lpr -h によってヘッダページを印字しないオ プションを選択したとしても, 依然としてヘッダページは印字され, その分の課金がおこなわれてしまいます.
では, どのような選択肢があるのでしょうか.
ヘッダページへの課金に関しては, 次のことができます.
LPD のやり方を受け入れ, ヘッダページは無料とする.
LPDng や PLP といった LPD の代替品をインストール する. LPD と入れ替えが可能な他のスプーリングソフトウェ アに関しては, 「 標準スプーラの代替品」をご覧ください.
スマートな 出力フィルタを作成する. 通常, 出力 フィルタはプリンタを初期化するか, 単純な文字列変換をす る程度の働きしかしません. (テキスト (入力) フィルタがな い場合) 出力フィルタはヘッダページとプレインテキストの 印字をおこなうのに適しています. プレインテキストを印字するためのテキストフィルタがない 場合, LPD はヘッダページを印字するためだけの目的で出 力フィルタを起動します. そして, LPD が生成するヘッダ ページのテキストを解析することにより, 出力フィルタはヘッ ダページに課金するために必要なユーザ名とホスト名を取得 することができます. この方式の唯一の問題点は, 出力フィ ルタは課金情報を格納するデータファイルの名前を知ることが できないということです (af 項目で指定されたファイ ル名は出力ファイルに渡されません). しかし, 既知の 名前の課金データファイルを使うのならば, その名前を出 力フィルタのプログラム中に埋め込むことができます. 解析の手順を簡単にするためには, /etc/printcap で sh 項目 (短いヘッダを指 定) を使うとよいでしょう. そしてまた, ここまでの方法は少なからぬトラブルを生じさ せるかもしれません. そうなれば, もちろんユーザはヘッダペー ジを無料で 提供してくれる気前のよいシステム管理者に感謝することで しょう.
これまでに述べたように, LPD ではプレインテキストのヘッ ダページをたくさんのプリンタに合うように生成することが できます. 残念ながら, PostScript プリンタは, プレインテキストを直接 印字することができません. ですから, LPD のヘッダページ機能は まったく役に立たない, あるいはほとんどの場合で役に立ちません.
ヘッダページを出力するための自明な方法の1つに, すべての変換フィ ルタとテキストフィルタにヘッダページを生成させる 方法があります. フィルタは, 適切なヘッダページを生成するために, ユーザ名とホス ト名の引数を使うべきです. この方法の欠点は, いつでも, lpr -h によってジョブが入力された場合でさえも, ヘッダページが印字 されるということです.
この方法で試してみましょう. 次のスクリプトは, 3つの引数 (ユーザ のログイン名, ホスト名, ジョブ名) をとり, 簡単な PostScript 用 のヘッダページを生成します.
#!/bin/sh # # make-ps-header - make a PostScript header page on stdout # Installed in /usr/local/libexec/make-ps-header # # # These are PostScript units (72 to the inch). Modify for A4 or # whatever size paper you are using: # page_width=612 page_height=792 border=72 # # Check arguments # if [ $# -ne 3 ]; then echo "Usage: `basename $0` <user> <host> <job>" 1>&2 exit 1 fi # # Save these, mostly for readability in the PostScript, below. # user=$1 host=$2 job=$3 date=`date` # # Send the PostScript code to stdout. # exec cat <<EOF %!PS % % Make sure we do not interfere with user's job that will follow % save % % Make a thick, unpleasant border around the edge of the paper. % $border $border moveto $page_width $border 2 mul sub 0 rlineto 0 $page_height $border 2 mul sub rlineto currentscreen 3 -1 roll pop 100 3 1 roll setscreen $border 2 mul $page_width sub 0 rlineto closepath 0.8 setgray 10 setlinewidth stroke 0 setgray % % Display user's login name, nice and large and prominent % /Helvetica-Bold findfont 64 scalefont setfont $page_width ($user) stringwidth pop sub 2 div $page_height 200 sub moveto ($user) show % % Now show the boring particulars % /Helvetica findfont 14 scalefont setfont /y 200 def [ (Job:) (Host:) (Date:) ] { 200 y moveto show /y y 18 sub def } forall /Helvetica-Bold findfont 14 scalefont setfont /y 200 def [ ($job) ($host) ($date) ] { 270 y moveto show /y y 18 sub def } forall % % That is it % restore showpage EOF
そして, 変換フィルタやテキストフィルタがそれぞれ, 最初にこのス クリプトを起動することで, ヘッダページが出力され, それから, ユー ザのジョブの印字をおこないます. 次に, このドキュメントの始めのほう で紹介した DVI 変換フィルタを, ヘッダページを印字するように変 更したものを示します.
#!/bin/sh # # psdf - DVI to PostScript printer filter # Installed in /usr/local/libexec/psdf # # Invoked by lpd when user runs lpr -d # orig_args="$@" fail() { echo "$@" 1>&2 exit 2 } while getopts "x:y:n:h:" option; do case $option in x|y) ;; # Ignore n) login=$OPTARG ;; h) host=$OPTARG ;; *) echo "LPD started `basename $0` wrong." 1>&2 exit 2 ;; esac done [ "$login" ] || fail "No login name" [ "$host" ] || fail "No host name" ( /usr/local/libexec/make-ps-header $login $host "DVI File" /usr/local/bin/dvips -f ) | eval /usr/local/libexec/lprps $orig_args
このフィルタがユーザ名やホスト名を決定するために 引数リストをど のように解析しなくてはならないかという点に注意してください. こ の解析方法は他の変換フィルタに対しても同様です. しかしながら, テキストフィルタについては, 引数の設定が少し異なっています (こ れについては, 「 フィルタはどのように機能しているか」 をご覧ください).
前述の通り, 上記の手法は, 極めて単純なのにも関らず, lpr で``ヘッダページを印字しない''オプション (-h オプション) が 使えなくなっています. ユーザが森林資源を (あるいは, ヘッダペー ジが課金されているならば, その僅かな金額を), 節約したいと望んでい る場合でも, すべてのフィルタがすべてのジョブ毎にヘッダページを印字 することになっているので, 節約することはできません.
ジョブ毎に印字されるヘッダページを ユーザが抑制できるようにする ためには, 「 ヘッダページに対する課金」で紹介したトリックを 使う必要があります. すな わち, LPD が生成するヘッダページの解析をおこない, PostScript 版のヘッダページを出力させる出力フィルタを作るのです. この場 合, ユーザが lpr -h でジョブを入力すると, LPD はヘッダペー ジを生成しなくなり, また, 出力フィルタも起動されません. そうで ないならば, 作成した出力フィルタが LPD からのテキストを読み込 み, ヘッダページを印字する適当な PostScript のコードがプリ ンタに送られるでしょう.
PostScript プリンタがシリアルポートに接続されている場合, 出力フィルタとして lprps を, 上記の動作をおこなうものとして psof を使うことができます. ただし, psof はヘッダペー ジに対して課金をおこないませんので注意してください.
FreeBSD では, ネットワーク越しの印字, すなわち, ジョブをリ モートプリンタに送ることをサポートしています. リモートプリンタ からの出力をするには, 一般に, 次の2つを参照してください.
リモートホストに接続されたプリンタにアクセスする方 法. プリンタがあるホストのシリアル, または, パラレルイ ンタフェースに接続されている場合, ネットワーク上の他の ホストからこのプリンタにアクセスできるように LPD を設 定します. 「 リモートホストに 接続されたプリンタ」 でどのよう にするかを説明します.
ネットワークに直接接続されているプリンタにアクセ スする方法. プリンタに, 旧来のシリアル, または, パラレ ルインタフェースに加えて (もしくは, これらに代わって) ネッ トワーク用のインタフェースがある場合. そのようなプリン タは次のように動作するでしょう.
そのプリンタが LPD のプロトコルを理解でき, リモー トホストからのジョブを キューに入れることさえできる場合. この場合, プリンタは, LPD が起動している一般のホスト のように振る舞います. そのようなプリンタを設定するため に, 「 リモートホストに接続されたプリンタ」 と同様の手 順をおこなってください.
そのプリンタが, データストリームによるネットワー ク接続をサポートしている場合. この場合, ネットワーク上 の1つのホストとしてプリンタを``接続''します. このホス トは, ジョブをスプーリングする責任を負い, スプーリング されたジョブはプリンタに送られます. そのようなプリンタ をインストールするためのいくつかの提案が「 ネットワークにおけるデータストリームの インタフェースを持つプリンタ」にあります.
LPD スプーリングシステムでは LPD (または LPD 互換のシス テム) が起動している他のホストへジョブを送る機能が始めからサポー トされています. この機能により, あるホストに接続されたプリンタ へ, 他のホストからアクセスできるようになります. また, LPD プ ロトコルを理解するネットワークインタフェースを持った プリンタに 対しても, この機能は働きます.
リモートプリンタへの出力を許可するためには, 最初に, あるホスト (これを, プリンタホストと呼びます) にプリンタを接続します. そして, 「 プリンタ設定導入編」 に書かれた簡単なプリンタの設定をおこなってください. 必要ならば, 「プリンタ設定上級編」 にあ る, 更に進んだ設定をおこなってください. そして, そのプリンタをテス トしてうまく動作することを確認し, LPD に許可した機能がうまく働 くかどうかを見てください. さらに ローカルホスト が プリンタホスト の LPD サービスの使用を 許可されているか確認して 下さい (「 リモートホストからのプリンタの利用を制限する 」参照).
LPD 互換のネットワークインタフェースを持つプリンタを使用してい る場合は, そのプリンタ自身が以下で説明する プリンタホスト になります. そして, プリンタ名とは, そのプリンタに設定し た名前のことを指します. これについては, プリンタ, および (また は), プリンタのネットワークインタフェースに付属するドキュメン トを参照してください.
次に, そのプリンタにアクセスしたいと思っている他ホストにおいて, そのホストの /etc/printcap ファイルに次にあげるエント リを作ります.
名前のエントリ. どんな名前でもよいのですが, 簡単 のため, 多分, プリンタホストで設定されたプリンタ名や別 名と同じものを使いたいと思うでしょう.
lp 項目で指定されるデバイスは明示的に空にす る (:lp=: とする).
スプーリングディレクトリを作成し, sd 項目で その位置を指定する. LPD では, プリンタホストにジョブ を送信するまでの間, このディレクトリにジョブを格納しま す.
rm 項目でプリンタホストの名前を指定します.
rp 項目で プリンタホスト に接続したプリン タ名を指定します.
これで終わりです. 変換フィルタやページの大きさやその他の事項を /etc/printcap に加える必要はありません.
次に, リモートホストに接続されたプリンタで印字するための設定例 を示します. ホスト rose には2台のプリンタ bamboo と rattan が接続されています. これらのプリンタをホスト orchid のユーザが使えるようにしましょう. 最初に orchid の /etc/printcap を示します (このファイルは, 「 ヘッダページの出力を許可する」 で参照することができます). このファイルには, 既に, プリンタ teak 用のエントリがありました. 以下では, これに, ホスト rose にある2台のプリンタ用のエントリが加えられ ています.
# # /etc/printcap for host orchid - added (remote) printers on rose # # # teak is local; it is connected directly to orchid: # teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\ :lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:\ :if=/usr/local/libexec/ifhp:\ :vf=/usr/local/libexec/vfhp:\ :of=/usr/local/libexec/ofhp: # # rattan is connected to rose; send jobs for rattan to rose: # rattan|line|diablo|lp|Diablo 630 Line Printer:\ :lp=:rm=rose:rp=rattan:sd=/var/spool/lpd/rattan: # # bamboo is connected to rose as well: # bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :lp=:rm=rose:rp=bamboo:sd=/var/spool/lpd/bamboo:
orchid で必要となる作業はスプーリングディレクトリを 作ることだけです.
# mkdir -p /var/spool/lpd/rattan /var/spool/lpd/bamboo # chmod 770 /var/spool/lpd/rattan /var/spool/lpd/bamboo # chown daemon.daemon /var/spool/lpd/rattan /var/spool/lpd/bamboo
これで, orchid のユーザが rattan と bamboo で印字す ることができるようになりました. 例えば, orchid のユーザが次の ように入力したとします.
% lpr -P bamboo -d sushi-review.dviすると, orchid の LPD システムは, ジョブをスプーリングディレ クトリ /var/spool/lpd/bamboo にコピーし, これが DVI ファイルを印字するジョブであることを記録します. ホスト rose の bamboo 用のスプーリングディレクトリに十分な容量が確保でき 次第, 両者の LPD は, ジョブのファイルを rose に転送します. こ のファイルは, そのすべてが印字されるまで, rose のキューに留まり ます. (bamboo は PostScript プリンタなので) DVI から PostScript への変換は rose でおこなわれます.
プリンタのネットワークインタフェースカードは, 2種類に分 類することができます. 1つはスプーラをエミュレートするもの (高価) で, もう 1 つはシリアルやパラレルポートを使うようにプリンタにデー タを送ることができるだけのもの (安価) です. この節では, 後者の使 い方を説明します. 前者のプリンタは, 前節「 リモートホストに接続されたプリンタ」 の方法が適用できます.
/etc/printcap ファイルでは, シリアルかパラレルのイン タフェースのどちらを使うのか, そして, (シリアルインタフェース を使う場合) そのボーレートはいくらであるか, フロー制御は使うのか, タブのための遅延を加えるのか, 改行文字を変換するかなどの指定を おこなうことができます. しかし, TCP/IP や他のネットワークポートか らデータを受け取るプリンタを接続するための 指定をおこなうことはでき ません.
ネットワーク接続されたプリンタにデータを送るためには, テキスト フィルタと変換フィルタから呼び出すことができる 通信プログラムを 開発する必要があります. 以下に, そのようなプログラムの例を示し ます. スクリプト netprint では, 標準入力から印字データを すべて受け取り, ネットワーク接続されたプリンタにこれを送ります. netprint の最初の引数でプリンタのホスト名を, 2番目の引数 で接続するポート番号を指定します. このプログラムでは単方向通信 (FreeBSD からプリンタ) のみをサポートしていることに注意してくだ さい. ネットワークプリンタの多くは双方向通信をサポートしていま すので, その恩恵 (プリンタの状態を得たり, 課金をおこなうなど) にあず かりたいと思われるかもしれません.
#!/usr/bin/perl # # netprint - Text filter for printer attached to network # Installed in /usr/local/libexec/netprint # $#ARGV eq 1 || die "Usage: $0 <printer-hostname> <port-number>"; $printer_host = $ARGV[0]; $printer_port = $ARGV[1]; require 'sys/socket.ph'; ($ignore, $ignore, $protocol) = getprotobyname('tcp'); ($ignore, $ignore, $ignore, $ignore, $address) = gethostbyname($printer_host); $sockaddr = pack('S n a4 x8', &AF_INET, $printer_port, $address); socket(PRINTER, &PF_INET, &SOCK_STREAM, $protocol) || die "Can't create TCP/IP stream socket: $!"; connect(PRINTER, $sockaddr) || die "Can't contact $printer_host: $!"; while (<STDIN>) { print PRINTER; } exit 0;
このスクリプトは, 様々なフィルタが利用することができます. 仮に, Diablo 750-N ラインプリンタを持っており, これがネットワークに 接続されているとしましょう. プリンタはポート番号5100にて印字す るデータを受け取ります. プリンタのホスト名は scrivener としま す. このとき, このプリンタのテキストフィルタは次のようになりま す.
#!/bin/sh # # diablo-if-net - Text filter for Diablo printer `scrivener' listening # on port 5100. Installed in /usr/local/libexec/diablo-if-net # exec /usr/libexec/lpr/lpf "$@" | /usr/local/libexec/netprint scrivener 5100
本節では, プリンタの利用に制約を与えるための情報を記して います. LPD システムでは, プリンタ (ローカル, リモートのいずれ に接続されていても) にアクセスできる人を制限する機能, 複数部の コピーの印字の可否を制御する機能, ジョブのサイズの最大値やプリ ンタキューに入るジョブの最大個数を制御する 機能を提供しています.
LPD システムではユーザが複数部のコピーの印字を簡単におこなう 機能を提供しています. ユーザが, (例えば) lpr -#5 コマ ンドを使ってジョブを印字すると, ジョブのそれぞれのファイルのコ ピーを5部得ることができます. これがよい機能であると思うかどう かは人それぞれでしょう.
複数部のコピーの印字によってプリンタが 必要以上に消耗してしまう と感じるならば, /etc/printcap ファイルに sc 項 目を加えてください. これにより, lpr(1) の -# オプションの使用 が禁止されます. このオプションが指定されているにも関らず, -# オプションを使うと, 次のようなメッセージが表示され, このオプションの利用できない旨を伝えます.
lpr: multiple copies are not allowed
リモートホストからプリンタをアクセスできる 設定にしている場合 (この 設定については, 「 リモートホストに接続されたプリンタ」 をご覧ください), その リモートホストの /etc/printcap にも同じように sc 項目を追加する必要があることに注意してください. そうしないと, ユーザは別なホストから複数部のコピーの 印字することができてしま います.
例を使って説明しましょう. 次に示す /etc/printcap ファ イルは, ホスト rose のものです. プリンタ rattan は極めて 頑丈なので, 複数部のコピーの印字は許可されています. しかし, レー ザプリンタの bamboo はもう少しデリケートで, このプリンタ から複数部のコピーを印字することを sc 項目を追加すること で禁止しています.
# # /etc/printcap for host rose - restrict multiple copies on 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:sc:\ :lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:\ :if=/usr/local/libexec/psif:\ :df=/usr/local/libexec/psdf:
さらに, orchid の /etc/printcap にも
sc
項目を 追加する必要があります (orchid でこの編集をおこなっているときに, つ いでに, プリンタ teak でも複数部のコピーの印字を禁止する ことにしましょう).# # /etc/printcap for host orchid - no multiple copies for local # printer teak or remote printer bamboo teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\ :lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:sc:\ :if=/usr/local/libexec/ifhp:\ :vf=/usr/local/libexec/vfhp:\ :of=/usr/local/libexec/ofhp: rattan|line|diablo|lp|Diablo 630 Line Printer:\ :lp=:rm=rose:rp=rattan:sd=/var/spool/lpd/rattan: bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :lp=:rm=rose:rp=bamboo:sd=/var/spool/lpd/bamboo:sc:
sc 項目を指定することにより, lpr -# の使用を防 ぐことができます. しかし, この状態では lpr(1) を複数回起動し たり, 1回のジョブで次のように同じファイルを 複数個指定すること を防ぐまでには至っていません.
% lpr forsale.sign forsale.sign forsale.sign forsale.sign forsale.sign
このような悪用を防ぐ方法は (その指示を無視することも含めて) たく さんあります. 各自で調べてみてください.
それぞれのプリンタを使用できる人を限定するには, UNIX の グループ権限のメカニズムを利用し, さらに, /etc/printcap で rg 項目を指定することでおこないます. あるプリンタにアクセスさせてもよいと思うユーザすべてを UNIXのある グループに入れてください. そして, そのグループ名を rg で 指定します.
このとき, そのグループに含まれないユーザ (root も含む) が rg の指定がされたプリンタを使用すると, 次のようなメッセー ジが表示され, プリンタの使用はできません. lpr: Not a member of the restricted group sc (suppress multiple copies : 複数部のコピーの印字を禁止 する) を指定するときと同様に, rg が指定されたプリンタがリ モートホストからもアクセスでき (この設定については, 「 リモートホストに接続されたプリンタ」 をご覧ください), かつ, そ のホストでもプリンタを使用できる人を限定するのが 妥当であると思 う場合は, そのホストの /etc/printcap にも rg 指 定をおこなう必要があります.
例えば, プリンタ rattan は誰でも利用できるが, bamboo はグループ artists に属している人のみが利用で きるようにしてみましょう. 以下に, もうお馴染みとなったホスト rose の /etc/printcap を示します.
# # /etc/printcap for host rose - restricted group 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:sc:rg=artists:\ :lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:\ :if=/usr/local/libexec/psif:\ :df=/usr/local/libexec/psdf:
これ以外の /etc/printcap ファイル (ホスト orchid のもの) はそのままにしておくことにします. もちろん, orchid のユーザは 全員 bamboo を利用することができます. これは, orchid に は特定のユーザのみにしかアクセスさせておらず, そのユーザにはプ リンタを利用させたいと思っているからなのかもしれませんし, そう でないかもしれません.
Note: 1台のプリンタを複数グループのユーザに利用させること はできません.
たくさんのユーザからプリンタが利用される場合には, 多分, ユーザが印字要求を出すことができるファイルのサイズに 上限値を置 く必要が生じるでしょう. 結局のところ, スプーリングディレクトリ が置かれているファイルシステムの空き容量がその 上限値になる訳で すが, あるユーザがこれを独占的に使用すること避けるために, 他ユー ザからのジョブ用の空き容量を確保する必要もあります.
LPD では, mx 項目を指定することにより, ジョブ中の個々のファ イルのサイズの上限値を制限する機能を提供しています. 指定される ファイルサイズの単位は BUFSIZ ブロックで, 1 BUFSIZ ブロックは 1024バイトを表わします. この mx 項目の値として0が指定される と, ファイルサイズの制限はなくなります.
Note: この制限はジョブ中の各 ファイルに対して適用されるものであり, ジョブ全体のサイズ を制限するものではありません.
ところで, プリンタに設定された上限値を超えるファイルサイズのファ イルが入力された場合でも, LPD はこれを拒否しません. その代わ りに, このファイルは, その先頭から上限値のファイルサイズまでし かキューに入れられません. そして, その部分までが印字され, 残り の部分は捨てられます. これが正しい動作といえるのかどうかは議 論の余地があるところです.
それでは, 設定例に登場しているプリンタ rattan と bamboo の印字可能なファイルサイズに制限を加えてみましょう. artists グループの人達が作る PostScript ファイルのサイズは 巨大になる傾向があるので, 上限値を5Mバイトとします. それから, プレインテキスト用のラインプリンタは無制限とします.
# # /etc/printcap for host rose # # # No limit on job size: # rattan|line|diablo|lp|Diablo 630 Line Printer:\ :sh:sd=/var/spool/lpd/rattan:\ :lp=/dev/lpt0:\ :if=/usr/local/libexec/if-simple: # # Limit of five megabytes: # bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:mx#5000:\ :lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:\ :if=/usr/local/libexec/psif:\ :df=/usr/local/libexec/psdf:
この場合もそうですが, この制限はローカル (ホスト rose) のユーザ のみに適用されます. リモートホストからプリンタを利用できるよう に設定している場合は, そのリモートホストのユーザはこの制限を受 けません. これらのユーザにも制限を加える場合は, リモートホスト の /etc/printcap の mx を指定する必要があります. リモートホストから印字するための詳しい情報については, 「 リモートホストに接続されたプリンタ」 を参照してください.
リモートホストに接続されたプリンタへのジョブの サイズを制限する 特別な方法は他にもあります. これについては, 「 リモートホストからのプリンタの利用を制限する」 を参照してください.
LPD スプーリングシステムでは, リモートホストから要求され たジョブの印字を制限するための方法がいくつか 提供されています.
ローカルの LPD が印字要求を受け付けるリモートホストは, ファイル /etc/hosts.equiv と /etc/hosts.lpd によって制御することができます. LPD では, あるホストから印字の要求がきたとき, このホス トの名前がこれら2つのファイルのどちらかに含まれている かどうかを調べます. これが含まれていない場合は, LPD はこの要求を拒否します.
これらのファイルの形式は単純です. 各行にホストの名前を 1つずつ書いていきます. ファイル /etc/hosts.equiv の方は ruserok(3) プロトコル でも利用され, rsh(1) や rcp(1) といったプログラム の動作に影響するので注意が必要です. /etc/hosts.equiv の記述は慎重におこないましょう.
例として, 以下にホスト rose の /etc/hosts.lpd を示します.
orchid violet madrigal.fishbaum.de
この例では, rose はホスト orchid, violet, そして madrigal.fishbaum.de からの要求を受け付けることになり ます. その他のホストが rose の LPD にアクセスしようと しても, LPD はこれを拒否します (訳注:拒否されるのは, そのホストが /etc/hosts.equiv にも含まれてい ない場合です).
スプーリングディレクトリがある ファイルシステムに残して おく必要がある空き容量の大きさを制御することが できます. ローカルプリンタ用のスプーリングディレクトリに minfree という名前のファイルを作成します. そして, そのファイルの中にリモートホストからのジョブの要求を受 け付けるために必要な空き容量のディスクブロックサイズ (1 ディスクブロック=512バイト) を記します.
これで, リモートホストのユーザにファイルシステムを満杯 にされないことが保証されます. この機能を使うと, ローカ ルホストのユーザに対してある種の優先権を与えることもで きます. ローカルホストのユーザは, minfree ファイ ルで指定された値よりもディスクの空き容量が下回った後で もずっと, ジョブをキューに入れることができるのです.
例えば, プリンタ bamboo 用の minfree を作っ てみましょう. このプリンタのスプーリングディレクトリを 調べるために, /etc/printcap を調べてみましょ う. 以下に, bamboo のエントリ部分を示します.
bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:mx#5000:\ :lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:mx#5000:\ :if=/usr/local/libexec/psif:\ :df=/usr/local/libexec/psdf:
スプーリングディレクトリは
sd
で指定されます. LPD がリモートホストからのジョブを受け付けるために必要 なファイルシステムの空き容量を3Mバイト (=6144ディスクブ ロック) にすることにしましょう.# echo 6144 > /var/spool/lpd/bamboo/minfree
/etc/printcap の rs 項目を指定することで, ローカルプリンタを利用できるリモートホストのユーザを制 限することができます. ローカルホストに接続されたプリン タ用のエントリに rs 項目が指定されている場合, LPD は印字を要求したユーザのアカウントと同じログイン名 がローカルホストに登録されている/em/場合に限り/, その ジョブが受け付けられます. そうでないユーザからのジョブ は LPD は拒否します.
この機能は, (例えば) 複数の部署がネットワークを共有して おり, この内のあるユーザが部署の境界を越えて活動してい る場合には特に有用です. そのようなユーザに対して, シス テムのアカウントを与えるだけで, これらのユーザは自分が 所属する部署のシステムからそのシステムに接続されている プリンタを使用することができます. これらのユーザにはむ しろ, プリンタの使用だけを認め, その他のコンピュー タ資源を利用させたくないときは, それらのユーザにはホー ムディレクトリを与えず, ログインシェルはシェルとしては 何の役にも立たない /usr/bin/false などを指定 して, これらのユーザのアカウントはプリンタ用の``形式的 な''ものとします.
という訳で, 印字するためには料金をとることが必要です. 取ら ない理由などありましょうか. 紙やインクにはお金がかかります. そ して, プリンタの維持費もかかります. プリンタには可動部分が搭載 されており, これらの部分は壊れやすいという傾向があります. プリ ンタや, その利用形態, 維持費について調査をし, 1ページ (1フィー ト, 1メートルなど) 当たりにかかるコストを調べておいてください. これに基づき, プリンタの利用に対する課金を, 実際に, どのように 始めればよいのでしょうか.
さて, 残念ながら, この部分に関しては LPD スプーリングシステム はほとんど役に立ちません. 課金は使用しているプリンタの種類, 印 字するもののファイルの形式, プリンタの利用に対する課金での あなた自身の要求に大きく左右されます.
課金システムを実現するためには, プリンタのテキストフィルタ (プ レインテキストのジョブに対して課金するため) と変換フィルタ (その 他のファイル形式に対して課金するため) を変更して, 印字したペー ジを数えたり, プリンタに印字したページ数を取得するための要求を 送る必要があります. ただし, 出力フィルタのみを利用している場合 は, 課金をおこなうことができません. フィルタに関しては, 「 フィルタ」をご覧く ださい.
一般に, 課金方式には次の2つがあります.
定期的に課金する方法 はよく利用される方法です. この理由は, 恐らく, 比較的簡単に実現できるからです. 誰 かがジョブを印字する度に, フィルタはそのユーザ名, ホス ト名, 印字したページ数を課金データファイルに記録します. 毎月, 毎学期, 毎年, あるいは, お好みの時期に, 様々なプ リンタの課金用ファイルを集め, それぞれのユーザが印字し たページ数を合計し, その分の課金をおこないます. 次回の課金 時期のためのデータを0にして課金を再開するために, この 処理をおこなった後, すべてのログファイルを削除し,
利用毎に課金する方法 はあまり利用されていません. これは, 実現するのが比較的難しいからです. この方式では, プリンタを使用したらすぐに, フィルタがユーザにその利用 に対する課金をおこないます. ディスククオータのように, 課金 作業は瞬時におこなわれます. この方式では, ユーザのアカウン トが赤字になる場合に, ユーザが印字をおこなうことを拒否する ことができます. また, ユーザに``プリンタ版 quota''を 調べたり, 調整したりする方法を提供したいと思うかもしれ ません. これを実現するためには, ユーザとその quota を 追跡するために, あるデータベース用のコードが必要となり ます.
LPD スプーリングシステムでは, 両方式を簡単にですがサポー トしています. これは, (ほとんどの場合で) 印字作業をフィ ルタがおこなっていたように, 課金作業もこのためのコードも用 意することで実現されています. しかし, 明るい面もありま す. それは, 課金方式に関して, 非常に大きな柔軟性が与え られたということです. 例えば, 「定期的に課金する方法」 か, 「利用毎に課金する方法」のどちらかを選びまず, そし て, どんな情報 (ユーザ名, ホスト名, ジョブのタイプ, 印 字された頁数, 使用した紙の大きさ, 印字をするために要した 時間など) をログに記録するかを決めます. 以上のことをおこな うには, 上記の情報を保持するために, フィルタを変更しな くてはなりません.
FreeBSD には, 「定期的に課金する方法」による課金をすぐに 設定できるように, 2個のプログラムを添付しています. そ の内の1つはテキストフィルタ lpf で, これについて は, 「 テキストフィルタ lpf」をご覧ください. もう1つは, pac(8) で, これはプリンタの課金データファイルからのエントリを集め, これを合計するプログラムです.
「 フィルタはどのように機能しているか」で述べたように, LPD では テキストフィルタや変換フィルタを起動しますが, そのコマ ンドラインで使用している課金データファイルの名前が指定 されます. 両フィルタはこの引数を使って, どの課金データ ファイルのエントリに書き込めばよいのかを知ることができ ます. このファイルの名前は /etc/printcap 中の af 項目によって指定されます. このファイルが絶対パ スで指定されない場合は, スプーリングディレクトリからの 相対パスとして扱われます.
LPD は, 紙のページの幅と行数 (pw と pl 項目で 指定される) を引数として lpf を起動します. lpf では, 何ページ印字したかを決定するためにこれ らの引数を使用します. ファイルをプリンタに送った後, 課 金情報を課金データファイルに書き込みます. このファイル は次のようになります.
2.00 rose:andy 3.00 rose:kelly 3.00 orchid:mary 5.00 orchid:mary 2.00 orchid:zhang
課金データファイルはプリンタ毎に分けて作るべきです. こ れは, lpf にはデータファイルをロックする機構が組 み込まれていないためです. したがって, lpf が2つ起動 されたとき, 同じファイルに同時に書き込みをおこなった場合, お互いのエントリが破壊されてしまうかもしれません. 課金 用ファイルを各プリンタ毎に確実に分けるには, /etc/printcap 中の af=acct 項目を使いま す.
プリンタの利用に対してユーザに課金する準備ができたら, スプーリングディレクトリに移動した後, pac(8) と入力 してください. 次のような, ドル中心主義の課金リストが表 示されます(訳注:ドル中心主義という表現は, 表示がドルで 出ることへの著者の皮肉でしょう. セントがあるので小数点 以下が表示されますが, この機能も日本では邪魔ですね).
Login pages/feet runs price orchid:kelly 5.00 1 $ 0.10 orchid:mary 31.00 3 $ 0.62 orchid:zhang 9.00 1 $ 0.18 rose:andy 2.00 1 $ 0.04 rose:kelly 177.00 104 $ 3.54 rose:mary 87.00 32 $ 1.74 rose:root 26.00 12 $ 0.52 total 337.00 154 $ 6.74
pac(8) が受け付ける引数には 次のようなものがあります.
プリンタ printer の利用に対する課金リストを作成し ます. このオプションは, /etc/printcap の af が絶対パスで指定されていた場合に限り, 動作しま す.
ユーザ名のアルファベット順ではなく, 課金額の低い順にリ ストを並べます.
課金データファイルにあるホスト名を無視します. このオプショ ンを使用すると, ホスト alpha のユーザ smith とホスト gamma のユーザ smith は同一人物として扱われます. この オプションが指定されない場合は, 両者は別なユーザとして 扱います.
/etc/printcap の pc 項目で指定された値, または, デフォルトの値 (2セント) に代わり, 紙1ページ, ま たは, 1フィート当たりの価格を指定します. price として, 浮動小数点数を指定することができます.
リストの並べる順番を逆順にします.
課金リストを作成し, 課金データファイルを削除します.
ユーザ names に対する課金情報のみを表示します.
pac(8) が生成するデフォルトのリストには, 各ホストのユーザ別 に印字ページ数が表示されます. (ユーザがサイト内のすべてのホスト を使用できるため) ホスト名の情報が意味を持たない場合, pac -m を実行してください. 次のようなリストが得られます.
Login pages/feet runs price andy 2.00 1 $ 0.04 kelly 182.00 105 $ 3.64 mary 118.00 35 $ 2.36 root 26.00 12 $ 0.52 zhang 9.00 1 $ 0.18 total 337.00 154 $ 6.74
課金額を決めるために, pac(8) は /etc/printcap ファ イルの pc 項目で指定された値 (デフォルト値は200, すなわち1 ページ当たり2セント) を使います. この項目で, 印字物に課金したい と思う1ページ当たり, または, 1フィート当たりの価格を100分の1セ ント単位で指定します. pac(8) を -p オプション付きで起動 すると, この値を置き換えることができます. この -p オプショ ンで指定する額の単位は, 100分の1セント単位ではなく, ドル単位で す. 例えば, 次の指定では, 1ページ当たりの単価が1ドル50セントに なります.
# pac -p1.50このオプションを使うと, 実際の課金額を集計することができます.
最後に, pac -s を起動すると, 課金情報は課金データ累計ファ イルに保存されます. このファイルの名前は, プリンタの課金データ ファイルの後ろに _sum を付けたものとなります. そして, 課 金データファイルは削除されます. 次に pac(8) が起動されると, その時点までの累計金額を得るために, 課金データ累計ファイルが読 み込まれ, 通常の課金データファイルからの情報に 加算されます.
課金を, リモートホストからの印字でさえも, 正確におこなうため には, ジョブで使用された紙が何ページであるかを特定でき る必要があります. このことは, プリンタ利用に対する課金 をおこなう上の根本的な問題です.
プレインテキストのジョブの場合, 問題を解決するのはさほ ど難しくはありません. ジョブが何行であったかを数え, プ リンタがサポートしている紙1ページに印字できる最大の行 数と比較すればよいのです. 重ね打ちするために利用される ファイル中のバックスペース文字や, 物理的に複数の行に渡 る長い論理行に対する取り扱いを 忘れずにおこなってください.
(「テキストフィ,ルタ lpf」で紹介した) テキストフィルタ lpf では, 課金をおこなうときに, これらの取り扱いをおこなってくれます. 課 金をおこなうために必要なテキストフィルタを作成している方は, lpf のソースコードが参考になるでしょう.
これに対して, 他のファイル形式の処理はどのようにすれば よいのでしょうか.
まず, DVI から LaserJet, または, DVI から PostScript への変換の場合, フィルタが dvilj や dvips の 出力メッセージを解析することで, 何ページ分の変換がおこなわ れたかを知ることができます. 他のファイル形式とその変換 プログラムに関しても, 同様のことができるかもしれません.
しかし, この方式には問題点があります. それは, 変換され たページがすべて印字されるとは限らないということです. 例 えば, プリンタが紙詰まりを起こしたり, トナー切れになっ たり, はたまた, 爆発したりするかもしれません. そのよう な状況により印字が途中で中止されたとしても, この方式で は, ユーザは全ページ分の料金を課されてしまうのです.
それでは, どのような対策をたてることができるのでしょう か.
正確な 課金をおこなうための唯一の確実な方法は, 何 ページ印字したのかを知らせることができるプリンタを入手 し, これをシリアルポートかネットワークに接続することで す. ほとんどすべての PostScript プリンタではこの概念 がサポートされています. 他のプリンタも同様です (Imagen レーザプリンタをネットワーク接続するなど). それぞれの プリンタのフィルタを, ジョブを印字した後で印字ページ数 を得るように, 変更してください. そして, 課金情報はここ で得られた値のみに 基づいて記録してください. 行数 を数えたり, エラーが生じやすいファイルの調査は必要とさ れません.
もちろん, 気前よく印字料 金をすべて無料にすることもできます.