1 /* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996 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
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA. */
21 #include <hurd/term.h>
27 #include <cthreads.h> /* For `struct mutex'. */
28 #include "set-hooks.h"
29 #include "hurdmalloc.h" /* XXX */
32 struct mutex _hurd_dtable_lock
= MUTEX_INITIALIZER
; /* XXX ld bug; must init */
33 struct hurd_fd
**_hurd_dtable
;
37 DEFINE_HOOK (_hurd_fd_subinit
, (void));
39 /* Initialize the file descriptor table at startup. */
46 __mutex_init (&_hurd_dtable_lock
);
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
;
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");
57 /* Initialize the descriptor table. */
58 for (i
= 0; (unsigned int) i
< _hurd_init_dtablesize
; ++i
)
60 if (_hurd_init_dtable
[i
] == MACH_PORT_NULL
)
61 /* An unused descriptor is marked by a null pointer. */
62 _hurd_dtable
[i
] = NULL
;
65 /* Allocate a new file descriptor structure. */
66 struct hurd_fd
*new = malloc (sizeof (struct hurd_fd
));
68 __libc_fatal ("hurd: Can't allocate initial file descriptors\n");
70 /* Initialize the port cells. */
71 _hurd_port_init (&new->port
, MACH_PORT_NULL
);
72 _hurd_port_init (&new->ctty
, MACH_PORT_NULL
);
74 /* Install the port in the descriptor.
75 This sets up all the ctty magic. */
76 _hurd_port2fd (new, _hurd_init_dtable
[i
], 0);
78 _hurd_dtable
[i
] = new;
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;
90 /* Initialize the remaining empty slots in the table. */
91 for (; i
< _hurd_dtablesize
; ++i
)
92 _hurd_dtable
[i
] = NULL
;
94 /* Run things that want to run after the file descriptor table
96 RUN_HOOK (_hurd_fd_subinit
, ());
98 (void) &init_dtable
; /* Avoid "defined but not used" warning. */
101 text_set_element (_hurd_subinit
, init_dtable
);
103 /* XXX when the linker supports it, the following functions should all be
104 elsewhere and just have text_set_elements here. */
106 /* Called by `getdport' to do its work. */
109 get_dtable_port (int fd
)
112 int err
= HURD_DPORT_USE (fd
, __mach_port_mod_refs (__mach_task_self (),
114 MACH_PORT_RIGHT_SEND
,
119 return MACH_PORT_NULL
;
125 file_t (*_hurd_getdport_fn
) (int fd
) = get_dtable_port
;
127 #include <hurd/signal.h>
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. */
133 fork_child_dtable (void)
140 for (i
= 0; !err
&& i
< _hurd_dtablesize
; ++i
)
142 struct hurd_fd
*d
= _hurd_dtable
[i
];
146 /* No other thread is using the send rights in the child task. */
147 d
->port
.users
= d
->ctty
.users
= NULL
;
149 if (d
->ctty
.port
!= MACH_PORT_NULL
)
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
,
157 d
->ctty
.port
= MACH_PORT_NULL
;
160 /* XXX for each fd with a cntlmap, reauth and re-map_cntl. */
164 (void) &fork_child_dtable
; /* Avoid "defined but not used" warning. */
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
);
170 /* Called when our process group has changed. */
178 __mutex_lock (&_hurd_dtable_lock
);
180 for (i
= 0; i
< _hurd_dtablesize
; ++i
)
182 struct hurd_fd
*const d
= _hurd_dtable
[i
];
183 struct hurd_userlink ulink
, ctty_ulink
;
187 /* Nothing to do for an unused descriptor cell. */
190 port
= _hurd_port_get (&d
->port
, &ulink
);
191 ctty
= _hurd_port_get (&d
->ctty
, &ctty_ulink
);
193 if (ctty
!= MACH_PORT_NULL
)
195 /* This fd has a ctty-special port. We need a new one, to tell
196 the io server of our different process group. */
198 if (__term_open_ctty (port
, _hurd_pid
, _hurd_pgrp
, &new))
199 new = MACH_PORT_NULL
;
200 _hurd_port_set (&d
->ctty
, new);
203 _hurd_port_free (&d
->port
, &ulink
, port
);
204 _hurd_port_free (&d
->ctty
, &ctty_ulink
, ctty
);
207 __mutex_unlock (&_hurd_dtable_lock
);
210 (void) &ctty_new_pgrp
; /* Avoid "defined but not used" warning. */
213 text_set_element (_hurd_pgrp_changed_hook
, ctty_new_pgrp
);
215 /* Called to reauthenticate the dtable when the auth port changes. */
223 __mutex_lock (&_hurd_dtable_lock
);
225 for (i
= 0; i
< _hurd_dtablesize
; ++i
)
227 struct hurd_fd
*const d
= _hurd_dtable
[i
];
228 mach_port_t
new, newctty
, ref
;
231 /* Nothing to do for an unused descriptor cell. */
234 ref
= __mach_reply_port ();
236 /* Take the descriptor cell's lock. */
237 __spin_lock (&d
->port
.lock
);
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
245 ref
, MACH_MSG_TYPE_MAKE_SEND
,
248 /* Replace the port in the descriptor cell
249 with the newly reauthenticated port. */
251 if (d
->ctty
.port
!= MACH_PORT_NULL
&&
252 ! __io_reauthenticate (d
->ctty
.port
,
253 ref
, MACH_MSG_TYPE_MAKE_SEND
) &&
254 ! __USEPORT (AUTH
, __auth_user_authenticate
256 ref
, MACH_MSG_TYPE_MAKE_SEND
,
258 _hurd_port_set (&d
->ctty
, newctty
);
260 _hurd_port_locked_set (&d
->port
, new);
263 /* Lost. Leave this descriptor cell alone. */
264 __spin_unlock (&d
->port
.lock
);
266 __mach_port_destroy (__mach_task_self (), ref
);
269 __mutex_unlock (&_hurd_dtable_lock
);
272 (void) &reauth_dtable
; /* Avoid "defined but not used" warning. */
275 text_set_element (_hurd_reauth_hook
, reauth_dtable
);