| 1 | /* Open a pseudoterminal. | 
|---|
| 2 | Copyright (C) 2018-2020 Free Software Foundation, Inc. | 
|---|
| 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 | 
|---|
| 17 | <https://www.gnu.org/licenses/>.  */ | 
|---|
| 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 | } | 
|---|
| 110 |  | 
|---|