Formerly ../hurd/dtable.c.~24~
[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
29
30 #ifdef noteven
31 struct mutex _hurd_dtable_lock;
32 #endif
33 struct hurd_dtable _hurd_dtable;
34 int _hurd_dtable_rlimit;
35 struct hurd_userlink *_hurd_dtable_users;
36
37 const struct _hurd_dtable_resizes _hurd_dtable_resizes;
38
39
40 /* Initialize the file descriptor table at startup.  */
41
42 static void
43 init_dtable (void)
44 {
45   register size_t i;
46   struct hurd_fd **dt;
47
48 #ifdef noteven
49   __mutex_init (&_hurd_dtable_lock);
50 #endif
51
52   _hurd_dtable_users = NULL;
53
54   /* The initial size of the descriptor table is that of the passed-in
55      table, rounded up to a multiple of FOPEN_MAX descriptors.  */
56   _hurd_dtable.size
57     = (_hurd_init_dtablesize + FOPEN_MAX - 1) / FOPEN_MAX * FOPEN_MAX;
58   _hurd_dtable_rlimit = _hurd_dtable.size;
59
60   /* Allocate the vector of pointers.  */
61   dt = _hurd_dtable.d = malloc (_hurd_dtable.size * sizeof (*_hurd_dtable.d));
62   if (dt == NULL)
63     __libc_fatal ("hurd: Can't allocate file descriptor table\n");
64
65   /* Initialize the descriptor table.  */
66   for (i = 0; i < _hurd_init_dtablesize; ++i)
67     {
68       if (_hurd_init_dtable[i] == MACH_PORT_NULL)
69         /* An unused descriptor is marked by a null pointer.  */
70         dt[i] = NULL;
71       else
72         {
73           /* Allocate a new file descriptor structure.  */
74           struct hurd_fd *new = malloc (sizeof (struct hurd_fd));
75           if (new == NULL)
76             __libc_fatal ("hurd: Can't allocate initial file descriptors\n");
77
78           /* Initialize the port cells.  */
79           _hurd_port_init (&new->port, MACH_PORT_NULL);
80           _hurd_port_init (&new->ctty, MACH_PORT_NULL);
81
82           /* Install the port in the descriptor.
83              This sets up all the ctty magic.  */
84           _hurd_port2fd (new, _hurd_init_dtable[i], 0);
85         }
86     }
87
88   /* Clear out the initial descriptor table.
89      Everything must use _hurd_dtable now.  */
90   __vm_deallocate (__mach_task_self (),
91                    (vm_address_t) _hurd_init_dtable,
92                    _hurd_init_dtablesize * sizeof (_hurd_init_dtable[0]));
93   _hurd_init_dtable = NULL;
94   _hurd_init_dtablesize = 0;
95
96   /* Initialize the remaining empty slots in the table.  */
97   for (; i < _hurd_dtable.size; ++i)
98     dt[i] = NULL;
99 }
100
101 text_set_element (__libc_subinit, init_dtable);
102
103 /* XXX when the linker supports it, the following functions should all be
104    elsewhere and just have text_set_elements here.  */
105 \f
106 /* Called by `getdport' to do its work.  */
107
108 static file_t
109 get_dtable_port (int fd)
110 {
111   file_t dport;
112   int err = _HURD_DPORT_USE (fd,
113                              __mach_port_mod_refs (__mach_task_self (),
114                                                    (dport = 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 text_set_element (_hurd_getdport_fn, get_dtable_port);
127 \f
128 #if 0
129 /* Called on fork to install the dtable in NEWTASK.
130    The dtable lock is held.  */
131
132 static error_t
133 fork_dtable (task_t newtask)
134 {
135   error_t err;
136   int i;
137
138   err = 0;
139
140   for (i = 0; !err && i < _hurd_dtable.size; ++i)
141     {
142       struct hurd_userlink ulink, ctty_ulink;
143       io_t port = _hurd_port_get (&_hurd_dtable.d[i].port, &ulink);
144       io_t ctty = _hurd_port_get (&_hurd_dtable.d[i].ctty, &ctty_ulink);
145
146       if (port != MACH_PORT_NULL)
147         err = __mach_port_insert_right (newtask, port, port,
148                                         MACH_MSG_TYPE_COPY_SEND);
149       if (!err && ctty != MACH_PORT_NULL)
150         err = __mach_port_insert_right (newtask, ctty, ctty,
151                                         MACH_MSG_TYPE_COPY_SEND);
152
153       _hurd_port_free (&_hurd_dtable.d[i].port, &ulink, port);
154       _hurd_port_free (&_hurd_dtable.d[i].ctty, &ctty_ulink, ctty);
155
156       /* XXX for each fd with a cntlmap, reauth and re-map_cntl.  */
157     }
158   __mutex_unlock (&_hurd_dtable_lock);
159   return err;
160 }
161
162 text_set_element (_hurd_fork_hook, fork_dtable);
163 text_set_element (_hurd_fork_locks, _hurd_dtable_lock);
164 #endif
165 \f
166 /* Called to reauthenticate the dtable when the auth port changes.  */
167
168 static void
169 reauth_dtable (void)
170 {
171   int i;
172
173   __mutex_lock (&_hurd_dtable_lock);
174
175   for (i = 0; i < _hurd_dtable.size; ++i)
176     {
177       struct hurd_fd *const d = _hurd_dtable.d[i];
178       mach_port_t new, newctty;
179       
180       if (d == NULL)
181         /* Nothing to do for an unused descriptor cell.  */
182         continue;
183
184       /* Take the descriptor cell's lock.  */
185       __spin_lock (&d->port.lock);
186       
187       /* Reauthenticate the descriptor's port.  */
188       if (d->port.port != MACH_PORT_NULL &&
189           ! __io_reauthenticate (d->port.port, _hurd_pid) &&
190           ! __USEPORT (AUTH, __auth_user_authenticate (port,
191                                                        d->port.port, _hurd_pid,
192                                                        &new)))
193         {
194           /* Replace the port in the descriptor cell
195              with the newly reauthenticated port.  */
196
197           if (d->ctty.port != MACH_PORT_NULL &&
198               ! __io_reauthenticate (d->ctty.port, _hurd_pid) &&
199               ! __USEPORT (AUTH, __auth_user_authenticate (port,
200                                                            d->ctty.port,
201                                                            _hurd_pid,
202                                                            &newctty)))
203             _hurd_port_set (&d->ctty, newctty);
204
205           _hurd_port_locked_set (&d->port, new);
206         }
207       else
208         /* Lost.  Leave this descriptor cell alone.  */
209         __spin_unlock (&d->port.lock);
210     }
211
212   __mutex_unlock (&_hurd_dtable_lock);
213 }
214
215 text_set_element (_hurd_reauth_hook, reauth_dtable);
216 \f
217 static void
218 rectty_dtable (mach_port_t cttyid)
219 {
220   int i;
221   
222   __mutex_lock (&_hurd_dtable_lock);
223
224   for (i = 0; i < _hurd_dtable.size; ++i)
225     {
226       struct hurd_fd *const d = _hurd_dtable.d[i];
227       mach_port_t newctty;
228
229       if (d == NULL)
230         /* Nothing to do for an unused descriptor cell.  */
231         continue;
232
233       if (cttyid == MACH_PORT_NULL)
234         /* We now have no controlling tty at all.  */
235         newctty = MACH_PORT_NULL;
236       else
237         _HURD_PORT_USE (&d->port,
238                         ({ mach_port_t id;
239                            /* Get the io object's cttyid port.  */
240                            if (! __term_getctty (port, &id))
241                              {
242                                if (id == cttyid && /* Is it ours?  */
243                                    /* Get the ctty io port.  */
244                                    __term_become_ctty (port, _hurd_pid,
245                                                        _hurd_pgrp,
246                                                        _hurd_msgport,
247                                                        &newctty))
248                                  /* XXX it is our ctty but the call failed? */
249                                  newctty = MACH_PORT_NULL;
250                                __mach_port_deallocate
251                                  (__mach_task_self (), (mach_port_t) id);
252                              }
253                            else
254                              newctty = MACH_PORT_NULL;
255                            0;
256                          }));
257
258       /* Install the new ctty port.  */
259       _hurd_port_set (&d->ctty, newctty);
260     }
261
262   __mutex_unlock (&_hurd_dtable_lock);
263 }
264 \f
265 #if 0
266
267 #include <sys/ioctl.h>
268
269
270 /* Make FD be the controlling terminal.
271    This function is called for `ioctl (fd, TCIOSCTTY)'.  */
272
273 static int
274 tiocsctty (int fd,
275            int request,         /* Always TCIOSCTTY.  */
276            void *arg)           /* Not used.  */
277 {
278   mach_port_t cttyid;
279   error_t err;
280
281   /* Get FD's cttyid port, unless it is already ours.  */
282   err = _HURD_DPORT_USE (fd,
283                          ctty ? EADDRINUSE : __term_getctty (port, &cttyid));
284   if (err == EADDRINUSE)
285     /* FD is already the ctty.  Nothing to do.  */
286     return 0;
287   else if (err)
288     return err;
289
290   /* Make it our own.  */
291   _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], cttyid); /* Consumes ref.  */
292
293   /* Reset all the ctty ports in all the descriptors.  */
294   _HURD_PORT_USE (&_hurd_ports[INIT_PORT_CTTYID], (rectty_dtable (port), 0));
295
296   return 0;
297 }
298 _HURD_HANDLE_IOCTL (tiocsctty, TIOCSCTTY);
299
300 /* Dissociate from the controlling terminal.  */
301
302 static int
303 tiocnotty (int fd,
304            int request,         /* Always TIOCNOTTY.  */
305            void *arg)           /* Not used.  */
306 {
307   /* XXX should verify that FD is ctty and return EINVAL? */
308
309   /* Clear our cttyid port cell.  */
310   _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], MACH_PORT_NULL);
311
312   /* Reset all the ctty ports in all the descriptors.  */
313   _HURD_PORT_USE (&_hurd_ports[INIT_PORT_CTTYID],
314                   (rectty_dtable (MACH_PORT_NULL), 0));
315
316   return 0;
317 }
318 _HURD_HANDLE_IOCTL (tiocnotty, TIOCNOTTY);
319
320 #endif