具有第二个参数的 dup2() POSIX 函数的含义等于零

Meaning of dup2() POSIX function with second argument equals Zero

有时我会看到 dup2() 函数的奇怪用法。例如:

    if ((sock= accept(sockfd, (struct sockaddr *)&s_addr, &namelen)) == -1){
                syslog(LOG_ERR, "in accept: %m");
                exit(3);

    }
            dup2(sock, 0);
            close(sockfd);
            sock = 0;

它甚至不检查 return 值。它对这些论点到底有什么作用? man dup2 表示如果 newfd (second argument of dup2) was previously open, it is silently closed before being reused. 但 0 是标准输入,为什么我们还需要这样做?

这实际上是一种相当常见的范例,用于将程序配置为在作为标准输入的套接字上运行。

它本身似乎毫无意义——为什么不直接对套接字描述符进行操作呢? - 但在实践中,它几乎总是跟着一个 fork() 操作,该操作运行一些期望从标准输入读取的子进程。

Poof - 现在它可以与套接字一起使用。

您可能会看到以类似方式操作的标准输出。

编辑:一个超级简单的例子是在您接受 TCP 连接后为您提供 shell 的网络服务:

    ...
    if ((sock= accept(sockfd, (struct sockaddr *)&s_addr, &namelen)) == -1){
        syslog(LOG_ERR, "in accept: %m");
        exit(3);
    }
    dup2(sock, 0); // stdin
    dup2(sock, 1); // stdout
    dup2(sock, 2); // stderr
    close(sock);

    system("/bin/sh");  // terrible security

所以现在当您连接到它时 - 也许使用来自客户端的 telnet - 您有一个 shell 似乎是传统的 stdin/out/err,所有连接到套接字。

重点是您看到这主要仅在必须执行某些 子进程 时使用,它假设文件描述符 0/1/2 以某种方式设置.

注意:这是一个糟糕的想法,高度 不安全,你唯一一次真正看到它是在恶意软件中。我犹豫要不要在此处包含该示例,但它是如此清晰的说明,我认为它值得。