FreeBSD kézikönyv
Előző | Fejezet 9. Nyomtatás | Következő

# 9.4. Magasszintű nyomtatóbeállítás

Ebben a szakaszban olyan szűrőket mutatunk be, amelyek speciálisan formázott állományok, fejléclapok, hálózati nyomtatás, nyomtatási nyilvántartás vagy szabályozás esetén használhatóak.

## 9.4.1. Szűrők

Noha az LPD képes hálózati protokollokat, nyomtatási sorokat, hozzáférést és sok minden más nyomtatási feladatot kezelni, a tényleges munka legnagyobb része a szűrőkben (filter) történik. A szűrők olyan programok, amelyek tartják a kapcsolatot a nyomtatóval és megbirkóznak annak eszközfüggőségeivel és különleges igényeivel. Az egyszerű beállítás során egy primitív szövegszűrőt állítottunk be (lásd A szövegszűrő telepítése) -- ami annyira egyszerű, hogy szinte minden nyomtatón működnie kell.

Azonban mindahhoz, hogy ki tudjuk használni a különböző átalakítási, nyilvántartási lehetőségeket, valamint a nyomtatók különlegességeit és egyebeit, meg kell értenünk a szűrők pontos működését. Az előbb említett feladatok ugyanis teljesen a szűrő kezében vannak. Ezzel kapcsolatban azonban rossz hír, hogy ezeket a szűrőket nekünk kell megírnunk. A jó hír ellenben az, hogy könnyen találunk ilyen szűrőket, vagy ha éppen nem lelnénk valamelyiket, akkor is gyorsan meg tudjuk ezeket írni.

Sőt, a FreeBSD alapból tartalmaz is egyet, amit a `/usr/libexec/lpr/lpf` helyen találunk meg, és sok olyan nyomtatóval képes együttműködni, amelyek nyers szöveget tudnak nyomtatni. (Kezeli az állományokban felbukkanó törléseket és tabulálásokat, valamint képes nyilvántartást vezetni, de semmi többet.) Rajta kívül még számos szűrőt és szűrőelemet is találhatunk a FreeBSD Portgyűjteményében.

Lássuk, mit tartogat számunkra ez a rész:

- A Hogyan működnek a szűrők? című szakaszban megpróbálunk egyfajta áttekintést adni a szűrők nyomtatási folyamatban betöltött szerepéről. Mindenképpen érdemes elolvasnunk ezt a szakaszt, mivel ebben derül ki, hogy valójában mi is történik a “függöny mögött”, vagyis amikor az LPD használja ezeket a szűrőket. Ezzel a tudással el tudjuk kerülni vagy éppen nyakon tudjuk csípni azokat a problémákat, amelyek a nyomtatóinkhoz telepített szűrők hozzáadása során adódhatnak.

- Az LPD alapból arra számít, hogy minden nyomtató képes nyers szöveget nyomtatni. Ez gondot okoz a PostScript® (és minden más nyelv alapú) nyomtatók esetén, mivel azok nem képesek nyers szöveget nyomtatni. Szöveges nyomtatási feladatok PostScript nyomtatókon című szakaszban viszont fény derül rá, hogyan kerekedjünk felül ezen. Feltétlenül olvassuk el, ha PostScript nyomtatónk van.

- A PostScript számos program közkedvelt kimeneti formátuma, sőt gyakran maguk a felhasználók is szeretnek ilyen programokat írni. Sajnos azonban a PostScript nyomtatók egyáltalán nem olcsók. A PostScript szimulációja nem PostScript nyomtatókon című szakaszban megtudhatjuk, miképp tudjuk úgy módosítani a szűrőt, hogy nem PostScript nyomtatókon is tudjunk PostScript programokkal nyomtatni. Ezt a szakaszt akkor érdemes elolvasni, ha nincs PostScript nyomtatónk.

- A Konverziós szűrők című szakaszban eláruljuk, miként lehetséges automatizálni a különböző állományformátumok és a nyomtatók által érthető formátumok közti konverziókat, legyen az grafikus vagy betűszedésre vonatkozó adat. A szakasz elolvasása során megismerjük, hogyan tudjuk a nyomtatónkat képessé tenni az `lpr `-t`` paranccsal troff adatok, vagy a `lpr `-d`` paranccsal a TeX DVI állományainak, esetleg az `lpr `-v`` paranccsal raszteres képek nyomtatására és így tovább. Csak ajánlani tudjuk ennek elolvasását.

- A Kimeneti szűrők című szakaszban kivesézzük az LPD egyik kevésbé használt lehetőségét is, a kimeneti szűrőket. Hacsak nem fejléclapokat akarunk készíteni (lásd Fejléclapok), akkor ezt a szakaszt nyugodtan kihagyhatjuk.

- Az lpf szövegszűrő szakaszban bemutatásra kerül a FreeBSD-ben alapból megtalálható `lpf` szűrő, amely egy sornyomtatóknál (vagy az így viselkedő lézernyomtatóknál) használható egyszerű szövegszűrő. Ha nyers szövegek nyomtatásánál meg akarjuk oldani a nyomtatási feladatok nyilvántartását, vagy a törlés karakter láttán a nyomtatónk füstölni kezdene, akkor mindenképpen érdemes belemerülnünk az `lpf` titkaiba.

> Megjegyzés: A most következő szkriptek mindegyike megtalálható a `/usr/share/examples/printing` könyvtárban.

### 9.4.1.1. Hogyan működnek a szűrők?

Ahogy már korábban is jeleztük, a szűrő egy olyan végrehajtható program, amelyet az LPD indít el, amikor a nyomtatóval eszközfüggetlen módon kommunikál.

Amikor az LPD egy feladat elvégzése során ki akar nyomtatni egy állományt, akkor elindít egy ilyen szűrőprogramot. A szűrő szabványos bemenetére elküldi a kinyomtatandó állományt, a szabványos kimenetét a nyomtatóra, a szabványos hibajelzéseit pedig egy naplóállományba irányítja (ez utóbbit az `/etc/printcap` állományban az `lf` tulajdonsággal adhatjuk meg, vagy alapértelmezés szerinti a `/dev/console` állományba kerül).

Az LPD a használni kívánt szűrőt és annak paramétereit az `/etc/printcap` állományban felsoroltak vagy az lpr(1) parancssorában megadottak szerint választja ki. Például, ha a felhasználó a `lpr `-t`` parancsot adja ki, akkor az LPD a célként megadott nyomtatónál szereplő `tf` tulajdonság által megadott troff szűrőt kezdi el használni. Amennyiben a felhasználó egyszerűen csak nyers szöveget akar nyomtatni, akkor az `if` szűrőnek kellene elindulnia (ez viszont csak részben igaz: lásd Kimeneti szűrők).

Háromfajta szűrő jelenhet meg az `/etc/printcap` állományban:

- A szövegszűrő (text filter), ami a hagyományos szöveges nyomtatásért felelős, és amit az LPD dokumentációjában érdekes módon bemeneti szűrőnek (input filter) hívnak. Mivel az LPD arra számít, hogy minden nyomtató alapból képes kinyomtatni bármilyen nyers szöveget, ezért a szövegszűrő feladata, hogy a nyomtató számára gondoskodjon a tabulátorok, törlések és más egyéb speciális karakterek megfelelő kezeléséről. Emellett ha olyan helyen vagyunk, ahol szükség van a nyomtatási feladatok nyilvántartására is, a szövegszűrő ennek megoldására is képes, méghozzá úgy, hogy összeszámolja a kinyomtatott sorokat, és elosztja ezeket a nyomtató által oldalanként nyomtatott sorok számával. Egy szövegszűrő a következő paraméterekkel indulhat:

  `szűrőnév` [-c] -w `szélesség` -l `hossz` -i `behúzás` -n `hozzáférés` -h `gépnév` `nyilvántartás`

  ahol a

  `-c`

    akkor jelenik meg, ha egy nyomtatási feladatot az `lpr `-l`` paranccsal adunk át

  `szélesség`

    az `/etc/printcap` állományban definiált `pw` (page width, avagy oldalszélesség) tulajdonság értéke, ami alapbeállítás szerint 132

  `hossz`

    a `pl` (page length, avagy oldalhossz) tulajdonság értéke, amely az alapbeállítás szerint 66

  `behúzás`

    az `lpr `-i`` parancs megadása során használt behúzás mértéke, ami alapból 0

  `hozzáférés`

    a nyomtatást végző felhasználó hozzáférésének megnevezése

  `gépnév`

    a gép neve, amiről a nyomtatási feladat érkezett

  `nyilvántartás`

    ez a nyilvántartást tároló állomány `af` tulajdonsággal definiált neve

- A konverziós szűrők (conversion filter) egy adott állományformátumot hoznak a nyomtató számára értelmes formára. Például ditroff adatok közvetlenül ugyan nem nyomtathatóak, azonban a ditroff állományokhoz tudunk telepíteni egy olyan szűrőt, amely a ditroff adatokat a nyomtató számára is emészthető és nyomtatható formájúvá teszi. A Konverziós szűrők című szakasz tud ezekről többet mondani. Ilyen esetekben kérhetünk nyilvántartást. A konverziós szűrők az alábbi paraméterekkel indulhatnak:

  `szűrőnév` -x `pixelszélesség` -y `pixelmagasság` -n `hozzáférés` -h `gépnév` `nyilvántartás`

  ahol a `pixelszélesség` a `px` tulajdonság értékéből (ami alapból 0), a `pixelmagasság` a `py` tulajdonság értékéből (ami alapból szintén 0) származik.

- A kimeneti szűrő (output filter), ami csak akkor aktív, ha a szövegszűrő nem, vagy ha engedélyeztük fejléclapok nyomtatását. Tapasztalatom szerint az ilyen szűrőket ritkán használják. A Kimeneti szűrők című szakasz mutatja be a működésüket. Ekkor csupán két paraméterünk van:

  `szűrőnév` -w `szélesség` -l `hosszúság`

  amik rendre megegyeznek a szövegszűrők `-w` és `-l` paramétereivel.

A szűrők ki is tudnak lépni a következő kódokkal (exit status):

0

  A szűrő sikeresen kinyomtatta az állományt.

1

  A szűrőnek nem sikerült kinyomtatnia az állományt, azonban szeretné, ha az LPD újból megpróbálkozna vele. Az LPD tehát ebben az esetben újraindítja a szűrőt.

2

  A szűrőnek nem sikerült kinyomtatnia az állományt, és nem is kívánja újra megpróbálni. Ekkor az LPD eldobja az állományt.

A FreeBSD kiadásokban megtalálható `/usr/libexec/lpr/lpf` szövegszűrő képes a kapott szélesség és hossz paraméterekkel megállapítani az oldaltöréseket és a nyomtató használatát nyilvántartani, amihez a hozzáférés, gépnév és nyilvántartás adatait használja fel.

Amikor majd igyekszünk mellé újabb szűrőket beszerezni, ne felejtsük el ellenőrizni, hogy együtt tudnak-e működni az LPD-vel. Ha a válasz igen, akkor a fentebb említett paraméterek mindegyikét ismerniük kell. Az általános használatra készült szűrők készítése során mi magunknak is be kell tartanunk ezeket az elvárásokat.

### 9.4.1.2. Szöveges nyomtatási feladatok PostScript® nyomtatókon

Ha csak egyedül dolgozunk a számítógépen és PostScript (vagy bármilyen más nyelvet ismerő) nyomtatónk van, valamint megígérjük, hogy soha nem küldünk sem mi, sem pedig nem küldetünk semmilyen más programmal nyers szöveget a nyomtatóra, akkor átléphetjük ezt a szakaszt.

Ha viszont egyaránt akarunk küldeni PostScript programot és nyers szöveget tartalmazó nyomtatási feladatot a nyomtatónak, akkor ehhez kénytelenek vagyunk a rendszerünket beállítani. Először is szükségünk van szövegszűrőre, ami megállapítja, hogy a frissen érkezett nyomtatási feladat nyers szöveget vagy PostScript programot tartalmaz-e. Minden PostScript-alapú feladat a `%!` karaktersorozattal kezdődik (a többi esetben olvassuk a nyomtató leírását). Szóval, ha a nyomtatandó állomány első két karaktere ilyen, akkor egy PostScript programmal van dolgunk és közvetlenül továbbküldhetjük a nyomtatási feladatot a nyomtatónak. Minden más esetben a szűrőnek előbb át kell alakítania a szöveget PostScript nyelvre.

Hogyan érhetjük el mindezt?

Ha soros nyomtatónk van, akkor erre a feladatra az `lprps` parancs tökéletes. Az `lprps` egy olyan PostScript szűrő, amely mind a két irányban képes közvetíteni. Folyamatosan rögzíti egy állományba a nyomtató állapotát, így a felhasználók és rendszergazdák pontosan látják a nyomtató jelenlegi állapotát (például “`toner low`” (a toner hamarosan kifogy) vagy “`paper jam`” (a papír beragadt)). Ami viszont sokkal lényegesebb, hogy a `psif` nevű program képes megmondani az érkező nyomtatási feladat valódi típusát, és ennek megfelelően meg tudja hívni nyers szöveg átalakítására a `textps` (egy másik program, amit a `lprps` mellé kapunk) parancsot. Ezután az `lprps` elküldi a feladatot a nyomtatónak.

Az `lprps` a FreeBSD Portgyűjteményének része (lásd A Portgyűjtemény), ezért a használni kívánt papír méretétől függően pillanatok alatt magunk is letölhetjük, fordíthatjuk és telepíthetjük a `print/lprps-a4` és `print/lprps-letter` csomagok valamelyikét. Az `lprps` telepítése után egyszerűen csak adjuk meg a `psif` elérési útvonalát. Ha tehát telepítettük a Portgyűjteményből az `lprps` csomagot, akkor egy soros portra csatlakozó PostScript nyomtató esetén ezt kell beírnunk az `/etc/printcap` állományba:

    :if=/usr/local/libexec/psif:

Ezenkívül még az `rw` tulajdonsággal meg kell mondanunk az LPD-nek, hogy a nyomtatót írásra és olvasásra nyissa meg.

Amennyiben a PostScript nyomtatónk a párhuzamos porton csatlakozik (és amiért a nyomtatónk nem képes az `lprps` által igényelt kétirányú kommunikációra), szövegszűrőként a következő szkriptet fogjuk használni:

    #!/bin/sh
    #
    #  psif - PostScript vagy nyers szöveg nyomtatása PostScript nyomtatón
    #  Ez a szkriptes változat, NEM pedig az lprps-hez mellékelt szűrő
    #  (a /usr/local/libexec/psif állomány)!
    #

    IFS="" read -r first_line
    first_two_chars=`expr "$first_line" : '\(..\)'`

    if [ "$first_two_chars" = "%!" ]; then
        #
        #  PostScript: nyomtassuk ki.
        #
        echo "$first_line" && cat && printf "\004" && exit 0
        exit 2
    else
        #
        #  Nyers szöveg: alakítsuk át, majd nyomtassuk ki.
        #
        ( echo "$first_line"; cat ) | /usr/local/bin/textps && printf "\004" && exit 0
        exit 2
    fi

A fentebb szereplő szkriptben a `textps` programot használjuk a nyers szövegek PostScript programokra alakításához, de helyette bármilyen más konvertáló programot is igénybe vehetünk. A FreeBSD Portgyűjteményében (lásd A Portgyűjtemény) találhatunk erre a célra egy `a2ps` nevű programot is, amit esetleg érdemes lehet közelebbről megnéznünk.

### 9.4.1.3. PostScript szimulációja nem PostScript nyomtatókon

A PostScript a magas színvonalú betűszedés és nyomtatás de facto szabványa. Emellett azonban a PostScript egy költséges szabvány is. Az Aladdin Enterprises-nak hála azonban létezik egy hozzá hasonló szabad szoftver, a Ghostscript, amely képes FreeBSD-n is futni. A Ghostscript képes a legtöbb PostScript állomány olvasására, megjelenítésére mindenféle eszközökön, beleértve a PostScriptet nem ismerő nyomtatókat is. A Ghostscript és egy speciális szövegszűrő telepítésével el tudjuk érni, hogy egy nem PostScript nyomtató valódi PostScript nyomtatóként viselkedjen.

Ha telepíteni szeretnénk, a Ghostscript megtalálható a FreeBSD Portgyűjteményében. Innen tehát magunk is könnyedén le tudjuk tölteni, fordítani és telepíteni.

A PostScript nyomtatás szimulációjához először egy szűrő segítségével észre kell vennünk, hogy egy PostScript formátumú állományt készülünk kinyomtatni. Ha nem ilyen a nyomtatási feladat, akkor egyenesen a nyomtatóra küldjük, azonban minden más esetben először a Ghostscript segítségével átalakítjuk egy olyan formátumba, amit a nyomtató is képes feldolgozni.

Nézzünk erre egy példát: a most következő szövegszűrő a Hewlett Packard DeskJet 500-as nyomtatóihoz használható. Más nyomtató esetén cseréljük ki a `gs` (Ghostscript) parancs `-sDEVICE` paraméterét a neki megfelelőre. (A telepített Ghostscript által ismert nyomtatók listáját a `gs `-h`` paranccsal kérdezhetjük le.)

    #!/bin/sh
    #
    #  ifhp - Ghostscripttel szimulált Postscript nyomtatás DeskJet 500-on
    #  Helye: /usr/local/libexec/ifhp

    #
    #  LF karaktereket CR+LF-ként kezeljük (elkerülve ezzel a HP/PCL
    #  nyomtatókon a "lépcsőzést"):
    #
    printf "\033&k2G" || exit 2

    #
    #  Az állomány első két karakterének beolvasása
    #
    IFS="" read -r first_line
    first_two_chars=`expr "$first_line" : '\(..\)'`

    if [ "$first_two_chars" = "%!" ]; then
        #
        #  Ez PostScript: küldjük át a Ghostscripten és nyomtassuk ki.
        #
        /usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 \
          -sOutputFile=- - && exit 0
    else
        #
        #  Nyers szöveg vagy HP/PCL, ezért küldjük át közvetlenül. Az utolsó
        #  lap kidobásához küldünk még egy lapdobást is.
        #
        echo "$first_line" && cat && printf "\033&l0H" &&
    exit 0
    fi

    exit 2

Befejezésül az `if` tulajdonságon keresztül értesítenünk kell erről a szűrőről az LPD-t is:

    :if=/usr/local/libexec/ifhp:

Készen is vagyunk! Most már nyugodtan beírhatjuk, hogy `lpr ``sima.szöveg``` vagy `lpr ``akármi.ps```, mind a kettőnek ki kell tudnia nyomtatódnia.

### 9.4.1.4. Konverziós szűrők

Miután elvégeztük az Alacsonyszintű nyomtatóbeállítás című szakaszban leírt beállításokat, a (nyers ASCII szöveg mellett) kedvenc állományformátumainkhoz is minden bizonnyal szeretnénk telepíteni néhány konverziós szűrőt.

#### 9.4.1.4.1. Miért használjunk konverziós szűrőket?

A konverziós szűrők segítségével állományok mindenféle formátumait könnyen ki tudjuk nyomtatni. Például tegyük fel, hogy sokat dolgozunk a TeX betűszedő rendszerrel és egy PostScript nyomtatónk van. Minden alkalommal, amikor egy DVI állományt hozunk létre a TeX forrásból, azt közvetlenül még nem tudjuk a nyomtatóra küldeni. Ehhez a következő parancsokat kell kiadnunk:

    % dvips hínár-elemzés.dvi
    % lpr hínár-elemzés.ps

Ha telepítünk egy konverziós szűrőt a DVI állományokhoz, meg tudjuk spórolni ezt a manuális átalakítási lépést azzal, hogy átadjuk ezt a feladatot az LPD-nek. Így ezután mindig, amikor egy DVI állományt akarunk kinyomtatni, csupán egyetlen lépésre lesz szükségünk:

    % lpr -d hínár-elemzés.dvi

Az LPD-nek a `-d` paraméterrel adjuk meg, hogy a nyomtatás előtt hajtsa végre a DVI átalakítását. A Formázási és konverziós beállítások című szakaszban találjuk meg a többi konverziós opciót.

Minden olyan konverziós beállításhoz, amit használni szeretnénk a nyomtatóval, telepítenünk kell egy konverziós szűrőt (conversion filter) és meg kell adnunk a nevét az `/etc/printcap` állományban. A konverziós szűrők az egyszerű nyomtatóbeállításnál szereplő szövegszűrőkhöz hasonlítanak (lásd A szövegszűrő telepítése szakasz) azzal a kivétellel, hogy a nyers szövegek kinyomtatása helyett ezek a szűrők a nyomtató számára értelmes formátumra alakítják az állományokat.

#### 9.4.1.4.2. Milyen konverziós szűrőket érdemes telepíteni?

Olyan konverziós szűrőket telepítsünk, amelyekre gyakran szükségünk lehet. Ha például sok DVI adatot szeretnénk nyomtatni a jövőben, akkor használjunk DVI konverziós szűrőt, vagy ha sok troff formátumú adatot nyomtatunk, akkor minden bizonnyal jól fog jönni egy troff szűrő.

A következő táblázat foglalja össze azokat a szűrőket, amelyekkel az LPD képes együttműködni. Megtudhatjuk, hogy az `/etc/printcap` állományban melyik tulajdonság tartozik hozzájuk és hogyan hívjuk meg ezeket az `lpr` paranccsal:

Állománytípus | Tulajdonság az `/etc/printcap` állományban | Az `lpr` kapcsolója
--- | --- | ---
cifplot | `cf` | `-c`
DVI | `df` | `-d`
plot | `gf` | `-g`
ditroff | `nf` | `-n`
FORTRAN forrás | `rf` | `-f`
troff | `tf` | `-f`
raster | `vf` | `-v`
nyers szöveg | `if` | nincs, `-p`, vagy `-l`

A példánkban tehát a `lpr `-d`` parancs használata arra utal, hogy a nyomtatónak az `/etc/printcap` állományból a `df` tulajdonságára van szüksége.

Minden hadakozás ellenére állíthatjuk, hogy a FORTRAN források és a plot által használt szövegek formátuma napjainkra már elavultnak tekinthető. Ezért ezekhez az opciókhoz a saját szűrőinkkel tetszőleges formázási lehetőségeket rendelhetünk. Például, ha Printerleaf (az Interleaf asztali kiadványszerkesztő formátuma) állományokat szeretnénk közvetlenül nyomtatni, akkor valószínűleg nem lesz szükségünk plot állományokra. Ezért a `gf` tulajdonságnak megadhatunk egy Printerleaf konverziós szűrőt, amelyen keresztül aztán a felhasználók az `lpr `-g`` paranccsal Printerleaf állományokat tudnak nyomtatni.

#### 9.4.1.4.3. Konverziós szűrők telepítése

Mivel a konverziós szűrők az alap FreeBSD rendszeren kívülre kerülnek, ezért ezeket minden valószínűség szerint valahol a `/usr/local` könyvtárban találjuk meg. Ezen belül is általában a `/usr/local/libexec` könyvtárban fordulnak elő, mivel ezeket csak az LPD futtatja, senki másnak nincs rájuk szüksége.

A konverziós szűrők aktiválásához az `/etc/printcap` állományban egyszerűen adjuk meg az alkalmas tulajdonságoknak megfelelő szűrők elérési útvonalait.

A példánkban most felveszünk egy DVI konverziós szűrőt a `bamboo` nevű nyomtatóhoz. Itt ismét láthatjuk a korábban használt `/etc/printcap` állományt, ahol most azonban a `bamboo` nevű nyomtatónál hozzáadtunk egy `df` tulajdonságot:

    #
    #  /etc/printcap (rose) -  egy df szűrő hozzáadása a bamboo
    #  nevű nyomtatóhoz
    #
    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:ms#-parenb cs8 clocal crtscts:rw:\
            :if=/usr/local/libexec/psif:\
            :df=/usr/local/libexec/psdf:

A DVI szűrő ebben az esetben a `/usr/local/libexec/psdf` néven elérhető aprócska szkript. Ezt találhatjuk benne:

    #!/bin/sh
    #
    #  psdf - DVI szűrő PostScript nyomtatóhoz
    #  Helye: /usr/local/libexec/psdf
    #
    # Az lpr -d parancs hatására hívódik meg
    #
    exec /usr/local/bin/dvips -f | /usr/local/libexec/lprps "$@"

A szkript a `dvips` parancsot szűrőként futtatja (az `-f` paraméterrel) a szabványos bemenetről, ahova a nyomtatási feladatot is kapja. Ezután elindítja az `lprps` PostScript szűrőt (lásd a Szöveges nyomtatási feladatok PostScript nyomtatókon című szakaszt) az LPD által átadott paraméterekkel. Az `lprps` parancs ezekkel a paraméterekkel tartja nyilván az így kinyomtatott lapokat.

#### 9.4.1.4.4. További példák konverziós szűrőkre

A konverziós szűrők telepítésének nincs bevált receptje, ezért ebben a szakaszban bemutatunk rájuk néhány működő illusztrációt. Ezeket tudjuk felhasználni saját szűrők elkészítésére. Vagy ha megtehetjük, használjuk közvetlenül ezeket.

Ebben a példa szkriptben Hewlett Packard LaserJet III-Si nyomtatókhoz hozunk létre raszteres (pontosabban GIF formátumú) konverziós szűrőt:

    #!/bin/sh
    #
    #  hpvf - GIF állományokat konvertál át HP/PCL-be, majd kinyomtatja
    #  Helye: /usr/local/libexec/hpvf

    PATH=/usr/X11R6/bin:$PATH; export PATH
    giftopnm | ppmtopgm | pgmtopbm | pbmtolj -resolution 300 \
        && exit 0 \
        || exit 2

Úgy működik, hogy a GIF állományt először PNM (portable anymap), utána PGM (portable graymap), majd PBM (portable bitmap) formátumúra alakítja, amiből végül LaserJet/PCL-kompatibilis adat lesz.

Ez lesz a hozzá tartozó `/etc/printcap` állomány:

    #
    #  /etc/printcap (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:

A most következő szkript a groff betűszedű rendszerből érkező troff adatokat alakítja át a `bamboo` nevű PostScript nyomtató számára:

    #!/bin/sh
    #
    #  pstf - a groff troff adait alakítja PS-re, majd kinyomtatja
    #  Helye: /usr/local/libexec/pstf
    #
    exec grops | /usr/local/libexec/lprps "$@"

A szkript az `lprps` parancs segítségével kommunikál a nyomtatóval. Ha a nyomtatónk párhuzamos porton csatlakozik, akkor helyette ezt a szkriptet használjuk:

    #!/bin/sh
    #
    #  pstf - a groff troff adatait alakítja PS-re, majd kinyomtatja
    #  Helye: /usr/local/libexec/pstf
    #
    exec grops

Kész is! A szűrő életrekeltéséhez mindössze ennyit kell beillesztenünk az `/etc/printcap` állományba:

    :tf=/usr/local/libexec/pstf:

Most pedig jöjjön a FORTRAN szerelmeseinek szívét megmelengető szkript. Ez egy olyan szövegszűrő, amely bármelyik nyers szöveget közvetlenül kezelni tudó nyomtató esetén működik. A `teak` nevű nyomtatóhoz helyezzük be:

    #!/bin/sh
    #
    # hprf - FORTRAN szövegszűrő LaserJet 3si-hez
    # Helye: /usr/local/libexec/hprf
    #

    printf "\033&k2G" && fpr && printf "\033&l0H" &&
     exit 0
    exit 2

Az `/etc/printcap` állományban a `teak` nyomtatóhoz a következő sor beírásával tudjuk engedélyezni ezt a szűrőt:

    :rf=/usr/local/libexec/hprf:

Most pedig következzen egy utolsó, de az eddigieknél valamivel összetettebb példa. Ebben a korábban bemutatott `teak` nevű LaserJet nyomtatóhoz fogunk hozzáadni egy DVI szűrőt. Először is következzen a művelet egyszerűbb része: bővítsük ki az `/etc/printcap` állományt a DVI szűrő helyének megadásával:

    :df=/usr/local/libexec/hpdf:

Ezután következzék a nehezebb rész: a szűrő elkészítése. Ehhez szükségünk lesz egy DVI-ről LaserJet/PCL-re alakító programra. A FreeBSD Portgyűjteményében (lásd A Portgyűjtemény) találunk is egyet: a csomag neve `print/dvi2xx`. A csomag telepítésével megkapjunk a nekünk kellő `dvilj2p` programot, ami képes DVI-t LaserJet IIp, LaserJet III és a LaserJet 2000 típusok által ismert kódokra fordítani.

A `dvilj2p` felhasználásától függetlenül a `hpdf` néven létrehozni kívánt szűrőnk még így is bonyolult lesz, hiszen a `dvilj2p` nem tud olvasni a szabványos bemenetről, hanem mindenáron egy állománnyal akar dolgozni. Sőt, olyan állománnyal, amelynek `.dvi` kiterjesztése van, ezért még a `/dev/fd/0` (vagyis a szabványos bemenethez tartozó eszközleíró) használata is akadályokba ütközik.

Üröm még az örömünkben, hogy a `/tmp` könyvtárat sem tudjuk felhasználni ideiglenes link létrehozására: a szimbolikus linkeket a `bin` felhasználó és csoport birtokolja, a szűrőt pedig a `daemon` felhasználó futtatja. A `/tmp` könyvtárban rááadásul csak a tulajdonosaik képesek állományokat átnevezni vagy törölni (sticky bit). Ezért a szűrő ugyan létre tudna hozni egy linket, azonban ezt a feladata végeztével nem lesz majd képes törölni, mivel a link egy másik felhasználóhoz tartozik.

Ezért a szűrő az aktuális könyvtárban fogja létrehozni ezt a szimbolikus linket, ami jelen esetünkben a nyomtatási rendszer által használt könyvtár lesz (ezt az `/etc/printcap` állomány `sd` tulajdonságával adjuk meg). Itt remekül el tudják végezni a feladataikat a szűrők, különösen mivel (néha) több hely van itt, mint a `/tmp` könyvtárban.

Végül lássuk magát a szűrőt:

    #!/bin/sh
    #
    #  hpdf - DVI adat nyomtatása HP/PCL nyomtatón
    #  Helye: /usr/local/libexec/hpdf

    PATH=/usr/local/bin:$PATH; export PATH

    #
    #  Létrehozunk egy függvényt az átmeneti állományok törlésére. Ezek
    #  az aktuális könyvtárban jönnek létre, ami pedig a nyomtatási
    #  rendszer adott nyomtatóhoz tartozó könyvtára lesz.
    #
    cleanup() {
       rm -f hpdf$$.dvi
    }

    #
    #  Létrehozunk egy függvényt a súlyos hibák kezelésére: írassunk ki
    #  egy adott üzenetet és lépjünk ki a 2-es hibakóddal.  Ezzel üzenünk
    #  az LPD-nek, hogy ne hajtsa végre újra a nyomtatási feladatot.
    #
    fatal() {
        echo "$@" 1>&2
        cleanup
        exit 2
    }

    #
    #  Ha a felhasználó eltávolítja a nyomtatási feladatot a sorból, akkor az
    #  LPD egy SIGINT jelzést fog küldeni, ezért próbáljuk meg azt elkapni
    #  (néhány más egyéb jelzéssel együtt), így még tudjuk törölni az
    #  ideiglenesen # létrehozott állományokat.
    #
    trap cleanup 1 2 15

    #
    #  Gondoskodjunk róla, hogy a feladat megkezdésekor még egyetlen
    #  használt állomány sem létezik.
    #
    cleanup

    #
    #  Kössük össze a szabványos bemenetet egy DVI állománnyal (amit
    #  majd nyomtatni akarunk).
    #
    ln -s /dev/fd/0 hpdf$$.dvi || fatal "Cannot symlink /dev/fd/0"

    #
    #  LF = CR+LF
    #
    printf "\033&k2G" || fatal "Cannot initialize printer"

    #
    #  Alakítsuk át az adatot és nyomtassunk. A dvilj2p által visszaadott érték
    #  nem túlságosan megbízható, ezért ne is foglalkozzunk vele.
    #
    dvilj2p -M1 -q -e- dfhp$$.dvi

    #
    #  Takarítsunk el magunk után és lépjünk ki szabályosan
    #
    cleanup
    exit 0

#### 9.4.1.4.5. Automatikus konverziók: a konverziós szűrők helyett

A konverziós szűrők sokat segítenek egy kényelmes nyomtatási környezet kialakításában, azonban a használatukhoz a felhasználóknak (az lpr(1) parancson keresztül) egyenként hivatkozniuk kell rájuk. Ha a rendszerünk felhasználói nem eléggé műveltek számítástechnikai téren, akkor még egy szűrő megadása is zavaró lehet számukra. Ami még ennél is rosszabb, hogy egy rosszul megadott szűrő hatására a nyomtató sem fogja jól kezelni az adott állomány formátumát és erre válaszul akár többszáz lapot is pillanatok alatt kiköphet magából.

A konverziós szűrők telepítése helyett gyakran csak egy (alapértelmezett) szövegszűrőre van szükségünk, amely kideríti a nyomtatandó állomány pontos formátumát és magától elindítja a neki megfelelő konverziós szűrőt. Ilyen esetekben például a `file` parancs pont a hasznunkra válhat. Persze bizonyos állománytípusok közt nagyon nehéz különbséget tenni -- de ezekre továbbra is adhatunk még külön konverziós szűrőket.

A FreeBSD Portgyűjteményében találhatunk egy `apsfilter` elnevezésű szövegszűrőt (`print/apsfilter`), ami képes ilyen automatikus konverzióra. Képes felismerni a nyers szöveget, PostScript programokat, DVI és szinte bármilyen formátumú állományokat, lefuttatni rájuk a megfelelő átalakításokat, majd kinyomtatni ezeket.

### 9.4.1.5. Kimeneti szűrők

Az LPD nyomtatási rendszer kezel egy eddig még nem tárgyalt szűrőtípust is: ez a kimeneti szűrő. A kimeneti szűrő a szövegszűrőhöz hasonlóan csak nyers szöveg nyomtatására használatos, de tartalmaz néhány egyszerűsítést. Ha kizárólag csak kimeneti szűrőket alkalmazunk, akkor:

- Az LPD az egész nyomtatási feladathoz egyetlen kimeneti szűrőt fog használni, nem pedig minden állományhoz külön.

- Az LPD a kimeneti szűrő számára nem nyújt semmilyen segítséget a nyomtatási feladaton belül szereplő állományok kezdetének vagy végének megállapításában.

- Az LPD a szűrőnek nem adja át sem a felhasználó hozzáférését, sem pedig gépnevét, ezért nyilvántartásra nem alkalmas. Mindent összegezve lényegében csak két paramétert kap meg:

  `szűrőnév` -w`szélesség` -l`hossz`

  ahol a `szélesség` a kérdéses nyomtató `pw` tulajdonságából, a `hossz` pedig a `pl` tulajdonságából származik.

Ne bűvöljön el minket a szűrő egyszerűsége! Ha például a nyomtatási feladatban minden állományt újabb lapon szeretnénk kezdeni, akkor azt kimeneti szűrővel nem tudjuk megoldani. Erre a célra használjunk szövegszűrőt (másik nevén bemeneti szűrőt), lásd A szövegszűrő telepítése szakaszt. Továbbá, a kimeneti szűrő valójában sokkal bonyolultabb abban a tekintetben, hogy a beérkező adatok közül neki kell kikeresnie a speciális jelentéssel bíró karaktereket ugyanúgy, ahogy az LPD helyett saját magának kell küldenie a jelzéseket.

Azonban a kimeneti szűrők használata elkerülhetetlen, ha például fejléclapokat akarunk nyomtatni, és esetleg még különböző inicializálásra használatos speciális kódokat vagy karakterláncokat akarunk ez előtt kiküldeni. (Ellenben badarság a fejléclapoktól követelni a felhasználó adatait, hiszen az LPD a kimeneti szűrőnek nem ad semmilyen erre vonatkozó információt.)

Egyetlen nyomtató esetén az LPD egyaránt lehetővé teszi kimeneti, szöveg- és más egyéb szűrők használatát. Ilyenkor az LPD a kimeneti szűrőn keresztül csak a fejlécet tartalmazó oldal (lásd a Fejléclapok szakaszt) nyomtatását indítja el. Ezt követően az LPD arra számít, hogy a kimeneti szűrő két karakter, az ASCII 031 és az ezt követő ASCII 001, hatására leállítja magát. Amikor tehát a kimeneti szűrő érzékeli ezt a két karaktert (031, 001), akkor a `SIGSTOP` jelzéssel le kell állnia. Miután az LPD lefuttatta a többi szűrőt, a `SIGCONT` jelzéssel újraindítja a kimeneti szűrőt.

Ha van kimeneti szűrőnk, de nincs szövegszűrőnk, akkor az LPD minden további feldolgozás nélkül továbbadja a nyomtatási feladatot a kimeneti szűrőnek. Ahogy már korábban is említettük, a kimeneti szűrő a nyomtatási feladatban levő összes állományt egymás után nyomtatja ki, lapdobások vagy bármilyen más papírmozgatás nélkül, ezért valószínűleg nem ez kell nekünk. Az esetek túlnyomó részében ehhez elég egy szövegszűrő.

A korábban szövegszűrőként beharangozott `lpf` program kimeneti szűrőként is képes funkcionálni. Ha szükségünk lenne egy gyorsan összecsapható kimeneti szűrőre, és nem akarunk a speciális karakterek, valamint a jelzések küldésével elidőzni, akkor próbálkozzunk az `lpf` használatával. Az `lpf` parancsot mellesleg becsomagolhatjuk egy olyan szkriptbe is, amely elvégzi a nyomtató számára szükséges inicializálást.

### 9.4.1.6. Az `lpf` szövegszűrő

A FreeBSD bináris terjesztéséhez mellékelt `/usr/libexec/lpr/lpf` program egy szövegszűrő (bemeneti szűrő), amely képes (az `lpr `-i`` paranccsal hozzáadott nyomtatási feladatokat) tabulálni, (az `lpr `-l`` paranccsal felvett nyomtatási feladatokban) a vezérlőkaraktereket figyelemen kívül hagyni, a nyomtatási feladatban előforduló törlések és behúzások nyomtatási pozícióját igazítani és nyilvántartani a kinyomtatott lapokat. Kimeneti szűrőként is tud viselkedni.

Az `lpf` szűrő rengeteg nyomtatási környezetben felhasználható. Habár nem képes a nyomtatónak inicializáló jelsorozatokat küldeni, mégis könnyű olyan szkriptet írni, amely elvégzi ezeket a hiányzó kezdeti beállításokat, majd lefuttatja az `lpf` szűrőt.

Az `lpf` akkor lesz képes helyesen számolni a kinyomtatott lapokat, ha ehhez az `/etc/printcap` állományban jól töltjük ki a `pw` és `pl` tulajdonságokat. Ezen értékek segítségével határozható meg ugyanis, hogy mennyi szöveg fért rá egy lapra és így mennyi lapot emésztett fel az adott felhasználó által küldött nyomtatási feladat. A nyomtatás nyilvántartásával kapcsolatban A nyomtató használatának nyilvántartása című szakaszt érdemes elolvasni.

## 9.4.2. Fejléclapok

Ha nagyon sok felhasználónk van, és sok különböző nyomtatót is használnak, akkor előbb vagy utóbb minden bizonnyal elkerülhetetlenné fog válni a fejléclapok használata.

A fejléc-, vagy más néven munka- vagy elválasztó lapok segítik elő az elvégzett nyomtatási feladatok azonosítását. A többi dokumentumtól eltérő módon, általában dekoratív keretben, nagy, vastag betűkkel nyomtatódnak ki, hogy a halomnyi papír között a felhasználók könnyedén megtalálhassák az elküldött nyomtatási feladataik eredményét. Természetesen a fejléclapok nyilvánvaló hátulütője, hogy így minden nyomtatási feladathoz még egy lappal többet kell elhasználni és mivel gyakorlatilag néhány percnél tovább nincs is rájuk szükség, meglehetősen hamar a kukába kerülnek. (A fejléclapok nyomtatási feladatonként jönnek létre, nem pedig a nyomtatási feladatokban levő állományokhoz egyenként, ezért nem is akkora pazarlás ez.)

Az LPD rendszer képes magától fejléclapokat készíteni a nyomtatásokhoz, amennyiben a nyomtatónk képes közvetlenül nyers szöveget nyomtatni. Ha PostScript nyomtatónk van, akkor ennek legyártásához egy külső programra van szükségünk, lásd a Fejléclapok PostScript nyomtatókon szakaszt.

### 9.4.2.1. A fejléclapok engedélyezése

Az Alacsonyszintű nyomtatóbeállítás című szakaszban az `/etc/printcap` állományban a `sh` (úgy mint “suppress header”) tulajdonsággal kikapcsoltuk a fejléclapokat. A fejléclapok engedélyezéséhez mindössze el kell távolítanunk ezt az `sh` tulajdonságot.

Ez túl egyszerű, nemde?

Igen, ez így van. Előfordulhat, hogy szükségünk van még egy olyan kimeneti szűrőre is, amely inicializáló karaktereket küld a nyomtatónak. Íme egy példa ehhez a Hewlett Packard PCL-kompatibilis nyomtatói esetére:

    #!/bin/sh
    #
    #  hpof - Kimeneti szűrő Hewlett Packard PCL-kompatibilis nyomtatókhoz
    #  Helye: /usr/local/libexec/hpof

    printf "\033&k2G" || exit 2
    exec /usr/libexec/lpr/lpf

Az `of` tulajdonsággal adjuk meg a kimeneti szűrőt. A Kimeneti szűrők szakaszban erről részletesebben is olvashatunk.

A korábban ismertetett `teak` nevű nyomtatóhoz most az alábbi minta `/etc/printcap` állományt mellékeljük. Itt engedélyeztük a fejléclapokat és hozzátettük az iménti kimeneti szűrőt:

    #
    #  /etc/printcap (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:

Mostantól kezdve, amikor a felhasználók a `teak` nyomtatón akarnak nyomtatni, minden nyomtatási feladathoz kapni fognak egy fejléclapot. Amennyiben a kedves felhasználók mégis keresgetni akarják a nyomtatásaikat, az `lpr `-h`` paranccsal tetszőleges módon letilthatják azokat. Az lpr(1) többi hasonló opcióját A fejléclapokhoz tartozó beállítások szakaszban találjuk.

> Megjegyzés: Az LPD minden fejléclap után egy lapdobást küld. Ha erre a célra a nyomtatónk egy eltérő karaktert vagy karaktersorozatot használ, akkor azt az `/etc/printcap` állomány `ff` tulajdonságával határozhatjuk meg.

### 9.4.2.2. A fejléclapok vezérlése

A fejléclapok engedélyezésével az LPD egy ún. hosszú fejlécet fog készíteni, vagyis a felhasználót, a gépet és a nyomtatási feladatot jól azonosító, egész lapot kitöltő óriási betűket. Erre egy példa (amiben a `rose` nevű gépről `kelly` küldte az “outline” elnevezésű nyomtatási feladatot):

          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

Ezt követően az LPD elküld még egy lapdobást is, ezért maga a nyomtatási feladat eredménye egy új oldalon fog kezdődni (kivéve, ha az `/etc/printcap` állományban az adott nyomtatóhoz tartozó bejegyzésben megadtuk az `sf` (úgy mint “suppress form feeds”, vagyis a lapdobások letiltása) tulajdonságot.

Ha úgy jobban tetszik, akkor az `/etc/printcap` állományban a `sb` tulajdonsággal az LPD utasítható rövid fejlécek készítésére is. Ilyenkor a fejléclap tartalma mindössze ennyi lesz:

    rose:kelly  Job: outline  Date: Sun Sep 17 11:07:51 1995

Alapértelmezés szerint az LPD először a fejléclapot, majd a nyomtatási feladatot végzi el. Ezt a sorrendet az `/etc/printcap` állományban a `hl` (header last) tulajdonsággal meg tudjuk fordítani.

### 9.4.2.3. A nyomtató használatának nyilvántartása

Az LPD által felkínált fejléclapok használata során egyetlen irányelv érvényesül a nyilvántartásukban: a fejléclapok költségmentesek.

De miért?

Azért, mert kizárólag csak a kimeneti szűrő képes a fejléclapok viselkedését irányítani, ami viszont nem képes semmiféle nyilvántartásra, hiszen nem kapja meg az ehhez szükséges felhasználói- vagy gépnév információkat, illetve nyilvántartásokat. Emiatt fogalma sincs róla, hogy kit terhel az adott nyomtató használata. Úgy sem tudjuk megoldani a problémát, ha a szöveg- vagy konverziós szűrőkben (ahol már rendelkezésünkre állnak a felhasználó és a gépének adatai) “növeljük a lapok számát eggyel” a nyomtatási feladatban, mivel a felhasználók az `lpr `-h`` parancs használatával kedvük szerint letilthatják a fejléclapokat. Ezt ugyan alapvetően a természetet óvni kívánó felhasználók részesítik előnyben, de ettől függetlenül sem erőszakolhatjuk rá mindenkire.

Az sem elég, ha minden szűrő létrehozza a saját fejlécét (amiért aztán pénzt kérhetnénk). Mivel ha a felhasználók az `lpr `-h`` paranccsal le akarják tiltani a fejlécek használatát, attól a szűrőkhöz még mindig létrejönnek, hiszen az LPD a `-h` opcióról semmilyen értesítést nem küld át a szűrőknek.

Nos, ilyenkor mitévők legyünk?

A lehetőségeink:

- Elfogadjuk az LPD elvét, és nem számítunk fel költséget a fejléclapokra.

- Az LPD helyett egy másik nyomtatási rendszert használunk, például az LPRng rendszert. A Más nyomtatási rendszerek című szakaszban kiderül, milyen alternatívák érhetőek el az LPD kiváltására.

- Írjunk mi magunk egy intelligens kimeneti szűrőt. Normális esetben a kimeneti szűrők nem valók másra, csupán a nyomtató alaphelyzetbe hozására vagy egyszerűbb karakterkonverziók elvégzésére. Fejléclapokhoz és nyers szöveget tartalmazó nyomtatási feladathoz remekül használható (ahol nincs szöveg- (avagy bemeneti) szűrő). Azonban ha a nyers szövegekhez van szövegszűrőnk, akkor az LPD a kimeneti szűrőt csak a fejléclapokhoz indítja el. Emellett a kimeneti szűrő az LPD által generált fejléc szövegéből képes megmondani, melyik felhasználóhoz és géphez tartozik a szóbanforgó fejléc. A módszer egyetlen bökkenője, hogy a nyilvántartásokat tároló állományról viszont még így se tudunk semmilyen információt szerezni (mivel nem kapjuk meg az `af` tulajdonsággal beállított állomány nevét). Ha azonban egy rendszerszinten elérhető állományba mentjük ezeket az adatokat, akkor akár bele is drótozhatjuk ezt a kimeneti szűrőbe. A kimeneti szűrőnek az adatok megtalálásában ilyenkor úgy tudunk segíteni, ha az `/etc/printcap` állományban az `sh` (rövid fejléc) tulajdonságot állítjuk be. De ez igazából sok hűhó semmiért, és a felhasználók is jobban megbecsülik az olyan nagylelkű rendszergazdát, aki nem számítja fel nekik a fejléclapokat.

### 9.4.2.4. Fejléclapok PostScript nyomtatókon

Ahogy arról már korábban is szó esett, az LPD képes többféle nyomtató számára is megfelelő, nyers szövegű fejléclapokat készíteni. Persze a PostScript közvetlenül nem képes nyers szövegek nyomtatására, ezért az LPD ezen lehetősége lényegében használhatatlan -- többnyire.

Ilyen helyzetben a fejléclapok használatának nyilvánvaló módja, hogy minden szövegszűrőt fejlécek gyártására utasítunk. Ezek a szűrők a felhasználóról és a gépéről kapott információkból össze tudják állítani a megfelelő fejléclapot. A megoldás hátránya, hogy ez még olyankor is megtörténik, amikor a felhasználók az `lpr `-h`` paranccsal küldik a nyomtatási feladataikat.

Kísérletezzünk egy kicsit ezzel a módszerrel! A most következő szkript három paramétert fogad el (a felhasználó hozzáférést, a gép és a nyomtatási feladat nevét), majd ezekből létrehoz egy egyszerű PostScript formátumú fejlécet:

    #!/bin/sh
    #
    #  make-ps-header - PostScript fejléc létrehozása a szabvány kimenetre
    #  Helye: /usr/local/libexec/make-ps-header
    #

    #
    #  Ezek itt a PostScript által használt egységekben vannak megadva
    #  (72/col vagy 28/cm).  Írjuk át az általunk használt papírméretre,
    #  A4-re vagy amit éppen használunk:
    #
    page_width=612
    page_height=792
    border=72

    #
    #  A paraméterek ellenőrzése.
    #
    if [ $# -ne 3 ]; then
        echo "Usage: `basename $0` <user> <host> <job>" 1>&2
        exit 1
    fi

    #
    #  Mentsük el ezeket, leginkább az olvashatóság miatt.
    #
    user=$1
    host=$2
    job=$3
    date=`date`

    #
    #  Küldjük el a PostScript-kódot a szabványos kimenetre.
    #
    exec cat <<EOF
    %!PS

    %
    %  Gondoskodjunk róla, hogy ne zavarjuk az utánunk következő
    %  felhasználó nyomtatási feladatának végrehajtását.
    %
    save

    %
    %  Csináljunk egy csúf vastag szegélyt, körbe a papíron.
    %
    $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

    %
    %  Jelenítsük meg a felhasználó azonosítóját szép, feltűnő
    %  betűkkel.
    %
    /Helvetica-Bold findfont 64 scalefont setfont
    $page_width ($user) stringwidth pop sub 2 div $page_height 200 sub moveto
    ($user) show

    %
    %  Most pedig mutassuk az unalmas részleteket.
    %
    /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

    %
    % Ennyi lett volna.
    %
    restore
    showpage
    EOF

Ezzel a szkripttel pedig mindegyik konverziós és szövegszűrő először létrehoz egy fejléclapot, majd elvégzi a felhasználó nyomtatási feladatát. Íme egy korábban már bemutatott DVI szűrő, amit most kiegészítünk a fejléclapok használatával:

    #!/bin/sh
    #
    #  psdf - DVI szűrő PostScript nyomtatóhoz
    #  Helye: /usr/local/libexec/psdf
    #
    #  Az lpr -d parancs hatására hívódik meg.
    #

    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

Láthatjuk, hogy a szűrőnek a felhasználói- és a gépnév megállapításához végig kell néznie a paraméterek listáját. Ez lényegében minden más konverziós szűrőnél ugyanígy néz ki. Ez a lista azonban a szövegszűrők esetén némileg eltér (lásd a Hogyan működnek a szűrők? szakaszt).

Már az előbbiekben is tárgyaltuk, hogy ez a megoldás, habár eléggé egyszerű, az `lpr` számára nem teszi lehetővé a fejléclapok letiltását (a `-h` opció). Ha a felhasználóink kímélni akarják a fákat (vagy meg akarják úszni a fejléclapok égbeszökő költségeit), akkor ezt nem tudják megtenni, hiszen a szűrők minden nyomtatási feladathoz készíteni fognak fejléceket.

Ezt a korlátozást csak úgy tudjuk elsöpörni, ha bevetjük a A nyomtató használatának nyilvántartása szakaszban leírt cselt, tehát készítünk egy olyan kimeneti szűrőt, amely megkeresi az LPD-vel generált fejléceket és létrehozza azok PostScript változatát. Ha valaki az `lpr `-h`` paranccsal küld nyomtatnivalót, akkor LPD nem készít hozzá fejléclapot, ahogy a kimeneti szűrőnk sem. A kimeneti szűrő minden más esetben beolvassa az LPD által küldött szöveget és átküldi a neki megfelelő PostScript kódot a nyomtatóra.

Ha soros PostScript nyomtatónk van, akkor használhatjuk a `psof` kimeneti szűrőhöz tartozó `lprps` parancsot is, ami pontosan az előbbit végzi el. Hozzátennénk azonban, hogy a `psof` nem számolja a fejléclapokat.

## 9.4.3. Hálózati nyomtatás

A FreeBSD tud hálozaton is nyomtatni, vagyis tud távoli számítógépeknek is nyomtatási feladatot küldeni. A hálózati nyomtatás kifejezés általánosságban véve két különböző dologra utalhat:

- Egy távoli számítógéphez kapcsolt nyomtató hozzáférését. A géphez a nyomtató a hagyományos soros vagy párhuzamos csatolófelületen keresztül kapcsolódik, amit aztán az LPD alkalmas beállításával a hálózaton mindenki számára elérhetővé teszünk. A Távoli számítógépekre csatlakoztatott nyomtatók című szakasz erről szól.

- Egy közvetlenül a hálózatra kapcsolt nyomtató hozzáférését. A nyomtató tehát rendelkezik még egy hálózati csatlakozással is a hagyományos soros vagy párhuzamos felület mellett (vagy éppen helyett). Egy ilyen nyomtató a következőképpen működhet:

  - Elfogadja az LPD kéréseit, és még képes nyomtatási feladatokat is tárolni. Ebben az esetben teljesen egyenértékű egy LPD alkalmazást futtató számítógéppel. Ekkor nincs más teendőnk, csak követnünk kell a Távoli számítógépeken telepített nyomtatók című szakasz utasításait.

  - Hálózati adatfolyamokkal dolgozik. Ebben az esetben a nyomtatót “hozzá kell kapcsolnunk” a hálózaton található egyik számítógéphez, ami majd a nyomtatási feladatok tárolásáért és folyamatos küldéséért lesz felelős. A Nyomtatók hálózati adatcsatlakozással szakasz az ilyen fajtájú nyomtatók telepítésére tesz néhány javaslatot.

### 9.4.3.1. Távoli számítógépekre csatlakoztatott nyomtatók

Az LPD nyomtatási rendszer alapból képes más, szintén LPD-t (vagy vele kompatibilis rendszert) futtató számítógépekre nyomtatási feladatokat küldeni. Ezzel lényegében az egyik géphez hozzá tudunk kapcsolni egy nyomtatót, amit aztán a többiek számára elérhetővé teszünk. Ez olyan nyomtatók esetében is működik, amelyek ismerik az LPD által alkalmazott protokollt.

A távoli nyomtatáshoz először telepítsük a nyomtatót valamelyik számítógépre az Alacsonyszintű nyomtatóbeállítás szakaszban leírtak szerint, és ezzel az lesz a nyomtatószerverünk. Ezután, amennyiben szükségesnek találjuk, végezzünk magasabb szintű nyomtatóbeállításokat is. Ne felejtsük el kipróbálni a nyomtatón, hogy rendesen működik az LPD mindegyik olyan beállításával, amit engedélyeztünk. Emellett gondoskodjunk minden olyan jogosultságról is, amivel a helyi számítógépről el tudjuk érni a távoli számítógép által felkínált LPD szolgáltatást (lásd Távoli számítógépekről érkező kérések szabályozása).

Ha olyan nyomtatót használunk, aminek a hálózati felülete kompatibilis az LPD rendszerrel, akkor az előbb említett nyomtatószerver lényegében maga lesz a nyomtató, valamint a nyomtató neve a rajta beállított név. Ezzel kapcsolatban olvassuk el a nyomtatóhoz és/vagy a hálózati csatolójához mellékelt dokumentációt.

> Tipp: Amikor a Hewlett Packard Laserjet típusú nyomtatóit használjuk, a `text` nevű nyomtatónév magától elvégzi a LF és CRLF formátumú sortörések közti átalakítást, ezért ilyenkor nincs szükségünk a `hpif` szkriptre.

Ezután ha szeretnénk más gépek részére is elérhetővé tenni a frissen telepített nyomtatónkat, adjuk meg mindegyikük `/etc/printcap` állományában a következőket:

1. Tetszőlegesen választott nevet, álneveket. Az egyszerűség kedvéért azonban itt érdemes ugyanazokat a neveket választani, mint amit a nyomtatószerveren is használunk.

2. Szándékosan hagyjuk az `lp` tulajdonságot üresen (`:lp=:`).

3. Hozzunk létre egy nyomtatási könyvtárat, és jelöljük meg a helyét az `sd` tulajdonsággal. Az LPD itt fogja összegyűjteni a nyomtatási feladatokat, mielőtt elküldené azokat a nyomtatószervernek.

4. Adjuk meg a nyomtatószerver nevét az `rm` tulajdonság segítségével.

5. Az `rp` tulajdonsággal adjuk meg a nyomtatószerverre csatlakoztatott nyomtató nevét.

Kész! Az `/etc/printcap` állományban már nem kell megadni konverziós szűrőket, oldalbeállításokat és semmi más egyebet.

Lássunk mindezekre egy példát. A `rose` nevű számítógéphez két nyomtató csatlakozik, a `bamboo` és a `rattan`. Most pedig beállítjuk, hogy az `orchid` nevű gép felhasználói képesek legyenek ezekkel a nyomtatókkal dolgozni. Ekkor a most következők szerint fog kinézni az `orchid` (a Fejléclapok engedélyezése szakaszban bemutatott) `/etc/printcap` állománya. Tartalmazza a `teak` nevű nyomtató beállításait is, és ehhez fogjuk hozzáadni a `rose` másik két nyomtatóját:

    #
    #  /etc/printcap (orchid) - a rose két (távoli) nyomtatójának
    #  hozzáadása
    #

    #
    #  A "teak" egy helyi nyomtató, közvetlenül az orchidhoz
    #  csatlakozik:
    #
    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:

    #
    #  A "rattan" rose-hoz csatlakozik, így küldhetünk neki nyomtatási
    #  feladatot:
    #
    rattan|line|diablo|lp|Diablo 630 Line Printer:\
            :lp=:rm=rose:rp=rattan:sd=/var/spool/lpd/rattan:

    #
    #  A "bamboo" is a rose-hoz tartozik:
    #
    bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
            :lp=:rm=rose:rp=bamboo:sd=/var/spool/lpd/bamboo:

Ezután már csak létre kell hoznunk a megfelelő nyomtatási könyvtárakat az `orchid` nevű gépen:

    # 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

Mostantól kezdve az `orchid` felhasználói képesek lesznek nyomtatni a `rattan` és `bamboo` nevű nyomtatókon is. Ezért, ha az `orchid` egyik felhasználója beírja, hogy:

    % lpr -P bamboo -d sushi-leírás.dvi

Az `orchid` gépen működő LPD rendszer ezt a nyomtatási feladatot a bemásolja a `/var/spool/lpd/bamboo` nevű nyomtatási könyvtárba és feljegyzi róla, hogy a nyomtatásához DVI szűrőre lesz szükség. Ahogy `rose` gépen található `bamboo` nyomtatási könyvtárában elegendő hely keletkezik, a két LPD átküldi egymás közt a `rose` nevű gépre az állományt. Ezután az állomány egészen addig várakozik a `rose` nyomtatási sorában, amíg végezetül kinyomtatásra nem kerül. A `rose` fogja átalakítani DVI-ről PostScript formátumra átalakítani (mivel a `bamboo` egy PostScript nyomtató).

### 9.4.3.2. Nyomtatók hálózati adatcsatlakozással

Amikor hálózati kártyát vásárolunk a nyomtatónkhoz, általában két változatukkal találkozhatunk: az egyikük nyomtatási rendszerként működik (ez a drágább), a másikuk pedig egyszerűen csak soros vagy párhuzamos csatlakozón továbbítandó adatként közvetíti az adatokat a nyomtató felé (az olcsóbb). A drágábbik változatot az előző, Távoli számítógépekre csatlakoztatott nyomtatók című szakaszban leírtak szerint tudjuk használni.

Az `/etc/printcap` állományban ugyan meg tudjuk adni, hogy a nyomtató soros vagy párhuzamos portra csatlakozik, és azon keresztül milyen adatátviteli sebességgel (amennyiben soros), forgalomirányítással, tabulálással, sortörési konvenció szerint stb. kommunikáljunk vele. Azonban TCP/IP vagy más hálózati porton ülő nyomtatók adatait itt nem tudjuk kifejteni.

A hálózatra kötött nyomtatók használatához lényegében egy olyan külön kifejlesztett kommunikációs programra van szükségünk, amely a szöveg- vagy konverziós szűrőkhöz hasonló módon hívható meg. Erre rögtön adunk is egy példát: a `netprint` szkript a szabványos bemenetről beolvassa az összes kinyomtatandó adatot és átküldi azokat a hálózatra csatlakoztatott nyomtatónak. A szkript első paramétereként a nyomtató hálózati nevét adjuk meg, másodiknak pedig portot. Azonban megjegyezzünk, hogy ez csak egyirányú kommunikációt tesz lehetővé (a FreeBSD-től a nyomtatóig). Sok hálózati nyomtató viszont két irányban is képes kommunikálni, ezért érdemes lehet ezt kihasználni (a nyomtató állapotának lekérdezésére, nyilvántartások készítésére stb).

    #!/usr/bin/perl
    #
    #  netprint - A hálózatra csatlakoztatott nyomtató szövegszűrője
    #  Helye: /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;

Rengeteg szűrőben fel tudjuk használni ezt a szkriptet. Például tegyük fel, hogy egy Diablo 750-N típusú sornyomtatót csatlakoztattunk a hálózatra, amely az 5100-as porton várja a nyomtatandó adatokat. A hálózati neve most `scrivener` lesz. Íme a hozzá tartozó szövegszűrő:

    #!/bin/sh
    #
    #  diablo-if-net - Az 5100-as porton figyelő `scrivener' nevű Diablo
    #  nyomtató szövegszűrője. Helye: /usr/local/libexec/diablo-if-net
    #
    exec /usr/libexec/lpr/lpf "$@" | /usr/local/libexec/netprint scrivener 5100

## 9.4.4. A nyomtató használatának szabályozása

Ebben a szakaszban a nyomtató használatának korlázásáról írunk. Az LPD rendszeren keresztül meghatározhatjuk, hogy ki képes helyben vagy távolról hozzáférni a nyomtatóhoz, mennyi másolatot nyomtathat, mennyi és egyenként mekkora nyomtatási feladatokat küldhet.

### 9.4.4.1. A másolatok számának szabályozása

Az LPD segítségével a felhasználók egy állományt könnyen ki tudnak nyomtatni akár többször is. Ha (például) a felhasználó egy nyomtatási feladat kiküldéséhez az `lpr `-#5`` parancsot használja, akkor a nyomtatási feladatban levő összes állományból öt példányt kap. Ennek létjogosultságát azonban nekünk kell megítélni.

Amennyiben úgy érezzük, hogy a további példányok készítése csupán felesleges papír- és tintapazarlás, akkor az `sc` tulajdonság megadásával az `/etc/printcap` állományban kikapcsolhatjuk az lpr(1) `-#` lehetőség használatát. Így amikor a felhasználók a `-#` kapcsolóval küldenek el feladatokat a nyomtatóra, a következőt fogják tapasztalni:

    lpr: multiple copies are not allowed

Fordítása:

    lpr: másolatok nyomtatása nem engedélyezett

Vigyázzunk arra, hogy ha távoli számítógépen zajlik a nyomtatás (lásd Távoli számítógépekre csatlakoztatott nyomtatók), akkor az `sc` tulajdonságot a távoli számítógép `/etc/printcap` állományában is be kell állítani, máskülönben a felhasználók egy másik számítógépről mindig képesek lesznek több példány nyomtatására.

Nézzünk erre egy példát. Itt most a `rose` nevű számítógép `/etc/printcap` állományát vesszük szemügyre. Ebben a `rattan` egy nagyon szívélyes nyomtató lesz, ezért engedélyezi a másolatok nyomtatását, azonban a `bamboo` nevű lézernyomtató nála már sokkal válogatósabb lesz, ezért a beállításai közt az `sc` tulajdonsággal kikapcsoljuk a másodpéldányok nyomtatását:

    #
    #  /etc/printcap (rose) - A másolatok korlátozása a "bamboo"
    #  nevű nyomtatón
    #
    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:ms#-parenb cs8 clocal crtscts:rw:\
            :if=/usr/local/libexec/psif:\
            :df=/usr/local/libexec/psdf:

Az `sc` tulajdonságot az `orchid` `/etc/printcap` állományában is meg kell adni (és ha már itt vagyunk, akkor tegyük meg ugyanezt a `teak` esetében is):

    #
    #  /etc/printcap (orchid) - Nincsenek másodpéldányok sem a helyi
    #  "teak" nyomtatón, sem pedig a távoli "bamboo" nyomtatón
    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:

Az `sc` tulajdonság használatával ugyan megakadályozzuk az `lpr `-#`` parancs teljesítését, azonban ez még mindig nem óv meg minket attól, hogy a felhasználók képesek legyenek többször egymás után lefuttatni az lpr(1) parancsot, vagy éppen egyetlen nyomtatási feladatban több állományt is elküldeni:

    % lpr forsale.sign forsale.sign forsale.sign forsale.sign forsale.sign

Számos módszer kínálkozik az effajta visszaélések kivédésére (beleértve a figyelmen kívül hagyást is), lehet velük kísérletezgetni!

### 9.4.4.2. A nyomtatók hozzáférésének szabályozása

A UNIX® csoportkezelésével és az `/etc/printcap` állományban található `rg` tulajdonság felhasználásával korlátozni tudjuk, ki milyen nyomtatón dolgozhat. Ehhez mindössze annyit kell tennünk, hogy besoroljuk egy csoportba azokat a felhasználókat, amelyek hozzáférhetnek a nyomtatóhoz, és az `rg` tulajdonsággal megnevezzük azt.

A csoporton kívüli felhasználókat (köztük magát a `root` felhasználót is) pedig ezután így üdvözli a rendszer, ha megpróbálnak valamit kinyomtatni egy korlátozott felhasználású nyomtatón:

    lpr: Not a member of the restricted group

Az üzenet fordítása:

    lpr: Nem jogosult felhasználó

Ha erre a távoli számítógépek esetén szükségünk lenne (lásd Távoli számítógépekre csatlakoztatott nyomtatók), akkor tegyük ugyanazt, mint amit az `sc` (a másodpéldányok letiltása, “suppress multiple copies”) tulajdonság esetén is, vagyis az `rg` tulajdonságot adjuk meg azokon a távoli számítógépeken is, amelyek hozzá tudnak férni a megosztott nyomtatóhoz.

Például megengedjük, hogy a `rattan` nevű nyomtatót bárki használhassa, azonban a `bamboo` nyomtatót csak az `artists` nevű csoport használhatja. Következzen hát akkor a `rose` korábbról már ismert `/etc/printcap` állománya:

    #
    #  /etc/printcap (rose) - A bamboo hozzáférésének korlátozása
    #
    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:ms#-parenb cs8 clocal crtscts:rw:\
            :if=/usr/local/libexec/psif:\
            :df=/usr/local/libexec/psdf:

Most ne bántsuk a másik (az `orchid` nevű gépen levő) `/etc/printcap` állományt. Így persze az `orchid` bármelyik felhasználója nyomtathat a `bamboo` nyomtatón. De ez most egy olyan eset, ahol egyébként lekorlátozzuk a `orchid` elérését is, ezért az ott beengedett felhasználók már akár használhatják is a nyomtatót. Vagy sem.

> Megjegyzés: Minden nyomtatóhoz csak egy ilyen csoportot adhatunk meg.

### 9.4.4.3. A beküldött nyomtatási feladatok méretének szabályozása

Ha sok felhasználó szeretne a nyomtatóinkhoz hozzáférni, akkor minden bizonnyal meg akarunk adni egy felső határt a felhasználók által beküldhető nyomtatások méretére vonatkozóan. Mivel a nyomtatási könyvtáraknak otthont adó állományrendszer is egyszer betelhet, ezért mindenképpen érdemes gondoskodni arról, hogy mindenki nyomtatási feladatát el tudjuk rendesen tárolni.

Az LPD az `mx` tulajdonsággal lehetőséget ad arra, hogy lekorlátozzuk a nyomtatási feladatokban található egyes állományok méretét. Ennek mértékegysége egy `BUFSIZ` blokk, ami pedig 1024 byte. Ha értékül nullát adunk meg, akkor nincs korlátozás, viszont ha semmit sem rögzítünk, akkor az `mx` tulajdonság alapértéke, vagyis 1000 blokk lesz a határ.

> Megjegyzés: Ez az érték a nyomtatási feladatokban levő egyes állományok méretére vonatkozik, nem pedig a nyomtatási feladatok teljes méretére.

Fontos tudni, hogy az LPD nem dobja vissza a méreten felüli állományokat. Ehelyett a méret alatti részt szépen berakja a sorba és kinyomtatja, a többi pedig elhagyja. Lehetne rajta vitázni, hogy ez mennyire helyes cselekedet.

Példaképpen definiáljunk a korábban használt `rattan` és `bamboo` nyomtatóinkhoz ilyen korlátokat. Mivel az `artists` csoport tagjai hajlamosak nagy PostScript állományokat küldeni, ezért most lekorlátozzuk ezt öt megabyte-ra. A szöveges nyomtatónk esetén azonban nem lesz semmilyen határ:

    #
    #  /etc/printcap (rose)
    #

    #
    #  Itt nincs korlát a nyomtatási feladatokra:
    #
    rattan|line|diablo|lp|Diablo 630 Line Printer:\
            :sh:mx#0:sd=/var/spool/lpd/rattan:\
            :lp=/dev/lpt0:\
            :if=/usr/local/libexec/if-simple:

    #
    #  Öt megabyte a PostScript:
    #
    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:ms#-parenb cs8 clocal crtscts:rw:\
            :if=/usr/local/libexec/psif:\
            :df=/usr/local/libexec/psdf:

Ismét hozzátesszük, hogy ezek a korlátok csak a helyi felhasználókra vonatkoznak. Amennyiben távolról is el lehet érni ezt a nyomtatót, a távoli felhasználókat nem fog semmilyen korlátozás érinteni. Azokon a számítógépeken is meg kell adnunk az `/etc/printcap` állományban az `mx` tulajdonságot. Ehhez a Távoli számítógépekre csatlakoztatott nyomtatók című szakaszban találunk segítséget.

Van még egy speciális módszer, amivel képesek vagyunk szabályozni a távolról érkező kérések méretét. Erről a Távoli számítógépekről érkező kérések szabályozása szakaszban olvashatunk.

### 9.4.4.4. Távoli számítógépekről érkező kérések szabályozása

Az LPD nyomtatási rendszer több módot is szolgáltat a távolról érkező nyomtatási feladatok szabályozására:

Az elérés szabályozása

  Az `/etc/hosts.equiv` és `/etc/hosts.lpd` állományok segítségével beállíthatjuk, hogy mely távoli számítógépektől fogadjon el kéréseket az LPD. Az LPD minden kérés elfogadásakor ellenőrzi, hogy a küldő számítógép címe szerepel-e az említett állományok valamelyikében. Ha nem, akkor az LPD visszautasítja a kérést.

  A két állomány felépítése egyszerű, mert bennük minden sorban egy-egy hálózati nevet adunk meg. Hozzátennénk azonban, hogy legyünk óvatosak, mivel az `/etc/hosts.equiv` állományt az ruserok(3) protokoll is használja, ezért ennek módosítása hatással van az rsh(1) és rcp(1) programok működésére.

  Például most nézzük meg a `rose` `/etc/hosts.lpd` állományát:

      orchid
      violet
      madrigal.fishbaum.de

  Ennek megfelelően tehát a `rose` elfogadja az `orchid`, `violet` és `madrigal.fishbaum.de` nevű távoli számítógépek kéréseit. Ha bármilyen más gép próbál hozzáférni a `rose` által felkínált LPD szolgáltatáshoz, visszautasítja.

A méret szabályozása

  Szabályozhatjuk többek közt azt is, hogy mennyi szabad területnek kell fennmaradnia a nyomtatási könyvtárnak otthont adó állományrendszeren. A helyi nyomtató könyvtárában ehhez hozzunk létre egy `minfree` nevű állományt. Ide írjuk be, mennyi szabad lemezblokk (512 byte-os egység a lemezen) szükségeltetik egy távolról beérkező nyomtatási feladat fogadásához.

  Így gondoskodhatunk róla, hogy a távoli felhasználók nem fogják eltömíteni az állományrendszerünket, illetve ezzel egyúttal adhatunk némi előnyt a helyi felhasználóknak is: ők ugyanis még azután is képesek lesznek nyomtatási feladatokat küldeni a nyomtatónak, miután az állományrendszeren található szabad terület mennyisége már rég a `minfree` állományban szereplő érték alá csökkent.

  Példaként most a `bamboo` nevű nyomtatónkhoz adjunk meg egy ilyen `minfree` állományt. Ehhez az `/etc/printcap` állományból tudjuk kideríteni a hozzá tartozó nyomtatási könyvtárat. Lássuk tehát belőle a `bamboo` bejegyzését:

      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:ms#-parenb cs8 clocal crtscts:rw:mx#5000:\
              :if=/usr/local/libexec/psif:\
              :df=/usr/local/libexec/psdf:

  A nyomtatási könyvtárat az `sd` tulajdonság határozza meg. Úgy állítjuk most be, hogy az LPD számára a távoli nyomtatási feladatok fogadásához ebben a könyvtárban legalább három megabyte (6144 blokk) szabad területnek mindig lennie kell:

      # echo 6144 > /var/spool/lpd/bamboo/minfree

A felhasználók szabályozása

  Az `/etc/printcap` állományban megadható `rs` tulajdonság segítségével korlátozhatjuk a helyi nyomtatókhoz hozzáférni képes távoli felhasználókat. Amikor az `rs` tulajdonság szerepel egy helyben csatlakozó nyomtató leírásánál, akkor az LPD csak abban az esetben fogad el távoli felhasználóktól nyomtatási feladatot, ha az adott feladatot küldő felhasználónak ugyanazon a néven van a helyi gépen is hozzáférése. Máskülönben az LPD vissza fogja utasítani a kérést.

  Ez a tulajdonság különösen fontos olyan környezetben, ahol (például) több szervezeti egység használ egyetlen közös hálózatot és bizonyos felhasználók képesek átlépni szervezeti egységük határait, mivel ha a hozzáférést adunk nekik a rendszereinkhez, akkor képesek a saját helyükről használni ezeket. Ha ehelyett csupán a nyomtatóinkat és a számítógépünk összes erőforrását akarjuk megosztani, akkor létrehozhatunk a számukra olyan “token” hozzáféréseket is, amikhez nem tartozik sem felhasználói könyvtár, sem pedig parancsértelmező (pontosabban a `/usr/bin/false`).

## 9.4.5. A nyomtató használatának nyilvántartása

Tehát szükségünk lenne a nyomtatások költségének elszámolására. Miért is ne tennénk ilyet? A papír és a tinta bizony pénzbe kerül, amihez még hozzájárulnak más egyéb karbantartási költségek is -- a nyomtatók dugig vannak mindenféle mozgó alkatrésszel, amelyek előbb-utóbbi el is romlanak. Tegyük fel, hogy a nyomtatóink kapacitása, kihasználtsága és karbantartási költsége alapján már megállapítottunk egy elszámolási egységet (oldalanként, méterenként, akárminként). De hogyan lássunk hozzá a nyomtatások költségének tényleges nyilvántartásához?

Van egy rossz hírünk: az LPD nyomtatási rendszer önmaga nem tud segíteni ebben a feladatban. A nyilvántartás nagyban függ a használt nyomtatóktól, a nyomtatott formátumoktól és nyomtató általunk kiszabott költségeitől.

A nyilvántartás létrehozásához át kell írnunk a nyomtatóhoz tartozó szűrőt (a nyers szövegek költségének felszámításához) és konverziós szűrőket (a különféle formátumok költségei miatt), amikkel aztán számolhatjuk vagy lekérdezhetjük a kinyomtatott lapokat. Egyetlen kimeneti szűrő használatával szinte semmire se megyünk, mivel az nem képes nyilvántartás vezetésére. Erről bővebb útmutatást a Szűrők szakaszban találhatunk.

Általánosságban véve két módon vezethetünk nyilvántartást:

- Az időszakos elszámolás a gyakoribb, mivel ez az egyszerűbb. Amikor valaki végrehajt egy nyomtatási feladatot, a szűrő a nyilvántartást tároló állományba feljegyzi a felhasználó azonosítóját, a gépének nevét és a kinyomtatott oldalakat. Ezután minden hónapban, félévben, évben vagy akár tetszőleges időközönként összegyűjtjük a nyomtatók nyilvántartásait és külön feljegyezzük az egyes felhasználók nyomtatásait, majd benyújtjuk róla a számlát. Töröljük az összes naplóállományt, és tiszta lappal kezdjük a következő időszakot.

- Az azonnali elszámolás már nem annyira népszerű, mivel nehezebb megvalósítani. Ekkor a felhasználók már közvetlenül a nyomtatás után megkapják a számlát, hasonlóan a lemezkvótákhoz. Meg tudjuk akadályozni ezzel azt is, hogy a felhasználók túlléphessék az előre kiszabott “nyomtatási kvótájukat”, amit persze menet közben lehet ellenőrizni és állítgatni. A felhasználók és kvótájuk nyomonkövetéséhez viszont szükségünk lesz egy kis adatbáziskezelésre is.

Az LPD nyomtatási rendszer mind a két módszer kivitelezéséhez tud segítséget nyújtani, hiszen amikor szűrőket állítunk be (vagyis szinte mindig), lehetőségünk van a nyilvántartást végző programrészleteket is beilleszteni. És ami feltétlenül előnyös: óriási mértékű rugalmasságot ajánl fel a nyilvántartás megvalósításához. Például magunk választhatjuk ki, hogy időszakos vagy azonnali elszámolást alkalmazunk. Meg tudjuk adni, milyen információkat rögzítsünk: felhasználói neveket, számítógépek neveit, a nyomtatási feladatok típusát, vagy a kinyomtatott oldalakat, a felhasznált lapok területét, a nyomtatások időbeli igényeit és így tovább. Ehhez mindössze csak a szűrőket kell módosítani.

### 9.4.5.1. Nyilvántartás gyorsan és egyszerűen

A FreeBSD-ben egyből találunk is két programot, amivel pillanatok alatt ki tudunk alakítani egy egyszerű időszakos elszámolási rendszert. Ezek Az lpf szövegszűrő című szakaszban ismertetett `lpf` és a nyomtatók nyilvántartásait tartalmazó állományok adatainak összegyűjtését és kiértékelését végző pac(8).

Ahogy korábban már leírtuk a szűrőkről szóló szakaszban (Szűrők), az LPD a szöveg- és konverziós szűrőket parancssorból a nyilvántartást tároló állomány nevével indítja el. Ezt a paramétert a szűrők aztán fel tudják használni a nyilvántartások feljegyzéséhez. Az állomány nevét az `/etc/printcap` állományban szereplő `af` tulajdonsággal tudjuk megadni, vagy teljes elérési úttal, vagy pedig a nyomtatási könyvtárhoz viszonyítva.

Az LPD az `lpf` szűrőt a lap szélességének és hosszának megadásával indítja el (ezeket az értékeket a `pw` és `pl` tulajdonságokból származtatja). Az `lpf` ezek felhasználásával meg tudja mondani, mennyi papírt használtunk el. Miután kiküldte az állományt a nyomtatóra, nyilvántartásba is veszi. Ezek a típusú bejegyzések valahogy így néznek ki:

    2.00 rose:andy
    3.00 rose:kelly
    3.00 orchid:mary
    5.00 orchid:mary
    2.00 orchid:zhang

Minden nyomtatóhoz érdemes külön nyilvántartást vezetni, mivel az `lpf` nem tartalmaz semmilyen beépített zárolási megoldást, ezért két `lpf` párhuzamos futtatása könnyen összezagyválhatja a közösen használt nyilvántartások tartalmát. Az `/etc/printcap` állományban az `af=acct` tulajdonság megadásával könnyen létre tudunk hozni minden nyomtatóhoz külön nyilvántartást. Ilyenkor minden nyomtató könyvtárában megjelenik egy `acct` nevű állomány.

Amikor elérkezünk a nyomtatások kiszámlázásához, futtassuk le a pac(8) programot. Ehhez mindössze annyit kell tennünk, hogy átlépünk az elszámolni kívánt nyomtató könyvtárába és begépeljük a `pac` parancsot. Ekkor kapunk egy ehhez hasonló, dollár alapú kimutatást:

      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

A pac(8) a következő paramétereket várja:

`-P`nyomtató``

  Az kiértékelendő `nyomtató` neve. Ez a paraméter csak akkor használható, ha az `/etc/printcap` állományban az `af` tulajdonságnak teljes elérési utat adtunk meg.

`-c`

  A felhasználók nevei helyett a fizetendő összeg szerint rendezze a listát.

`-m`

  Hagyja figyelmen kívül a nyilvántartásban szereplő gépek hálózati neveit. Ennek hatására az `alpha` gépről nyomtató `smith` meg fog egyezni a `gamma` gépről nyomtatóval. A beállítás nélkül ez a két felhasználó el fog térni.

`-p`ár``

  A paraméterként megadott `ár` dollár értékkel számol oldalanként vagy lábanként az `/etc/printcap` állományban megadott `pc` tulajdonság értéke helyett (ami alapból két cent). Az `ár` lebegőpontos (valós) számként is megadható.

`-r`

  A rendezési sorrend megfordítása.

`-s`

  Hozzon létre egy elszámolást, majd törölje a hozzá kapcsolódó nyilvántartási adatokat.

`név` `...`

  Csak az adott `nevű` felhasználók adatait értékelje ki.

A pac(8) által alapértelmezés szerint generált kimutatásban láthatjuk az egyes gépekről származó egyes felhasználók kinyomtatott oldalait. Ha nekünk viszont nem számít, hogy honnan küldték a kéréseket (mivel bárhonnan lehet küldeni), akkor a `pac `-m`` paranccsal az alábbi táblázatot készíttethetjük el:

      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

Itt megtaláljuk a ténylegesen kifizetendő összegeket is, amik kiszámításához a pac(8) az `/etc/printcap` állomány `pc` tulajdonságát használja (ez alapból 200, avagy 2 cent oldalanként). Ezzel a tulajdonsággal tehát egy cent századrészében mérve tudjuk megadni az oldalakénti vagy lábankénti árakat. Ezt a beállítást természetesen a pac(8) `-p` opciójával felül tudjuk bírálni. Arra azonban vigyázzunk, hogy a `-p` után dollárban kell megadnunk az árat. Emiatt tehát a

    # pac -p1.50

parancs szerint minden egyes oldal másfél dollárba fog kerülni. Ezzel az opcióval aztán alaposan megdönthetjük az árakat.

Végezetül megemlítjük, hogy a `pac `-s`` parancs az általa létrehozott elszámolást egy külön állományba menti, amelynek a neve nagyjából megegyezik a nyilvántartást végzőével, de `_sum`-ra (mint “summary”, azaz elszámolás) végződik. Ezután nullázza a nyilvántartást. Amikor a pac(8) programot újra lefuttatjuk, újból beolvassa a korábban elmentett elszámolásokat, majd hozzászámolja a többit a hagyományos nyilvántartási adatokból.

### 9.4.5.2. Hogyan tudjuk számolni a kinyomtatott lapokat?

A nyilvántartás pontos vezetéséhez még távolról is valamilyen módon meg kell tudnunk mondani, hogy mennyi lapot használt egy nyomtatási feladat végrehajtása. Ez a nyomtatás nyilvántartásának egyik alapvető problémája.

A nyers szövegek esetében ez nem is annyira bonyolult: egyszerűen számoljuk össze, hogy a nyomtatási feladatban mennyi sor kinyomtatására lesz szükség és vessük össze ezt a nyomtató által lapoként kinyomtatott sorok számálva. Ne felejtsük el számításba venni a szövegben felbukkanó törlések hatását, vagy az olyan hosszú sorokat, amelyek a valóságban több sorban fognak megjelenni.

Viszont (Az lpf szövegszűrő című szakaszban bemutatott) `lpf` program ezeket mind lekezeli a nyilvántartások készítése során. Ezért ha szintén egy nyilvántartást vezetni képes szövegszűrőt akarunk írni, akkor mindenképpen érdemes megnéznünk az `lpf` forráskódját.

De hogyan bánjunk el a többi formátummal?

Nos, a DVI-Laserjet és DVI-PostScript közti átalakítások esetén a kinyomtatott lapok számának megállapításához meg kell tanítanunk a szűrőnket értelmezni a `dvilj` vagy `dvips` parancsok kimenetét. Ugyanezt meg tudjuk tenni más formátumok és más konverziós programok használata során is.

Azonban ezek a módszerek nem veszik számításba, hogy a nyomtató egyáltalán kinyomtatta-e az összes elküldött oldalt. Sok minden történhet még addig, például beragadhat a papír, kifogyhat a tinta vagy akár felrobbanhat a nyomtató -- a felhasználónak ettől függetlenül még fizetnie kell.

Mit lehet ilyenkor tenni?

A precíz nyilvántartásnak csak egyetlen biztos módja létezik. Olyan nyomtatót szerezzünk be, amely képes megmondani, mennyi lapot használt el a nyomtatás során, majd egy ilyet csatlakoztassunk soros porton vagy hálózaton keresztül. Szinte majdnem az összes PostScript nyomtató támogatja ezt a lehetőséget, ahogy sok más gyártmány és típus is (például a hálózati Imagen lézernyomtatók). A nyomtatóhoz tartozó szűrőt ehhez úgy kell módosítani, hogy lekérdezzük a kinyomtatott lapok számát a nyomtatás után és kizárólag erre az értékre alapozva készítünk nyilvántartást. Itt nincs szükség sem a sorok számolására, sem pedig az állományok (könnyen elhibázható) átvizsgálására.

Természetesen lehetünk nagylelkűek és ne számítsunk fel semmit a nyomtatásért.

Előző | Tartalom | Következő
Kezdeti beállítások | Fel | A nyomtatók használata

Ha kérdése van a FreeBSD-vel kapcsolatban, a következő címre írhat (angolul): <freebsd-questions@FreeBSD.org>.
Ha ezzel a dokumentummal kapcsolatban van kérdése, kérjük erre a címre írjon: <gabor@FreeBSD.org>.