]> git.ipfire.org Git - thirdparty/glibc.git/blame - hurd/dtable.c
Update copyright notices with scripts/update-copyrights
[thirdparty/glibc.git] / hurd / dtable.c
CommitLineData
d4697bc9 1/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
c84142e8
UD
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
c84142e8
UD
8
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
41bdb6e2 12 Lesser General Public License for more details.
c84142e8 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
28f540f4 17
28f540f4
RM
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 <cthreads.h> /* For `struct mutex'. */
26#include "set-hooks.h"
27#include "hurdmalloc.h" /* XXX */
28
29
30struct mutex _hurd_dtable_lock = MUTEX_INITIALIZER; /* XXX ld bug; must init */
31struct hurd_fd **_hurd_dtable;
32int _hurd_dtablesize;
33
34
35DEFINE_HOOK (_hurd_fd_subinit, (void));
36
37/* Initialize the file descriptor table at startup. */
38
39static void
40init_dtable (void)
41{
1e9dc039 42 int i;
28f540f4
RM
43
44 __mutex_init (&_hurd_dtable_lock);
45
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;
49
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");
54
55 /* Initialize the descriptor table. */
1e9dc039 56 for (i = 0; (unsigned int) i < _hurd_init_dtablesize; ++i)
28f540f4
RM
57 {
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
62 {
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");
67
68 /* Initialize the port cells. */
69 _hurd_port_init (&new->port, MACH_PORT_NULL);
70 _hurd_port_init (&new->ctty, MACH_PORT_NULL);
71
72 /* Install the port in the descriptor.
73 This sets up all the ctty magic. */
74 _hurd_port2fd (new, _hurd_init_dtable[i], 0);
75
76 _hurd_dtable[i] = new;
77 }
78 }
79
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;
87
88 /* Initialize the remaining empty slots in the table. */
89 for (; i < _hurd_dtablesize; ++i)
90 _hurd_dtable[i] = NULL;
91
92 /* Run things that want to run after the file descriptor table
93 is initialized. */
94 RUN_HOOK (_hurd_fd_subinit, ());
95
96 (void) &init_dtable; /* Avoid "defined but not used" warning. */
97}
98
99text_set_element (_hurd_subinit, init_dtable);
100
101/* XXX when the linker supports it, the following functions should all be
102 elsewhere and just have text_set_elements here. */
103\f
104/* Called by `getdport' to do its work. */
105
106static file_t
107get_dtable_port (int fd)
108{
72e1a750 109 struct hurd_fd *d = _hurd_fd_get (fd);
28f540f4 110 file_t dport;
72e1a750
RM
111
112 if (!d)
113 return __hurd_fail (EBADF), MACH_PORT_NULL;
114
115 HURD_CRITICAL_BEGIN;
116
117 dport = HURD_PORT_USE (&d->port,
118 ({
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,
124 1);
125 if (err)
126 {
127 errno = err;
128 outport = MACH_PORT_NULL;
129 }
130 else
131 outport = port;
132 outport;
133 }));
134
135 HURD_CRITICAL_END;
136
137 return dport;
28f540f4
RM
138}
139
140file_t (*_hurd_getdport_fn) (int fd) = get_dtable_port;
141\f
142#include <hurd/signal.h>
143
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. */
147static error_t
148fork_child_dtable (void)
149{
150 error_t err;
151 int i;
152
153 err = 0;
154
155 for (i = 0; !err && i < _hurd_dtablesize; ++i)
156 {
157 struct hurd_fd *d = _hurd_dtable[i];
158 if (d == NULL)
159 continue;
160
161 /* No other thread is using the send rights in the child task. */
162 d->port.users = d->ctty.users = NULL;
163
164 if (d->ctty.port != MACH_PORT_NULL)
165 {
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;
173 }
174
175 /* XXX for each fd with a cntlmap, reauth and re-map_cntl. */
176 }
177 return err;
178
179 (void) &fork_child_dtable; /* Avoid "defined but not used" warning. */
180}
181
182data_set_element (_hurd_fork_locks, _hurd_dtable_lock); /* XXX ld bug: bss */
183text_set_element (_hurd_fork_child_hook, fork_child_dtable);
184\f
185/* Called when our process group has changed. */
186
187static void
188ctty_new_pgrp (void)
189{
190 int i;
8f0c527e 191
28f540f4
RM
192 HURD_CRITICAL_BEGIN;
193 __mutex_lock (&_hurd_dtable_lock);
194
72e1a750 195 if (__USEPORT (CTTYID, port == MACH_PORT_NULL))
28f540f4 196 {
72e1a750
RM
197 /* We have no controlling terminal. If we haven't had one recently,
198 but our pgrp is being pointlessly diddled anyway, then we will
199 have nothing to do in the loop below because no fd will have a
200 ctty port at all.
201
202 More likely, a setsid call is responsible both for the change
203 in pgrp and for clearing the cttyid port. In that case, setsid
204 held the dtable lock while updating the dtable to clear all the
205 ctty ports, and ergo must have finished doing so before we run here.
206 So we can be sure, again, that the loop below has no work to do. */
28f540f4 207 }
72e1a750
RM
208 else
209 for (i = 0; i < _hurd_dtablesize; ++i)
210 {
211 struct hurd_fd *const d = _hurd_dtable[i];
212 struct hurd_userlink ulink, ctty_ulink;
213 io_t port, ctty;
214
215 if (d == NULL)
216 /* Nothing to do for an unused descriptor cell. */
217 continue;
218
219 port = _hurd_port_get (&d->port, &ulink);
220 ctty = _hurd_port_get (&d->ctty, &ctty_ulink);
221
222 if (ctty != MACH_PORT_NULL)
223 {
224 /* This fd has a ctty-special port. We need a new one, to tell
225 the io server of our different process group. */
226 io_t new;
227 if (__term_open_ctty (port, _hurd_pid, _hurd_pgrp, &new))
228 new = MACH_PORT_NULL;
229 _hurd_port_set (&d->ctty, new);
230 }
231
232 _hurd_port_free (&d->port, &ulink, port);
233 _hurd_port_free (&d->ctty, &ctty_ulink, ctty);
234 }
28f540f4
RM
235
236 __mutex_unlock (&_hurd_dtable_lock);
237 HURD_CRITICAL_END;
238
239 (void) &ctty_new_pgrp; /* Avoid "defined but not used" warning. */
240}
241
242text_set_element (_hurd_pgrp_changed_hook, ctty_new_pgrp);
243\f
244/* Called to reauthenticate the dtable when the auth port changes. */
245
246static void
247reauth_dtable (void)
248{
249 int i;
250
251 HURD_CRITICAL_BEGIN;
252 __mutex_lock (&_hurd_dtable_lock);
253
254 for (i = 0; i < _hurd_dtablesize; ++i)
255 {
256 struct hurd_fd *const d = _hurd_dtable[i];
257 mach_port_t new, newctty, ref;
8f0c527e 258
28f540f4
RM
259 if (d == NULL)
260 /* Nothing to do for an unused descriptor cell. */
261 continue;
262
263 ref = __mach_reply_port ();
264
265 /* Take the descriptor cell's lock. */
266 __spin_lock (&d->port.lock);
8f0c527e 267
28f540f4
RM
268 /* Reauthenticate the descriptor's port. */
269 if (d->port.port != MACH_PORT_NULL &&
270 ! __io_reauthenticate (d->port.port,
271 ref, MACH_MSG_TYPE_MAKE_SEND) &&
272 ! __USEPORT (AUTH, __auth_user_authenticate
273 (port,
28f540f4
RM
274 ref, MACH_MSG_TYPE_MAKE_SEND,
275 &new)))
276 {
277 /* Replace the port in the descriptor cell
278 with the newly reauthenticated port. */
279
280 if (d->ctty.port != MACH_PORT_NULL &&
281 ! __io_reauthenticate (d->ctty.port,
282 ref, MACH_MSG_TYPE_MAKE_SEND) &&
283 ! __USEPORT (AUTH, __auth_user_authenticate
284 (port,
28f540f4
RM
285 ref, MACH_MSG_TYPE_MAKE_SEND,
286 &newctty)))
287 _hurd_port_set (&d->ctty, newctty);
288
289 _hurd_port_locked_set (&d->port, new);
290 }
291 else
292 /* Lost. Leave this descriptor cell alone. */
293 __spin_unlock (&d->port.lock);
294
295 __mach_port_destroy (__mach_task_self (), ref);
296 }
297
298 __mutex_unlock (&_hurd_dtable_lock);
299 HURD_CRITICAL_END;
300
301 (void) &reauth_dtable; /* Avoid "defined but not used" warning. */
302}
303
304text_set_element (_hurd_reauth_hook, reauth_dtable);