Various programs that deal with namespaces will use pty devices that exist in another namespace. One obvious candiate are containers. So far ttyname() was incorrectly handling this case because the pts device stems from the host and thus cannot be found amongst the current namespace's /dev/pts/<n> entries. Serge Hallyn and I recently upstreamed patches to glibc that allow ttyname{_r}() to correctly handle this case. At a minimum, ttyname{_r}() will set errno to ENODEV in case it finds that the /dev/pts/<n> device that the symlink points to exists in another namespace. This commit will allow screen to handle this case and behave correctly in a container.
Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- src/screen.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/screen.c b/src/screen.c index e47b76e..6d06cf1 100644 --- a/src/screen.c +++ b/src/screen.c @@ -646,18 +646,26 @@ int main(int argc, char **argv) #define SET_TTYNAME(fatal) do \ { \ + int saved_errno = 0; \ + errno = 0; \ if (!(attach_tty = ttyname(0))) \ { \ - if (fatal) \ + /* stdin is a tty but it exists in another namespace. */ \ + if (fatal && errno == ENODEV) \ + attach_tty = ""; \ + else if (fatal) \ Panic(0, "Must be connected to a terminal."); \ else \ attach_tty = ""; \ } \ else \ { \ + saved_errno = errno; \ if (stat(attach_tty, &st)) \ Panic(errno, "Cannot access '%s'", attach_tty); \ - if (CheckTtyname(attach_tty)) \ + /* Only call CheckTtyname() if the device does not exist in another \ + * namespace. */ \ + if (saved_errno != ENODEV && CheckTtyname(attach_tty)) \ Panic(0, "Bad tty '%s'", attach_tty); \ } \ if (strlen(attach_tty) >= MAXPATHLEN) \ -- 2.11.0