#include #include #include #include #include #include #include #include #include void test_event(int fd, int kq, const char *what, u_short flag) { char buf = 'a'; printf(" %s -> ", what); struct kevent event, tevent; EV_SET(&event, fd, flag, EV_ADD | EV_CLEAR, 0, 0, NULL); int rc = kevent(kq, &event, 1, NULL, 0, NULL); if (rc == -1) { err(EXIT_FAILURE, "kevent (set)"); } rc = kevent(kq, NULL, 0, &tevent, 1, NULL); if (rc == -1) { err(EXIT_FAILURE, "kevent (wait)"); } else if (rc > 0) { if (tevent.flags & EV_ERROR) { err(EXIT_FAILURE, "kevent (flags)"); } else { switch (tevent.filter) { case EVFILT_READ: printf("read triggered -> "); rc = read(fd, &buf, 1); if (rc == -1) { printf("error: %s\n", strerror(errno)); } else if (rc == 0) { printf("ok, EOF\n"); } else { printf("ok, %0x\n", buf); } break; case EVFILT_WRITE: printf("write triggered -> "); rc = write(fd, &buf, 1); if (rc == -1) { printf("error: %s\n", strerror(errno)); } else { printf("ok, written\n"); } break; break; default: printf("unknown event triggered\n"); break; } } } } void test(const char* path) { printf("%s\n", path); int fd = open(path, O_RDONLY); if (fd == -1) { err(EXIT_FAILURE, "open failed: %s\n", path); } int kq = kqueue(); if (kq == -1) { err(EXIT_FAILURE, "kqueue failed\n"); } test_event(fd, kq, "read", EVFILT_READ); test_event(fd, kq, "write", EVFILT_WRITE); close(kq); close(fd); } int main() { test("/dev/nullo"); test("/dev/fullo"); test("/dev/zeroo"); return 0; }