master xplshn/aruu / shared / libutil / tty.c
 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}