pipe() doesn't seem to work. (Pyramid OSx 4.4) (Summary)

A.V. Raman ARaman at massey.ac.nz
Tue Mar 27 09:41:47 AEST 1990


For the sake of other readers who may be interested, I'm restating the
problem here and posting a summary of the replies I received.

---- Faulty Code begins ----
#include <stdio.h>
setup()
{
   int fd[2];

   if (pipe(fd) < 0) {  /* write to fd[1] and read fd[0] */
      perror("pipe");
      exit(1);
   }
   if (fork() == 0) {   /* set up child to read pipe as stdin */
      close(0);
      dup(fd[0]);
      close(fd[1]);
      execl("/bin/cat","cat","-n",NULL);  /* ucb cat -n to number lines */
      perror("exec");
   } else {            /* set up parent to write to pipe as stdout */
/**/  printf (" ");    /* program fails if this line is removed */
      close(1);
      dup(fd[1]);
      close(fd[0]);
   }
}

main(argc,argv)
char **argv;
{
   FILE *fp;
   char buf [BUFSIZ];
   
   if (argc == 1)
      exit(1);
   setup();			/* setup pipe with cat reading other end */
   if ((fp = fopen(argv[1],"r")) == NULL) {
      perror(argv[1]);
      exit(1);
   }
   while (fgets(buf,BUFSIZ,fp) != NULL)
      printf("%s", buf);        /* write into pipe */
   fclose(fp);
   close(1);
   return 0;
}
---- Code ends ----

Thanks for all the prompt solutions that I received for the problem.
The fault in my program narrows down to my mixing buffered and unbuffered
IO incorrectly.

Reproduced with the permission of Cuong T. Nguyen of Center for Integrated
Systems, Stanford University:

>The problem is with stdio buffering, which can be none, line,
>or block.  When the program is started, stdio is typically fully
>(block) buffered.  When your first printf() is called (actually,
>_flsbuf()), IF stdout is a tty, buffering is set to line.  Otherwise
>it is left alone.  That's why the null print("  ") insertion helps,
>and also why write() doesn't, since it is not part of stdio.
>
>When your printf's are fully buffered, anything left unflushed
>in stdout before the pipes close is lost.  The simplest thing
>to do is an fflush(stdout) at the end.  Else you can do something
>a la setlinebuf() to force the buffering type you like.

- Anand



More information about the Comp.unix.questions mailing list