A pipe is a unidirectional connection that usually ends up being between two processes associated by a common ancestor, typically the first of the two processes to be created, unless it is a shell in which case the shell creates the pipe and has two children that use the pipe. The pipe has a write end which is used by one process; it has a read end used by the other. It is often simplest to arrange for the standard output of one process to be connected to the standard input of the other. It is also simplest to use file descriptors rather than standard I/O file streams.
The sequence of operations is:
- Call
pipe() to create the pipe. - Call
fork() to create a child. - The child process (return value 0 from
fork()) does: close() the write end of the pipe dup2() the read end of the pipe to standard input close() the read end of the pipe execve() the child process that will read from the pipe (its standard input)
- The parent process (return value > 0 from
fork()) does: close() the read end of the pipe dup2() the write end of the pipe to standard output. close() the write end of the pipe execve() the process that will write to the pipe (its standard output)
Note that in this scenario, you end up closing both the file descriptors returned by the pipe() call, and you close them twice (once in the parent, once in the child).
If the parent process should write to the child via a file stream, use the fdopen() call on the write file descriptor (and don't use dup2() on it, or close() it -- you close it with fclose() on the file stream returned by fdopen(), or by exiting).
If you want to tell the child process which file descriptor number it can read from to get the input from the pipe, then you don't need to do the dup2() in the child; you can simply format up a string in an array of characters (plural - you need at least characters and should allow for a dozen or so, since it is extremely cheap), and you can then arrange to pass the arguments to the execve() function. Remember that the child would need three pointers at minimum: one for argv[0], the program name; one for the file descriptor number; and one for the terminating null pointer. That's how execve() knows when it has reached the end of the argument list. If you are using just execv(), the same comments apply; you just don't get to determine the child's environment (as in, the list of environment variables it receives); it will just get the same environment as the parent process had at the time of the fork().
The first step in each of ¶3 and ¶4 are the crucial ones. If you omit them, the pipe won't work properly.
passwrite; that array can only hold the NUL that marks the end of the string, and not anything else.