1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <syslog.h>
4 #include <errno.h>
5 #include <mach/mach.h>
6 #include <sys/types.h>
7 #include <sys/event.h>
8 #include <sys/time.h>
9 #include <servers/bootstrap.h>
10 
11 struct msg_send
12 {
13 	mach_msg_header_t hdr;
14 	char body[256];
15 };
16 
17 struct msg_recv
18 {
19 	mach_msg_header_t hdr;
20 	char body[256];
21 	mach_msg_trailer_t trailer;
22 };
23 
main()24 int main()
25 {
26 	kern_return_t kr;
27 	mach_port_t bport, port, pset;
28 	struct msg_recv message;
29 	struct msg_send reply;
30 	struct kevent64_s kev;
31 	int kq, r;
32 
33 	task_get_special_port(mach_task_self(), TASK_BOOTSTRAP_PORT, &bport);
34 	syslog(LOG_ERR, "bootstrap port: %d", bport);
35 
36 	kr = bootstrap_check_in(bootstrap_port, "mach.service-test", &port);
37 	if (kr != KERN_SUCCESS) {
38 		syslog(LOG_ERR, "bootstrap_check_in: kr=%d", kr);
39 		exit(1);
40 	}
41 
42 	syslog(LOG_ERR, "service port: %d", port);
43 
44 	kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &pset);
45 	if (kr != KERN_SUCCESS) {
46 		syslog(LOG_ERR, "mach_port_allocate: kr=%d", kr);
47 		exit(1);
48 	}
49 
50 	kr = mach_port_move_member(mach_task_self(), port, pset);
51 	if (kr != KERN_SUCCESS) {
52 		syslog(LOG_ERR, "mach_port_move_member: kr=%d", kr);
53 		exit(1);
54 	}
55 
56 	kq = kqueue();
57 	syslog(LOG_ERR, "kqueue fd: %d", kq);
58 
59 	memset(&kev, 0, sizeof(struct kevent64_s));
60 	EV_SET64(&kev, pset, EVFILT_MACHPORT, EV_ADD | EV_ENABLE, MACH_RCV_MSG,
61 	    0, 0, (uint64_t)&message, sizeof message);
62 
63 	if (kevent64(kq, &kev, 1, NULL, 0, 0, NULL) < 0) {
64 		syslog(LOG_ERR, "kevent64: %s (%d)", strerror(errno), errno);
65 		return 0;
66 	}
67 
68 	for (;;) {
69 		message.hdr.msgh_local_port = port;
70 		message.hdr.msgh_size = sizeof(struct msg_recv);
71 
72 		r = kevent64(kq, NULL, 0, &kev, 1, 0, NULL);
73 		if (r < 0) {
74 			syslog(LOG_ERR, "kevent64 failed: %s (%d)", strerror(errno), errno);
75 			continue;
76 		}
77 
78 		syslog(LOG_ERR, "kevent64: events=%d", r);
79 
80 		memset(&reply, 0, sizeof(struct msg_send));
81 		sprintf(&reply.body[0], "hello buddy");
82 		reply.hdr.msgh_local_port = MACH_PORT_NULL;
83 		reply.hdr.msgh_remote_port = message.hdr.msgh_remote_port;
84 		reply.hdr.msgh_size = sizeof(struct msg_send);
85 		reply.hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
86 		kr = mach_msg_send((mach_msg_header_t *)&reply);
87 		if (kr != KERN_SUCCESS)
88 			syslog(LOG_ERR, "mach_msg_send failure: kr=%d", kr);
89 	}
90 }
91 
92