Update.
[glibc.git] / hurd / dtable.c
blob30f6a5ee822f21da7f4803506171ea486381b868
1 /* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 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 Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 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 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
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 */
31 struct mutex _hurd_dtable_lock = MUTEX_INITIALIZER; /* XXX ld bug; must init */
32 struct hurd_fd **_hurd_dtable;
33 int _hurd_dtablesize;
36 DEFINE_HOOK (_hurd_fd_subinit, (void));
38 /* Initialize the file descriptor table at startup. */
40 static void
41 init_dtable (void)
43 int i;
45 __mutex_init (&_hurd_dtable_lock);
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;
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");
56 /* Initialize the descriptor table. */
57 for (i = 0; (unsigned int) i < _hurd_init_dtablesize; ++i)
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
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");
69 /* Initialize the port cells. */
70 _hurd_port_init (&new->port, MACH_PORT_NULL);
71 _hurd_port_init (&new->ctty, MACH_PORT_NULL);
73 /* Install the port in the descriptor.
74 This sets up all the ctty magic. */
75 _hurd_port2fd (new, _hurd_init_dtable[i], 0);
77 _hurd_dtable[i] = new;
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;
89 /* Initialize the remaining empty slots in the table. */
90 for (; i < _hurd_dtablesize; ++i)
91 _hurd_dtable[i] = NULL;
93 /* Run things that want to run after the file descriptor table
94 is initialized. */
95 RUN_HOOK (_hurd_fd_subinit, ());
97 (void) &init_dtable; /* Avoid "defined but not used" warning. */
100 text_set_element (_hurd_subinit, init_dtable);
102 /* XXX when the linker supports it, the following functions should all be
103 elsewhere and just have text_set_elements here. */
105 /* Called by `getdport' to do its work. */
107 static file_t
108 get_dtable_port (int fd)
110 file_t dport;
111 int err = HURD_DPORT_USE (fd, __mach_port_mod_refs (__mach_task_self (),
112 (dport = port),
113 MACH_PORT_RIGHT_SEND,
114 1));
115 if (err)
117 errno = err;
118 return MACH_PORT_NULL;
120 else
121 return dport;
124 file_t (*_hurd_getdport_fn) (int fd) = get_dtable_port;
126 #include <hurd/signal.h>
128 /* We are in the child fork; the dtable lock is still held.
129 The parent has inserted send rights for all the normal io ports,
130 but we must recover ctty-special ports for ourselves. */
131 static error_t
132 fork_child_dtable (void)
134 error_t err;
135 int i;
137 err = 0;
139 for (i = 0; !err && i < _hurd_dtablesize; ++i)
141 struct hurd_fd *d = _hurd_dtable[i];
142 if (d == NULL)
143 continue;
145 /* No other thread is using the send rights in the child task. */
146 d->port.users = d->ctty.users = NULL;
148 if (d->ctty.port != MACH_PORT_NULL)
150 /* There was a ctty-special port in the parent.
151 We need to get one for ourselves too. */
152 __mach_port_deallocate (__mach_task_self (), d->ctty.port);
153 err = __term_open_ctty (d->port.port, _hurd_pid, _hurd_pgrp,
154 &d->ctty.port);
155 if (err)
156 d->ctty.port = MACH_PORT_NULL;
159 /* XXX for each fd with a cntlmap, reauth and re-map_cntl. */
161 return err;
163 (void) &fork_child_dtable; /* Avoid "defined but not used" warning. */
166 data_set_element (_hurd_fork_locks, _hurd_dtable_lock); /* XXX ld bug: bss */
167 text_set_element (_hurd_fork_child_hook, fork_child_dtable);
169 /* Called when our process group has changed. */
171 static void
172 ctty_new_pgrp (void)
174 int i;
176 HURD_CRITICAL_BEGIN;
177 __mutex_lock (&_hurd_dtable_lock);
179 for (i = 0; i < _hurd_dtablesize; ++i)
181 struct hurd_fd *const d = _hurd_dtable[i];
182 struct hurd_userlink ulink, ctty_ulink;
183 io_t port, ctty;
185 if (d == NULL)
186 /* Nothing to do for an unused descriptor cell. */
187 continue;
189 port = _hurd_port_get (&d->port, &ulink);
190 ctty = _hurd_port_get (&d->ctty, &ctty_ulink);
192 if (ctty != MACH_PORT_NULL)
194 /* This fd has a ctty-special port. We need a new one, to tell
195 the io server of our different process group. */
196 io_t new;
197 if (__term_open_ctty (port, _hurd_pid, _hurd_pgrp, &new))
198 new = MACH_PORT_NULL;
199 _hurd_port_set (&d->ctty, new);
202 _hurd_port_free (&d->port, &ulink, port);
203 _hurd_port_free (&d->ctty, &ctty_ulink, ctty);
206 __mutex_unlock (&_hurd_dtable_lock);
207 HURD_CRITICAL_END;
209 (void) &ctty_new_pgrp; /* Avoid "defined but not used" warning. */
212 text_set_element (_hurd_pgrp_changed_hook, ctty_new_pgrp);
214 /* Called to reauthenticate the dtable when the auth port changes. */
216 static void
217 reauth_dtable (void)
219 int i;
221 HURD_CRITICAL_BEGIN;
222 __mutex_lock (&_hurd_dtable_lock);
224 for (i = 0; i < _hurd_dtablesize; ++i)
226 struct hurd_fd *const d = _hurd_dtable[i];
227 mach_port_t new, newctty, ref;
229 if (d == NULL)
230 /* Nothing to do for an unused descriptor cell. */
231 continue;
233 ref = __mach_reply_port ();
235 /* Take the descriptor cell's lock. */
236 __spin_lock (&d->port.lock);
238 /* Reauthenticate the descriptor's port. */
239 if (d->port.port != MACH_PORT_NULL &&
240 ! __io_reauthenticate (d->port.port,
241 ref, MACH_MSG_TYPE_MAKE_SEND) &&
242 ! __USEPORT (AUTH, __auth_user_authenticate
243 (port,
244 ref, MACH_MSG_TYPE_MAKE_SEND,
245 &new)))
247 /* Replace the port in the descriptor cell
248 with the newly reauthenticated port. */
250 if (d->ctty.port != MACH_PORT_NULL &&
251 ! __io_reauthenticate (d->ctty.port,
252 ref, MACH_MSG_TYPE_MAKE_SEND) &&
253 ! __USEPORT (AUTH, __auth_user_authenticate
254 (port,
255 ref, MACH_MSG_TYPE_MAKE_SEND,
256 &newctty)))
257 _hurd_port_set (&d->ctty, newctty);
259 _hurd_port_locked_set (&d->port, new);
261 else
262 /* Lost. Leave this descriptor cell alone. */
263 __spin_unlock (&d->port.lock);
265 __mach_port_destroy (__mach_task_self (), ref);
268 __mutex_unlock (&_hurd_dtable_lock);
269 HURD_CRITICAL_END;
271 (void) &reauth_dtable; /* Avoid "defined but not used" warning. */
274 text_set_element (_hurd_reauth_hook, reauth_dtable);