3 * Copyright (C) 2011 Simone Piccardi
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /****************************************************************
22 * FIFO, signal, event and alarm reporter
23 * an example program for I/O multiplexing with signalfd and Co.
25 * Author: Simone Piccardi
28 * Usage: reporterd -h give all info
30 ****************************************************************/
32 * Include needed headers
34 #include <sys/types.h> /* primitive system data types */
35 #include <sys/stat.h> /* file characteristics constants and functions */
36 #include <unistd.h> /* unix standard library */
37 #include <stdio.h> /* standard I/O library */
38 #include <stdlib.h> /* C standard library */
39 #include <string.h> /* C strings library */
40 #include <errno.h> /* error definitions and routines */
41 #include <signal.h> /* signal constants, types and functions */
42 #include <fcntl.h> /* file control functions */
43 #include <sys/epoll.h> /* Linux epoll interface */
44 #include <sys/signalfd.h>/* Linux signalfd interface */
49 /* Subroutines declaration */
53 /* default name for the input fifo */
54 char *fifoname = "/tmp/reporter.fifo";
56 #define MAX_EPOLL_EV 10
58 int main(int argc, char *argv[])
60 /* Variables definition */
61 int i, n, nread, t = 10;
63 int fifofd, epfd, sigfd;
65 struct epoll_event epev, events[MAX_EPOLL_EV];
66 struct signalfd_siginfo siginf;
67 char *sig_names[] = { // signal name declaration from bits/signum.h
68 "------- ", /*0 Filler for signal names array */
69 "SIGHUP ", /*1 Hangup (POSIX). */
70 "SIGINT ", /*2 Interrupt (ANSI). */
71 "SIGQUIT ", /*3 Quit (POSIX). */
72 "SIGILL ", /*4 Illegal instruction (ANSI). */
73 "SIGTRAP ", /*5 Trace trap (POSIX). */
74 "SIGABRT ", /*6 Abort (ANSI). */
75 "SIGBUS ", /*7 BUS error (4.2 BSD). */
76 "SIGFPE ", /*8 Floating-point exception (ANSI). */
77 "SIGKILL ", /*9 Kill, unblockable (POSIX). */
78 "SIGUSR1 ", /*10 User-defined signal 1 (POSIX). */
79 "SIGSEGV ", /*11 Segmentation violation (ANSI). */
80 "SIGUSR2 ", /*12 User-defined signal 2 (POSIX). */
81 "SIGPIPE ", /*13 Broken pipe (POSIX). */
82 "SIGALRM ", /*14 Alarm clock (POSIX). */
83 "SIGTERM ", /*15 Termination (ANSI). */
84 "SIGSTKFLT ", /*16 Stack fault. */
85 "SIGCHLD ", /*17 Child status has changed (POSIX). */
86 "SIGCONT ", /*18 Continue (POSIX). */
87 "SIGSTOP ", /*19 Stop, unblockable (POSIX). */
88 "SIGTSTP ", /*20 Keyboard stop (POSIX). */
89 "SIGTTIN ", /*21 Background read from tty (POSIX). */
90 "SIGTTOU ", /*22 Background write to tty (POSIX). */
91 "SIGURG ", /*23 Urgent condition on socket (4.2 BSD). */
92 "SIGXCPU ", /*24 CPU limit exceeded (4.2 BSD). */
93 "SIGXFSZ ", /*25 File size limit exceeded (4.2 BSD). */
94 "SIGVTALRM ", /*26 Virtual alarm clock (4.2 BSD). */
95 "SIGPROF ", /*27 Profiling alarm clock (4.2 BSD). */
96 "SIGWINCH ", /*28 Window size change (4.3 BSD, Sun). */
97 "SIGIO ", /*29 I/O now possible (4.2 BSD). */
98 "SIGPWR ", /*30 Power failure restart (System V). */
99 "SIGSYS " /*31 Bad system call. */
102 * Input section: decode parameters passed in the calling
103 * Use getopt function
105 opterr = 0; /* don't want writing to stderr */
106 while ( (i = getopt(argc, argv, "ht:f:")) != -1) {
112 printf("Wrong -h option use\n");
120 t = strtol(optarg, NULL, 10);
122 case '?': /* unrecognized options */
123 printf("Unrecognized options -%c\n",optopt);
125 default: /* should not reached */
129 /* ***********************************************************
131 * Options processing completed
133 * Main code beginning
135 * ***********************************************************/
139 if ((epfd=epoll_create(5)) < 0) // epoll init
140 die("Failing on epoll_create");
141 /* Signal setup for signalfd and epoll use */
142 sigemptyset(&sigmask);
143 sigaddset(&sigmask, SIGINT);
144 sigaddset(&sigmask, SIGQUIT);
145 sigaddset(&sigmask, SIGTERM);
146 if (sigprocmask(SIG_BLOCK, &sigmask, NULL) == -1) // block signals
147 die("Failing in signalfd");
148 if ((sigfd=signalfd(-1, &sigmask, SFD_NONBLOCK)) == -1) // take a signalfd
149 die("Failing in signalfd");
150 epev.data.fd = sigfd; // add fd to epoll
151 epev.events = EPOLLIN;
152 if (epoll_ctl(epfd, EPOLL_CTL_ADD, sigfd, &epev))
153 die("Failing in signal epoll_ctl");
154 /* Fifo setup for epoll use */
155 if (mkfifo(fifoname, 0622)) { // create well known fifo if does't exist
157 die("Cannot create well known fifo");
159 if ((fifofd = open(fifoname, O_RDWR|O_NONBLOCK)) < 0) // open fifo
160 die("Cannot open well known fifo");
161 epev.data.fd = fifofd; // add fd to epoll
162 epev.events = EPOLLIN;
163 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fifofd, &epev))
164 die("Failing in fifo epoll_ctl");
166 * Main body: wait something to report
168 printf("FifoReporter starting, pid %i\n", getpid());
170 if ((n=epoll_wait(epfd, events, MAX_EPOLL_EV, -1)) < 0)
171 die("error on epoll_wait");
172 debug("Got %i events\n", n);
173 /* loop on epoll events */
174 for (i=0; i<n; i++) {
175 if (events[i].data.fd == sigfd) { // if signalfd ready
176 printf("Signal received:\n");
177 while(nread=read(sigfd, &siginf, sizeof(siginf))) {
180 die("signalfd read error");
184 if (nread != sizeof(siginf)) {
185 printf("Error on signal data read, '\n");
188 printf("Got %s\n", sig_names[siginf.ssi_signo]);
189 printf("From pid %i\n", siginf.ssi_pid);
190 if(siginf.ssi_signo == SIGINT) { // SIGINT is exit
191 printf("SIGINT means exit\n");
196 } else if (events[i].data.fd == fifofd) { // if fifofd ready
197 printf("Message from fifo:\n");
198 while ((nread = read(fifofd, buffer, 5000))) {
199 debug("read %i from fifofd %i, event %i\n",
200 nread, fifofd, events[i].data.fd );
203 die("fifo read error");
205 printf("end message\n");
209 if (fputs(buffer, stdout) == EOF)
210 die("Error on terminal write");
212 } else { // anything else is an error
213 printf("epoll activity on unknown %i file descriptor\n",
219 debug("Exiting for unknown reasons\n");
222 * routine to print usage info and exit
225 printf("Elementary event reporter\n");
227 printf(" reporterd [-h] [-f] -n XXX \n");
228 printf(" -h\t print this help\n");
229 printf(" -f\t filename set fifo file\n");
233 * Print error message and exit routine
235 void die(char * mess) {