Coverage Report

Created: 2026-08-13 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/util-linux/lib/ttyutils.c
Line
Count
Source
1
/*
2
 * No copyright is claimed.  This code is in the public domain; do with
3
 * it what you wish.
4
 *
5
 * Written by Karel Zak <kzak@redhat.com>
6
 */
7
#include <ctype.h>
8
#include <unistd.h>
9
10
#ifdef HAVE_GETTTYNAM
11
# include <ttyent.h>
12
#endif
13
14
#include "c.h"
15
#include "ttyutils.h"
16
17
#ifdef __linux__
18
#  ifndef DEFAULT_VCTERM
19
0
#    define DEFAULT_VCTERM "linux"
20
#  endif
21
#  if defined (__s390__) || defined (__s390x__)
22
#    define DEFAULT_TTYS0  "dumb"
23
#    define DEFAULT_TTY32  "ibm327x"
24
#    define DEFAULT_TTYS1  "vt220"
25
#  endif
26
#  ifndef DEFAULT_STERM
27
0
#    define DEFAULT_STERM  "vt102"
28
#  endif
29
#elif defined(__GNU__)
30
#  ifndef DEFAULT_VCTERM
31
#    define DEFAULT_VCTERM "hurd"
32
#  endif
33
#  ifndef DEFAULT_STERM
34
#    define DEFAULT_STERM  "vt102"
35
#  endif
36
#else
37
#  ifndef DEFAULT_VCTERM
38
#    define DEFAULT_VCTERM "vt100"
39
#  endif
40
#  ifndef DEFAULT_STERM
41
#    define DEFAULT_STERM  "vt100"
42
#  endif
43
#endif
44
45
static int get_env_int(const char *name)
46
0
{
47
0
  const char *cp = getenv(name);
48
49
0
  if (cp) {
50
0
    char *end = NULL;
51
0
    long x;
52
53
0
    errno = 0;
54
0
    x = strtol(cp, &end, 10);
55
56
0
    if (errno == 0 && end && *end == '\0' && end > cp &&
57
0
        x > 0 && x <= INT_MAX)
58
0
      return x;
59
0
  }
60
61
0
  return -1;
62
0
}
63
64
int get_terminal_dimension(int *cols, int *lines)
65
0
{
66
0
  int c = 0, l = 0;
67
68
0
#if defined(TIOCGWINSZ)
69
0
  struct winsize  w_win;
70
0
  if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &w_win) == 0) {
71
0
    c = w_win.ws_col;
72
0
    l = w_win.ws_row;
73
0
  }
74
#elif defined(TIOCGSIZE)
75
  struct ttysize  t_win;
76
  if (ioctl (STDOUT_FILENO, TIOCGSIZE, &t_win) == 0) {
77
    c = t_win.ts_cols;
78
    l = t_win.ts_lines;
79
  }
80
#endif
81
0
  if (cols) {
82
0
    if (c <= 0)
83
0
      c = get_env_int("COLUMNS");
84
0
    *cols = c;
85
0
  }
86
0
  if (lines) {
87
0
    if (l <= 0)
88
0
      l = get_env_int("LINES");
89
0
    *lines = l;
90
0
  }
91
0
  return 0;
92
0
}
93
94
int get_terminal_width(int default_width)
95
0
{
96
0
  int width = 0;
97
98
0
  get_terminal_dimension(&width, NULL);
99
100
0
  return width > 0 ? width : default_width;
101
0
}
102
103
int get_terminal_stdfd(void)
104
0
{
105
0
  if (isatty(STDIN_FILENO))
106
0
    return STDIN_FILENO;
107
0
  if (isatty(STDOUT_FILENO))
108
0
    return STDOUT_FILENO;
109
0
  if (isatty(STDERR_FILENO))
110
0
    return STDERR_FILENO;
111
112
0
  return -EINVAL;
113
0
}
114
115
int get_terminal_name(const char **path,
116
          const char **name,
117
          const char **number)
118
0
{
119
0
  const char *tty;
120
0
  const char *p;
121
0
  int fd;
122
123
124
0
  if (name)
125
0
    *name = NULL;
126
0
  if (path)
127
0
    *path = NULL;
128
0
  if (number)
129
0
    *number = NULL;
130
131
0
  fd = get_terminal_stdfd();
132
0
  if (fd < 0)
133
0
    return fd; /* error */
134
135
0
  tty = ttyname(fd);
136
0
  if (!tty)
137
0
    return -1;
138
139
0
  if (path)
140
0
    *path = tty;
141
0
  if (name || number)
142
0
    tty = strncmp(tty, "/dev/", 5) == 0 ? tty + 5 : tty;
143
0
  if (name)
144
0
    *name = tty;
145
0
  if (number) {
146
0
    for (p = tty; p && *p; p++) {
147
0
      if (isdigit(*p)) {
148
0
        *number = p;
149
0
        break;
150
0
      }
151
0
    }
152
0
  }
153
0
  return 0;
154
0
}
155
156
int get_terminal_type(const char **type)
157
0
{
158
0
  *type = getenv("TERM");
159
0
  if (*type)
160
0
    return -EINVAL;
161
0
  return 0;
162
0
}
163
164
char *get_terminal_default_type(const char *ttyname, int is_serial)
165
0
{
166
0
  if (ttyname) {
167
0
#ifdef HAVE_GETTTYNAM
168
0
    struct ttyent *ent = getttynam(ttyname);
169
170
0
    if (ent && ent->ty_type)
171
0
      return strdup(ent->ty_type);
172
0
#endif
173
174
#if defined (__s390__) || defined (__s390x__)
175
    /*
176
     * Special terminal on first serial line on a S/390(x) which
177
     * is due legacy reasons a block terminal of type 3270 or
178
     * higher.  Whereas the second serial line on a S/390(x) is
179
     * a real character terminal which is compatible with VT220.
180
     */
181
    if (strcmp(ttyname, "ttyS0") == 0)    /* linux/drivers/s390/char/con3215.c */
182
      return strdup(DEFAULT_TTYS0);
183
    else if (strncmp(ttyname, "3270/tty", 8) == 0)  /* linux/drivers/s390/char/con3270.c */
184
      return strdup(DEFAULT_TTY32);
185
    else if (strcmp(ttyname, "ttyS1") == 0)   /* linux/drivers/s390/char/sclp_vt220.c */
186
      return strdup(DEFAULT_TTYS1);
187
#endif
188
0
  }
189
190
0
  return strdup(is_serial ? DEFAULT_STERM : DEFAULT_VCTERM);
191
0
}
192
193
#ifdef TEST_PROGRAM_TTYUTILS
194
# include <stdlib.h>
195
int main(void)
196
{
197
  const char *path, *name, *num;
198
  int c, l;
199
200
  if (get_terminal_name(&path, &name, &num) == 0) {
201
    char *term;
202
203
    fprintf(stderr, "tty path:      %s\n", path);
204
    fprintf(stderr, "tty name:      %s\n", name);
205
    fprintf(stderr, "tty number:    %s\n", num);
206
207
    fprintf(stderr, "tty term:      %s\n", getenv("TERM"));
208
209
    term = get_terminal_default_type(name, 0);
210
    fprintf(stderr, "tty dflt term: %s\n", term);
211
    free(term);
212
  }
213
  get_terminal_dimension(&c, &l);
214
  fprintf(stderr,         "tty cols:      %d\n", c);
215
  fprintf(stderr,         "tty lines:     %d\n", l);
216
217
218
  return EXIT_SUCCESS;
219
}
220
#endif /* TEST_PROGRAM_TTYUTILS */