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