| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 | #include <errno.h>#include <unistd.h>#include <string.h>#include <sys/stat.h>#include <dirent.h>static int __check_dir_for_tty_match(char * dirname, struct stat *st, char *buf, size_t buflen){    DIR *fp;    int len;    struct stat dst;    struct dirent *d;    fp = opendir(dirname);    if (fp == NULL)	return errno;    strncpy(buf, dirname, buflen);    strncat(buf, "/", buflen);    len = strlen(dirname) + 1;    while ((d = readdir(fp)) != 0) {	strncpy(buf+len, d->d_name, buflen-len);	buf[buflen-1]='\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... */	if (lstat(buf, &dst) == 0 &&		st->st_dev == dst.st_dev && st->st_ino == dst.st_ino)#else	if (lstat(buf, &dst) == 0 &&		S_ISCHR(dst.st_mode) && st->st_rdev == dst.st_rdev)#endif	{	    closedir(fp);	    return 0;	}    }    closedir(fp);    return ENOTTY;}/* 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 */char *ttyname(int fd){    static char name[NAME_MAX];    ttyname_r(fd, name, NAME_MAX);    return(name);}int ttyname_r(int fd, char *buf, size_t buflen){    int noerr;    struct stat st;    noerr = errno;    if (buf==NULL) {	noerr = EINVAL;	goto cool_found_it;    }    /* Make sure we have enough space to return "/dev/pts/0" */    if (buflen < 10) {	noerr = ERANGE;	goto cool_found_it;    }    if (!isatty (fd)) {	noerr = ENOTTY;	goto cool_found_it;    }    if (fstat(fd, &st) < 0)	return errno;    if (!isatty(fd)) {	noerr = ENOTTY;	goto cool_found_it;    }    /* Lets try /dev/vc first (be devfs compatible) */    if ( (noerr=__check_dir_for_tty_match("/dev/vc", &st, buf, buflen)) == 0) 	goto cool_found_it;    /* Lets try /dev/tts next (be devfs compatible) */    if ( (noerr=__check_dir_for_tty_match("/dev/tts", &st, buf, buflen)) == 0) 	goto cool_found_it;    /* Lets try /dev/pts next */    if ( (noerr=__check_dir_for_tty_match("/dev/pts", &st, buf, buflen)) == 0) 	goto cool_found_it;    /* Lets try walking through /dev last */    if ( (noerr=__check_dir_for_tty_match("/dev", &st, buf, buflen)) == 0) 	goto cool_found_it;cool_found_it:    __set_errno(noerr);    return noerr;}
 |