2 * Copyright (c) 2009 Mark Heily <mark@heily.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 #include <sys/socket.h>
28 extern const struct filter evfilt_read;
29 extern const struct filter evfilt_write;
30 extern const struct filter evfilt_signal;
31 extern const struct filter evfilt_vnode;
32 extern const struct filter evfilt_proc;
33 extern const struct filter evfilt_timer;
34 extern const struct filter evfilt_user;
37 filter_register(struct kqueue *kq, short filter, const struct filter *src)
43 filt = (-1 * filter) - 1;
44 if (filt >= EVFILT_SYSCOUNT)
47 dst = &kq->kq_filt[filt];
48 memcpy(dst, src, sizeof(*src));
50 RB_INIT(&dst->kf_knote);
51 TAILQ_INIT(&dst->kf_event);
52 if (src->kf_id == 0) {
53 dbg_puts("filter is not implemented");
58 assert(src->kf_destroy);
59 assert(src->kf_copyout);
60 assert(src->kn_create);
61 assert(src->kn_modify);
62 assert(src->kn_delete);
63 assert(src->kn_enable);
64 assert(src->kn_disable);
66 rv = src->kf_init(dst);
68 dbg_puts("filter failed to initialize");
73 /* Add the filter's event descriptor to the main fdset */
74 if (dst->kf_pfd > 0) {
75 FD_SET(dst->kf_pfd, &kq->kq_fds);
76 if (dst->kf_pfd > kq->kq_nfds)
77 kq->kq_nfds = dst->kf_pfd;
78 dbg_printf("fds: added %d (nfds=%d)", dst->kf_pfd, kq->kq_nfds);
80 dbg_printf("filter %d (%s) registered", filter, filter_name(filter));
86 filter_register_all(struct kqueue *kq)
92 rv += filter_register(kq, EVFILT_READ, &evfilt_read);
93 rv += filter_register(kq, EVFILT_WRITE, &evfilt_write);
94 rv += filter_register(kq, EVFILT_SIGNAL, &evfilt_signal);
95 rv += filter_register(kq, EVFILT_VNODE, &evfilt_vnode);
96 rv += filter_register(kq, EVFILT_PROC, &evfilt_proc);
97 rv += filter_register(kq, EVFILT_TIMER, &evfilt_timer);
98 rv += filter_register(kq, EVFILT_USER, &evfilt_user);
101 filter_unregister_all(kq);
109 filter_unregister_all(struct kqueue *kq)
113 for (i = 0; i < EVFILT_SYSCOUNT; i++) {
114 if (kq->kq_filt[i].kf_id == 0)
117 if (kq->kq_filt[i].kf_destroy != NULL)
118 kq->kq_filt[i].kf_destroy(&kq->kq_filt[i]);
120 knote_free_all(&kq->kq_filt[i]);
122 memset(&kq->kq_filt[0], 0, sizeof(kq->kq_filt));
126 filter_socketpair(struct filter *filt)
130 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0)
133 fcntl(sockfd[0], F_SETFL, O_NONBLOCK);
134 filt->kf_wfd = sockfd[0];
135 filt->kf_pfd = sockfd[1];
140 filter_lookup(struct filter **filt, struct kqueue *kq, short id)
142 if (~id < 0 || ~id >= EVFILT_SYSCOUNT) {
143 dbg_printf("invalid id: id %d ~id %d", id, (~id));
148 *filt = &kq->kq_filt[~id];
149 if ((*filt)->kf_copyout == NULL) {
159 filter_name(short filt)
162 const char *fname[EVFILT_SYSCOUNT] = {
177 if (id < 0 || id >= EVFILT_SYSCOUNT)
178 return "EVFILT_INVALID";
184 filter_raise(struct filter *filt)
187 if (write(filt->kf_wfd, " ", 1) < 0) {
191 if (errno != EAGAIN) {
192 dbg_printf("write(2): %s", strerror(errno));
193 /* TODO: set filter error flag */
204 filter_lower(struct filter *filt)
210 n = read(filt->kf_pfd, &buf, sizeof(buf));
217 dbg_printf("read(2): %s", strerror(errno));