KSH - központi statisztikai shell

Köszönöm a Teremtőnek, hogy olyan könnyű munkát osztott rám, mint az ékezetes betűkkel való kínlódás... Mindig van új varázslat, valahogy sosem ér véget a dolog. Most éppen egy ilyen shell-scriptem van:


#!/bin/ksh

export LC_ALL=hu_HU.UTF-8

cat <<DONE
@öÖőŐüÜűŰ@
DONE

Az utólsó előtti sorban nyolc ékezetes betű van, ISO-8859-2 szerint (f6 d6 f5 d5 fc dc fb db). Ez persze ellentmond a LC_ALL-nak, tehát megérdemelném, hogy a dolgozó nép megvetése sújtson. Talán még azt is megérdemelném, hogy valamilyen hibaüzenet jöjjön.

A valóság más: dash, bash, zsh végrehajtja, ksh belefagy.

Namostan van nekem forrásból fordított ksh-m, debian.packages.org-ról, de az olyan csudállatiasan eredeti, hogy egyszerűen nem látom, hol kellenne a '-g' opciót belerakni, hogy debuggolhassak. Na majd talán a github-on találok valamit...

Szerk: A githubról jött friss verzió nem mutatja ezt a hibát. Azért majd próbálok még nyomozni, mi lehetett.

20180720.2006: Az érdekesség kedvéért reprodukáltam az eggyel ezelőtti hibát, ez annyiból áll, hogy LC_CTYPE=hu_HU.ISO8859-2 LC_TIME=C beállításokkal kell végrehajtani azt, hogy


cat <<DONE
Árvíztűrő tükörfúrógép
LC_CTYPE=$LC_CTYPE
DONE

A biztonság kedvéért hexásan is idézem a problémás sort:


      16: c1 72 76 ed  7a 74 fb 72  f5 20 74 fc  6b f6 72 66  Árvíztűrő tükörf
      26: fa 72 f3 67  e9 70 0a                               úrógép.

Ennek a kimenete (hexásan):


     118: 72 76 7a 74  3e 72 a6 20  74 84 6b 00  72 66 63 72  rvzt>rŚ t.k.rfcr
     128: 0c 67 2c 70  0a                                     .g,p.
     12d: 4c 43 5f 43  54 59 50 45  3d 68 75 5f  48 55 2e 49  LC_CTYPE=hu_HU.I
     13d: 53 4f 38 38  35 39 2d 32  0a                        SO8859-2.

Szép vegyes eredmény... megoldási lehetőségek:
* a 'bos.rte.loc' komponenst frissítjük '6.1.6.15'-ről, '6.1.6.16'-ra
* a LC_TIME-ot szándékosan érvénytelen értékre állítjuk. Gondolom, ekkor nem sikerül a setlocale(3), ezen elszomorodik, és bánatában lemond arról a konverzióról, amire nem is kérte senki.
* /bin/ksh helyett /bin/ksh93-at használunk (haladó esetben /usr/local/bin/bash-t)

20180728.1744 Úgy vélem látni, hogy a libc:mbtowc átvezet a libi18n:__mbtowc_sbcs függvénybe

A jó és rossz működés táblázattal szemléltetve (latin2->ucs2)


0080 0081 0082 0083 0084 0085 0086 0087 0089 008a 008b 008c 008e 008d 008e 008f
0090 0091 0092 0093 0094 0095 0096 0097 0099 009a 009b 009c 009e 009d 009e 009f
00a0 0104 02d8 0141 00a4 013d 015a 00a7 0160 015e 0164 0179 017d 00ad 017d 017b
00b0 0105 02db 0142 00b4 013e 015b 02c7 0161 015f 0165 017a 017e 02dd 017e 017c
0154 00c1 00c2 0102 00c4 0139 0106 00c7 00c9 0118 00cb 011a 00ce 00cd 00ce 010e
0110 0143 0147 00d3 00d4 0150 00d6 00d7 016e 00da 0170 00dc 0162 00dd 0162 00df
0155 00e1 00e2 0103 00e4 013a 0107 00e7 00e9 0119 00eb 011b 00ee 00ed 00ee 010f
0111 0144 0148 00f3 00f4 0151 00f6 00f7 016f 00fa 0171 00fc 0163 00fd 0163 02d9

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 7c1b 02a6 1032 2fa0 0000 4186 7d60 0030 7d60 0124
2c0c 0001 4082 0008 483e 045a 2c0c 0002 0008 4843 79ce 2c0c 4082 0003 4082 0008
4801 928e 4800 3f2e 7d60 0124 6000 0000 012c 6000 0000 6000 6000 0000 6000 0000
6000 0000 419d 000c 7d71 42a6 4800 370a 42a6 5463 003e 5484 54a5 003e 54a5 003e

20180807.1511
Ennek a hibának a nyomozásában látni vélek egy gyanús pontot:


$ nm -X64 -xv /usr/ccs/lib/libi18n.a_6.1.6.15 | cat -n
     1  /usr/ccs/lib/libi18n.a_6.1.6.15[shr_64.o]:
   297  .check_iconv         T  0x00001760
   344  .check_iconv         T  0x00002540

$ nm -X64 -xv /usr/ccs/lib/libi18n.a_6.1.6.16 | cat -n
     1  /usr/ccs/lib/libi18n.a_6.1.6.16[shr_64.o]:
   296  .check_iconv         T  0x00001760

Vagyis a 'check_iconv' valamiért kétszer van benne a hibát mutató verzióban. Ez a check_iconv az, aki meghívja a libiconv_open-t, az alábbi paraméterekkel:


jó:    r3="UCS-2",  r4="ISO8859-2"
rossz: r3="UTF-32", r4=NULL

Hozzászólások

legújabb hűdetrendi buildtool
+1
Már a ./configure is egyre inkább utálatosabb számomra. A legegyszerűbb-legkisebb programok is valami csoda-buildtoolt igényelnek, miközben gyakorlatilag egy-két gcc/clang-parancs segítségével minden elkészülne.

Hódolattal bámullak, hogy mindig milyen feleslegesnek tűnő alapkutatásokkal molyolsz! ;)
Bár nem kérdezted, de elmondanám a véleményemet.

A shell/prompt unix parancsok kiadására való.
Az utf8 nem konzolra való.
"Az a rendszer, amelyiken nincs definiálva a karakterkészlet: működésképtelen."
(Az idézet egy megboldogult, volt osztálytársamtól és főnökömtől származik. Számtalan esetben igaznak bizonyult.)
Ha már az a beteges ötleted támadt, hogy ékezetes karaktert jelenítsél meg terminálon, (mielőtt megsértődnél: nekem is ilyen ötleteim szoktak lenni,) akkor miért nem azt állítod be?

Szóval látom a problémát, de vajon mi a cél? ;)
Ha meg kimeríted "invalid byte sequence" fogalmát, akkor mire számítasz? Ilyen esetben a mount is eldobja a kanalat.

A válasz többirányú! ;)

Egyrészt egy kis csúsztatás, mert bloggerünk egyszer olyat szólt, hogy a shell csak programok futtatására való és nem programok írására. Mivel a szokványos programok soha nem multibájtos neveken neveztetnek, ezért a nem utf8 konzol is kiválóan alkalmas ilyen feladatokra.

Másrészt tegyük fel, hogy az első állítás helyes. Az egyes programok alapvető működése az en_US, avagy a C (POSIX) nyelvi környezetben garantált. Bármilyen más környezet is használható, de csak a saját rákfenéivel. Az összes többi esetben a LANG kezelése a tetszőleges nyelvű szövegek feldolgozásánál valamely programok feladata. Tehát a helyes konstelláció az, amikor a LANG még véletlenül sem befolyásolja az oprendszer működését. Ugyanakkor az oprendszer beállitása sem befolyásolhatja a programok nyelvi működését.

Ez utóbbit nem én találtam fel, hanem olvastam több dokumentumban. Ezen kívül számtalan esetben szívott ilyennel, aki ezt az egyszerű szabályt nem tartotta be. Általában felesleges a multibájtos binárisnak futnia.

Tehát úgy fogalmaznám meg: Nem tilos, de az egyszerű, problémamentes élet reményében nem ajánlatos.

Természetésen elismerem annak a rétegnek a létezését, akik szeretik amikor az ls a zsé betűre rendez. ;) Szerintem ez a komoly munkától elég messze esik. Sőt, velem is előfordult, hogy nyitottam egy új konzolt, mert éppen utf8-at kellett nézegetnem. De ez nem tipikus.

> Egyrészt egy kis csúsztatás, mert bloggerünk egyszer azt mondta, hogy a shell csak programok futtatására való és nem programok írására.
> Mivel a szokványos programok soha nem multibájtos neveken neveztetnek, ezért a nem utf8 konzol is kiválóan alkalmas ilyen feladatokra.

Találjuk meg a hibát ebben a következtetésben;)
Ugyebár a programok indítása magában foglalja a programok paraméterezését is, és adott esetben a paraméterben még ékezetes betű is lehet. Adott esetben a ksh segítségével a 'MÉZLEKVÁR' string 'MZLEKVR'-ként érkezett meg a konzervcímkegyártó géphez...

Ha a "program környezet" a shell, akkor megszegted a (már említett) "Az a rendszer, amelyiken nincs definiálva a karakterkészlet: működésképtelen." szabályt.

Nem ez a baj. A "MÉZLEKVÁR" nem paraméter, hanem adat. Ha következetes vagy, akkor legközelebb azért nyafizol, mert a hülye ksh nem eszi meg paraméterkén a gif formátumot.

Tehát a példa nem életszerű. Rossz az a rendszer, ahol általános adatot hibásan definiált nyelvi környezetben parancssorból kell megadni. Már csak azért sem jó, mert egy címkét először megtervezünk (a megfelelő beállítások mellett *tervező programmal - legyen az akár vi editor), majd tároljuk. A nyomtatás mindig a tárolt és ellenőrzött mintából megy. Ha nem így teszel, akkor az elgépelés valószínűsége sokkal nagyobb, tehát ugyanúgy selejt lehet a végeredmény.

Ha ez scriptből megy (mondjuk oda írtad be az "etalont"), akkor - ismervén a kimeneti karakterkészlet követelményt - a script írásának és futtatásának is megfelelő nyelvi környezetben kell történnie. Alternatívaként akár megírhatod cp852-ben a scriptet, majd futtatás előtt iconv segítségével az adott környezetre konvertálod. Vérpistikeként meg a paraméter mögé is odapájpolhatsz egy iconv-ot. :-)

Az se tetszik, hogy ha valami nem megy, akkor az egyes shelleket próbálgatod. AIX=ksh, linux=bash és abban a környezetben kell megoldanod a feladatot! Ilyenkor ugye nem root-ként dolgozunk, tehát a munkához használatos user környezetét is lehet alakítani.

Ha nem látod át az egész rendszert, szívesen segítek megoldani az egészet, akár pm-ben is.

Egyépként meg wtf mézlekvár?! :-D