El código proporcionado por eerpini no funciona como está escrito. Tenga en cuenta, por ejemplo, que los extremos de tubería que están cerrados en el elemento primario se usan posteriormente. Mire
close(wpipefd[1]);
y la posterior escritura en ese descriptor cerrado. Esto es solo una transposición, pero muestra que este código nunca se ha usado. A continuación hay una versión que he probado. Desafortunadamente, cambié el estilo del código, por lo que no se aceptó como una edición del código de eerpini.
El único cambio estructural es que solo redirigí las E/S del niño (tenga en cuenta que las llamadas dup2 solo están en la ruta secundaria). Esto es muy importante porque las E/S del padre se estropean. Gracias a eerpini por la respuesta inicial, que utilicé para desarrollar esta.
#define PIPE_READ 0
#define PIPE_WRITE 1
int createChild(const char* szCommand, char* const aArguments[], char* const aEnvironment[], const char* szMessage) {
int aStdinPipe[2];
int aStdoutPipe[2];
int nChild;
char nChar;
int nResult;
if (pipe(aStdinPipe) < 0) {
perror("allocating pipe for child input redirect");
return -1;
}
if (pipe(aStdoutPipe) < 0) {
close(aStdinPipe[PIPE_READ]);
close(aStdinPipe[PIPE_WRITE]);
perror("allocating pipe for child output redirect");
return -1;
}
nChild = fork();
if (0 == nChild) {
// child continues here
// redirect stdin
if (dup2(aStdinPipe[PIPE_READ], STDIN_FILENO) == -1) {
exit(errno);
}
// redirect stdout
if (dup2(aStdoutPipe[PIPE_WRITE], STDOUT_FILENO) == -1) {
exit(errno);
}
// redirect stderr
if (dup2(aStdoutPipe[PIPE_WRITE], STDERR_FILENO) == -1) {
exit(errno);
}
// all these are for use by parent only
close(aStdinPipe[PIPE_READ]);
close(aStdinPipe[PIPE_WRITE]);
close(aStdoutPipe[PIPE_READ]);
close(aStdoutPipe[PIPE_WRITE]);
// run child process image
// replace this with any exec* function find easier to use ("man exec")
nResult = execve(szCommand, aArguments, aEnvironment);
// if we get here at all, an error occurred, but we are in the child
// process, so just exit
exit(nResult);
} else if (nChild > 0) {
// parent continues here
// close unused file descriptors, these are for child only
close(aStdinPipe[PIPE_READ]);
close(aStdoutPipe[PIPE_WRITE]);
// Include error check here
if (NULL != szMessage) {
write(aStdinPipe[PIPE_WRITE], szMessage, strlen(szMessage));
}
// Just a char by char read here, you can change it accordingly
while (read(aStdoutPipe[PIPE_READ], &nChar, 1) == 1) {
write(STDOUT_FILENO, &nChar, 1);
}
// done with these in this example program, you would normally keep these
// open of course as long as you want to talk to the child
close(aStdinPipe[PIPE_WRITE]);
close(aStdoutPipe[PIPE_READ]);
} else {
// failed to create child
close(aStdinPipe[PIPE_READ]);
close(aStdinPipe[PIPE_WRITE]);
close(aStdoutPipe[PIPE_READ]);
close(aStdoutPipe[PIPE_WRITE]);
}
return nChild;
}
posible duplicado de [? ¿Cómo puedo ejecutar un programa externo de C y analizar su salida] (http://stackoverflow.com/questions/43116/how-can -i-run-an-external-program-from-c-and-parse-its-output) –
¿Qué es "Linux 3.0"? – Joe
@Joachim Pileborg: No, no es un duplicado, necesito stdin y stdout. popen es unidireccional (stdin o stdout, no ambos). –