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