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:
- A cucc egy subshell-ben fut.
- 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.
- 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.
- 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.
- 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:
- Az fd4-et átirányítjuk az stdout alatti file description-re (nem descriptor-ra!), ami jelenleg a pipe.
- 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.
- A 3-as fd-re már nincs szükségünk, lezárjuk.
- 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.
- 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