Les pipes (ou les sockets) fonctionnent très bien pour faire ce que tu demandes. A mon avis, il doit y avoir quelques erreurs dans ton code. A titre d'information, voilà un bout de code repris d'un projet qui fait ce que tu demandes. Je croisi que les noms de variables et de fonctions sont assez explicites. Le troisièmem argument de la fonction est un pointeur vers un entier dans lequel sera stocké le descripteur du socket à utiliser pour lire l'output du programme. Par exemple:
int output_desc;
io_popen(, , &output_desc);
read(output_desc, ...
int
io_popen(char *argv[], char *envp[], int *srv_child)
{
int sockpair[2];
int child_srv;
if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair) == -1)
{
log_error("socketpair failed: %s", strerror(errno));
return -1;
}
*srv_child = sockpair[0];
child_srv = sockpair[1];
int retval = fork();
if(retval < 0)
{
/* parent - fork has failed */
log_error("fork failed: %s", strerror(errno));
io_close(child_srv);
io_close(*srv_child);
return -1;
}
else if(retval > 0)
{
/* parent - close the file descriptor used by the child */
io_close(child_srv);
return 0;
}
/*---------------*
| Child process |
*---------------*/
/* close socket used by parent */
io_close(*srv_child);
/* logs shouldn't be accessed by cgi */
log_close();
/* close stdin and stdout */
io_close(STDIN_FILENO);
io_close(STDOUT_FILENO);
/* duplicate input and output to stdin and stdout */
if (dup2(child_srv, STDIN_FILENO) != STDIN_FILENO ||
dup2(child_srv, STDOUT_FILENO) != STDOUT_FILENO)
{
io_close(child_srv);
debug_msg(ERROR, "dup2 failed: %s", strerror(errno));
_exit(EXIT_FAILURE);
}
execve(argv[0], argv, envp);
/* execve doesn't return on success */
if (errno == ENOEXEC || errno == EACCES)
debug_msg(ERROR, "CGI file not executable");
else
debug_msg(ERROR, "execve failed: %s", strerror(errno));
/* prevent the call to the function registered with atexit */
_exit(EXIT_FAILURE);
}
|