#include <stdio.h>
#include <mach/mach.h>
#include <mach/mach_port.h> // for mach_port_*
#include <stdlib.h> // for ATOI...
#include <unistd.h> // for exit(...)
#include <bootstrap.h> // Darwin specific

int main (int argc, char **argv){ 


	extern mach_port_t	bootstrap_port; // the name of the bootstrap port

	printf("My bootstrap port is 0x%x\n", bootstrap_port);

	kern_return_t kr = KERN_SUCCESS;
	pid_t targetPid = 0;

#if WANTLOOKUP
	mach_port_t lookedup_port = MACH_PORT_NULL; 


	kr = bootstrap_look_up(bootstrap_port, // mach_port_t bp, 
		argv[1], // const name_t service_name,
		&lookedup_port); //  mach_port_t *sp);


	if (KERN_SUCCESS == kr) {
		printf("0x%x :-)\n", lookedup_port);

	}
	else {
		printf(":-(\n");
	}

#else 
	targetPid = atoi(argv[1]);
#endif

	

	// MACH PORT APIS

	mach_port_t target = mach_task_self();

	if (targetPid != 0) {

		kr = task_for_pid (mach_task_self(),
					targetPid,
				&target);

		if (KERN_SUCCESS != kr) { fprintf(stderr,"I can't do that, HAL!\n"); exit(5);}
	}

	mach_port_name_t allocatedPort;

	kr=  mach_port_allocate(target,  // ipc_space_t task,
				MACH_PORT_RIGHT_RECEIVE, // mach_port_right_t right,
				&allocatedPort); // mach_port_name_t *name);

	printf("0x%x\n", allocatedPort);


	// INTROSPECTION:
        ipc_info_space_t space_info; 
        ipc_info_name_array_t table_info;
        mach_msg_type_number_t table_infoCnt;
        ipc_info_tree_name_array_t tree_info;
        mach_msg_type_number_t tree_infoCnt;


	kr = mach_port_space_info (target, // ipc_space_read_t space,
			&space_info, // ipc_info_space_t *space_info,
			&table_info, // ipc_info_name_array_t *table_info,
			&table_infoCnt, // mach_msg_type_number_t *table_infoCnt, <- OUT
			&tree_info, // ipc_info_tree_name_array_t *tree_info,
			&tree_infoCnt); // mach_msg_type_number_t *tree_infoCnt);


	if (kr != KERN_SUCCESS) { printf("Error: %s\n", mach_error_string(kr));}


	printf("IPC Information: Gen # Mask: 0x%x, Table Size: %d\n",
			space_info.iis_genno_mask,
			space_info.iis_table_size);



	int table_size = space_info.iis_table_size;

	int p = 0;

	for (p = 0 ;
	     p < table_size; // could also get this from table_infoCnt
	     p++) {


	printf("Name: 0x%x\tType: 0x%x, Object: 0x%x, Urefs: %d\n", 
		table_info[p].iin_name,
		table_info[p].iin_type,
		table_info[p].iin_object,
		table_info[p].iin_urefs);


	} // end p

	return 0 ;

}