summaryrefslogtreecommitdiffstats
path: root/freebsd/kqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/kqueue.c')
-rw-r--r--freebsd/kqueue.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/freebsd/kqueue.c b/freebsd/kqueue.c
new file mode 100644
index 0000000..e8825db
--- /dev/null
+++ b/freebsd/kqueue.c
@@ -0,0 +1,142 @@
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+int printer_ready;
+char * printer;
+char * queue_dir;
+char * trigger;
+#define BUFLEN 50
+char queue_dir_new[BUFLEN];
+char trigger_cmd[BUFLEN];
+
+int open_and_subscribe(struct kevent * change, const char * path)
+{
+ int f;
+ f = open(path, O_RDONLY);
+ if (f == -1) {
+ perror("open");
+ return -1;
+ }
+
+ EV_SET(change, f, EVFILT_VNODE,
+ EV_ADD | EV_ENABLE | EV_ONESHOT,
+ NOTE_DELETE | NOTE_EXTEND |
+ NOTE_WRITE | NOTE_ATTRIB,
+ 0, 0);
+}
+
+int check_printer_status(){
+ struct stat buf;
+ //printf("%s\n", printer);
+ int r = stat(printer, &buf);
+ if (r<0) {
+ if (printer_ready != 0) {
+ printf("Printer offline\n");
+ }
+ printer_ready = 0;
+ if (errno == ENOENT) {
+ printf("Printer not detected\n");
+ } else {
+ perror("stat");
+ return -1;
+ }
+ } else {
+ if (printer_ready != 1) {
+ printf("Printer online\n");
+ print_loop(printer, queue_dir);
+ }
+ printer_ready = 1;
+ }
+ return 0;
+}
+
+int print_loop()
+{
+ FILE * p;
+ int status;
+ char buf[BUFLEN];
+ printf("Print loop\n");
+ p = popen(trigger_cmd, "r");
+ if (p == NULL)
+ perror("popen");
+ while (fgets(buf, BUFLEN, p) != NULL)
+ printf("%s", buf);
+ status = pclose(p);
+ if (status != 0) {
+ printf("Trigger exited with status %d\n", status);
+ }
+ return status;
+}
+
+int main(int argc, const char * argv[])
+{
+ int fd, fq, kq, nev;
+ struct kevent change;
+ struct kevent event;
+
+ int len;
+
+ if (argc != 4) {
+ fprintf(stderr, "usage: %s printer queue_dir trigger\n", argv[0]);
+ return -1;
+ }
+ printer = strdup(argv[1]);
+ queue_dir = strdup(argv[2]);
+ trigger = strdup(argv[3]);
+
+ len = snprintf(trigger_cmd, BUFLEN, "%s %s %s", trigger, printer, queue_dir);
+ if (len >= BUFLEN - 1) {
+ printf("Buffer too small\n");
+ return -1;
+ }
+
+ len = snprintf(queue_dir_new, BUFLEN, "%s/new", queue_dir);
+ if (len >= BUFLEN - 1) {
+ printf("Buffer too small\n");
+ return -1;
+ }
+
+ printer_ready = 0;
+
+ kq = kqueue();
+ if (kq == -1)
+ perror("kqueue");
+
+ fq = open_and_subscribe(&change, queue_dir_new);
+
+ struct timespec timeout;
+ timeout.tv_sec = 5;
+ timeout.tv_nsec = 0;
+
+ check_printer_status();
+ for (;;) {
+ nev = kevent(kq, &change, 1, &event, 1, &timeout);
+ if (nev == -1)
+ perror("kevent");
+ if (nev == 0) { // timeout
+ check_printer_status();
+ } else if (nev > 0) {
+ if (event.fflags & NOTE_DELETE) {
+ continue;
+ }
+ printf("Got event for %d\n", event.ident);
+ if (printer_ready) {
+ print_loop(printer, queue_dir, trigger);
+ }
+ }
+ }
+
+ close(kq);
+ close(fq);
+ close(fd);
+ return EXIT_SUCCESS;
+}