From 23636137a4047460c448493bba811cb2e0d854ce Mon Sep 17 00:00:00 2001 From: Peter Avalos Date: Sun, 15 Mar 2009 16:56:50 -1000 Subject: [PATCH] Sync ttyname with FreeBSD: * 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 | 2 +- lib/libc/gen/ttyname.3 | 51 ++++---- lib/libc/gen/ttyname.c | 179 ++++++--------------------- lib/libc_r/uthread/pthread_private.h | 2 - 4 files changed, 69 insertions(+), 165 deletions(-) diff --git a/include/unistd.h b/include/unistd.h index c2c308f685..83f2b8cd3b 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -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); diff --git a/lib/libc/gen/ttyname.3 b/lib/libc/gen/ttyname.3 index 91402f5c57..c1ce33c02b 100644 --- a/lib/libc/gen/ttyname.3 +++ b/lib/libc/gen/ttyname.3 @@ -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 . diff --git a/lib/libc/gen/ttyname.c b/lib/libc/gen/ttyname.c index 469e48c916..3748831697 100644 --- a/lib/libc/gen/ttyname.c +++ b/lib/libc/gen/ttyname.c @@ -10,10 +10,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,10 +26,9 @@ * 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" @@ -41,173 +36,75 @@ #include #include #include -#include #include #include #include #include #include - -#include +#include +#include "reentrant.h" #include "un-namespace.h" -#include #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); } diff --git a/lib/libc_r/uthread/pthread_private.h b/lib/libc_r/uthread/pthread_private.h index ceae8bab1c..1b89dc094e 100644 --- a/lib/libc_r/uthread/pthread_private.h +++ b/lib/libc_r/uthread/pthread_private.h @@ -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); -- 2.41.0