int main(int argc, char **argv) { struct sigaction sa; int inotify_fd; int ret; int pid_fd; sigemptyset(&sa.sa_mask); sa.sa_handler = signal_handler; sa.sa_flags = SA_RESTART; if (sigaction(SIGHUP, &sa, NULL) < 0) { syslog(LOG_ERR, "failed to listen for signal SIGHUP : %m"); exit(EXIT_FAILURE); } if (sigaction(SIGTERM, &sa, NULL) < 0) { syslog(LOG_ERR, "failed to listen for signal SIGTERM : %m"); exit(EXIT_FAILURE); } pid_fd = daemonize(); if (pid_fd < 0) exit(EXIT_FAILURE); clear_all_rules(); load_all_rules(); inotify_fd = configure_inotify(); while (inotify_fd >= 0 && !terminate && !restart) { ret = monitor(inotify_fd); if (ret < 0 && errno == EINTR) { continue; } else if (ret < 0) { syslog(LOG_ERR, "Failed to monitor properly : %m"); break; } ret = handle_inotify_event(inotify_fd); if (ret < 0) break; } close(pid_fd); remove(PID_FILE); if (restart && execv(argv[0], argv)) syslog(LOG_ERR, "Failed to restart : %m"); clear_all_rules(); syslog(LOG_DEBUG, "Finished %s", argv[0]); exit(terminate == 1 ? EXIT_SUCCESS : EXIT_FAILURE); }
int process_inotify_event(int fd) { char buffer[512]; int len; int offset = 0; if ((len = read(fd, buffer, sizeof(buffer))) < 0) { LOGE("Unable to read inotify event (%m)\n"); return -errno; } while (len >= (int) sizeof(struct inotify_event)) { struct inotify_event *evt = (struct inotify_event *) &buffer[offset]; if (handle_inotify_event(evt) < 0) LOGE("Error handling inotify event (%m)\n"); len -= sizeof(struct inotify_event) + evt->len; offset += sizeof(struct inotify_event) + evt->len; } return 0; }
static int watch_files(struct file_struct *_files, int n_files) { int ifd, i; char buf[n_files * INOTIFY_BUFLEN]; ifd = inotify_init(); if (errno == ENOSYS) { fprintf(stderr, "Error: inotify is not supported by the kernel you're currently running.\n"); exit(EXIT_FAILURE); } else if (unlikely(ifd < 0)) { fprintf(stderr, "Error: Could not initialize inotify (%s)\n", strerror(errno)); exit(EXIT_FAILURE); } for (i = 0; i < n_files; i++) { if (!_files[i].ignore) { _files[i].i_watch = inotify_add_watch(ifd, _files[i].name, IN_MODIFY|IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT); if (_files[i].i_watch < 0) { fprintf(stderr, "Error: Could not create inotify watch on file '%s' (%s)\n", _files[i].name, strerror(errno)); ignore_file(&_files[i]); } } } while (n_ignored < n_files) { ssize_t len; int ev_idx = 0; len = read(ifd, buf, (n_files * INOTIFY_BUFLEN)); if (unlikely(len < 0)) { /* Some signal, likely ^Z/fg's STOP and CONT interrupted the inotify read, retry */ if (errno == EINTR || errno == EAGAIN) continue; else { fprintf(stderr, "Error: Could not read inotify events (%s)\n", strerror(errno)); exit(EXIT_FAILURE); } } while (ev_idx < len) { struct inotify_event *inev; struct file_struct *f = NULL; inev = (struct inotify_event *) &buf[ev_idx]; /* Which file has produced the event? */ for (i = 0; i < n_files; i++) { if (!_files[i].ignore && _files[i].fd >= 0 && _files[i].i_watch == inev->wd) { f = &_files[i]; break; } } if (unlikely(!f)) break; if (handle_inotify_event(inev, f) < 0) break; ev_idx += sizeof(struct inotify_event) + inev->len; } } close(ifd); return -1; }