diff options
Diffstat (limited to 'login/openpty.c')
-rw-r--r-- | login/openpty.c | 54 |
1 files changed, 37 insertions, 17 deletions
diff --git a/login/openpty.c b/login/openpty.c index c8e4d102c9..941ba039e3 100644 --- a/login/openpty.c +++ b/login/openpty.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998-2016 Free Software Foundation, Inc. +/* Copyright (C) 1998-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998. @@ -92,28 +92,35 @@ openpty (int *amaster, int *aslave, char *name, char _buf[512]; #endif char *buf = _buf; - int master, slave; + int master, ret = -1, slave = -1; + + *buf = '\0'; master = getpt (); if (master == -1) return -1; if (grantpt (master)) - goto fail; + goto on_error; if (unlockpt (master)) - goto fail; - - if (pts_name (master, &buf, sizeof (_buf))) - goto fail; + goto on_error; - slave = open (buf, O_RDWR | O_NOCTTY); +#ifdef TIOCGPTPEER + /* Try to allocate slave fd solely based on master fd first. */ + slave = ioctl (master, TIOCGPTPEER, O_RDWR | O_NOCTTY); +#endif if (slave == -1) { - if (buf != _buf) - free (buf); - - goto fail; + /* Fallback to path-based slave fd allocation in case kernel doesn't + * support TIOCGPTPEER. + */ + if (pts_name (master, &buf, sizeof (_buf))) + goto on_error; + + slave = open (buf, O_RDWR | O_NOCTTY); + if (slave == -1) + goto on_error; } /* XXX Should we ignore errors here? */ @@ -127,14 +134,27 @@ openpty (int *amaster, int *aslave, char *name, *amaster = master; *aslave = slave; if (name != NULL) - strcpy (name, buf); + { + if (*buf == '\0') + if (pts_name (master, &buf, sizeof (_buf))) + goto on_error; + + strcpy (name, buf); + } + + ret = 0; + + on_error: + if (ret == -1) { + close (master); + + if (slave != -1) + close (slave); + } if (buf != _buf) free (buf); - return 0; - fail: - close (master); - return -1; + return ret; } libutil_hidden_def (openpty) |