Nejc Bertoncelj

COPRIS

3. 2. 2023, urejeno 25. 9. 2023

COPRIS (Converting Printer Server) je tiskalniški strežnik, napisan kot preprostejša alternativa sistemu CUPS. Izdelal sem ga za potrebo tiskanja besedila prek matričnega tiskalnika [1], [2], prisotnega v lokalnem omrežju.

Izvorna koda: https://github.com/bertronika/copris. Najnovejša navodila: copris.1.txt.

„Izkoristi obstoječa orodja“

Tiskanje besedila prek omrežja naj bi bilo za sistem CUPS mala malica, a so moji eksperimenti vodili v nasprotno smer. Matrični tiskalnik Epson LX–300 sem prek pretvornika vzporedna vrataUSB priključil na strežnik z Linuxovo distribucijo, vstopil v CUPS-ov spletni vmesnik, dodal tiskalnik in ga postavil v skupno rabo. Vse dobro. Na svojem računalniku sem nato dodal omrežni tiskalnik, in postopek je bil zaključen… Do prvega poskusnega tiskanja (echo "Halo!" | lpr), ki ni proizvedlo nobene fizične kopije. Tudi drugo ni. Morda gre pa v tretje rado, in res, značilen (beri: neznosen) zvok tiskanja, in pred mano je bil preizkusni izpis. Vendar pa to ni bil zaključek diagnostične seje, saj je le na vsak tretji poskus tiskalnik dejansko tiskal. Občasno je še to odpovedalo, v kernelovem zapisniku pa se je pojavila neka napaka glede pisanja na virtualni tiskalniški vmesnik (žal si je nisem shranil). Iztakniti in nazaj vtakniti pretvornik je bila rešitev. Morda strojna oprema noče sodelovati? Poskusil sem še najbolj preprost način – na strežniku sem zaganjal echo "Ahoj!" > /dev/usb/lp0. Delovalo je prav vsakokrat.

Brskanje po medmrežju ni preveč pomagalo, napaka je bila pač preredka. Sošolec mi je že ponujal svoj pretvornik, če je morda moj okvarjen, ali pa je njegov gonilnik v Linuxu nepopoln. Vendar sem po vseh poskusih opazil še drug neželjen vzorec – CUPS je vedno tiskal v grafičnem načinu. To je sicer (dandanes) smiselna nastavitev, saj želimo dokumente natisniti s točno takimi pisavami, velikostmi in postavitvami, kot so v digitalni obliki dokumenta. Moj tiskalnik pa je bil le 9-iglični, kar pomeni, da je bila kakovost natisnjenega besedila po pretvorbi vektorskih pisav v nizkoločljivostne približke precej slaba. Dejansko je bilo pisanje neobdelanega besedila neposredno v tiskalnik najkakovostnejša metoda, saj ta že vsebuje vgrajene, lepo berljive pisave. Dobro, se da CUPS prepričati, da ne obdela besedila in ga surovega pošlje tiskalniku? Ne! Vsaj sam nisem našel take metode, obstajajo rešitve, ki surovo besedilo pretvorijo v PostScript ali PDF in ga pošljejo tiskalniku, vendar lahko samo upaš, da bodo črke ostale na istih mestih (le kaj bo s šumniki?).

netcat – revežev strežnik 

Po neuspehih s CUPS-om sem programski sklad znatno poenostavil. Pisanje surovega besedila v Linuxovo znakovno napravo deluje, lahko bi jo le izpostavil lokalnemu omrežju. V igro vstopi nc(1), vsestranski program za delo z vtičnicami TCP, UDP, celo UDS. Z uporabo zastavice -l ga zaženemo kot strežnik, standardni izhod pa preusmerimo neposredno na tiskalnik. Dodajmo še -k, ki ne zapre procesa po prekinitvi prve seje, in strežniška stran je končana. Na uporabniški strani uporabimo isti program, na standardni vhod preusmerimo želeno besedilo in dodamo še -N, da lahko s Ctrl-D prekinemo interaktivno sejo. Nobenih gonilnikov, nobene obsežne (ali manjkajoče) dokumentacije, le standardna orodja.

Kaj pa slovenščina? 

V angleško govorečih državah bi ta programska postavitev zadostovala. Vendar pa v Sloveniji želimo tiskati slovenska besedila. Zakaj bi to bila ovira?

$ (printf 'n' | hexdump -C); printf 'č' | hexdump -C
00000000  6e                                                |n|
00000000  c4 8d                                             |..|

Prav vse slovenske črke (ki niso del angleške abecede), so v UTF-8 kodirane z dvema bajtoma. Oba bajta črke ‘č’ ležita izven nabora ASCII, kar nakazujeta dve piki v zgornjem izpisu programa hexdump(1). Drugi znaki so lahko kodirani še z več bajti, simbol za evro ‘€’ se npr. kodira s tremi, trenutni maksimum pa je na štirih bajtih. Stari tiskalniki kodiranja UTF-8 ne poznajo in tolmačijo vsak bajt posebej. Kam kažeta šestnajstiška c4 in 8d? Na nam nepričakovana mesta v tiskalnikovi privzeti kodirni tabeli, kar povzro▄a zmedo s ╝umniki.

A tiskalnik šumnike vendarle pozna! V mojem Epsonu se nahaja pomnilnik EPROM, na njem nalepka ljubljanskega podjetja Repro, ki je tiskalnik uvozilo in predelalo za naš trg. Kje pa jih najdemo? Na mestih nekaterih drugih znakov, na primer: ‘Č’ dobimo z vnosom ^, ‘š’ z {, ‘Ž’ pa z @. Enkodiranje je neformalno poimenovano YUSCII in je obstajalo že za teleprinterje, zato ga je prevzel tudi računalniški sektor.

Potrebujemo torej pretvorbo besedila (kaj že pomenita prvi dve črki kratice COPRIS?). Spet sem imel na voljo standardna orodja, na primer tr ali sed. Spisal sem torej skript v Bash-u, izumil ‘definicijske’ datoteke, ki so transformirale večbajtne znake v ustrezne enobajtne, in naslednji prototip je ugledal luč… le moje sobe (na srečo).

Sistem je bil izjemno krhek in nerazširljiv, napake se je težko zaznalo. Program tr (GNU Coreutils) bi za pretvorbo znakov ustrezal bolje, vendar še v času pisanja ne podpira večbajtnih znakov. Skrajni čas za ustrezno izvedbo.

Kako napisati svoj netcat? 

Izbral sem programski jezik C. Do tedaj resneje še nisem programiral, za seboj sem imel malce večji projekt na platformi Arduino, kak skript v Bashu, nekaj poskusov Pythona in ducat laboratorijskih vaj iz Programiranja II. Predmetnik 2. letnika dodiplomske elektronike je kazal dobršno mero programiranja mikrokrmilniških sistemov, zato se je zavoljo dobrega predznanja izbira zdela smiselna.

Jezik imamo. Kaj pa program? Od kod se naučiti komunikacije z Internetom? Na Internetu, seveda. Izvedba vtičniškega strežnika je na srečo zelo pogost programerski izziv, zato je virov veliko (naj omenim izvrsten Beej’s Guide to Network Programming). Tudi izbira povezavnega protokola TCP je bila hitra, saj želim celovit prenos besedila, pa tudi poznati prejemnika. Hitro sem ‘prepisal’ izvirni Bash skript v C, od takrat pa se program le razvija (kolikor študij dopušča).

COPRIS 1.0* 

S prvotnim programom še nisem bil popolnoma zadovoljen. In kot se velikokrat zgodi v takih situacijah, sem namesto tiskanja začel povečevati osnoven nabor funkcij.

COPRIS poleg omrežja sedaj bere tudi iz standardnega vhoda, če je tiskalnik dostopen na lokalnem računalniku. Omrežni način ima zmožnost omejiteve števila prejetih znakov. Vse konfiguracijske datoteke so formata INI in podpirajo komentarje, tudi medvrstične. Za prekodiranje znakov sem dodal nekatera narodna kodiranja (npr. YUSCII) in pogoste kodne tabele (npr. CP852).

Ena večjih in pomembnejših funkcij je razumevanje označevalnega jezika Markdown. Tiskalniki podpirajo ubežne sekvence, ki lahko oblikujejo besedilo, zato se lahko sedaj poleg kodirnih datotek uporabi še funkcijske datoteke, ki podajo ukaze, ki jih tiskalnik podpira.

Poleg novih zmožnosti so programu dodani še testi enot in testi programskega izhoda. Z njimi se prepričam, da posamezne funkcije delujejo po pričakovanju in da COPRIS izbrano vhodno datoteko pretvori v pričakovano izhodno.

* še ni izdan.

Opozorilo uporabnikom 

COPRIS naj ne deluje kot superuporabnik in naj ni javno izpostavljen Internetu.

Popolno zaupanje računalniške soseščine, ali nič. Tveganje pri neupoštevanju tega pravila ni le tisk neželenega neznančevega besedila (kar bi lahko bil dober hec), temveč prevzem strežniškega računalnika, morda celo omrežja, v katerem se strežnik nahaja. Trudim se, da je COPRIS čim temeljiteje preizkušen in ne uporablja prehudih programerskih trikov, a to ni zagotovilo o popolni varnosti. COPRIS naj ne bo javno dosegljiv (razen če deluje v programskem peskovniku). Hkrati uporabite številko vrat, večjo od 1023. S tem je storjen osnoven varnostni korak – izničenje potrebe po delovanju kot superuporabnik.


© 2023 Nejc Bertoncelj · kontakt · Vsebina objavljena pod licenco CC BY-SA 4.0.