]>
Commit | Line | Data |
---|---|---|
28f540f4 RM |
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 | { | |
1e9dc039 | 44 | int i; |
28f540f4 RM |
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. */ | |
1e9dc039 | 58 | for (i = 0; (unsigned int) i < _hurd_init_dtablesize; ++i) |
28f540f4 RM |
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); |