Formerly ../mach/Makefile.~16~
[kopensolaris-gnu/glibc.git] / hurd / dtable.c
1 /* Copyright (C) 1991, 1992 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 Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 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 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB.  If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA.  */
18
19 #include <ansidecl.h>
20 #include <hurd.h>
21 #include <gnu-stabs.h>
22 #include <stdlib.h>
23 #include <limits.h>
24
25
26 struct _hurd_dtable _hurd_dtable;
27 struct mutex _hurd_dtable_lock;
28 int _hurd_dtable_rlimit;
29 int *_hurd_dtable_user_dealloc;
30
31 const struct _hurd_dtable_resizes _hurd_dtable_resizes;
32
33
34 /* Initialize the file descriptor table at startup.  */
35
36 static void
37 init_dtable (void)
38 {
39   register size_t i;
40
41   __mutex_init (&_hurd_dtable_lock);
42
43   _hurd_dtable_user_dealloc = NULL;
44
45   /* The initial size of the descriptor table is that of the passed-in
46      table, rounded up to a multiple of OPEN_MAX descriptors.  */
47   _hurd_dtable.size
48     = (_hurd_init_dtablesize + OPEN_MAX - 1) / OPEN_MAX * OPEN_MAX;
49   _hurd_dtable_rlimit = _hurd_dtable.size;
50
51   _hurd_dtable.d = malloc (_hurd_dtable.size * sizeof (*_hurd_dtable.d));
52   if (_hurd_dtable.d == NULL)
53     __libc_fatal ("hurd: Can't allocate file descriptor table\n");
54
55   for (i = 0; i < _hurd_init_dtablesize; ++i)
56     {
57       struct _hurd_fd *const d = &_hurd_dtable.d[i];
58       io_statbuf_t stb;
59       io_t ctty;
60
61       _hurd_port_init (&d->port, _hurd_init_dtable[i]);
62       d->flags = 0;
63
64       if (_hurd_ctty_fstype != 0 &&
65           /* We have a controlling tty.  Is this it?  */
66           ! __io_stat (d->port.port, &stb) &&
67           stb.stb_fstype == _hurd_ctty_fstype &&
68           stb.stb_fsid == _hurd_ctty_fsid &&
69           stb.stb_fileid == _hurd_ctty_fileid &&
70           /* This is a descriptor to our controlling tty.  */
71           ! __term_become_ctty (d->port.port, _hurd_pid, _hurd_pgrp,
72                                 _hurd_sigport, &ctty))
73         {
74           /* Operations on CTTY return EBACKGROUND when we are not a
75              foreground user of the tty.  */
76           d->port.port = ctty;
77           ctty = _hurd_init_dtable[i];
78         }
79       else
80         /* No ctty magic happening here.  */
81         ctty = MACH_PORT_NULL;
82
83       _hurd_port_init (&d->ctty, ctty);
84     }
85
86   /* Initialize the remaining empty slots in the table.  */
87   for (; i < _hurd_dtable.size; ++i)
88     {
89       _hurd_port_init (&_hurd_dtable.d[i].port, MACH_PORT_NULL);
90       _hurd_port_init (&_hurd_dtable.d[i].ctty, MACH_PORT_NULL);
91       _hurd_dtable.d[i].flags = 0;
92     }
93
94   /* Clear out the initial descriptor table.
95      Everything must use _hurd_dtable now.  */
96   __vm_deallocate (__mach_task_self (),
97                    _hurd_init_dtable,
98                    _hurd_init_dtablesize * sizeof (_hurd_init_dtable[0]));
99   _hurd_init_dtable = NULL;
100   _hurd_init_dtablesize = 0;
101 }
102
103 text_set_element (__libc_subinit, init_dtable);
104 \f
105 /* Called by `getdport' to do its work.  */
106
107 static file_t
108 get_dtable_port (int fd)
109 {
110   file_t dport;
111   int err = _HURD_DPORT_USE (fd,
112                              __mach_port_mod_refs (__mach_task_self (),
113                                                    (dport = port),
114                                                    MACH_PORT_RIGHT_SEND,
115                                                    1));
116   if (err)
117     {
118       errno = err;
119       return MACH_PORT_NULL;
120     }
121   else
122     return dport;
123 }
124
125 text_set_element (_hurd_getdport_fn, get_dtable_port);
126 \f
127 /* Called on fork to install the dtable in NEWTASK.
128    The dtable lock is held.  */
129
130 static error_t
131 fork_dtable (task_t newtask)
132 {
133   error_t err;
134   int i;
135
136   err = 0;
137
138   for (i = 0; !err && i < _hurd_dtable.size; ++i)
139     {
140       int dealloc, dealloc_ctty;
141       io_t port = _HURD_PORT_USE (&_hurd_dtable.d[i].port, &dealloc);
142       io_t ctty = _HURD_PORT_USE (&_hurd_dtable.d[i].ctty, &dealloc_ctty);
143
144       if (port != MACH_PORT_NULL)
145         err = __mach_port_insert_right (newtask, port, port,
146                                         MACH_PORT_COPY_SEND);
147       if (!err && ctty != MACH_PORT_NULL)
148         err = __mach_port_insert_right (newtask, ctty, ctty,
149                                         MACH_PORT_COPY_SEND);
150
151       _hurd_port_free (port, &dealloc);
152       _hurd_port_free (ctty, &dealloc_ctty);
153
154       /* XXX for each fd with a cntlmap, reauth and re-map_cntl.  */
155     }
156   __mutex_unlock (&_hurd_dtable_lock);
157   return err;
158 }
159
160 text_set_element (_hurd_fork_hook, fork_dtable);
161 text_set_element (_hurd_fork_locks, _hurd_dtable_lock);
162 \f
163 /* Called to reauthenticate the dtable when the auth port changes.  */
164
165 static void
166 reauth_dtable (void)
167 {
168   int d;
169
170   __mutex_lock (&_hurd_dtable_lock);
171
172   for (d = 0; d < _hurd_dtable.size; ++d)
173     {
174       struct _hurd_fd *const d = &hurd_dtable.d[d];
175       mach_port_t new, newctty;
176       
177       /* Take the descriptor cell's lock.  */
178       __spin_lock (&cell->port.lock);
179       
180       /* Reauthenticate the descriptor's port.  */
181       if (cell->port.port != MACH_PORT_NULL &&
182           ! __io_reauthenticate (cell->port.port) &&
183           ! _HURD_PORT_USE (&_hurd_auth,
184                             __auth_user_authenticate (port,
185                                                       cell->port.port, &new)))
186         {
187           /* Replace the port in the descriptor cell
188              with the newly reauthenticated port.  */
189
190           if (cell->ctty.port != MACH_PORT_NULL &&
191               ! __io_reauthenticate (cell->ctty.port) &&
192               ! _HURD_PORT_USE (&_hurd_auth,
193                                 __auth_user_authenticate (port,
194                                                           cell->ctty.port,
195                                                           &newctty)))
196             _hurd_port_set (&cell->ctty, newctty);
197
198           _hurd_port_locked_set (&cell->port, new);
199         }
200       else
201         /* Lost.  Leave this descriptor cell alone.  */
202         __spin_unlock (&cell->port.lock);
203     }
204
205   __mutex_unlock (&_hurd_dtable_lock);
206 }
207
208 text_set_element (_hurd_reauth_hook, reauth_dtable);