5

I am trying to replace stdin with another pipe, then place the original stdin back to fd #0.

e.g.

dup2(p, 0); // p is a pre-existing fd of a pipe
exec(/* some commands */);

//what will be here in order to have the original stdin back?

scanf(...) //continue processing with original stdin.
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Yi Lin Liu
  • 169
  • 1
  • 11
  • 2
    Simply `dup2()` stdin to a temporary filedescriptor first and `dup2()` it back again later – Ctx Dec 25 '18 at 18:49
  • @Ctx Is it possible to keep stdin without temporary duplicate it? – Yi Lin Liu Dec 25 '18 at 18:52
  • 1
    Not "keep" it, you could reopen it if it is possible. Depending on what your stdin is, this might be not possible however. – Ctx Dec 25 '18 at 18:53
  • The 'exec..()` commands do not return, unless they failed. So the only reasonable statements after an exec command are: `perror( "exec.. failed" );` followed by `exit( EXIT_FAILURE );` – user3629249 Dec 27 '18 at 17:13

1 Answers1

6

You can't recover the original once it has been overwritten (closed). What you can do is save a copy of it before you overwrite it (which requires planning ahead, of course):

int old_stdin = dup(STDIN_FILENO);

dup2(p, STDIN_FILENO);
close(p);               // Usually correct when you dup to a standard I/O file descriptor.

…code using stdin…

dup2(old_stdin, STDIN_FILENO);
close(old_stdin);       // Probably correct
scanf(…);

However, your code mentions exec(…some commands…); — if that is one of the POSIX execve() family of functions, then you won't reach the scanf() (or the second dup2()) call unless the exec*() call fails.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Without duplicate the stdin to temporary fd, would you be able to reopen stdin? – Yi Lin Liu Dec 25 '18 at 18:56
  • 1
    In general, no. The original standard input might be a pipe, a socket, or some other fancy and ephemeral file type, which cannot be reopened. Plus you don't have a name to (re)open it with. After the `dup2(p, STDIN_FILENO);` operation succeeds, `/dev/stdin` is no help; it yields the file that `p` was opened for, not the original standard input. – Jonathan Leffler Dec 25 '18 at 18:58
  • 1
    Also, while I think about it, note that you may run into problems with buffering of input if you dink with file descriptor while the standard I/O library has some input read from the kernel but not delivered to the application. (Similar problems could occur with outputs too.) – Jonathan Leffler Dec 25 '18 at 20:14