Solved

Pipe

Posted on 2003-10-24
13
713 Views
Last Modified: 2010-04-22
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
0
Comment
Question by:hongjun
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 5
13 Comments
 
LVL 17

Expert Comment

by:rstaveley
ID: 9613654
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
 
LVL 33

Author Comment

by:hongjun
ID: 9613665
dup2 has got only 2 parameters right?
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 9613667
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 33

Author Comment

by:hongjun
ID: 9613674
the above works if without the fgets
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 9613694
fgets needs stdin to be working and the mis-use of dup2 is probably what's screwing up stdin.
0
 
LVL 33

Author Comment

by:hongjun
ID: 9613705
I suspect that as well.
Are you able to give some clue to get it to work?
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 9613748
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
 
LVL 17

Expert Comment

by:rstaveley
ID: 9613761
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
 
LVL 17

Expert Comment

by:rstaveley
ID: 9615927
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
 
LVL 33

Author Comment

by:hongjun
ID: 9616053
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
 
LVL 33

Author Comment

by:hongjun
ID: 9616072
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
 
LVL 17

Accepted Solution

by:
rstaveley earned 500 total points
ID: 9616428
Remember to get rid of the trailing '\n' in the parameter buffers. fgets also gets the newline character.
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 9616443
char *cptr;

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

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Have you ever been frustrated by having to click seven times in order to retrieve a small bit of information from the web, always the same seven clicks, scrolling down and down until you reach your target? When you know the benefits of the command l…
The purpose of this article is to demonstrate how we can upgrade Python from version 2.7.6 to Python 2.7.10 on the Linux Mint operating system. I am using an Oracle Virtual Box where I have installed Linux Mint operating system version 17.2. Once yo…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

749 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question