Sync ttyname with FreeBSD:
authorPeter Avalos <pavalos@theshell.com>
Mon, 16 Mar 2009 02:56:50 +0000 (16:56 -1000)
committerPeter Avalos <pavalos@theshell.com>
Tue, 7 Apr 2009 07:10:04 +0000 (21:10 -1000)
* SuS says ttyname_r should return an int, so do that.

* Use devname(3) instead of rolling our own code.

* Simplify the threaded/unthreaded stuff.

include/unistd.h
lib/libc/gen/ttyname.3
lib/libc/gen/ttyname.c
lib/libc_r/uthread/pthread_private.h

index c2c308f..83f2b8c 100644 (file)
@@ -120,7 +120,7 @@ long         sysconf(int);
 pid_t   tcgetpgrp(int);
 int     tcsetpgrp(int, pid_t);
 char   *ttyname(int);
-char   *ttyname_r(int, char *, size_t);
+int    ttyname_r(int, char *, size_t);
 int     unlink(const char *);
 ssize_t         write(int, const void *, size_t);
 
index 91402f5..c1ce33c 100644 (file)
@@ -9,10 +9,6 @@
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
 .\" 4. Neither the name of the University nor the names of its contributors
 .\"    may be used to endorse or promote products derived from this software
 .\"    without specific prior written permission.
@@ -30,7 +26,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)ttyname.3  8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/gen/ttyname.3,v 1.5.2.3 2001/12/14 18:33:51 ru Exp $
+.\" $FreeBSD: src/lib/libc/gen/ttyname.3,v 1.14 2007/01/09 00:27:55 imp Exp $
 .\" $DragonFly: src/lib/libc/gen/ttyname.3,v 1.3 2005/11/19 22:32:53 swildner Exp $
 .\"
 .Dd March 22, 2009
@@ -38,6 +34,7 @@
 .Os
 .Sh NAME
 .Nm ttyname ,
+.Nm ttyname_r ,
 .Nm isatty ,
 .Nm ttyslot
 .Nd get name of associated terminal (tty) from file descriptor
@@ -47,7 +44,7 @@
 .In unistd.h
 .Ft char *
 .Fn ttyname "int fd"
-.Ft char *
+.Ft int
 .Fn ttyname_r "int fd" "char *buf" "size_t len"
 .Ft int
 .Fn isatty "int fd"
@@ -62,7 +59,7 @@ These descriptors are not related to the standard
 typedef, but refer to the special device files found in
 .Pa /dev
 and named
-.Pa /dev/tty Ns Em xx
+.Pa /dev/tty Ns Ar xx
 and for which an entry exists
 in the initialization file
 .Pa /etc/ttys .
@@ -86,9 +83,14 @@ a file descriptor for which
 is true.
 .Pp
 The
+.Fn ttyname
+function
+returns the name stored in a static buffer which will be overwritten
+on subsequent calls.
+The
 .Fn ttyname_r
-function is a thread-safe version of
-.Fn ttyname .
+function
+takes a buffer and length as arguments to avoid this problem.
 .Pp
 The
 .Fn ttyslot
@@ -112,6 +114,10 @@ is true; otherwise
 a
 .Dv NULL
 pointer is returned.
+The
+.Fn ttyname_r
+function returns 0 if successful.
+Otherwise an error number is returned.
 .Pp
 The
 .Fn ttyslot
@@ -119,17 +125,18 @@ function
 returns the unit number of the device file if found; otherwise
 the value zero is returned.
 .Sh FILES
-.Bl -tag -width /etc/ttys -compact
+.Bl -tag -width ".Pa /etc/ttys" -compact
 .It Pa /dev/\(**
 .It Pa /etc/ttys
 .El
 .Sh ERRORS
 The
-.Fn ttyname
+.Fn ttyname ,
+.Fn ttyname_r ,
 and
 .Fn isatty
 functions
-may fail if:
+may fail and return the following error codes:
 .Bl -tag -width Er
 .It Bq Er EBADF
 The
@@ -139,24 +146,26 @@ is not a valid open file descriptor.
 The
 .Fa fd
 is not associated with a terminal.
+.It Bq Er ERANGE
+The
+.Fa bufsize
+argument
+is smaller than the length of the string to be returned.
 .El
 .Sh SEE ALSO
 .Xr ioctl 2 ,
 .Xr ttys 5
 .Sh HISTORY
-A
+The
 .Fn isatty ,
 .Fn ttyname ,
 and
 .Fn ttyslot
-function
+functions
 appeared in
 .At v7 .
-.Sh BUGS
 The
-.Fn ttyname
-function leaves its result in an internal static object and returns
-a pointer to that object.
-Subsequent calls to
-.Fn ttyname
-will modify the same object.
+.Fn ttyname_r
+function
+appeared in
+.Fx 6.0 .
index 469e48c..3748831 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libc/gen/ttyname.c,v 1.10.6.2 2002/10/15 19:46:46 fjoe Exp $
- * $DragonFly: src/lib/libc/gen/ttyname.c,v 1.14 2005/11/19 22:32:53 swildner Exp $
- *
  * @(#)ttyname.c       8.2 (Berkeley) 1/27/94
+ * $FreeBSD: src/lib/libc/gen/ttyname.c,v 1.24 2007/01/09 00:27:55 imp Exp $
+ * $DragonFly: src/lib/libc/gen/ttyname.c,v 1.14 2005/11/19 22:32:53 swildner Exp $
  */
 
 #include "namespace.h"
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <dirent.h>
-#include <limits.h>
 #include <stdlib.h>
 #include <termios.h>
 #include <unistd.h>
 #include <string.h>
 #include <paths.h>
-
-#include <pthread.h>
+#include <errno.h>
+#include "reentrant.h"
 #include "un-namespace.h"
 
-#include <db.h>
 #include "libc_private.h"
 
-static char static_buf[TTY_PATH_MAX] = _PATH_DEV;
-static char *oldttyname(int, struct stat *);
-static char *ttyname_threaded(int fd);
-static char *ttyname_unthreaded(int fd);
-extern int  __sys_fstat(int, struct stat *);
+static char ttyname_buf[sizeof(_PATH_DEV) + NAME_MAX];
 
-static pthread_mutex_t ttyname_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_key_t   ttyname_key;
-static int             ttyname_init = 0;
+static once_t          ttyname_init_once = ONCE_INITIALIZER;
+static thread_key_t    ttyname_key;
+static int             ttyname_keycreated = 0;
 
-char *
-ttyname(int fd)
-{
-       char           *ret;
-
-       if (__isthreaded == 0)
-               ret = ttyname_unthreaded(fd);
-       else
-               ret = ttyname_threaded(fd);
-       return (ret);
-}
-
-char *
+int
 ttyname_r(int fd, char *buf, size_t len)
 {
-       struct dirent *dirp;
-       DIR   *dp;
-       struct stat     dsb;
-       struct stat     sb;
-       char           *rval;
-       int             minlen;
+       struct stat     sb;
+       size_t used;
 
-       rval = NULL;
+       *buf = '\0';
 
        /* Must be a terminal. */
        if (!isatty(fd))
-               return (rval);
+               return (ENOTTY);
        /* Must be a character device. */
-       if (__sys_fstat(fd, &sb) || !S_ISCHR(sb.st_mode))
-               return (rval);
+       if (_fstat(fd, &sb) || !S_ISCHR(sb.st_mode))
+               return (ENOTTY);
        /* Must have enough room */
        if (len <= sizeof(_PATH_DEV))
-               return (rval);
+               return (ERANGE);
 
-       if ((dp = opendir(_PATH_DEV)) != NULL) {
-               memcpy(buf, _PATH_DEV, sizeof(_PATH_DEV));
-               for (rval = NULL; (dirp = readdir(dp)) != NULL;) {
-                       if (dirp->d_ino != sb.st_ino)
-                               continue;
-                       minlen = (len - (sizeof(_PATH_DEV) - 1)) < (dirp->d_namlen + 1) ?
-                               (len - (sizeof(_PATH_DEV) - 1)) : (dirp->d_namlen + 1);
-                       memcpy(buf + sizeof(_PATH_DEV) - 1, dirp->d_name, minlen);
-                       if (stat(buf, &dsb) || sb.st_dev != dsb.st_dev ||
-                           sb.st_ino != dsb.st_ino)
-                               continue;
-                       rval = buf;
-                       break;
-               }
-               closedir(dp);
-       }
-       return (rval);
+       strcpy(buf, _PATH_DEV);
+       used = strlen(buf);
+       devname_r(sb.st_rdev, S_IFCHR, buf + used, len - used);
+       return (0);
+}
+
+static void
+ttyname_keycreate(void)
+{
+       ttyname_keycreated = (thr_keycreate(&ttyname_key, free) == 0);
 }
 
 char *
-ttyname_threaded(int fd)
+ttyname(int fd)
 {
        char    *buf;
 
-       if (ttyname_init == 0) {
-               _pthread_mutex_lock(&ttyname_lock);
-               if (ttyname_init == 0) {
-                       if (_pthread_key_create(&ttyname_key, free)) {
-                               _pthread_mutex_unlock(&ttyname_lock);
+       if (thr_main() != 0)
+               buf = ttyname_buf;
+       else {
+               if (thr_once(&ttyname_init_once, ttyname_keycreate) != 0 ||
+                   !ttyname_keycreated)
+                       return (NULL);
+               if ((buf = thr_getspecific(ttyname_key)) == NULL) {
+                       if ((buf = malloc(sizeof ttyname_buf)) == NULL)
                                return (NULL);
-                       }
-                       ttyname_init = 1;
-               }
-               _pthread_mutex_unlock(&ttyname_lock);
-       }
-
-       /* Must have thread specific data field to put data */
-       if ((buf = _pthread_getspecific(ttyname_key)) == NULL) {
-               if ((buf = malloc(TTY_PATH_MAX)) != NULL) {
-                       if (_pthread_setspecific(ttyname_key, buf) != 0) {
+                       if (thr_setspecific(ttyname_key, buf) != 0) {
                                free(buf);
                                return (NULL);
                        }
-               } else {
-                       return (NULL);
-               }
-       }
-       return (ttyname_r(fd, buf, TTY_PATH_MAX));
-}
-
-static char *
-ttyname_unthreaded(int fd)
-{
-       struct stat sb;
-       struct termios ttyb;
-       DB *db;
-       DBT data, key;
-       struct {
-               mode_t type;
-               dev_t dev;
-       } bkey;
-
-       /* Must be a terminal. */
-       if (tcgetattr(fd, &ttyb) < 0)
-               return (NULL);
-       /* Must be a character device. */
-       if (_fstat(fd, &sb) || !S_ISCHR(sb.st_mode))
-               return (NULL);
-
-       if ( (db = dbopen(_PATH_DEVDB, O_RDONLY, 0, DB_HASH, NULL)) ) {
-               memset(&bkey, 0, sizeof(bkey));
-               bkey.type = S_IFCHR;
-               bkey.dev = sb.st_rdev;
-               key.data = &bkey;
-               key.size = sizeof(bkey);
-               if (!(db->get)(db, &key, &data, 0) &&
-                   (sizeof(_PATH_DEV) + data.size - 1 < sizeof(static_buf))) {
-                       bcopy(data.data,
-                           static_buf + sizeof(_PATH_DEV) - 1, data.size);
-                       (db->close)(db);
-                       return (static_buf);
                }
-               (db->close)(db);
        }
-       return (oldttyname(fd, &sb));
-}
-
-static char *
-oldttyname(int fd __unused, struct stat *sb)
-{
-       struct dirent *dirp;
-       DIR *dp;
-       struct stat dsb;
 
-       if ((dp = opendir(_PATH_DEV)) == NULL)
+       if (ttyname_r(fd, buf, sizeof ttyname_buf) != 0)
                return (NULL);
-
-       while ( (dirp = readdir(dp)) ) {
-               if (dirp->d_ino != sb->st_ino)
-                       continue;
-               if (sizeof(_PATH_DEV) + dirp->d_namlen >= sizeof(static_buf))
-                       continue;
-               bcopy(dirp->d_name, static_buf + sizeof(_PATH_DEV) - 1,
-                   dirp->d_namlen + 1);
-               if (stat(static_buf, &dsb) || sb->st_dev != dsb.st_dev ||
-                   sb->st_ino != dsb.st_ino)
-                       continue;
-               closedir(dp);
-               return (static_buf);
-       }
-       closedir(dp);
-       return (NULL);
+       return (buf);
 }
index ceae8ba..1b89dc0 100644 (file)
@@ -1156,8 +1156,6 @@ SCLASS int        _thread_kern_new_state
  */
 __BEGIN_DECLS
 char    *__ttyname_basic(int);
-char    *__ttyname_r_basic(int, char *, size_t);
-char    *ttyname_r(int, char *, size_t);
 void   _cond_wait_backout(pthread_t);
 void   _fd_lock_backout(pthread_t);
 int     _find_thread(pthread_t);