(linenum→info "unix/slp.c:2238")

glibc/2.7/hurd/dtable.c

    1: /* Copyright (C) 1991,92,93,94,95,96,97,99 Free Software Foundation, Inc.
    2:    This file is part of the GNU C Library.
    3: 
    4:    The GNU C Library is free software; you can redistribute it and/or
    5:    modify it under the terms of the GNU Lesser General Public
    6:    License as published by the Free Software Foundation; either
    7:    version 2.1 of the License, or (at your option) any later version.
    8: 
    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:    Lesser General Public License for more details.
   13: 
   14:    You should have received a copy of the GNU Lesser General Public
   15:    License along with the GNU C Library; if not, write to the Free
   16:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   17:    02111-1307 USA.  */
   18: 
   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 */
   29: 
   30: 
   31: struct mutex _hurd_dtable_lock = MUTEX_INITIALIZER; /* XXX ld bug; must init */
   32: struct hurd_fd **_hurd_dtable;
   33: int _hurd_dtablesize;
   34: 
   35: 
   36: DEFINE_HOOK (_hurd_fd_subinit, (void));
   37: 
   38: /* Initialize the file descriptor table at startup.  */
   39: 
   40: static void
   41: init_dtable (void)
   42: {
   43:   int i;
   44: 
   45:   __mutex_init (&_hurd_dtable_lock);
   46: 
   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;
   50: 
   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");
   55: 
   56:   /* Initialize the descriptor table.  */
   57:   for (i = 0; (unsigned int) i < _hurd_init_dtablesize; ++i)
   58:     {
   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
   63:         {
   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");
   68: 
   69:           /* Initialize the port cells.  */
   70:           _hurd_port_init (&new->port, MACH_PORT_NULL);
   71:           _hurd_port_init (&new->ctty, MACH_PORT_NULL);
   72: 
   73:           /* Install the port in the descriptor.
   74:              This sets up all the ctty magic.  */
   75:           _hurd_port2fd (new, _hurd_init_dtable[i], 0);
   76: 
   77:           _hurd_dtable[i] = new;
   78:         }
   79:     }
   80: 
   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;
   88: 
   89:   /* Initialize the remaining empty slots in the table.  */
   90:   for (; i < _hurd_dtablesize; ++i)
   91:     _hurd_dtable[i] = NULL;
   92: 
   93:   /* Run things that want to run after the file descriptor table
   94:      is initialized.  */
   95:   RUN_HOOK (_hurd_fd_subinit, ());
   96: 
   97:   (void) &init_dtable;          /* Avoid "defined but not used" warning.  */
   98: }
   99: 
  100: text_set_element (_hurd_subinit, init_dtable);
  101: 
  102: /* XXX when the linker supports it, the following functions should all be
  103:    elsewhere and just have text_set_elements here.  */
  104: ^L
  105: /* Called by `getdport' to do its work.  */
  106: 
  107: static file_t
  108: get_dtable_port (int fd)
  109: {
  110:   struct hurd_fd *d = _hurd_fd_get (fd);
  111:   file_t dport;
  112: 
  113:   if (!d)
  114:     return __hurd_fail (EBADF), MACH_PORT_NULL;
  115: 
  116:   HURD_CRITICAL_BEGIN;
  117: 
  118:   dport = HURD_PORT_USE (&d->port,
  119:                          ({
  120:                            error_t err;
  121:                            mach_port_t outport;
  122:                            err = __mach_port_mod_refs (__mach_task_self (),
  123:                                                        port,
  124:                                                        MACH_PORT_RIGHT_SEND,
  125:                                                        1);
  126:                            if (err)
  127:                              {
  128:                                errno = err;
  129:                                outport = MACH_PORT_NULL;
  130:                              }
  131:                            else
  132:                              outport = port;
  133:                            outport;
  134:                          }));
  135: 
  136:   HURD_CRITICAL_END;
  137: 
  138:   return dport;
  139: }
  140: 
  141: file_t (*_hurd_getdport_fn) (int fd) = get_dtable_port;
  142: ^L
  143: #include <hurd/signal.h>
  144: 
  145: /* We are in the child fork; the dtable lock is still held.
  146:    The parent has inserted send rights for all the normal io ports,
  147:    but we must recover ctty-special ports for ourselves.  */
  148: static error_t
  149: fork_child_dtable (void)
  150: {
  151:   error_t err;
  152:   int i;
  153: 
  154:   err = 0;
  155: 
  156:   for (i = 0; !err && i < _hurd_dtablesize; ++i)
  157:     {
  158:       struct hurd_fd *d = _hurd_dtable[i];
  159:       if (d == NULL)
  160:         continue;
  161: 
  162:       /* No other thread is using the send rights in the child task.  */
  163:       d->port.users = d->ctty.users = NULL;
  164: 
  165:       if (d->ctty.port != MACH_PORT_NULL)
  166:         {
  167:           /* There was a ctty-special port in the parent.
  168:              We need to get one for ourselves too.  */
  169:           __mach_port_deallocate (__mach_task_self (), d->ctty.port);
  170:           err = __term_open_ctty (d->port.port, _hurd_pid, _hurd_pgrp,
  171:                                   &d->ctty.port);
  172:           if (err)
  173:             d->ctty.port = MACH_PORT_NULL;
  174:         }
  175: 
  176:       /* XXX for each fd with a cntlmap, reauth and re-map_cntl.  */
  177:     }
  178:   return err;
  179: 
  180:   (void) &fork_child_dtable;    /* Avoid "defined but not used" warning.  */
  181: }
  182: 
  183: data_set_element (_hurd_fork_locks, _hurd_dtable_lock); /* XXX ld bug: bss */
  184: text_set_element (_hurd_fork_child_hook, fork_child_dtable);
  185: ^L
  186: /* Called when our process group has changed.  */
  187: 
  188: static void
  189: ctty_new_pgrp (void)
  190: {
  191:   int i;
  192: 
  193:   HURD_CRITICAL_BEGIN;
  194:   __mutex_lock (&_hurd_dtable_lock);
  195: 
  196:   if (__USEPORT (CTTYID, port == MACH_PORT_NULL))
  197:     {
  198:       /* We have no controlling terminal.  If we haven't had one recently,
  199:          but our pgrp is being pointlessly diddled anyway, then we will
  200:          have nothing to do in the loop below because no fd will have a
  201:          ctty port at all.
  202: 
  203:          More likely, a setsid call is responsible both for the change
  204:          in pgrp and for clearing the cttyid port.  In that case, setsid
  205:          held the dtable lock while updating the dtable to clear all the
  206:          ctty ports, and ergo must have finished doing so before we run here.
  207:          So we can be sure, again, that the loop below has no work to do.  */
  208:     }
  209:   else
  210:     for (i = 0; i < _hurd_dtablesize; ++i)
  211:       {
  212:         struct hurd_fd *const d = _hurd_dtable[i];
  213:         struct hurd_userlink ulink, ctty_ulink;
  214:         io_t port, ctty;
  215: 
  216:         if (d == NULL)
  217:           /* Nothing to do for an unused descriptor cell.  */
  218:           continue;
  219: 
  220:         port = _hurd_port_get (&d->port, &ulink);
  221:         ctty = _hurd_port_get (&d->ctty, &ctty_ulink);
  222: 
  223:         if (ctty != MACH_PORT_NULL)
  224:           {
  225:             /* This fd has a ctty-special port.  We need a new one, to tell
  226:                the io server of our different process group.  */
  227:             io_t new;
  228:             if (__term_open_ctty (port, _hurd_pid, _hurd_pgrp, &new))
  229:               new = MACH_PORT_NULL;
  230:             _hurd_port_set (&d->ctty, new);
  231:           }
  232: 
  233:         _hurd_port_free (&d->port, &ulink, port);
  234:         _hurd_port_free (&d->ctty, &ctty_ulink, ctty);
  235:       }
  236: 
  237:   __mutex_unlock (&_hurd_dtable_lock);
  238:   HURD_CRITICAL_END;
  239: 
  240:   (void) &ctty_new_pgrp;        /* Avoid "defined but not used" warning.  */
  241: }
  242: 
  243: text_set_element (_hurd_pgrp_changed_hook, ctty_new_pgrp);
  244: ^L
  245: /* Called to reauthenticate the dtable when the auth port changes.  */
  246: 
  247: static void
  248: reauth_dtable (void)
  249: {
  250:   int i;
  251: 
  252:   HURD_CRITICAL_BEGIN;
  253:   __mutex_lock (&_hurd_dtable_lock);
  254: 
  255:   for (i = 0; i < _hurd_dtablesize; ++i)
  256:     {
  257:       struct hurd_fd *const d = _hurd_dtable[i];
  258:       mach_port_t new, newctty, ref;
  259: 
  260:       if (d == NULL)
  261:         /* Nothing to do for an unused descriptor cell.  */
  262:         continue;
  263: 
  264:       ref = __mach_reply_port ();
  265: 
  266:       /* Take the descriptor cell's lock.  */
  267:       __spin_lock (&d->port.lock);
  268: 
  269:       /* Reauthenticate the descriptor's port.  */
  270:       if (d->port.port != MACH_PORT_NULL &&
  271:           ! __io_reauthenticate (d->port.port,
  272:                                  ref, MACH_MSG_TYPE_MAKE_SEND) &&
  273:           ! __USEPORT (AUTH, __auth_user_authenticate
  274:                        (port,
  275:                         ref, MACH_MSG_TYPE_MAKE_SEND,
  276:                         &new)))
  277:         {
  278:           /* Replace the port in the descriptor cell
  279:              with the newly reauthenticated port.  */
  280: 
  281:           if (d->ctty.port != MACH_PORT_NULL &&
  282:               ! __io_reauthenticate (d->ctty.port,
  283:                                      ref, MACH_MSG_TYPE_MAKE_SEND) &&
  284:               ! __USEPORT (AUTH, __auth_user_authenticate
  285:                            (port,
  286:                             ref, MACH_MSG_TYPE_MAKE_SEND,
  287:                             &newctty)))
  288:             _hurd_port_set (&d->ctty, newctty);
  289: 
  290:           _hurd_port_locked_set (&d->port, new);
  291:         }
  292:       else
  293:         /* Lost.  Leave this descriptor cell alone.  */
  294:         __spin_unlock (&d->port.lock);
  295: 
  296:       __mach_port_destroy (__mach_task_self (), ref);
  297:     }
  298: 
  299:   __mutex_unlock (&_hurd_dtable_lock);
  300:   HURD_CRITICAL_END;
  301: 
  302:   (void) &reauth_dtable;        /* Avoid "defined but not used" warning.  */
  303: }
  304: 
  305: text_set_element (_hurd_reauth_hook, reauth_dtable);
Syntax (Markdown)