1 #include <cerrno> 2 #include <cstdio> 3 #include <cstring> 4 #include <exception> 5 #include <fcntl.h> 6 #include <functional> 7 #include <sdeventplus/event.hpp> 8 #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 17 void 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 48 void 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 59 void clean_exit(sdeventplus::source::Signal& source, 60 const struct signalfd_siginfo*) 61 { 62 source.get_event().exit(0); 63 } 64 65 int main(int argc, char* argv[]) 66 { 67 if (argc != 2) 68 { 69 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)); 85 return 1; 86 } 87 88 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 } 118 } 119