diff options
Diffstat (limited to 'hurd/dtable.c')
-rw-r--r-- | hurd/dtable.c | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/hurd/dtable.c b/hurd/dtable.c new file mode 100644 index 0000000000..3e785a9710 --- /dev/null +++ b/hurd/dtable.c @@ -0,0 +1,277 @@ +/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <hurd.h> +#include <hurd/term.h> +#include <hurd/fd.h> +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <limits.h> +#include <cthreads.h> /* For `struct mutex'. */ +#include "set-hooks.h" +#include "hurdmalloc.h" /* XXX */ + + +struct mutex _hurd_dtable_lock = MUTEX_INITIALIZER; /* XXX ld bug; must init */ +struct hurd_fd **_hurd_dtable; +int _hurd_dtablesize; + + +DEFINE_HOOK (_hurd_fd_subinit, (void)); + +/* Initialize the file descriptor table at startup. */ + +static void +init_dtable (void) +{ + register size_t i; + + __mutex_init (&_hurd_dtable_lock); + + /* The initial size of the descriptor table is that of the passed-in + table. It will be expanded as necessary up to _hurd_dtable_rlimit. */ + _hurd_dtablesize = _hurd_init_dtablesize; + + /* Allocate the vector of pointers. */ + _hurd_dtable = malloc (_hurd_dtablesize * sizeof (*_hurd_dtable)); + if (_hurd_dtablesize != 0 && _hurd_dtable == NULL) + __libc_fatal ("hurd: Can't allocate file descriptor table\n"); + + /* Initialize the descriptor table. */ + for (i = 0; i < _hurd_init_dtablesize; ++i) + { + if (_hurd_init_dtable[i] == MACH_PORT_NULL) + /* An unused descriptor is marked by a null pointer. */ + _hurd_dtable[i] = NULL; + else + { + /* Allocate a new file descriptor structure. */ + struct hurd_fd *new = malloc (sizeof (struct hurd_fd)); + if (new == NULL) + __libc_fatal ("hurd: Can't allocate initial file descriptors\n"); + + /* Initialize the port cells. */ + _hurd_port_init (&new->port, MACH_PORT_NULL); + _hurd_port_init (&new->ctty, MACH_PORT_NULL); + + /* Install the port in the descriptor. + This sets up all the ctty magic. */ + _hurd_port2fd (new, _hurd_init_dtable[i], 0); + + _hurd_dtable[i] = new; + } + } + + /* Clear out the initial descriptor table. + Everything must use _hurd_dtable now. */ + __vm_deallocate (__mach_task_self (), + (vm_address_t) _hurd_init_dtable, + _hurd_init_dtablesize * sizeof (_hurd_init_dtable[0])); + _hurd_init_dtable = NULL; + _hurd_init_dtablesize = 0; + + /* Initialize the remaining empty slots in the table. */ + for (; i < _hurd_dtablesize; ++i) + _hurd_dtable[i] = NULL; + + /* Run things that want to run after the file descriptor table + is initialized. */ + RUN_HOOK (_hurd_fd_subinit, ()); + + (void) &init_dtable; /* Avoid "defined but not used" warning. */ +} + +text_set_element (_hurd_subinit, init_dtable); + +/* XXX when the linker supports it, the following functions should all be + elsewhere and just have text_set_elements here. */ + +/* Called by `getdport' to do its work. */ + +static file_t +get_dtable_port (int fd) +{ + file_t dport; + int err = HURD_DPORT_USE (fd, __mach_port_mod_refs (__mach_task_self (), + (dport = port), + MACH_PORT_RIGHT_SEND, + 1)); + if (err) + { + errno = err; + return MACH_PORT_NULL; + } + else + return dport; +} + +file_t (*_hurd_getdport_fn) (int fd) = get_dtable_port; + +#include <hurd/signal.h> + +/* We are in the child fork; the dtable lock is still held. + The parent has inserted send rights for all the normal io ports, + but we must recover ctty-special ports for ourselves. */ +static error_t +fork_child_dtable (void) +{ + error_t err; + int i; + + err = 0; + + for (i = 0; !err && i < _hurd_dtablesize; ++i) + { + struct hurd_fd *d = _hurd_dtable[i]; + if (d == NULL) + continue; + + /* No other thread is using the send rights in the child task. */ + d->port.users = d->ctty.users = NULL; + + if (d->ctty.port != MACH_PORT_NULL) + { + /* There was a ctty-special port in the parent. + We need to get one for ourselves too. */ + __mach_port_deallocate (__mach_task_self (), d->ctty.port); + err = __term_open_ctty (d->port.port, _hurd_pid, _hurd_pgrp, + &d->ctty.port); + if (err) + d->ctty.port = MACH_PORT_NULL; + } + + /* XXX for each fd with a cntlmap, reauth and re-map_cntl. */ + } + return err; + + (void) &fork_child_dtable; /* Avoid "defined but not used" warning. */ +} + +data_set_element (_hurd_fork_locks, _hurd_dtable_lock); /* XXX ld bug: bss */ +text_set_element (_hurd_fork_child_hook, fork_child_dtable); + +/* Called when our process group has changed. */ + +static void +ctty_new_pgrp (void) +{ + int i; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_dtable_lock); + + for (i = 0; i < _hurd_dtablesize; ++i) + { + struct hurd_fd *const d = _hurd_dtable[i]; + struct hurd_userlink ulink, ctty_ulink; + io_t port, ctty; + + if (d == NULL) + /* Nothing to do for an unused descriptor cell. */ + continue; + + port = _hurd_port_get (&d->port, &ulink); + ctty = _hurd_port_get (&d->ctty, &ctty_ulink); + + if (ctty != MACH_PORT_NULL) + { + /* This fd has a ctty-special port. We need a new one, to tell + the io server of our different process group. */ + io_t new; + if (__term_open_ctty (port, _hurd_pid, _hurd_pgrp, &new)) + new = MACH_PORT_NULL; + _hurd_port_set (&d->ctty, new); + } + + _hurd_port_free (&d->port, &ulink, port); + _hurd_port_free (&d->ctty, &ctty_ulink, ctty); + } + + __mutex_unlock (&_hurd_dtable_lock); + HURD_CRITICAL_END; + + (void) &ctty_new_pgrp; /* Avoid "defined but not used" warning. */ +} + +text_set_element (_hurd_pgrp_changed_hook, ctty_new_pgrp); + +/* Called to reauthenticate the dtable when the auth port changes. */ + +static void +reauth_dtable (void) +{ + int i; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_dtable_lock); + + for (i = 0; i < _hurd_dtablesize; ++i) + { + struct hurd_fd *const d = _hurd_dtable[i]; + mach_port_t new, newctty, ref; + + if (d == NULL) + /* Nothing to do for an unused descriptor cell. */ + continue; + + ref = __mach_reply_port (); + + /* Take the descriptor cell's lock. */ + __spin_lock (&d->port.lock); + + /* Reauthenticate the descriptor's port. */ + if (d->port.port != MACH_PORT_NULL && + ! __io_reauthenticate (d->port.port, + ref, MACH_MSG_TYPE_MAKE_SEND) && + ! __USEPORT (AUTH, __auth_user_authenticate + (port, + d->port.port, + ref, MACH_MSG_TYPE_MAKE_SEND, + &new))) + { + /* Replace the port in the descriptor cell + with the newly reauthenticated port. */ + + if (d->ctty.port != MACH_PORT_NULL && + ! __io_reauthenticate (d->ctty.port, + ref, MACH_MSG_TYPE_MAKE_SEND) && + ! __USEPORT (AUTH, __auth_user_authenticate + (port, + d->ctty.port, + ref, MACH_MSG_TYPE_MAKE_SEND, + &newctty))) + _hurd_port_set (&d->ctty, newctty); + + _hurd_port_locked_set (&d->port, new); + } + else + /* Lost. Leave this descriptor cell alone. */ + __spin_unlock (&d->port.lock); + + __mach_port_destroy (__mach_task_self (), ref); + } + + __mutex_unlock (&_hurd_dtable_lock); + HURD_CRITICAL_END; + + (void) &reauth_dtable; /* Avoid "defined but not used" warning. */ +} + +text_set_element (_hurd_reauth_hook, reauth_dtable); |