Link to home
Start Free TrialLog in
Avatar of hongjun
hongjunFlag for Singapore

asked on

Pipe

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
Avatar of rstaveley
rstaveley
Flag of United Kingdom of Great Britain and Northern Ireland image

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.
Avatar of hongjun

ASKER

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 :-)
Avatar of hongjun

ASKER

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.
Avatar of hongjun

ASKER

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<--------
Avatar of hongjun

ASKER

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
Avatar of hongjun

ASKER

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
ASKER CERTIFIED SOLUTION
Avatar of rstaveley
rstaveley
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
char *cptr;

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