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
fifo_read(evutil_socket_t fd,short event,void * arg)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
signal_cb(evutil_socket_t fd,short event,void * arg)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
main(int argc,char ** argv)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