]>
Commit | Line | Data |
---|---|---|
28f540f4 | 1 | /* ioctl commands which must be done in the C library. |
56f778c9 | 2 | Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. |
28f540f4 RM |
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 Library General Public License as | |
7 | published by the Free Software Foundation; either version 2 of the | |
8 | 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 | Library General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Library General Public | |
16 | License along with the GNU C Library; see the file COPYING.LIB. If | |
17 | not, write to the Free Software Foundation, Inc., 675 Mass Ave, | |
18 | Cambridge, MA 02139, USA. */ | |
19 | ||
20 | #include <hurd.h> | |
21 | #include <hurd/fd.h> | |
22 | #include <sys/ioctl.h> | |
23 | #include <hurd/ioctl.h> | |
24 | ||
25 | ||
26 | ||
27 | /* Symbol set of ioctl handler lists. If there are user-registered | |
28 | handlers, one of these lists will contain them. The other lists are | |
29 | handlers built into the library. */ | |
30 | symbol_set_define (_hurd_ioctl_handler_lists) | |
31 | ||
32 | /* Look up REQUEST in the set of handlers. */ | |
33 | ioctl_handler_t | |
34 | _hurd_lookup_ioctl_handler (int request) | |
35 | { | |
36 | void *const *ptr; | |
37 | const struct ioctl_handler *h; | |
38 | ||
9e3db9cd RM |
39 | /* Mask off the type bits, so that we see requests in a single group as a |
40 | contiguous block of values. */ | |
41 | request = _IOC_NOTYPE (request); | |
42 | ||
28f540f4 RM |
43 | for (ptr = symbol_set_first_element (_hurd_ioctl_handler_lists); |
44 | !symbol_set_end_p (_hurd_ioctl_handler_lists, ptr); | |
45 | ++ptr) | |
46 | for (h = *ptr; h != NULL; h = h->next) | |
47 | if (request >= h->first_request && request <= h->last_request) | |
48 | return h->handler; | |
49 | ||
50 | return NULL; | |
51 | } | |
52 | \f | |
53 | #include <fcntl.h> | |
54 | ||
55 | /* Find out how many bytes may be read from FD without blocking. */ | |
56 | ||
57 | static int | |
58 | fioctl (int fd, | |
59 | int request, | |
60 | int *arg) | |
61 | { | |
62 | error_t err; | |
63 | ||
64 | *(volatile int *) arg = *arg; | |
65 | ||
66 | switch (request) | |
67 | { | |
68 | default: | |
9e3db9cd | 69 | err = ENOTTY; |
28f540f4 RM |
70 | break; |
71 | ||
72 | case FIONREAD: | |
73 | { | |
74 | mach_msg_type_number_t navail; | |
75 | err = HURD_DPORT_USE (fd, __io_readable (port, &navail)); | |
76 | if (!err) | |
77 | *arg = (int) navail; | |
78 | } | |
79 | break; | |
80 | ||
81 | case FIONBIO: | |
82 | err = HURD_DPORT_USE (fd, (*arg ? | |
83 | __io_set_some_openmodes : | |
84 | __io_clear_some_openmodes) | |
85 | (port, O_NONBLOCK)); | |
86 | break; | |
87 | ||
88 | case FIOASYNC: | |
89 | err = HURD_DPORT_USE (fd, (*arg ? | |
90 | __io_set_some_openmodes : | |
91 | __io_clear_some_openmodes) | |
92 | (port, O_ASYNC)); | |
93 | break; | |
94 | ||
95 | case FIOSETOWN: | |
96 | err = HURD_DPORT_USE (fd, __io_mod_owner (port, *arg)); | |
97 | break; | |
98 | ||
99 | case FIOGETOWN: | |
100 | err = HURD_DPORT_USE (fd, __io_get_owner (port, arg)); | |
101 | break; | |
102 | } | |
103 | ||
9e3db9cd | 104 | return err ? __hurd_dfail (fd, err) : 0; |
28f540f4 RM |
105 | } |
106 | ||
107 | _HURD_HANDLE_IOCTLS (fioctl, FIOGETOWN, FIONREAD); | |
108 | ||
109 | ||
110 | static int | |
111 | fioclex (int fd, | |
112 | int request) | |
113 | { | |
114 | int flag; | |
115 | ||
116 | switch (request) | |
117 | { | |
118 | default: | |
9e3db9cd | 119 | return __hurd_fail (ENOTTY); |
28f540f4 RM |
120 | case FIOCLEX: |
121 | flag = FD_CLOEXEC; | |
122 | break; | |
123 | case FIONCLEX: | |
124 | flag = 0; | |
125 | break; | |
126 | } | |
127 | ||
128 | return __fcntl (fd, F_SETFD, flag); | |
129 | } | |
9e3db9cd | 130 | _HURD_HANDLE_IOCTL (fioclex, FIOCLEX, FIONCLEX); |
28f540f4 RM |
131 | \f |
132 | #include <hurd/term.h> | |
56f778c9 | 133 | #include <hurd/tioctl.h> |
28f540f4 RM |
134 | |
135 | static void | |
136 | rectty_dtable (mach_port_t cttyid) | |
137 | { | |
138 | int i; | |
56f778c9 | 139 | |
28f540f4 RM |
140 | HURD_CRITICAL_BEGIN; |
141 | __mutex_lock (&_hurd_dtable_lock); | |
142 | ||
143 | for (i = 0; i < _hurd_dtablesize; ++i) | |
144 | { | |
145 | struct hurd_fd *const d = _hurd_dtable[i]; | |
146 | mach_port_t newctty; | |
147 | ||
148 | if (d == NULL) | |
149 | /* Nothing to do for an unused descriptor cell. */ | |
150 | continue; | |
151 | ||
152 | if (cttyid == MACH_PORT_NULL) | |
153 | /* We now have no controlling tty at all. */ | |
154 | newctty = MACH_PORT_NULL; | |
155 | else | |
156 | HURD_PORT_USE (&d->port, | |
157 | ({ mach_port_t id; | |
158 | /* Get the io object's cttyid port. */ | |
159 | if (! __term_getctty (port, &id)) | |
160 | { | |
161 | if (id == cttyid && /* Is it ours? */ | |
162 | /* Get the ctty io port. */ | |
163 | __term_open_ctty (port, | |
164 | _hurd_pid, _hurd_pgrp, | |
165 | &newctty)) | |
166 | /* XXX it is our ctty but the call failed? */ | |
167 | newctty = MACH_PORT_NULL; | |
168 | __mach_port_deallocate | |
169 | (__mach_task_self (), (mach_port_t) id); | |
170 | } | |
171 | else | |
172 | newctty = MACH_PORT_NULL; | |
173 | 0; | |
174 | })); | |
175 | ||
176 | /* Install the new ctty port. */ | |
177 | _hurd_port_set (&d->ctty, newctty); | |
178 | } | |
179 | ||
180 | __mutex_unlock (&_hurd_dtable_lock); | |
181 | HURD_CRITICAL_END; | |
182 | } | |
183 | ||
184 | ||
185 | /* Called when we have received a message saying to use a new ctty ID port. */ | |
186 | ||
187 | error_t | |
188 | _hurd_setcttyid (mach_port_t cttyid) | |
189 | { | |
190 | error_t err; | |
191 | ||
192 | if (cttyid != MACH_PORT_NULL) | |
193 | { | |
194 | /* Give the new send right a user reference. | |
195 | This is a good way to check that it is valid. */ | |
196 | if (err = __mach_port_mod_refs (__mach_task_self (), cttyid, | |
197 | MACH_PORT_RIGHT_SEND, 1)) | |
198 | return err; | |
199 | } | |
200 | ||
201 | /* Install the port, consuming the reference we just created. */ | |
202 | _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], cttyid); | |
203 | ||
204 | /* Reset all the ctty ports in all the descriptors. */ | |
205 | __USEPORT (CTTYID, (rectty_dtable (cttyid), 0)); | |
206 | ||
207 | return 0; | |
208 | } | |
209 | ||
210 | ||
211 | /* Make FD be the controlling terminal. | |
212 | This function is called for `ioctl (fd, TCIOSCTTY)'. */ | |
213 | ||
214 | static int | |
215 | tiocsctty (int fd, | |
216 | int request) /* Always TIOCSCTTY. */ | |
217 | { | |
218 | mach_port_t cttyid; | |
219 | error_t err; | |
220 | ||
221 | /* Get FD's cttyid port, unless it is already ours. */ | |
222 | err = HURD_DPORT_USE (fd, ctty != MACH_PORT_NULL ? EADDRINUSE : | |
223 | __term_getctty (port, &cttyid)); | |
224 | if (err == EADDRINUSE) | |
225 | /* FD is already the ctty. Nothing to do. */ | |
226 | return 0; | |
227 | else if (err) | |
228 | return __hurd_fail (err); | |
229 | ||
56f778c9 RM |
230 | /* Change the terminal's pgrp to ours. */ |
231 | err = HURD_DPORT_USE (fd, __tioctl_tiocspgrp (port, _hurd_pgrp)); | |
232 | if (err) | |
233 | return __hurd_fail (err); | |
234 | ||
28f540f4 RM |
235 | /* Make it our own. */ |
236 | _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], cttyid); | |
237 | ||
238 | /* Reset all the ctty ports in all the descriptors. */ | |
239 | __USEPORT (CTTYID, (rectty_dtable (cttyid), 0)); | |
240 | ||
241 | return 0; | |
242 | } | |
243 | _HURD_HANDLE_IOCTL (tiocsctty, TIOCSCTTY); | |
244 | ||
245 | /* Dissociate from the controlling terminal. */ | |
246 | ||
247 | static int | |
248 | tiocnotty (int fd, | |
249 | int request) /* Always TIOCNOTTY. */ | |
250 | { | |
251 | mach_port_t fd_cttyid; | |
252 | error_t err; | |
253 | ||
254 | if (err = HURD_DPORT_USE (fd, __term_getctty (port, &fd_cttyid))) | |
255 | return __hurd_fail (err); | |
256 | ||
257 | if (__USEPORT (CTTYID, port != fd_cttyid)) | |
258 | err = EINVAL; | |
259 | ||
260 | __mach_port_deallocate (__mach_task_self (), fd_cttyid); | |
261 | ||
262 | if (err) | |
263 | return __hurd_fail (err); | |
264 | ||
265 | /* Clear our cttyid port cell. */ | |
266 | _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], MACH_PORT_NULL); | |
267 | ||
268 | /* Reset all the ctty ports in all the descriptors. */ | |
56f778c9 | 269 | |
28f540f4 RM |
270 | __USEPORT (CTTYID, (rectty_dtable (MACH_PORT_NULL), 0)); |
271 | ||
272 | return 0; | |
273 | } | |
274 | _HURD_HANDLE_IOCTL (tiocnotty, TIOCNOTTY); |