next up previous contents index
Next: Der Batchdämon crond Up: Der Druckerdämon lpd Previous: Den lpd erziehen

Die Druckerfilter

 

Mit Ausnahme des Papierformates sind in der printcap-Datei keine Informationen über die genaue Ansteuerung des Druckers gespeichert. Das bedeutet, daß der Druckerdämon nicht einmal einen Reset oder eine Druckerinitialisierung selbst ausführen kann. Trotzdem kann ein gut eingerichteter lpd eine Vielzahl unterschiedlicher Formate auf jedem angeschlossenen Drucker ausgeben, vorausgesetzt, die Systemverwalterin hat die passenden Filter installiert.

Der lpd kann einen Ausgabefilter ( of) und bis zu neun Eingabefilter ( cf, df, gf, if, nf, rf, tf, vf und pr, siehe oben) benutzen.

Der Ausgabefilter

Der Ausgabefilter ist in erster Linie dazu gedacht, die Ausgabe der vom lpd selbst generierten Titelseiten am Beginn jedes Druckjobs zu filtern. Weil eine eventuell notwendige Druckerinitialisierung bereits für diese Titelseite sinnvoll ist, sollte der Ausgabefilter auch diese Aufgabe erfüllen.

Das Zusammenspiel des Ausgabefilters mit dem lpd ist insofern etwas kompliziert, als dieser nur einmal zu Beginn des ersten Druckjobs gestartet wird. Für den Ausdruck der eigentlichen Dokumente benutzt der Druckerdämon einen der Eingabefilter und hält den Ausgabefilter bis zum Beginn des nächsten Jobs an. Dazu schreibt der Dämon die Zeichenkette '\031\1' in die Standardeingabe des Ausgabefilters. Der Filter muß sich daraufhin selbst mit SIGSTOP anhalten und auf das SIGCONT-Signal warten.

Die Eingabefilter

Die Zahl möglicher Formate, in denen ein Dokument vorliegen kann, und die Zahl möglicher Druckersprachen, in die dieses Format umgewandelt werden muß, um tatsächlich auf dem Papier zu erscheinen, ist so groß, daß es keine einfache Methode gibt, diese Übersetzung direkt vom Druckerdämon ausführen zu lassen.

Deshalb muß die Systemverwalterin dem lpd für jedes Eingabeformat einen Eingabefilter bereitstellen, der dieses Format für den installierten Drucker aufbereitet.

Das Zusammenwirken des lpd mit den Eingabefiltern ist sehr einfach. Mit einer der Optionen c, d, f, g, n, p, t und v gibt der Benutzer beim Aufruf von lpr an, welches Format sein Dokument hat, und bestimmt so, welcher Eingabefilter benutzt wird. Dieser Filter wird dann vom lpd für den Ausdruck des bei diesem Aufruf von lpr bestimmten Dokumentes in einer Pipeline gestartet. Der Dämon ruft den if-Filter mit folgender Kommandozeile auf:

if [-c] -wSpalten -lZeilen -i Einrückung -n Name -h Host Accountdatei

Die -c Option ist gesetzt, wenn der lpr mit der Option -l aufgerufen wurde. Alle anderen Eingabefilter werden mit der Zeile

filter -x Breite -y Länge -n Name -h Host Accountdatei

aufgerufen.

Während ein Eingabefilter aktiv ist, bleibt der Ausgabefilter angehalten. Der Eingabefilter liest aus der Pipeline (Standardeingabe), verändert den Datenstrom seinem Programm entsprechend und schreibt die Daten in die Standardausgabe, die direkt mit dem Drucker verbunden ist.

So ein Filter kann ein vollständiges C-Programm sein. Das dem lpd-Paket beiliegende Programm lpf ist beispielsweise ein Eingabefilter speziell für groff-Dokumente.

  Als Eingabefilter können aber auch Shellscripts oder perl- Programme verwendet werden. Auf diese Weise kann zum Beispiel die Umwandlung einer Postscriptdatei für einen Epson-Nadeldrucker mit dem Ghostscript-Interpreter gs erfolgen:

#!/bin/bash
#
gs -q -dNOPAUSE -sDEVICE=EPSON -sOutputFile=- -

Ein schönes Beispiel für die vielfältigen Möglichkeiten, einen Filter zu bauen, ist das magic-filter-Script von Brian McCauley. Dieses Shellprogramm nutzt das file-Kommando zur Erkennung des Formats einer Eingabedatei und wählt automatisch den passenden Filter für die weitere Bearbeitung.gif

#!/bin/bash
# BAM's magic-filter
# (C) Brian McCauley (B.A.McCauley@bham.ac.uk) 1993

# Der Druckerdämon hat nicht unbedingt eine brauchbare PATH Umgebungsvariable
PATH=$PATH:/usr/bin:/bin:/usr/local/bin
 
# Das magic-filter Script kann durch Links unter verschiedenen Namen aufgerufen
# werden. Dadurch kann das Verhalten des Filters durch die Optionen (Schalter)
# des `lpr' Kommandos bestimmt werden.
basename=${0##*/}


# Mit dem im Paket des magic-filter enthaltenen C-Programm rewind-stdin wird
# sichergestellt, daß der Filepointer am Anfang der Eingabedatei steht. Wenn
# die Eingabe nicht aus einer Datei kommt, sondern aus einer Pipeline, schlägt
# das Zurücksetzen fehl.

if rewind-stdin ; then
  tmpfile=""
else
  # In diesem Fall wird der Name für eine garantiert neue temporäre Datei
  # bestimmt. (Dieses Script kann rekursiv aufgerufen werden.)
  while tmpfile=/tmp/$basename.$$.$RANDOM; test -e $tmpfile; do :; done
fi

# Mit dem `file'-Kommando wird versucht, das Format der Druckdatei festzustellen.

if [ -z "$tmpfile" ] ; then
  magic=`file -`
else 
  # Wenn die Datei durch eine Pipeline kommt, wird das erste Kilobyte
  # gespeichert und zur Identifizierung an das `file' Kommando gegeben.
  dd bs=1 count=1024 of=$tmpfile 2>/dev/null
  magic=`file $tmpfile`
fi

# Der Dateiname wird von der Ausgabe von `file' entfernt.

magic=${magic#*:\ }
 
filter=""
prefilter=""
nopipe=0

# Der folgende Block wird von Brian McCauley als separates Script ausgeführt.
# Das erleichtert das Einfügen neuer Filter für andere Formate. Die Anführungs-
# zeichen um die Ausdrücke mit den Wildcards in diesem Beispiel müssen ab der
# bash-Version 1.13 entfernt werden!

# Hier werden in Abhängigkeit von dem durch das `file'-Kommando bestimmten
# Format und die Optionen beim Aufruf von `lpr' die passenden Filter bestimmt.

case $magic in

  # Wenn die Druckdatei komprimiert ist, wird ein prefilter zum Entpacken
  # zwischengeschaltet.

  "block compressed data*" | "gzip compressed*" ) prefilter="gzip -d" ;;

  # Der Name, unter dem der magic-filter aufgerufen wird, variiert in
  # Abhängigkeit von den Optionen, mit denen `lpr' aufgerufen wurde.

  "*" ) case $basename in
    # This is my example
    "lp.df" ) case $magic in
      "DVI*" ) filter=${0%/*}/sample-filters/dvi2epson; nopipe=1 ;;
      "PostScript*" ) filter=${0%/*}/sample-filters/ps2epson ;;
      "TeXinfo source" ) filter=${0%/*}/sample-filters/texi2epson ;;
    esac ;;
    # Hier ist der Eintrag für den if-Inputfilter, der aufgerufen wird, wenn
    # keine der Optionen für `lpr' benutzt wurde.
    "lp.if" ) filter=${0%/*}/text-filter ;;
  esac ;;
esac 


# Wenn die Datei als komprimiert erkannt ist, wird sie in diesem Schritt durch
# das prefilter-Programm entpackt, um anschließend wieder rekursiv durch den
# magic-filter bearbeitet zu werden.

if [ -n "$prefilter" ]; then
  if [ -z "$tmpfile" ]; then
    rewind-stdin
    eval $prefilter | $0 $*
  else
    ( cat $tmpfile; rm $tmpfile; cat ) | \
    eval $prefilter | $0 $*
  fi
  exit
fi

# Wenn ein Filter für das Dokumentformat bestimmt werden konnte, wird jetzt das
# Dokument tatsächlich bearbeitet.

if [ -z "$filter" ] ; then
  echo $0: "Can't handle $magic" >&2
else
  if [ -z "$tmpfile" ]; then
    rewind-stdin
    exec $filter $*
  else

    # Wenn der Filter nicht aus einer Pipeline lesen kann, muß der Rest der
    # Druckdatei in der temporären Datei zwischengelagert werden. (Die ersten
    # 1024 Bytes wurden bereits zur Identifizierung gespeichert.

    if [ "$nopipe" = 1 ]; then 
      cat >>$tmpfile
      $filter $* <$tmpfile
    else
      ( cat $tmpfile; rm $tmpfile; cat ) | $filter $*
      exit
    fi
  fi
fi

# Wenn am Ende noch eine in dieser Instanz des magic-filter-Scripts erzeugte
# temporäre Datei existiert, wird sie gelöscht.

if [ -n "$tmpfile" ] ; then
  rm $tmpfile
fi
   



next up previous contents index
Next: Der Batchdämon crond Up: Der Druckerdämon lpd Previous: Den lpd erziehen



Linux Anwenderhandbuch -- Copyright 1993, 1994, 1995 S. Hetze, D. Hohndel, O. Kirch, M. Müller