xref: /haiku/src/system/libroot/posix/unistd/ttyname.c (revision 1d9d47fc72028bb71b5f232a877231e59cfe2438)
1 /*
2 ** Copyright 2003, Daniel Reinhold, danielre@users.sf.net. All rights reserved.
3 ** Distributed under the terms of the OpenBeOS License.
4 */
5 
6 
7 #include <SupportDefs.h>
8 
9 #include <stdio.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <dirent.h>
13 #include <sys/stat.h>
14 #include <sys/param.h>
15 
16 
17 /* the root directory in /dev where all tty devices reside */
18 #define DEV_TTY  "/dev/tt/"
19 
20 
21 /** return the full pathname of the tty device
22  *	(NULL if not a tty or an error occurs)
23  */
24 
25 char *
26 ttyname(int fd)
27 {
28 	static char pathname[MAXPATHLEN];
29 	char  *stub = pathname + sizeof(DEV_TTY) - 1;
30 	int   stubLen = sizeof(pathname) - sizeof(DEV_TTY);
31 	struct stat fdStat;
32 	DIR   *dir;
33 	bool  found = false;
34 
35 	// first, some sanity checks:
36 	if (!isatty(fd))
37 		return NULL;
38 
39 	if (fstat(fd, &fdStat) < 0)
40 		return NULL;
41 
42 	if (!S_ISCHR(fdStat.st_mode))
43 		return NULL;
44 
45 	// start with the root tty directory at /dev
46 	strcpy(pathname, DEV_TTY);
47 
48 	if ((dir = opendir(pathname)) != NULL) {
49 		// find a matching entry in the directory:
50 		//   we must match both the inode for the file
51 		//   and the device that the file resides on
52 		struct dirent *e;
53 		struct stat entryStat;
54 
55 		while ((e = readdir(dir)) != NULL) {
56 			// try to match the file's inode
57 			if (e->d_ino != fdStat.st_ino)
58 				continue;
59 
60 			// construct the entry's full filename and
61 			// call stat() to retrieve the inode info
62 			strncpy(stub, e->d_name, stubLen);
63 
64 			if (stat(pathname, &entryStat) < 0)
65 				continue;
66 
67 			if (entryStat.st_ino == fdStat.st_ino &&
68 			    entryStat.st_dev == fdStat.st_dev) {
69 			    found = true;
70 			    break;
71 			}
72 		}
73 
74 		closedir(dir);
75 	}
76 
77 	return found ? pathname : NULL;
78 }
79