Menü
Avatar von Mattias Schlenker
  • Mattias Schlenker, Mattias Schlenker

mehr als 1000 Beiträge seit 13.05.2006

Re: Hilfe mit CUPS ... immernoch ... gesucht

Vielelicht hilft das (mit freundlicher Genehmigung des Autors). Ist
schon älter, sollte aber immer noch passen...

Pfiffig Papier sparen

Cups-Backend-Programmierung am Beispiel platzsparender Ausdrucke

Kaum ein Druckdialog bietet das Drucken von zwei Seiten nebeneinander
auf einem Blatt. Ein etwa 15 Zeilen langes Shellscript hilft dabei,
diese Funktionalität direkt in Cups in Form eines virtuellen Druckers
nachzurüsten.

Die kleinen Druckhelferlein "mpage" oder "psnup" sind längst keine
Geheimtips mehr. Im Gegenteil, seit bald fünfzehn Jahren erhältlich,
sind sie bei vielen Anwendern zum ständigen Begleiter geworden, wenn
es darum geht, Foliensätze platzsparend auf wenige Seiten zu
reduzieren oder Broschüren für das Falten und Heften vorzubereiten.
Eine Integration in die Druckdialoge der großen Desktopumgebungen
sucht man jedoch vergebens. So bleibt nur der Aufruf auf der
Kommandozeile -- verständlich, daß bei vielen Ausdrucken deshalb
unnötigerweise auf die Reduzierung verzichtet wird.

Der Autor verwendete deshalb bis vor einer Weile ein kleines Script,
das in Perl/Tk geschrieben war, welches die wichtigsten Parameter von
"mpage" mittels Checkboxen setzen lies. In einem größeren Netzwerk
mit vielen Clients ist soetwas natürlich ineffizient, da das Script
auf jedem Rechner im Netz installiert werden muß. Wir haben uns
deshalb überlegt, wie eine derartige Funktionalität direkt im
Drucksystem zu integrieren ist. Unter dem traditionellen Berkeley-LPD
verwendet man dafür in der Regel eine angepasstes Filterscript. Cups
stellt mit dem Backend-Mechanismus von vorneherein ein flexibles
Konzept bereit.

=== Was ist ein Backend?

Backends bei Cups sind kleine Programme, bei denen lediglich das
Aufrufschema vorgegeben ist. Wird kein Parameter übergeben, gibt das
Script die Kurzbezeichnung des Backends und den Typ aus. Werden fünf
oder sechs Parameter übergeben, rechnet das Script mit der Übergabe
von Job-ID, Nutzer, Titel, Zahl der Kopien, Optionen und entweder dem
Dateinamen des Druckjobs oder es erwartet den Druckjob an der
Standardeingabe. Desweiteren steht innerhalb des Backends die in Cups
eingerichtete Device-URI als Umgebungsvariable $DEVICE_URI zur
Verfügung.

Mit Kenntnis dieses Aufbaus lässt sich bereits ein kleines
Dummy-Backend programmieren, das nichts anderes tut als die
übergebenen Parameter in Textdateien zu schreiben:

#!/bin/sh
if [ $# -eq 0 ]
then
    echo "dummyback \"Unknown\" \"Network Device\""
    exit 0
else
    echo "$1" > /tmp/1job-id.txt
    echo "$2" > /tmp/2user.txt
    echo "$3" > /tmp/3title.txt
    echo "$4" > /tmp/4copies.txt
    echo "$5" > /tmp/5options.txt
    echo "$DEVICE_URI" > /tmp/device-uri.txt
    exit 0
fi

Speichern Sie dieses Script als "dummyback" im Backend-Verzeichnis
von Cups, das Sie je nach Distribution unter "/usr/lib/cups/backend",
"/usr/libexec/cups/backend" oder "/usr/local/libexec/cups/backend"
befindet. Damit das Script verfügbar ist, müssen Sie Cups neu
starten. Öffnen Sie anschließend das Konfigurationstool von Cups, der
Autor bevorzugt dafür das unter http://localhost:631/ erreichbare
Webfrontend und legen Sie einen neuen Drucker mit dem Dummy-Backend
an.

Wenn Sie nun auf diesen Dummy-Drucker drucken findet kein
tatsächlicher Ausdruck statt. Aus den im Verzeichnis /tmp neu
entstandenen Textdateien können Sie jedoch die übergebenen Parameter
herauslesen. Mit diesen Kenntnissen der Funktionsweise und
Übergabepraxis lässt sich das eigene Backend in Angriff nehmen.

=== Zwei auf eins: das eigene Backend

Wir müssen letztendlich drei Fälle unterscheiden:

  - Es wird kein Parameter übergeben, in diesem Fall sind Name und
Typ des Backends auszugeben
  - Es werden fünf Parameter übergeben, der eigentliche Druckjob
folgt an der Standardeingabe
  - Werden sechs Parameter übergeben ist der sechste Paramter der
Name der zu druckenden Datei

Alle übrigen jobspezifischen Parameter interessieren nicht. Eine
besondere Bedeutung kommt jedoch der Device-URI zu. Wir wollen diese
dazu verwenden, neben dem Drucker auf dem der spätere Ausdruck
erfolgen soll die Zahl der Seiten und die Orientierung zu übergeben.

Eine Device-URI

   multipleinone://laserjet/2/normal

soll zwei normale Seiten auf einem Blatt ausgeben und den Ausdruck
zum lokal angelegten Drucker "laserjet" schicken, während

   multipleinone://deskjet/4/updown

dafür sorgen soll, daß vier Folien im Querformat in korrekter
Reihenfolge den Weg auf eine Seite finden. Um die Device-URI
aufzusplitten ist "awk" das richtige Werkzeug. Gibt man diesem als
Feldtrenner den Slash an, können wir an Position 3, 4 und 5 die
nützlichen Parameter herausfischen, so den Namen des Druckers mit:

   PRN="$( echo \"$DEVICE_URI\" |\
    awk -F/ '{ print $3 }' )"

Ähnlich sieht es mit dem letzten Feld aus, das angibt, ob Folien im
Querformat oder normale Seiten im Hochformat gedruckt werden sollen.
Handelt es sich um Folien, muß "mpage" der Parameter "-R" übergeben
werden:

   if [ "$( echo \"$DEVICE_URI\" |\
 awk -F/ '{ print $5 }' )" == updown ]
   then
 UPDOWN="-R"
   fi

Aus den resultierenden Feldern lässt sich schlißelich der eigentliche
Druckbefehl zusammensetzen:

   mpage -bA4 -${PAGES} ${UPDOWN} -o |\
      lpr -P${PRN}

Für die Ausgabe verwenden wir hier quick and dirty den Druckbefehl
"lpr", der vom cups-lpr-Paket bereitgestellt wird. Letztendlich nimmt
ein Druckjob damit zweimal den Weg über das Drucksystem, was nicht
gerade elegant ist, aber auch keine Probleme verursacht. Das fertige
Script zeigt der Kasten "Für Ungeduldige".

Doch auch unser Backend bietet noch Verbesserungsmöglichkeiten, Schön
wäre es, weitere Mpage-Parameter als fünftes Kommandozeilenargument
zu übergeben. In Umgebungen mit vielen unbedachten Nutzern wie
Universitäts-Rechnerpools mag es darüberhinaus sinnvoll sein, zu
überprüfen, daß Postscript oder Plaintext übergeben wurden. Eine
unbedacht zum Drucker geschickte PDF-Datei wird sonst im Quelltext
ausgedruckt.

=== Fazit:

Die Anpassung von Cups mit eigenen Erweiterungen ist nicht schwer.
Vom Verständnis des Backend-Konzeptes bis zum fertigen Script verging
bei uns weniger als eine halbe Stunde. Die Übergabe vieler Parameter
und vor allem der sehr gut konfigurierbare Device-URI-String hilft
bei der Umsetzung eigener Ideen. Dennoch wird es wohl noch eine Weile
dauern, bis sich die Erweiterbarkeit von Cups so weit herumgesprochen
hat, wie die Verwendung eigener Filterscipte im klassischen LPD. Am
Backend-Konzept von Cups kann es nicht liegen, dieses ist
durchsichtig und intuitiv. Hat man es verinnerlicht, ist es ein
leichtes, Backends zu erstellen, die in PNG-Dateien drucken, PDFs per
Mail versenden oder flexibler faxen und einfacher einzurichten sind
als ein Hylafax-Server.

Bewerten
- +
Anzeige