blob: 7f726872cefd884ad503a05c4ff42c64b84bf90d [file] [log] [blame]
William A. Kennington III7b79fb52018-07-22 22:19:11 -07001#include <cerrno>
William A. Kennington III8f90e282018-07-17 14:40:14 -07002#include <cstdio>
William A. Kennington III7b79fb52018-07-22 22:19:11 -07003#include <cstring>
4#include <exception>
5#include <fcntl.h>
6#include <functional>
William A. Kennington III8f90e282018-07-17 14:40:14 -07007#include <sdeventplus/event.hpp>
William A. Kennington III7b79fb52018-07-22 22:19:11 -07008#include <sdeventplus/source/event.hpp>
9#include <sdeventplus/source/io.hpp>
10#include <sdeventplus/source/signal.hpp>
11#include <signal.h>
12#include <sys/epoll.h>
13#include <sys/stat.h>
14#include <sys/types.h>
15#include <unistd.h>
16
17void reader(const char* fifo, sdeventplus::source::IO& source, int fd, uint32_t)
18{
19 char buf[4096];
20 ssize_t r = read(fd, buf, sizeof(buf));
21 if (r == 0)
22 {
23 int newfd = open(fifo, O_NONBLOCK | O_RDONLY);
24 if (newfd < 0)
25 {
26 fprintf(stderr, "Failed to open %s: %s\n", fifo, strerror(errno));
27 source.get_event().exit(1);
28 return;
29 }
30 source.set_fd(newfd);
31 if (close(fd))
32 {
33 fprintf(stderr, "Failed to close fd\n");
34 source.get_event().exit(1);
35 return;
36 }
37 return;
38 }
39 if (r < 0)
40 {
41 fprintf(stderr, "Reader error: %s\n", strerror(errno));
42 source.get_event().exit(1);
43 return;
44 }
45 printf("%.*s", static_cast<int>(r), buf);
46}
47
48void remover(const char* fifo, sdeventplus::source::EventBase& source)
49{
50 int r = unlink(fifo);
51 if (r)
52 {
53 fprintf(stderr, "Failed to remove fifo %s: %s\n", fifo,
54 strerror(errno));
55 source.get_event().exit(1);
56 }
57}
58
59void clean_exit(sdeventplus::source::Signal& source,
60 const struct signalfd_siginfo*)
61{
62 source.get_event().exit(0);
63}
William A. Kennington III8f90e282018-07-17 14:40:14 -070064
65int main(int argc, char* argv[])
66{
67 if (argc != 2)
68 {
William A. Kennington III7b79fb52018-07-22 22:19:11 -070069 fprintf(stderr, "Usage: %s [named pipe to create]\n", argv[0]);
70 return 1;
71 }
72 const char* fifo = argv[1];
73
74 // Block all signals before changing system state so we guarantee our clean
75 // up routines are in place
76 sigset_t signals;
77 if (sigfillset(&signals))
78 {
79 fprintf(stderr, "Failed to populate signals: %s\n", strerror(errno));
80 return 1;
81 }
82 if (sigprocmask(SIG_BLOCK, &signals, nullptr))
83 {
84 fprintf(stderr, "Failed to mask signals: %s\n", strerror(errno));
William A. Kennington III8f90e282018-07-17 14:40:14 -070085 return 1;
86 }
87
William A. Kennington III7b79fb52018-07-22 22:19:11 -070088 if (mkfifo(fifo, 0622))
89 {
90 fprintf(stderr, "Failed to mkfifo %s: %s\n", fifo, strerror(errno));
91 return 1;
92 }
93
94 int fd = open(fifo, O_NONBLOCK | O_RDONLY);
95 if (fd < 0)
96 {
97 fprintf(stderr, "Failed to open %s: %s\n", fifo, strerror(errno));
98 return 1;
99 }
100
101 try
102 {
103 sdeventplus::Event event = sdeventplus::Event::get_default();
104 sdeventplus::source::Exit remover_source(
105 event, std::bind(remover, fifo, std::placeholders::_1));
106 sdeventplus::source::Signal sigint(event, SIGINT, clean_exit);
107 sdeventplus::source::IO reader_source(
108 event, fd, EPOLLIN,
109 std::bind(reader, fifo, std::placeholders::_1,
110 std::placeholders::_2, std::placeholders::_3));
111 return event.loop();
112 }
113 catch (const std::exception& e)
114 {
115 fprintf(stderr, "%s\n", e.what());
116 return 1;
117 }
William A. Kennington III8f90e282018-07-17 14:40:14 -0700118}