I was reading APUE(Advanced Programming in the UNIX Environment) 3e.
And there is an example code to explain how fcntl()
works like below.
(I changed some of the headers included and some parts of code to be independent from this book's library. And in order to have the code to rely only on the standard libraries.)
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int val;
if (argc != 2) {
fprintf(stderr, "usage: %s <descriptor#>\n", argv[0]);
exit(1);
}
if ((val = fcntl(atoi(argv[1]), F_GETFL, 0)) < 0) {
perror("fcntl error for fd");
exit(1);
}
switch (val & O_ACCMODE) {
case O_RDONLY:
printf("read only");
break;
case O_WRONLY:
printf("write only");
break;
case O_RDWR:
printf("read write");
break;
default:
fprintf(stderr, "unknown access mode\n");
//exit(1);
}
if (val & O_APPEND)
printf(", append");
if (val & O_NONBLOCK)
printf(", nonblocking");
if (val & O_SYNC)
printf(", synchronous writes");
#if !defined(_POSIX_C_SOURCE) && defined(O_FSYNC) && (O_FSYNC != O_SYNC)
if (val & O_FSYNC)
printf(", synchronous writes");
#endif
putchar('\n');
exit(0);
}
After making a binary based on this code, the book (85 page) gives some example to test the file status flags, from the given file descriptor as argument. And one of them is like following.
$ ./a.out 0 < /dev/tty
and its result is
read only
But where I got some curiosity about the redirection operator above is: 0
is given
as the single command argument to the program, and it uses only argv[1]
but anything else.
Then, how redirected /dev/tty
could be delivered to the program?
Does /dev/tty
in the command line above overwrite the argument 0
or something?
CodePudding user response:
how redirected
/dev/tty
could be delivered to the program?
It's not. <
and /dev/tty
aren't passed as arguments; they tell the shell to redirect the child's stdin (fd 0).
The shell does something similar to
pid_t pid = fork();
if ( pid == 0 ) {
int for_stdin = open( "/dev/tty", O_RDONLY );
dup2( for_stdin, 0 );
close( for_stdin );
execlp( "./a.out", "0", NULL );
}