Die Minimaleinstellungen für lpd liefern ein System, das Dateien in Warteschlangen verwalten und sie drucken kann. Es kümmert sich nicht darum, ob der Drucker die Dateien überhaupt versteht und wird vermutlich keine ansehnlichen Ausgaben produzieren. Trotzdem ist es der erste Schritt zum Verständnis, also weiterlesen!
Um eine Warteschlange zu lpd hinzuzufügen, muß man einen Eintrag in
/etc/printcap
hinzufügen und ein neues Spool-Verzeichnis unter
/var/spool/lpd
erzeugen.
Ein Eintrag in /etc/printcap
sieht wie folgt aus:
# LOKALER djet500
lp|dj|deskjet:\
:sd=/var/spool/lpd/dj:\
:mx#0:\
:lp=/dev/lp0:\
:sh:
Das definiert einen Spool namens lp
, dj
oder deskjet
, im
Verzeichnis /var/spool/lpd/dj
, ohne maximale Auftragsgröße,
der an ein Device /dev/lp0
druckt und am Anfang des
Druckauftrags keine Trennseite hinzufügt (mit dem Namen der Person,
die gedruckt hat, etc.).
Jetzt wäre der richtige Augenblick, um die man-page für
printcap
zu
lesen.
Das obige Beispiel sieht sehr einfach aus, hat aber ein Problem. Wenn man keine Files sendet, die ein DeskJet 500 verstehen kann, wird dieser Deskjet seltsame Sachen drucken. Wenn man z.B. eine gewöhnlichen UNIX-Textdatei an den Deskjet schickt, interpretiert er die Newlines wörtlich und gibt aus:
Dies ist Zeile eins.
Dies ist Zeile zwei.
Dies ist Zeile drei.
und so weiter. Der Ausdruck einer PostScript-Datei würde eine schöne Liste der PostScript-Befehle geben, mit diesem "Treppenstufeneffekt" ausgedruckt, aber keine sinnvolle Ausgabe.
Also wird mehr benötigt, und genau das ist die Aufgabe des Filters.
Dem aufmerksame Leser werden bei der printcap man-page die
Spool-Attribute if
und of
aufgefallen sein. if
oder der
Inputfilter ist genau das, was man jetzt braucht.
Wenn man ein kleines Shellscript namens filter
schreibt, daß
Zeilenumbrüche (CR) vor die Newlines setzt, wird der
"Treppenstufeneffekt" verhindert. Also muß in den printcap-Eintrag
eine if
-Zeile eingefügt werden:
lp|dj|deskjet:\
:sd=/var/spool/lpd/dj:\
:mx#0:\
:lp=/dev/lp0:\
:if=/var/spool/lpd/dj/filter:\
:sh:
Ein simples Filterscript könnte sein:
#!perl
while(<STDIN>){printf "$_\r";};
Wenn man das machen würde, hätte man einen Spool, in den man gewöhnliche UNIX-Textdateien drucken kann und sinnvolle Ergebnisse bekäme. (Ja, es gibt vier Millionen bessere Möglichkeiten diesen Filter zu schreiben, aber wenige so anschauliche. Der Leser möge dies effizienter gestalten.)
Das einzige verbleibende Problem besteht darin, daß gewöhnlicher Text nichts Besonderes ist - es wäre sicherlich besser, wenn man PostScript und andere formatierte Texte oder Grafik-Ausgaben drucken könnte. Ja, gut, das wäre es, und es ist einfach. Dazu muß einfach der obige Zeilenumbruch-Filter erweitert werden. Wenn man einen Filter schreibt, der beliebige Dateitypen akzeptiert und diese in Deskjet-verständliche Ausgaben umwandelt, hat man wirklich einen cleveren Druck-Spooler!
So ein Filter wird Magic-Filter genannt. Man sollte sich nicht die Mühe machen und selber einen schreiben, solange man keine wirklich ungewöhnlichen Sachen drucken will. Es gibt einige wirklich gute im Netz.
Auf Grund von häufigen Nachfragen ist hier eine Liste der Permissions der wichtigen Dateien, wie sie auf dem System des Autors gesetzt sind. Es gibt bessere Möglichkeiten, im Idealfall ohne SUID root, sondern mit SGID Binärdateien, aber so wurde das System installiert und es funktioniert. (Ehrlich gesagt, wenn ein Verkäufer noch nicht einmal ein funktionierendes lpd liefern kann...)
-r-sr-sr-x 1 root lp /usr/bin/lpr*
-r-sr-sr-x 1 root lp /usr/bin/lprm*
-rwxr--r-- 1 root root /usr/sbin/lpd*
-r-xr-sr-x 1 root lp /usr/sbin/lpc*
drwxrwxr-x 4 root lp /var/spool/lpd/
drwxr-xr-x 2 root lp /var/spool/lpd/lp/
Lpd muß momentan als root aufgerufen werden, damit es die lp Service-Ports mit niedrigen Nummern ansprechen kann. Es sollte vielleicht UID lp.lp oder so etwas nach der Bindung werden, aber das tut es wohl nicht.