[net.unix-wizards] Why doesn't this work

dale@mddc.UUCP (Dale Anglin) (07/17/84)

[]

I have a need to read the "who" list into a program buffer.  I wrote a test
program to verify that it would work.  The output of the following program
is as expected except that the program seems to hang up in the "read" call.

CRT dialog...
% cc tst.c -o tst
% tst
about to read who
chris    ttyj5   Jul 17 08:15
dale     ttyj3   Jul 17 08:31

... at this point, "tst" does not return to the shell.  It can be ^Z'd and
^C'd, but does not terminate as expected.
file tst.c cut here -----------------------------------------------
/*
 *-- Why doesn't this work ???
 *
 *	Program is supposed to execute and read the "who" processor output
 */

main()
{
	int	pipefd[2];
	int	pid;
	int	chkpid;
	char	buffer[100];


	pipe(pipefd);

	switch(pid=fork())
	{
	case -1:				/* error */
	    printf("could not fork\n");
	    exit(0);

	case 0:					/* child */
	    close(1);
	    dup(pipefd[1]);
	    printf("about to exec who\n");
	    execlp("/bin/who", "who", (char*)0);
	    printf("could not execute\n");
	    exit(0);

	default:				/* parent */
	    close(0);
	    dup(pipefd[0]);

	    printf("about to read who\n");
	    while (read(0,buffer,1) == 1)
	    {
		putchar(buffer[0]);
	    }

	    printf("after who output\n");
	    while ((chkpid = wait(0)) != pid && chkpid > 0) /* null */;
	}

	printf("about to exit\n");

	exit(0);
}
end of file tst.c cut here ----------------------------------------

I was hoping the "read" statement would EOF on the pipe.

Any ideas ?   Thanks in advance.

Dale Anglin
Management Decisions Development Corp.
7209 Dixie Highway
Fairfield, Ohio   45014
(513) 874-6464

...{ucbvax,decvax,inhp4,mhuxi}!cbosgd!mddc!dale			(uucp)

brad@bradley.UUCP (07/18/84)

#R:mddc:-34200:bradley:400006:000:1348
bradley!brad    Jul 18 08:40:00 1984

Below is the mod's I made to the program, the reason it didn't work
was that you had dup'ed a file descr. This now leaves two file descr.
going to the same place. When you forked you needed to close them after
the dupes. I am not sure you need to close both sides but I generally
do just to be safe.

Bradley Smith			{ihnp4,cepu,uiucdcs,noao}!bradley!brad
Bradley University
Text Processing
----------------------- 1,.d here --------------------------------
/*
 *-- Why doesn't this work ???
 *
 *	Program is supposed to execute and read the "who" processor output
 */

main()
{
	int	pipefd[2];
	int	pid;
	int	chkpid;
	char	buffer[100];


	pipe(pipefd);

	switch(pid=fork())
	{
	case -1:				/* error */
	    printf("could not fork\n");
	    exit(0);

	case 0:					/* child */
	    close(1);
	    close(pipefd[0]);
	    dup(pipefd[1]);
	    close(pipefd[1]);
	    printf("about to exec who\n");
	    execl("/bin/who", "who", (char*)0);
	    printf("could not execute\n");
	    exit(0);

	default:				/* parent */
	    close(0);
	    close(pipefd[1]);
	    dup(pipefd[0]);
	    close(pipefd[0]);

	    printf("about to read who\n");
	    while (read(0,buffer,1) == 1)
	    {
		putchar(buffer[0]);
	    }

	    printf("after who output\n");
	    while ((chkpid = wait(0)) != pid && chkpid > 0) /* null */;
	}

	printf("about to exit\n");

	exit(0);
}

toby@gargoyle.UChicago.UUCP (Toby Harness) (07/18/84)

(sorry, but I can`t seem to reply)

Well, you didn`t close the 'unused' sides of the pipe.

	pipe(pipefd);

	switch(pid=fork())
	...
	case 0:					/* child */
========>   close(pipefd[0]);	/* not necessary, just good practice */
	    close(1);
	    dup(pipefd[1]);
	    printf("about to exec who\n"); 
	    execlp("/bin/who", "who", (char*)0);
	    printf("could not execute\n");
	    exit(0);

	default:				/* parent */
========>   close (pipefd[1]);	/* necessary */
	    close(0);
	    dup(pipefd[0]);
	...

Toby Harness		Ogburn/Stouffer Center, University of Chicago
			...ihnp4!gargoyle!toby

steiny@scc.UUCP (Don Steiny) (07/19/84)

****

	When a program is reading from a pipe it does not read an EOF
until the write end of the pipe is closed.  

	When one forks a process, closes standard output and makes
file descriptor 1 the write end of the pipe, file discriptor
1 is sill open in the parent.   The problem program keeps writing to
1 in the parent, so 1 is never closed, the read inside the fork
never reads an EOF and the program hangs.  The following modifications
will make it work:

diff tst.c new.c
---------------------------------


5a6
> # include <stdio.h>
26c27,29
< 	    printf("about to exec who\n");
---
> 	    close(0);
> 	    close(pipefd[0]);
> 	    fprintf(stderr,"about to exec who\n");
28c31
< 	    printf("could not execute\n");
---
> 	    fprintf(stderr,"could not execute\n");
33a37,38
> 	    close(1);
> 	    close(pipefd[1]);
34a40
> 
38c44
< 		putchar(buffer[0]);
---
> 		putc(buffer[0],stderr);


-------------------------


				Don Steiny
				Personetics
				109 Torrey Pine Terr.
				Santa Cruz, Calif. 95060
				(408) 425-0382
				ucbvax!hplabs!pesnta!scc!steiny
				harpo!fortune!idsvax!scc!steiny