/* Trace RPCs sent to selected ports Copyright (C) 1998, 1999, 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc. This file is part of the GNU Hurd. The GNU Hurd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. The GNU Hurd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include struct port_info *notify_pi; struct port_class *other_class; struct port_bucket *traced_bucket; int trace_and_forward (mach_msg_header_t *inp, mach_msg_header_t *outp) { return 1; } /* This function runs in the tracing thread and drives all the tracing. */ static any_t trace_thread_function (void *arg) { struct port_bucket *const bucket = arg; ports_manage_port_operations_one_thread (bucket, trace_and_forward, 0); return 0; } /* Run a child and have it do more or else `execvpe (argv, envp);'. */ pid_t traced_spawn () { error_t err; pid_t pid; mach_port_t foo; task_t traced_task; err = task_create (mach_task_self (), 0, &traced_task); assert_perror (err); err = mach_port_request_notification (mach_task_self (), traced_task, MACH_NOTIFY_DEAD_NAME, 1, notify_pi->port_right, MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo); assert_perror (err); mach_port_deallocate (mach_task_self (), foo); task_terminate (traced_task); exit (0); return pid; } int main (int argc, char **argv, char **envp) { error_t err; traced_bucket = ports_create_bucket (); other_class = ports_create_class (0, 0); err = ports_create_port (other_class, traced_bucket, sizeof (*notify_pi), ¬ify_pi); assert_perror (err); /* Spawn a single thread that will receive intercepted messages, print them, and interpose on the ports they carry. The access to the `traced_info' and ihash data structures is all single-threaded, happening only in this new thread. */ cthread_detach (cthread_fork (trace_thread_function, traced_bucket)); traced_spawn (); ports_destroy_right (notify_pi); return 0; }