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 etwa so aus:
# LOKALER djet500
lp|dj|deskjet:\
:sd=/var/spool/lpd/dj:\
:mx#0:\
:lp=/dev/lp0:\
:sh:
Dies definiert einen Spool namens lp
, dj
oder
deskjet
mit dem Spool-Verzeichnis
/var/spool/lpd/dj
, ohne maximale Auftragsgröße,
der auf das Device /dev/lp0
ausgibt und am Anfang des
Druckauftrags kein Deckblatt hinzufügt (mit dem Namen der Person,
die gedruckt hat, etc.).
Jetzt wäre der richtige Augenblick, um die
printcap Man-page
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 Zeilenwechsel "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.
Offensichtlich wird mehr benötigt, und genau das ist die Aufgabe
des Filterns. Dem aufmerksame Leser werden bei der printcap
man-page die Spool-Attribute if
und of
aufgefallen
sein. if
, der Inputfilter, ist genau das, was wir jetzt
brauchen.
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 einfaches Filterscript könnte sein:
#!perl
# The above line should really have the whole path to perl
# This script must be executable: chmod 755 filter
while(<STDIN>){chop $_; print "$_\r\n";};
# You might also want to end with a form feed: print "\f";
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öhnlichen Text zu drucken nichts Besonderes ist - es wäre sicherlich besser, wenn man PostScript und andere formatierte Texte oder Grafik-Ausgaben drucken könnte. Ja, das wäre es, und es ist einfach zu machen. Dazu muß einfach der obige Zeilenumbruch-Filter erweitert werden. Wenn man einen Filter schreibt, der beliebige Dateitypen akzeptiert und diese in Deskjet-geeignete 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. Der APS-Filter ist einer der besten, oder Ihre Linux-Distribution hat vielleicht ein Drucker-Setup Tool, das all dies deutlich vereinfacht.
Auf Grund von häufigen Nachfragen folgtt hier eine Liste der Permissions der wichtigen Dateien, wie sie auf meinem System 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 Anbindung werden, aber das tut es wohl nicht. Dumm, das.