mchawi@garnet.berkeley.edu (06/22/89)
it is in these dark moments of being really confounded by seemingly simple problems for long periods of time that i fling my problems forth: on sunos 3.5 (egads!), given a child process that has its stdin & stdout tied to an AF_INET socket, it seems that it is necessary to force a fflush() to send output through the socket connection. i don't want to change the child program in any way (it's huge), it just does simple printf's and gets(). this problem doesn't occur prior to the exec()! i thought that the child inherits the exact same file descriptors. here are [3] programs (server, client, & child) that demo the problem: /*-(cut-here)---------------------------------------------------------*/ #include <stdio.h> #include <fcntl.h> #include <sgtty.h> char b[380]; int main () { struct sgttyb t, u; int fd, status, pid, w; if (setup_inet (&fd)) /* set up a server socket */ return (-1); if ((pid = fork ()) == 0) { close (0); dup (fd); /* redirect stdio */ close (1); dup (fd); close (fd); printf ("inside child's for() call, b4 the exec().\n"); printf ("\nthese lines print out ok to the client.\n"); execlp ("gekko", "gekko", (char *) 0); exit (127); } close (fd); while ((w = wait (&status)) != pid && w != -1) ; } #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> static struct sockaddr_in server; /*--------------------------------------*/ int setup_inet (pfd) int *pfd; { int sock, length; sock = socket (AF_INET, SOCK_STREAM, 0); /* create socket */ if (sock < 0) exit (-1); server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = 0; if (bind (sock, &server, sizeof (server))) { perror ("binding stream socket\n"); exit (-1); } /* find out assigned port number */ length = sizeof (server); getsockname (sock, &server, &length); printf ("server: socket has port #%d\n", ntohs (server.sin_port)); listen (sock, 5); *pfd = accept (sock, 0, 0); /* start accepting connections */ return (0); } /*-(cut-here)---------------------------------------------------------*/ /* "gekko", the child program: */ #include <stdio.h> #include <sgtty.h> main () { char b[80]; for (;;) { printf ("input: "); gets (b); printf ("got: %s\n", b); #if !PROBLEM_SOLVED fflush (stdout); /* <<<--- WANNA EXCLUDE THIS */ #endif } } /*-(cut-here)---------------------------------------------------------*/ /* client program, simplified. enter the name of the machine the server program is running on, and the port number it returns. */ #include <stdio.h> #include <sys/types.h> #include <sys/time.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> char host [22]; int port; int fd; struct sockaddr_in x; struct timeval ts; /*----------------------*/ main () { char b[333]; struct hostent *hp; ts.tv_sec = 5; ts.tv_usec = 0; printf ("host? "); gets (host); /* get the name & number */ printf ("port? "); gets (b); port = atoi (b); fd = socket (AF_INET, SOCK_STREAM, 0); bzero ((char *) &x, sizeof (struct sockaddr_in)); x.sin_family = AF_INET; hp = gethostbyname (host); if (hp == NULL) exit (-1); bcopy (hp->h_addr, (char *) &x.sin_addr, hp->h_length); x.sin_port = (unsigned short) htons (port); /* connect the client */ if (connect (fd, &x, sizeof (struct sockaddr_in)) < 0) { perror ("not connected"); exit (-1); } main_loop (); } /*----------------------*/ main_loop () { int i, n; char B[256]; for (;;) { printf ("0 - quit; 1 - read; 2 - write.\n"); printf ("what? "); gets (B); switch (B[0]) { case '1': if (read_socket (B, &n)) return (-1); if (n) printf ("--> %s\n", B); break; case '2': printf ("string: "); gets (B); i = strlen (B); if (!i) break; B[i] = '\n'; B[i+1] = '\0'; if (write_socket (B)) return (-1); break; default: return (close (fd)); break; } } } /*----------------------*/ int read_socket (b, n) char *b; int *n; { int ready, nfd; ready = 1 << fd; nfd = select (20, &ready, (int *)0, (int *)0, &ts); if (ready && nfd > 0) { *n = read (fd, b, 2048); if (*n > 0) b[*n] = '\0'; } return (0); } /*----------------------*/ int write_socket (b) char *b; { int ready; ready = 1 << fd; select (20, (int *)0, &ready, (int *)0, &ts); write (fd, b, strlen (b)); return (0); }