1 /* $NetBSD: event-read-fifo.c,v 1.1.1.2 2021/04/07 02:43:15 christos Exp $ */ 2 /* 3 * This sample code shows how to use Libevent to read from a named pipe. 4 * XXX This code could make better use of the Libevent interfaces. 5 * 6 * XXX This does not work on Windows; ignore everything inside the _WIN32 block. 7 * 8 * On UNIX, compile with: 9 * cc -I/usr/local/include -o event-read-fifo event-read-fifo.c \ 10 * -L/usr/local/lib -levent 11 */ 12 13 #include <event2/event-config.h> 14 15 #include <sys/types.h> 16 #include <sys/stat.h> 17 #ifndef _WIN32 18 #include <sys/queue.h> 19 #include <unistd.h> 20 #include <sys/time.h> 21 #include <signal.h> 22 #else 23 #include <winsock2.h> 24 #include <windows.h> 25 #endif 26 #include <fcntl.h> 27 #include <stdlib.h> 28 #include <stdio.h> 29 #include <string.h> 30 #include <errno.h> 31 32 #include <event2/event.h> 33 34 static void 35 fifo_read(evutil_socket_t fd, short event, void *arg) 36 { 37 char buf[255]; 38 int len; 39 struct event *ev = arg; 40 #ifdef _WIN32 41 DWORD dwBytesRead; 42 #endif 43 44 fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p\n", 45 (int)fd, event, arg); 46 #ifdef _WIN32 47 len = ReadFile((HANDLE)fd, buf, sizeof(buf) - 1, &dwBytesRead, NULL); 48 49 /* Check for end of file. */ 50 if (len && dwBytesRead == 0) { 51 fprintf(stderr, "End Of File"); 52 event_del(ev); 53 return; 54 } 55 56 buf[dwBytesRead] = '\0'; 57 #else 58 len = read(fd, buf, sizeof(buf) - 1); 59 60 if (len <= 0) { 61 if (len == -1) 62 perror("read"); 63 else if (len == 0) 64 fprintf(stderr, "Connection closed\n"); 65 event_del(ev); 66 event_base_loopbreak(event_get_base(ev)); 67 return; 68 } 69 70 buf[len] = '\0'; 71 #endif 72 fprintf(stdout, "Read: %s\n", buf); 73 } 74 75 /* On Unix, cleanup event.fifo if SIGINT is received. */ 76 #ifndef _WIN32 77 static void 78 signal_cb(evutil_socket_t fd, short event, void *arg) 79 { 80 struct event_base *base = arg; 81 event_base_loopbreak(base); 82 } 83 #endif 84 85 int 86 main(int argc, char **argv) 87 { 88 struct event *evfifo; 89 struct event_base* base; 90 #ifdef _WIN32 91 HANDLE socket; 92 /* Open a file. */ 93 socket = CreateFileA("test.txt", /* open File */ 94 GENERIC_READ, /* open for reading */ 95 0, /* do not share */ 96 NULL, /* no security */ 97 OPEN_EXISTING, /* existing file only */ 98 FILE_ATTRIBUTE_NORMAL, /* normal file */ 99 NULL); /* no attr. template */ 100 101 if (socket == INVALID_HANDLE_VALUE) 102 return 1; 103 104 #else 105 struct event *signal_int; 106 struct stat st; 107 const char *fifo = "event.fifo"; 108 int socket; 109 110 if (lstat(fifo, &st) == 0) { 111 if ((st.st_mode & S_IFMT) == S_IFREG) { 112 errno = EEXIST; 113 perror("lstat"); 114 exit(1); 115 } 116 } 117 118 unlink(fifo); 119 if (mkfifo(fifo, 0600) == -1) { 120 perror("mkfifo"); 121 exit(1); 122 } 123 124 socket = open(fifo, O_RDONLY | O_NONBLOCK, 0); 125 126 if (socket == -1) { 127 perror("open"); 128 exit(1); 129 } 130 131 fprintf(stderr, "Write data to %s\n", fifo); 132 #endif 133 /* Initialize the event library */ 134 base = event_base_new(); 135 136 /* Initialize one event */ 137 #ifdef _WIN32 138 evfifo = event_new(base, (evutil_socket_t)socket, EV_READ|EV_PERSIST, fifo_read, 139 event_self_cbarg()); 140 #else 141 /* catch SIGINT so that event.fifo can be cleaned up */ 142 signal_int = evsignal_new(base, SIGINT, signal_cb, base); 143 event_add(signal_int, NULL); 144 145 evfifo = event_new(base, socket, EV_READ|EV_PERSIST, fifo_read, 146 event_self_cbarg()); 147 #endif 148 149 /* Add it to the active events, without a timeout */ 150 event_add(evfifo, NULL); 151 152 event_base_dispatch(base); 153 event_base_free(base); 154 #ifdef _WIN32 155 CloseHandle(socket); 156 #else 157 close(socket); 158 unlink(fifo); 159 #endif 160 libevent_global_shutdown(); 161 return (0); 162 } 163 164