master xplshn/aruu / shared / libutil / tty.c
 1/* See LICENSE file for copyright and license details. */
 2#include <sys/sysmacros.h>
 3#include <sys/types.h>
 4#include <sys/stat.h>
 5
 6#include <fcntl.h>
 7#include <dirent.h>
 8#include <limits.h>
 9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <unistd.h>
13
14#include "../util.h"
15
16void
17devtotty(int dev, int *tty_maj, int *tty_min)
18{
19	*tty_maj = (dev >> 8) & 0xfff;
20	*tty_min = (dev & 0xff) | ((dev >> 12) & 0xfff00);
21}
22
23int
24ttytostr(int tty_maj, int tty_min, char *str, size_t n)
25{
26	struct stat sb;
27	struct dirent *dp;
28	DIR *dirp;
29	char path[PATH_MAX];
30	int fd;
31	int r = 0;
32
33	switch (tty_maj) {
34	case 136:
35		snprintf(str, n, "pts/%d", tty_min);
36		return 0;
37	case 4:
38		snprintf(str, n, "tty%d", tty_min);
39		return 0;
40	default:
41		str[0] = '?';
42		str[1] = '\0';
43		break;
44	}
45
46	dirp = opendir("/dev");
47	if (!dirp) {
48		weprintf("opendir /dev:");
49		return -1;
50	}
51
52	while ((dp = readdir(dirp))) {
53		if (!strcmp(dp->d_name, ".") ||
54		    !strcmp(dp->d_name, ".."))
55			continue;
56
57		if (strlcpy(path, "/dev/", sizeof(path)) >= sizeof(path)) {
58			weprintf("path too long\n");
59			r = -1;
60			goto err0;
61		}
62		if (strlcat(path, dp->d_name, sizeof(path)) >= sizeof(path)) {
63			weprintf("path too long\n");
64			r = -1;
65			goto err0;
66		}
67
68		if (stat(path, &sb) < 0) {
69			weprintf("stat %s:", path);
70			r = -1;
71			goto err0;
72		}
73
74		if ((int)major(sb.st_rdev) == tty_maj &&
75		    (int)minor(sb.st_rdev) == tty_min) {
76			fd = open(path, O_RDONLY | O_NONBLOCK);
77			if (fd < 0)
78				continue;
79			if (isatty(fd)) {
80				strlcpy(str, dp->d_name, n);
81				close(fd);
82				break;
83			} else {
84				close(fd);
85				r = -1;
86				goto err0;
87			}
88		}
89	}
90
91err0:
92	if (closedir(dirp) < 0) {
93		weprintf("closedir /dev:");
94		r = -1;
95	}
96
97	return r;
98}