I've checked the socket FAQ and old usenet articles related to the
subject but I haven't found a solution to my specific problem. I'm
attempting to exec() a tty-oriented interactive program that uses the
stdio library. I go through the usual redirection of stdin, stdout to a
socket before exec()'ing the program, but I'm finding that due to the
buffering of stdout in the exec()'d child, I can't access all the
child's output from the parent using a socket read().
I don't have the source to the exec()'d program so explicitly
fflush()'ing stdout is not an option. The only partial solution I've
been able to come up with (see snippet below) is to set the child's
stdout socket buffer size to one byte using setsockopt(). However, this
is only a partial solution since one byte of data is always inaccessible
in a stdio buffer until another byte is sent to stdout - this leaves the
parent always one byte short! I also tried disabling buffering on the
redirected stdout stream using setvbuff() just before exec()'ing the
child program (again, see snippet below) but this attribute did not get
inherited by the child.
So is my partial solution the only solution? Or is there some other
approach I have overlooked. Any help would be greatly appreciated!
Code snippet follows my .sig...
--
* Greg Bond * Dept. of Electrical Eng.
* voice: (604) 822 0899 * 2356 Main Mall
* fax: (604) 822 5949 * Vancouver, BC
* web: http://www.ee.ubc.ca/~bond * Canada, V6T 1Z4
/* parent.c */
/* Copyright 1996, GWBond, Dept. of Electrical Eng., UBC */
/* GWBond July 1996 */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
main(int argc, char **argv) {
int sockets[2];
char *child = argv[1];
pid_t child_pid;
int bufsz = 1;
if (socketpair (AF_UNIX, SOCK_STREAM, 0, sockets) != 0 ) {
fprintf (stderr, "Socket creation failure");
exit(0);
}
if ((child_pid = fork ()) == -1) {
fprintf (stderr, "Error forking child");
exit(0);
}
if (child_pid == 0) {
/* child */
char *argv[] = {NULL, NULL};
argv[0] = child;
close (sockets[0]);
if (dup2 (sockets[1], 0) != 0) {
fprintf (stderr, "Error redirecting stdin");
exit(0);
}
if (dup2 (sockets[1], 1) != 1) {
fprintf (stderr, "Error redirecting stdout");
exit(0);
}
/* currently using stderr for debugging */
/* dup2 (sockets[1], 2);*/
close (sockets[1]);
/* Set buffer size on stdout socket to be one byte. */
/* Still means that last byte in buff can't be read by parent! */
setsockopt (1, SOL_SOCKET, SO_SNDBUF, &bufsz, sizeof (bufsz));
/* Alternative to above is to disable buffering on stdout stream. */
/* But this attribute doesn't get inherited by exec'd child! */
/* if (setvbuf (stdout, NULL, _IONBF, 0) != 0) {*/
/* fprintf (stderr, "Error modifying stdout buffering"); */
/* exit(0); */
/* } */
if (execv (child, argv) == -1) {
fprintf (stderr, "Child creation failure");
exit(0);
}
}
else {
/* parent */
/* rest of code deleted .... */