]> git.ipfire.org Git - thirdparty/glibc.git/blame - hurd/dtable.c
2006-08-02 Thomas Schwinge <tschwinge@gnu.org>
[thirdparty/glibc.git] / hurd / dtable.c
CommitLineData
72e1a750 1/* Copyright (C) 1991,92,93,94,95,96,97,99 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
AJ
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
28f540f4 18
28f540f4
RM
19#include <hurd.h>
20#include <hurd/term.h>
21#include <hurd/fd.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <fcntl.h>
25#include <limits.h>
26#include <cthreads.h> /* For `struct mutex'. */
27#include "set-hooks.h"
28#include "hurdmalloc.h" /* XXX */
29
30
31struct mutex _hurd_dtable_lock = MUTEX_INITIALIZER; /* XXX ld bug; must init */
32struct hurd_fd **_hurd_dtable;
33int _hurd_dtablesize;
34
35
36DEFINE_HOOK (_hurd_fd_subinit, (void));
37
38/* Initialize the file descriptor table at startup. */
39
40static void
41init_dtable (void)
42{
1e9dc039 43 int i;
28f540f4
RM
44
45 __mutex_init (&_hurd_dtable_lock);
46
47 /* The initial size of the descriptor table is that of the passed-in
48 table. It will be expanded as necessary up to _hurd_dtable_rlimit. */
49 _hurd_dtablesize = _hurd_init_dtablesize;
50
51 /* Allocate the vector of pointers. */
52 _hurd_dtable = malloc (_hurd_dtablesize * sizeof (*_hurd_dtable));
53 if (_hurd_dtablesize != 0 && _hurd_dtable == NULL)
54 __libc_fatal ("hurd: Can't allocate file descriptor table\n");
55
56 /* Initialize the descriptor table. */
1e9dc039 57 for (i = 0; (unsigned int) i < _hurd_init_dtablesize; ++i)
28f540f4
RM
58 {
59 if (_hurd_init_dtable[i] == MACH_PORT_NULL)
60 /* An unused descriptor is marked by a null pointer. */
61 _hurd_dtable[i] = NULL;
62 else
63 {
64 /* Allocate a new file descriptor structure. */
65 struct hurd_fd *new = malloc (sizeof (struct hurd_fd));
66 if (new == NULL)
67 __libc_fatal ("hurd: Can't allocate initial file descriptors\n");
68
69 /* Initialize the port cells. */
70 _hurd_port_init (&new->port, MACH_PORT_NULL);
71 _hurd_port_init (&new->ctty, MACH_PORT_NULL);
72
73 /* Install the port in the descriptor.
74 This sets up all the ctty magic. */
75 _hurd_port2fd (new, _hurd_init_dtable[i], 0);
76
77 _hurd_dtable[i] = new;
78 }
79 }
80
81 /* Clear out the initial descriptor table.
82 Everything must use _hurd_dtable now. */
83 __vm_deallocate (__mach_task_self (),
84 (vm_address_t) _hurd_init_dtable,
85 _hurd_init_dtablesize * sizeof (_hurd_init_dtable[0]));
86 _hurd_init_dtable = NULL;
87 _hurd_init_dtablesize = 0;
88
89 /* Initialize the remaining empty slots in the table. */
90 for (; i < _hurd_dtablesize; ++i)
91 _hurd_dtable[i] = NULL;
92
93 /* Run things that want to run after the file descriptor table
94 is initialized. */
95 RUN_HOOK (_hurd_fd_subinit, ());
96
97 (void) &init_dtable; /* Avoid "defined but not used" warning. */
98}
99
100text_set_element (_hurd_subinit, init_dtable);
101
102/* XXX when the linker supports it, the following functions should all be
103 elsewhere and just have text_set_elements here. */
104\f
105/* Called by `getdport' to do its work. */
106
107static file_t
108get_dtable_port (int fd)
109{
72e1a750 110 struct hurd_fd *d = _hurd_fd_get (fd);
28f540f4 111 file_t dport;
72e1a750
RM
112
113 if (!d)
114 return __hurd_fail (EBADF), MACH_PORT_NULL;
115
116 HURD_CRITICAL_BEGIN;
117
118 dport = HURD_PORT_USE (&d->port,
119 ({
120 error_t err;
121 mach_port_t outport;
122 err = __mach_port_mod_refs (__mach_task_self (),
123 port,
124 MACH_PORT_RIGHT_SEND,
125 1);
126 if (err)
127 {
128 errno = err;
129 outport = MACH_PORT_NULL;
130 }
131 else
132 outport = port;
133 outport;
134 }));
135
136 HURD_CRITICAL_END;
137
138 return dport;
28f540f4
RM
139}
140
141file_t (*_hurd_getdport_fn) (int fd) = get_dtable_port;
142\f
143#include <hurd/signal.h>
144
145/* We are in the child fork; the dtable lock is still held.
146 The parent has inserted send rights for all the normal io ports,
147 but we must recover ctty-special ports for ourselves. */
148static error_t
149fork_child_dtable (void)
150{
151 error_t err;
152 int i;
153
154 err = 0;
155
156 for (i = 0; !err && i < _hurd_dtablesize; ++i)
157 {
158 struct hurd_fd *d = _hurd_dtable[i];
159 if (d == NULL)
160 continue;
161
162 /* No other thread is using the send rights in the child task. */
163 d->port.users = d->ctty.users = NULL;
164
165 if (d->ctty.port != MACH_PORT_NULL)
166 {
167 /* There was a ctty-special port in the parent.
168 We need to get one for ourselves too. */
169 __mach_port_deallocate (__mach_task_self (), d->ctty.port);
170 err = __term_open_ctty (d->port.port, _hurd_pid, _hurd_pgrp,
171 &d->ctty.port);
172 if (err)
173 d->ctty.port = MACH_PORT_NULL;
174 }
175
176 /* XXX for each fd with a cntlmap, reauth and re-map_cntl. */
177 }
178 return err;
179
180 (void) &fork_child_dtable; /* Avoid "defined but not used" warning. */
181}
182
183data_set_element (_hurd_fork_locks, _hurd_dtable_lock); /* XXX ld bug: bss */
184text_set_element (_hurd_fork_child_hook, fork_child_dtable);
185\f
186/* Called when our process group has changed. */
187
188static void
189ctty_new_pgrp (void)
190{
191 int i;
8f0c527e 192
28f540f4
RM
193 HURD_CRITICAL_BEGIN;
194 __mutex_lock (&_hurd_dtable_lock);
195
72e1a750 196 if (__USEPORT (CTTYID, port == MACH_PORT_NULL))
28f540f4 197 {
72e1a750
RM
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.
202
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. */
28f540f4 208 }
72e1a750
RM
209 else
210 for (i = 0; i < _hurd_dtablesize; ++i)
211 {
212 struct hurd_fd *const d = _hurd_dtable[i];
213 struct hurd_userlink ulink, ctty_ulink;
214 io_t port, ctty;
215
216 if (d == NULL)
217 /* Nothing to do for an unused descriptor cell. */
218 continue;
219
220 port = _hurd_port_get (&d->port, &ulink);
221 ctty = _hurd_port_get (&d->ctty, &ctty_ulink);
222
223 if (ctty != MACH_PORT_NULL)
224 {
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 if (__term_open_ctty (port, _hurd_pid, _hurd_pgrp, &new))
229 new = MACH_PORT_NULL;
230 _hurd_port_set (&d->ctty, new);
231 }
232
233 _hurd_port_free (&d->port, &ulink, port);
234 _hurd_port_free (&d->ctty, &ctty_ulink, ctty);
235 }
28f540f4
RM
236
237 __mutex_unlock (&_hurd_dtable_lock);
238 HURD_CRITICAL_END;
239
240 (void) &ctty_new_pgrp; /* Avoid "defined but not used" warning. */
241}
242
243text_set_element (_hurd_pgrp_changed_hook, ctty_new_pgrp);
244\f
245/* Called to reauthenticate the dtable when the auth port changes. */
246
247static void
248reauth_dtable (void)
249{
250 int i;
251
252 HURD_CRITICAL_BEGIN;
253 __mutex_lock (&_hurd_dtable_lock);
254
255 for (i = 0; i < _hurd_dtablesize; ++i)
256 {
257 struct hurd_fd *const d = _hurd_dtable[i];
258 mach_port_t new, newctty, ref;
8f0c527e 259
28f540f4
RM
260 if (d == NULL)
261 /* Nothing to do for an unused descriptor cell. */
262 continue;
263
264 ref = __mach_reply_port ();
265
266 /* Take the descriptor cell's lock. */
267 __spin_lock (&d->port.lock);
8f0c527e 268
28f540f4
RM
269 /* Reauthenticate the descriptor's port. */
270 if (d->port.port != MACH_PORT_NULL &&
271 ! __io_reauthenticate (d->port.port,
272 ref, MACH_MSG_TYPE_MAKE_SEND) &&
273 ! __USEPORT (AUTH, __auth_user_authenticate
274 (port,
28f540f4
RM
275 ref, MACH_MSG_TYPE_MAKE_SEND,
276 &new)))
277 {
278 /* Replace the port in the descriptor cell
279 with the newly reauthenticated port. */
280
281 if (d->ctty.port != MACH_PORT_NULL &&
282 ! __io_reauthenticate (d->ctty.port,
283 ref, MACH_MSG_TYPE_MAKE_SEND) &&
284 ! __USEPORT (AUTH, __auth_user_authenticate
285 (port,
28f540f4
RM
286 ref, MACH_MSG_TYPE_MAKE_SEND,
287 &newctty)))
288 _hurd_port_set (&d->ctty, newctty);
289
290 _hurd_port_locked_set (&d->port, new);
291 }
292 else
293 /* Lost. Leave this descriptor cell alone. */
294 __spin_unlock (&d->port.lock);
295
296 __mach_port_destroy (__mach_task_self (), ref);
297 }
298
299 __mutex_unlock (&_hurd_dtable_lock);
300 HURD_CRITICAL_END;
301
302 (void) &reauth_dtable; /* Avoid "defined but not used" warning. */
303}
304
305text_set_element (_hurd_reauth_hook, reauth_dtable);