Piping between several processes in C - c

I'm writing a shell in C and am trying to implement multiple pipes. I've done this by creating a two dimensional array with pipes and using a separate pipe everytime. All commands in between pipes are separated by a parsing function and put into a struct. Every command line in-between pipes gets it's own process. And for all commands in the middle I'm trying to read from the previous process and write to the next one. Somewhere here the problem starts. It works fine for one pipe, however when I trying more than one pipe I don't get any output and the program gets stuck. In GDB I get a failed message from the execvp after forking the second process. What can this be due to?
int create_pipe(int* fd)
{
int pipe_id = pipe(fd);
if (pipe_id == -1)
{
return -1;
}
return 0;
}
void write_pipe(int* fd)
{
close(fd[READ]);
if ((dup2(fd[WRITE], STDOUT_FILENO)) < -1)
{
fork_error();
}
close(fd[WRITE]);
}
void read_pipe(int *fd)
{
close(fd[WRITE]);
if (dup2(fd[READ], STDIN_FILENO) < 0)
{
fork_error();
}
close(fd[READ]);
}
void need_to_pipe (int i, int (*fd)[2])
{
if (commands[i].pos == first)
{
write_pipe(fd[i * 2]);
}
else if (commands[i].pos == last)
{
read_pipe(fd[(i-1) *2]);
}
else //if (commands[i].pos == middle)
{
dup2(fd[(i-1)*2][READ], STDIN_FILENO);
close(fd[(i-1)*2][READ]);
close(fd[(i-1)*2][WRITE]);
//close(fd[(i)*2][READ]);
//close(fd[(i)*2][WRITE]);
close(fd[(i)*2][READ]);
dup2(fd[i*2][WRITE], STDOUT_FILENO);
close(fd[(i)*2][WRITE]);
}
}
/**
* Fork a proccess for command with index i in the command pipeline. If needed,
* create a new pipe and update the in and out members for the command..
*/
void fork_cmd(int i, int (*fd)[2]) {
pid_t pid;
switch (pid = fork()) {
case -1:
fork_error();
case 0:
// Child process after a successful fork().
if (!(commands[i].pos == single))
{
need_to_pipe(i, fd);
}
// Execute the command in the contex of the child process.
if (execvp(commands[i].argv[0], commands[i].argv)<0)
{
fprintf(stderr, "command not found: %s\n",
commands[i].argv[0]);
exit(EXIT_FAILURE);
}
default:
// Parent process after a successful fork().
break;
}
}
/**
* Fork one child process for each command in the command pipeline.
*/
void fork_cmds(int n, int (*fd)[2])
{
for (int i = 0; i < n; i++)
{
fork_cmd(i, fd);
}
}
void wait_once ()
{
wait(NULL);
}
/**
* Make the parents wait for all the child processes.
*/
void wait_for_all_cmds(int n)
{
for (int i = 0; i < n; i++)
{
wait_once();
//wait for number of child processes.
}
}
int main() {
int n; // Number of commands in a command pipeline.
size_t size = 128; // Max size of a command line string.
char line[size];
while(true) {
// Buffer for a command line string.
printf(" >>> ");
get_line(line, size);
n = parse_cmds(line, commands);
int fd[(n-1)][2];
for(int i =0;i<n-1;i++)
{
int pipe_id = pipe(fd[i*2]);
if (pipe_id == -1)
{
return -1;
}
}
fork_cmds(n, fd);
for(int i =0;i<n-1;i++)
{
int *fdclose= fd[i*2];
close (fdclose[READ]);
close (fdclose[WRITE]);
}
wait_for_all_cmds(n);
}
exit(EXIT_SUCCESS);
}

You [probably] have too many processes keeping pipe ends open (that do not belong to the given child) because your loop opens all pipes before any forking.
This places an undue burden on each child because it has to close many pipe ends to prevent it from holding open a pipe end, preventing other children from seeing an EOF on their input pipes.
To see this, for debug purposes in your present code, the child could do (just before the exec* call) (e.g.):
fprintf(stderr,"child: %d\n",getpid());
fflush(stderr);
system("ls -l /proc/self/fd 1>&2");
Each child should only have three open streams on stdin, stdout, and stderr (e.g. 0, 1, 2).
I think you'd find that there are many extraneous/detrimental streams open on the various children.
You only need two pipe arrays (e.g.): int pipeinp[2]; int pipeout[2]; Initially, pipeinp is all -1.
Roughly ...
Parent should do a single pipe call at the top of fork_cmd [before the fork] to pipeout.
The child dups (and closes) the read end of pipeinp [if not -1] to stdin.
Child dups/closes the write end of pipeout to stdout.
It closes the read end of pipeout.
After that, the parent should copy pipeout to pipeinp and close the write end of pipeinp
This should be repeated for all pipe stages.
No pipe to pipeout should be done for the last command. And, the [last] child should not change stdout.
For a working example, see my answer: fd leak, custom Shell

Related

Piping output between N processes in C

I'm trying to write a C program to simulate the piping of two or more processes together, like ls | sort | wc so running my code as ./driver ls sort wc should show the same result. I think I'm really close, but I can't seem to find the bug in my code below. Any help would be appreciated, I'm really stumped here.
I think I understand what is supposed to happen, but Im crossing my wires somehow in making it happen. The parent should fork child processes who in turn reroute their STDOUT to the write end of a pipe(a). Any child who is created beyond the first child should consider the read end of this pipe(a) as its STDIN, as well as redirect it's own output to a pipe(b) of it's own.
Say a third process is piped. It should consider the read end of the pipe(b) as STDIN, and again pipe its output to the write end of a new pipe(c) before executing the requested command.
The last case is the when the final process is passed to the pipe. In this example, a fourth process would consider the read end of the pipe(c) but should not need to redirect the STDOUT, just send it to STDOUT as normal.
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#define FORK_CHILD 0
static void error_and_exit(void) {
fprintf(stderr, "Error: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
static int fork_or_die(void) {
int pid = fork();
if (pid == -1) {
error_and_exit();
}
return pid;
}
int main(const int argc, const char * argv[])
{
int processes = argc - 1;
int apipe[argc - 1][2];
int pid;
int result = -1;
for (int i = 0; i < processes; i++) {
result = pipe(apipe[i]);
if (result == -1) {
error_and_exit();
}
}
for (int i = 0; i < processes; i++) {
pid = fork_or_die();
// Child process executes process
if (pid == FORK_CHILD) {
// If we are not the first program in the pipe
if (i > 1) {
// Use the output from the previous program in the pipe as our input
// Check the read end of the pipe and STDIN are different descriptors
if (apipe[i - 1][0] != STDIN_FILENO) {
// Send the read end of the pipe to STDIN
if (dup2(apipe[i - 1][0], STDIN_FILENO) == -1) {
error_and_exit();
}
}
}
// Before we execute a process, bind the write end of the pipe to STDOUT
// Don't do this to the last process in the pipe, just send output to STDOUT as normal
if (i < processes - 1) {
// Check the write end of the pipe and STDOUT are different descriptors
if (apipe[i][1] != STDOUT_FILENO) {
// Send the write end of the pipe to STDOUT
if (dup2(apipe[i][1], STDOUT_FILENO) == -1) {
error_and_exit();
}
}
}
// Child executes requested process
if (execlp(argv[i + 1], argv[i + 1], (char *)NULL) == -1) {
error_and_exit();
}
wait(NULL);
}
// Parent does nothing until loop exits (waits for children)
}
return 0;
}
I've spotted three issues with your code:
As You have decided to index children starting from 0, not one but two processes will skip this part of code. The simplest fix that comes to my mind right now is to change the 1 to 0 or > to >=.
// If we are not the first program in the pipe
if (i > 1) {
You are calling wait in code that is not executed by parent. Moving the call outside the if (pid == FORK_CHILD) branch won't help as parent will wait for one child to finish before another one is started. Child process's write operation may wait for next child to consume some data and make place in buffer. Simplest solution that comes to my mind right now is to move wait calls to another loop.
You keep all pipe's descriptor open in parent and child processes. You should close it before wait loop in parent and before execlp in forked processes. The programs like grep, sort won't finish unless they receive EOF in their incoming streams. The pipe won't send EOF as long as at least one write descriptor is still open.
The code with minimal changes applied:
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#define FORK_CHILD 0
static void error_and_exit(void) {
fprintf(stderr, "Error: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
static int fork_or_die(void) {
int pid = fork();
if (pid == -1) {
error_and_exit();
}
return pid;
}
int main(const int argc, const char * argv[])
{
int processes = argc - 1;
int apipe[argc - 1][2];
int pid;
int result = -1;
for (int i = 0; i < processes; i++) {
result = pipe(apipe[i]);
if (result == -1) {
error_and_exit();
}
}
for (int i = 0; i < processes; i++) {
pid = fork_or_die();
// Child process executes process
if (pid == FORK_CHILD) {
// If we are not the first program in the pipe
if (i > 0) {
// Use the output from the previous program in the pipe as our input
// Check the read end of the pipe and STDIN are different descriptors
if (apipe[i - 1][0] != STDIN_FILENO) {
// Send the read end of the pipe to STDIN
if (dup2(apipe[i - 1][0], STDIN_FILENO) == -1) {
error_and_exit();
}
}
}
// Before we execute a process, bind the write end of the pipe to STDOUT
// Don't do this to the last process in the pipe, just send output to STDOUT as normal
if (i < processes - 1) {
// Check the write end of the pipe and STDOUT are different descriptors
if (apipe[i][1] != STDOUT_FILENO) {
// Send the write end of the pipe to STDOUT
if (dup2(apipe[i][1], STDOUT_FILENO) == -1) {
error_and_exit();
}
}
}
for (int j = 0; j < processes; j++) {
if(close(apipe[j][0]) == -1)
error_and_exit();
if(close(apipe[j][1]) == -1)
error_and_exit();
}
// Child executes requested process
if (execlp(argv[i + 1], argv[i + 1], (char *)NULL) == -1) {
error_and_exit();
}
}
}
// Parent does nothing until loop exits (waits for children)
for (int i = 0; i < processes; i++) {
if(close(apipe[i][0]) == -1)
error_and_exit();
if(close(apipe[i][1]) == -1)
error_and_exit();
}
for (int i = 0; i < processes; i++) {
wait(NULL);
}
return 0;
}

C - Implementing pipes in a basic shell [duplicate]

I am trying to implement a shell in C. I can execute simple commands just fine with a simple execvp() but one of the requirements is to manage commands like this: "ls -l | head | tail -4" with a 'for' loop and only one 'pipe()' statement redirecting stdin and stdout. Now after days I'm a bit lost.
N = Number of simple commands (3 in the example: ls, head, tail)
commands = a list of structs with the commands, like this:
commands[0].argv[0]: ls
commands[0].argv[1]: -l
commands[1].argv[0]: head
commands[2].argv[0]: tail
commands[2].argv[1]: -4
So, I made the for loop, and started to redirect stdin and stdout in order to connect all the commands with pipes, but...I'm just clueless why it doesn't work.
for (i=0; i < n; i++){
pipe(pipe);
if(fork()==0){ // CHILD
close(pipe[0]);
close(1);
dup(pipe[1]);
close(pipe[1]);
execvp(commands[i].argv[0], &commands[i].argv[0]);
perror("ERROR: ");
exit(-1);
}else{ // FATHER
close(pipe[1]);
close(0);
dup(pipe[0]);
close(pipe[0]);
}
}
What I want to create is a 'line' of childed processes:
[ls -l] ----pipe----> [head] ----pipe----> [tail -4]
All this processes have a root (the process runing my shell) so, the first father is also a child of the shell process, I'm a bit exhausted already, can anyone help me here please?
I'm not even sure if the childs should be the ones executing the commands.
Thanks guys !!
Nothing complex here, just have in mind that the last command should output to the original process' file descriptor 1 and the first should read from original process file descriptor 0. You just spawn the processes in order, carrying along the input side of the previous pipe call.
So, here's are the types:
#include <unistd.h>
struct command
{
const char **argv;
};
Make a helper function with a simple well defined semantics:
int
spawn_proc (int in, int out, struct command *cmd)
{
pid_t pid;
if ((pid = fork ()) == 0)
{
if (in != 0)
{
dup2 (in, 0);
close (in);
}
if (out != 1)
{
dup2 (out, 1);
close (out);
}
return execvp (cmd->argv [0], (char * const *)cmd->argv);
}
return pid;
}
And here's the main fork routine:
int
fork_pipes (int n, struct command *cmd)
{
int i;
pid_t pid;
int in, fd [2];
/* The first process should get its input from the original file descriptor 0. */
in = 0;
/* Note the loop bound, we spawn here all, but the last stage of the pipeline. */
for (i = 0; i < n - 1; ++i)
{
pipe (fd);
/* f [1] is the write end of the pipe, we carry `in` from the prev iteration. */
spawn_proc (in, fd [1], cmd + i);
/* No need for the write end of the pipe, the child will write here. */
close (fd [1]);
/* Keep the read end of the pipe, the next child will read from there. */
in = fd [0];
}
/* Last stage of the pipeline - set stdin be the read end of the previous pipe
and output to the original file descriptor 1. */
if (in != 0)
dup2 (in, 0);
/* Execute the last stage with the current process. */
return execvp (cmd [i].argv [0], (char * const *)cmd [i].argv);
}
And a small test:
int
main ()
{
const char *ls[] = { "ls", "-l", 0 };
const char *awk[] = { "awk", "{print $1}", 0 };
const char *sort[] = { "sort", 0 };
const char *uniq[] = { "uniq", 0 };
struct command cmd [] = { {ls}, {awk}, {sort}, {uniq} };
return fork_pipes (4, cmd);
}
Appears to work. :)
First, you are prematurely closing the pipes. Close only the end that you don't need in the current process, and remember to close stdin/stdout in the child.
Secondly, you need to remember the fd from the previous command. So, for two processes, this looks like:
int pipe[2];
pipe(pipe);
if ( fork() == 0 ) {
/* Redirect output of process into pipe */
close(stdout);
close(pipe[0]);
dup2( pipe[1], stdout );
execvp(commands[0].argv[0], &commands[0].argv[0]);
}
if ( fork() == 0 ) {
/* Redirect input of process out of pipe */
close(stdin);
close(pipe[1]);
dup2( pipe[0], stdin );
execvp(commands[1].argv[0], &commands[1].argv[0]);
}
/* Main process */
close( pipe[0] );
close( pipe[1] );
waitpid();
Now your job is to add error handling to this and generate n-1 pipes for n processes to start. The code in the first fork() block needs to be run for the appropriate pipe for processes 1..n-1, and the code in the second fork() block for the processes 2..n.

How do you create Unix pipes dynamically?

I have a program that uses fork() to create child processes, and I want to have the children communicate back to the parent process using Unix pipes.
The problem is that multiple pipes don't seem to be created, or maybe there's a problem with my array. When I used prinf() in the parent program it reads identical data from every pipe, even though each child sends different data.
Here is my code:
// Variables
int pipes_count = 0;
int *pipes[MAXCLIENTS];
int new_pipefd[2];
int pipe_bytes;
char pipe_buffer[MAXDATASIZE];
while(1) {
// Pipe creation
pipe(new_pipefd);
pipes[pipes_count] = new_pipefd;
pipes_count++;
if (fork()) {
// unrelated code for parent here
close(new_pipefd[1]); // close the parent's write-end of the pipe
break;
} else {
// unrelated code for child here
close(new_pipefd[0]); // close the child's read-end of the pipe
break;
}
if (some condition) { break; } // The parent will stop creating pipes
}
while(condition that guarantees this is the child) {
write(new_pipefd[1], buffer, strlen(recv_buffer));
close(new_pipefd[1]);
return 0; // the child process ends
}
// This is a loop where the parent reads what the children sent
for (int i = 0; i < pipes_count; i++) {
pipe_bytes = read(pipes[i][0], pipe_buffer, sizeof pipe_buffer);
if (pipe_bytes == 0) {
close(pipes[i][0]);
} else {
printf("Testing: %s\n", pipe_buffer);
}
}
As I noted in my comments, the problem is in the assignment pipes[pipes_count] = new_pipefd; at:
int pipes_count = 0;
int *pipes[MAXCLIENTS];
int new_pipefd[2];
int pipe_bytes;
char pipe_buffer[MAXDATASIZE];
while(1) {
// Pipe creation
pipe(new_pipefd);
pipes[pipes_count] = new_pipefd;
pipes_count++;
The trouble is that the variable new_pipefd is an array, so you're copying the address of the same array into each of the elements of pipes, which means that the parent only has access to the last pipe that was created.
I think you should be using code more like:
int pipes_count = 0;
int pipes[MAXCLIENTS]; // Changed type!
int new_pipefd[2];
char pipe_buffer[MAXDATASIZE];
while (1)
{
// Pipe creation
pipe(new_pipefd);
pipes[pipes_count++] = new_pipefd[0]; // Just the read end of the pipe
if (fork())
{
// unrelated code for parent here
close(new_pipefd[1]); // close the parent's write-end of the pipe
// break; // This break is not wanted
}
else
{
// unrelated code for child here
close(new_pipefd[0]); // close the child's read-end of the pipe
break;
}
if (some condition)
break; // The parent will stop creating pipes
}
while (condition that guarantees this is the child)
{
write(new_pipefd[1], buffer, strlen(recv_buffer));
close(new_pipefd[1]);
return 0; // the child process ends
}
// This is a loop where the parent reads what the children sent
for (int i = 0; i < pipes_count; i++) {
int pipe_bytes = read(pipes[i], pipe_buffer, sizeof(pipe_buffer));
if (pipe_bytes != 0)
printf("Testing: %.*s\n", pipe_bytes, pipe_buffer); // Safe!
close(pipes[i]);
}
Were it my code, I'd have a function (which I traditionally call be_childish()) to invoke in the 'if it is a child' block of code in the loop. The function would never return, and would be passed whatever resources it needs (new_pipefd for sure, maybe other information too). I often have a function be_parental() to do the parental activities. I find this cleans up most of the code, forcing clean separation of the activities.

Connecting n commands with pipes in a shell?

I am trying to implement a shell in C. I can execute simple commands just fine with a simple execvp() but one of the requirements is to manage commands like this: "ls -l | head | tail -4" with a 'for' loop and only one 'pipe()' statement redirecting stdin and stdout. Now after days I'm a bit lost.
N = Number of simple commands (3 in the example: ls, head, tail)
commands = a list of structs with the commands, like this:
commands[0].argv[0]: ls
commands[0].argv[1]: -l
commands[1].argv[0]: head
commands[2].argv[0]: tail
commands[2].argv[1]: -4
So, I made the for loop, and started to redirect stdin and stdout in order to connect all the commands with pipes, but...I'm just clueless why it doesn't work.
for (i=0; i < n; i++){
pipe(pipe);
if(fork()==0){ // CHILD
close(pipe[0]);
close(1);
dup(pipe[1]);
close(pipe[1]);
execvp(commands[i].argv[0], &commands[i].argv[0]);
perror("ERROR: ");
exit(-1);
}else{ // FATHER
close(pipe[1]);
close(0);
dup(pipe[0]);
close(pipe[0]);
}
}
What I want to create is a 'line' of childed processes:
[ls -l] ----pipe----> [head] ----pipe----> [tail -4]
All this processes have a root (the process runing my shell) so, the first father is also a child of the shell process, I'm a bit exhausted already, can anyone help me here please?
I'm not even sure if the childs should be the ones executing the commands.
Thanks guys !!
Nothing complex here, just have in mind that the last command should output to the original process' file descriptor 1 and the first should read from original process file descriptor 0. You just spawn the processes in order, carrying along the input side of the previous pipe call.
So, here's are the types:
#include <unistd.h>
struct command
{
const char **argv;
};
Make a helper function with a simple well defined semantics:
int
spawn_proc (int in, int out, struct command *cmd)
{
pid_t pid;
if ((pid = fork ()) == 0)
{
if (in != 0)
{
dup2 (in, 0);
close (in);
}
if (out != 1)
{
dup2 (out, 1);
close (out);
}
return execvp (cmd->argv [0], (char * const *)cmd->argv);
}
return pid;
}
And here's the main fork routine:
int
fork_pipes (int n, struct command *cmd)
{
int i;
pid_t pid;
int in, fd [2];
/* The first process should get its input from the original file descriptor 0. */
in = 0;
/* Note the loop bound, we spawn here all, but the last stage of the pipeline. */
for (i = 0; i < n - 1; ++i)
{
pipe (fd);
/* f [1] is the write end of the pipe, we carry `in` from the prev iteration. */
spawn_proc (in, fd [1], cmd + i);
/* No need for the write end of the pipe, the child will write here. */
close (fd [1]);
/* Keep the read end of the pipe, the next child will read from there. */
in = fd [0];
}
/* Last stage of the pipeline - set stdin be the read end of the previous pipe
and output to the original file descriptor 1. */
if (in != 0)
dup2 (in, 0);
/* Execute the last stage with the current process. */
return execvp (cmd [i].argv [0], (char * const *)cmd [i].argv);
}
And a small test:
int
main ()
{
const char *ls[] = { "ls", "-l", 0 };
const char *awk[] = { "awk", "{print $1}", 0 };
const char *sort[] = { "sort", 0 };
const char *uniq[] = { "uniq", 0 };
struct command cmd [] = { {ls}, {awk}, {sort}, {uniq} };
return fork_pipes (4, cmd);
}
Appears to work. :)
First, you are prematurely closing the pipes. Close only the end that you don't need in the current process, and remember to close stdin/stdout in the child.
Secondly, you need to remember the fd from the previous command. So, for two processes, this looks like:
int pipe[2];
pipe(pipe);
if ( fork() == 0 ) {
/* Redirect output of process into pipe */
close(stdout);
close(pipe[0]);
dup2( pipe[1], stdout );
execvp(commands[0].argv[0], &commands[0].argv[0]);
}
if ( fork() == 0 ) {
/* Redirect input of process out of pipe */
close(stdin);
close(pipe[1]);
dup2( pipe[0], stdin );
execvp(commands[1].argv[0], &commands[1].argv[0]);
}
/* Main process */
close( pipe[0] );
close( pipe[1] );
waitpid();
Now your job is to add error handling to this and generate n-1 pipes for n processes to start. The code in the first fork() block needs to be run for the appropriate pipe for processes 1..n-1, and the code in the second fork() block for the processes 2..n.

Implementing pipelining in a Linux shell

I'm trying to develop a shell in Linux as an Operating Systems project. One of the requirements is to support pipelining (where calling something like ls -l|less passes the output of the first command to the second). I'm trying to use the C pipe() and dup2() commands but the redirection doesn't seem to be happening (less complains that it didn't receive a filename). Can you identify where I'm going wrong/how I might go about fixing that?
EDIT: I'm thinking that I need to use either freopen or fdopen somewhere since I'm not using read() or write()... is that correct?
(I've heard from others who've done this project that using freopen() is another way to solve this problem; if you think that would be better, tips for going that direction would also be appreciated.)
Here's my execute_external() function, which executes all commands not built-in to the shell. The various commands in the pipe (e.g. [ls -l] and [less]) are stored in the commands[] array.
void execute_external()
{
int numCommands = 1;
char **commands;
commands = malloc(sizeof(char *));
if(strstr(raw_command, "|") != NULL)
{
numCommands = separate_pipeline_commands(commands);
}
else
{
commands[0] = malloc(strlen(raw_command) * sizeof(char));
commands[0] = raw_command;
}
int i;
int pipefd[2];
for (i = 0; i < numCommands; i++)
{
char **parameters_array = malloc(strlen(commands[i]) * sizeof(char *));
int num_params;
num_params = str_to_str_array(commands[i], parameters_array);
if (numCommands > 1 && i > 0 && i != numCommands - 1)
{
if (pipe(pipefd) == -1)
{
printf("Could not open a pipe.");
}
}
pid_t pid = fork();
pmesg(2, "Process forked. ID = %i. \n", pid);
int status;
if (fork < 0)
{
fprintf(to_write_to, "Could not fork a process to complete the external command.\n");
exit(EXIT_FAILURE);
}
if (pid == 0) // This is the child process
{
if (numCommands > 1) { close(pipefd[1]); } // close the unused write end of the pipe
if (i == 0) // we may be pipelining and this is the first process
{
dup2(1, pipefd[1]); // set the source descriptor (for the next iteration of the loop) to this proc's stdout
}
if (i !=0 && (i != numCommands-1)) // we are pipelining and this is not the first or last process
{
dup2(pipefd[0], 0); // set the stdin of this process to the source of the previous process
}
if (execvp(parameters_array[0], parameters_array) < 0)
{
fprintf(to_write_to, "Could not execute the external command. errno: %i.\n", errno);
exit(EXIT_FAILURE);
}
else { pmesg(2, "Executed the child process.\n");}
}
else
{
if (numCommands > 1) { close(pipefd[0]); } // close the unused read end of the pipe
if (backgrounding == 0) { while(wait(&status) != pid); }// Wait for the child to finish executing
}
free(parameters_array);
}
free(commands);
}
It looks like there are a couple of bugs going on in your code.
First, all your dup2's are only in the child. In order to connect a pipe you will need to dup2 the stdout of the parent to the write end pipefd[1] of the pipe. Then you would hook up the read end to stdin.
Also it looks like on of your dup2's is backwards with dup2 fildes is duplicated to fildes2. So when you reassign stdin you want dup2(in, 0) and for stdout you want dup2(out, 1).
So a stripped down piece of piping code is going to look like:
int pipefd[2];
pipe(pipefd);
pid_t pid = fork();
if (pid == 0) //The child
{
dup2(pipefd[0], 0);
}
else
{
dup2(pipefd[1], 1);
}

Resources