Controlling a program from shell script

Hi all,

I am trying to write a shell script that starts a program, reads from its stdout and can write to its stdin.
I'm having trouble to get it to work, I tried using named pipes, and using exec and file descriptors.
Just couldn't get it to work, so I thought I'll post it here to see if someone is willing to help me.

The program is called primes, and it first asks for my name

>What's your name?
<test
>Hi, test
>Given 10 numbers, calculate sum of its prime factors!
>1 : 187
>Sum:
<answer1
>2 : 123
<answer2
...

Thanks!

You should show your work and what scripts you have written, what you have tried and why.

Sure, I can show, but I had many versions and just in general have no clue how to do this.

I'm currently trying to create a named pipe for the input, so that I can write to that in my script (> $pipe).
Then I'm running the primes program in the background, which gets the $pipe on stdin.
I did a tail -f there to keep it opened, otherwise the stream would close when I write to it with for instance echo "test name" > $pipe.
But, it doesn't work, and I'm also not even sure how to debug this.

#!/bin/bash

mkfifo /tmp/primes.input
tail -f /tmp/primes.input | /tmp/primes >&0 &

echo "test name" > /tmp/primes.input

while true
do
    if read line; then
        echo "read: $line"

        if [[ "$line" == *"1 : "* ]]; then
	    echo "Solve this one: $line"
	    echo "12345" > /tmp/primes.input
        fi
    fi
done

------ Post updated at 03:00 PM ------

Now using this version. I thought I should perhaps not background the program. But this also doesn't seem to work.
This version does not output anything when I start it ... (not seeing the "read: ..." and also not seeing any output of the program).

#!/bin/bash
PROGRAM=/tmp/primes

mkfifo $PROGRAM.stdin

tail -f $PROGRAM.stdin | $PROGRAM | while true
do
    if read line; then
        echo "read: $line"

	if [[ "$line" == *"What's your name?"* ]]; then
	    echo "test name" > $PROGRAM.stdin
        elif [[ "$line" == *"1 : "* ]]; then
	    echo "Solve this one: $line"
	    echo "12345" > $PROGRAM.stdin
        fi
    fi
done

The first question i have is: how exactly is the program reading the input?

If this is done via the gets() the problem might be a missing EOL ("\n") or EOF character at the end of the input line. Some programs (i.e. passwd also clear their <stdin> to make sure that redirection does not take place. Your program might have a similar mechanism in place.

Other than that: you might want to explore the "coprocess-facility" of the Korn shell if you want to bidirectionally communicate with asynchronously running jobs. If i remember correctly some versions of bash have that too now, but i have no experience with this in bash . It seems to work slightly different there than in Korn shell.

I hope this helps.

bakunin

1 Like

Wow, I didn't know about coproc.
That seems to make my life a lot simpler indeed! Thanks.