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