10.4. Geavanceerde printerinstallatie
Terug | Hoofdstuk 10. Afdrukken | Volgende

## 10.4. Geavanceerde printerinstallatie

Deze sectie behandelt het gebruik van filters om speciaal opgemaakte tekst en voorbladen af te drukken, via het netwerk af te drukken en printergebruik te beperken en statistieken bij te houden.

### 10.4.1. Filters

Hoewel LPD veel van het afdrukwerk afhandelt (netwerkverkeer, wachtrijafhandeling, toegangscontrole, enzovoort), wordt het echte werk door de filters gedaan. Filters zijn programma's die met een printer communiceren en inspelen op printerspecifieke eigenschappen. In de eenvoudige printeropzet is een filter geïnstalleerd voor platte tekst, een zeer eenvoudig filter dat met de meeste printers zou moeten werken (Tekstfilter installeren).

Om echter gebruik te maken van formaatomzetting, printeradministratie, printerspecifieke aanpassingen, enzovoort, is het nodig te weten hoe filters werken. Uiteindelijk is het de verantwoordelijkheid van het filter om deze zaken af te handelen. Het slechte nieuws is dat de beheerder in het merendeel van de gevallen het filter moet aanleveren. Het goede nieuws is dat veel filters algemeen beschikbaar zijn en als ze dat niet zijn, zijn ze vaak makkelijk te schrijven.

FreeBSD heeft een ingebouwd filter, `/usr/libexec/lpr/lpf`, die met veel printers werkt die platte tekst kunnen afdrukken. Het filter regelt backspace en tabs in bestanden en administreert printergebruik, maar dat is zo'n beetje alles wat dit filter doet. Er zijn ook diverse filters en filtercomponenten in de FreeBSD Portscollectie.

Hieronder wordt het volgende beschreven:

- In Hoe filters werken staat een overzicht van de rol die een filter speelt in het afdrukproces. Lees dat onderdeel om een indruk te krijgen wat er “onder de motorkap” gebeurt als LPD filters gebruikt. Deze kennis helpt mogelijke problemen te voorkomen of op te lossen als meerdere filters worden geïnstalleerd voor printers.

- LPD gaat er van uit dat elke printer standaard platte tekst af kan drukken. Dit geeft problemen voor PostScript® (of andere op taal gebaseerde) printers die niet in staat zijn direct platte tekst af te drukken. In Platte tekst op PostScript®-printers afdrukken staat wat er kan worden gedaan om dit probleem te verhelpen. Lees verder in dit onderdeel als het om PostScript®-printers gaat.

- Voor veel programma's is PostScript® een populair uitvoerformaat. Sommige mensen schrijven PostScript® code zelfs direct. PostScript®-printers zijn echter kostbaar. In PostScript® simuleren op niet-PostScript®-printers staat hoe de tekstfilter van een printer aangepast moet worden zodat die PostScript® accepteert en afdrukt op een niet-PostScript®-printer. Dit onderdeel is van toepassing voor niet-PostScript®-printers.

- In Conversiefilters wordt een methode beschreven om de conversie van bepaalde bestandsformaten te automatiseren, zoals van grafische of tekstopmaakprogramma's, naar formaten die een printer kan begrijpen. Na het lezen van dit onderdeel is een beheerder in staat om een printer zodanig in te stellen dat gebruikers `lpr -t` kunnen invoeren om troff-gegevens af te drukken, `lpr -d` om TeX DVI-gegevens af te drukken of `lpr -v` om rasterplaatjes af te drukken, enzovoorts. Het wordt aangeraden deze sectie te lezen.

- In Uitvoerfilters wordt een niet vaak gebruikte functionaliteit van LPD behandeld: uitvoerfilters. Tenzij voorbladen worden afgedrukt (Voorbladen), kan deze sectie waarschijnlijk overgeslagen worden.

- lpf: een tekstfilter beschrijft `lpf`, een redelijk complete, eenvoudige tekstfilter voor lijnprinters (en laserprinters die zich als lijnprinters voordoen) dat wordt geleverd bij FreeBSD. Voor een snelle manier om printeradministratie aan de praat te krijgen voor platte tekst of voor printers waar rook uit komt bij het zien van backspace karakters, is het serieus te overwegen gebruik te maken van `lpf`.

### Opmerking:

Een kopie van de scripts die hieronder worden beschreven, staan in de map `/usr/share/examples/printing`.

#### 10.4.1.1. Hoe filters werken

Zoals eerder genoemd, is een filter een programma dat wordt uitgevoerd door LPD voor het afhandelen van het apparaatafhankelijke deel van de communicatie met een printer.

Als LPD een bestand wil afdrukken uit een afdrukopdracht, start het een filterprogramma. Het koppelt de standaard invoer van de filter aan het af te drukken bestand, de standaard uitvoer aan de printer en de standaard foutmelding aan het logboekbestand voor foutmeldingen (zoals opgegeven via de optie `lf` in `/etc/printcap` of standaard `/dev/console`).

Welk filter LPD start en de argumenten van het filter hangen af van wat er in het bestand `/etc/printcap` wordt opgegeven en de argumenten die de gebruiker geeft op de commandoregel van lpr(1). Als een gebruiker bijvoorbeeld `lpr -t` ingeeft, start LPD het filter troff, zoals wordt opgegeven via de optie `tf` voor de betreffende printer. Als een gebruiker platte tekst wilt afdrukken, dan wordt het filter `if` gestart (dit klopt bijna: zie Uitvoerfilters voor de details).

Er zijn drie soorten filters die in `/etc/printcap` kunnen worden opgegeven:

- Het tekstfilter, dat in de LPD documentatie verwarrend genoeg input filter wordt genoemd, verwerkt het afdrukken van gewone tekst. Beschouw het als het standaardfilter. LPD verwacht dat elke printer standaard platte tekst kan afdrukken en het is de taak van het tekstfilter om er voor te zorgen dat backspaces, tabs en andere speciale karakters de printer niet in de war sturen. In een omgeving waar moet worden bijgehouden hoeveel er wordt afgedrukt, moet het tekstfilter ook administreren hoeveel pagina's er zijn afgedrukt. Dit gaat meestal door het aantal afgedrukte regels te tellen en dit te vergelijken met het aantal regels per pagina dat door de printer wordt ondersteund. Het tekstfilter wordt aangeroepen met de volgende lijst argumenten:

  `filter-name` [-c] -w `width` -l `length` -i `indent` -n `login` -h `host` `acct-file`

  met

  `-c`

    wordt gebruikt als de afdrukopdracht is gegeven met `lpr -l`

  `width`

    is de waarde van de optie `pw` (page width: paginabreedte), zoals opgegeven in `/etc/printcap`, standaard 132

  `length`

    is de waarde van de optie `pl` (page length: paginalengte), standaard 66

  `indent`

    geeft aan hoeveel wordt ingesprongen door `lpr -i`, standaard 0

  `login`

    de gebruikersnaam van de gebruiker die de afdrukopdracht gaf

  `host`

    de hostnaam waar de afdrukopdracht gegeven is

  `acct-file`

    de naam van het administratiebestand zoals opgegeven via de optie `af`.

- Een conversiefilter converteert een specifiek bestandsformaat naar een formaat dat een printer begrijpt. Bijvoorbeeld: ditroff typesettinggegevens kunnen niet direct worden afgedrukt, maar er bestaat wel een conversiefilter om ditroff-gegevens te converteren naar een formaat dat een printer kan verteren en afdrukken. Dit wordt in Conversiefilters beschreven. Conversiefilters zijn ook nodig om printergebruik te administreren, mocht dat nodig zijn. Conversiefilters worden met de volgende argumenten aangeroepen:

  `filter-name` -x `pixel-width` -y `pixel-height` -n `login` -h `host` `acct-file`

  Hier is `pixel-width` de waarde van de optie `px` (standaard 0) en `pixel-height` is de waarde van de optie `py` (standaard 0).

- Het uitvoerfilter wordt alleen gebruikt als er geen tekstfilter is of als er voorbladen worden afgedrukt. De ervaring leert dat uitvoerfilters zelden worden gebruikt. In sectie Uitvoerfilters worden ze beschreven. Er zijn slechts twee argumenten die aan een uitvoerfilter worden meegegeven:

  `filter-name` -w `width` -l `length`

  Deze zijn identiek aan de argumenten `-w` en `-l` van het tekstfilter.

Filters moeten afsluiten met de volgende waarde:

exit 0

  Als het filter een bestand succesvol heeft afgedrukt.

exit 1

  Als het filter niet geslaagd is om een bestand af te drukken, maar wil dat LPD het nogmaals probeert. LPD herstart het filter als die afsluit met deze status.

exit 2

  Als het filter niet geslaagd is om een bestand af te drukken, maar niet wil dat LPD het nogmaals probeert. LPD verwijdert het bestand uit de wachtrij.

Het tekstfilter dat bij FreeBSD wordt geleverd, `/usr/libexec/lpr/lpf`, benut de argumenten voor paginabreedte en -lengte om te bepalen wanneer een nieuwe pagina moet worden begonnen en om het printergebruik bij te houden. Het gebruikt de argumenten voor login, host en administratiebestand om accountingregels aan te maken.

Controleer bij het zoeken naar filters of ze LPD-compatibel zijn. Zo ja, dan ondersteunen ze de argumenten zoals hierboven beschreven. Zorg bij het zelf schrijven van filters voor algemeen gebruik dat ze dezelfde argumenten en exitcodes ondersteunen.

#### 10.4.1.2. Platte tekst op PostScript®-printers afdrukken

Als een computer en PostScript® (of andere op taal gebaseerde) printer maar één gebruiker hebben die belooft nooit platte tekst naar de printer te sturen of programma's te gebruiken die dat doen, dan is dit onderdeel overbodig.

Als gebruikers zowel PostScript® als platte tekst naar een printer willen sturen, dan is het aan te raden de printerinstellingen hierop aan te passen. Hiervoor moet het tekstfilter bij elke nieuwe opdracht bepalen of het om platte tekst of PostScript® gaat. Alle PostScript®-opdrachten beginnen met `%!` (raadpleeg de printerhandleiding voor andere printertalen). Als dit de eerste twee karakters zijn van een opdracht is het PostScript® en kan de rest van een opdracht direct doorgestuurd worden. Is dit niet het geval, dan moet de filter de tekst omzetten in PostScript® en het resultaat afdrukken.

Hoe gaat dat werken?

Voor seriële printers kan het meest eenvoudig `lprps` geïnstalleerd worden. `lprps` is een PostScript®-afdrukfilter die tweewegcommunicatie met een printer heeft. Het werkt het statusbestand van een printer bij met uitgebreide informatie afkomstig van een printer, zodat gebruikers en beheerders precies kunnen zien wat de status van een printer is (zoals: toner bijna op of papier vastgelopen). Maar belangrijker, het omvat het programma `psif` dat bepaalt of een binnenkomende opdracht platte tekst is en `textps` (dat ook geleverd wordt met `lprps`) om opdrachten om te zetten naar PostScript®. Vervolgens wordt een opdracht met `lprps` naar een printer gestuurd.

`lprps` is onderdeel van de FreeBSD Portscollectie (zie De Portscollectie). U kunt één van de ports print/lprps-a4 of print-lprps-letter installeren afhankelijk van de gebruikte papiermaat. Nadat `lprps` is geïnstalleerd moet de installatielocatie ervan aan `psif` worden doorgeven dat onderdeel is van `lprps`. Als `lprps` is geïnstalleerd via de Portscollectie, gebruik dan het volgende voor de seriële PostScript®-printer in `/etc/printcap`:

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

Ook moet de optie `rw` worden opgeven, die LPD vertelt om een printer in lezen/schrijvenmodus te openen.

Als een parallelle PostScript®-printer wordt ingesteld (en dus geen tweewegcommunicatie toegepast kan worden met de printer, zoals vereist door `lprps`), dan kan het volgende shellscript gebruikt worden als tekstfilter:

    #!/bin/sh
    #
    #  psif - Druk PostScript® of platte tekst af op een PostScript®
    #  printer. Script versie; NIET de versie die wordt geleverd bij lprps
    #  Geïnstalleerd in /usr/local/libexec/psif
    #

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

    if [ "$first_two_chars" = "%!" ]; then
        #
        #  PostScript® opdracht, afdrukken.
        #
        echo "$first_line" && cat && printf "\004" && exit 0
        exit 2
    else
        #
        #  Platte tekst, converteren en dan afdrukken.
        #
        ( echo "$first_line"; cat ) | /usr/local/bin/textps && printf "\004" && exit 0
        exit 2
    fi

In bovenstaand script is `textps` een programma dat geïnstalleerd is om platte tekst om te zetten naar PostScript®. Elk tekst-naar-PostScript® programma volstaat. De FreeBSD Portscollectie (zie De Portscollectie) bevat een uitgebreid tekst-naar-PostScript®-programma, `a2ps`, dat wellicht handig is om te gebruiken.

#### 10.4.1.3. PostScript® simuleren op niet-PostScript®-printers

PostScript® is de facto de standaard voor op hoge kwaliteit typesetten en afdrukken. PostScript® is echter een dure standaard. Gelukkig heeft Aladdin Enterprises een gratis PostScript®-kloon, Ghostscript, die werkt onder FreeBSD. Ghostscript kan de meeste PostScript®-bestanden lezen en de pagina's op verschillende soorten apparaten weergeven, waaronder veel niet-PostScript®-printers. Door Ghostscript te installeren en een printer gebruik te laten maken van een speciaal tekstfilter voor uw printer, kan uw niet-PostScript®-printer zich gedragen als een echte PostScript®-printer.

Ghostscript is beschikbaar via de FreeBSD Portscollectie, vele versies zijn beschikbaar, de meest gebruikte versie is print/ghostscript-gpl.

Om PostScript® te simuleren moet een tekstfilter detecteren of het een PostScript®-bestand aan het afdrukken is. Zo niet, dan stuurt het filter het bestand direct naar een printer, anders gebruikt het filter Ghostscript om het bestand om te zetten naar een formaat dat door een printer wordt begrepen.

Een voorbeeld: het volgende script is een tekstfilter voor Hewlett Packard DeskJet 500 printers. Voor andere printers moet het argument `-sDEVICE` voor het commando `gs` (Ghostscript) vervangen worden. (Met `gs -h` wordt een lijst met apparaten getoond worden die de huidige installatie van Ghostscript ondersteunt.)

    #!/bin/sh
    #
    #  ifhp - Druk Ghostscript-gesimuleerd PostScript® af op een DeskJet
    #  500.  Geïnstalleerd in /usr/local/libexec/ifhp

    #
    #  Behandel LF als CR+LF (om een "trapeffect" op HP/PCL
    #  printer te voorkomen):
    #
    printf "\033&k2G" || exit 2

    #
    #  Lees de eerste twee karakters van het bestand
    #
    IFS="" read -r first_line
    first_two_chars=`expr "$first_line" : '\(..\)'`

    if [ "$first_two_chars" = "%!" ]; then
        #
        #  Het is PostScript®. Gebruik Ghostscript om te converteren
        #  en druk het af.
        #
        /usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 \
            -sOutputFile=- - && exit 0
    else
        #
        #  Platte tekst of HP/PCL, dus direct afdrukken;  druk een
        #  pagina-einde af om de laatste pagina te ejecteren.
        #
        echo "$first_line" && cat && printf "\033&l0H" &&
    exit 0
    fi

    exit 2

Tot slot moet LPD op de hoogte gebracht worden van het filter via de optie `if`:

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

Dat is alles. Nu kan `lpr platte.tekst` en `lpr watdanook.ps` ingevoerd worden en beiden worden juist afgedrukt.

#### 10.4.1.4. Conversiefilters

Na de eenvoudige installatie, zoals beschreven in Eenvoudige printerinstallatie, te hebben voltooid, is het waarschijnlijk wenselijk om conversiefilters te installeren voor favoriete bestandsformaten (naast platte ASCII-tekst).

##### 10.4.1.4.1. Waarom conversiefilters installeren?

Conversiefilters maken het afdrukken van verschillende bestanden eenvoudig. Stel dat veel gebruik gemaakt wordt van het tekstverwerkingsprogramma TeX en een PostScript® printer. Elke keer als door TeX een DVI-bestand wordt gegenereerd, kan dat niet direct afgedrukt worden. Het DVI-bestand moet omgezet worden naar PostScript®. De te geven opdrachten zijn de volgende:

    % dvips zeewieranalyse.dvi
    % lpr zeewieranalyse.ps

Na installatie van een conversiefilter voor DVI-bestanden kan deze handmatige conversie overgeslagen worden door LPD de conversie te laten uitvoeren. Elke keer als een DVI-bestand wordt afgedrukt, hoeft alleen de volgende opdracht gegeven te worden:

    % lpr -d zeewieranalyse.dvi

LPD voert de DVI-bestandsconversie uit door `-d` te geven. In Opties voor opmaak en conversie staat een lijst van conversie-opties.

Voor elke conversie-optie moet een conversiefilter geïnstalleerd worden en moet in `/etc/printcap` de locatie worden opgegeven. Een conversiefilter is als het tekstfilter voor de eenvoudige printerinstallatie (Tekstfilter installeren), behalve dat in plaats van platte tekst af te drukken, het conversiefilter het bestand converteert naar een formaat dat een printer begrijpt.

##### 10.4.1.4.2. Welke conversiefilters installeren?

Installeer de conversiefilters die nodig zijn. Als veel DVI-bestanden worden afgedrukt, dan is het handig een DVI-filter te installeren. Als veel troff wordt afgedrukt, dan is het waarschijnlijk handig een troff-filter te installeren.

De volgende tabel geeft een samenvatting van filters waarmee LPD kan werken, hoe ze in `/etc/printcap` kunnen worden aangeroepen en hoe ze met `lpr` kunnen worden aangeroepen:

Bestandsformaat | `/etc/printcap` optie | `lpr` optie
--- | --- | ---
cifplot | `cf` | `-c`
DVI | `df` | `-d`
plot | `gf` | `-g`
ditroff | `nf` | `-n`
FORTRAN-tekst | `rf` | `-f`
troff | `tf` | `-f`
raster | `vf` | `-v`
platte tekst | `if` | geen, `-p`, of `-l`

In het voorbeeld waarbij `lpr -d` wordt gebruikt, moet voor de printer een optie `df` gedefinieerd staan in `/etc/printcap`.

Ondanks wat anderen mogelijk beweren, zijn formaten als FORTRAN-tekst en plot waarschijnlijk verouderd. Dit biedt de mogelijkheid een nieuwe betekenis te geven aan deze opties door zelf een filter te installeren. Stel dat direct Printerleaf-bestanden afgedrukt moeten worden (bestanden van het bureaubladpublicatieprogramma Interleaf), maar nooit plotbestanden worden afgedrukt. Dan kan een Printerleaf-conversiefilter geïnstalleerd worden onder de optie `gf` en gebruikers kunnen geïnstrueerd worden om `lpr -g` te gebruiken om Printerleaf-bestanden af te drukken.

##### 10.4.1.4.3. Conversiefilters installeren

Aangezien conversiefilters programma's zijn die niet onder de FreeBSD-basisinstallatie vallen, kunnen ze het best onder `/usr/local` geplaatst worden. De map `/usr/local/libexec` is een veelgebruikte locatie, omdat hier programma's te vinden zijn die alleen door LPD gebruikt worden. Gewone gebruikers hoeven ze nooit te gebruiken.

Om een conversiefilter te activeren, moet de bestandslocatie onder de juiste optie voor de betreffende printer in `/etc/printcap` opgegeven worden.

In het onderstaande voorbeeld wordt het DVI-conversiefilter toegevoegd onder de sectie van de printer `bamboo`. Hieronder staat opnieuw het voorbeeldbestand `/etc/printcap`, nu met de nieuwe optie `df` voor de printer `bamboo`:

    #
    #  /etc/printcap voor host rose - df-filter voor bamboo toegevoegd
    #
    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/ttyu5:ms#-parenb cs8 clocal crtscts:rw:\
            :if=/usr/local/libexec/psif:\
            :df=/usr/local/libexec/psdf:

Het DVI-filter is een shellscript met de naam `/usr/local/libexec/psdf`. Het script ziet er als volgt uit:

    #!/bin/sh
    #
    #  psdf - DVI naar PostScript afdrukfilter
    #  Geïnstalleerd in /usr/local/libexec/psdf
    #
    # Aangeroepen door lpd wanneer een gebruiker lpr -d uitvoert
    #
    exec /usr/local/bin/dvips -f | /usr/local/libexec/lprps "$@"

Dit script roept `dvips` in filtermodus aan (het `-f` argument) op de standaard uitvoer, de af te drukken opdracht. Vervolgens start het PostScript® afdrukfilter `lprps` (zie Platte tekst op PostScript®-printers afdrukken) met de argumenten die LPD aan het script doorgeeft. `lprps` gebruikt deze argumenten om de afgedrukte pagina's te administreren.

##### 10.4.1.4.4. Meer voorbeelden van conversiefilters

Er is geen vaste procedure om conversiefilters te installeren, er worden in deze sectie wat werkende voorbeelden gegeven. Gebruik deze als hulp bij het zelf maken van filters. Gebruik ze zonder aanpassingen indien mogelijk.

Dit voorbeeldscript is een raster (eigenlijk een GIF-bestand) conversiefilter voor een HP LaserJet III-Si printer:

    #!/bin/sh
    #
    #  hpvf - Converteer GIF-bestanden naar HP/PCL, druk vervolgens af
    #  Geïnstalleerd in /usr/local/libexec/hpvf

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

Het script converteert achtereenvolgens het GIF-bestand naar een PNM-bestand (portable anymap), een PGM-bestand (portable graymap), een PBM-bestand (portable bitmap) en tenslotte naar LaserJet/PCL formaat.

Een `/etc/printcap` bestand dat bovenstaand filter gebruikt ziet er als volgt uit:

    #
    #  /etc/printcap voor host orchid
    #
    teak|hp|laserjet|HP LaserJet 3Si:\
            :lp=/dev/lpt0:sh:sd=/var/spool/lpd/teak:mx#0:\
            :if=/usr/local/libexec/hpif:\
            :vf=/usr/local/libexec/hpvf:

Het volgende script is een conversiefilter voor troff-gegevens afkomstig van het groff-typesettingsysteem voor de PostScript®-printer `bamboo`:

    #!/bin/sh
    #
    #  pstf - Converteert groff's troffgegevens naar PS, drukt vervolgens af.
    #  Geïnstalleerd in /usr/local/libexec/pstf
    #
    exec grops | /usr/local/libexec/lprps "$@"

Bovenstaande script maakt eveneens gebruik van `lprps` om de communicatie met een printer af te handelen. Als een printer op een parallelle poort is aangesloten, ziet het er als volgt uit:

    #!/bin/sh
    #
    #  pstf - Converteert groff's troff naar PS, drukt vervolgens af.
    #  Geïnstalleerd in /usr/local/libexec/pstf
    #
    exec grops

Dat is alles. In `/etc/printcap` moet het volgende toegevoegd worden om het filter beschikbaar te maken:

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

Hieronder een voorbeeld waarvan FORTRAN-programmeurs waarschijnlijk tranen in hun ogen krijgen: een FORTRAN-tekstfilter voor een willekeurige printer die in staat is platte tekst af te drukken. Het filter wordt actief gemaakt voor `teak`:

    #!/bin/sh
    #
    # hprf - FORTRAN tekstfilter voor LaserJet 3si:
    # Geïnstalleerd in /usr/local/libexec/hprf
    #

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

De onderstaande regel wordt toegevoegd aan `/etc/printcap` voor de printer `teak` om het filter beschikbaar te maken:

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

Het laatste voorbeeld is wellicht complexer. Er wordt een DVI-filter toegevoegd voor de eerder genoemde LaserJet printer `teak`. Eerst het makkelijke gedeelte: in `/etc/printcap` wordt de locatie van het DVI-filter opgegeven:

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

Nu het moeilijke gedeelte: het schrijven van het filter. Daarvoor is een DVI-naar-LaserJet/PCL conversieprogramma nodig. De FreeBSD Portscollectie (zie Portscollectie) heeft er een: print/dvi2xx. Door deze port te installeren komt het programma dat nodig is beschikbaar, `dvilj2p`, waarmee DVI geconverteerd kan worden naar LaserJet IIp-, LaserJet III- en LaserJet 2000-formaten.

Het hulpprogramma `dvilj2p` maakt het filter `hpdf` redelijk complex, omdat `dvilj2p` niet van de standaard invoer kan lezen. Het wil werken met een bestandsnaam. Nog lastiger is dat de bestandsnaam moet eindigen op `.dvi`, zodat moeilijk gebruik gemaakt kan worden van `/dev/fd/0` als standaard. Dit probleem kan omzeild worden door een (symbolische) koppeling aan te maken van een tijdelijk bestand (eindigend op `.dvi`) naar `/dev/fd/0`. Hiermee wordt `dvilj2p` gedwongen van de standaard invoer te lezen.

De enige andere hobbel die genomen moet worden, is dat `/tmp` niet gebruikt kan worden als tijdelijke koppeling. Symbolische koppelingen zijn eigendom van de gebruiker en groep `bin`. Het filter wordt uitgevoerd door de gebruiker `daemon`. De map `/tmp` heeft het sticky-bit aan staan. Het filter kan de koppeling wel aanmaken, maar het is niet mogelijk de koppeling te verwijderen als de opdracht is uitgevoerd, omdat de koppeling eigendom is van een andere gebruiker.

In plaats hiervan maakt het filter een symbolische koppeling aan in de huidige werkmap, de wachtrijmap (zoals opgegeven in de optie `sd` in `/etc/printcap`). Dit is een perfecte plaats voor filters om hun werk te doen, zeker gezien er (soms) meer vrije schijfruimte is in de wachtrijmap dan onder `/tmp`.

Dit is het uiteindelijke filter:

    #!/bin/sh
    #
    #  hpdf - Druk DVI-gegevens af op een HP/PCL printer
    #  Geïnstalleerd in /usr/local/libexec/hpdf

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

    #
    #  Definieer een functie om tijdelijke bestanden op te ruimen. Deze
    #  staan in de huidige map; de wachtrijmap voor de printer.
    #
    cleanup() {
       rm -f hpdf$$.dvi
    }

    #
    #  Definieer een functie om fatale fouten te verwerken: geef de
    #  opgegeven boodschap weer en sluit af met 2. Afsluiten met 2 vertelt
    #  LPD niet nog eens te proberen de afdrukopdracht af te drukken.
    #
    fatal() {
        echo "$@" 1>&2
        cleanup
        exit 2
    }

    #
    #  Als de gebruiker de opdracht annuleert, stuurt LPD een SIGINT, dus
    #  ondervang SIGINT (en enkele andere signalen) om onze rommel op te
    #  ruimen.
    #
    trap cleanup 1 2 15

    #
    #  Voor de zekerheid bestaande tijdelijke bestanden opruimen
    #
    cleanup

    #
    #  Koppel het DVI-invoerbestand aan de standaard invoer (het af te
    #  drukken bestand).
    #
    ln -s /dev/fd/0 hpdf$$.dvi || fatal "Cannot symlink /dev/fd/0"

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

    #
    #  Converteer en druk af.  De retourneerwaarde van dvilj2p lijkt niet
    #  betrouwbaar, dus negeren we het.
    #
    dvilj2p -M1 -q -e- dfhp$$.dvi

    #
    #  Opruimen en afsluiten
    #
    cleanup
    exit 0

##### 10.4.1.4.5. Automatische conversie: een alternatief voor conversiefilters

Al deze conversiefilters bieden vele mogelijkheden voor afdrukomgevingen, maar dwingen de gebruiker aan te geven (op de lpr(1) commandoregel) welk filter gebruikt moet worden. Als gebruikers niet zo vaardig zijn in het gebruik van computers, wordt het al snel vervelend steeds aan te moeten geven welk filter gebruikt moet worden. Vervelender is echter wanneer een gebruiker een verkeerd filter gebruikt voor een bepaald bestandsformaat. Het resultaat kan zijn dat een printer honderden pagina's papier uitspuugt.

In plaats van het installeren van conversiefilters, is het te proberen om het (standaard) tekstfilter het bestandstype van het af te drukken bestand te laten detecteren en dan automatisch het juiste conversiefilter aan te laten roepen. Programma's als `file` kunnen hierbij handig zijn. Voor sommige bestandsformaten kan het moeilijk zijn de verschillen te ontdekken en voor deze bestanden kan alsnog een conversiefilter beschikbaar worden gesteld.

De FreeBSD Portscollectie heeft een tekstfilter dat automatisch converteert genaamd `apsfilter` (print/apsfilter). Het detecteert platte tekst, PostScript® en DVI-bestanden, voert de juiste conversie uit en druk de bestanden af.

#### 10.4.1.5. Uitvoerfilters

Het wachtrijsysteem LPD ondersteunt een ander type filter waar nog geen aandacht aan is besteed: een uitvoerfilter. Een uitvoerfilter is bedoeld om alleen platte tekst af te drukken, net als een tekstfilter, maar met veel vereenvoudigingen. Wanneer een uitvoerfilter wordt gebruikt, maar geen tekstfilter, dan:

- start LPD een uitvoerfilter voor de gehele opdracht, in plaats van voor elk bestand in de opdracht;

- biedt LPD het uitvoerfilter niet de voorziening van het identificeren van het begin of eind van de bestanden in de afdrukopdracht;

- stuurt LPD de gebruikersnaam en de hostnaam niet door aan het filter. Het is dus niet bedoeld om een afdrukadministratie bij te houden. In feite zijn er maar twee argumenten:

  `filter-name` -w`width` -l`length`

  Hierbij is `width` afkomstig van de optie `pw` en `length` afkomstig van de optie `pl` voor de betreffende printer.

De eenvoud van een uitvoerfilter is verleidelijk. Als elk bestand in een afdrukopdracht op een nieuwe pagina moet beginnen, is een uitvoerfilter niet geschikt. In dat geval dient een tekstfilter (ook wel invoerfilter) gebruikt te worden (zie Tekstfilter installeren. Verder is een uitvoerfilter eigenlijk veel ingewikkelder, omdat de te verwerken bytestroom gecontroleerd moet worden op speciale tekens en steeds signalen naar zichzelf moet sturen in opdracht van LPD.

Een uitvoerfilter is noodzakelijk als voorbladen gewenst zijn en het nodig is om escape-reeksen of andere initialisatietekens te sturen voor het afdrukken van het voorblad. Maar het is tevens nutteloos als het voorblad voor rekening van de afkomstige gebruiker moet komen, aangezien LPD geen gebruiker of hostinformatie naar het uitvoerfilter stuurt.

Op een enkele printer staat LPD het gebruik van zowel een uitvoerfilter als van een tekst of andere filter toe. In deze gevallen start LPD het uitvoerfilter alleen voor het afdrukken van het voorblad (zie Voorbladen). LPD verwacht vervolgens van het uitvoerfilter dat deze zichzelf stopt door twee bytes naar het filter te sturen: ASCII 031 gevolgd door ASCII 001. Als een uitvoerfilter deze twee bytes ziet (031, 001), moet die stoppen door een `SIGSTOP` naar zichzelf te sturen. Als LPD klaar is met het uitvoeren van alle andere filters, dan herstart deze het uitvoerfilter door er een `SIGCONT` naar toe te sturen.

Als er wel een uitvoerfilter, maar geen tekstfilter is en LPD is niet bezig met het verwerken van een opdracht met platte tekst, dan gebruikt LPD het uitvoerfilter voor het afdrukken van de opdracht. Zoals eerder vermeld, drukt het uitvoerfilter elk bestand van de opdracht achter elkaar af zonder pagina-einden of andere signalen voor paginavoortgang. Dit is waarschijnlijk niet gewenst. In bijna alle gevallen is een tekstfilter nodig.

Het programma `lpf`, dat eerder geïntoduceerd is als tekstfilter, kan ook worden uitgevoerd als uitvoerfilter. Als een ad-hoc uitvoerfilter nodig is, maar het schrijven van de bytedetectie en signaalverzending code niet wenselijk is, dan is `lpf` het proberen waard. `lpf` kan ook opgenomen worden in een shellscript om initialisatiecode af te handelen die eventueel nodig is voor een printer.

#### 10.4.1.6. `lpf`: een tekstfilter

Het programma `/usr/libexec/lpr/lpf` uit de gecompileerde FreeBSD-distributie is een tekstfilter (invoerfilter) die uitvoer kan inspringen (een opdracht gegeven met `lpr -i`), karakters onveranderd kan doorlaten (een opdracht gegeven met `lpr -l`), de printpositie voor backspaces en tabs in de opdracht kan aanpassen en afgedrukte pagina's kan administreren. Het kan ook functioneren als uitvoerfilter.

Het filter `lpf` is geschikt voor vele afdrukomgevingen. Hoewel het zelf niet in staat is initialisatiesequenties naar een printer te sturen, is het vrij eenvoudig om een shellscript te schrijven dat de initialisatie doet en vervolgens `lpf` aanroept.

Als `lpf` afgedrukte pagina's moet administreren, is het nodig om de juiste waarden in te vullen voor de opties `pw` en `pl` in het bestand `/etc/printcap`. Deze waarden worden gebruikt om te bepalen hoeveel tekst er op een pagina past en hoeveel pagina's er in een afdrukopdracht zijn afgedrukt. Zie Printergebruik administreren voor meer informatie.

### 10.4.2. Voorbladen

Als er veel gebruikers zijn die allemaal verschillende printers gebruiken, dan is het te overwegen gebruik te maken van voorbladen als noodzakelijk kwaad.

Voorbladen, in het Engels ook wel bekend als banner of burst pagina's, identificeren wie een bepaalde opdracht heeft afgedrukt. Ze worden meestal bedrukt met grote, dikgedrukte letters, eventueel met een decoratieve rand, zodat ze in een stapel afdrukken opvallen tussen de afgedrukte documenten. Ze maken het gebruikers mogelijk hun afdrukopdracht snel te vinden. Het nadeel van het gebruik van voorbladen is dat er een extra blad moet worden afgedrukt voor elke opdracht, waarmee hun nut niet langer duurt dan een paar minuten. Uiteindelijk belanden ze in een papierbak of afvalberg. Voorbladen gaan vooraf aan elke opdracht, niet aan elk bestand in een opdracht, waardoor de verspilling beperkt blijft.

Het LPD-systeem kan automatisch voorbladen afdrukken als een printer direct platte tekst kan afdrukken. In geval van een PostScript®-printer, is het nodig een extern programma aan te roepen om een voorblad te genereren (zie Voorbladen op PostScript®-printers.

#### 10.4.2.1. Voorbladen afdrukken

In de sectie Eenvoudige printerinstallatie is het afdrukken van voorbladen uitgeschakeld door de optie `sh` (“suppress header”) in het bestand `/etc/printcap` op te geven. Om wel voorbladen af te drukken, hoeft alleen de optie `sh` verwijderd te worden.

Dit klinkt wat al te makkelijk, of niet?

Dat klopt. Het kan nodig zijn een uitvoerfilter op te geven die initialisatiestrings naar een printer stuurt. Hier is een voorbeeld uitvoerfilter voor HP PCL-compatible printers:

    #!/bin/sh
    #
    #  hpof - Uitvoerfilter voor HP PCL-compatible printers
    #  Geïnstalleerd in /usr/local/libexec/hpof

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

Geef de locatie van het uitvoerfilter op met de optie `of`. Zie Uitvoerfilters voor meer informatie.

Hier is een voorbeeldbestand `/etc/printcap` voor de printer `teak` die eerder is geïntroduceerd;. Het afdrukken van voorbladen is geactiveerd en bovenstaande uitvoerfilter is toegevoegd:

    #
    #  /etc/printcap voor host orchid
    #
    teak|hp|laserjet|HP 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:

Als gebruikers nu een opdracht sturen naar `teak`, wordt er bij elke opdracht een voorblad afgedrukt. Als gebruikers liever willen zoeken naar hun afdrukken, dan kunnen ze de voorbladen onderdrukken door de opdracht te geven met het commando `lpr -h`. Zie Voorbladopties voor meer opties voor lpr(1).

### Opmerking:

LPD drukt een karakter voor pagina-einde af na elk voorblad. Als een printer een ander teken of sequentie gebruikt voor het beëindigen van een pagina, dan kan dit opgeven worden met de optie `ff` in `/etc/printcap`.

#### 10.4.2.2. Voorbladen beheren

Door het afdrukken van voorbladen aan te zetten, produceert LPD een lang voorblad waarop in grote letters de gebruiker, host en opdracht te lezen zijn. Hier volgt een voorbeeld (`kelly` heeft de opdracht “outline” afgedrukt vanaf host `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 geeft een paginabegin na deze tekst, zodat de opdracht op een nieuwe pagina begint (tenzij de optie `sf` (suppress form feeds, “onderdruk paginabegin”) is toegevoegd bij de desbetreffende printer in `/etc/printcap`).

Als dit wenselijk is, kan LPD ook een korte tekst op het voorblad afdrukken; geef hiervoor de optie `sb` (short banner, “kort voorblad”) op in het bestand `/etc/printcap`. Het voorblad ziet er dan als volgt uit:

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

Standaard drukt LPD het voorblad als eerste af en vervolgens de opdracht. Om dat om te keren, moet de optie `hl` (header last, “voorblad laatst”) in `/etc/printcap` worden opgeven.

#### 10.4.2.3. Voorbladen administreren

Het gebruik van LPD's ingebouwde voorbladen dwingt een bepaald paradigma af wat betreft het administreren van printergebruik: voorbladen moeten gratis zijn.

Waarom?

Omdat het uitvoerfilter het enige externe programma is dat controle heeft als het voorblad afgedrukt wordt dat het gebruik zou kunnen administreren. Het heeft echter geen beschikking over informatie over gebruiker of host of een administratiebestand. Het heeft dus geen idee wie voor het gebruik moet worden belast. Het volstaat ook niet om gewoon “het aantal pagina's met één op te hogen” door het tekstfilter of een van de conversiefilters (dat wel beschikt over gebruiker- en hostinformatie) te veranderen, omdat gebruikers het afdrukken van een voorblad kunnen onderdrukken met `lpr -h`. Ze worden dan aangeslagen voor voorbladen die niet zijn afgedrukt. Milieubewuste gebruikers gebruiken vast `lpr -h`, maar dit kan niet worden afgedwongen.

Het is ook niet voldoende om elk filter zijn eigen voorblad te laten genereren (om zo het gebruik te kunnen administreren). Als gebruikers het afdrukken van voorbladen willen onderdrukken met `lpr -h`, krijgen ze toch een voorblad en worden er ook voor belast, aangezien LPD geen kennis over de optie `-h` doorgeeft aan de filters.

Wat zijn dan de mogelijkheden?

- Accepteer het paradigma van LPD en maak voorbladen gratis;

- Installeer een alternatief voor LPD, zoals LPRng. In Alternatieven voor het standaard wachtrijsysteem staat meer over andere afdruksoftware die in plaats van LPD geïnstalleerd kan worden;

- Schrijf een slim uitvoerfilter. Gewoonlijk is een uitvoerfilter bedoeld om niet meer te doen dan het initialiseren van een printer of wat eenvoudige karakterconversie. Het is geschikt voor voorbladen en opdrachten met platte tekst (als er een tekstfilter is). Maar als er een tekstfilter is voor opdrachten met platte tekst, dan start LPD het uitvoerfilter alleen voor voorbladen. Het uitvoerfilter kan dan het voorblad dat LPD genereert analyseren om te bepalen welke gebruiker en host belast moeten worden voor het afdrukken van het voorblad. Het enige probleem is dat het uitvoerfilter nog steeds niet weet in welk bestand het gebruik moet worden bijgehouden (de naam van het bestand opgegeven in de `af` wordt niet meegegeven), maar als een bekend bestand gebruikt wordt, kan dit in het uitvoerfilter worden opgeven. Om het parsen af te handelen kan gebruik gemaakt worden van de optie `sh` (short header, “kort voorblad”) in `/etc/printcap`. Dit kan echter wat omslachtig zijn en gebruikers waarderen zeker de meer gulle systeembeheerder die voorbladen gratis maakt.

#### 10.4.2.4. Voorbladen op PostScript®-printers

Zoals hierboven beschreven, kan LPD een voorblad in platte tekst genereren, dat geschikt is voor de meeste printers. Natuurlijk kan PostScript® platte tekst niet direct afdrukken, zodat de voorbladfunctie van LPD nutteloos is.

Een voor de hand liggende manier om voorbladen te krijgen, is elk conversiefilter en tekstfilter zijn eigen voorblad te laten genereren. De filters moeten gebruik maken van de argumenten gebruiker en host om een geschikt voorblad te genereren. Het nadeel van deze methode is dat gebruikers altijd een voorblad krijgen, ook wanneer zij een opdracht geven met `lpr -h`.

Deze methode wordt nader beschreven. Het volgende script heeft drie argumenten (gebruikersnaam, hostnaam en de naam van de opdracht) en maakt een eenvoudig PostScript®-voorblad:

    #!/bin/sh
    #
    #  make-ps-header - genereer een PostScript-voorblad op stdout
    #  Geïnstalleerd in /usr/local/libexec/make-ps-header
    #

    #
    #  Dit zijn PostScript-eenheden (72 in een inch). Pas dit aan voor A4
    #  of het gebruikte formaat:
    #
    page_width=612
    page_height=792
    border=72

    #
    #  Controleer argumenten
    #
    if [ $# -ne 3 ]; then
        echo "Usage: `basename $0` <user> <host> <job>" 1>&2
        exit 1
    fi

    #
    #  Bewaar deze, voornamelijk voor de leesbaarheid in de PostScript®-code.
    #
    user=$1
    host=$2
    job=$3
    date=`date`

    #
    #  Stuur de PostScript®-code naar stdout.
    #
    exec cat <<EOF
    %!PS

    %
    %  Vermijd conflicten met de opdracht van de gebruiker die volgt.
    %
    save

    %
    %  Maak een dikke, onaangename border in de marge van het papier.
    %
    $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

    %
    %  Toon de gebruikersnaam duidelijk, groot en prominent
    %
    /Helvetica-Bold findfont 64 scalefont setfont
    $page_width ($user) stringwidth pop sub 2 div $page_height 200 sub moveto
    ($user) show

    %
    %  Nu volgen de saaie bijzonderheden
    %
    /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

    %
    % Dat is alles
    %
    restore
    showpage
    EOF

Nu kan zowel het conversiefilter als het tekstfilter dit script aanroepen om eerst een voorblad te genereren en vervolgens de opdracht van de gebruiker af te drukken. Hier volgt het eerder gebruikte DVI-conversieprogramma, aangepast om een voorblad te maken:

    #!/bin/sh
    #
    #  psdf - DVI naar PostScript printfilter
    #  Geïnstalleerd in /usr/local/libexec/psdf
    #
    #  Aangeroepen door lpd, wanneer de gebruiker lpr -d uitvoert
    #

    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

Merk op hoe het filter eerst de argumentenlijst moet nagaan om te bepalen wat de gebruikers- en hostnaam zijn. Dit is gelijk voor de andere conversiefilters. Het tekstfilter heeft echter een andere verzameling argumenten (zie Hoe filters werken).

Zoals eerder is beschreven, is het in bovenstaande opzet, hoewel deze simpel is, niet mogelijk “voorbladen te onderdrukken” (de optie `-h` in `lpr`). Als gebruikers een boom willen sparen (of een paar centen bij betaalde voorbladen) dan is dit dus niet mogelijk, aangezien elk filter een voorblad afdrukt voor iedere opdracht.

Om gebruikers in staat te stellen per opdracht voorbladen te onderdrukken, moet gebruik gemaakt worden van de truc uit Voorbladen administreren: schrijf een uitvoerfilter dat het door LPD gegenereerde voorblad inleest en een PostScript®-versie genereert. Als de gebruiker de opdracht geeft met `lpr -h`, dan genereert LPD geen voorblad en het uitvoerfilter ook niet. Anders leest het uitvoerfilter de tekst van LPD in en stuurt een geschikt voorblad in PostScript® naar de printer.

Voor een PostScript®-printer op een seriële lijn kan gebruik gemaakt worden van `lprps`, dat met een uitvoerfilter wordt geleverd en het bovenstaande kan doen. Voorbladen worden door `psof` niet geteld.

### 10.4.3. Afdrukken via het netwerk

FreeBSD ondersteunt afdrukken via het netwerk: het sturen van opdrachten naar printers op afstand. Afdrukken via een netwerk betekent over het algemeen twee verschillende dingen:

- Het benaderen van een printer aangesloten op een andere computer. Een printer met een conventionele seriële of parallelle verbinding wordt op een bepaalde computer geïnstalleerd. Vervolgens wordt LPD zodanig ingesteld dat afdrukken vanaf andere computers in het netwerk mogelijk is. In Printers geïnstalleerd op andere hosts staat hoe dit te doen.

- Het benaderen van een printer die direct is aangesloten op een netwerk. Een printer heeft een netwerkinterface naast (of in plaats van) een gewone seriële of parallelle poort. Zo een printer kan als volgt werken:

  - Het begrijpt het LPD protocol en kan zelfs opdrachten van andere hosts in de wachtrij plaatsen. In dit geval werkt een printer als een gewone host die LPD heeft draaien. Volg de procedure in Printers geïnstalleerd op andere hosts om een dergelijke printer te installeren

  - Het kan zijn dat een printer een netwerkverbinding ondersteunt. In dit geval kan een printer worden “aangesloten” op een bepaalde host op het netwerk door deze host verantwoordelijk te maken voor het plaatsen van opdrachten in een wachtrij en het versturen van opdrachten naar de printer. In Printers met netwerkinterfaces staan enkele suggesties om zulke printers te installeren.

#### 10.4.3.1. Printers geïnstalleerd op andere hosts

Het wachtrijsysteem LPD heeft een ingebouwde mogelijkheid om opdrachten naar andere hosts te sturen die ook LPD draaien (of een systeem dat compatibel is met LPD). Deze eigenschap maakt het mogelijk om een printer op een host te installeren en deze toegankelijk te maken voor andere hosts. Het werkt ook met printers die over een netwerkinterface beschikken en het LPD-protocol begrijpen.

Om dit soort afdrukken op afstand mogelijk te maken, moet een printer eerst op een host geïnstalleerd worden, de printerhost, door de printerinstallatie te volgen als beschreven in Eenvoudige printerinstallatie. Stel desgewenst de printer in voor geavanceerde taken volgens Geavanceerde printerinstallatie. Test de printer en controleer of deze werkt met eventueel speciaal ingestelde opties voor LPD. De lokale host moet geautoriseerd zijn om de LPD-dienst op de verre host te gebruiken (zie Opdrachten van hosts op afstand beperken).

Als een printer een netwerkinterface heeft die compatibel is met LPD, dan is de printerhost in onderstaande beschrijving de printer zelf en de printernaam is de naam die voor de printer is ingesteld. Meer informatie staat in de documentatie bij de printer en/of de printernetwerkinterface.

### Tip:

Bij een HP LaserJet voert de printernaam `text` automatisch de CRLF-conversie uit. Het is dan niet nodig het script `hpif` te gebruiken.

Op hosts die toegang moeten krijgen tot de printer, moet in `/etc/printcap` een regel worden toegevoegd met het volgende:

1. Geef de regel een willekeurige naam. Om het eenvoudig te houden kunnen wellicht het beste dezelfde namen en aliassen worden gebruikt als op de printerhost;

2. Laat de optie `lp` expliciet leeg (`:lp=:`);

3. Maak een wachtrijmap aan en geef de locatie op met de optie `sd`. LPD slaat hier afdrukopdrachten op alvorens ze naar de printerhost te sturen;

4. Geef de naam van de printerhost op met de optie `rm`;

5. Geef de naam van de printer op de printerhost op met de optie `rp`.

Dit is het. Conversiefilters, paginadimensies, enzovoort, hoeven niet in `/etc/printcap` opgegeven te worden.

Hier volgt een voorbeeld. De host `rose` heeft twee printers: `bamboo` en `rattan`. Gebruikers op de host `orchid` krijgen toegang tot deze printers. Hier volgt `/etc/printcap` voor `orchid` (uit Voorbladen afdrukken). Er stond in het bestand al een regel voor de printer `teak`. Voor de twee printers op de host `rose` zijn twee regels toegevoegd:

    #
    #  /etc/printcap voor host orchid - printers (op afstand) op rose toegevoegd
    #

    #
    #  teak is lokaal; het is direct aangesloten op orchid:
    #
    teak|hp|laserjet|HP 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 aangesloten op rose; stuur opdrachten voor rattan naar rose:
    #
    rattan|line|diablo|lp|Diablo 630 Line Printer:\
            :lp=:rm=rose:rp=rattan:sd=/var/spool/lpd/rattan:

    #
    #  bamboo is ook aangesloten op rose:
    #
    bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
            :lp=:rm=rose:rp=bamboo:sd=/var/spool/lpd/bamboo:

Op `orchid` moeten wachtrijmappen worden aangemaakt:

    # 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

Nu kunnen gebruikers op `orchid` afdrukken op `rattan` en `bamboo`. Een gebruiker op `orchid` geeft bijvoorbeeld de volgende invoer:

    % lpr -P bamboo -d sushi-review.dvi

Dan kopieert LPD op `orchid` de opdracht naar de wachtrijmap `/var/spool/lpd/bamboo` en ziet dat het een DVI-opdracht is. Zodra de host `rose` ruimte heeft in zijn wachtrijmap `bamboo`, sturen de twee LPD's het bestand naar `rose`. Het bestand wacht in de wachtrij van `rose` totdat het succesvol is afgedrukt. Het wordt geconverteerd naar PostScript® (aangezien `bamboo` een PostScript®-printer is) op `rose`.

#### 10.4.3.2. Printers met netwerkinterfaces

Netwerkkaarten voor printers zijn er in twee versies: een versie die een wachtrij nabootst (de duurdere versies), of versies die alleen de mogelijkheid geven om er informatie naar te sturen alsof het een seriële of parallelle poort is (de goedkopere versies). In Printers geïnstalleerd op andere hosts wordt het voor de duurdere beschreven.

Het formaat van `/etc/printcap` maakt het mogelijk om op te geven welke seriële, of parallelle poort gebruikt moet worden en (in geval van een seriële poort) de baud-snelheid, of er communicatie moet worden toegepast, vertragingen voor tabs, conversies voor nieuwe regelkarakters en meer. Er is geen mogelijkheid om een verbinding met een printer op te geven die op een TCP/IP of andere netwerkpoort luistert.

Om informatie naar een netwerkprinter te sturen, is het nodig een programma te ontwikkelen dat door tekst- en conversiefilters kan worden aangeroepen. Hier volgt een voorbeeld: het script `netprint` stuurt alle informatie van de standaard invoer naar een netwerkprinter. Als eerste argument wordt de hostnaam van de printer opgegeven en als tweede argument het poortnummer waarmee de verbinding moet worden opgezet. Er wordt alleen eenrichtingcommunicatie ondersteund (FreeBSD naar printer). Veel netwerkprinters ondersteunen tweewegcommunicatie. Het kan wenselijk zijn hiervan gebruik te maken (om printerstatus op te vragen, statistieken bij te houden, enzovoort).

    #!/usr/bin/perl
    #
    #  netprint - Tekstfilter voor printer aangesloten op het netwerk
    #  Geïnstalleerd 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;

Dit script kan vervolgens in verschillende filters gebruikt worden. Stel dat een Diablo 750-N matrixprinter op het netwerk is aangesloten. Op poort 5100 accepteert de printer informatie om af te drukken. De hostnaam van de printer is `scrivener`. Hier volgt het tekstfilter voor de printer:

    #!/bin/sh
    #
    #  diablo-if-net - Tekstfilter voor Diablo printer 'scrivener' luistert
    #  op poort 5100. Geïnstalleerd in /usr/local/libexec/diablo-if-net
    #
    exec /usr/libexec/lpr/lpf "$@" | /usr/local/libexec/netprint scrivener 5100

### 10.4.4. Printergebruik beperken

Nu volgt informatie over het beperken van printergebruik. Het LPD-systeem maakt het mogelijk te bepalen wie er toegang heeft tot een printer, zowel lokaal als op afstand, of meerdere kopieën afgedrukt mogen worden, hoe lang opdrachten mogen zijn en hoe lang wachtrijen mogen worden.

#### 10.4.4.1. Meerdere kopieën beperken

Het LPD systeem maakt het heel makkelijk voor gebruikers om meerdere afdrukken van een bestand te maken. Gebruikers kunnen opdrachten afdrukken met bijvoorbeeld `lpr -#5` en krijgen dan vijf kopieën van elk bestand in de opdracht. De systeembeheerder kan beslissen of dit wenselijk is.

Wanneer meerdere kopieën onwenselijk zijn, kan de optie `-#` van lpr(1) worden uitgeschakeld door de optie `sc` in `/etc/printcap` op te nemen. Als gebruikers opdrachten versturen met de optie `-#`, zien ze het volgende:

    lpr: multiple copies are not allowed

Als het mogelijk is van andere hosts af te drukken (zie Printers geïnstalleerd op andere hosts), moet de optie `sc` ook in `/etc/printcap` van de andere hosts aanwezig zijn. Anders kunnen gebruikers nog steeds multi-kopie opdrachten van andere hosts sturen.

Hier volgt een voorbeeld. Hieronder staat `/etc/printcap` voor de host `rose`. De printer `rattan` is redelijk krachtig, dus meerdere kopieën zijn toegestaan. De laserprinter `bamboo` is wat gevoeliger, dus meerdere kopieë zijn uitgeschakeld door de optie `sc` toe te voegen:

    #
    #  /etc/printcap voor host rose - beperk meerdere kopieën op 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/ttyu5:ms#-parenb cs8 clocal crtscts:rw:\
            :if=/usr/local/libexec/psif:\
            :df=/usr/local/libexec/psdf:

Nu moet ook de optie `sc` worden toegevoegd in `/etc/printcap` van host `orchid` (tegelijk worden meerdere kopieën voor de printer `teak` uitgeschakeld):

    #
    #  /etc/printcap voor host orchid - geen meerdere kopieën voor lokale
    #  printer teak of printer op afstand bamboo
    teak|hp|laserjet|HP 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:

Door de optie `sc` te gebruiken, wordt het gebruik van `lpr -#i` voorkomen, maar dat weerhoudt gebruikers er nog steeds niet van om lpr(1) meerdere keren te aanroepen of meerdere keren hetzelfde bestand te versturen in een opdracht:

    % lpr voorverkoop.teken voorverkoop.teken voorverkoop.teken voorverkoop.teken voorverkoop.teken

Er zijn vele manieren om dit misbruik te voorkomen (onder andere door het te negeren), welke vrij zijn om te verkennen.

#### 10.4.4.2. Printertoegang beperken

Door gebruik te maken van het UNIX® groepmechanisme en de optie `rg` in `/etc/printcap` kan geregeld worden wie er op welke printer kan afdrukken. De gebruikers die toegang hebben tot een printer moeten in een groep worden geplaatst en deze groep moet in de optie `rg` worden genoemd.

Als gebruikers buiten de groep (inclusief `root`) naar de beheerde printer proberen te printen, worden ze begroet met het volgende bericht:

    lpr: Not a member of the restricted group

Net als met de optie `sc` (suppress multiple copies: onderdruk meerdere kopieën) moet `rg`, indien wenselijk, ook op andere hosts worden opgegeven die ook toegang hebben tot printers (zie Printers geïnstalleerd op andere hosts).

In het volgende voorbeeld heeft iedereen toegang tot de printer `rattan`, maar alleen gebruikers in de groep `artists` kunnen gebruik maken van `bamboo`. Hier volgt het bekende `/etc/printcap` voor de host `rose`:

    #
    #  /etc/printcap voor host rose - beperkte toegang voor groep 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/ttyu5:ms#-parenb cs8 clocal crtscts:rw:\
            :if=/usr/local/libexec/psif:\
            :df=/usr/local/libexec/psdf:

De andere voorbeeldbestanden `/etc/printcap` (voor de host `orchid`) worden niet aangepast. Natuurlijk kan iedereen op `orchid` afdrukken op `bamboo`. Het kan zijn dat er sowieso alleen bepaalde gebruikers op `orchid` zijn toegestaan en dat deze gebruikers toegang mogen hebben tot de printer. Of wellicht niet.

### Opmerking:

Er kan per printer slechts één groep worden opgegeven.

#### 10.4.4.3. Grootte van afdrukopdrachten bepalen

Als veel gebruikers toegang hebben tot printers kan het nodig zijn een limiet op te geven voor de grootte van de bestanden die gebruikers naar een printer kunnen sturen. Er is immers slechts beperkte ruimte op het bestandssysteem en er moet ook voldoende ruimte zijn voor opdrachten van andere gebruikers.

LPD heeft de mogelijkheid om met de optie `mx` een limiet op te geven voor het maximum aantal bytes van een bestand in een afdrukopdracht. De eenheden worden opgegeven in `BUFSIZ` blokken, die 1024 bytes groot zijn. Een nul voor deze optie betekent geen limiet aan de bestandsgrootte. Als de optie wordt weggelaten, wordt een standaardlimiet van 1000 blokken gebruikt.

### Opmerking:

De limiet heeft betrekking op de bestanden in een opdracht, niet op de totale grootte van een opdracht.

LPD weigert een bestand dat groter is dan de opgegeven limiet niet. In plaats daarvan plaatst het zo veel mogelijk van het bestand op de wachtrij, om dit vervolgens af te drukken. De rest wordt genegeerd. Of dit gedrag wenselijk is, is onderwerp van debat.

Nu worden limieten voor de voorbeeldprinters `rattan` en `bamboo` opgegeven. Aangezien de PostScript®-bestanden van die `artists` nogal groot kunnen worden, krijgen ze een limiet van vijf megabyte opgelegd. Er wordt geen limiet opgelegd voor de platte tekst printer:

    #
    #  /etc/printcap voor host rose
    #

    #
    #  Geen limiet op opdrachtgrootte:
    #
    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:

    #
    #  Limiet van vijf megabyte:
    #
    bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
            :sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:mx#5000:\
            :lp=/dev/ttyu5:ms#-parenb cs8 clocal crtscts:rw:\
            :if=/usr/local/libexec/psif:\
            :df=/usr/local/libexec/psdf:

Ook hier zijn de limieten alleen van toepassing op lokale gebruikers. Als toegang tot deze printers van andere hosts mogelijk is, worden deze gebruikers niet beperkt. Het is daarom nodig de optie `mx` ook in de `/etc/printcap` van de betreffende hosts op te geven. In Printers geïnstalleerd op andere hosts staat meer informatie over afdrukken op andere hosts.

Er is een andere gespecialiseerde manier om opdrachtgrootte voor printers op afstand te beperken (zie Opdrachten van hosts op afstand beperken.

#### 10.4.4.4. Opdrachten van hosts op afstand beperken

Het wachtrijsysteem LPD beschikt over verschillende methoden om afdrukopdrachten van hosts op afstand te beperken:

Hostbeperkingen

  Met de bestanden `/etc/hosts.equiv` en `/etc/hosts.lpd` kan worden ingesteld van welke hosts op afstand een lokale LPD-opdracht wordt geaccepteerd. LPD controleert of een inkomend verzoek afkomstig is van een host die wordt genoemd in een van deze bestanden. Zo niet, dan weigert LPD het verzoek.

  Het formaat van deze bestanden is eenvoudig: één host per regel. `/etc/hosts.equiv` wordt ook gebruikt door het protocol ruserok(3) en heeft invloed op programma's als rsh(1) en rcp(1). Voorzichtigheid is dus geboden.

  Als voorbeeld volgt hier `/etc/hosts.lpd` voor de host `rose`:

      orchid
      violet
      madrigal.fishbaum.de

  Dit betekent dat `rose` verzoeken accepteert van de hosts `orchid`, `violet` en `madrigal.fishbaum.de`. Voor iedere andere host die verbinding probeert te maken met LPD op `rose`, wordt de opdracht geweigerd.

Omvangbeperkingen

  De hoeveelheid vrije ruimte die over moet blijven op een bestandssysteem waar een wachtrij zich bevindt kan ook worden ingesteld. Hiervoor moet een bestand met de naam `minfree` in de wachtrijmap worden aangemaakt. In dit bestand kan een getal worden gezet dat het aantal schijfblokken (512 bytes) aan vrije ruimte aangeeft dat beschikbaar moet blijven wil een opdracht worden geaccepteerd.

  Hiermee kan worden gegarandeerd dat gebruikers op afstand een bestandssysteem niet vol kunnen schrijven. Ook kan hierdoor een soort voorrang worden gegeven aan lokale gebruikers: zij kunnen nog opdrachten plaatsen als de vrije schijfruimte al lang beneden de opgegeven limiet uit `minfree` is gekomen.

  Als voorbeeld wordt een bestand `minfree` voor de printer `bamboo` toegevoegd. In `/etc/printcap` staat de juiste wachtrijmap:

      bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
              :sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:mx#5000:\
              :lp=/dev/ttyu5:ms#-parenb cs8 clocal crtscts:rw:mx#5000:\
              :if=/usr/local/libexec/psif:\
              :df=/usr/local/libexec/psdf:

  De wachtrijmap wordt opgegeven met de optie `sd`. Er wordt een limiet van drie megabyte ingesteld (wat gelijk staat aan 6144 schijfblokken) voor de hoeveelheid vrije schijfruimte die op het bestandssysteem beschikbaar moet zijn voordat LPD een opdracht op afstand accepteert:

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

Gebruikersbeperkingen

  Met de optie `rs` in `/etc/printcap` kan worden geregeld welke gebruikers op afstand kunnen afdrukken op lokale printers. Als `rs` voorkomt voor een lokale printer accepteert LPD opdrachten van hosts op afstand als de gebruiker die de opdracht wil plaatsen ook een account heeft met dezelfde gebruikersnaam op de lokale host. Anders weigert LPD de opdracht.

  Deze optie is met name nuttig in een omgeving waar (bijvoorbeeld) verschillende afdelingen een netwerk delen en gebruikers de grenzen van de afdeling overschrijden. Door ze een account te geven op een systeem kunnen ze de aangesloten printers gebruiken vanaf het systeem van hun eigen afdeling. Wanneer ze alleen gebruik mogen maken van de printers en niet van overige diensten op de computer, kunnen “tokenaccounts” worden aangemaakt, zonder thuismap en met een nutteloze shell als `/usr/bin/false`.

### 10.4.5. Printergebruik administreren

Het kan nodig zijn om afdrukken te doorbelasten. Inkt en papier kosten geld en er zijn onderhoudskosten. Printers zitten vol met bewegende delen en hebben de neiging kapot te gaan. Nu is er gekeken naar de printers, het gebruikerspatroon en de onderhoudskosten en op basis hiervan is een prijs vastgesteld per pagina (of per centimeter, per meter, of per wat dan ook). Hoe wordt nu een administratie bijgehouden van gemaakte afdrukken?

Het slechte nieuws is dat het wachtrijsysteem LPD hierbij niet echt helpt. Het administreren van afdrukken is erg afhankelijk van het type printer, het afdrukformaat en de wensen die een systeembeheerder heeft ten aanzien van het doorbelasten van printergebruik.

Om het administreren te implementeren, is het nodig om aanpassingen te maken in de tekstfilter (om platte tekst opdrachten te belasten) en de conversiefilters (om opdrachten in andere bestandsformaten te belasten), om pagina's te tellen, of de printer te vragen hoeveel pagina's er zijn afgedrukt. Het volstaat niet om het eenvoudige uitvoerfilter te gebruiken, aangezien dit niet in staat is het gebruik te administreren. Zie Filters.

In het algemeen zijn er twee manieren om gebruik te administreren:

- Periodiek administreren is de meer gebruikelijke manier, omdat het waarschijnlijk makkelijker is. Als iemand een opdracht afdrukt, schrijft het filter de gebruiker, host en het aantal pagina's in een administratiebestand. Elke maand, semester, jaar, of een andere gewenste periode kunnen de administratiebestanden verzameld worden om het aantal afgedrukte pagina's op te tellen en het gebruik in rekening te brengen. De logboekbestanden kunnen vervolgens geschoond worden, zodat met een schone lei de volgende periode begonnen kan worden.

- Directe administratie is minder gebruikelijk, waarschijnlijk omdat het moeilijker is. Met deze methode zorgen de filters ervoor dat gebruikers voor hun printergebruik worden afgerekend op het moment dat ze er gebruik van maken. Net als schijfquota is de administratie onmiddellijk. Hiermee wordt voorkomen dat gebruikers kunnen afdrukken wanneer ze over hun limiet zijn gegaan. Ook biedt dit de mogelijkheid voor gebruikers om hun afdrukquotum te controleren, of aan te passen. Deze methode vereist databasecode om gebruikers en hun quota bij te houden.

Het wachtrijsysteem LPD ondersteunt beide methoden op eenvoudige wijze. Aangezien de filters (meestal) moeten worden aangeleverd, moet ook de code voor de administratie worden geleverd. Er is echter een voordeel: er is grote flexibiliteit in de administratiemethode. Zo kan bijvoorbeeld gekozen worden tussen periodieke of directe administratie. Er kan gekozen worden welke informatie opgeslagen wordt: gebruikersnamen, hostnamen, type opdracht, aantal afgedrukte pagina's, hoe lang het afdrukken duurde, enzovoort. Dit alles kan worden gedaan door de filters aan te passen.

#### 10.4.5.1. Kort door de bocht printeradministratie

FreeBSD wordt met twee programma's geleverd waarmee periodieke administratie direct kan worden opgezet. Het zijn het tekstfilter `lpf`, beschreven in lpf: een tekstfilter en pac(8), een programma dat posten uit administratiebestanden verzamelt en optelt.

Zoals beschreven in de sectie over filters (Filters), roept LPD de tekst- en conversiefilters aan met de naam van het administratiebestand als argument. De filters kunnen dit argument gebruiken om te bepalen in welk bestand de gegevens voor de administratie moeten worden weggeschreven. De naam van dit bestand is afkomstig van de optie `af` uit `/etc/printcap`. Als er geen absoluut pad wordt opgegeven, dan is de locatie relatief aan de wachtrijmap.

LPD start `lpf` met paginabreedte en -lengte argumenten (afkomstig uit de opties `pw` en `pl`). Het filter `lpf` gebruikt deze argumenten om te bepalen hoeveel papier er gebruikt zal worden. Nadat het bestand naar de printer is gestuurd, schrijft het een post in het administratiebestand. De posten zien er als volgt uit:

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

Aangezien `lpf` geen ingebouwde logica voor bestandslocking kent, moet voor elke printer een apart administratiebestand gebruikt worden. Twee `lpf`s kunnen elkaars posten corrumperen als ze tegelijk in hetzelfde bestand schrijven. De optie `af=acct` in `/etc/printcap` biedt een makkelijke manier om er zeker van te zijn dat aparte bestanden worden gebruikt. Dan bevindt elk administratiebestand zich in de wachtrijmap van de betreffende printer en krijgt de naam `acct` krijgen

Wanneer het tijd is om met gebruikers af te rekenen voor hun afdrukken, kan het programma pac(8) gedraaid worden. Ga naar de wachtrijmap van de printer waarvoor betaald moet worden en typ `pac`. Er verschijnt een dollar-centrische samenvatting zoals het volgende:

      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

Dit zijn de argumenten die pac(8) verwacht:

`-P`printer``

  De `printer` waarvoor een samenvatting moet worden gegenereerd. Deze optie werkt alleen als er een absoluut pad is gegeven in de optie `af` in `/etc/printcap`.

`-c`

  Sorteer de uitvoer op kosten, in plaats van alfabetisch op gebruikersnaam.

`-m`

  Negeer de hostnamen in het administratiebestand. Met deze optie is de gebruiker `smith` op host `alpha` dezelfde gebruiker als `smith` op host `gamma`. Zonder deze optie zijn het verschillende gebruikers.

`-p`prijs``

  Bereken de prijs met `prijs` dollar per pagina of per voet, in plaats van de prijs uit de optie `pc` in `/etc/printcap` of twee cent (de standaard). De `prijs` kan worden opgegeven als een decimaal getal.

`-r`

  Keer de sorteervolgorde om.

`-s`

  Maak een bestand met een samenvatting van de administratie en leeg het administratiebestand.

`namen` `…`

  Druk de administratiegegevens alleen af voor gebruikersnamen `namen`.

In de standaard samenvatting die pac(8) genereert, is het aantal pagina's te zien dat iedere gebruiker vanaf een bepaalde host heeft afgedrukt. Wanneer de hostnaam niet van belang is (bijvoorbeeld omdat gebruikers iedere host kunnen gebruiken), gebruik dan `pac -m` om de volgende samenvatting te genereren:

      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

Om het verschuldigde bedrag te berekenen gebruikt pac(8) de optie `pc` uit `/etc/printcap` (standaard aantal van 200 of 2 cent per pagina). Specificeer, in honderden centen, de prijs per pagina of per voet die berekent moet worden. Deze waarde kan worden aangepast door pac(8) aan te roepen met de optie `-p`. De eenheden van de optie `-p` zijn echter in dollars, niet in honderden centen. Bijvoorbeeld,

    # pac -p1.50

zorgt ervoor dat elke pagina 1,50 dollar kost. U kunt echt grote winsten maken met deze optie.

Tenslotte kan met `pac -s` de samenvatting worden opgeslagen in een bestand dat dezelfde naam krijgt als het administratiebestand van de printer, maar dan met `_sum` toegevoegd aan de naam. Vervolgens wordt het administratiebestand geleegd. Als pac(8) opnieuw wordt aangeroepen, herleest pac(8) het samenvattingsbestand om de startwaarden te bepalen en telt daar de informatie bij op van het standaard administratiebestand.

#### 10.4.5.2. Hoe kan het aantal afgedrukte pagina's worden geteld?

Om ook maar de minste nauwkeurigheid bij het administreren te verkrijgen, is het nodig te weten hoeveel papier een afdrukopdracht gebruikt. Dit is het centrale probleem van het bijhouden van printerstatistieken.

Voor opdrachten met platte tekst is het probleem niet zo moeilijk op te lossen: het aantal regels in een opdracht wordt geteld en vergeleken met het aantal regels per pagina dat door een printer wordt ondersteund. Hierbij moet niet worden vergeten dat backspaces in het bestand regels overschrijven en dat lange logische regels worden afgedrukt als meerdere fysieke regels.

Het tekstfilter `lpf` (geïntroduceerd in lpf: een tekstfilter) houdt met deze zaken rekening bij het administreren. Als het nodig is een tekstfilter te schrijven dat ook het printergebruik moet bijhouden, dan is het nuttig de broncode van `lpf` te bestuderen.

Hoe worden andere bestandsformaten dan verwerkt?

Voor een DVI-naar-LaserJet, of DVI-naar-PostScript® conversie kan het filter de diagnostische uitvoer van `dvilj` of `dvips` bekijken om te bepalen hoeveel pagina's er zijn geconverteerd. Voor andere formaten kan hetzelfde worden gedaan met behulp van de betreffende conversieprogramma's.

Deze methoden hebben echter als nadeel dat een printer eventueel niet alle pagina's ook daadwerkelijk afdrukt. Zo kan het papier vast komen te zitten, de toner opraken of de printer ontploffen, terwijl de gebruiker toch moet betalen.

Dus, wat kan hieraan worden gedaan?

Er is slechts één betrouwbare manier om nauwkeurig te administreren. Dat is met behulp van een printer die kan vertellen hoeveel papier er is gebruikt. Deze moet vervolgens worden aangesloten met een seriële lijn, of een netwerkverbinding. Bijna alle PostScript®-printers hebben deze mogelijkheid, andere modellen en merken mogelijk ook (bijvoorbeeld Imagen netwerklaserprinters). De filters dienen voor deze printers aangepast te worden om het papierverbruik na elke opdracht te achterhalen en de administratieve informatie alleen op deze waarde te baseren. Er is geen noodzaak om foutgevoelig regels te tellen of bestanden te analyseren.

Natuurlijk kan een beheerder ook vrijgevig zijn en alle afdrukken gratis maken.

Terug | Omhoog | Volgende
10.3. Standaardinstallatie | Begin | 10.5. Printers gebruiken