1

I am working on a school project, and though it's not required, I want to implement this functionality. With that said, I can't share code, but I think it's irrelevant in this case.

When using fork(), my understanding is that the child process created inherits stdin and stdout, as the child inherits all the file streams from the parent.

My shell requires background capability, and while it technically already has that, if the "background" program runs, it still receives all the data from stdin and continues output to the screen which is just a jumbled mess. For the record, my instructor's compiled sample shell does the same thing, but I don't want that to happen!

I'm pretty certain I should be using a combination of pipe(), fork(), and dup2(), but I can't put it all together. I understand fork, but I don't understand how pipe or dup2 works and how I should implement it in the shell. I'm thinking something along these lines:

thePipe[2] = pipe();
pid = fork();
close stdin/out on child somehow if backgrounded

But I don't understand the functionality of pipe() or dup2() so I'm stuck.

Thanks!

Christopher Schneider
  • 3,745
  • 2
  • 24
  • 38
  • 1
    possible duplicate of [Implementing pipelining in c. What would be the best way to do that? (Own linux shell)](http://stackoverflow.com/questions/13331139/implementing-pipelining-in-c-what-would-be-the-best-way-to-do-that-own-linux) – John Zwinck Sep 08 '14 at 03:26
  • 1
    If I'm understanding correctly, you will probably want to do something with the terminal (termcap or terminfo?) if possible to tell it to generate SIGTTIN and or SIGTTOU [job control signals](http://www.gnu.org/software/libc/manual/html_node/Job-Control-Signals.html). It has been while since I looked into this, so I can't provide an actual answer unfortunately. –  Sep 08 '14 at 03:50
  • Read [Advanced Linux Programming](http://advancedlinuxprogramming.com/); it explains quite well how to use [pipe(7)](http://man7.org/linux/man-pages/man7/pipe.7.html)-s – Basile Starynkevitch Sep 08 '14 at 04:14
  • 1
    Shells always work this way, background processes continue to write to stdin and stdout just like foreground processes do. Inhibiting this across the board would not be desirable behavior in a shell. What you want is either (1) a program that doesn't write to any standard streams; or (2) to redirect your background program's standard streams when you run it. – Crowman Sep 08 '14 at 04:14
  • Refer *man 2 pipe* and *man 2 dup* to get better understanding on unnamed pipe and dup. If you want to understand named pipe then you can also refer *man 2 mknod*. – Adarsh Sep 08 '14 at 04:21
  • Man pages are rather cryptic, which was why I asked. They are tantamount to reading legal documents, and while I've gotten better at reading them, I still miss the meaning. Duskwuff's answer seems to be what I want to do. – Christopher Schneider Sep 26 '14 at 23:22

1 Answers1

2

You don't want pipes here. Processes run in an interactive shell should share their standard file descriptors with the shell — doing otherwise would break a lot more things (including the child processes' ability to determine they're running interactively, and to interact with the tty to handle things like window size changes). It'd also seriously complicate pipelines. Don't do it.

The missing piece here is process groups, which are described in the "General Terminal Interface" section of the Open Group UNIX specs. In brief, the kernel can be made to explicitly recognize a "foreground process group" for the terminal. If a process that isn't in this group tries to read from or write to the terminal, it is automatically stopped.

A brief walkthrough of what is necessary to make a properly functioning shell is available as part of the GNU libc manual, under "Implementing a Job Control Shell". Try following their instructions and see how that goes.

  • Thanks very much. This is now another one of those things that I ran out of time to follow up on since the project was complete and now we've got another one assigned. I'll revise our shell sometime in the near future. Now that the project is finished and the deadline passed, I have made the code public: https://github.com/ccs19/sysnet1p1 – Christopher Schneider Sep 26 '14 at 23:23