#include <signal.h> /* signal constants, types and functions */
#include <fcntl.h> /* file control functions */
#include <sys/epoll.h> /* Linux epoll interface */
+#include <sys/signalfd.h>/* Linux signalfd interface */
#include "macros.h"
#include "Gapil.h"
/* Subroutines declaration */
void usage(void);
+void die(char *);
/* default name for the input fifo */
char *fifoname = "/tmp/reporter.fifo";
+#define MAX_EPOLL_EV 10
+
int main(int argc, char *argv[])
{
/* Variables definition */
- int i, nread, t = 1;
+ int i, n, nread, t = 10;
char buffer[4096];
int fifofd, epfd, sigfd;
- struct epoll_event epev;
sigset_t sigmask;
- char buffer[1024];
+ struct epoll_event epev, events[MAX_EPOLL_EV];
+ struct signalfd_siginfo siginf;
+ char *sig_names[] = { // signal name declaration from bits/signum.h
+ "------- ", /*0 Filler for signal names array */
+ "SIGHUP ", /*1 Hangup (POSIX). */
+ "SIGINT ", /*2 Interrupt (ANSI). */
+ "SIGQUIT ", /*3 Quit (POSIX). */
+ "SIGILL ", /*4 Illegal instruction (ANSI). */
+ "SIGTRAP ", /*5 Trace trap (POSIX). */
+ "SIGABRT ", /*6 Abort (ANSI). */
+ "SIGBUS ", /*7 BUS error (4.2 BSD). */
+ "SIGFPE ", /*8 Floating-point exception (ANSI). */
+ "SIGKILL ", /*9 Kill, unblockable (POSIX). */
+ "SIGUSR1 ", /*10 User-defined signal 1 (POSIX). */
+ "SIGSEGV ", /*11 Segmentation violation (ANSI). */
+ "SIGUSR2 ", /*12 User-defined signal 2 (POSIX). */
+ "SIGPIPE ", /*13 Broken pipe (POSIX). */
+ "SIGALRM ", /*14 Alarm clock (POSIX). */
+ "SIGTERM ", /*15 Termination (ANSI). */
+ "SIGSTKFLT ", /*16 Stack fault. */
+ "SIGCHLD ", /*17 Child status has changed (POSIX). */
+ "SIGCONT ", /*18 Continue (POSIX). */
+ "SIGSTOP ", /*19 Stop, unblockable (POSIX). */
+ "SIGTSTP ", /*20 Keyboard stop (POSIX). */
+ "SIGTTIN ", /*21 Background read from tty (POSIX). */
+ "SIGTTOU ", /*22 Background write to tty (POSIX). */
+ "SIGURG ", /*23 Urgent condition on socket (4.2 BSD). */
+ "SIGXCPU ", /*24 CPU limit exceeded (4.2 BSD). */
+ "SIGXFSZ ", /*25 File size limit exceeded (4.2 BSD). */
+ "SIGVTALRM ", /*26 Virtual alarm clock (4.2 BSD). */
+ "SIGPROF ", /*27 Profiling alarm clock (4.2 BSD). */
+ "SIGWINCH ", /*28 Window size change (4.3 BSD, Sun). */
+ "SIGIO ", /*29 I/O now possible (4.2 BSD). */
+ "SIGPWR ", /*30 Power failure restart (System V). */
+ "SIGSYS " /*31 Bad system call. */
+ };
/*
* Input section: decode parameters passed in the calling
* Use getopt function
/*
* Initial setup
*/
- if (mkfifo(fifoname, 0622)) { // create well known fifo if does't exist
- if (errno!=EEXIST) {
- perror("Cannot create well known fifo");
- exit(1);
- }
- }
- epfd = epoll_create(5); // initialize epoll
- if (epfd < 0) {
- perror("Failing on epoll_create");
- exit(1);
- }
- if ((fifofd = open(fifoname, O_RDONLY|O_NONBLOCK)) < 0) { // open fifo
- perror("Cannot open read only well known fifo");
- exit(1);
- }
- epev.data.fd = fifofd; /* add fifofd to epoll */
- epev.events = EPOLLIN;
- if (epoll_ctl(epfd, EPOLL_CTL_ADD, fifofd, &epev)) {
- perror("Failing in epoll_ctl");
- exit(-1);
- }
+ if ((epfd=epoll_create(5)) < 0) // epoll init
+ die("Failing on epoll_create");
+ /* Signal setup for signalfd and epoll use */
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGINT);
sigaddset(&sigmask, SIGQUIT);
sigaddset(&sigmask, SIGTERM);
- // blocking signal treated by signalfd to avoid default action
- if (sigprocmask(SIG_BLOCK, &sigmask, NULL) == -1) {
- perror("Failing in sigprocmask");
- exit(1);
- }
- if ((sigfd=signalfd(-1, &sigmask, SFD_NONBLOCK)) == -1) {
- perror("Failing in signalfd");
- exit(-1);
- }
- epev.data.fd = sigfd; /* add sigfd to epoll */
+ if (sigprocmask(SIG_BLOCK, &sigmask, NULL) == -1) // block signals
+ die("Failing in signalfd");
+ if ((sigfd=signalfd(-1, &sigmask, SFD_NONBLOCK)) == -1) // take a signalfd
+ die("Failing in signalfd");
+ epev.data.fd = sigfd; // add fd to epoll
epev.events = EPOLLIN;
- if (epoll_ctl(epfd, EPOLL_CTL_ADD, sigfd, &epev)) {
- perror("Failing in epoll_ctl");
- exit(-1);
+ if (epoll_ctl(epfd, EPOLL_CTL_ADD, sigfd, &epev))
+ die("Failing in signal epoll_ctl");
+ /* Fifo setup for epoll use */
+ if (mkfifo(fifoname, 0622)) { // create well known fifo if does't exist
+ if (errno!=EEXIST)
+ die("Cannot create well known fifo");
}
-
- /* Main body: loop over requests */
+ if ((fifofd = open(fifoname, O_RDWR|O_NONBLOCK)) < 0) // open fifo
+ die("Cannot open well known fifo");
+ epev.data.fd = fifofd; // add fd to epoll
+ epev.events = EPOLLIN;
+ if (epoll_ctl(epfd, EPOLL_CTL_ADD, fifofd, &epev))
+ die("Failing in fifo epoll_ctl");
+ /*
+ * Main body: wait something to report
+ */
+ printf("FifoReporter starting, pid %i\n", getpid());
while (1) {
- if ((i = epoll_wait(epfd, &epev, 1, -1)) < 0) {
- perror("error on epoll_wait");
- exit(-1);
- }
- switch (epev.fd) {
- /*
- * Handling options
- */
- case sigfd:
- // signals
- break;
- case fifofd:
- // fifo
- break;
- default: /* should not reached */
- printf("something wrong, epoll activity on unknown %i file descriptor\n", epev.data.fd);
- exit(-1);
+ if ((n=epoll_wait(epfd, events, MAX_EPOLL_EV, -1)) < 0)
+ die("error on epoll_wait");
+ debug("Got %i events\n", n);
+ /* loop on epoll events */
+ for (i=0; i<n; i++) {
+ if (events[i].data.fd == sigfd) { // if signalfd ready
+ printf("Signal received:\n");
+ while(nread=read(sigfd, &siginf, sizeof(siginf))) {
+ if (nread < 0) {
+ if (errno != EAGAIN)
+ die("signalfd read error");
+ else
+ break;
+ }
+ if (nread != sizeof(siginf)) {
+ printf("Error on signal data read, '\n");
+ continue;
+ }
+ printf("Got %s\n", sig_names[siginf.ssi_signo]);
+ printf("From pid %i\n", siginf.ssi_pid);
+ if(siginf.ssi_signo == SIGINT) { // SIGINT is exit
+ printf("SIGINT means exit\n");
+ unlink(fifoname);
+ exit(0);
+ }
+ }
+ } else if (events[i].data.fd == fifofd) { // if fifofd ready
+ printf("Message from fifo:\n");
+ while ((nread = read(fifofd, buffer, 5000))) {
+ debug("read %i from fifofd %i, event %i\n",
+ nread, fifofd, events[i].data.fd );
+ if (nread < 0) {
+ if (errno != EAGAIN)
+ die("fifo read error");
+ else
+ printf("end message\n");
+ break;
+ }
+ buffer[nread] = 0;
+ if (fputs(buffer, stdout) == EOF)
+ die("Error on terminal write");
+ }
+ } else { // anything else is an error
+ printf("epoll activity on unknown %i file descriptor\n",
+ epev.data.fd);
+ exit(-1);
+ }
}
-
}
debug("Exiting for unknown reasons\n");
}
* routine to print usage info and exit
*/
void usage(void) {
- printf("Elementary fortune server\n");
+ printf("Elementary event reporter\n");
printf("Usage:\n");
- printf(" fortuned [-h] [-f] -n XXX \n");
- printf(" -h print this help\n");
- printf(" -t filename set fifo file\n");
+ printf(" reporterd [-h] [-f] -n XXX \n");
+ printf(" -h\t print this help\n");
+ printf(" -f\t filename set fifo file\n");
exit(1);
}
/*
- * Signal Handler to manage termination
+ * Print error message and exit routine
*/
-void HandSIGTERM(int signo) {
- debug("Terminated by %s\n", strsignal(signo));
- unlink(fifoname);
- exit(0);
+void die(char * mess) {
+ perror(mess);
+ exit(-1);
}