Formerly ../hurd/alloc-fd.c.~6~
[kopensolaris-gnu/glibc.git] / hurd / dtable.c
index 02e8386..301513b 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1993, 1994 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
@@ -18,14 +18,21 @@ Cambridge, MA 02139, USA.  */
 
 #include <ansidecl.h>
 #include <hurd.h>
+#include <hurd/term.h>
+#include <hurd/fd.h>
 #include <gnu-stabs.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
 #include <limits.h>
 
 
-struct _hurd_dtable _hurd_dtable;
+#ifdef noteven
 struct mutex _hurd_dtable_lock;
-int *_hurd_dtable_user_dealloc;
+#endif
+struct hurd_dtable _hurd_dtable;
+int _hurd_dtable_rlimit;
+struct hurd_userlink *_hurd_dtable_users;
 
 const struct _hurd_dtable_resizes _hurd_dtable_resizes;
 
@@ -36,69 +43,65 @@ static void
 init_dtable (void)
 {
   register size_t i;
+  struct hurd_fd **dt;
 
+#ifdef noteven
   __mutex_init (&_hurd_dtable_lock);
+#endif
 
-  _hurd_dtable_user_dealloc = NULL;
+  _hurd_dtable_users = NULL;
 
   /* The initial size of the descriptor table is that of the passed-in
-     table, rounded up to a multiple of OPEN_MAX descriptors.  */
+     table, rounded up to a multiple of FOPEN_MAX descriptors.  */
   _hurd_dtable.size
-    = (_hurd_init_dtablesize + OPEN_MAX - 1) / OPEN_MAX * OPEN_MAX;
+    = (_hurd_init_dtablesize + FOPEN_MAX - 1) / FOPEN_MAX * FOPEN_MAX;
+  _hurd_dtable_rlimit = _hurd_dtable.size;
 
-  _hurd_dtable.d = malloc (_hurd_dtable.size * sizeof (*_hurd_dtable.d));
-  if (_hurd_dtable.d == NULL)
+  /* Allocate the vector of pointers.  */
+  dt = _hurd_dtable.d = malloc (_hurd_dtable.size * sizeof (*_hurd_dtable.d));
+  if (dt == NULL)
     __libc_fatal ("hurd: Can't allocate file descriptor table\n");
 
+  /* Initialize the descriptor table.  */
   for (i = 0; i < _hurd_init_dtablesize; ++i)
     {
-      struct _hurd_fd *const d = &_hurd_dtable.d[i];
-      io_statbuf_t stb;
-      io_t ctty;
-
-      _hurd_port_init (&d->port, _hurd_init_dtable[i]);
-      d->flags = 0;
-
-      if (_hurd_ctty_fstype != 0 &&
-         /* We have a controlling tty.  Is this it?  */
-         ! __io_stat (d->port.port, &stb) &&
-         stb.stb_fstype == _hurd_ctty_fstype &&
-         stb.stb_fsid == _hurd_ctty_fsid &&
-         stb.stb_fileid == _hurd_ctty_fileid &&
-         /* This is a descriptor to our controlling tty.  */
-         ! __term_become_ctty (d->port.port, _hurd_pid, _hurd_pgrp,
-                               _hurd_sigport, &ctty))
+      if (_hurd_init_dtable[i] == MACH_PORT_NULL)
+       /* An unused descriptor is marked by a null pointer.  */
+       dt[i] = NULL;
+      else
        {
-         /* Operations on CTTY return EBACKGROUND when we are not a
-            foreground user of the tty.  */
-         d->port.port = ctty;
-         ctty = _hurd_init_dtable[i];
+         /* 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);
        }
-      else
-       /* No ctty magic happening here.  */
-       ctty = MACH_PORT_NULL;
-
-      _hurd_port_init (&d->ctty, ctty);
-    }
-
-  /* Initialize the remaining empty slots in the table.  */
-  for (; i < _hurd_dtable.size; ++i)
-    {
-      _hurd_port_init (&_hurd_dtable.d[i].port, MACH_PORT_NULL);
-      _hurd_port_init (&_hurd_dtable.d[i].ctty, MACH_PORT_NULL);
-      _hurd_dtable.d[i].flags = 0;
     }
 
   /* Clear out the initial descriptor table.
      Everything must use _hurd_dtable now.  */
   __vm_deallocate (__mach_task_self (),
-                  _hurd_init_dtable,
+                  (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_dtable.size; ++i)
+    dt[i] = NULL;
 }
 
 text_set_element (__libc_subinit, init_dtable);
+
+/* XXX when the linker supports it, the following functions should all be
+   elsewhere and just have text_set_elements here.  */
 \f
 /* Called by `getdport' to do its work.  */
 
@@ -122,6 +125,7 @@ get_dtable_port (int fd)
 
 text_set_element (_hurd_getdport_fn, get_dtable_port);
 \f
+#if 0
 /* Called on fork to install the dtable in NEWTASK.
    The dtable lock is held.  */
 
@@ -135,19 +139,19 @@ fork_dtable (task_t newtask)
 
   for (i = 0; !err && i < _hurd_dtable.size; ++i)
     {
-      int dealloc, dealloc_ctty;
-      io_t port = _HURD_PORT_USE (&_hurd_dtable.d[i].port, &dealloc);
-      io_t ctty = _HURD_PORT_USE (&_hurd_dtable.d[i].ctty, &dealloc_ctty);
+      struct hurd_userlink ulink, ctty_ulink;
+      io_t port = _hurd_port_get (&_hurd_dtable.d[i].port, &ulink);
+      io_t ctty = _hurd_port_get (&_hurd_dtable.d[i].ctty, &ctty_ulink);
 
       if (port != MACH_PORT_NULL)
        err = __mach_port_insert_right (newtask, port, port,
-                                       MACH_PORT_COPY_SEND);
+                                       MACH_MSG_TYPE_COPY_SEND);
       if (!err && ctty != MACH_PORT_NULL)
        err = __mach_port_insert_right (newtask, ctty, ctty,
-                                       MACH_PORT_COPY_SEND);
+                                       MACH_MSG_TYPE_COPY_SEND);
 
-      _hurd_port_free (port, &dealloc);
-      _hurd_port_free (ctty, &dealloc_ctty);
+      _hurd_port_free (&_hurd_dtable.d[i].port, &ulink, port);
+      _hurd_port_free (&_hurd_dtable.d[i].ctty, &ctty_ulink, ctty);
 
       /* XXX for each fd with a cntlmap, reauth and re-map_cntl.  */
     }
@@ -157,50 +161,160 @@ fork_dtable (task_t newtask)
 
 text_set_element (_hurd_fork_hook, fork_dtable);
 text_set_element (_hurd_fork_locks, _hurd_dtable_lock);
+#endif
 \f
 /* Called to reauthenticate the dtable when the auth port changes.  */
 
 static void
 reauth_dtable (void)
 {
-  int d;
+  int i;
 
   __mutex_lock (&_hurd_dtable_lock);
 
-  for (d = 0; d < _hurd_dtable.size; ++d)
+  for (i = 0; i < _hurd_dtable.size; ++i)
     {
-      struct _hurd_fd *const d = &hurd_dtable.d[d];
+      struct hurd_fd *const d = _hurd_dtable.d[i];
       mach_port_t new, newctty;
       
+      if (d == NULL)
+       /* Nothing to do for an unused descriptor cell.  */
+       continue;
+
       /* Take the descriptor cell's lock.  */
-      __spin_lock (&cell->port.lock);
+      __spin_lock (&d->port.lock);
       
       /* Reauthenticate the descriptor's port.  */
-      if (cell->port.port != MACH_PORT_NULL &&
-         ! __io_reauthenticate (cell->port.port) &&
-         ! _HURD_PORT_USE (&_hurd_auth,
-                           __auth_user_authenticate (port,
-                                                     cell->port.port, &new)))
+      if (d->port.port != MACH_PORT_NULL &&
+         ! __io_reauthenticate (d->port.port, _hurd_pid) &&
+         ! __USEPORT (AUTH, __auth_user_authenticate (port,
+                                                      d->port.port, _hurd_pid,
+                                                      &new)))
        {
          /* Replace the port in the descriptor cell
             with the newly reauthenticated port.  */
 
-         if (cell->ctty.port != MACH_PORT_NULL &&
-             ! __io_reauthenticate (cell->ctty.port) &&
-             ! _HURD_PORT_USE (&_hurd_auth,
-                               __auth_user_authenticate (port,
-                                                         cell->ctty.port,
-                                                         &newctty)))
-           _hurd_port_set (&cell->ctty, newctty);
+         if (d->ctty.port != MACH_PORT_NULL &&
+             ! __io_reauthenticate (d->ctty.port, _hurd_pid) &&
+             ! __USEPORT (AUTH, __auth_user_authenticate (port,
+                                                          d->ctty.port,
+                                                          _hurd_pid,
+                                                          &newctty)))
+           _hurd_port_set (&d->ctty, newctty);
 
-         _hurd_port_locked_set (&cell->port, new);
+         _hurd_port_locked_set (&d->port, new);
        }
       else
        /* Lost.  Leave this descriptor cell alone.  */
-       __spin_unlock (&cell->port.lock);
+       __spin_unlock (&d->port.lock);
     }
 
   __mutex_unlock (&_hurd_dtable_lock);
 }
 
 text_set_element (_hurd_reauth_hook, reauth_dtable);
+\f
+static void
+rectty_dtable (mach_port_t cttyid)
+{
+  int i;
+  
+  __mutex_lock (&_hurd_dtable_lock);
+
+  for (i = 0; i < _hurd_dtable.size; ++i)
+    {
+      struct hurd_fd *const d = _hurd_dtable.d[i];
+      mach_port_t newctty;
+
+      if (d == NULL)
+       /* Nothing to do for an unused descriptor cell.  */
+       continue;
+
+      if (cttyid == MACH_PORT_NULL)
+       /* We now have no controlling tty at all.  */
+       newctty = MACH_PORT_NULL;
+      else
+       _HURD_PORT_USE (&d->port,
+                       ({ mach_port_t id;
+                          /* Get the io object's cttyid port.  */
+                          if (! __term_getctty (port, &id))
+                            {
+                              if (id == cttyid && /* Is it ours?  */
+                                  /* Get the ctty io port.  */
+                                  __term_become_ctty (port, _hurd_pid,
+                                                      _hurd_pgrp,
+                                                      _hurd_msgport,
+                                                      &newctty))
+                                /* XXX it is our ctty but the call failed? */
+                                newctty = MACH_PORT_NULL;
+                              __mach_port_deallocate
+                                (__mach_task_self (), (mach_port_t) id);
+                            }
+                          else
+                            newctty = MACH_PORT_NULL;
+                          0;
+                        }));
+
+      /* Install the new ctty port.  */
+      _hurd_port_set (&d->ctty, newctty);
+    }
+
+  __mutex_unlock (&_hurd_dtable_lock);
+}
+\f
+#if 0
+
+#include <sys/ioctl.h>
+
+
+/* Make FD be the controlling terminal.
+   This function is called for `ioctl (fd, TCIOSCTTY)'.  */
+
+static int
+tiocsctty (int fd,
+          int request,         /* Always TCIOSCTTY.  */
+          void *arg)           /* Not used.  */
+{
+  mach_port_t cttyid;
+  error_t err;
+
+  /* Get FD's cttyid port, unless it is already ours.  */
+  err = _HURD_DPORT_USE (fd,
+                        ctty ? EADDRINUSE : __term_getctty (port, &cttyid));
+  if (err == EADDRINUSE)
+    /* FD is already the ctty.  Nothing to do.  */
+    return 0;
+  else if (err)
+    return err;
+
+  /* Make it our own.  */
+  _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], cttyid); /* Consumes ref.  */
+
+  /* Reset all the ctty ports in all the descriptors.  */
+  _HURD_PORT_USE (&_hurd_ports[INIT_PORT_CTTYID], (rectty_dtable (port), 0));
+
+  return 0;
+}
+_HURD_HANDLE_IOCTL (tiocsctty, TIOCSCTTY);
+
+/* Dissociate from the controlling terminal.  */
+
+static int
+tiocnotty (int fd,
+          int request,         /* Always TIOCNOTTY.  */
+          void *arg)           /* Not used.  */
+{
+  /* XXX should verify that FD is ctty and return EINVAL? */
+
+  /* Clear our cttyid port cell.  */
+  _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], MACH_PORT_NULL);
+
+  /* Reset all the ctty ports in all the descriptors.  */
+  _HURD_PORT_USE (&_hurd_ports[INIT_PORT_CTTYID],
+                 (rectty_dtable (MACH_PORT_NULL), 0));
+
+  return 0;
+}
+_HURD_HANDLE_IOCTL (tiocnotty, TIOCNOTTY);
+
+#endif