Gippeumi
Gippeumi

Reputation: 261

Redirecting stdin in bash not working on normal files?

I was making an script to read command from file and execute. It reads command from file and executes it. Also, reads input from a file and outputs commmand's every output to a file.

I was making this for communicating with ComputerCraft(an Minecraft mod which uses lua).

I googled and it was not hard to find how to redirect stdin. It seems to work with something like /dev/stdin, but not normal files.

I tested with cat, nano and bash but none of them tried to read user input. I also tested with this simple C program:

#include <stdio.h>

int main()
{
   char str1[20], str2[30];

   printf("Enter name: ");
   scanf("%s", str1);

   printf("Enter your website name: ");
   scanf("%s", str2);

   printf("Entered Name: %s\n", str1);
   printf("Entered Website:%s", str2);

   return(0);
}

When I run this program using the script, I got this:

Enter name: Enter your website name: Entered Name:

Entered Website:

On normal case, this should look like this:

Enter name: Gippeumi

Enter your website name: omg

Entered Name: Gippeumi

Entered Website:omg

Is there any way to make this work?

EDIT: I forgot to upload the script. Here is it:

#!/bin/bash
echo "Loading..."
BASE_DIR="mem/"
STATUS_FILE=$BASE_DIR"Status"
OUTPUT_FILE=$BASE_DIR"Output"
INPUT_FILE=$BASE_DIR"Input"
RETCODE_FILE=$BASE_DIR"ReturnedCode"
CMDIN_FILE=$BASE_DIR"CommandInput"

READY=0
RUNNING=1

sudo umount mem
sudo mount -t tmpfs tmpfs mem
rm -rf $INPUT_FILE
echo $READY > $STATUS_FILE
touch $OUTPUT_FILE
touch $INPUT_FILE
touch $RETCODE_FILE
touch $CMDIN_FILE
echo "Ready for command inputs."
while true; do
    cmd=`cat $CMDIN_FILE`
    if [ ! -z "$cmd" ]; then
        echo "Running: "$cmd
        #Clear inputs first
        echo "" > $CMDIN_FILE
        echo "" > $INPUT_FILE
        echo $RUNNING > $STATUS_FILE
        $cmd < $INPUT_FILE > $OUTPUT_FILE 2>&1
        echo $? > $RETCODE_FILE
        echo $READY > $STATUS_FILE
    fi
done

And I can use like this:

echo "ls" > mem/CommandInput #Enter command
cat mem/Output #See output

I made another script to test commands easily.

echo "Loading..."
BASE_DIR="mem/"
STATUS_FILE=$BASE_DIR"Status"
OUTPUT_FILE=$BASE_DIR"Output"
INPUT_FILE=$BASE_DIR"Input"
RETCODE_FILE=$BASE_DIR"ReturnedCode"
CMDIN_FILE=$BASE_DIR"CommandInput"

READY=0
RUNNING=1

echo "Ready for user inputs."
while true; do
    printf "> "
    read cmd
    echo $cmd > $CMDIN_FILE
    while [ `cat $STATUS_FILE` -eq 0 ]; do
        echo "Dummy" > /dev/null
    done
    while [ `cat $STATUS_FILE` -eq 1 ]; do
        echo "Dummy" > /dev/null
    done
    cat $OUTPUT_FILE
    echo "Return code: " `cat $RETCODE_FILE`
done

NOTE: I didn't wrote to file. But I think it should do something even if I didn't wrote anything to file. What I wanted is launch program first, and write later. Maybe EOF caused problem?

And this is what happened when I launched the C program.

When I start this script, it looks like this:

Loading...
Ready for user inputs.
> 

And I typed ./inputTest which is the C program.

> ./inputTest
Enter name: Enter your website name: Entered Name: 
Entered Website:Return code:  0
> 

Please note that I just entered the command. I couldn't try to type anything because it didn't let me to type anything.

In apt-get, it never asked me anything. If I run "sudo apt-get remove " on that prompt, it just removes package without asking. I didn't used -y option.

Upvotes: 0

Views: 424

Answers (1)

rici
rici

Reputation: 241721

In this line, you clear the input file (apparently deliberately):

echo "" > $INPUT_FILE

Then you supply the empty input file to your command:

$cmd < $INPUT_FILE > $OUTPUT_FILE 2>&1

Your test program doesn't check for end of file errors, but that is certainly what it will receive when it tries to read from stdin after stdin has been redirected to an empty file. (Since nothing is read into your buffers, and the buffers are never initialized, the attempt to print the data is Undefined Behaviour. So the fact that the output is just whitespace is purely coincidental.)

Why is this outcome surprising?

If you have real data in the same input file, you should not empty the file before you read the data.

Upvotes: 5

Related Questions