在APUE 3E的85便士上,如何实现“./a.out 0< /dev/tty”这样的重定向

nwwlzxa7  于 2022-10-17  发布在  Unix
关注(0)|答案(1)|浏览(180)

我正在阅读APUE(Unix环境中的高级编程)3E。
下面有一个示例代码来解释fcntl()是如何工作的。
(我更改了包含的一些标题和部分代码,使其独立于本书的库。并且为了使代码只依赖于标准库。)


# 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);
}

在基于这段代码生成二进制文件之后,本书(85页)给出了一些示例,以给定的文件描述符为参数来测试文件状态标志。其中一个就像是追随。

$ ./a.out 0 < /dev/tty

它的结果是

read only

但我对上面的重定向操作符感到好奇的地方是:0被作为程序的单个命令参数给出,并且它只使用argv[1],而不使用其他任何参数。
那么,重定向后的/dev/tty如何下发给程序?
上面命令行中的/dev/tty是否覆盖了参数0或其他什么?

pjngdqdw

pjngdqdw1#

如何将重定向的/dev/tty传递到程序?
不是的。</dev/tty不是作为参数传递的;它们告诉外壳程序重定向子进程的stdin(Fd0)。
该外壳的功能类似于

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 );
}

相关问题