1

Context: I'm building a UNIX shell, and am currently implementing pipes.

Goal: calls separated by pipes pass output from one to another, only final output is to be printed.

Symptom: the last process continues to output into the pipe, thus I can see nothing and have no clue as to if it executed correctly, received the previous process's output as input etc.

Diagnosing whether I can switch output between the pipe and the console at will: I simply create the pipe, direct it into it and then back to the console, before I proceed to code that precedes the execvp() call (i.e. it should anyway be printed) to see if it's back on the terminal.

Code I tested:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "errno.h"
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <signal.h>

//all the #includes I've got in the original project

int main(int argc, char* argv[])
{
    int fp[2];
    pipe(fp);

    int saved_fd_0, saved_fd_1;

    saved_fd_0 = dup2(fp[0], 0);
    saved_fd_1 = dup2(fp[1], 1);
    dup2(saved_fd_1, 1);
    dup2(saved_fd_0, 0);
    close(fp[0]);
    close(fp[1]);

    printf("output is at terminal");
}

I chose this sequence based on this answer but it fails to print anything past this piece of code. Unfortunately similar questions I have found typically come down to an fflush() call or aren't concerned with restoring output to the terminal (i.e. I didn't just ask without doing any research).

Many thanks in advance.

I am testing with ls | wc as input.

Community
  • 1
  • 1
user3079666
  • 1,159
  • 10
  • 23
  • Please show us your code. It's hard to see what went wrong without seeing your code. – fuz Nov 29 '15 at 21:15
  • The fault is in the code I wrote in the question, all else functions as expected. There is no other pipe/IO -related code in the project (other than the pipe(function and the integer declarations)). – user3079666 Nov 29 '15 at 21:16
  • By *"the last process continues to output into the pipe"* you mean the first process in `ls | wc`? – Kenney Nov 29 '15 at 21:16
  • I mean the `wc` process. To avoid any dependency on the code around the `execs` I just run the code that sets the output to the pipes and back to the terminal without anything else in between, so I can simply see if output is back on the terminal. – user3079666 Nov 29 '15 at 21:20
  • @user3079666 No, it isn't. Please show us the rest of your code, or, even better, make a [mcve] so we can understand your issue by observing it on our own computers. – fuz Nov 29 '15 at 21:25
  • @FUZxxl, Give me 5 minutes, though I believe you will see that the example will still be mostly this block. – user3079666 Nov 29 '15 at 21:27
  • @FUZxxl placed full code (didn't bother to remove any #includes not needed), note that the PIPES macro I didn't explain earlier was just an if() statement. The program should output to the terminal if the output is properly reset to the terminal (which it isn't on my machine) – user3079666 Nov 29 '15 at 21:36
  • @user3079666 Read the manual of `dup2()` again. It doesn't return what you think it does and `saved_fd_0` will just be 0 again. `dup2()` doesn't save the duped over file descriptor, you have to do that on your own (with a call to `dup()` or such). – fuz Nov 29 '15 at 21:37
  • @FUZxxl, You have a very good point, I was mislead to believe I'd get the old descriptor, though I must say that it is more logical than returning the new one, as that one is readily available in not one, but two variables (lest I be once more deceived by [this page](http://man7.org/linux/man-pages/man2/dup.2.html)). For the sake of it though (call me vain, but it's just who I am), do you agree that the problem did not reside in any other code than the one original cited? – user3079666 Nov 29 '15 at 21:46
  • @user3079666 Now I do, but I wasn't able to understand your problem completely without seeing the [mcve]. Especially the bit where you made a pipe was missing to me. “the old descriptor” doesn't exist anymore, it's duplicated over. What do you think that should be? – fuz Nov 29 '15 at 21:49
  • @FUZxxl, yeah I got it later on, should have put the whole thing from the start. When you ask what I think that should be, what are you referring to? The return value? – user3079666 Nov 29 '15 at 22:16
  • @user3079666 You said you expected to get “the old descriptor.” What do you expect “the old descriptor to be?” – fuz Nov 30 '15 at 08:43
  • @FUZxxl Since before the redirection to the pipe I was printing to the terminal, I expected the old descriptor to point to the terminal. I also think it's more intuitive since the old file descriptor is lost, while there are already two references to the new one that are directly accessible, so returning the former file descriptor would probably be more useful (in my opinion). – user3079666 Nov 30 '15 at 09:01
  • @user3079666 The purpose of `dup2()` is to duplicate over a file-descriptor to make two file descriptors refer to the same file description. If `dup2()` would give you a copy of the duplicated-over file descriptor, every use of `dup2()` would leak a file descriptor. Thus it doesn't do that. You need to manually duplicate the to-be-duplicated-over file descriptor if you want to retain it. – fuz Nov 30 '15 at 09:37
  • I am not entirely sure about how this would be done... My best guess is `dup2(1, saved_fd_1)` to store the old descriptor, but I still don't see any output.. – user3079666 Nov 30 '15 at 10:22

1 Answers1

-2

U did search alright, above code barely does anything useful. Sounds like coll. project, so here are a few hints

  1. multiple pipes can appear on a cmdline

  2. pipes is all you need to make it work (diagrams can help)

sanoj
  • 61
  • 2
  • 6
  • Please spell. Also, I don't see how your answer answers the question. – fuz Nov 30 '15 at 08:43
  • The above code is unit test of sorts, it is meant to specifically check if I can restore output to the terminal after directing it into a pipe. – user3079666 Nov 30 '15 at 09:03