int main (void) {
int rc=fork();
if(rc==0){
close(1); //close stdout BEFORE opening my file
open("./c.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
//execve "wc"
char *cmd[3];
cmd[0] = strdup("wc"); //file to execuable
cmd[1]=strdup("c.c"); //first arg to command 'wc' -> c.c
cmd[2]=NULL;
execvp(cmd[0], cmd);
}
If I close() stdout, then the output of execve ("wc"), will be in file c.txt
but ONLY if I close stdout BEFORE open()ing. If I call it AFTER
open("./c.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
close(1);
then -> wc: write error: Bad file descriptor
.
I have read, that for open() (probably in my case for wc
output) is OS reaching file descriptor from 0, and so it first find 1
as stdout to printf() to screen. So I need to close() it, in order to use file descriptor from open("./c.txt") for wc
. But If that is correct (I do not know where I have understood it correctly), then it would not matter whether I close stdout before or after open() call, does it? Once it is closed, OS has no other FD to use as output. I maybe does not understand it clearly.
question: why must be fd1 closed first in order to make redirection to c.txt?
A few concepts to establish first.
stdout
is one of the streams automatically opened as part of program startup. The program startup code uses file descriptor 1
for stdout
).execve
creates a new process with the same open file descriptors as the parent/calling process (there are exceptions and naunces which can be read from the execve man page.open
will look for the lowest available file descriptor to use.Ok, so now to your code.
Case 1 - close, open, execve
In this case the following sequence of events happens:
stdout
=>fd 1
.close(1)
makes fd 1
available.open("c.txt")
returns 1
which effectively redirects stdout
to the file.execve
creates a new process which has 1
open and redirected to the file.wc
writes to fd 1
which now ends up in the file.Case 2 - open,close,execve
In this case the following sequence of events happens:
stdout
=>fd 1
.open("c.txt")
is called but fd 1
is not available so it returns 2
.close(1)
means there is now effectively no stdout
.execve
creates a new process which has no open stream on fd 1
(ie no stdout
).wc
tries to write to fd 1
and gets a bad file descriptor
error since fd 1
is not open.