It’s a bit difficult but doable:
function die {
print -ru2 -- "E: $*"
exit 1
}
function psubin {
local stdin=$(cat; echo .) pipe
pipe=$(mktemp /tmp/psub.XXXXXXXXXX) || die mktemp
# this is racy
rm -f "$pipe"
mkfifo "$pipe" || die mkfifo
(
# don’t block parent
exec <&- >&- 2>&-
# write content to FIFO
print -nr -- "${stdin%.}" >"$pipe"
# signal EOF to reader, ensure it’s not merged
sleep 0.1
:>"$pipe"
# clean up
(sleep 1; rm -f "$pipe") &
) &
print -nr -- "$pipe"
}
diff -u $(echo abc | psubin) $(echo def | psubin)
The problems you and I encountered here are:
mkfifo complains unless you rm mktemp’s output first
- mksh blocks for the background process if it still shares any file descriptors (stdin, stdout, stderr) with the parent (Note: This is probably the only valid use case for using
>&- instead of >/dev/null, and only because we can guarantee these fds to no longer be used, nor replaced by any new fds)
- as we don’t have stdin in the background process we’ll need to cache its content, byte-exact
- EOF with FIFOs (named pipes) is nontrivial. Let’s just leave at that… (we could do some tricks with trying to open the FIFO non-blocking to check if there’s a reader, and signal EOF until the reader died, but this works well enough for now)
- it’s nicer if the FIFO is removed after use…
On the other hand: good thing we’re doing this now, because I eventually will wish to implement <(…) into mksh itself, and then I need to know what to watch out for, since we can’t use /dev/fd/ as GNU bash does, because that’s not portable enough.
diff <(echo abc) <(echo def )in bash ? (and fish example is not working for me)