2

Related:

I've read the above questions and I still can't work out how to do what I need.

I have a binary command I'll call getreport that does the following:

  1. Prompt for a password (prompt sent to stderr)
  2. Read the password from stdin.
  3. Print extensive data to stdout.

I have another binary command to parse the output from the first command that I'll call processreport. However, it doesn't work with stdin; it will only accept and process a file specified on the command line with a -i flag. It reads from the file, does things with the data it reads in, and outputs data about what it did. (The processreport command can also prompt for a password, entirely separately from getreport.)

I want to use process substitution to make this possible in a single line, rather than requiring a temp file to hold the output of getreport.

Something like:

processreport -i <(getreport)

However, I don't know how to make getreport read in from the terminal the password it requires.

Is this possible?

Wildcard
  • 36,499

2 Answers2

3
{ getreport | 4<&0 <&3 processreport -i /dev/fd/4; } 3<&0

It could be more simple if you're willing always to read explicitly from /dev/tty:

getreport | 3<&0 </dev/tty processreport -i /dev/fd/3

...or more simply still if you know that stderr will always equal stdin - as it typically does in a terminal...

getreport | 3<&0 <&2 processreport -i /dev/fd/3
mikeserv
  • 58,310
  • 3
    That looks too good to be true thus I would like to point out this: "The processreport command can also prompt for a password, entirely separately from getreport." – Hauke Laging Feb 05 '16 at 06:35
  • @HaukeLaging - ok, thanks for that - it does complicate matters some, but it doesn't make it much more difficult. i overlooked it i guess, but at least it does explain why processreport requires a named read file. – mikeserv Feb 05 '16 at 06:54
2

getreport cannot read from the terminal because it is a background process.

man 2 read:

EIO : I/O error.
This will happen for example when the process is in a background process group, tries to read from its controlling terminal, and either it is ignoring or blocking SIGTTIN or its process group is orphaned.

I guess what you want is not possible without some shell wrapping. But maybe this is closer to what you want:

mkfifo fifo; read -p "Input for FIFO: " input; echo "$input">fifo &
cat <(read bginput <fifo; echo "$bginput"); rm fifo

This obviously doesn't not work well for wrong passwords and read retries.

mkfifo fifo; read -p "Input for FIFO: " input; echo "$input">fifo &
processreport -i <(getreport <fifo); rm fifo
Hauke Laging
  • 90,279