Reputation: 637
i'm really confuse i don't know what's going on, so i'm not sure what to ask :/
i was going to use this question to send input to the standard input of a program, in a bash script (i want program.c
to read on stdin and print what it reads, i do that with readline without trouble, and i want scrit.sh
to send to stdin what program.c
will read, and i was doing it in a complicated way, when i realized that a while loop with read
in the middle of my code was already accomplishing this task, and i don't know why !)
so it works without me sending anything intentionally to the STDIN (i do obviously, but it was not my intention when writing this loop), but i don't understand what's going on
here is how it looks : i use a bash script to call a program.c, which use readline to read the stdin and print it. The script.sh i wrote below should absolutely not work for what i understant (not much), but it does (almost) !
program.c :
#include <unistd.h>
#include <stdlib.h>
#include <readline/readline.h>
int main(void)
{
char *line_input;
line_input = readline("[myPrompt]> ");
if (!line_input)
{
write(1, "exit\n", 5);
exit(0);
}
write(1, line_input, strlen(line_input));
write(1, "\n", 1);
return (0);
}
script.sh :
#!/bin/bash
VAR="\
one
two"
while read -r line
do
echo "line: $line"
./program
done < <(echo "$VAR")
and the output :
line: one
[myPrompt]> two
two
[myPrompt]> exit
so the word two
is written to the right of [myPrompt]>
, i guess the stdin, and it's executed by ./program.c
why ? i never sent it, i just called ./program
in the while loop of the script, but it don't send anything to stdin
and why does it start at the second word ?
i can't reproduce this behavior if i don't use read in my loop, so it could be related
Upvotes: 0
Views: 196
Reputation: 781200
< <(echo "$VAR")
uses process substitution to redirect the standard input of the loop to the output of the echo "$VAR"
command. It affects the entire loop, not just the read -r line
line.
./program
inherits stdin
from this, so it also reads from the process substitution. read -r line
reads the first line, then readline()
in ./program
reads the second line.
And because readline()
is intended for interactive input, it echoes the input as it's reading it. That's why you see it on the prompt line, where you would see it if you were responding interactively.
If you want the program to read from the terminal rather than the input redirection, you can redirect it to /dev/tty
:
#!/bin/bash
VAR="\
one
two"
while read -r line
do
echo "line: $line"
./program </dev/tty
done < <(echo "$VAR")
You can also save the original stdin that the script inherited, and redirect to that.
#!/bin/bash
VAR="\
one
two"
while read -r line
do
echo "line: $line"
./program.c <&3
done 3<&0 < <(echo "$VAR")
BTW, instead of using process substitution, you can use a here-string: <<<"$VAR"
Upvotes: 3