ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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.
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.
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.
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
Location: Northeastern Michigan, where Carhartt is a Designer Label
Distribution: Slackware 32- & 64-bit Stable
Posts: 3,541
Rep:
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")):
Create a pipe by calling pipe.
Call fork (both the parent process and the child process have access to the pipe).
Close the standard output in the child.
Duplicate the write side of the pipe by calling dup; it is duplicated on the lowest unused file descriptor (standard output).
The child process execs a program that writes to standard output.
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...
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:
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
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.
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?
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.