]> git.ipfire.org Git - thirdparty/glibc.git/blame - hurd/hurdioctl.c
Cleanup of configuration options
[thirdparty/glibc.git] / hurd / hurdioctl.c
CommitLineData
28f540f4 1/* ioctl commands which must be done in the C library.
951ca0c5 2 Copyright (C) 1994,95,96,97,99,2001,2002,2009,2010
e87e2f48 3 Free Software Foundation, Inc.
c84142e8
UD
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
c84142e8
UD
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 14 Lesser General Public License for more details.
c84142e8 15
41bdb6e2
AJ
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
28f540f4
RM
20
21#include <hurd.h>
22#include <hurd/fd.h>
23#include <sys/ioctl.h>
24#include <hurd/ioctl.h>
f41c998d 25#include <string.h>
28f540f4
RM
26
27
28/* Symbol set of ioctl handler lists. If there are user-registered
29 handlers, one of these lists will contain them. The other lists are
30 handlers built into the library. */
31symbol_set_define (_hurd_ioctl_handler_lists)
32
33/* Look up REQUEST in the set of handlers. */
34ioctl_handler_t
35_hurd_lookup_ioctl_handler (int request)
36{
37 void *const *ptr;
38 const struct ioctl_handler *h;
39
9e3db9cd
RM
40 /* Mask off the type bits, so that we see requests in a single group as a
41 contiguous block of values. */
42 request = _IOC_NOTYPE (request);
43
28f540f4
RM
44 for (ptr = symbol_set_first_element (_hurd_ioctl_handler_lists);
45 !symbol_set_end_p (_hurd_ioctl_handler_lists, ptr);
46 ++ptr)
47 for (h = *ptr; h != NULL; h = h->next)
48 if (request >= h->first_request && request <= h->last_request)
49 return h->handler;
50
51 return NULL;
52}
53\f
54#include <fcntl.h>
55
56/* Find out how many bytes may be read from FD without blocking. */
57
58static int
59fioctl (int fd,
60 int request,
61 int *arg)
62{
63 error_t err;
64
65 *(volatile int *) arg = *arg;
66
67 switch (request)
68 {
69 default:
9e3db9cd 70 err = ENOTTY;
28f540f4
RM
71 break;
72
73 case FIONREAD:
74 {
75 mach_msg_type_number_t navail;
76 err = HURD_DPORT_USE (fd, __io_readable (port, &navail));
77 if (!err)
78 *arg = (int) navail;
79 }
80 break;
81
82 case FIONBIO:
83 err = HURD_DPORT_USE (fd, (*arg ?
84 __io_set_some_openmodes :
85 __io_clear_some_openmodes)
86 (port, O_NONBLOCK));
87 break;
88
89 case FIOASYNC:
90 err = HURD_DPORT_USE (fd, (*arg ?
91 __io_set_some_openmodes :
92 __io_clear_some_openmodes)
93 (port, O_ASYNC));
94 break;
95
96 case FIOSETOWN:
97 err = HURD_DPORT_USE (fd, __io_mod_owner (port, *arg));
98 break;
99
100 case FIOGETOWN:
101 err = HURD_DPORT_USE (fd, __io_get_owner (port, arg));
102 break;
103 }
104
9e3db9cd 105 return err ? __hurd_dfail (fd, err) : 0;
28f540f4
RM
106}
107
108_HURD_HANDLE_IOCTLS (fioctl, FIOGETOWN, FIONREAD);
109
110
111static int
112fioclex (int fd,
113 int request)
114{
115 int flag;
116
117 switch (request)
118 {
119 default:
9e3db9cd 120 return __hurd_fail (ENOTTY);
28f540f4
RM
121 case FIOCLEX:
122 flag = FD_CLOEXEC;
123 break;
124 case FIONCLEX:
125 flag = 0;
126 break;
127 }
128
129 return __fcntl (fd, F_SETFD, flag);
130}
7c97bb09 131_HURD_HANDLE_IOCTLS (fioclex, FIOCLEX, FIONCLEX);
28f540f4
RM
132\f
133#include <hurd/term.h>
56f778c9 134#include <hurd/tioctl.h>
28f540f4 135
72e1a750
RM
136/* Install a new CTTYID port, atomically updating the dtable appropriately.
137 This consumes the send right passed in. */
138
139void
140_hurd_locked_install_cttyid (mach_port_t cttyid)
28f540f4 141{
72e1a750
RM
142 mach_port_t old;
143 struct hurd_port *const port = &_hurd_ports[INIT_PORT_CTTYID];
144 struct hurd_userlink ulink;
28f540f4 145 int i;
56f778c9 146
72e1a750
RM
147 /* Install the new cttyid port, and preserve it with a ulink.
148 We unroll the _hurd_port_set + _hurd_port_get here so that
149 there is no window where the cell is unlocked and CTTYID could
150 be changed by another thread. (We also delay the deallocation
151 of the old port until the end, to minimize the duration of the
152 critical section.)
153
154 It is important that changing the cttyid port is only ever done by
155 holding the dtable lock continuously while updating the port cell and
156 re-ctty'ing the dtable; dtable.c assumes we do this. Otherwise, the
157 pgrp-change notification code in dtable.c has to worry about racing
158 against us here in odd situations. The one exception to this is
159 setsid, which holds the dtable lock while changing the pgrp and
160 clearing the cttyid port, and then unlocks the dtable lock to allow
161
162
163 */
164
165 __spin_lock (&port->lock);
166 old = _hurd_userlink_clear (&port->users) ? port->port : MACH_PORT_NULL;
167 port->port = cttyid;
168 cttyid = _hurd_port_locked_get (port, &ulink);
28f540f4
RM
169
170 for (i = 0; i < _hurd_dtablesize; ++i)
171 {
172 struct hurd_fd *const d = _hurd_dtable[i];
e87e2f48 173 mach_port_t newctty = MACH_PORT_NULL;
28f540f4
RM
174
175 if (d == NULL)
176 /* Nothing to do for an unused descriptor cell. */
177 continue;
178
e87e2f48
ST
179 if (cttyid != MACH_PORT_NULL)
180 /* We do have some controlling tty. */
28f540f4
RM
181 HURD_PORT_USE (&d->port,
182 ({ mach_port_t id;
183 /* Get the io object's cttyid port. */
184 if (! __term_getctty (port, &id))
185 {
e87e2f48 186 if (id == cttyid /* Is it ours? */
28f540f4 187 /* Get the ctty io port. */
e87e2f48
ST
188 && __term_open_ctty (port,
189 _hurd_pid, _hurd_pgrp,
190 &newctty))
28f540f4
RM
191 /* XXX it is our ctty but the call failed? */
192 newctty = MACH_PORT_NULL;
e87e2f48 193 __mach_port_deallocate (__mach_task_self (), id);
28f540f4 194 }
28f540f4
RM
195 0;
196 }));
197
198 /* Install the new ctty port. */
199 _hurd_port_set (&d->ctty, newctty);
200 }
201
202 __mutex_unlock (&_hurd_dtable_lock);
72e1a750
RM
203
204 if (old != MACH_PORT_NULL)
205 __mach_port_deallocate (__mach_task_self (), old);
206 _hurd_port_free (port, &ulink, cttyid);
207}
208
209static void
210install_ctty (mach_port_t cttyid)
211{
212 HURD_CRITICAL_BEGIN;
213 __mutex_lock (&_hurd_dtable_lock);
214 _hurd_locked_install_cttyid (cttyid);
28f540f4
RM
215 HURD_CRITICAL_END;
216}
217
218
219/* Called when we have received a message saying to use a new ctty ID port. */
220
221error_t
222_hurd_setcttyid (mach_port_t cttyid)
223{
224 error_t err;
225
226 if (cttyid != MACH_PORT_NULL)
227 {
228 /* Give the new send right a user reference.
229 This is a good way to check that it is valid. */
230 if (err = __mach_port_mod_refs (__mach_task_self (), cttyid,
231 MACH_PORT_RIGHT_SEND, 1))
232 return err;
233 }
234
235 /* Install the port, consuming the reference we just created. */
72e1a750 236 install_ctty (cttyid);
28f540f4
RM
237
238 return 0;
239}
240
241
951ca0c5
CFH
242static inline error_t
243do_tiocsctty (io_t port, io_t ctty)
28f540f4
RM
244{
245 mach_port_t cttyid;
246 error_t err;
247
951ca0c5
CFH
248 if (ctty != MACH_PORT_NULL)
249 /* PORT is already the ctty. Nothing to do. */
28f540f4 250 return 0;
951ca0c5
CFH
251
252 /* Get PORT's cttyid port. */
253 err = __term_getctty (port, &cttyid);
254 if (err)
255 return err;
28f540f4 256
56f778c9 257 /* Change the terminal's pgrp to ours. */
951ca0c5 258 err = __tioctl_tiocspgrp (port, _hurd_pgrp);
56f778c9 259 if (err)
951ca0c5
CFH
260 __mach_port_deallocate (__mach_task_self (), cttyid);
261 else
262 /* Make it our own. */
263 install_ctty (cttyid);
56f778c9 264
951ca0c5
CFH
265 return err;
266}
28f540f4 267
951ca0c5
CFH
268/* Make FD be the controlling terminal.
269 This function is called for `ioctl (fd, TCIOSCTTY)'. */
270
271static int
272tiocsctty (int fd,
273 int request) /* Always TIOCSCTTY. */
274{
199428c1 275 return __hurd_fail (HURD_DPORT_USE (fd, do_tiocsctty (port, ctty)));
28f540f4
RM
276}
277_HURD_HANDLE_IOCTL (tiocsctty, TIOCSCTTY);
278
279/* Dissociate from the controlling terminal. */
280
281static int
282tiocnotty (int fd,
283 int request) /* Always TIOCNOTTY. */
284{
285 mach_port_t fd_cttyid;
286 error_t err;
287
288 if (err = HURD_DPORT_USE (fd, __term_getctty (port, &fd_cttyid)))
289 return __hurd_fail (err);
290
291 if (__USEPORT (CTTYID, port != fd_cttyid))
292 err = EINVAL;
293
294 __mach_port_deallocate (__mach_task_self (), fd_cttyid);
295
296 if (err)
297 return __hurd_fail (err);
298
72e1a750
RM
299 /* Clear our cttyid port. */
300 install_ctty (MACH_PORT_NULL);
28f540f4
RM
301
302 return 0;
303}
304_HURD_HANDLE_IOCTL (tiocnotty, TIOCNOTTY);
7facfddd
MK
305\f
306#include <hurd/pfinet.h>
307#include <net/if.h>
308#include <netinet/in.h>
309
310/* Fill in the buffer IFC->IFC_BUF of length IFC->IFC_LEN with a list
311 of ifr structures, one for each network interface. */
312static int
313siocgifconf (int fd, int request, struct ifconf *ifc)
314{
315 error_t err;
b62b62ac 316 size_t data_len = ifc->ifc_len;
7facfddd
MK
317 char *data = ifc->ifc_buf;
318
319 if (data_len <= 0)
320 return 0;
321
322 err = HURD_DPORT_USE (fd, __pfinet_siocgifconf (port, ifc->ifc_len,
323 &data, &data_len));
324 if (data_len < ifc->ifc_len)
325 ifc->ifc_len = data_len;
326 if (data != ifc->ifc_buf)
327 {
328 memcpy (ifc->ifc_buf, data, ifc->ifc_len);
329 __vm_deallocate (__mach_task_self (), (vm_address_t) data, data_len);
330 }
331 return err ? __hurd_dfail (fd, err) : 0;
332}
333_HURD_HANDLE_IOCTL (siocgifconf, SIOCGIFCONF);