Solved

Pipe

Posted on 2003-10-24
13
712 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
  • 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
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 
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

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

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

The purpose of this article is to fix the unknown display problem in Linux Mint operating system. After installing the OS if you see Display monitor is not recognized then we can install "MESA" utilities to fix this problem or we can install additio…
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…
This Micro Tutorial will give you a basic overview how to record your screen with Microsoft Expression Encoder. This program is still free and open for the public to download. This will be demonstrated using Microsoft Expression Encoder 4.
This Micro Tutorial demonstrates using Microsoft Excel pivot tables, how to reverse engineer competitors' marketing strategies through backlinks.

770 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