summaryrefslogtreecommitdiff
path: root/hurd/dtable.c
diff options
context:
space:
mode:
Diffstat (limited to 'hurd/dtable.c')
-rw-r--r--hurd/dtable.c277
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);