4812c69fafc9645647e08e6842b8420a53b26a0e
[kopensolaris-gnu/glibc.git] / hurd / dtable.c
1 /* Copyright (C) 1991, 1992, 1993, 1994 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 <hurd/term.h>
22 #include <hurd/fd.h>
23 #include <gnu-stabs.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <limits.h>
28 #include <cthreads.h>           /* For `struct mutex'.  */
29 #include "set-hooks.h"
30 #include "hurdmalloc.h"         /* XXX */
31
32
33 struct mutex _hurd_dtable_lock = MUTEX_INITIALIZER; /* XXX ld bug; must init */
34 struct hurd_fd **_hurd_dtable;
35 int _hurd_dtablesize;
36
37
38 DEFINE_HOOK (_hurd_fd_subinit, (void));
39
40 /* Initialize the file descriptor table at startup.  */
41
42 static void
43 init_dtable (void)
44 {
45   register size_t i;
46
47   __mutex_init (&_hurd_dtable_lock);
48
49   /* The initial size of the descriptor table is that of the passed-in
50      table.  It will be expanded as necessary up to _hurd_dtable_rlimit.  */
51   _hurd_dtablesize = _hurd_init_dtablesize;
52
53   /* Allocate the vector of pointers.  */
54   _hurd_dtable = malloc (_hurd_dtablesize * sizeof (*_hurd_dtable));
55   if (_hurd_dtablesize != 0 && _hurd_dtable == NULL)
56     __libc_fatal ("hurd: Can't allocate file descriptor table\n");
57
58   /* Initialize the descriptor table.  */
59   for (i = 0; i < _hurd_init_dtablesize; ++i)
60     {
61       if (_hurd_init_dtable[i] == MACH_PORT_NULL)
62         /* An unused descriptor is marked by a null pointer.  */
63         _hurd_dtable[i] = NULL;
64       else
65         {
66           /* Allocate a new file descriptor structure.  */
67           struct hurd_fd *new = malloc (sizeof (struct hurd_fd));
68           if (new == NULL)
69             __libc_fatal ("hurd: Can't allocate initial file descriptors\n");
70
71           /* Initialize the port cells.  */
72           _hurd_port_init (&new->port, MACH_PORT_NULL);
73           _hurd_port_init (&new->ctty, MACH_PORT_NULL);
74
75           /* Install the port in the descriptor.
76              This sets up all the ctty magic.  */
77           _hurd_port2fd (new, _hurd_init_dtable[i], 0);
78
79           _hurd_dtable[i] = new;
80         }
81     }
82
83   /* Clear out the initial descriptor table.
84      Everything must use _hurd_dtable now.  */
85   __vm_deallocate (__mach_task_self (),
86                    (vm_address_t) _hurd_init_dtable,
87                    _hurd_init_dtablesize * sizeof (_hurd_init_dtable[0]));
88   _hurd_init_dtable = NULL;
89   _hurd_init_dtablesize = 0;
90
91   /* Initialize the remaining empty slots in the table.  */
92   for (; i < _hurd_dtablesize; ++i)
93     _hurd_dtable[i] = NULL;
94
95   /* Run things that want to run after the file descriptor table
96      is initialized.  */
97   RUN_HOOK (_hurd_fd_subinit, ());
98
99   (void) &init_dtable;          /* Avoid "defined but not used" warning.  */
100 }
101
102 text_set_element (_hurd_subinit, init_dtable);
103
104 /* XXX when the linker supports it, the following functions should all be
105    elsewhere and just have text_set_elements here.  */
106 \f
107 /* Called by `getdport' to do its work.  */
108
109 static file_t
110 get_dtable_port (int fd)
111 {
112   file_t dport;
113   int err = HURD_DPORT_USE (fd, __mach_port_mod_refs (__mach_task_self (),
114                                                       (dport = ctty ?: port),
115                                                       MACH_PORT_RIGHT_SEND,
116                                                       1));
117   if (err)
118     {
119       errno = err;
120       return MACH_PORT_NULL;
121     }
122   else
123     return dport;
124 }
125
126 file_t (*_hurd_getdport_fn) (int fd) = get_dtable_port;
127 \f
128 #include <hurd/signal.h>
129
130 /* We are in the child fork; the dtable lock is still held.
131    The parent has inserted send rights for all the normal io ports,
132    but we must recover ctty-special ports for ourselves.  */
133 static error_t
134 fork_child_dtable (void)
135 {
136   error_t err;
137   int i;
138
139   err = 0;
140
141   for (i = 0; !err && i < _hurd_dtablesize; ++i)
142     {
143       struct hurd_fd *d = _hurd_dtable[i];
144       if (d == NULL)
145         continue;
146
147       /* No other thread is using the send rights in the child task.  */
148       d->port.users = d->ctty.users = NULL;
149
150       if (d->ctty.port != MACH_PORT_NULL)
151         {
152           /* There was a ctty-special port in the parent.
153              We need to get one for ourselves too.  */
154           __mach_port_deallocate (__mach_task_self (), d->port.port);
155           err = __term_open_ctty (d->ctty.port, _hurd_pid, _hurd_pgrp,
156                                   &d->port.port);
157           if (err)
158             {
159               d->port.port = d->ctty.port;
160               d->ctty.port = MACH_PORT_NULL;
161             }
162         }
163
164       /* XXX for each fd with a cntlmap, reauth and re-map_cntl.  */
165     }
166   return err;
167
168   (void) &fork_child_dtable;    /* Avoid "defined but not used" warning.  */
169 }
170
171 data_set_element (_hurd_fork_locks, _hurd_dtable_lock); /* XXX ld bug: bss */
172 text_set_element (_hurd_fork_child_hook, fork_child_dtable);
173 \f
174 /* Called when our process group has changed.  */
175
176 static void
177 ctty_new_pgrp (void)
178 {
179   int i;
180   
181   HURD_CRITICAL_BEGIN;
182   __mutex_lock (&_hurd_dtable_lock);
183
184   for (i = 0; i < _hurd_dtablesize; ++i)
185     {
186       struct hurd_fd *const d = _hurd_dtable[i];
187       struct hurd_userlink ulink, ctty_ulink;
188       io_t port, ctty;
189
190       if (d == NULL)
191         /* Nothing to do for an unused descriptor cell.  */
192         continue;
193
194       port = _hurd_port_get (&d->port, &ulink);
195       ctty = _hurd_port_get (&d->ctty, &ctty_ulink);
196
197       if (ctty)
198         {
199           /* This fd has a ctty-special port.  We need a new one, to tell
200              the io server of our different process group.  */
201           io_t new;
202           if (! __term_open_ctty (ctty, _hurd_pid, _hurd_pgrp, &new))
203             _hurd_port_set (&d->port, new);
204         }
205
206       _hurd_port_free (&d->port, &ulink, port);
207       _hurd_port_free (&d->ctty, &ctty_ulink, ctty);
208     }
209
210   __mutex_unlock (&_hurd_dtable_lock);
211   HURD_CRITICAL_END;
212
213   (void) &ctty_new_pgrp;        /* Avoid "defined but not used" warning.  */
214 }
215
216 text_set_element (_hurd_pgrp_changed_hook, ctty_new_pgrp);
217 \f
218 /* Called to reauthenticate the dtable when the auth port changes.  */
219
220 static void
221 reauth_dtable (void)
222 {
223   int i;
224
225   HURD_CRITICAL_BEGIN;
226   __mutex_lock (&_hurd_dtable_lock);
227
228   for (i = 0; i < _hurd_dtablesize; ++i)
229     {
230       struct hurd_fd *const d = _hurd_dtable[i];
231       mach_port_t new, newctty;
232       
233       if (d == NULL)
234         /* Nothing to do for an unused descriptor cell.  */
235         continue;
236
237       /* Take the descriptor cell's lock.  */
238       __spin_lock (&d->port.lock);
239       
240       /* Reauthenticate the descriptor's port.  */
241       if (d->port.port != MACH_PORT_NULL &&
242           ! __io_reauthenticate (d->port.port, _hurd_pid) &&
243           ! __USEPORT (AUTH, __auth_user_authenticate (port,
244                                                        d->port.port, _hurd_pid,
245                                                        &new)))
246         {
247           /* Replace the port in the descriptor cell
248              with the newly reauthenticated port.  */
249
250           if (d->ctty.port != MACH_PORT_NULL &&
251               ! __io_reauthenticate (d->ctty.port, _hurd_pid) &&
252               ! __USEPORT (AUTH, __auth_user_authenticate (port,
253                                                            d->ctty.port,
254                                                            _hurd_pid,
255                                                            &newctty)))
256             _hurd_port_set (&d->ctty, newctty);
257
258           _hurd_port_locked_set (&d->port, new);
259         }
260       else
261         /* Lost.  Leave this descriptor cell alone.  */
262         __spin_unlock (&d->port.lock);
263     }
264
265   __mutex_unlock (&_hurd_dtable_lock);
266   HURD_CRITICAL_END;
267
268   (void) &reauth_dtable;        /* Avoid "defined but not used" warning.  */
269 }
270
271 text_set_element (_hurd_reauth_hook, reauth_dtable);