Cannot read from pipe connected to standard input

Ah hello.

I am experimenting with Linux pipes, and how we can set them to be standard file descriptors.  I am trying to read input from a pipe and display it in my program (called testApp) as follows:

int main(int argc, char *argv[])
{
	int pfd[2];
	int j, dummy, dummy2;
	char buf[1024];

	if (pipe(pfd) == -1)
		return -1;

	if (pfd[1] != STDIN_FILENO)
	{ 
		/* Defensive check */
		if (dup2(pfd[1], STDIN_FILENO) == -1)
			return -1;
		if (close(pfd[1]) == -1)
			return -1;
	}
	do
	{
		dummy2 = read(pfd[0], buf, sizeof (buf));
		buf[dummy2] = '\0';
		printf("Read %i bytes from standard input (%s)", dummy2, buf);
	} while (dummy2 != -1);
	
	return 0;
}

Open in new window


I want to be able to call this using a command such as the following:

ps -a | ./myProg

Open in new window


I can see that I have set up the pipe properly from the following:

me@me-VirtualBox:$ ls -l /proc/8967/fd
total 0
l-wx------ 1 me me 64 Oct  7 13:03 0 -> pipe:[93037]
lrwx------ 1 me me 64 Oct  7 13:03 1 -> /dev/pts/1
lrwx------ 1 me me 64 Oct  7 13:03 2 -> /dev/pts/1
lr-x------ 1 me me 64 Oct  7 13:03 3 -> pipe:[93037]

Open in new window

However, when I run the command above from a terminal, my program just sits there.
 
(Note that I know I could achieve this just by reading from stdin, but I want to understand why I cannot do it with pipes)

1) What is wrong with my code?

Now, I thought I might have called dup2() incorrectly, so I changed it to

if (dup2(STDIN_FILENO, pfd[1]) == -1) /* was dup2(pfd[1], STDIN_FILENO)*/

Open in new window


Then, when I run my program, I just get "Read 0 bytes from standard input ()" repeatedly output.

2) What is going on here?

TIA
LVL 19
mrwad99Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
You are 'dup()' ing 'pfd[1]' and then trying to read from 'pfd[0]' - I guess that is not what you actually want to do.
0
mrwad99Author Commented:
I think it is though...here is my thinking.

The write end of my pipe (pfd[1]) is connected to standard input.  So when the command

ls | ./testapp

will send the output of ls to the standard input of ./testapp, which is the write end of my pipe,  Hence I then read from pfd[0] (the read end) expecting to see the output from ls appear on it.
0
mrwad99Author Commented:
I've requested that this question be deleted for the following reason:

No solution.
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

Duncan RoeSoftware DeveloperCommented:
You need to leave more than 3 days before giving up on a Q - the Call to Experts only just went out.
I think I see what you were hoping to do, but it's never going to work.
The reason you read no bytes from your pipe is that no process wrote any bytes to the other end. Here's why:
- You issue the command ps -a | ./myProg. This causes the shell to create a pipe with one end being file unit 1 of ps and the other end being file unit 0 of ./myProg.
 - ./myProg issues dup2(pfd[1], STDIN_FILENO). This closes ./myProg's existing file unit 0. The shell's pipe disappears and ps terminates with errno==EPIPE (assuming it caught the preceding fatal SIGPIPE signal)
0
mrwad99Author Commented:
Thanks Duncan.  I didn't realise it took so long for the neglected question alert to go out.  I thought after five days (2014-10-07 to 2014-10-12) I wouldn't get anything.  My mistake.

OK.  

I think I understand what you are saying, but can you humour me and just verify my understanding please (might sound strange but putting it in my own words proves to myself that I do understand what is happening :))

At the time my program is started by the shell, my program has fd 0, which is standard input.  This is the fd that lives at the read end of the pipe created by the shell.  Because I close that (in order to have standard input re-opened as the write end of the pipe I create in my program) the data that was sent down it by the shell is lost without being read (because that pipe is now "broken" as it only has one open end).

I am then left with the pipe created in my program that is having nothing sent to it.  I can however send stuff to this pipe and get the output I originally expected if I do something like

echo Hi > /proc/<myProg PID>/fd/0

Open in new window


(Haha, just as I finished typing that I decided to run my program again, accidentally doing so with the output from ls not ps.  It seems that ls gives a more informative result compared to ps which is in line with your comment about EPIPE:

$ ls -l | ./myProg
ls: write error: Broken pipe

Open in new window

)

1) Is all this correct?
2) So overall, I cannot achieve what I am after using pipes, and if I wanted to do this I would just read from standard input.  Correct?

Thanks in advance.
0
Duncan RoeSoftware DeveloperCommented:
Yes, pretty much. Nice experiment with /proc - you are writing to fd 0 which is open for writing so hey, it works.
Your summary in point 2 is right - just read from standard input.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mrwad99Author Commented:
Thank you very much Duncan :)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.