I know this is a simple exercise but I'm having troubles with it. I'm trying to emulate:

grep arg1 arg2 | wc -l 

I'm getting the following error: "wc: standard input: Bad file descriptor when executing". This is my code:

int main(int argc, char *argv[]) { if (argc != 3) usage(); int pd[2]; //Pipe descriptor pipe(pd); int pid = fork(); if (pid < 0) perror("Something failed on trying to create a child process!\n"); else if (pid == 0) { //Child dup2(pd[1], 0); close(pd[0]); close(pd[1]); execlp("wc", "wc", "-l", (char *)NULL); } else { //Parent dup2(pd[0], 1); close(pd[0]); close(pd[1]); execlp("grep", "grep", argv[1], argv[2], (char *)NULL); } } 

What can be the problem?

2

2 Answers

You have:

else if (pid == 0) { //Child dup2(pd[1], 0); close(pd[0]); close(pd[1]); execlp("wc", "wc", "-l", (char *)NULL); } 

You need:

else if (pid == 0) { //Child dup2(pd[0], 0); close(pd[0]); close(pd[1]); execlp("wc", "wc", "-l", (char *)NULL); fprintf(stderr, "Failed to execute 'wc'\n"); exit(1); } 

The crucial change is the dup2(); your code copies the write end of the pipe to the child's standard input , which is not a recipe for happiness. The revised code copies the read end of the pipe to the child's standard input. It's easy enough to remember which is which: stdin is file descriptor 0 and pipe descriptor 0 of the pair is the input descriptor (read end of the pipe), while stdout is file descriptor 1 and pipe descriptor 1 of the pair is the output descriptor (write end of the pipe).

You need the converse change in the 'parent' code.

The error arises when wc tries to read from a file descriptor that's only open for writing.

Note that if execlp() — or any other member of the exec*() family of functions — returns, it failed. It is important to deal with that error, usually by reporting a problem on standard error and exiting. It is seldom correct to have no statement after the exec*() operation.

3

As I can see, you trying to replicate the terminal command of "wc -l | grep something something".

The problem is that you are not providing input to wc. wc -l command requires an input for which it should count its lines. Try something like:

execlp("wc", "wc", "-l", "somefile.txt", (char *)NULL); 
1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.