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