Formerly ../hurd/dtable.c.~26~
[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 void (*_hurd_dtable_deallocate) (void *);
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, __mach_port_mod_refs (__mach_task_self (),
113                                                       (dport = port),
114                                                       MACH_PORT_RIGHT_SEND,
115                                                       1));
116   if (err)
117     {
118       errno = err;
119       return MACH_PORT_NULL;
120     }
121   else
122     return dport;
123 }
124
125 text_set_element (_hurd_getdport_fn, get_dtable_port);
126 \f
127 #if 0
128 /* Called on fork to install the dtable in NEWTASK.
129    The dtable lock is held.  */
130
131 static error_t
132 fork_dtable (task_t newtask)
133 {
134   error_t err;
135   int i;
136
137   err = 0;
138
139   for (i = 0; !err && i < _hurd_dtable.size; ++i)
140     {
141       struct hurd_userlink ulink, ctty_ulink;
142       io_t port = _hurd_port_get (&_hurd_dtable.d[i].port, &ulink);
143       io_t ctty = _hurd_port_get (&_hurd_dtable.d[i].ctty, &ctty_ulink);
144
145       if (port != MACH_PORT_NULL)
146         err = __mach_port_insert_right (newtask, port, port,
147                                         MACH_MSG_TYPE_COPY_SEND);
148       if (!err && ctty != MACH_PORT_NULL)
149         err = __mach_port_insert_right (newtask, ctty, ctty,
150                                         MACH_MSG_TYPE_COPY_SEND);
151
152       _hurd_port_free (&_hurd_dtable.d[i].port, &ulink, port);
153       _hurd_port_free (&_hurd_dtable.d[i].ctty, &ctty_ulink, ctty);
154
155       /* XXX for each fd with a cntlmap, reauth and re-map_cntl.  */
156     }
157   __mutex_unlock (&_hurd_dtable_lock);
158   return err;
159 }
160
161 text_set_element (_hurd_fork_hook, fork_dtable);
162 text_set_element (_hurd_fork_locks, _hurd_dtable_lock);
163 #endif
164 \f
165 /* Called to reauthenticate the dtable when the auth port changes.  */
166
167 static void
168 reauth_dtable (void)
169 {
170   int i;
171
172   __mutex_lock (&_hurd_dtable_lock);
173
174   for (i = 0; i < _hurd_dtable.size; ++i)
175     {
176       struct hurd_fd *const d = _hurd_dtable.d[i];
177       mach_port_t new, newctty;
178       
179       if (d == NULL)
180         /* Nothing to do for an unused descriptor cell.  */
181         continue;
182
183       /* Take the descriptor cell's lock.  */
184       __spin_lock (&d->port.lock);
185       
186       /* Reauthenticate the descriptor's port.  */
187       if (d->port.port != MACH_PORT_NULL &&
188           ! __io_reauthenticate (d->port.port, _hurd_pid) &&
189           ! __USEPORT (AUTH, __auth_user_authenticate (port,
190                                                        d->port.port, _hurd_pid,
191                                                        &new)))
192         {
193           /* Replace the port in the descriptor cell
194              with the newly reauthenticated port.  */
195
196           if (d->ctty.port != MACH_PORT_NULL &&
197               ! __io_reauthenticate (d->ctty.port, _hurd_pid) &&
198               ! __USEPORT (AUTH, __auth_user_authenticate (port,
199                                                            d->ctty.port,
200                                                            _hurd_pid,
201                                                            &newctty)))
202             _hurd_port_set (&d->ctty, newctty);
203
204           _hurd_port_locked_set (&d->port, new);
205         }
206       else
207         /* Lost.  Leave this descriptor cell alone.  */
208         __spin_unlock (&d->port.lock);
209     }
210
211   __mutex_unlock (&_hurd_dtable_lock);
212 }
213
214 text_set_element (_hurd_reauth_hook, reauth_dtable);
215 \f
216 #include <hurd/signal.h>
217
218 static void
219 rectty_dtable (mach_port_t cttyid)
220 {
221   int i;
222   
223   __mutex_lock (&_hurd_dtable_lock);
224
225   for (i = 0; i < _hurd_dtable.size; ++i)
226     {
227       struct hurd_fd *const d = _hurd_dtable.d[i];
228       mach_port_t newctty;
229
230       if (d == NULL)
231         /* Nothing to do for an unused descriptor cell.  */
232         continue;
233
234       if (cttyid == MACH_PORT_NULL)
235         /* We now have no controlling tty at all.  */
236         newctty = MACH_PORT_NULL;
237       else
238         HURD_PORT_USE (&d->port,
239                        ({ mach_port_t id;
240                           /* Get the io object's cttyid port.  */
241                           if (! __term_getctty (port, &id))
242                             {
243                               if (id == cttyid && /* Is it ours?  */
244                                   /* Get the ctty io port.  */
245                                   __term_become_ctty (port, _hurd_pid,
246                                                       _hurd_pgrp,
247                                                       _hurd_msgport,
248                                                       &newctty))
249                                 /* XXX it is our ctty but the call failed? */
250                                 newctty = MACH_PORT_NULL;
251                               __mach_port_deallocate
252                                 (__mach_task_self (), (mach_port_t) id);
253                             }
254                           else
255                             newctty = MACH_PORT_NULL;
256                           0;
257                         }));
258
259       /* Install the new ctty port.  */
260       _hurd_port_set (&d->ctty, newctty);
261     }
262
263   __mutex_unlock (&_hurd_dtable_lock);
264 }
265 \f
266 #if 0
267
268 #include <sys/ioctl.h>
269
270
271 /* Make FD be the controlling terminal.
272    This function is called for `ioctl (fd, TCIOSCTTY)'.  */
273
274 static int
275 tiocsctty (int fd,
276            int request,         /* Always TCIOSCTTY.  */
277            void *arg)           /* Not used.  */
278 {
279   mach_port_t cttyid;
280   error_t err;
281
282   /* Get FD's cttyid port, unless it is already ours.  */
283   err = _HURD_DPORT_USE (fd,
284                          ctty ? EADDRINUSE : __term_getctty (port, &cttyid));
285   if (err == EADDRINUSE)
286     /* FD is already the ctty.  Nothing to do.  */
287     return 0;
288   else if (err)
289     return err;
290
291   /* Make it our own.  */
292   _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], cttyid); /* Consumes ref.  */
293
294   /* Reset all the ctty ports in all the descriptors.  */
295   _HURD_PORT_USE (&_hurd_ports[INIT_PORT_CTTYID], (rectty_dtable (port), 0));
296
297   return 0;
298 }
299 _HURD_HANDLE_IOCTL (tiocsctty, TIOCSCTTY);
300
301 /* Dissociate from the controlling terminal.  */
302
303 static int
304 tiocnotty (int fd,
305            int request,         /* Always TIOCNOTTY.  */
306            void *arg)           /* Not used.  */
307 {
308   /* XXX should verify that FD is ctty and return EINVAL? */
309
310   /* Clear our cttyid port cell.  */
311   _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], MACH_PORT_NULL);
312
313   /* Reset all the ctty ports in all the descriptors.  */
314   _HURD_PORT_USE (&_hurd_ports[INIT_PORT_CTTYID],
315                   (rectty_dtable (MACH_PORT_NULL), 0));
316
317   return 0;
318 }
319 _HURD_HANDLE_IOCTL (tiocnotty, TIOCNOTTY);
320
321 #endif