]>
Commit | Line | Data |
---|---|---|
2cc7bad0 | 1 | /* Open a pseudoterminal. |
581c785b | 2 | Copyright (C) 2018-2022 Free Software Foundation, Inc. |
2cc7bad0 ZW |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
2cc7bad0 ZW |
18 | |
19 | #include <support/tty.h> | |
20 | #include <support/check.h> | |
21 | #include <support/support.h> | |
22 | ||
23 | #include <errno.h> | |
24 | #include <stdlib.h> | |
25 | #include <string.h> | |
26 | ||
27 | #include <fcntl.h> | |
28 | #include <termios.h> | |
29 | #include <sys/ioctl.h> | |
30 | #include <unistd.h> | |
31 | ||
32 | /* As ptsname, but allocates space for an appropriately-sized string | |
33 | using malloc. */ | |
34 | static char * | |
35 | xptsname (int fd) | |
36 | { | |
37 | int rv; | |
38 | size_t buf_len = 128; | |
39 | char *buf = xmalloc (buf_len); | |
40 | for (;;) | |
41 | { | |
42 | rv = ptsname_r (fd, buf, buf_len); | |
43 | if (rv) | |
44 | FAIL_EXIT1 ("ptsname_r: %s", strerror (errno)); | |
45 | ||
46 | if (memchr (buf, '\0', buf_len)) | |
47 | return buf; /* ptsname succeeded and the buffer was not truncated */ | |
48 | ||
49 | buf_len *= 2; | |
50 | buf = xrealloc (buf, buf_len); | |
51 | } | |
52 | } | |
53 | ||
54 | void | |
55 | support_openpty (int *a_outer, int *a_inner, char **a_name, | |
56 | const struct termios *termp, | |
57 | const struct winsize *winp) | |
58 | { | |
59 | int outer = -1, inner = -1; | |
60 | char *namebuf = 0; | |
61 | ||
62 | outer = posix_openpt (O_RDWR | O_NOCTTY); | |
63 | if (outer == -1) | |
64 | FAIL_EXIT1 ("posix_openpt: %s", strerror (errno)); | |
65 | ||
66 | if (grantpt (outer)) | |
67 | FAIL_EXIT1 ("grantpt: %s", strerror (errno)); | |
68 | ||
69 | if (unlockpt (outer)) | |
70 | FAIL_EXIT1 ("unlockpt: %s", strerror (errno)); | |
71 | ||
72 | ||
73 | #ifdef TIOCGPTPEER | |
74 | inner = ioctl (outer, TIOCGPTPEER, O_RDWR | O_NOCTTY); | |
75 | #endif | |
76 | if (inner == -1) | |
77 | { | |
78 | /* The kernel might not support TIOCGPTPEER, fall back to open | |
79 | by name. */ | |
80 | namebuf = xptsname (outer); | |
81 | inner = open (namebuf, O_RDWR | O_NOCTTY); | |
82 | if (inner == -1) | |
83 | FAIL_EXIT1 ("%s: %s", namebuf, strerror (errno)); | |
84 | } | |
85 | ||
86 | if (termp) | |
87 | { | |
88 | if (tcsetattr (inner, TCSAFLUSH, termp)) | |
89 | FAIL_EXIT1 ("tcsetattr: %s", strerror (errno)); | |
90 | } | |
91 | #ifdef TIOCSWINSZ | |
92 | if (winp) | |
93 | { | |
94 | if (ioctl (inner, TIOCSWINSZ, winp)) | |
95 | FAIL_EXIT1 ("TIOCSWINSZ: %s", strerror (errno)); | |
96 | } | |
97 | #endif | |
98 | ||
99 | if (a_name) | |
100 | { | |
101 | if (!namebuf) | |
102 | namebuf = xptsname (outer); | |
103 | *a_name = namebuf; | |
104 | } | |
105 | else | |
106 | free (namebuf); | |
107 | *a_outer = outer; | |
108 | *a_inner = inner; | |
109 | } |