- předchozí článek - následující článek - obsah - úvodní stránka -

Linuxové noviny 01/2000

Tiskárny v Unixu

Petr Olšák, 4. ledna 2000

Na konci roku 1999 koupila naše katedra několik nových tiskáren a já jsem je připojoval do naší heterogenní sítě postavené na unixových serverech. Rozhodl jsem se sepsat zkušenosti s tím spojené do článku, který můžete použít jako jakési hautú, ovšem forma článku je určena pro Linuxové noviny.

Teorie

Staré unixové aplikace vytvářely pouze holý textový výstup a předpokládalo se, že ten může být tištěn na tiskárnách. Řádkové tiskárny (Line PRinter, proto program lpr) holé texty tiskly bez problémů a nic více se neřešilo. Jakmile vznikly modely tiskáren, které umějí tisknout grafiku, vývojáři firmy Adobe navrhli velmi dobrý standard, který popisuje pokyny pro tisk grafiky - jazyk PostScript. Jedná se o lidsky čitelný programovací jazyk. Unixové tiskové spoolery tedy nadále obsahují textové soubory: buď skutečné holé texty určené pro řádkové tiskárny nebo PostScript, určený pro grafické tiskárny. Pokud unixové aplikace nabízejí možnost tisknout grafiku, musejí mít v sobě zabudován generátor PostScriptu. Žádné rozhraní se systémem při programování tiskových algoritmů v aplikacích se nevyužívá.

PostScript by měla umět zpracovat každá tiskárna schopná grafického provozu. To je bohužel jen sen. Některé tiskárny rozumějí pouze svému vlastnímu jazyku, který je od mezinárodního standardu (jakým je PostScript) na hony vzdálen. V lepším případě je tento jazyk tiskárny výrobcem zveřejněn a programátoři z komunity volného software pro něj napíší modul do Ghostscriptu. Pak je možno zařadit do tiskového spooleru filtr, který volá program Ghostscript. Ten umí interpretovat PostScript a prostřednictvím zmíněného modulu jej převede na jazyk tiskárny. Tento výstup se pošle přímo na port tiskárny. Tiskárna se z pohledu unixového uživatele jeví jako schopná zpracovat PostScript. Že problém řeší nějaký Ghostscript na tiskovém serveru nemusí uživatele zajímat.

V horším případě výrobce hardwaru nezveřejní jazyk tiskárny, ale některý programátor volného software se přesto pokusí experimenty, pokusy a omyly zjistit, jak se dá s tiskárnou domluvit, a napíše k tomu modul do Ghostscriptu. Tím je úloha převedena na předchozí případ, ovšem s tím, že se zřejmě nepodaří využít všechny hardwarové schopnosti tiskárny. V ještě horším případě se programátoři volného software danou tiskárnou vůbec nezabývají a nehodlají zabývat (protože například výrobce nezveřejní technickou specifikaci zařízení a oni nemají potřebu na něm tisknout). V takovém případě existuje jediná rada: takovou tiskárnu nekupujte!

To je ovšem rada za všechny peníze. Zkuste zajít za prodavačem počítačového vybavení s dotazem, zda pro jazyk nabízené tiskárny existuje modul do Ghostscriptu. Z nejvyšší pravděpodobností vám prodavač nebude rozumět. Když mu vysvětlíte, že je to velmi důležité, protože jinak na té tiskárně nepůjde vůbec tisknout, bude prodavač argumentovat, že přece v dodávce je CDčko s ovladačem pro Woknous, takže jakýpak problém. Je tedy potřeba vykašlat se na prodavače a důkladně prohlédnout informace o Ghostscriptu na Internetu včetně možností jeho modulů s návazností na typ tiskárny, kterou zamýšlíte zakoupit. Je také možné se plácnout přes kapsu a koupit tiskárnu, která sama umí PostScript. Pak jste při připojení k Unixu zcela bez problémů.

Nahlédnutí do oken

Protože v naší katederní síti existují stále zatvrzelí uživatelé používající MS Woknous, krátce se zmíním o technických principech tisku z tohoto operačního systému.

Aplikace, která má vytvářet tiskový výstup, musí dávat pokyny o vzhledu stránky přímo operačnímu systému prostřednictvím aplikačního interfejsu (API). Je to něco podobného jako systémové volání v Unixu. Tím se aplikace stává sice nezávislou na typu připojené tiskárny, ale zároveň se stává těžce závislou na Woknous. Pro srovnání připomeneme, že unixová aplikace generuje PostScript, což je jazyk zcela nezávislý na použitém operačním systému. Tiskové algoritmy unixové aplikace můžeme tedy snadno přenést na libovolný jiný operační systém (s výjimkou Woknous). Přepsat ale programový kód tisku ve Woknousové aplikaci znamená napsat vše zcela znovu. Nezávidím programátorům, kteří vsadili na Woknous a nyní musejí přepisovat rozsáhlé kusy svých programů pro použití v rozumnějších operačních systémech.

Tiskové pokyny z aplikace jsou zpracovány systémem Woknous a jsou dále předávány jednotnému rozhraní všech tiskových ovladačů pro Woknous. Tiskový ovladač (dodávaný výrobcem tiskárny) z nich vygeneruje jazyk, kterému rozumí daná tiskárna a výsledek pošle do spooleru. Odtud se úloha vytiskne. Vidíme tedy další rozdíl. Zatímco v unixových spoolerech máme pro grafický tisk pouze PostScript bez závislosti na typu tiskárny, ve Woknousových spoolerech je vždy úloha předžvejkaná do jazyka tiskárny. Taková úloha může být mnohonásobně objemnější, než kdyby zůstala v PostScriptu. Na Woknousové spoolery je tedy často potřeba vymezit více místa. Další nevýhodou je, že při problémech s tiskem se nedá ve Woknous snadno přijít, kde je chyba. V Unixu můžeme při problémech zachytit PostScript ve spooleru a důkladně si jej prohlédnout (textovým editorem a Ghostscriptem). Ve Woknous můžeme sice také zachytit soubor ve spooleru, ale nebude nám to nic platné, protože jazyk tiskárny je většinou binární a člověku zcela nesrozumitelný.

Všimneme si dalšího důležitého rozdílu mezi Unixem a Woknous. Každá stanice s Woknous musí mít instalovány všechny ovladače pro všechny síťově viditelné tiskárny. Do sítě posílá předžvejkanou úlohu už v jazyce tiskárny. Nákup nové tiskárny připojené do sítě tedy obnáší obejít všechny Woknousové klienty s disketou nebo CDčkem a do zblbnutí instalovat ovladač. Na druhé straně unixový filtr, který spouští Ghostscript pro převedení PostScriptu do jazyka tiskárny, je instalován až na konci řetězce, tedy na tiskovém serveru, ke kterému je tiskárna připojena. Jednotliví unixoví klienti nepotřebují instalovat žádný doprovodný software pro danou tiskárnu. Uživatelům pošleme jen e-mail, že mají do svého printcapu přidat jeden nový řádek, a o více se nestaráme. Méně poučeným uživatelům to uděláme sami pomocí ssh, aniž bychom museli zvednout zadek ze židle.

Dalším problémem ve Woknous je skutečnost, že začaly zcela ignorovat možnost tisku na starých řádkových tiskárnách. Nelze jednoduše poslat tiskárně prostý textový soubor k vytištění bez toho, aby jej Woknousy nepřeložily do sekvence grafických pokynů. Viděl jsem, jak uživatel Woknous zpracoval PostScriptový soubor pro PostScriptovou tiskárnu. Řeknu vám, byl to zážitek. Nejprve natáhl PostScriptový soubor do Woknousového GhostWiew a dal požadavek k tisku. GhostView byl konfigurován tak, že spustil Ghostscript pro interpretaci PostScriptu a vytvořil sekvenci grafických pokynů na úrovni API. Woknousy to zpracovaly a předaly ovladači pro tiskárnu. Ovladač z toho vygeneroval nový PostScript, který předal tiskárně. Tiskárna ten PostScript interpretovala znovu. Skutečnost, že to vůbec fungovalo, je přece úžasná!

Uživatel Woknous má jistě další možnosti. Objevil jsem tuto: na velmi nelogickém místě v systému konfiguračních nabídek se najde provázání skutečného výstupního portu tiskárny s DOSovým logickým portem LPT1 až LPT nevím kolik. Ten skutečný výstupní port může být fyzicky na tiskárně nebo to může být odkaz na síťový server a tiskárnu na něm. Z DOSu ve Woknous se pak dají posílat data do uvedeného logického portu, která jsou přesměrována do výstupního portu bez žádné interpretace, prostě tak, jak jsou. Takže uživatel Woknous může v DOSu poslat text na řádkovou tiskárnu pomocí copy soubor.txt lpt1 nebo může PostScriptový soubor vytisknout přímo bez drbání se pravou rukou za levým uchem povelem copy soubor.ps lpt2.

Věčný DOS

U DOSových aplikací se předpokládalo, že každá aplikace bude umět vygenerovat jazyk všech tiskáren, které jsou na trhu. To je velmi špatná koncepce, která činí DOSové aplikace závislé na typu tiskárny. DOS je tedy použitelný jen pro výstup na řádkových tiskárnách nebo při použití aplikací, které náhodou generují jazyk shodný s jazykem naší tiskárny.

Při propojení DOSových klientů s Unixovými tiskovými servery existuje ještě jeden problém, na který jsem už kdysi dávno narazil při připojování DOSových klientů přes PCNFS. Zatímco Unixový program lpr vytvoří kompletně "zapouzdřenou" tiskovou úlohu (má jasně definovaný začátek a konec), DOSová aplikace nic takového nedělá. Ta prostě posílá do portu tiskárny data. Někdy se odmlčí, protože se třeba zamyslí nad nějakým mezivýpočtem, a pak pokračuje v zasílání dat do portu. Otázka, kde končí jedna úloha a začíná druhá je pro DOS nezajímavá. Ve víceuživatelských a víceúlohových systémech nás ale tato otázka silně zajímá. Proto tiskové servery, které přijímají úlohu z DOSu, mají možnost konfigurace časové prodlevy, po jejímž překročení server shledá úlohu za ukončenou a zapouzdří ji. Prodleva bývá nastavena zhruba na půl minuty. Uživatel tisknoucí z DOSu pak jako střela vyběhne ze své kanceláře k tiskárně, kde půl minuty musí přešlapovat, než server ukončí příjem úlohy a úlohu začne tisknout. Uživatel při přešlapování mudruje něco o tom, že informace by se po síťových kabelech měly šířit rychlostí světla. Delší časová prodleva by znamenala delší přešlapování DOSových uživatelů před tiskárnami a více mudrování. Na druhé straně kratší prodleva by mohla znamenat nepříjemné roztržení úlohy v místě, kde se DOSová aplikace pouze zamyslí, protože je tak blbě naprogramovaná. Druhá část úlohy by pak nemusela mít správně definovanou hlavičku a mohla by způsobit, že by byl přešlapující a mudrující uživatel zavalen tunami nesprávně potištěných papírů a jeho důvěra v počítačovou techniku by klesla na nulu.

Síťové propojení tiskáren

Unixový tiskový démon lpd umí přijmout tiskovou úlohu ze sítě nebo z lokálu, uložit ji do spooleru, aplikovat na jednotlivé úlohy ze spooleru případný filtr, přeposlat úlohu kolegovi démonovi z jiného počítače kdekoli v TCP/IP síti a konečně poslat úlohy na lokální port, ke kterému je připojena tiskárna. Programem lpr může uživatel tiskovou úlohu vytvořit a pokud se nestačila vytisknout, může ji uživatel zrušit pomocí programu lprm. Konečně program lpc je určen pro správu tiskáren (pozastavení tisku, přerovnání tiskové fronty, restart démona atd.) a většinu svých funkcí umožňuje jen správci systému. Toto programové vybavení je staré jak Metuzalém, ale je stále nenahraditelné.

Na naší katedře je šest veřejně používaných tiskáren umístěných ve společné místnosti. Jedna je připojena přímo na linuxový server paralelním kabelem (který vede krz zeď a je poněkud delší, než připouští norma ajtripl-í, ale problémy se nedostavily). Další dvě tiskárny jsou připojeny ke staršímu SUNu jednou paralelně a jednou seriově krz zeď, další tiskárna má vlastní síťovou kartu a k posledním dvěma jsme dokoupili síťový printservřík.

Printservřík je taková sympatická tichá a malinká krabička, na níž z jedné strany kouká konektor pro připojení ke 100MB síti a na druhé straně vidíme tři paralelní porty. Využil jsem z nich zatím jenom dva. Při nákupu tohoto zařízení jsem se neobešel bez problémů. Na můj dotaz, zda nabízený printservřík umí po síti komunikovat stejně jako unixové lpd, mi žádný prodavač nebyl schopen odpovědět. Někteří z nich začali dokonce plácat něco o tiskových ovladačích k jednotlivým tiskárnám, čímž naznačili, že totálně nevědí, která bije. Je pravda, že jsem si mohl technickou specifikaci různých výrobků přečíst na Internetu, ale chtěl jsem si vyzkoušet pohotovost prodavačů. Jedna firma nám nabídla, že nám zařízení na krátkou dobu zapůjčí. Jakmile jsem otevřel manuál, věděl jsem, že printservřík můj požadavek o unixovém lpd splňuje. Šlo o Micronet PSHX3P-B.

Škatulka naběhne v režimu, kdy sice nezná své IP číslo, ale dá se jí toto číslo vnutit na libovolném Unixu pomocí arp -s IP.číslo hw:ad:re:sa. HW adresa je odvozena od sériového čísla, které lze najít na spodní straně krabičky. Pak už se dá z krabičky pomocí FTP získat textový konfigurační soubor, upravit jej a poslat zpět. Bylo potřeba dizejblovat SMB protokol, aby mi na krabičku neposílaly Woknousy úlohy přímo. Dále jsem NEkonfiguroval bránu (gejtwej), protože lpd server v krabičce neumí spolupracovat se známým souborem hosts.lpd, tj. nelze omezit tisk jen z vybraných mašinek. Protože nechci, aby mi na tom tisknul kdokoli z Internetu, zůstává krabička díky nekonfigurované bráně mimo segment sítě naší katedry neviditelná. Kdo chce tisknout z větší vzdálenosti, pošle úlohu na lpd běžící na našem linuxového serveru, ten ji po kontrole v hosts.lpd odmítne nebo akceptuje a v druhém případě ji přepošle na lpd do printservříku.

Na linuxovém serveru mi běží samba, která nabízí uživatelům MS Woknous tisk na všech veřejných tiskárnách. Pokud uživatel na klientovi konfiguruje výstupní port třeba ve tvaru \\masina\fs1, samba na serveru masina provede autentizaci uživatele a spustí lpr -Pfs1. Tisková úloha je dále zpracovávána unixovým lpd pro tiskárnu s názvem fs1. Na serveru mám printcap zhruba ve tvaru, jak ukazuje Výpis 1.


# printcap
# řádky začínají bez mezer a pokračovací řádky začínají tabelátorem

lj4|LaserJet4:\
        :lp=/dev/lp0:\
        :mx#50000:rw:sh:\
        :sd=/var/spool/lj4:\
        :lf=/var/adm/lj4-errs:\
        :rg=lj4user:

dj8|dj880c|DeskJet880Color:\
        :lp=/dev/null:\
        :mx#50000:sh:\
        :sd=/var/spool/dj8:\
        :if=/etc/tisky/filter-dj8:\
        :rg=dj8user:
dj8raw:\
        :lp=:rm=printservrik:mx#50000:rp=L2:sd=/var/spool/dj8raw:rg=daemon:

ep24:\
        :lp=:rm=starysun:mx#50000:rp=ep24:sd=/var/spool/ep24:rg=ep24user:
lj3:\
        :lp=:rm=starysun:mx#50000:rp=lj3:sd=/var/spool/lj3:rg=lj3user:

lp|fs1|FS1750:\
        :lp=/dev/null:\
        :mx#50000:sh:\
        :sd=/var/spool/fs1:\
        :if=/etc/tisky/filter-fs1:\
        :rg=fs1user:
fs1raw:\
        :lp=:rm=printservrik:mx#50000:rp=L1:sd=/var/spool/fs1raw:rg=fs1user:

cp6|cp660|CanonCP660:\
        :lp=:rm=cp660:mx#50000:rp=xjprint:sd=/var/spool/cp6:rg=cp6user:
cp6d|cp6dup|cp660dup:\
        :lp=/dev/null:\
        :mx#50000:sh:\
        :sd=/var/spool/cp6d:\
        :if=/etc/tisky/filter-cp6d:\
        :rg=cp6user:
cp6m|cp6manual|cp660manual:\
        :lp=/dev/null:\
        :mx#50000:sh:\
        :sd=/var/spool/cp6m:\
        :if=/etc/tisky/filter-cp6m:\
        :rg=cp6user:

Výpis 1

Jednoduchý filtr

Z Výpis 1 je patrné, že uživatelé mají více logických jmen, než vlastních tiskáren. Zabývejme se nejprve tiskárnou HP DeskJet880, která má logická jména dj8 a dj8raw. Při použití jména dj8 je tiskové úloze vložen do cesty filtr specifikovaný parametrem if. Obsah tohoto skriptu vidíme na Výpis 2. Na druhé straně jméno dj8raw je použito pro přímou komunikaci s tiskárnou bez aktivace filtru. Protože užití tiskárny dj8raw je dovoleno jen skupině daemon, nemohou na ni běžní uživatelé tisknout přímo. Díky inteligenci filtru to ani nepotřebují. Vlastnosti filtru si nyní popíšeme.


#!/bin/bash

# This filter runs gs if the '%!' are first two chars on input.
# Nov 1999                                    Petr Olsak

dd of=/tmp/pprint.$$ count=1 bs=2 2> /dev/null

if echo -n '%!' | cmp - /tmp/pprint.$$ > /dev/null ; then
# The PrintJob is in PostScript, we start GhostScript filter:
  cat /tmp/pprint.$$ - | \
    gs -q -sDEVICE=cdj880 -sPAPERSIZE=a4 -dNOPAUSE \
       -dSAFER -dBATCH -sOutputFile=- - | lpr -U $5 -Pdj8raw
else
# The PrintJob contains raw data, no changes are needed:
  cat /tmp/pprint.$$ - | lpr -U $5 -Pdj8raw
fi

rm /tmp/pprint.$$

Výpis 2

Protože je tiskárna HP DeskJet880 připojena na printservřík, použitý filtr vlastně není v pravém slova smyslu filtrem s výstupem na standardní výstup. Pokud by byla tiskárna připojena dejme tomu na /dev/lp1, zrušili bychom v printcapu jméno dj8raw a pro tiskárnu dj8 bychom konfigurovali přímo lp=/dev/lp1. Ve skriptu bychom umazali na dvou místech text "| lpr -U $5 -Pdj8raw" a mohli bychom tisknout lokálně. Tehdy by filtr skutečně četl standardní vstup a případně modifikovaná data předával na standardní výstup. Démon lpd nasměruje tento výstup do zařízení specifikovaného parametrem lp.

Ptáte se, proč nelze zařadit filtr přímo pro tiskárnu, která má v printcapu konfigurováno rm=jinam pro přesměrování úlohy jinému lpd démonovi? Jednoduše proto, že v tomto případě démon filtr do úlohy zařadit nemumí. Ptáte se proč neumí? To já nevím.

Filtr z Výpis 2 má následující vlastnosti. Sejme pomocí dd z tiskové úlohy první dva bajty a zkontroluje, zda tyto bajty neobsahují text %!. Pokud ano, jedná se o PostScriptovou úlohu. Každá PostScriptová úloha musí začínat těmito znaky. V takovém případě filtr nasadí Ghostscript. Inkoustová tiskárna HP DeskJet880 totiž sama PostScript neumí. Pokud ale první dva znaky jsou jiné, jedná se o úlohu, která je zřejmě přímo v jazyce tiskárny (vytvořil ji asi Woknousový klient). Filtr proto příkazem cat spojí odloupnuté dva bajty se zbytkem úlohy a bez interpretace pošle úlohu na výstup. Výstupem je v případě připojení tiskárny na printservřík povel lpr -U $5 -Pdj8raw, což způsobí přesměrování úlohy do printservříku. Přitom vlastnictví úlohy zůstává díky parametru -U původnímu uživateli, který ji může pomocí lprm ve frontě dj8raw případně likvidovat.

Tiskárna HP DeskJet880 nemá v současné době modul do Ghostscriptu přímo v jeho distribuci. Modul naštěstí existuje zvlášť na

http://www.proaxis.com/mgelhaus/linux/software/hp880c/hp880c.html.

Lze postupovat podle návodu z této stránky a zakompilovat do Ghostscriptu 5.50 nové zařízení cdj880. Nebyly s tím žádné problémy. V této souvislosti upozorňuji na to, že například k tiskárnám HP DeskJet7xx jsem nikde modul do Ghostscriptu nenašel, takže tyto modely jsou pro Unix nepoužitelné. Jeden takový model na katedře už nějakou dobu máme a je připojen lokálně v kanceláři uživatele používajícího výhradně Woknous. Nic jiného se s takovou tiskárnou dělat nedá.

Při návrhu filtrů je nutno nezapomenout na úvodní specifikaci shellu pomocí dvojznaku #!. Jednou jsem byl lenivý tak učinit, protože jsem navrhoval jednořádkový filtr a krutě jsem na to doplatil. Přitom ti mezci, co psali manové stránky pro lpd a printcap, se ani slůvkem nezmínili o tom, že specifikace shellu je ve filtru povinná. Stálo mě to několik hodin zbytečného času.

Složitější filtr

Popíšeme nyní zajímavější filtr pro tiskárnu fs1. Jedná se o černobílou laserovou tiskárnu Kyocera, která umí PostScript a má duplexní podavač (tj. umí tisknout oboustranně). Protože to je tiskárna s nejlevnějším provozem, rozhodl jsem se na ni přenést hlavní zátěž tisků na naší katedře. Proto jsem ji ztotožnil se jménem lp, následkem čehož veškeré tisky, ve kterých uživatel nespecifikuje tiskárnu, jsou přesměrovány na Kyoceru. Tiskárna tedy musí zvládnout jednak předžvejkanou úlohu z MS Woknous, jednak PostScript z Unixu a jednak musí emulovat řádkovou tiskárnu pro tisk "holých" textových souborů. Přitom tyto textové soubory mohou být kódovány v různých češtinách a filtr by to měl zjistit a za všech okolností vytisknout správně. Uživatel se nemusí zabývat, v jaké češtině má textový soubor připraven.

Filtr k této tiskárně vidíme na Výpis 3. Pokud je úloha PostScriptová, filtr k ní připojí PostScriptový pokyn pro oboustranný tisk a úlohu přepošle na výstup. Protože i tato tiskárna je připojena na printservřík, je výstupem nový povel lpr, ovšem to nás už nepřekvapuje. Soubor duplex.ps vidíme na Výpis 4. Pokud by někdo chtěl méně často orientovaný duplex (převracení stránky přes kratší hranu), musel by sám PostScriptový pokyn do výstupního souboru naeditovat. Místo false settumble by napsal true settumble a výstup by pustil přímo na fs1raw, aby obešel filtr.


#!/bin/bash
# Nov 1999                                    Petr Olsak

dd of=/tmp/pprint.$$ count=1 bs=2 2> /dev/null

if echo -n '%!' | cmp - /tmp/pprint.$$ > /dev/null ; then
# The PrintJob is in PostScript, we insert a duplex command:
  echo `date '+%X, %d.%m %Y'`: $5 "PS-duplex" > /var/log/fs1-use
  cat /etc/tisky/duplex.ps /tmp/pprint.$$ - | lpr -U $5 -Pfs1raw
  rm /tmp/pprint.$$
  exit
fi

# Ten dvojznak ^[ níže je ve skutečnosti jediný znak Escape (kód 27)
if grep '^[' /tmp/pprint.$$ > /dev/null; then
# The PrintJob contains raw data from Windows, no changes are possible:
  echo `date '+%X, %d.%m %Y'`: $5 "MS-Win" > /var/log/fs1-use
  cat /tmp/pprint.$$ - | lpr -U $5 -Pfs1raw
  rm /tmp/pprint.$$
  exit
fi

cat /tmp/pprint.$$ - > u$$.txt

if cat u$$.txt | tr 'X\000-\010\016-\031\033-\037' 'B[X*26]' |\
   grep -l X >/dev/null; then
#  Binary data?
   echo `date '+%X, %d.%m %Y'`: $5 "Binary" > /var/log/fs1-use
   lpr -U $5 -Pfs1raw u$$.txt    
   rm /tmp/pprint.$$ u$$.txt
   exit
fi

# The PrintJob contains ASCII text, we will test encoding of CZ
# Tři tečky níže (...) znamenají "atd". Ve skutečném skriptu jsou
# důsledně vypsány všechny kódy, které do testovaného kódování nepatří
# v osmičkovém tvaru, což se nedá do časopisu tisknout, neboť řádky
# jsou pak příliš dlouhé. 
# Pro jednoduchost jsem ponechal pouze rozlišení mezi kódováním
# Kamenických a ISO8859-2.
if cat u$$.txt | tr 'X\200-\377' 'B[X*128]' | grep -l X >/dev/null; then
#  Úloha obsahuje znaky nad kód 128
   if cat u$$.txt | tr \
      'X\200-\214\216-\227\231-\233...\367\373' 'B[X*128]' |\
      grep -l X >/dev/null; then
#     Kódování není podle ISO8859-2
      if cat u$$.txt | tr 'X\260-\377' 'B[X*128]' |\
        grep -l X >/dev/null; then
#       Kódování není ani podle Kamenických
#       Neznámé kódování, ponecháme ISO8859-2
        trfile=il2-cs
      else
#       Kódování je podle Kamenických
        trfile=kam-cs
      fi
   else
#     Kódování je podle ISO8859-2
      trfile=il2-cs
   fi
else
#  Úloha neobsahuje znaky nad kód 128
#  Kódování US ASCII text
   trfile=il2-cs
fi

# We make PostScript via TeX
ln -s /usr/local/share/texmf/tex/plain/misc/verbtisk.tex u$$.tex
tex -fmt=csplain -translate-file=$trfile \
  \\def\\user{$5@$7}\\def\\file{u$$.txt}\\input u$$ \\act\\end >/dev/null
echo `date '+%X, %d.%m %Y'`: $5 "Plain-text" [$trfile] > /var/log/fs1-use
dvips -h duplex.ps -o - u$$ | lpr -U $5 -Pfs1raw
rm /tmp/pprint.$$ u$$.tex u$$.dvi u$$.log u$$.txt

Výpis 3

Je-li mezi prvními dvěma znaky úlohy znak iskejp (kód 27), jedná se o úlohu z Woknous. Pozorováním jsem zjistil, že ačkoli ovladač ve Woknous generuje PostScriptový kód, neodpustí si na začátku úlohy poněkud zbytečnou iskejp sekvenci o tom, že tisková úloha je připravena v PostScriptu. Tiskárna této sekvenci rozumí, takže úlohu bez interpretace filtrem předáme přímo tiskárně. Uživatel Woknous může v grafické nabídce ovladače zatrhnout, zda chce duplexní tisk a jaký, takže ani tuto otázku neřešíme a požádáme všechny uživatele Woknous, aby si v ovladači zatrhli implicitně duplex, protože šetříme při tisku papírem.


statusdict begin true setduplexmode false 
settumble end

Výpis 4

Pokud se v úloze vyskytují znaky nepoužívané v holých textových souborech, předpokládáme, že se jedná o binární soubor, který zřejmě vygeneroval nějaký zmatený ovladač ve Woknous. Pokusíme se úlohu bez interpretace vytisknout, ovšem na zodpovědnost uživatele, který to spáchal.

V ostatních případech se dá předpokládat, že úloha obsahuje holý textový soubor a filtr bude emulovat řádkovou tiskárnu prostřednictvím TeXu. Nejprve se filtr pokusí zjistit, v jaké češtině je úloha připravena. Výsledek uloží do proměnné trfile. Úloha je konvertována do PostScriptu pomocí TeXového formátu csplain za použití konverzní TCX tabulky trfile.

Na Výpis 5 vidíme TeXový soubor verbtisk.tex, který bude zajímat zvláště TeXové fajnšmekry. Makro TeXu zde řeší kompletní verbatim tisk souboru včetně patičky se jménem uživatele a času tisku a včetně interpretace tabelátorů, které mají vytvořit jednu nebo více mezer tak, aby další znak začínal v nejbližším sloupci, který je násobkem osmi.


%% Fonty
\font\tt=cc at 10pt
\font\it=ptmri8z at 7pt

%% Výpočet hodiny a minuty
\newcount\hour \newcount\minute \newcount\hhour
\hour=\time \minute=\time
\divide\hour by 60
\hhour=\hour \multiply\hhour by 60
\advance\minute by -\hhour

%% Paticka
\csaccents
\footline={\it u\v zivatel: \user,\hskip4em
           dne: \the\day. \the\month. \the\year, 
           \the\hour:\ifnum\minute<10 0\fi
           \the\minute 
           \hfill strana: \the\pageno \hskip1cm}

%% Rozměry zrcadla
\hoffset=-1in \advance\hoffset by 2cm
\voffset=-1in \advance\voffset by .8cm
\advance\hsize by 2.7cm \advance\vsize by3.3cm
\baselineskip=11.7pt
\parindent=0pt

%% Makro pro tabelátor
\newdimen\lastlinewidth  \newcount\tabwidth
\setbox0=\hbox{\tt xxxxxxxx}
\tabwidth=\wd0 %% kazdych 8 znaku je zarazka
\predisplaypenalty=10000 
\postdisplaypenalty=10000
\def\tab{$$\advance\predisplaysize by-2em
         \global\lastlinewidth=\predisplaysize
         \abovedisplayskip=-\baselineskip 
	 \belowdisplayskip=-\baselineskip
         \predisplaysize=\maxdimen$$
         \divide\lastlinewidth by\tabwidth
         \advance\lastlinewidth by1sp
         \multiply\lastlinewidth by\tabwidth
         \hskip\lastlinewidth\null}

%% Příprava na verbatim
{\obeyspaces 
 \gdef\activespace{\obeyspaces\let =\ }
 \catcode`\^^I=13 \catcode`\^^L=13
 \gdef^^I{\tab}
 \gdef^^L{\endgrafl\break}
}
\def\setverb{%
\def\do##1{\catcode`##1=12}\dospecials}

%% Načtení souboru jako verbatim:
%% csplain \def\file{nazev.txt}
%%    \def\user{uzivatel}\input verbatisk \act\end
\def\act{\bgroup \setverb \activespace 
  \catcode`\^^I=13 \catcode`\^^L=13
  \def\par{\endgraf\leavevmode} 
  \obeylines \tt
  \input\file\space
  \egroup} 

Výpis 5

Font cc (Courier Condensed) jsem pro TeX připravil pomocí povelů z Výpis 6. Výsledný PostScript tedy neobsahuje žádné předloudované fonty a využívá pouze fonty vestavěné do PostScriptového interpretu každé tiskárny. Program dvips připraví výstup tak, že fonty v tiskárně nemusejí vůbec být české; akcentované znaky jsou v PostScriptovém kódu sestaveny pomocí komponent. Je to tedy robustní řešení. Vidíme také, že v zájmu šetření papírem zařazuji programem dvips do úlohy pokyn pro duplexní tisk, takže nám emulátor řádkové tiskárny bude tisknout jednak úhledně a jednak oboustranně.


$ cd ~/prac
$ cp /usr/lib/a2ac/cscorr.tab .
$ cp /usr/lib/a2ac/xt2.enc .
$ ftp ftp.adobe.com
    ... získáme soubor com_____.afm
$ mv com_____.afm courier.afm
    ... font courier se v Ghostscriptu nahrazuje fontem NimbusMonL-Regu.
        Je tedy možné soubor courier.afm získat též takto:
$ cp /usr/share/ghostscript/fonts/n022003l.afm courier.afm
$ vi cscorr.tab
    ... Upravit, aby šířka ď a ť byla stejná jako šířka ostatních písmen
        prakticky to znamená zrušit řádky RWX
$ a2ac courier.afm cscorr.tab cscourier.afm
$ afm2tfm cscourier.afm -e 0.8 -t xt2.enc -v cc rcc
$ vptovf cc.vpl cc.vf cc.tfm
$ su
# vi /usr/share/texmf/dvips/config/psfonts.map
    ... Přidat řádek:
        rcc Courier ".8 ExtendFont"
# cp rcc.tfm /usr/share/texmf/fonts/tfm/adobe/raw/
# cp cc.tfm /usr/share/texmf/fonts/tfm/adobe/a2ac/
# cp cc.vf /usr/share/texmf/fonts/vf/adobe/a2ac/
# mktexlsr

Výpis 6

Více podavačů

Další tiskárna, kterou bylo potřeba připojit, byla tiskárna Canon CP660, barevná, laserová s možností tisku na A3 s duplexním podavačem a PostScriptem level 3. Tato tiskárna se dodává se síťovou kartou a diskem. Je to poměrně velké monstrum. Na ovládacím panelu tiskárny se dá nakonfigurovat IP připojení. Dizejbloval jsem SMB a IP bránu ze stejných důvodů, jako u printservříku. Tiskárna automaticky startuje WWW server, takže plno administrativních úkonů lze dělat z WWW brousítka. Netskejp ale v některých uživatelských konfiguracích padal; zatím se mi nepodařilo odhalit proč. Ovšem to není pro připojení tiskárny do sítě nejdůležitější. Podstatné je, že tiskárna má svůj lpd, který dokáže akceptovat unixové tiskové úlohy ze sítě.

Tiskárna má dva spodní zásobníky, jeden na A4 a druhý na A3. Pokud tisková úloha obsahuje PostScriptovou instrukci o formátu papíru A3, tiskárna si automaticky vezme papír ze zásobníku A3, jinak (implicitně) bere papír ze zásobníku A4. Povel dvips -tA3 -Pcp6 soubor tedy způsobí tisk na papíry A3, zatímco dvips -Pcp6 soubor vyjede úlohu na papírech A4.

Mimoto má tiskárna postranní zásobník (tzv. manuální podavač) a dá se jí PostScriptovými instrukcemi říci, aby papír vyjížděl nikoli nahoře potiskem dolů, ale naproti postrannímu zásobníku potiskem nahoru. Papír pak může projet z manuálního podavače krz tiskárnu zcela rovně a bylo vyzkoušeno, že tímto způsobem lze protáhnout tiskárnou velmi tvrdé papíry, kterým já z legrace říkám překližky. Tato dráha by se měla volit též při tisku na transparentní fólie.

Protože unixový uživatel nemá k dispozici Woknousový ovladač se zaškrtávátky, kde by si mohl nastavit cestu papíru, zavedl jsem pro něj kromě logického jména cp6 ještě jména cp6m a cp6d. Při tisku na cp6m (CP660-manual) přidá filtr na začátek úlohy PostScriptové instrukce k "ručnímu" tisku, tj. tiskárna vezme papír z manuálního podavače a vyplivne jej naproti potiskem nahoru. Varianta cp6d (CP660-duplex) aktivuje jiný filtr, který přidá na začátek úlohy PostScriptové pokyny pro oboustranný tisk.

Uživatelé tedy nemusejí volit způsob podávání papíru z panelu na tiskárně, ale každá tisková úloha si nese s sebou definici o tom, kudy má papír procházet. Uživatelé si tak vzájemně nekonkurují. Jeden uživatel může založit průsvitné fólie do manuálního podavače, zatímco jiný uživatel tiskne běžnou úlohu ze spodního zásobníku. Na naší starší tiskárně připojené k síti se mohlo stát, že uživatel přepnul na panelu manuální podávání, založil fólie a než se stačil vzpamatovat, jiný uživatel mu je potisknul. To nepřispívalo k vzájemné pohodě mezi uživateli. Proto jsem kdysi vyráběl speciální "přivlastňovací" skript lpown, který způsobí, že tisk na tiskárně může realizovat jen uživatel, který skritp spustil, zatímco úlohy ostatních uživatelů zůstaly zablokovány. Protože tiskárnu občas někdo zapomněl odblokovat, ani toto řešení nepřispívalo příliš k pohodě mezi uživateli.

Tiskárna CP660 má poněkud samorostlý lpd démon, který kašle na to, který uživatel úlohu zaslal. Jméno uživatele každé úlohy se démon pokouší přečíst ze záhlaví úlohy v PostScriptových komentářích. Pokud tam jméno uživatele nenajde, úloha se ve frontě v tiskárně tváří, jakoby patřila uživateli UNKNOWN. Považuji to za chybu v implementaci démona v tiskárně, ale zase mě to tak moc nevadí. Tiskárna vytváří podrobný logovací soubor, kde je řečeno, kdo co a kolik černobílých a kolik barevných stránek a jaké velikosti kdy natisknul. Unixoví uživatelé ale zůstávají z hlediska tohoto souboru v příjemné anonymitě skryti pod společným jménem UNKNOWN. Woknousoví uživatelé jsou ovšem logováni se všemi detaily, protože jejich ovladače vytvářejí PostScriptové komentáře přesně podle představ tiskárny. Mohl bych sice zařadit do tisku filtr, který by přidával do tiskové úlohy tyto PostScriptové komentáře i pro unixové uživatele, ale zatím mě okolnosti netlačí toto dělat.

Ostatní tiskárny

Při pohledu do printcapu z Výpis 1 vidíme, jak jsou k linuxovému serveru připojeny ostatní tiskárny. Lejzrovka HP Laserjet4 je připojena přímo na paralelní port /dev/lp0. Protože tiskárna umí PostScript a není na ni potřeba emulovat řádkovou tiskárnu, není v tomto případě použit žádný filtr.

Poslední dvě tiskárny jsou připojeny ke starému SUNu. Tiskárny i komp jsou muzejní exponáty, ovšem stále funkční. Máme je v provozu asi od roku 1993. Občas je potřeba ze SUNa utřít prach a kabely osvobodit od pavučin. Žádnou jinou údržbu toto zařízení nepotřebuje. Celé roky ani nevíme, že si to tam v koutečku pořád spokojeně funí. Na SUNovi jsem kdysi instaloval Ghostscript (kdybych se tam podíval, asi bych se zhrozil, jak starověká verze to je). Obě tiskárny mají konfigurován inteligentní filtr, který podle prvních dvou znaků úlohy (%!) pozná, zda se jedná o PostScript nebo ne. Pokud ano, zařadí Ghostscript a přeloží úlohu podle cílové tiskárny buď do jazyka Epsonky (24 jehlová tiskárna) nebo do jazyka PCL (tiskárna LaserJet 3).

Monitorování tisků

Jak jsem již uvedl výše, tiskárna CP660 monitoruje tiskové aktivity Woknousových uživatelů důkladně. Bohužel, protože unixový lpd je software starý jak Metuzalém, nemá zmáknuté monitorování stránek grafického tisku. Počítání řádků textových tiskových úloh je nám v dnešní době k ničemu. Protože jsou ale tiskové úlohy mnohdy ve spooleru už předžvejkány Woknousovými ovladači do jazyka tiskáren, je zhola nemožné zjistit počet vytištěných stránek, aniž bychom museli programovat interpret jazyka tiskárny. Kdyby všechny tiskové úlohy byly v PostScriptu, šlo by teoreticky interpretovat je Ghostscriptem a zjistit tak počet vytištěných stránek. Domnívám se ale, že to je příliš nákladný monitoring, zvláště pokud tiskárna je PostScriptová a úlohu by musela interpretovat ještě jednou.

Kdysi dávno jsem udělal v rámci tiskových filtrů na starých SUNech jednoduchý monitoring tisku. Počítal jsem jednotlivé úlohy každého uživatele a dobu trvání tisku každé úlohy. Celkový počet úloh a součet doby trvání tisku každého uživatele jsem pak automatem zpracoval a jednou měsíčně (prvního v měsíci, 13 minut po půlnoci) automat poslal report í-mejlem naši paní šéfové. Počet vytištěných stránek se bohužel tímto způsobem nedozvěděla. *


- předchozí článek - následující článek - obsah - úvodní stránka -