int main (int argc, char **argv) { mach_port_t bootstrap; mach_port_t control; error_t err; /* Parse our options... */ argp_parse (&argp, argc, argv, 0, 0, 0); task_get_bootstrap_port (mach_task_self (), &bootstrap); if (bootstrap == MACH_PORT_NULL) error (1, 0, "Must be started as a translator"); linktarget = argv[1]; /* Reply to our parent */ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &control); mach_port_insert_right (mach_task_self (), control, control, MACH_MSG_TYPE_MAKE_SEND); err = fsys_startup (bootstrap, 0, control, MACH_MSG_TYPE_COPY_SEND, &realnode); mach_port_deallocate (mach_task_self (), control); mach_port_deallocate (mach_task_self (), bootstrap); if (err) error (1, err, "Starting up translator"); io_restrict_auth (realnode, &realnodenoauth, 0, 0, 0, 0); mach_port_deallocate (mach_task_self (), realnode); /* Mark us as important. */ mach_port_t proc = getproc (); if (proc == MACH_PORT_NULL) error (2, err, "cannot get a handle to our process"); err = proc_mark_important (proc); /* This might fail due to permissions or because the old proc server is still running, ignore any such errors. */ if (err && err != EPERM && err != EMIG_BAD_ID) error (2, err, "Cannot mark us as important"); mach_port_deallocate (mach_task_self (), proc); /* Launch */ while (1) { /* The timeout here is 10 minutes */ err = mach_msg_server_timeout (fsys_server, 0, control, MACH_RCV_TIMEOUT, 1000 * 60 * 10); if (err == MACH_RCV_TIMED_OUT) exit (0); } }
void ports_manage_port_operations_one_thread (struct port_bucket *bucket, ports_demuxer_type demuxer, int timeout) { error_t err; int internal_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outheadp) { struct port_info *pi; struct rpc_info link; int status; error_t err; register mig_reply_header_t *outp = (mig_reply_header_t *) outheadp; static const mach_msg_type_t RetCodeType = { /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32, /* msgt_size = */ 32, /* msgt_number = */ 1, /* msgt_inline = */ TRUE, /* msgt_longform = */ FALSE, /* msgt_deallocate = */ FALSE, /* msgt_unused = */ 0 }; /* Fill in default response. */ outp->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(inp->msgh_bits), 0); outp->Head.msgh_size = sizeof *outp; outp->Head.msgh_remote_port = inp->msgh_remote_port; outp->Head.msgh_local_port = MACH_PORT_NULL; outp->Head.msgh_seqno = 0; outp->Head.msgh_id = inp->msgh_id + 100; outp->RetCodeType = RetCodeType; outp->RetCode = MIG_BAD_ID; pi = ports_lookup_port (bucket, inp->msgh_local_port, 0); if (pi) { err = ports_begin_rpc (pi, inp->msgh_id, &link); if (err) { mach_port_deallocate (mach_task_self (), inp->msgh_remote_port); outp->RetCode = err; status = 1; } else { /* No need to check cancel threshhold here, because in a single threaded server the cancel is always handled in order. */ status = demuxer (inp, outheadp); ports_end_rpc (pi, &link); } ports_port_deref (pi); } else { outp->RetCode = EOPNOTSUPP; status = 1; } return status; } do err = mach_msg_server_timeout (internal_demuxer, 0, bucket->portset, timeout ? MACH_RCV_TIMEOUT : 0, timeout); while (err != MACH_RCV_TIMED_OUT); }
void ports_manage_port_operations_one_thread (struct port_bucket *bucket, ports_demuxer_type demuxer, int timeout) { struct ports_thread thread; error_t err; int internal_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outheadp) { struct port_info *pi; struct rpc_info link; int status; error_t err; register mig_reply_header_t *outp = (mig_reply_header_t *) outheadp; static const mach_msg_type_t RetCodeType = { /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32, /* msgt_size = */ 32, /* msgt_number = */ 1, /* msgt_inline = */ TRUE, /* msgt_longform = */ FALSE, /* msgt_deallocate = */ FALSE, /* msgt_unused = */ 0 }; /* Fill in default response. */ outp->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(inp->msgh_bits), 0); outp->Head.msgh_size = sizeof *outp; outp->Head.msgh_remote_port = inp->msgh_remote_port; outp->Head.msgh_local_port = MACH_PORT_NULL; outp->Head.msgh_seqno = 0; outp->Head.msgh_id = inp->msgh_id + 100; outp->RetCodeType = RetCodeType; outp->RetCode = MIG_BAD_ID; if (MACH_MSGH_BITS_LOCAL (inp->msgh_bits) == MACH_MSG_TYPE_PROTECTED_PAYLOAD) pi = ports_lookup_payload (bucket, inp->msgh_protected_payload, NULL); else { pi = ports_lookup_port (bucket, inp->msgh_local_port, 0); if (pi) { /* Store the objects address as the payload and set the message type accordingly. This prevents us from having to do another hash table lookup in the intran functions if protected payloads are not supported by the kernel. */ inp->msgh_bits = MACH_MSGH_BITS_OTHER (inp->msgh_bits) | MACH_MSGH_BITS (MACH_MSGH_BITS_REMOTE (inp->msgh_bits), MACH_MSG_TYPE_PROTECTED_PAYLOAD); inp->msgh_protected_payload = (unsigned long) pi; } } if (pi) { err = ports_begin_rpc (pi, inp->msgh_id, &link); if (err) { mach_port_deallocate (mach_task_self (), inp->msgh_remote_port); outp->RetCode = err; status = 1; } else { /* No need to check cancel threshold here, because in a single threaded server the cancel is always handled in order. */ status = demuxer (inp, outheadp); ports_end_rpc (pi, &link); } ports_port_deref (pi); } else { outp->RetCode = EOPNOTSUPP; status = 1; } _ports_thread_quiescent (&bucket->threadpool, &thread); return status; } /* XXX It is currently unsafe for most servers to terminate based on inactivity because a request may arrive after a server has started shutting down, causing the client to receive an error. Prevent the service loop from terminating by setting TIMEOUT to zero. */ timeout = 0; _ports_thread_online (&bucket->threadpool, &thread); do err = mach_msg_server_timeout (internal_demuxer, 0, bucket->portset, timeout ? MACH_RCV_TIMEOUT : 0, timeout); while (err != MACH_RCV_TIMED_OUT); _ports_thread_offline (&bucket->threadpool, &thread); }