blob: 2d8b207d3c26c68348e6df8df6c6f200b700af4b [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998.
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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20#include <errno.h>
21#include <fcntl.h>
22#include <stdlib.h>
23#include <stdbool.h>
24#include <unistd.h>
25#include <paths.h>
26#include <sys/statfs.h>
27
28extern __typeof(statfs) __libc_statfs;
29
30
31#if !defined __ASSUME_DEVPTS__
32
33/* Constant that identifies the `devpts' filesystem. */
34# define DEVPTS_SUPER_MAGIC 0x1cd1
35/* Constant that identifies the `devfs' filesystem. */
36# define DEVFS_SUPER_MAGIC 0x1373
37#endif
38
39/* Path to the master pseudo terminal cloning device. */
40#define _PATH_DEVPTMX _PATH_DEV "ptmx"
41/* Directory containing the UNIX98 pseudo terminals. */
42#define _PATH_DEVPTS _PATH_DEV "pts"
43
44#if !defined __UNIX98PTY_ONLY__ && defined __UCLIBC_HAS_GETPT__
45/* Prototype for function that opens BSD-style master pseudo-terminals. */
46extern int __bsd_getpt (void) attribute_hidden;
47#endif
48
49/* Open a master pseudo terminal and return its file descriptor. */
50int
51posix_openpt (int flags)
52{
53#define have_no_dev_ptmx (1<<0)
54#define devpts_mounted (1<<1)
55#if !defined __UNIX98PTY_ONLY__
56 static smallint _state;
57#endif
58 int fd;
59
60#if !defined __UNIX98PTY_ONLY__
61 if (!(_state & have_no_dev_ptmx))
62#endif
63 {
64 fd = open (_PATH_DEVPTMX, flags);
65 if (fd != -1)
66 {
67#if defined __ASSUME_DEVPTS__
68 return fd;
69#else
70 struct statfs fsbuf;
71
72 /* Check that the /dev/pts filesystem is mounted
73 or if /dev is a devfs filesystem (this implies /dev/pts). */
74 if (
75#if !defined __UNIX98PTY_ONLY__
76 (_state & devpts_mounted) ||
77#endif
78 (__libc_statfs (_PATH_DEVPTS, &fsbuf) == 0
79 && fsbuf.f_type == DEVPTS_SUPER_MAGIC)
80 || (__libc_statfs (_PATH_DEV, &fsbuf) == 0
81 && fsbuf.f_type == DEVFS_SUPER_MAGIC))
82 {
83 /* Everything is ok. */
84#if !defined __UNIX98PTY_ONLY__
85 _state |= devpts_mounted;
86#endif
87 return fd;
88 }
89
90 /* If /dev/pts is not mounted then the UNIX98 pseudo terminals
91 are not usable. */
92 close (fd);
93#if !defined __UNIX98PTY_ONLY__
94 _state |= have_no_dev_ptmx;
95#endif
96#endif
97 }
98 else
99 {
100#if !defined __UNIX98PTY_ONLY__
101 if (errno == ENOENT || errno == ENODEV)
102 _state |= have_no_dev_ptmx;
103 else
104#endif
105 return -1;
106 }
107 }
108#if !defined __UNIX98PTY_ONLY__ && defined __UCLIBC_HAS_GETPT__
109 /* If we have no ptmx then ignore flags and use the fallback. */
110 if (_state & have_no_dev_ptmx)
111 return __bsd_getpt();
112#endif
113 return -1;
114}
115libc_hidden_def(posix_openpt)
116#undef have_no_dev_ptmx
117#undef devpts_mounted
118
119#if defined __USE_GNU && defined __UCLIBC_HAS_GETPT__
120int getpt (void)
121{
122 return posix_openpt(O_RDWR);
123}
124
125#if !defined __UNIX98PTY_ONLY__ && defined __UCLIBC_HAS_GETPT__
126# define PTYNAME1 "pqrstuvwxyzabcde";
127# define PTYNAME2 "0123456789abcdef";
128
129# define __getpt __bsd_getpt
130# include "bsd_getpt.c"
131#endif
132#endif /* GNU && __UCLIBC_HAS_GETPT__ */