I have a working code for what you are trying to achieve here:
static bool
start_subprocess(char *const command[], int *pid, int *infd, int *outfd)
{
int p1[2], p2[2];
if (!pid || !infd || !outfd)
return false;
if (pipe(p1) == -1)
goto err_pipe1;
if (pipe(p2) == -1)
goto err_pipe2;
if ((*pid = fork()) == -1)
goto err_fork;
if (*pid) {
*infd = p1[1];
*outfd = p2[0];
close(p1[0]);
close(p2[1]);
return true;
} else {
dup2(p1[0], 0);
dup2(p2[1], 1);
close(p1[0]);
close(p1[1]);
close(p2[0]);
close(p2[1]);
execvp(*command, command);
/* Subprocess error occured. */
fprintf(stderr, "error running %s: %s\n", *command, strerror(errno));
abort();
}
err_fork:
close(p2[1]);
close(p2[0]);
err_pipe2:
close(p1[1]);
close(p1[0]);
err_pipe1:
return false;
}
You can consider this function public domain. It accepts a NULL-terminated list of command line arguments including the command itself and it sets the process id and file descriptors to talk to stdin and stdout output parameters.
On top of that you would acquire some knowlege about read
/write
POSIX-style functions (and syscalls), fgets
/fputs
and similar (buffered) ANSI-style functions and the bridges between them like fdopen
.