glibc "login_tty()" 函数的代码解释: "open(ttyname)" 紧接着 "close()"

code explanation for glibc "login_tty()" function: "open(ttyname)" immediately followed by "close()"

我正在阅读 glibc 代码,特别是 login_tty 函数,我发现了一段对我来说意义不大的代码:

newfd = open (fdname, O_RDWR);
(void) close (newfd);

这个打开一个文件马上就关闭了,我想知道为什么

complete function code:

int
login_tty (int fd)
{
        (void) setsid();
#ifdef TIOCSCTTY
        if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1)
                return (-1);
#else
        {
          /* This might work.  */
          char *fdname = ttyname (fd);
          int newfd;
          if (fdname)
            {
              if (fd != 0)
                (void) close (0);
              if (fd != 1)
                (void) close (1);
              if (fd != 2)
                (void) close (2);
              newfd = open (fdname, O_RDWR);
              (void) close (newfd);
            }
        }
#endif
        while (dup2(fd, 0) == -1 && errno == EBUSY)
          ;
        while (dup2(fd, 1) == -1 && errno == EBUSY)
          ;
        while (dup2(fd, 2) == -1 && errno == EBUSY)
          ;
        if (fd > 2)
                (void) close(fd);
        return (0);
}

我无法给出明确的答案,但它以某种方式试图使与 fd 关联的终端成为进程的 控制终端

如果您查看代码的第一个替代方案,它使用 ioctlTIOCSCTTY。这一个记录为“使给定终端成为调用进程的控制终端。[...]”,例如参见this manpage

您不理解的代码位于 TIOCSCTTY ioctl 不可用时使用的替代部分。我只能猜测,在关闭所有标准文件描述符(02)之后,打开一个 tty 文件可能会产生 副作用 控制终端。

根据 APUE(2005 年第 2 版)第 9.6 节 - 控制终端:

POSIX.1 leaves the choice of the mechanism used to allocate a controlling terminal up to each individual implementation. We’ll show the actual steps in Section 19.4.

Systems derived from UNIX System V allocate the controlling terminal for a session when the session leader opens the first terminal device that is not already associated with a session. This assumes that the call to open by the session leader does not specify the O_NOCTTY flag (Section 3.3).

BSD-based systems allocate the controlling terminal for a session when the session leader calls ioctl with a request argument of TIOCSCTTY (the third argument is a null pointer). The session cannot already have a controlling terminal for this call to succeed. (Normally, this call to ioctl follows a call to setsid, which guarantees that the process is a session leader without a controlling terminal.) The POSIX.1 O_NOCTTY flag to open is not used by BSD-based systems, except in compatibility-mode support for other systems.