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
LVL 33
hongjunAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

rstaveleyCommented:
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.
0
hongjunAuthor Commented:
dup2 has got only 2 parameters right?
0
rstaveleyCommented:
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 :-)
0
Cloud Class® Course: Certified Penetration Testing

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

hongjunAuthor Commented:
the above works if without the fgets
0
rstaveleyCommented:
fgets needs stdin to be working and the mis-use of dup2 is probably what's screwing up stdin.
0
hongjunAuthor Commented:
I suspect that as well.
Are you able to give some clue to get it to work?
0
rstaveleyCommented:
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.
0
rstaveleyCommented:
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.
0
rstaveleyCommented:
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<--------
0
hongjunAuthor Commented:
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
0
hongjunAuthor Commented:
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
0
rstaveleyCommented:
Remember to get rid of the trailing '\n' in the parameter buffers. fgets also gets the newline character.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
rstaveleyCommented:
char *cptr;

        fgets(parm1,19,stdin);
        if (cptr = strchr(parm1,'\n')) /* Find the new line character */
                *cptr = '\0'; /* Remove it */
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Linux OS Dev

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.