summaryrefslogtreecommitdiff
path: root/devel/linuxthreads/files
diff options
context:
space:
mode:
authorTor Egge <tegge@FreeBSD.org>2004-02-27 23:32:55 +0000
committerTor Egge <tegge@FreeBSD.org>2004-02-27 23:32:55 +0000
commitdeaa6380716ba4d8fd444520ae7a7615d5e52cfd (patch)
treebbf2fb8b778f5737bf2acceb3cbc2792f790b1fe /devel/linuxthreads/files
parentInclude string.h when running the test for gimp-print as it needs a proper (diff)
Add option to ignore posix priority scheduling.
Add threadsafe versions of some libc functions on FreeBSD 4.x. Register liblgcc_r_pic.a as installed for FreeBSD 5.x.
Notes
Notes: svn path=/head/; revision=102330
Diffstat (limited to 'devel/linuxthreads/files')
-rw-r--r--devel/linuxthreads/files/README.FreeBSD8
-rw-r--r--devel/linuxthreads/files/getlogin.c113
-rw-r--r--devel/linuxthreads/files/libc_thread.c2
-rw-r--r--devel/linuxthreads/files/patch-aa8
-rw-r--r--devel/linuxthreads/files/strptime.sed9
-rw-r--r--devel/linuxthreads/files/telldir.c182
-rw-r--r--devel/linuxthreads/files/ttyname.c215
7 files changed, 535 insertions, 2 deletions
diff --git a/devel/linuxthreads/files/README.FreeBSD b/devel/linuxthreads/files/README.FreeBSD
index 4a85faf0b40b..d59a697de9d1 100644
--- a/devel/linuxthreads/files/README.FreeBSD
+++ b/devel/linuxthreads/files/README.FreeBSD
@@ -130,3 +130,11 @@ set at 20 + 16 * MAXUSERS.
If other threads has been joined by the main thread before it calls
exit then exit handling should be fairly safe and the correct exit
code can be detected by the parent process.
+
+6) If the rate of sched_yield() calls is very high (due to
+ malloc / spinlock interaction) then
+ LINUXTHREADS_NO_POSIX_PRIORITY_SCHEDULING can be defined when
+ compiling the linuxthreads library. This has the same effect
+ as if the kernel was compiled without the _KPOSIX_PRIORITY_SCHEDULING
+ option, but limited to the linuxthread library.
+
diff --git a/devel/linuxthreads/files/getlogin.c b/devel/linuxthreads/files/getlogin.c
new file mode 100644
index 000000000000..11bf59bab4ec
--- /dev/null
+++ b/devel/linuxthreads/files/getlogin.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libc/gen/getlogin.c,v 1.4.2.1 2001/03/05 09:06:50 obrien Exp $
+ */
+
+#if __FreeBSD__ < 5
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getlogin.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <errno.h>
+#include <pwd.h>
+#include <utmp.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef _THREAD_SAFE
+#define THREAD_LOCK()
+#define THREAD_UNLOCK()
+#else
+#include <pthread.h>
+extern int __isthreaded;
+static pthread_mutex_t logname_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define THREAD_LOCK() if (__isthreaded) pthread_mutex_lock(&logname_mutex)
+#define THREAD_UNLOCK() if (__isthreaded) pthread_mutex_unlock(&logname_mutex)
+#endif /* _THREAD_SAFE */
+
+int _logname_valid; /* known to setlogin() */
+int _getlogin(char *, unsigned int);
+
+static char *
+getlogin_basic(int *status)
+{
+ static char logname[MAXLOGNAME];
+
+ if (_logname_valid == 0) {
+#ifdef __NETBSD_SYSCALLS
+ if (__getlogin(logname, sizeof(logname) - 1) < 0) {
+#else
+ if (_getlogin(logname, sizeof(logname)) < 0) {
+#endif
+ *status = errno;
+ return (NULL);
+ }
+ _logname_valid = 1;
+ }
+ *status = 0;
+ return (*logname ? logname : NULL);
+}
+
+char *
+getlogin(void)
+{
+ char *result;
+ int status;
+
+ THREAD_LOCK();
+ result = getlogin_basic(&status);
+ THREAD_UNLOCK();
+ return (result);
+}
+
+int
+getlogin_r(char *logname, int namelen)
+{
+ char *result;
+ int len;
+ int status;
+
+ THREAD_LOCK();
+ result = getlogin_basic(&status);
+ if (status == 0) {
+ if ((len = strlen(result) + 1) > namelen)
+ status = ERANGE;
+ else
+ strncpy(logname, result, len);
+ }
+ THREAD_UNLOCK();
+ return (status);
+}
+#endif /* __FreeBSD__ < 5 */
diff --git a/devel/linuxthreads/files/libc_thread.c b/devel/linuxthreads/files/libc_thread.c
index ada205fd2858..86db711d9995 100644
--- a/devel/linuxthreads/files/libc_thread.c
+++ b/devel/linuxthreads/files/libc_thread.c
@@ -82,6 +82,7 @@ static void _pthread_initialize(void)
{
#if defined(LINUXTHREADS)
+#if !defined(LINUXTHREADS_NO_POSIX_PRIORITY_SCHEDULING)
int mib[2];
size_t len;
@@ -91,6 +92,7 @@ static void _pthread_initialize(void)
if (-1 == sysctl (mib, 2, &_posix_priority_scheduling, &len, NULL, 0))
_posix_priority_scheduling = 0;
#endif
+#endif
/* This turns on thread safe behaviour in libc when we link with it */
__isthreaded = 1;
diff --git a/devel/linuxthreads/files/patch-aa b/devel/linuxthreads/files/patch-aa
index a805bfcb649f..1eaa73d68cdb 100644
--- a/devel/linuxthreads/files/patch-aa
+++ b/devel/linuxthreads/files/patch-aa
@@ -13,7 +13,7 @@ diff -ru ../../work/linuxthreads-2.2.3/Examples/Makefile ./Examples/Makefile
diff -ru ../../work/linuxthreads-2.2.3/Makefile ./Makefile
--- ../../work/linuxthreads-2.2.3/Makefile Wed Apr 25 21:50:59 2001
+++ ./Makefile Thu Jun 7 23:13:52 2001
-@@ -1,128 +1,122 @@
+@@ -1,128 +1,126 @@
-# Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
-# This file is part of the GNU C Library.
+LIB=lthread
@@ -74,6 +74,10 @@ diff -ru ../../work/linuxthreads-2.2.3/Makefile ./Makefile
+LD=${LINUXTHREADS_WRAP_LD}
+.endif
+
++.if defined(LINUXTHREADS_NO_POSIX_PRIORITY_SCHEDULING)
++CFLAGS += -DLINUXTHREADS_NO_POSIX_PRIORITY_SCHEDULING
++.endif
++
+CFLAGS += -I${LIBSRC_BASE}/libc/${MACHINE_ARCH} -I${.CURDIR}/sysdeps/${MACHINE_ARCH}
+
+# Contents of the library.
@@ -82,7 +86,7 @@ diff -ru ../../work/linuxthreads-2.2.3/Makefile ./Makefile
+ libc_calls.c libc_thread.c manager.c mutex.c pt-machine.c ptfork.c \
+ pthread.c ptlongjmp.c rwlock.c sched.c semaphore.c signals.c \
+ specific.c spinlock.c uthread_file.c wraputhread.c wrapsyscall.c \
-+ barrier.c localtime.c
++ barrier.c localtime.c getlogin.c telldir.c ttyname.c strptime.c
+
+.if defined(USING_GCC3)
+SOBJS += libgcc_r/unwind-sjlj.o libgcc_r/unwind-dw2.o libgcc_r/unwind-dw2-fde.o
diff --git a/devel/linuxthreads/files/strptime.sed b/devel/linuxthreads/files/strptime.sed
new file mode 100644
index 000000000000..de66d0666609
--- /dev/null
+++ b/devel/linuxthreads/files/strptime.sed
@@ -0,0 +1,9 @@
+1i\
+#if __FreeBSD__ == 4
+/.*MUTEX_STATIC.*/d
+/^#include "pthread_private.h"/d
+s/\&_gotgmt_mutexd/PTHREAD_MUTEX_INITIALIZER/
+s/\&logname_lock/PTHREAD_MUTEX_INITIALIZER/
+s/#include <libc_private.h>/extern int __isthreaded;/
+$a\
+#endif /* __FreeBSD__ == 4 */
diff --git a/devel/linuxthreads/files/telldir.c b/devel/linuxthreads/files/telldir.c
new file mode 100644
index 000000000000..31f573d5322a
--- /dev/null
+++ b/devel/linuxthreads/files/telldir.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libc/gen/telldir.c,v 1.4.12.1 2001/03/05 09:39:59 obrien Exp $
+ */
+
+#if __FreeBSD__ < 5
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)telldir.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+ * The option SINGLEUSE may be defined to say that a telldir
+ * cookie may be used only once before it is freed. This option
+ * is used to avoid having memory usage grow without bound.
+ */
+#define SINGLEUSE
+
+/*
+ * One of these structures is malloced to describe the current directory
+ * position each time telldir is called. It records the current magic
+ * cookie returned by getdirentries and the offset within the buffer
+ * associated with that return value.
+ */
+struct ddloc {
+ struct ddloc *loc_next;/* next structure in list */
+ long loc_index; /* key associated with structure */
+ long loc_seek; /* magic cookie returned by getdirentries */
+ long loc_loc; /* offset of entry in buffer */
+ const DIR* loc_dirp; /* directory which used this entry */
+};
+
+#define NDIRHASH 32 /* Num of hash lists, must be a power of 2 */
+#define LOCHASH(i) ((i)&(NDIRHASH-1))
+
+static long dd_loccnt; /* Index of entry for sequential readdir's */
+static struct ddloc *dd_hash[NDIRHASH]; /* Hash list heads for ddlocs */
+
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+extern int __isthreaded;
+static pthread_mutex_t telldir_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define THREAD_LOCK() if (__isthreaded) pthread_mutex_lock(&telldir_mutex)
+#define THREAD_UNLOCK() if (__isthreaded) pthread_mutex_unlock(&telldir_mutex)
+#else
+#define THREAD_LOCK()
+#define THREAD_UNLOCK()
+#endif
+
+/*
+ * return a pointer into a directory
+ */
+long
+telldir(dirp)
+ const DIR *dirp;
+{
+ int index;
+ struct ddloc *lp;
+
+ if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL)
+ return (-1);
+ THREAD_LOCK();
+ index = dd_loccnt++;
+ lp->loc_index = index;
+ lp->loc_seek = dirp->dd_seek;
+ lp->loc_loc = dirp->dd_loc;
+ lp->loc_dirp = dirp;
+ lp->loc_next = dd_hash[LOCHASH(index)];
+ dd_hash[LOCHASH(index)] = lp;
+ THREAD_UNLOCK();
+ return (index);
+}
+
+/*
+ * seek to an entry in a directory.
+ * Only values returned by "telldir" should be passed to seekdir.
+ */
+void
+_seekdir(dirp, loc)
+ DIR *dirp;
+ long loc;
+{
+ struct ddloc *lp;
+ struct ddloc **prevlp;
+ struct dirent *dp;
+
+ THREAD_LOCK();
+ prevlp = &dd_hash[LOCHASH(loc)];
+ lp = *prevlp;
+ while (lp != NULL) {
+ if (lp->loc_index == loc)
+ break;
+ prevlp = &lp->loc_next;
+ lp = lp->loc_next;
+ }
+ if (lp == NULL) {
+ THREAD_UNLOCK();
+ return;
+ }
+#ifdef SINGLEUSE
+ *prevlp = lp->loc_next;
+#endif
+ THREAD_UNLOCK();
+ if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek)
+ goto found;
+ (void) lseek(dirp->dd_fd, (off_t)lp->loc_seek, SEEK_SET);
+ dirp->dd_seek = lp->loc_seek;
+ dirp->dd_loc = 0;
+ while (dirp->dd_loc < lp->loc_loc) {
+ dp = readdir(dirp);
+ if (dp == NULL)
+ break;
+ }
+found:
+#ifdef SINGLEUSE
+ free((caddr_t)lp);
+#endif
+}
+
+/*
+ * Reclaim memory for telldir cookies which weren't used.
+ */
+void
+_reclaim_telldir(dirp)
+ const DIR *dirp;
+{
+ struct ddloc *lp;
+ struct ddloc **prevlp;
+ int i;
+
+ THREAD_LOCK();
+ for (i = 0; i < NDIRHASH; i++) {
+ prevlp = &dd_hash[i];
+ lp = *prevlp;
+ while (lp != NULL) {
+ if (lp->loc_dirp == dirp) {
+ *prevlp = lp->loc_next;
+ free((caddr_t)lp);
+ lp = *prevlp;
+ continue;
+ }
+ prevlp = &lp->loc_next;
+ lp = lp->loc_next;
+ }
+ }
+ THREAD_UNLOCK();
+}
+#endif /* __FreeBSD__ < 5 */
diff --git a/devel/linuxthreads/files/ttyname.c b/devel/linuxthreads/files/ttyname.c
new file mode 100644
index 000000000000..85452e869a69
--- /dev/null
+++ b/devel/linuxthreads/files/ttyname.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * 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 $
+ */
+
+#if __FreeBSD__ < 5
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ttyname.c 8.2 (Berkeley) 1/27/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+#include <db.h>
+#include <string.h>
+#include <paths.h>
+
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+static pthread_mutex_t ttyname_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_key_t ttyname_key;
+static int ttyname_init = 0;
+char *__ttyname_basic(int fd);
+
+char *
+ttyname(int fd)
+{
+ char *ret;
+
+ ret = __ttyname_basic(fd);
+
+ return (ret);
+}
+
+char *
+__ttyname_r_basic(int fd, char *buf, size_t len)
+{
+ register struct dirent *dirp;
+ register DIR *dp;
+ struct stat dsb;
+ struct stat sb;
+ char *rval;
+ int minlen;
+
+ rval = NULL;
+
+ /* Must be a terminal. */
+ if (!isatty(fd))
+ return (rval);
+ /* Must be a character device. */
+ if (fstat(fd, &sb) || !S_ISCHR(sb.st_mode))
+ return (rval);
+ /* Must have enough room */
+ if (len <= sizeof(_PATH_DEV))
+ return (rval);
+
+ if ((dp = opendir(_PATH_DEV)) != NULL) {
+ memcpy(buf, _PATH_DEV, sizeof(_PATH_DEV));
+ for (rval = NULL; (dirp = readdir(dp)) != NULL;) {
+ if (dirp->d_fileno != 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;
+ }
+ (void) closedir(dp);
+ }
+ return (rval);
+}
+
+char *
+__ttyname_basic(int fd)
+{
+ char *buf;
+
+ pthread_mutex_lock(&ttyname_lock);
+ if (ttyname_init == 0) {
+ if (pthread_key_create(&ttyname_key, free)) {
+ pthread_mutex_unlock(&ttyname_lock);
+ 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(sizeof(_PATH_DEV) + MAXNAMLEN)) != NULL) {
+ if (pthread_setspecific(ttyname_key, buf) != 0) {
+ free(buf);
+ return (NULL);
+ }
+ } else {
+ return (NULL);
+ }
+ }
+ return (__ttyname_r_basic(fd, buf, sizeof(_PATH_DEV) + MAXNAMLEN));
+}
+
+char *
+ttyname_r(int fd, char *buf, size_t len)
+{
+ char *ret;
+
+ ret = __ttyname_r_basic(fd, buf, len);
+ return (ret);
+}
+#else
+static char buf[sizeof(_PATH_DEV) + MAXNAMLEN] = _PATH_DEV;
+static char *oldttyname __P((int, struct stat *));
+
+char *
+ttyname(fd)
+ 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)) {
+ bcopy(data.data,
+ buf + sizeof(_PATH_DEV) - 1, data.size);
+ (void)(db->close)(db);
+ return (buf);
+ }
+ (void)(db->close)(db);
+ }
+ return (oldttyname(fd, &sb));
+}
+
+static char *
+oldttyname(fd, sb)
+ int fd;
+ struct stat *sb;
+{
+ register struct dirent *dirp;
+ register DIR *dp;
+ struct stat dsb;
+
+ if ((dp = opendir(_PATH_DEV)) == NULL)
+ return (NULL);
+
+ while ( (dirp = readdir(dp)) ) {
+ if (dirp->d_fileno != sb->st_ino)
+ continue;
+ bcopy(dirp->d_name, buf + sizeof(_PATH_DEV) - 1,
+ dirp->d_namlen + 1);
+ if (stat(buf, &dsb) || sb->st_dev != dsb.st_dev ||
+ sb->st_ino != dsb.st_ino)
+ continue;
+ (void)closedir(dp);
+ return (buf);
+ }
+ (void)closedir(dp);
+ return (NULL);
+}
+#endif
+#endif /* __FreeBSD__ < 5 */