OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [linux/] [uClibc/] [libc/] [termios/] [ttyname.c] - Rev 1765

Go to most recent revision | Compare with Previous | Blame | View Log

#include <string.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
 
/* Jan 1, 2004    Manuel Novoa III
 *
 * Kept the same approach, but rewrote the code for the most part.
 * Fixed some minor issues plus (as I recall) one SUSv3 errno case.
 */
 
/* This is a fairly slow approach.  We do a linear search through some
 * directories looking for a match.  Yes this is lame.  But it should
 * work, should be small, and will return names that match what is on
 * disk.  Another approach we could use would be to use the info in
 * /proc/self/fd, but that is even more lame since it requires /proc */
 
/* SUSv3 mandates TTY_NAME_MAX as 9.  This is obviously insufficient.
 * However, there is no need to waste space and support non-standard
 * tty names either.  So we compromise and use the following buffer
 * length.  (Erik and Manuel agreed that 32 was more than reasonable.)
 */
#define TTYNAME_BUFLEN		32
 
char *ttyname(int fd)
{
	static char name[TTYNAME_BUFLEN];
 
	return ttyname_r(fd, name, TTYNAME_BUFLEN) ? NULL : name;
}
 
static const char dirlist[] =
/*   12345670123 */
"\010/dev/vc/\0"	/* Try /dev/vc first (be devfs compatible) */
"\011/dev/tts/\0"	/* and /dev/tts next (be devfs compatible) */
"\011/dev/pts/\0"	/* and try /dev/pts next */
"\005/dev/\0";		/* and try walking through /dev last */
 
int ttyname_r(int fd, char *ubuf, size_t ubuflen)
{
	struct dirent *d;
	struct stat st;
	struct stat dst;
	const char *p;
	char *s;
	DIR *fp;
	int rv;
	int len;
	char buf[TTYNAME_BUFLEN];
 
	if (fstat(fd, &st) < 0) {
		return errno;
	}
 
	rv = ENOTTY;				/* Set up the default return value. */
 
	if (!isatty(fd)) {
		goto DONE;
	}
 
	for (p = dirlist ; *p ; p += 1 + p[-1]) {
		len = *p++;
 
		assert(len + 2 <= TTYNAME_BUFLEN); /* dirname + 1 char + nul */
 
		strcpy(buf, p);
		s = buf + len;
		len =  (TTYNAME_BUFLEN-2) - len; /* Available non-nul space. */
 
		if (!(fp = opendir(p))) {
			continue;
		}
 
		while ((d = readdir(fp)) != NULL) {
			/* This should never trigger for standard names, but we
			 * check it to be safe.  */
			if (strlen(d->d_name) > len) { /* Too big? */
				continue;
			}
 
			strcpy(s, d->d_name);
 
			if ((lstat(buf, &dst) == 0)
#if 0
				/* Stupid filesystems like cramfs fail to guarantee that
				 * st_ino and st_dev uniquely identify a file, contrary to
				 * SuSv3, so we cannot be quite so precise as to require an
				 * exact match.  Settle for something less...  Grumble... */
				&& (st.st_dev == dst.st_dev) && (st.st_ino == dst.st_ino)
#else
				&& S_ISCHR(dst.st_mode) && (st.st_rdev == dst.st_rdev)
#endif
				) {				/* Found it! */
				closedir(fp);
 
				/* We treat NULL buf as ERANGE rather than EINVAL. */
				rv = ERANGE;
				if (ubuf && (strlen(buf) <= ubuflen)) {
					strcpy(ubuf, buf);
					rv = 0;
				}
				goto DONE;
			}
		}
 
		closedir(fp);
	}
 
 DONE:
	__set_errno(rv);
 
	return rv;
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.