xref: /netbsd-src/external/bsd/libevent/dist/sample/event-read-fifo.c (revision 657871a79c9a2060a6255a242fa1a1ef76b56ec6)
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