Pipe

hongjun
hongjun used Ask the Experts™
on
Why this won't work?

#include <stdio.h>

char c[3][15] ={"/bin/ls", "usr/bin/wc", "/usr/bin/wc"};

int main()
{
      int i, j;
      int thisin;
      int pid[2];
      char temp[10];
      
      while ( 1 ) {
                                fflush(stdin);
            fgets(temp, 9, stdin);
            thisin = fileno(stdin);
            for (i=0; i<=2; i++ ) {
                  pipe(pid);
                  if ( fork() == 0 ) {
                        dup2(thisin, fileno, stdin);
                        if ( i != 2 )
                              dup2(pid[1], fileno(stdout));
                        close(pid[0]);
                        close(pid[1]);
                        execlp(c[i], c[i], NULL);
                  }
                  else {
                        dup2(pid[0], thisin);
                        close(pid[1]);
                        close(pid[0]);
                  }
            }
      }
      
      return 0;
}


Basically I want to have a simple program that will do piping. Now I have hardcoded the commands for piping (in c[][]). How then when I tried to have a fgets command in the loop, it just seems to overflow without waiting for fgets to execute.


hongjun
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Include unistd.h header for starters and that will point out that...

>    dup2(thisin, fileno, stdin);

...is very wrong.

NB: the fileno parameter is going to get the address of the function pointer.
dup2 has got only 2 parameters right?
Possile doing a man on dup2 is what you really need to do.

dup2 closes the first file descriptor and duplicates the second passing the descriptor to the first. The man page says that better than me though :-)
Starting with Angular 5

Learn the essential features and functions of the popular JavaScript framework for building mobile, desktop and web applications.

the above works if without the fgets
fgets needs stdin to be working and the mis-use of dup2 is probably what's screwing up stdin.
I suspect that as well.
Are you able to give some clue to get it to work?
OK, so you're using pipe to give yourself a pipe to read and write.

When you fork, you want one process to close stdout and replace stdin with the pipe reader and you want the other process to close stdin and replace stdout with the pipe writer.

If, however, you close stdin in a process, you can't expect to fgets from stdin in that process.

If you start be includig unistd.h and report your code with comments explaining what you are trying to achieve with each close and dup2, you'll probably debug your own code.
Sorry I can't be more helpful. I've made the mistake of working from home, which my wife took as an invitaton to go out shopping, leaving me with the kids... it's mayhem here.
Back from chaos...

I don't really quite understand what you're trying to achieve, but this may be helpful to nudge you in the right direction. The following code creates a pipe, forks, has the child close the pipe writer and dup2 the reader into STDIN and execls the word counter, has the parent close the pipe reader and dup2 the writer into STDOUT and then outputs some text with fputs....

--------8<--------
#include <stdio.h>
#include <unistd.h>

int main()
{
enum {READ,WRITE};
int p[2];

        pipe(p); /* Create a pipe */
        if (fork() != 0) {
                char cmd[] = "/usr/bin/wc"; /* Child spawns word counter */
                close(p[WRITE]); /* Child only reading from the pipe */
                dup2(p[READ],STDIN_FILENO); /* Make child's STDIN read from the pipe */
                execlp(cmd,cmd,NULL); /* Let's count the words on STDIN */
        }
        else {
                close(p[READ]); /* Parent only writing to the pipe */
                dup2(p[WRITE],STDOUT_FILENO); /* Make STDOUT write to the pipe */
                fputs("She sells sea shells on the sea shore\n",stdout); /* Here's the output */
        }
        return 0;
}
--------8<--------
OK perhaps i need an example on like i type this as input

char parm1[20]";
char parm2[20]";
char parm3[20]";

while ( 1 ) {
    fgets(parm1, 19, stdin);  /* i type this /ls */
    fgets(parm2, 19, stdin);  /* i type this /usr/bin/wc */
    fgets(parm3, 19, stdin);  /* i type this /usr/bin/wc */

    /* do the pipe here */
    /* expected to be something like this parm1 | parm2 | parm3 */
}


I know the above will end up with endless loop with while (1) but ignore it because I will end the program using Ctrl-C. I am only concerned with the pipe code. My present code seem to be "corrupting" stdin.


Thanks a million

hongjun
OK perhaps i need an example on like i type this as input

char parm1[20]";
char parm2[20]";
char parm3[20]";

while ( 1 ) {
    fgets(parm1, 19, stdin);  /* i type this /ls */
    fgets(parm2, 19, stdin);  /* i type this /usr/bin/wc */
    fgets(parm3, 19, stdin);  /* i type this /usr/bin/wc */

    /* do the pipe here */
    /* expected to be something like this parm1 | parm2 | parm3 */
}


I know the above will end up with endless loop with while (1) but ignore it because I will end the program using Ctrl-C. I am only concerned with the pipe code. My present code seem to be "corrupting" stdin.


Thanks a million

hongjun
Remember to get rid of the trailing '\n' in the parameter buffers. fgets also gets the newline character.
char *cptr;

        fgets(parm1,19,stdin);
        if (cptr = strchr(parm1,'\n')) /* Find the new line character */
                *cptr = '\0'; /* Remove it */

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial