/* * This sample code shows how to use Libevent to read from a named pipe. * XXX This code could make better use of the Libevent interfaces. * * XXX This does not work on Windows; ignore everything inside the _WIN32 block. * * On UNIX, compile with: * cc -I/usr/local/include -o event-read-fifo event-read-fifo.c \ * -L/usr/local/lib -levent */ #include <event2/event-config.h> #include <sys/types.h> #include <sys/stat.h> #ifndef _WIN32 #include <sys/queue.h> #include <unistd.h> #include <sys/time.h> #include <signal.h> #else #include <winsock2.h> #include <windows.h> #endif #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <event2/event.h> static void fifo_read(evutil_socket_t fd, short event, void *arg) { char buf[255]; int len; struct event *ev = arg; #ifdef _WIN32 DWORD dwBytesRead; #endif fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p\n", (int)fd, event, arg); #ifdef _WIN32 len = ReadFile((HANDLE)fd, buf, sizeof(buf) - 1, &dwBytesRead, NULL); /* Check for end of file. */ if (len && dwBytesRead == 0) { fprintf(stderr, "End Of File"); event_del(ev); return; } buf[dwBytesRead] = '\0'; #else len = read(fd, buf, sizeof(buf) - 1); if (len <= 0) { if (len == -1) perror("read"); else if (len == 0) fprintf(stderr, "Connection closed\n"); event_del(ev); event_base_loopbreak(event_get_base(ev)); return; } buf[len] = '\0'; #endif fprintf(stdout, "Read: %s\n", buf); } /* On Unix, cleanup event.fifo if SIGINT is received. */ #ifndef _WIN32 static void signal_cb(evutil_socket_t fd, short event, void *arg) { struct event_base *base = arg; event_base_loopbreak(base); } #endif int main(int argc, char **argv) { struct event *evfifo; struct event_base* base; #ifdef _WIN32 HANDLE socket; /* Open a file. */ socket = CreateFileA("test.txt", /* open File */ GENERIC_READ, /* open for reading */ 0, /* do not share */ NULL, /* no security */ OPEN_EXISTING, /* existing file only */ FILE_ATTRIBUTE_NORMAL, /* normal file */ NULL); /* no attr. template */ if (socket == INVALID_HANDLE_VALUE) return 1; #else struct event *signal_int; struct stat st; const char *fifo = "event.fifo"; int socket; if (lstat(fifo, &st) == 0) { if ((st.st_mode & S_IFMT) == S_IFREG) { errno = EEXIST; perror("lstat"); exit(1); } } unlink(fifo); if (mkfifo(fifo, 0600) == -1) { perror("mkfifo"); exit(1); } socket = open(fifo, O_RDONLY | O_NONBLOCK, 0); if (socket == -1) { perror("open"); exit(1); } fprintf(stderr, "Write data to %s\n", fifo); #endif /* Initalize the event library */ base = event_base_new(); /* Initalize one event */ #ifdef _WIN32 evfifo = event_new(base, (evutil_socket_t)socket, EV_READ|EV_PERSIST, fifo_read, event_self_cbarg()); #else /* catch SIGINT so that event.fifo can be cleaned up */ signal_int = evsignal_new(base, SIGINT, signal_cb, base); event_add(signal_int, NULL); evfifo = event_new(base, socket, EV_READ|EV_PERSIST, fifo_read, event_self_cbarg()); #endif /* Add it to the active events, without a timeout */ event_add(evfifo, NULL); event_base_dispatch(base); event_base_free(base); #ifdef _WIN32 CloseHandle(socket); #else close(socket); unlink(fifo); #endif libevent_global_shutdown(); return (0); }