xref: /openbmc/sdeventplus/example/follow.cpp (revision a8c11e3ca342b090aec615c832b85686bd4655f6)
17b79fb55SWilliam A. Kennington III #include <fcntl.h>
27b79fb55SWilliam A. Kennington III #include <signal.h>
37b79fb55SWilliam A. Kennington III #include <sys/epoll.h>
47b79fb55SWilliam A. Kennington III #include <sys/stat.h>
57b79fb55SWilliam A. Kennington III #include <sys/types.h>
67b79fb55SWilliam A. Kennington III #include <unistd.h>
77b79fb55SWilliam A. Kennington III 
8*a8c11e3cSPatrick Williams #include <sdeventplus/event.hpp>
9*a8c11e3cSPatrick Williams #include <sdeventplus/source/event.hpp>
10*a8c11e3cSPatrick Williams #include <sdeventplus/source/io.hpp>
11*a8c11e3cSPatrick Williams #include <sdeventplus/source/signal.hpp>
12*a8c11e3cSPatrick Williams 
13*a8c11e3cSPatrick Williams #include <cerrno>
14*a8c11e3cSPatrick Williams #include <cstdio>
15*a8c11e3cSPatrick Williams #include <cstring>
16*a8c11e3cSPatrick Williams #include <exception>
17*a8c11e3cSPatrick Williams #include <functional>
18*a8c11e3cSPatrick Williams 
reader(const char * fifo,sdeventplus::source::IO & source,int fd,uint32_t)197b79fb55SWilliam A. Kennington III void reader(const char* fifo, sdeventplus::source::IO& source, int fd, uint32_t)
207b79fb55SWilliam A. Kennington III {
217b79fb55SWilliam A. Kennington III     char buf[4096];
227b79fb55SWilliam A. Kennington III     ssize_t r = read(fd, buf, sizeof(buf));
237b79fb55SWilliam A. Kennington III     if (r == 0)
247b79fb55SWilliam A. Kennington III     {
257b79fb55SWilliam A. Kennington III         int newfd = open(fifo, O_NONBLOCK | O_RDONLY);
267b79fb55SWilliam A. Kennington III         if (newfd < 0)
277b79fb55SWilliam A. Kennington III         {
287b79fb55SWilliam A. Kennington III             fprintf(stderr, "Failed to open %s: %s\n", fifo, strerror(errno));
297b79fb55SWilliam A. Kennington III             source.get_event().exit(1);
307b79fb55SWilliam A. Kennington III             return;
317b79fb55SWilliam A. Kennington III         }
327b79fb55SWilliam A. Kennington III         source.set_fd(newfd);
337b79fb55SWilliam A. Kennington III         if (close(fd))
347b79fb55SWilliam A. Kennington III         {
357b79fb55SWilliam A. Kennington III             fprintf(stderr, "Failed to close fd\n");
367b79fb55SWilliam A. Kennington III             source.get_event().exit(1);
377b79fb55SWilliam A. Kennington III             return;
387b79fb55SWilliam A. Kennington III         }
397b79fb55SWilliam A. Kennington III         return;
407b79fb55SWilliam A. Kennington III     }
417b79fb55SWilliam A. Kennington III     if (r < 0)
427b79fb55SWilliam A. Kennington III     {
437b79fb55SWilliam A. Kennington III         fprintf(stderr, "Reader error: %s\n", strerror(errno));
447b79fb55SWilliam A. Kennington III         source.get_event().exit(1);
457b79fb55SWilliam A. Kennington III         return;
467b79fb55SWilliam A. Kennington III     }
477b79fb55SWilliam A. Kennington III     printf("%.*s", static_cast<int>(r), buf);
487b79fb55SWilliam A. Kennington III }
497b79fb55SWilliam A. Kennington III 
remover(const char * fifo,sdeventplus::source::EventBase & source)507b79fb55SWilliam A. Kennington III void remover(const char* fifo, sdeventplus::source::EventBase& source)
517b79fb55SWilliam A. Kennington III {
527b79fb55SWilliam A. Kennington III     int r = unlink(fifo);
537b79fb55SWilliam A. Kennington III     if (r)
547b79fb55SWilliam A. Kennington III     {
557b79fb55SWilliam A. Kennington III         fprintf(stderr, "Failed to remove fifo %s: %s\n", fifo,
567b79fb55SWilliam A. Kennington III                 strerror(errno));
577b79fb55SWilliam A. Kennington III         source.get_event().exit(1);
587b79fb55SWilliam A. Kennington III     }
597b79fb55SWilliam A. Kennington III }
607b79fb55SWilliam A. Kennington III 
clean_exit(sdeventplus::source::Signal & source,const struct signalfd_siginfo *)617b79fb55SWilliam A. Kennington III void clean_exit(sdeventplus::source::Signal& source,
627b79fb55SWilliam A. Kennington III                 const struct signalfd_siginfo*)
637b79fb55SWilliam A. Kennington III {
647b79fb55SWilliam A. Kennington III     source.get_event().exit(0);
657b79fb55SWilliam A. Kennington III }
668f90e28bSWilliam A. Kennington III 
main(int argc,char * argv[])678f90e28bSWilliam A. Kennington III int main(int argc, char* argv[])
688f90e28bSWilliam A. Kennington III {
698f90e28bSWilliam A. Kennington III     if (argc != 2)
708f90e28bSWilliam A. Kennington III     {
717b79fb55SWilliam A. Kennington III         fprintf(stderr, "Usage: %s [named pipe to create]\n", argv[0]);
727b79fb55SWilliam A. Kennington III         return 1;
737b79fb55SWilliam A. Kennington III     }
747b79fb55SWilliam A. Kennington III     const char* fifo = argv[1];
757b79fb55SWilliam A. Kennington III 
767b79fb55SWilliam A. Kennington III     // Block all signals before changing system state so we guarantee our clean
777b79fb55SWilliam A. Kennington III     // up routines are in place
787b79fb55SWilliam A. Kennington III     sigset_t signals;
797b79fb55SWilliam A. Kennington III     if (sigfillset(&signals))
807b79fb55SWilliam A. Kennington III     {
817b79fb55SWilliam A. Kennington III         fprintf(stderr, "Failed to populate signals: %s\n", strerror(errno));
827b79fb55SWilliam A. Kennington III         return 1;
837b79fb55SWilliam A. Kennington III     }
847b79fb55SWilliam A. Kennington III     if (sigprocmask(SIG_BLOCK, &signals, nullptr))
857b79fb55SWilliam A. Kennington III     {
867b79fb55SWilliam A. Kennington III         fprintf(stderr, "Failed to mask signals: %s\n", strerror(errno));
878f90e28bSWilliam A. Kennington III         return 1;
888f90e28bSWilliam A. Kennington III     }
898f90e28bSWilliam A. Kennington III 
907b79fb55SWilliam A. Kennington III     if (mkfifo(fifo, 0622))
917b79fb55SWilliam A. Kennington III     {
927b79fb55SWilliam A. Kennington III         fprintf(stderr, "Failed to mkfifo %s: %s\n", fifo, strerror(errno));
937b79fb55SWilliam A. Kennington III         return 1;
947b79fb55SWilliam A. Kennington III     }
957b79fb55SWilliam A. Kennington III 
967b79fb55SWilliam A. Kennington III     int fd = open(fifo, O_NONBLOCK | O_RDONLY);
977b79fb55SWilliam A. Kennington III     if (fd < 0)
987b79fb55SWilliam A. Kennington III     {
997b79fb55SWilliam A. Kennington III         fprintf(stderr, "Failed to open %s: %s\n", fifo, strerror(errno));
1007b79fb55SWilliam A. Kennington III         return 1;
1017b79fb55SWilliam A. Kennington III     }
1027b79fb55SWilliam A. Kennington III 
1037b79fb55SWilliam A. Kennington III     try
1047b79fb55SWilliam A. Kennington III     {
1058f90e28bSWilliam A. Kennington III         sdeventplus::Event event = sdeventplus::Event::get_default();
1067b79fb55SWilliam A. Kennington III         sdeventplus::source::Exit remover_source(
1077b79fb55SWilliam A. Kennington III             event, std::bind(remover, fifo, std::placeholders::_1));
1087b79fb55SWilliam A. Kennington III         sdeventplus::source::Signal sigint(event, SIGINT, clean_exit);
1097b79fb55SWilliam A. Kennington III         sdeventplus::source::IO reader_source(
1107b79fb55SWilliam A. Kennington III             event, fd, EPOLLIN,
1117b79fb55SWilliam A. Kennington III             std::bind(reader, fifo, std::placeholders::_1,
1127b79fb55SWilliam A. Kennington III                       std::placeholders::_2, std::placeholders::_3));
1138f90e28bSWilliam A. Kennington III         return event.loop();
1148f90e28bSWilliam A. Kennington III     }
1157b79fb55SWilliam A. Kennington III     catch (const std::exception& e)
1167b79fb55SWilliam A. Kennington III     {
1177b79fb55SWilliam A. Kennington III         fprintf(stderr, "%s\n", e.what());
1187b79fb55SWilliam A. Kennington III         return 1;
1197b79fb55SWilliam A. Kennington III     }
1207b79fb55SWilliam A. Kennington III }
121