207 lines
5.7 KiB
C
207 lines
5.7 KiB
C
/* Copyright (C) 1991, 1992 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 <gnu-stabs.h>
|
||
#include <stdlib.h>
|
||
#include <limits.h>
|
||
|
||
|
||
struct _hurd_dtable _hurd_dtable;
|
||
struct mutex _hurd_dtable_lock;
|
||
int *_hurd_dtable_user_dealloc;
|
||
|
||
const struct _hurd_dtable_resizes _hurd_dtable_resizes;
|
||
|
||
|
||
/* Initialize the file descriptor table at startup. */
|
||
|
||
static void
|
||
init_dtable (void)
|
||
{
|
||
register size_t i;
|
||
|
||
__mutex_init (&_hurd_dtable_lock);
|
||
|
||
_hurd_dtable_user_dealloc = NULL;
|
||
|
||
/* The initial size of the descriptor table is that of the passed-in
|
||
table, rounded up to a multiple of OPEN_MAX descriptors. */
|
||
_hurd_dtable.size
|
||
= (_hurd_init_dtablesize + OPEN_MAX - 1) / OPEN_MAX * OPEN_MAX;
|
||
|
||
_hurd_dtable.d = malloc (_hurd_dtable.size * sizeof (*_hurd_dtable.d));
|
||
if (_hurd_dtable.d == NULL)
|
||
__libc_fatal ("hurd: Can't allocate file descriptor table\n");
|
||
|
||
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))
|
||
{
|
||
/* Operations on CTTY return EBACKGROUND when we are not a
|
||
foreground user of the tty. */
|
||
d->port.port = ctty;
|
||
ctty = _hurd_init_dtable[i];
|
||
}
|
||
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,
|
||
_hurd_init_dtablesize * sizeof (_hurd_init_dtable[0]));
|
||
_hurd_init_dtable = NULL;
|
||
_hurd_init_dtablesize = 0;
|
||
}
|
||
|
||
text_set_element (__libc_subinit, init_dtable);
|
||
|
||
/* 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;
|
||
}
|
||
|
||
text_set_element (_hurd_getdport_fn, get_dtable_port);
|
||
|
||
/* Called on fork to install the dtable in NEWTASK.
|
||
The dtable lock is held. */
|
||
|
||
static error_t
|
||
fork_dtable (task_t newtask)
|
||
{
|
||
error_t err;
|
||
int i;
|
||
|
||
err = 0;
|
||
|
||
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);
|
||
|
||
if (port != MACH_PORT_NULL)
|
||
err = __mach_port_insert_right (newtask, port, port,
|
||
MACH_PORT_COPY_SEND);
|
||
if (!err && ctty != MACH_PORT_NULL)
|
||
err = __mach_port_insert_right (newtask, ctty, ctty,
|
||
MACH_PORT_COPY_SEND);
|
||
|
||
_hurd_port_free (port, &dealloc);
|
||
_hurd_port_free (ctty, &dealloc_ctty);
|
||
|
||
/* XXX for each fd with a cntlmap, reauth and re-map_cntl. */
|
||
}
|
||
__mutex_unlock (&_hurd_dtable_lock);
|
||
return err;
|
||
}
|
||
|
||
text_set_element (_hurd_fork_hook, fork_dtable);
|
||
text_set_element (_hurd_fork_locks, _hurd_dtable_lock);
|
||
|
||
/* Called to reauthenticate the dtable when the auth port changes. */
|
||
|
||
static void
|
||
reauth_dtable (void)
|
||
{
|
||
int d;
|
||
|
||
__mutex_lock (&_hurd_dtable_lock);
|
||
|
||
for (d = 0; d < _hurd_dtable.size; ++d)
|
||
{
|
||
struct _hurd_fd *const d = &hurd_dtable.d[d];
|
||
mach_port_t new, newctty;
|
||
|
||
/* Take the descriptor cell's lock. */
|
||
__spin_lock (&cell->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)))
|
||
{
|
||
/* 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);
|
||
|
||
_hurd_port_locked_set (&cell->port, new);
|
||
}
|
||
else
|
||
/* Lost. Leave this descriptor cell alone. */
|
||
__spin_unlock (&cell->port.lock);
|
||
}
|
||
|
||
__mutex_unlock (&_hurd_dtable_lock);
|
||
}
|
||
|
||
text_set_element (_hurd_reauth_hook, reauth_dtable);
|