aboutsummaryrefslogtreecommitdiff
path: root/libfshelp/start-translator-long.c
diff options
context:
space:
mode:
Diffstat (limited to 'libfshelp/start-translator-long.c')
-rw-r--r--libfshelp/start-translator-long.c166
1 files changed, 98 insertions, 68 deletions
diff --git a/libfshelp/start-translator-long.c b/libfshelp/start-translator-long.c
index 34202f43..5bf14541 100644
--- a/libfshelp/start-translator-long.c
+++ b/libfshelp/start-translator-long.c
@@ -1,5 +1,5 @@
-/*
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+/*
+ Copyright (C) 1995,96,99,2000,02, 04 Free Software Foundation, Inc.
Written by Miles Bader and Michael I. Bushnell.
This file is part of the GNU Hurd.
@@ -48,67 +48,79 @@ struct fsys_startup_reply
mach_port_t realnode;
};
-static const mach_msg_type_t flagsCheck = {
- MACH_MSG_TYPE_INTEGER_32, /* msgt_name = */
- 32, /* msgt_size = */
- 1, /* msgt_number = */
- TRUE, /* msgt_inline = */
- FALSE, /* msgt_longform = */
- FALSE, /* msgt_deallocate = */
- 0 /* msgt_unused = */
-};
-
-static const mach_msg_type_t control_portCheck =
-{
- 17, /* msgt_name = */
- 32, /* msgt_size = */
- 1, /* msgt_number = */
- TRUE, /* msgt_inline = */
- FALSE, /* msgt_longform = */
- FALSE, /* msgt_deallocate = */
- 0 /* msgt_unused = */
-};
-
-static const mach_msg_type_t RetCodeType = {
- MACH_MSG_TYPE_INTEGER_32, /* msgt_name = */
- 32, /* msgt_size = */
- 1, /* msgt_number = */
- TRUE, /* msgt_inline = */
- FALSE, /* msgt_longform = */
- FALSE, /* msgt_deallocate = */
- 0 /* msgt_unused = */
-};
-
-static const mach_msg_type_t realnodeType =
-{
- -1, /* msgt_name = */
- 32, /* msgt_size = */
- 1, /* msgt_number = */
- TRUE, /* msgt_inline = */
- FALSE, /* msgt_longform = */
- FALSE, /* msgt_deallocate = */
- 0 /* msgt_unused = */
-};
-
-
/* Wait around for an fsys_startup message on the port PORT from the
translator on NODE (timing out after TIMEOUT milliseconds), and return a
- send right for the resulting fsys control port in CONTROL. If a dead-name
+ send right for the resulting fsys control port in CONTROL. If a no-senders
notification is received on PORT, then it will be assumed that the
translator died, and EDIED will be returned. If an error occurs, the
error code is returned, otherwise 0. */
static error_t
-service_fsys_startup (fshelp_open_fn_t underlying_open_fn,
- mach_port_t port, long timeout,
- fsys_t *control)
+service_fsys_startup (fshelp_open_fn_t underlying_open_fn, void *cookie,
+ mach_port_t port, long timeout, fsys_t *control,
+ task_t task)
{
- error_t err;
- union
+ /* These should be optimized away to pure integer constants. */
+ const mach_msg_type_t flagsCheck =
+ {
+ MACH_MSG_TYPE_INTEGER_32, /* msgt_name = */
+ 32, /* msgt_size = */
+ 1, /* msgt_number = */
+ TRUE, /* msgt_inline = */
+ FALSE, /* msgt_longform = */
+ FALSE, /* msgt_deallocate = */
+ 0 /* msgt_unused = */
+ };
+ const mach_msg_type_t control_portCheck =
{
- mach_msg_header_t head;
- struct fsys_startup_request startup;
- mach_dead_name_notification_t dead;
+ MACH_MSG_TYPE_PORT_SEND, /* msgt_name = */
+ 32, /* msgt_size = */
+ 1, /* msgt_number = */
+ TRUE, /* msgt_inline = */
+ FALSE, /* msgt_longform = */
+ FALSE, /* msgt_deallocate = */
+ 0 /* msgt_unused = */
+ };
+ const mach_msg_type_t RetCodeType =
+ {
+ MACH_MSG_TYPE_INTEGER_32, /* msgt_name = */
+ 32, /* msgt_size = */
+ 1, /* msgt_number = */
+ TRUE, /* msgt_inline = */
+ FALSE, /* msgt_longform = */
+ FALSE, /* msgt_deallocate = */
+ 0 /* msgt_unused = */
+ };
+ const mach_msg_type_t realnodeType =
+ {
+ -1, /* msgt_name = */
+ 32, /* msgt_size = */
+ 1, /* msgt_number = */
+ TRUE, /* msgt_inline = */
+ FALSE, /* msgt_longform = */
+ FALSE, /* msgt_deallocate = */
+ 0 /* msgt_unused = */
+ };
+
+ /* Return true iff TYPE fails to match CHECK. */
+ inline int type_check (const mach_msg_type_t *type,
+ const mach_msg_type_t *check)
+ {
+ union
+ {
+ unsigned32_t word;
+ mach_msg_type_t type;
+ } t, c;
+ t.type = *type;
+ c.type = *check;
+ return t.word != c.word;
}
+
+ error_t err;
+ union
+ {
+ mach_msg_header_t head;
+ struct fsys_startup_request startup;
+ }
request;
struct fsys_startup_reply reply;
@@ -119,7 +131,7 @@ service_fsys_startup (fshelp_open_fn_t underlying_open_fn,
if (err)
return err;
- /* Check whether we actually got a dead-name notification instead. */
+ /* Check whether we actually got a no-senders notification instead. */
if (request.head.msgh_id == MACH_NOTIFY_NO_SENDERS)
return EDIED;
@@ -135,9 +147,8 @@ service_fsys_startup (fshelp_open_fn_t underlying_open_fn,
if (request.head.msgh_id != 22000)
reply.RetCode = MIG_BAD_ID;
- else if ((*(int *)&request.startup.control_portType
- != *(int *)&control_portCheck)
- || (*(int *)&request.startup.flagsType != *(int *)&flagsCheck))
+ else if (type_check (&request.startup.control_portType, &control_portCheck)
+ || type_check (&request.startup.flagsType, &flagsCheck))
reply.RetCode = MIG_BAD_ARGUMENTS;
else
{
@@ -147,7 +158,8 @@ service_fsys_startup (fshelp_open_fn_t underlying_open_fn,
reply.RetCode =
(*underlying_open_fn) (request.startup.flags,
- &reply.realnode, &realnode_type);
+ &reply.realnode, &realnode_type, task,
+ cookie);
reply.realnodeType = realnodeType;
reply.realnodeType.msgt_name = realnode_type;
@@ -161,6 +173,11 @@ service_fsys_startup (fshelp_open_fn_t underlying_open_fn,
sizeof(reply), 0,
request.head.msgh_remote_port,
MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ if (err == MACH_SEND_INTERRUPTED
+ && reply.realnodeType.msgt_name == MACH_MSG_TYPE_MOVE_SEND)
+ /* For MACH_SEND_INTERRUPTED, we'll have pseudo-received the message
+ and might have to clean up a generated send right. */
+ mach_port_deallocate (mach_task_self (), reply.realnode);
if (reply.RetCode)
/* Make our error return be the earlier one. */
@@ -172,19 +189,20 @@ service_fsys_startup (fshelp_open_fn_t underlying_open_fn,
error_t
fshelp_start_translator_long (fshelp_open_fn_t underlying_open_fn,
- char *name, char *argz, int argz_len,
- mach_port_t *fds,
+ void *cookie, char *name, char *argz,
+ int argz_len, mach_port_t *fds,
mach_msg_type_name_t fds_type, int fds_len,
mach_port_t *ports,
mach_msg_type_name_t ports_type, int ports_len,
int *ints, int ints_len,
+ uid_t owner_uid,
int timeout, fsys_t *control)
{
error_t err;
file_t executable;
mach_port_t bootstrap = MACH_PORT_NULL;
mach_port_t task = MACH_PORT_NULL;
- mach_port_t prev_notify, proc, saveport;
+ mach_port_t prev_notify, proc, saveport, childproc;
int ports_moved = 0;
/* Find the translator itself. Since argz has zero-separated elements, we
@@ -192,7 +210,7 @@ fshelp_start_translator_long (fshelp_open_fn_t underlying_open_fn,
executable = file_name_lookup(name, O_EXEC, 0);
if (executable == MACH_PORT_NULL)
return errno;
-
+
/* Create a bootstrap port for the translator. */
err =
mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &bootstrap);
@@ -200,15 +218,26 @@ fshelp_start_translator_long (fshelp_open_fn_t underlying_open_fn,
goto lose;
/* Create the task for the translator. */
- err = task_create (mach_task_self (), 0, &task);
+ err = task_create (mach_task_self (),
+#ifdef KERN_INVALID_LEDGER
+ NULL, 0, /* OSF Mach */
+#endif
+ 0, &task);
if (err)
goto lose;
- /* Designate TASK as our child. */
+ /* Designate TASK as our child and set it's owner accordingly. */
proc = getproc ();
proc_child (proc, task);
+ err = proc_task2proc (proc, task, &childproc);
mach_port_deallocate (mach_task_self (), proc);
-
+ if (err)
+ goto lose;
+ err = proc_setowner (childproc, owner_uid, owner_uid == (uid_t) -1);
+ mach_port_deallocate (mach_task_self (), childproc);
+ if (err)
+ goto lose;
+
assert (ports_len > INIT_PORT_BOOTSTRAP);
switch (ports_type)
{
@@ -264,13 +293,14 @@ fshelp_start_translator_long (fshelp_open_fn_t underlying_open_fn,
/* Ok, cool, we've got a running(?) program, now rendezvous with it if
possible using the startup protocol on the bootstrap port... */
- err = service_fsys_startup(underlying_open_fn, bootstrap, timeout, control);
+ err = service_fsys_startup(underlying_open_fn, cookie, bootstrap,
+ timeout, control, task);
lose:
if (!ports_moved)
{
int i;
-
+
if (fds_type == MACH_MSG_TYPE_MOVE_SEND)
for (i = 0; i < fds_len; i++)
mach_port_deallocate (mach_task_self (), fds[i]);