LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-07-2008, 07:22 PM   #1
gdsoccer
LQ Newbie
 
Registered: May 2008
Location: Ohio
Distribution: Ubuntu 8.04
Posts: 7

Rep: Reputation: 0
Implementing a Pipe


Hey all,

First time here and after a lot of frustration with trying to write a simple shell piping command I decided to try online to see if someone could point me in the right direction.

I don't expect anyone to give me the answer I would just like to know how exactly to reference a pipe() and fork()'ed files output.

Thanks a bunch
 
Old 05-07-2008, 08:05 PM   #2
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,359

Rep: Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751
What lang are you using? You mention shell, but the way you refer to it, sounds more eg C?
PS I've asked the mods to move this to the Prog forum, I think it'd get better exposure there.
 
Old 05-08-2008, 07:48 AM   #3
gdsoccer
LQ Newbie
 
Registered: May 2008
Location: Ohio
Distribution: Ubuntu 8.04
Posts: 7

Original Poster
Rep: Reputation: 0
I apologize, it is written in C.

thanks for the request to move, like I said first time here so I just sorta posted where I knew I would be safe
 
Old 05-08-2008, 07:55 AM   #4
SciYro
Senior Member
 
Registered: Oct 2003
Location: hopefully not here
Distribution: Gentoo
Posts: 2,038

Rep: Reputation: 51
Sorry, but its hard to know exactly what you want, can you be more specific or give examples? From the sound of things, you wanted to use pipes, but then asked about fork/pipe, which are only relevant when trying to spawn a new process and talk to it thru its pipe, but even then, its hard to tell exactly what you want to know about it.
 
Old 05-08-2008, 07:58 AM   #5
XavierP
Moderator
 
Registered: Nov 2002
Location: Kent, England
Distribution: Debian Testing
Posts: 19,192
Blog Entries: 4

Rep: Reputation: 475Reputation: 475Reputation: 475Reputation: 475Reputation: 475
As this is a programming problem I have moved it to the Programming forum where it will be seen by more people.
 
Old 05-08-2008, 08:58 AM   #6
tronayne
Senior Member
 
Registered: Oct 2003
Location: Northeastern Michigan, where Carhartt is a Designer Label
Distribution: Slackware 32- & 64-bit Stable
Posts: 3,541

Rep: Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065
Do you mean something like this?
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <wait.h>
#include <sys/types.h>

int     main    (void)
{
        char    line [BUFSIZ];
        char    *message = "This message comes from the child";
        int     fifo [2];

        if (pipe (fifo) == -1) {
                (void) fprintf (stderr, "cannot create pipe\n");
                exit (errno);
        }
        if (fork () == 0) {     /* child        */
                /*      write message and trailing null to pipe */
                (void) write (fifo [1], message, strlen (message) + 1);
        } else {                /* parent       */
                (void) read (fifo [0], line, 81);
                (void) fprintf (stdout, "Message = %s\n", line);
        }
        exit (EXIT_SUCCESS);
}
 
Old 05-08-2008, 01:18 PM   #7
gdsoccer
LQ Newbie
 
Registered: May 2008
Location: Ohio
Distribution: Ubuntu 8.04
Posts: 7

Original Poster
Rep: Reputation: 0
Yes what I am attempting to do is similar to what you have there tron. I apologize for being vague, being confused as I am it's a bit difficult to explain right off. The goal is to have a simple shell that will implement standard unix piping (i.e. ls | cat will pipe the output of ls into the cat command, not really the most useful example but should be sufficient to prove functionality).

I guess my biggest question is how to get the output of something like ls to be put into the pipe, can you use STDOUT or is there something else.

Thanks in advance, I've used linux for awhile now it's just the first time I've decided to delve into coding parts of it
 
Old 05-08-2008, 02:51 PM   #8
tronayne
Senior Member
 
Registered: Oct 2003
Location: Northeastern Michigan, where Carhartt is a Designer Label
Distribution: Slackware 32- & 64-bit Stable
Posts: 3,541

Rep: Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065
This isn't trivial (and it can be confusing if you're not familiar with the fork, exec and pipe standard library functions). Let me suggest that you see if you can find a copy of Steven G. Kochan and Patrick H. Wood Topics in C Programming (rev. ed.; New York: John Wiley & Sons, Inc., 1981). ISBN 0-471-53404-8 (see
http://www.kochan-wood.com) -- don't be put off by the age, this stuff hasn't changed much, if at all. Chapter 6, about pp. 315-325 explains, with examples, how to implement what you've described (there may be other works that do as good a job, but I'm only familiar with Kochan and Wood).

To allow a program to read from the standard output of another program (like popen (cmd, "r")):
  1. Create a pipe by calling pipe.
  2. Call fork (both the parent process and the child process have access to the pipe).
  3. Close the standard output in the child.
  4. Duplicate the write side of the pipe by calling dup; it is duplicated on the lowest unused file descriptor (standard output).
  5. The child process execs a program that writes to standard output.
  6. The parent process reads from the pipe.
A similar procedure can be followed to write to the standard input of a program (like popen (cmd, "w")) by closing the standard input and then doing the dup.

Here's an example program that demonstrates the above (from Topics):
Code:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>

int     main    (void)
{
        char    line [BUFSIZ];
        int     fifo [2], proc, n;

        (void) pipe (fifo);
        if ((proc = fork ()) == -1) {
                (void) fprintf (stderr, "can't fork\n");
                exit (errno);
        }
        if (proc == 0) {        /* child        */
                /*
                 *      close the standard input and
                 *      dup write end of pipe onto it
                */
                (void) close (1);
                (void) dup (fifo [1]);
                /*      run pwd with standard output attached to pipe   */
                (void) execl ("/bin/pwd", "pwd", NULL);
                /*      execl shouldn't return                          */
                (void) fprintf (stderr, "cannot execl pwd\n");
                exit (errno);
        }
        /*      parent: read from pipe                                  */
        n = read (fifo [0], line, BUFSIZ);
        line [n] = '\0';
        (void) fprintf (stdout, "current directory = %s", line);
        exit (EXIT_SUCCESS);
}
This is a simple demonstration program that does one thing only; to follow the example and build a multi-purpose program by digging into parsing command lines, the exec routines and the like. Again, it's not trivial but after a while the little light bulb will come on...

Hope this helps more than hurts.
 
Old 05-09-2008, 11:29 AM   #9
gdsoccer
LQ Newbie
 
Registered: May 2008
Location: Ohio
Distribution: Ubuntu 8.04
Posts: 7

Original Poster
Rep: Reputation: 0
I think I understand what you are saying. I think the part I was missing was the dup. Makes sense since it uses the lowest available descriptor that it should default to the one I just closed. Then it's just a matter of writing the first functions output to that and then having the parent read that output as it's parameters.

I think I have most of it down I'll link you what I have so far:


This is contained in main()
Code:
while(current != '\0')
{
       if(current == '|')
       {
          shellPipe(buf, i);
          break;
       }
       i++;
       current = buf[i];
}
The following is in shellPipe; index = the i value from main buf is the ls | cat string
Code:
int i, j;
int length = strlen(buf);
char first[];
char second[];
for(i = 0; i < (index - 1); i++)
{
    first[i] = buf[i];    
}
first[i] = '\0';

j = 0;
for(i = index + 2; i < length; i++)
{
    second[j] = buf[i];
    j++;
}
second[j] = '\0';
from here should just be a matter of using something like what you wrote that runs ls and stores the output into stdout for cat to read from. So what I was planning to try once I get out of work was to replace where you did a pwd with whatever the string in first is. Let me know if I messed up logically anywhere

Last edited by gdsoccer; 05-09-2008 at 11:31 AM. Reason: spelling
 
Old 05-09-2008, 06:52 PM   #10
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
FYI, a safer (and most commonly-used) technique than dup() is dup2(). This will close() the file descriptor and dup() it at the same time, thereby preventing any race conditions where a signal would be caught in between the system calls.
 
Old 05-14-2008, 09:54 AM   #11
gdsoccer
LQ Newbie
 
Registered: May 2008
Location: Ohio
Distribution: Ubuntu 8.04
Posts: 7

Original Poster
Rep: Reputation: 0
Hey again,

Been doing some work on this and I think I almost have it done. The one problem I have is that once i do the dup2(fifo[1], 1) my system hangs up and won't proceed to the next command. I think what I need to do is somehow restore that file descriptor after I make the system call. How would I go about doing that. Could I use dup2 again but with different parameters?

Thanks
 
Old 05-14-2008, 10:33 AM   #12
tronayne
Senior Member
 
Registered: Oct 2003
Location: Northeastern Michigan, where Carhartt is a Designer Label
Distribution: Slackware 32- & 64-bit Stable
Posts: 3,541

Rep: Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065
Perhaps a look at the example program at this link would be useful:
http://publib.boulder.ibm.com/iserie.../apis/dup2.htm
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
need help on implementing ssl dianarani Linux - Security 1 07-17-2007 06:00 AM
Implementing IPv6 ??? ajeetraina Linux - Server 0 07-09-2007 10:40 PM
implementing ping in C++ allomeen Linux - Networking 0 05-10-2006 04:47 PM
Implementing mmap Kumar Programming 0 09-08-2005 03:12 AM
Implementing GRsecurity int0x80 Linux - Security 13 09-30-2002 03:31 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:54 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration