Update install.texi, and regenerate INSTALL.
[glibc.git] / hurd / dtable.c
blobbbd3bfc89232234232339f29c1d0dbe74c75c9ac
1 /* Copyright (C) 1991-2021 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
18 #include <hurd.h>
19 #include <hurd/term.h>
20 #include <hurd/fd.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <limits.h>
25 #include <lock-intern.h> /* For `struct mutex'. */
26 #include "set-hooks.h"
27 #include "hurdmalloc.h" /* XXX */
30 struct mutex _hurd_dtable_lock = MUTEX_INITIALIZER; /* XXX ld bug; must init */
31 struct hurd_fd **_hurd_dtable;
32 int _hurd_dtablesize;
35 DEFINE_HOOK (_hurd_fd_subinit, (void));
37 /* Initialize the file descriptor table at startup. */
39 static void
40 init_dtable (void)
42 int i;
44 __mutex_init (&_hurd_dtable_lock);
46 /* The initial size of the descriptor table is that of the passed-in
47 table. It will be expanded as necessary up to _hurd_dtable_rlimit. */
48 _hurd_dtablesize = _hurd_init_dtablesize;
50 /* Allocate the vector of pointers. */
51 _hurd_dtable = malloc (_hurd_dtablesize * sizeof (*_hurd_dtable));
52 if (_hurd_dtablesize != 0 && _hurd_dtable == NULL)
53 __libc_fatal ("hurd: Can't allocate file descriptor table\n");
55 /* Initialize the descriptor table. */
56 for (i = 0; (unsigned int) i < _hurd_init_dtablesize; ++i)
58 if (_hurd_init_dtable[i] == MACH_PORT_NULL)
59 /* An unused descriptor is marked by a null pointer. */
60 _hurd_dtable[i] = NULL;
61 else
63 /* Allocate a new file descriptor structure. */
64 struct hurd_fd *new = malloc (sizeof (struct hurd_fd));
65 if (new == NULL)
66 __libc_fatal ("hurd: Can't allocate initial file descriptors\n");
68 /* Initialize the port cells. */
69 _hurd_port_init (&new->port, MACH_PORT_NULL);
70 _hurd_port_init (&new->ctty, MACH_PORT_NULL);
72 /* Install the port in the descriptor.
73 This sets up all the ctty magic. */
74 _hurd_port2fd (new, _hurd_init_dtable[i], 0);
76 _hurd_dtable[i] = new;
80 /* Clear out the initial descriptor table.
81 Everything must use _hurd_dtable now. */
82 __vm_deallocate (__mach_task_self (),
83 (vm_address_t) _hurd_init_dtable,
84 _hurd_init_dtablesize * sizeof (_hurd_init_dtable[0]));
85 _hurd_init_dtable = NULL;
86 _hurd_init_dtablesize = 0;
88 /* Initialize the remaining empty slots in the table. */
89 for (; i < _hurd_dtablesize; ++i)
90 _hurd_dtable[i] = NULL;
92 /* Run things that want to run after the file descriptor table
93 is initialized. */
94 RUN_HOOK (_hurd_fd_subinit, ());
96 (void) &init_dtable; /* Avoid "defined but not used" warning. */
99 text_set_element (_hurd_subinit, init_dtable);
101 /* XXX when the linker supports it, the following functions should all be
102 elsewhere and just have text_set_elements here. */
104 /* Called by `getdport' to do its work. */
106 static file_t
107 get_dtable_port (int fd)
109 struct hurd_fd *d = _hurd_fd_get (fd);
110 file_t dport;
112 if (!d)
113 return __hurd_fail (EBADF), MACH_PORT_NULL;
115 HURD_CRITICAL_BEGIN;
117 dport = HURD_PORT_USE (&d->port,
119 error_t err;
120 mach_port_t outport;
121 err = __mach_port_mod_refs (__mach_task_self (),
122 port,
123 MACH_PORT_RIGHT_SEND,
125 if (err)
127 errno = err;
128 outport = MACH_PORT_NULL;
130 else
131 outport = port;
132 outport;
133 }));
135 HURD_CRITICAL_END;
137 return dport;
140 file_t (*_hurd_getdport_fn) (int fd) = get_dtable_port;
142 #include <hurd/signal.h>
144 /* We are in the child fork; the dtable lock is still held.
145 The parent has inserted send rights for all the normal io ports,
146 but we must recover ctty-special ports for ourselves. */
147 static error_t
148 fork_child_dtable (void)
150 error_t err;
151 int i;
153 err = 0;
155 for (i = 0; !err && i < _hurd_dtablesize; ++i)
157 struct hurd_fd *d = _hurd_dtable[i];
158 if (d == NULL)
159 continue;
161 /* No other thread is using the send rights in the child task. */
162 d->port.users = d->ctty.users = NULL;
164 if (d->ctty.port != MACH_PORT_NULL)
166 /* There was a ctty-special port in the parent.
167 We need to get one for ourselves too. */
168 __mach_port_deallocate (__mach_task_self (), d->ctty.port);
169 err = __term_open_ctty (d->port.port, _hurd_pid, _hurd_pgrp,
170 &d->ctty.port);
171 if (err)
172 d->ctty.port = MACH_PORT_NULL;
175 /* XXX for each fd with a cntlmap, reauth and re-map_cntl. */
177 return err;
179 (void) &fork_child_dtable; /* Avoid "defined but not used" warning. */
182 data_set_element (_hurd_fork_locks, _hurd_dtable_lock); /* XXX ld bug: bss */
183 text_set_element (_hurd_fork_child_hook, fork_child_dtable);
185 /* Called when our process group has changed. */
187 static void
188 ctty_new_pgrp (void)
190 int i;
192 retry:
193 HURD_CRITICAL_BEGIN;
194 __mutex_lock (&_hurd_dtable_lock);
196 if (__USEPORT (CTTYID, port == MACH_PORT_NULL))
198 /* We have no controlling terminal. If we haven't had one recently,
199 but our pgrp is being pointlessly diddled anyway, then we will
200 have nothing to do in the loop below because no fd will have a
201 ctty port at all.
203 More likely, a setsid call is responsible both for the change
204 in pgrp and for clearing the cttyid port. In that case, setsid
205 held the dtable lock while updating the dtable to clear all the
206 ctty ports, and ergo must have finished doing so before we run here.
207 So we can be sure, again, that the loop below has no work to do. */
209 else
210 for (i = 0; i < _hurd_dtablesize; ++i)
212 struct hurd_fd *const d = _hurd_dtable[i];
213 struct hurd_userlink ulink, ctty_ulink;
214 io_t port, ctty;
216 if (d == NULL)
217 /* Nothing to do for an unused descriptor cell. */
218 continue;
220 port = _hurd_port_get (&d->port, &ulink);
221 ctty = _hurd_port_get (&d->ctty, &ctty_ulink);
223 if (ctty != MACH_PORT_NULL)
225 /* This fd has a ctty-special port. We need a new one, to tell
226 the io server of our different process group. */
227 io_t new;
228 error_t err;
229 if ((err = __term_open_ctty (port, _hurd_pid, _hurd_pgrp, &new)))
231 if (err == EINTR)
233 /* Got a signal while inside an RPC of the critical section, retry again */
234 __mutex_unlock (&_hurd_dtable_lock);
235 HURD_CRITICAL_UNLOCK;
236 goto retry;
238 new = MACH_PORT_NULL;
240 _hurd_port_set (&d->ctty, new);
243 _hurd_port_free (&d->port, &ulink, port);
244 _hurd_port_free (&d->ctty, &ctty_ulink, ctty);
247 __mutex_unlock (&_hurd_dtable_lock);
248 HURD_CRITICAL_END;
250 (void) &ctty_new_pgrp; /* Avoid "defined but not used" warning. */
253 text_set_element (_hurd_pgrp_changed_hook, ctty_new_pgrp);
255 /* Called to reauthenticate the dtable when the auth port changes. */
257 static void
258 reauth_dtable (void)
260 int i;
262 HURD_CRITICAL_BEGIN;
263 __mutex_lock (&_hurd_dtable_lock);
265 for (i = 0; i < _hurd_dtablesize; ++i)
267 struct hurd_fd *const d = _hurd_dtable[i];
268 mach_port_t new, newctty, ref;
270 if (d == NULL)
271 /* Nothing to do for an unused descriptor cell. */
272 continue;
274 ref = __mach_reply_port ();
276 /* Take the descriptor cell's lock. */
277 __spin_lock (&d->port.lock);
279 /* Reauthenticate the descriptor's port. */
280 if (d->port.port != MACH_PORT_NULL
281 && ! __io_reauthenticate (d->port.port,
282 ref, MACH_MSG_TYPE_MAKE_SEND)
283 && ! __USEPORT (AUTH, __auth_user_authenticate
284 (port,
285 ref, MACH_MSG_TYPE_MAKE_SEND,
286 &new)))
288 /* Replace the port in the descriptor cell
289 with the newly reauthenticated port. */
291 if (d->ctty.port != MACH_PORT_NULL
292 && ! __io_reauthenticate (d->ctty.port,
293 ref, MACH_MSG_TYPE_MAKE_SEND)
294 && ! __USEPORT (AUTH, __auth_user_authenticate
295 (port,
296 ref, MACH_MSG_TYPE_MAKE_SEND,
297 &newctty)))
298 _hurd_port_set (&d->ctty, newctty);
300 _hurd_port_locked_set (&d->port, new);
302 else
303 /* Lost. Leave this descriptor cell alone. */
304 __spin_unlock (&d->port.lock);
306 __mach_port_destroy (__mach_task_self (), ref);
309 __mutex_unlock (&_hurd_dtable_lock);
310 HURD_CRITICAL_END;
312 (void) &reauth_dtable; /* Avoid "defined but not used" warning. */
315 text_set_element (_hurd_reauth_hook, reauth_dtable);