#include #include #include #include #include #include "nfcommander.h" #include "config.h" #include "reader.h" #include "control.h" #include "command.h" typedef union { struct { uint32_t system; uint32_t fd; } components; uint64_t u64; } epoll_private_t; static volatile sig_atomic_t shutdown_requested = 0; static volatile sig_atomic_t pid_signaled = 0; static int epoll_fd = -1; static void signal_handler(int signum){ if(signum == SIGCHLD){ pid_signaled = 1; } else { shutdown_requested = 1; } } static int usage(char* fn){ printf("NFCommander %s - trigger actions based on near-field tags\n", NFCOMMANDER_VERSION); printf("\tUsage: %s \n", fn); return EXIT_FAILURE; } int core_manage_fd(int fd, int manage, notification_target_t system){ epoll_private_t data = { .components.system = system, .components.fd = fd }; struct epoll_event event = { .events = EPOLLIN, .data.u64 = data.u64 }; if(fd < 0){ return 0; } if(epoll_ctl(epoll_fd, manage ? EPOLL_CTL_ADD : EPOLL_CTL_DEL, fd, &event)){ perror("core/epoll_mod"); shutdown_requested = 1; return 1; } return 0; } int main(int argc, char** argv){ size_t n; int event_count; epoll_private_t polldata; if(argc < 2){ return usage(argv[0]); } //set up epoll instance struct epoll_event events[10]; epoll_fd = epoll_create1(EPOLL_CLOEXEC); if(epoll_fd < 0){ perror("core/epoll"); return EXIT_FAILURE; } //read configuration if(config_read(argv[1])){ //TODO cleanup return usage(argv[0]); } //start reader api if(reader_init()){ //TODO cleanup return EXIT_FAILURE; } //start control api if(control_start()){ printf("Failed to start control interface\n"); //TODO cleanup return EXIT_FAILURE; } //handle signals signal(SIGINT, signal_handler); signal(SIGCHLD, signal_handler); signal(SIGPIPE, SIG_IGN); //handle events while(!shutdown_requested){ event_count = epoll_wait(epoll_fd, events, sizeof(events) / sizeof(struct epoll_event), 1000); if(event_count < 0){ perror("core/poll"); break; } for(n = 0; n < event_count; n++){ polldata.u64 = events[n].data.u64; //TODO error checking switch(polldata.components.system){ case system_control: control_handle(polldata.components.fd); break; case system_reader: reader_handle(polldata.components.fd); break; case system_command: command_handle(polldata.components.fd); break; default: printf("Unhandled target system for fd %d\n", polldata.components.fd); break; } } if(pid_signaled){ pid_signaled = 0; command_reap(); } } //clean up reader_free(); control_free(); command_free(); config_free(); close(epoll_fd); epoll_fd = -1; }