Hi All,
I want to execute a binary and trap the stdout and stderr . I don't have the code for the binary. I have got the solution for this on the same list which is working fine. Many Thanks to Dave.
Here's the code :
=================================
Main Program:
/*
* Sample program to demonstrate super_popen
*
* by dave madden <dhm@webvision.com>
*/
#include <stdio.h>
#include <errno.h>
#include <sys/select.h>
int
super_popen( FILE **SI_SO_SE, const char *cmd )
{
int si[2] = { -1, -1 };
int so[2] = { -1, -1 };
int se[2] = { -1, -1 };
pid_t pid;
int e;
int fd;
/*
* Create 3 pipes to talk to subprocess on stdin/stdout/stderr
*/
if (pipe( si ) != 0 || pipe( so ) != 0 || pipe( se ) != 0) goto SHUTDOWN;
if ((pid = fork( )) == -1) goto SHUTDOWN;
if (pid) { /* in parent */
wait(0);
close( si[0] );
close( so[1] );
close( se[1] );
SI_SO_SE[0] = fdopen( si[1], "w" );
SI_SO_SE[1] = fdopen( so[0], "r" );
SI_SO_SE[2] = fdopen( se[0], "r" );
return 0; /* OK! */
}
/*
* This is the child process...we have to fiddle around with the
* pipe descriptors and then exec the program.
*/
/*
* Make sure none of our stdin/stdout/stderr descriptors are
* on FDs 0, 1, or 2 (if they are, it'll screw things up when
* we do the dup2()'s)
*/
if (si[0] < 2 || so[1] < 2 || se[1] < 2) {
int free_index = 0;
int free_fds[3];
printf( "have to (Edited by Computer101) with FDs in child\n" );
for (fd = 3; fd < FD_SETSIZE; fd++) {
if (fd != si[0] && fd != si[1] && fd != se[1]) {
free_fds[free_index++] = fd;
if (free_index == 3) break;
}
}
if (dup2( si[0], free_fds[0] ) == -1 ||
dup2( so[1], free_fds[1] ) == -1 ||
dup2( se[1], free_fds[2] ) == -1) exit( errno );
si[0] = free_fds[0];
so[1] = free_fds[1];
se[1] = free_fds[2];
}
/* close all other descriptors...don't want child to have copies */
for (fd = 0; fd < FD_SETSIZE; fd++)
if (fd != si[0] && fd != so[1] && fd != se[1]) close( fd );
dup2( si[0], 0 ); /* attach pipes to FD 0, 1, and 2 */
dup2( so[1], 1 );
dup2( se[1], 2 );
close( si[0] );
close( so[1] );
close( se[1] );
/* write( 1, "Hello\n", 6 );
write( 2, "World\n", 6 );
exit( 0 );*/
exit( execl( "/usr/bin/sh", "sh", "-c", cmd, 0 ) ); <=========My binary with arguments works fine
SHUTDOWN: /* something went wrong...close the pipes & etc */
e = errno;
close( si[0] ); close( si[1] );
close( so[0] ); close( so[1] );
close( se[0] ); close( se[1] );
errno = e;
return -1;
}
int
main( int argc, char **argv ) <========================Changed to a function in Library and called from my
{ application
FILE *child_io[3];
if (argc != 2) {
printf( "usage: %s <name-of-program-to-run>\n", argv[0] );
exit( 1 );
}
if (super_popen( child_io, argv[1] ) == 0) {
char buf[256];
fprintf( child_io[0], "Message to child\n" );
fflush( child_io[0] );
while (fgets( buf, sizeof(buf), child_io[1] ) != 0) { <================= Cannot read This Goes on endlessly
printf( "Child STDOUT: \"%.*s\"\n", strlen(buf) - 1, buf ); when function is called from library
}
while (fgets( buf, sizeof(buf), child_io[2] ) != 0) { <================= Cannot read This Goes on endlessly
printf( "Child STDERR: \"%.*s\"\n", strlen(buf) - 1, buf ); when function is called from library
}
} else {
printf("couldn't run %s: %d (%s)\n", argv[1], errno, strerror(errno));
}
exit( 0 );
}
=================================
But my problem is that I want to use all this code in a static library so I converted the main function to a function and made static library using codewarrior .Now when I call this function from my application it does everything finely except that it is not able to read from the File pointers being returned in the parent process in super_popen.
My application is MACOS X application.
(Please see my comments at relevant places in the code)
In the nutshell I cannot read from child_io[1] and child_io[2] when the function is called from the library.
Can somebody please point out what the problem is ?
Thanks in Advance
Deepak Kapila
=============================================
This question has been deleted with no points refunded. 01/25/2004 09:32AM PST
Computer101
E-E Admin
=============================================
by: orangehead911Posted on 2003-08-08 at 00:04:03ID: 9106177
> In the nutshell I cannot read from child_io[1] and child_io[2] when the function is called from the library.
Did this code work in a context outside of a static library?
The fgets() function call will block until either a newline character is encountered, end-of-file is reached or there is an error.
Do you have a guarantee that you will receive output from child_io[1] before child_io[2]? If not, your first call to fgets() will block until either of the above mentioned conditions occur. Furthermore, according to your code, your expecting ALL output to arrive on child_io[1] and end, BEFORE ANY output is read from child_io[2].
Assuming that it did, this is the classic single thread problem. Basically, you have blocking function calls, the fgets() function call will block until either the above mentioned conditions occur.
You should create one thread per descriptor you would like to read/write to/from to be able to asynchronously access all descriptors. If you don't, you will most likely block on one descriptor, while another one produces data. How would you abritrarily know which descriptor to read from first? You wouldn't!
You can do a 'man pthread' to access the man pages for the pthread API. I will be able to help you with the threading too, but if you already know how to handle pthreads...
I hope this helps!
orangehead