1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
#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;
}
|