1

Is it necessary to replace stdin with a pipe end when using pipes?

I have an application that:-

  • Creates a pipe,
  • Forks a child process, and then
  • execl() a new process image within new child process,

But I'm running into two conceptual issues.

  1. Is it necessary to use dup() or dup2() to replace stdin? It would obviously be easier to just use the fd from the pipe. (I need little insight about this)

  2. If you can just use the fd from the pipe, how do you pass an integer fd using execl() when execl takes char * arguments?

I'm having trouble figuring out exactly what remains open after execl() is performed, and how to access that information from the newly execl'd process.

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
perry_VW
  • 145
  • 3
  • 14
  • I think you are feeling using dup() and dup2() are complex/tough. [Here is very good tutorial colorful and easy with diagram.](http://www.ccse.kfupm.edu.sa/~akbar/ICS431_031/LabExercises/Lab8/Lab8.html) Also [Other useful chapters](http://www.ccse.kfupm.edu.sa/~akbar/ICS431_031/LabExercises/Exercises.html) – Grijesh Chauhan Apr 11 '13 at 07:12
  • Actually dup() and dup2() are easier other also possible way is using fcntl() or ioctl() function but not simpler then dup.() – Grijesh Chauhan Apr 11 '13 at 07:19
  • @GrijeshChauhan But, is dup necessary? I guess by necessary, I mean does a child processes open file descriptors stay open when execl is performed? I thought the exec family wiped out the process image if a new one. If it is not necessary, I'm not sure how you would pass a file descriptor of a pipe (which is an int) through char *arg. – perry_VW Apr 11 '13 at 12:28
  • I believe you are replacing standard commands with execl series of functions. Those function by-default writes on standard output also take input from standard input. To communicate with that process you have to Establishment pipe as IPC and have to explicitly change flow of input/output using dup(). But Suppose if your child process doesn't interacts with standard input/output then there is no point to redirect stdin/stdout. (*remember stdin/stdout are `FILE*` not descriptors*) – Grijesh Chauhan Apr 11 '13 at 13:15
  • answer to **second question**: Suppose you wants to redirect child process output to some other file opened by parent process. then you can pass `fd` of open file from parent process to child process as an argument. And follow same steps of redirect into that file using dup() – Grijesh Chauhan Apr 11 '13 at 13:19
  • I wish I could respond you in answer section with some example codes instead but because of short of time I can't :(.. I formatted your question and added some more useful tags and I hope you will get some good answers. – Grijesh Chauhan Apr 11 '13 at 13:22

2 Answers2

3

It depends on the commands you're running. However, many Unix commands read from standard input and write to standard output, so if the pipes are not set up so that the write end is the output of one command and the read end is the input of the next command, nothing happens (or, more accurately, programs read from places where the input isn't coming from, or write to places which will not be read from, or hang waiting for you to type the input at the terminal, or otherwise do not work as intended).

If your pipe is on file descriptors 3 and 4, the commands you execute must know to read from 3 and write to 4. You could handle that with shell, but it is moderately grotesque overkill to do so compared with using dup2().

No; you're not obliged to use dup2(), but it is generally easier to do so. You could close standard output and then use plain dup() instead of dup2().

If you use dup2() for a pipe, don't forget to close both of the original file descriptors.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
2

You are probably trying to feed data to a subprocess that exists on the system but on the off chance that you are also writing the child process then no you don't need to use dup() and stdin.

execl() keeps all open file descriptors from the parent process open so you could:

int fd[2];
pipe(fd);
if (fork() == 0)
{
    char tmp[20];
    close(fd[1]);
    snprintf(tmp, sizeof(tmp), "%d", fd[0]);
    execl("client", tmp, NULL);
    exit(1);
}

and in the code for client:

int main(int argc, char** argv)
{
    int fd = strtod(argv[1], NULL, 10);
    /* Read from fd */
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
the_jk
  • 539
  • 2
  • 10
  • Instead give OP an example that shows how to pass file descriptor to child process using parameters in execl(...,..) functions. – Grijesh Chauhan Apr 11 '13 at 13:24
  • @GrijeshChauhan, eh, that was what I did? – the_jk Apr 11 '13 at 13:32
  • Joel, could you explain what you mean by feed data to a subprocess that exists on the system vs writing the child process? – perry_VW Apr 11 '13 at 14:24
  • 2
    With "subprocess that exists on the system" I meant an already created program by someone else that probably expects to read data from stdin. When we write the child process ourselves however you can do other things, like for example give the file descriptor as an argument. – the_jk Apr 11 '13 at 14:27
  • Oh, I see. That comment clears up much of my confusion! I've written the child process that will get execl, so I know of the open file descriptors, but if I were to execl some random program, it would expect to read from stdin. – perry_VW Apr 11 '13 at 14:33
  • @perry_VW I came back n fortunately you got answer :) – Grijesh Chauhan Apr 11 '13 at 14:49
  • 1
    @GrijeshChauhan Thanks for your help with this question. Now going back and reading your comments make more sense to me. Thanks for editing the post to read more clearly! – perry_VW Apr 11 '13 at 14:51
  • @perry_VW welcome Perry :) I couldn't answer you, But you can comment back to me if you have any other doubt regarding this..and the Links I posted having good and easy stuff to learn quickly... – Grijesh Chauhan Apr 11 '13 at 14:54