1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
#include <stdio.h>
#include <signal.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <errno.h>
#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 <config-file>\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;
}
|