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