]> git.ipfire.org Git - thirdparty/util-linux.git/blame - lib/ttyutils.c
Merge branch 'clock' of https://github.com/t-8ch/util-linux
[thirdparty/util-linux.git] / lib / ttyutils.c
CommitLineData
0f23ee0c
KZ
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 */
4e76adb0 7#include <ctype.h>
285c1f3a 8#include <unistd.h>
4e76adb0 9
cba97be9
KZ
10#ifdef HAVE_GETTTYNAM
11# include <ttyent.h>
12#endif
13
4e76adb0
KZ
14#include "c.h"
15#include "ttyutils.h"
16
cba97be9
KZ
17#ifdef __linux__
18# ifndef DEFAULT_VCTERM
19# 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# 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
f46a8d7e
KZ
44
45static int get_env_int(const char *name)
4e76adb0 46{
f46a8d7e
KZ
47 const char *cp = getenv(name);
48
49 if (cp) {
50 char *end = NULL;
51 long x;
52
53 errno = 0;
54 x = strtol(cp, &end, 10);
55
56 if (errno == 0 && end && *end == '\0' && end > cp &&
57 x > 0 && x <= INT_MAX)
58 return x;
59 }
60
61 return -1;
62}
63
64int get_terminal_dimension(int *cols, int *lines)
65{
66 int c = 0, l = 0;
4e76adb0 67
43b4f7ea
BE
68#if defined(TIOCGWINSZ)
69 struct winsize w_win;
f46a8d7e
KZ
70 if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &w_win) == 0) {
71 c = w_win.ws_col;
72 l = w_win.ws_row;
73 }
43b4f7ea
BE
74#elif defined(TIOCGSIZE)
75 struct ttysize t_win;
f46a8d7e
KZ
76 if (ioctl (STDOUT_FILENO, TIOCGSIZE, &t_win) == 0) {
77 c = t_win.ts_cols;
78 l = t_win.ts_lines;
79 }
4e76adb0 80#endif
5119ef0a
SK
81 if (cols) {
82 if (c <= 0)
83 c = get_env_int("COLUMNS");
f46a8d7e 84 *cols = c;
5119ef0a
SK
85 }
86 if (lines) {
87 if (l <= 0)
88 l = get_env_int("LINES");
f46a8d7e 89 *lines = l;
5119ef0a 90 }
f46a8d7e
KZ
91 return 0;
92}
43b4f7ea 93
f46a8d7e
KZ
94int get_terminal_width(int default_width)
95{
96 int width = 0;
4e76adb0 97
f46a8d7e 98 get_terminal_dimension(&width, NULL);
43b4f7ea
BE
99
100 return width > 0 ? width : default_width;
4e76adb0
KZ
101}
102
a6d9d23b
KZ
103int get_terminal_stdfd(void)
104{
105 if (isatty(STDIN_FILENO))
106 return STDIN_FILENO;
042f62df 107 if (isatty(STDOUT_FILENO))
a6d9d23b 108 return STDOUT_FILENO;
042f62df 109 if (isatty(STDERR_FILENO))
a6d9d23b
KZ
110 return STDERR_FILENO;
111
112 return -EINVAL;
113}
114
285c1f3a 115int get_terminal_name(const char **path,
1ef28920
KZ
116 const char **name,
117 const char **number)
118{
119 const char *tty;
120 const char *p;
285c1f3a
SK
121 int fd;
122
1ef28920
KZ
123
124 if (name)
125 *name = NULL;
126 if (path)
127 *path = NULL;
128 if (number)
129 *number = NULL;
130
a6d9d23b
KZ
131 fd = get_terminal_stdfd();
132 if (fd < 0)
133 return fd; /* error */
285c1f3a 134
507341f8 135 tty = ttyname(fd);
1ef28920
KZ
136 if (!tty)
137 return -1;
a6d9d23b 138
1ef28920
KZ
139 if (path)
140 *path = tty;
a6d9d23b
KZ
141 if (name || number)
142 tty = strncmp(tty, "/dev/", 5) == 0 ? tty + 5 : tty;
1ef28920
KZ
143 if (name)
144 *name = tty;
145 if (number) {
146 for (p = tty; p && *p; p++) {
147 if (isdigit(*p)) {
148 *number = p;
149 break;
150 }
151 }
152 }
153 return 0;
154}
155
4d9b788d
KZ
156int get_terminal_type(const char **type)
157{
158 *type = getenv("TERM");
159 if (*type)
160 return -EINVAL;
161 return 0;
162}
1ef28920 163
cba97be9
KZ
164char *get_terminal_default_type(const char *ttyname, int is_serial)
165{
cba97be9 166 if (ttyname) {
84a8f5ed 167#ifdef HAVE_GETTTYNAM
cba97be9
KZ
168 struct ttyent *ent = getttynam(ttyname);
169
170 if (ent && ent->ty_type)
171 return strdup(ent->ty_type);
cba97be9
KZ
172#endif
173
174#if defined (__s390__) || defined (__s390x__)
cba97be9
KZ
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);
cba97be9 187#endif
84a8f5ed 188 }
cba97be9
KZ
189
190 return strdup(is_serial ? DEFAULT_STERM : DEFAULT_VCTERM);
191}
192
e8f7acb0 193#ifdef TEST_PROGRAM_TTYUTILS
5f247c8b 194# include <stdlib.h>
5f247c8b
KZ
195int main(void)
196{
1ef28920 197 const char *path, *name, *num;
f46a8d7e 198 int c, l;
1ef28920 199
b8fd5c05 200 if (get_terminal_name(&path, &name, &num) == 0) {
cba97be9
KZ
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);
1ef28920 212 }
f46a8d7e 213 get_terminal_dimension(&c, &l);
cba97be9
KZ
214 fprintf(stderr, "tty cols: %d\n", c);
215 fprintf(stderr, "tty lines: %d\n", l);
f46a8d7e 216
1ef28920 217
5f247c8b
KZ
218 return EXIT_SUCCESS;
219}
e8f7acb0 220#endif /* TEST_PROGRAM_TTYUTILS */