about summary refs log tree commit diff
path: root/REORG.TODO/hurd/dtable.c
diff options
context:
space:
mode:
Diffstat (limited to 'REORG.TODO/hurd/dtable.c')
-rw-r--r--REORG.TODO/hurd/dtable.c304
1 files changed, 304 insertions, 0 deletions
diff --git a/REORG.TODO/hurd/dtable.c b/REORG.TODO/hurd/dtable.c
new file mode 100644
index 0000000000..46bad42c3c
--- /dev/null
+++ b/REORG.TODO/hurd/dtable.c
@@ -0,0 +1,304 @@
+/* Copyright (C) 1991-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#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)
+{
+  int 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; (unsigned int) 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)
+{
+  struct hurd_fd *d = _hurd_fd_get (fd);
+  file_t dport;
+
+  if (!d)
+    return __hurd_fail (EBADF), MACH_PORT_NULL;
+
+  HURD_CRITICAL_BEGIN;
+
+  dport = HURD_PORT_USE (&d->port,
+			 ({
+			   error_t err;
+			   mach_port_t outport;
+			   err = __mach_port_mod_refs (__mach_task_self (),
+						       port,
+						       MACH_PORT_RIGHT_SEND,
+						       1);
+			   if (err)
+			     {
+			       errno = err;
+			       outport = MACH_PORT_NULL;
+			     }
+			   else
+			     outport = port;
+			   outport;
+			 }));
+
+  HURD_CRITICAL_END;
+
+  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);
+
+  if (__USEPORT (CTTYID, port == MACH_PORT_NULL))
+    {
+      /* We have no controlling terminal.  If we haven't had one recently,
+	 but our pgrp is being pointlessly diddled anyway, then we will
+	 have nothing to do in the loop below because no fd will have a
+	 ctty port at all.
+
+	 More likely, a setsid call is responsible both for the change
+	 in pgrp and for clearing the cttyid port.  In that case, setsid
+	 held the dtable lock while updating the dtable to clear all the
+	 ctty ports, and ergo must have finished doing so before we run here.
+	 So we can be sure, again, that the loop below has no work to do.  */
+    }
+  else
+    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,
+			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,
+			    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);