( uid_2716 | 2012. 02. 05., v – 18:42 )

Most mi van? :)

Indítsd el a legfelső szintű programot ("whatever") így:


(
  exec 3>&1
  whatever 4>&1 >&3 3>&- \
  | read 3>&-
)

Ennek hatására az alábbiak fognak történni:

  1. A cucc egy subshell-ben fut.
  2. Az exec sor dup2-vel oda irányítja (nyitja) a subshell 3-as fd-jét, ahova az stdout amúgy is mutat. Ezt azért kell külön sorba tenni, mert a következő sorban pipeline-t fogunk építeni, és ott már nem tudjuk teljes biztonsággal megakadályozni, hogy a pipe redirection minden más redirection előtt érvénybe lépjen. Vagyis a whatever program már nem férne hozzá az eredeti (fő shell-)stdout-hoz.
  3. Nézzük a pipeline-t. Az első tag némi redirection után lefuttatja a kérdéses programot (amely forkol, aztán elpatkol, a gyereke viszont nem, te meg arra akarsz várni). A második tag egy shell script, amely stdin-ről olvas egy sort, ill. EOF-ig, ha az előbb jön. Ennek a pipeline-nak akkor van vége, ha az utolsó elem befejeződik, ami jelen esetben a read.
  4. A pipeline mindkét tagja örökli a subshell-től az fd3-at. A read-nél ezt simán lezárjuk (bár nem lenne feltétlenül szükséges.
  5. A whatever örökli az fd3-at (ami a rendes shell script-ed stdout-jára van ráállítva), illetve kapott egy stdout-ot, ami a pipe-ra mutat. Ezen reszelünk egyet -- az átirányítások balról jobbra hajtódnak végre:
    1. Az fd4-et átirányítjuk az stdout alatti file description-re (nem descriptor-ra!), ami jelenleg a pipe.
    2. Az stdout-ot a pipe helyett áttoljuk az fd3 alatti file description-re (nem descriptor-ra!) így a whatever program (és az összes gyereke) stdout-ja a fő shell script stdout-ja lesz, ahogy illik.
    3. A 3-as fd-re már nincs szükségünk, lezárjuk.
  6. A whatever program, valamint összes gyereke fd4 "néven" rendelkezni fog egy referenciával a pipe-ra. Erről a programok nem fognak tudni (nem ők nyitották). Gond csak akkor lehet, ha valamelyik processz a fában szándékosan lezárja mindenét, amit nem ő maga nyitott meg (ez néha értelmes dolog, de ritka), illetve ha valamelyik processz a fában kifejezetten a 4-es fd-t manipulálja valamilyen célból (pl. valami hasonló shell script -- ez is valószínűtlen). Természetesen fstat()-tal is ránézhet bármelyik processz az fd4-ére, illetve beleírhat stb, de ez nagyon valószínűtlen. Jó esetben az összes gyerekprocessz rendelkezni fog egy write referenciával. A legutolsó write referencia akkor fog megszűnni, amikor az utolsó gyerekprocessz is kilép, a read pedig ekkor fog egy EOF-ot kapni.
  7. Amikor a subshell végül befejeződik, akkor természetesen az fd3-ja is véget ér.

Nem teszteltem :)

Kiegészítés: a kód tömöríthető pl. így:


(
  whatever 4>&1 >&3 3>&- \
  | read 3>&-
) 3>&1