1 /* Copyright (C) 1991,92,93,94,95,96,97,99 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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.
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 not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
20 #include <hurd/term.h>
26 #include <cthreads.h> /* For `struct mutex'. */
27 #include "set-hooks.h"
28 #include "hurdmalloc.h" /* XXX */
31 struct mutex _hurd_dtable_lock
= MUTEX_INITIALIZER
; /* XXX ld bug; must init */
32 struct hurd_fd
**_hurd_dtable
;
36 DEFINE_HOOK (_hurd_fd_subinit
, (void));
38 /* Initialize the file descriptor table at startup. */
45 __mutex_init (&_hurd_dtable_lock
);
47 /* The initial size of the descriptor table is that of the passed-in
48 table. It will be expanded as necessary up to _hurd_dtable_rlimit. */
49 _hurd_dtablesize
= _hurd_init_dtablesize
;
51 /* Allocate the vector of pointers. */
52 _hurd_dtable
= malloc (_hurd_dtablesize
* sizeof (*_hurd_dtable
));
53 if (_hurd_dtablesize
!= 0 && _hurd_dtable
== NULL
)
54 __libc_fatal ("hurd: Can't allocate file descriptor table\n");
56 /* Initialize the descriptor table. */
57 for (i
= 0; (unsigned int) i
< _hurd_init_dtablesize
; ++i
)
59 if (_hurd_init_dtable
[i
] == MACH_PORT_NULL
)
60 /* An unused descriptor is marked by a null pointer. */
61 _hurd_dtable
[i
] = NULL
;
64 /* Allocate a new file descriptor structure. */
65 struct hurd_fd
*new = malloc (sizeof (struct hurd_fd
));
67 __libc_fatal ("hurd: Can't allocate initial file descriptors\n");
69 /* Initialize the port cells. */
70 _hurd_port_init (&new->port
, MACH_PORT_NULL
);
71 _hurd_port_init (&new->ctty
, MACH_PORT_NULL
);
73 /* Install the port in the descriptor.
74 This sets up all the ctty magic. */
75 _hurd_port2fd (new, _hurd_init_dtable
[i
], 0);
77 _hurd_dtable
[i
] = new;
81 /* Clear out the initial descriptor table.
82 Everything must use _hurd_dtable now. */
83 __vm_deallocate (__mach_task_self (),
84 (vm_address_t
) _hurd_init_dtable
,
85 _hurd_init_dtablesize
* sizeof (_hurd_init_dtable
[0]));
86 _hurd_init_dtable
= NULL
;
87 _hurd_init_dtablesize
= 0;
89 /* Initialize the remaining empty slots in the table. */
90 for (; i
< _hurd_dtablesize
; ++i
)
91 _hurd_dtable
[i
] = NULL
;
93 /* Run things that want to run after the file descriptor table
95 RUN_HOOK (_hurd_fd_subinit
, ());
97 (void) &init_dtable
; /* Avoid "defined but not used" warning. */
100 text_set_element (_hurd_subinit
, init_dtable
);
102 /* XXX when the linker supports it, the following functions should all be
103 elsewhere and just have text_set_elements here. */
105 /* Called by `getdport' to do its work. */
108 get_dtable_port (int fd
)
110 struct hurd_fd
*d
= _hurd_fd_get (fd
);
114 return __hurd_fail (EBADF
), MACH_PORT_NULL
;
118 dport
= HURD_PORT_USE (&d
->port
,
122 err
= __mach_port_mod_refs (__mach_task_self (),
124 MACH_PORT_RIGHT_SEND
,
129 outport
= MACH_PORT_NULL
;
141 file_t (*_hurd_getdport_fn
) (int fd
) = get_dtable_port
;
143 #include <hurd/signal.h>
145 /* We are in the child fork; the dtable lock is still held.
146 The parent has inserted send rights for all the normal io ports,
147 but we must recover ctty-special ports for ourselves. */
149 fork_child_dtable (void)
156 for (i
= 0; !err
&& i
< _hurd_dtablesize
; ++i
)
158 struct hurd_fd
*d
= _hurd_dtable
[i
];
162 /* No other thread is using the send rights in the child task. */
163 d
->port
.users
= d
->ctty
.users
= NULL
;
165 if (d
->ctty
.port
!= MACH_PORT_NULL
)
167 /* There was a ctty-special port in the parent.
168 We need to get one for ourselves too. */
169 __mach_port_deallocate (__mach_task_self (), d
->ctty
.port
);
170 err
= __term_open_ctty (d
->port
.port
, _hurd_pid
, _hurd_pgrp
,
173 d
->ctty
.port
= MACH_PORT_NULL
;
176 /* XXX for each fd with a cntlmap, reauth and re-map_cntl. */
180 (void) &fork_child_dtable
; /* Avoid "defined but not used" warning. */
183 data_set_element (_hurd_fork_locks
, _hurd_dtable_lock
); /* XXX ld bug: bss */
184 text_set_element (_hurd_fork_child_hook
, fork_child_dtable
);
186 /* Called when our process group has changed. */
194 __mutex_lock (&_hurd_dtable_lock
);
196 if (__USEPORT (CTTYID
, port
== MACH_PORT_NULL
))
198 /* We have no controlling terminal. If we haven't had one recently,
199 but our pgrp is being pointlessly diddled anyway, then we will
200 have nothing to do in the loop below because no fd will have a
203 More likely, a setsid call is responsible both for the change
204 in pgrp and for clearing the cttyid port. In that case, setsid
205 held the dtable lock while updating the dtable to clear all the
206 ctty ports, and ergo must have finished doing so before we run here.
207 So we can be sure, again, that the loop below has no work to do. */
210 for (i
= 0; i
< _hurd_dtablesize
; ++i
)
212 struct hurd_fd
*const d
= _hurd_dtable
[i
];
213 struct hurd_userlink ulink
, ctty_ulink
;
217 /* Nothing to do for an unused descriptor cell. */
220 port
= _hurd_port_get (&d
->port
, &ulink
);
221 ctty
= _hurd_port_get (&d
->ctty
, &ctty_ulink
);
223 if (ctty
!= MACH_PORT_NULL
)
225 /* This fd has a ctty-special port. We need a new one, to tell
226 the io server of our different process group. */
228 if (__term_open_ctty (port
, _hurd_pid
, _hurd_pgrp
, &new))
229 new = MACH_PORT_NULL
;
230 _hurd_port_set (&d
->ctty
, new);
233 _hurd_port_free (&d
->port
, &ulink
, port
);
234 _hurd_port_free (&d
->ctty
, &ctty_ulink
, ctty
);
237 __mutex_unlock (&_hurd_dtable_lock
);
240 (void) &ctty_new_pgrp
; /* Avoid "defined but not used" warning. */
243 text_set_element (_hurd_pgrp_changed_hook
, ctty_new_pgrp
);
245 /* Called to reauthenticate the dtable when the auth port changes. */
253 __mutex_lock (&_hurd_dtable_lock
);
255 for (i
= 0; i
< _hurd_dtablesize
; ++i
)
257 struct hurd_fd
*const d
= _hurd_dtable
[i
];
258 mach_port_t
new, newctty
, ref
;
261 /* Nothing to do for an unused descriptor cell. */
264 ref
= __mach_reply_port ();
266 /* Take the descriptor cell's lock. */
267 __spin_lock (&d
->port
.lock
);
269 /* Reauthenticate the descriptor's port. */
270 if (d
->port
.port
!= MACH_PORT_NULL
&&
271 ! __io_reauthenticate (d
->port
.port
,
272 ref
, MACH_MSG_TYPE_MAKE_SEND
) &&
273 ! __USEPORT (AUTH
, __auth_user_authenticate
275 ref
, MACH_MSG_TYPE_MAKE_SEND
,
278 /* Replace the port in the descriptor cell
279 with the newly reauthenticated port. */
281 if (d
->ctty
.port
!= MACH_PORT_NULL
&&
282 ! __io_reauthenticate (d
->ctty
.port
,
283 ref
, MACH_MSG_TYPE_MAKE_SEND
) &&
284 ! __USEPORT (AUTH
, __auth_user_authenticate
286 ref
, MACH_MSG_TYPE_MAKE_SEND
,
288 _hurd_port_set (&d
->ctty
, newctty
);
290 _hurd_port_locked_set (&d
->port
, new);
293 /* Lost. Leave this descriptor cell alone. */
294 __spin_unlock (&d
->port
.lock
);
296 __mach_port_destroy (__mach_task_self (), ref
);
299 __mutex_unlock (&_hurd_dtable_lock
);
302 (void) &reauth_dtable
; /* Avoid "defined but not used" warning. */
305 text_set_element (_hurd_reauth_hook
, reauth_dtable
);