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