/* dispatcher.c -- * * This is a sample program that you can customize to create your own syslog * event handler. It will be started by syslog via the dispatcher option on * command line. This program can be built as follows: * * gcc dispatcher.c -o dispatcher */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sysklogd-dispatch.h" /* Local data */ static volatile int signaled = 0; static int pipe_fd; static struct sockaddr_un my_addr; static int fd; /* Local functions */ static int event_loop(void); /* SIGTERM handler */ static void term_handler( int sig ) { signaled = 1; } /* * main is started by sysklogd. See dispatcher in man sysklogd. */ int main(int argc, char *argv[]) { struct sigaction sa; struct stat stat_buf; setlocale (LC_ALL, ""); fprintf(stderr, "starting dispatcher...\n"); #ifndef DEBUG /* Make sure we are root */ if (getuid() != 0) { fprintf(stderr, "You must be root to run this program."); exit(1); } #endif /* register sighandlers */ sa.sa_flags = 0 ; sa.sa_handler = term_handler; sigemptyset( &sa.sa_mask ) ; sigaction( SIGTERM, &sa, NULL ); /* sa.sa_handler = term_handler; sigemptyset( &sa.sa_mask ) ; sigaction( SIGCHLD, &sa, NULL ); */ sa.sa_handler = SIG_IGN; sigaction( SIGHUP, &sa, NULL ); sigaction( SIGPIPE, &sa, NULL ); (void)chdir("/"); /* change over to pipe_fd */ pipe_fd = dup(0); close(0); fcntl(pipe_fd, F_SETFD, FD_CLOEXEC); /* Setup server */ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { perror("socket()"); exit(1); } fcntl(fd, F_SETFD, O_NONBLOCK); my_addr.sun_family=AF_UNIX; strncpy(my_addr.sun_path, "/tmp/dispatcher.sock", sizeof(my_addr.sun_path)); unlink(my_addr.sun_path); /* not necessary */ if (bind(fd, (struct sockaddr *) &my_addr, sizeof(my_addr)) == -1) { perror("bind()"); exit(1); } stat(my_addr.sun_path, &stat_buf); chmod(my_addr.sun_path, stat_buf.st_mode | S_IWOTH); if (listen(fd, 1) == -1) { perror("listen()"); exit(1); } /* Start the program */ return event_loop(); } static int event_loop(void) { void* data; struct iovec vec[2]; struct sysklogd_dispatcher_header hdr; pid_t pid; static socklen_t addrlen; int new_fd = -1; /* Allocate data structures */ data = malloc(MAXLINE); if (data == NULL) { fprintf(stderr, "Cannot allocate buffer\n"); return 1; } do { int rc; struct timeval tv; fd_set fdset; /* if there isn't anybody connected to server, try accept */ if (new_fd == -1 ) { addrlen = sizeof(my_addr); if ((new_fd = accept( fd, (struct sockaddr *) &my_addr, &addrlen))==-1) { perror("accept()"); exit(1); } } memset(data, 0, MAXLINE); memset(&hdr, 0, sizeof(hdr)); tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO(&fdset); FD_SET(pipe_fd, &fdset); rc = select(pipe_fd+1, &fdset, NULL, NULL, &tv); if (rc == 0) continue; else if (rc == -1) break; /* Get header first. it is fixed size */ vec[0].iov_base = (void*)&hdr; vec[0].iov_len = sizeof(hdr); rc = readv(pipe_fd, vec, 1); if (rc == 0 || rc == -1) { fprintf(stderr, "rc == %d(%s)\n", rc, strerror(errno)); break; } /* Analyze header */ /*nothing to do at the momemnt */ /* Next payload */ vec[1].iov_base = data; vec[1].iov_len = MAXLINE; rc = readv(pipe_fd, &vec[1], 1); if (rc == 0 || rc == -1) { fprintf(stderr, "rc == %d(%s)\n", rc, strerror(errno)); break; } /* handle some events here. */ if (new_fd != -1) { rc = write(new_fd, (char *)data, strlen(data)); if (rc <= 0) { if (errno == EPIPE) { close(new_fd); new_fd=-1; } else { perror("writev()"); new_fd=-1; } } } /* if( strstr((char *)data, "oops") ) { pid = fork(); if( !pid ) { execl("/usr/bin/zenity","/usr/bin/zenity","--warning", "--text", (char *)data, NULL); fprintf(stderr, "exec() failed\n"); } } */ /* fprintf(stderr,"type=%d, payload size=%d\n", hdr.type, hdr.size); fprintf(stderr,"data=\"%.*s\"\n", hdr.size, (char *)data); */ } while(!signaled); return 0; }