Formerly ../hurd/dtable.c.~22~
[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 <gnu-stabs.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <fcntl.h>
26 #include <limits.h>
27
28
29 #ifdef noteven
30 struct mutex _hurd_dtable_lock;
31 #endif
32 struct _hurd_dtable _hurd_dtable;
33 int _hurd_dtable_rlimit;
34 struct hurd_userlink *_hurd_dtable_users;
35
36 const struct _hurd_dtable_resizes _hurd_dtable_resizes;
37
38
39 /* Initialize the file descriptor table at startup.  */
40
41 static void
42 init_dtable (void)
43 {
44   register size_t i;
45   struct hurd_fd **dt;
46
47 #ifdef noteven
48   __mutex_init (&_hurd_dtable_lock);
49 #endif
50
51   _hurd_dtable_users = NULL;
52
53   /* The initial size of the descriptor table is that of the passed-in
54      table, rounded up to a multiple of FOPEN_MAX descriptors.  */
55   _hurd_dtable.size
56     = (_hurd_init_dtablesize + FOPEN_MAX - 1) / FOPEN_MAX * FOPEN_MAX;
57   _hurd_dtable_rlimit = _hurd_dtable.size;
58
59   /* Allocate the vector of pointers.  */
60   dt = _hurd_dtable.d = malloc (_hurd_dtable.size * sizeof (*_hurd_dtable.d));
61   if (dt == NULL)
62     __libc_fatal ("hurd: Can't allocate file descriptor table\n");
63
64   /* Initialize the descriptor table.  */
65   for (i = 0; i < _hurd_init_dtablesize; ++i)
66     {
67       if (_hurd_init_dtable[i] == MACH_PORT_NULL)
68         /* An unused descriptor is marked by a null pointer.  */
69         dt[i] = NULL;
70       else
71         {
72           /* Allocate a new file descriptor structure.  */
73           struct _hurd_fd *new = malloc (sizeof (struct hurd_fd));
74           if (new == NULL)
75             __libc_fatal ("hurd: Can't allocate initial file descriptors\n");
76
77           /* Initialize the locks.  CTTY.lock is not used, but let's be
78              paranoid.  */
79           __spin_lock_init (&new->port.lock);
80           __spin_lock_init (&new->ctty.lock);
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_port_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