Sophie

Sophie

distrib > Fedora > 14 > i386 > by-pkgid > 58a5ede102e1d98b5f21bc2102c4b730 > files > 8

fcron-3.0.5-1.fc14.src.rpm

/*	--*- c -*--
 * 
 * placed in the public domain by Patrice Dumas, Dec 2008.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/inotify.h>
#include <libgen.h>
#include <sys/types.h>
#include <dirent.h>

typedef struct fcron_watched_file {
   char * filename;
   int already_here;
} fcron_watched_file;

#ifndef SYSCONFDIR
# define SYSCONFDIR "/etc"
#endif

#ifndef CRONDIR
#define CRONDIR SYSCONFDIR "/cron.d" 
#endif

fcron_watched_file watched_config_files [] = {
 { SYSCONFDIR "/crontab", 0 },
 { SYSCONFDIR "/fcrontab", 0 },
 { CRONDIR, 0 },
 {NULL, 0}
};

/* size of the event structure, not counting name */
#define EVENT_SIZE  (sizeof (struct inotify_event))
/* 1024 events with filenames of length 1024 */
#define BUF_LEN        (1024 * (EVENT_SIZE + 1024))
char events_buffer[BUF_LEN];

int main(int argc, char *argv[])
{
 int fd;
 int watch_desc;
 int watch_desc_sysconfdir;
 int watch_sysconfdir = 0;
 fcron_watched_file *watched_file;
 struct stat st;
 int debug = 0;

 fd = inotify_init();
 if (fd < 0) {
  perror("inotify_init()");
  return EXIT_FAILURE;
 }

 /* 
 * if file or dir exist, add a watch, otherwise set a watch on the up 
 * directory to watch file appear */
 for (watched_file = watched_config_files; watched_file->filename != NULL; watched_file++) {
  if (lstat(watched_file->filename, &st) == 0) {
   watch_desc = inotify_add_watch(fd, watched_file->filename, IN_CLOSE_WRITE | IN_ATTRIB | IN_MOVED_TO | IN_MOVED_FROM | IN_MOVE_SELF | IN_DELETE);
   if (watch_desc < 0) {
    if (lstat(watched_file->filename, &st) == 0) {
     fprintf(stderr, "inotify_add_watch(%s): %s\n", watched_file->filename, strerror(errno));
     close(fd);
     return EXIT_FAILURE;
    }
    else /* file was removed between the first stat and inotify_add_watch */
     return EXIT_SUCCESS;
   }
   watched_file->already_here = 1;
   if (debug)
    fprintf(stderr, "File/dir already there: %s\n", watched_file->filename);
  }
  else if (! watch_sysconfdir) {
   watch_desc_sysconfdir = inotify_add_watch(fd, SYSCONFDIR, IN_CREATE | IN_MOVED_TO);
   if (watch_desc_sysconfdir < 0) {
    perror("inotify_add_watch("SYSCONFDIR")");
    close(fd);
    return EXIT_FAILURE;
   }
   if (debug)
    fprintf(stderr, "Watching " SYSCONFDIR " (for %s)\n", watched_file->filename);
   watch_sysconfdir = 1;
  }
 }

 /* the loop is needed in case a file or directory is missing
 * since in that case we don't exit if another file is added in 
 * SYSCONFDIR */
 while (1)
 {
  fd_set fds;
  int rc;
  int len;
  int i = 0;

  FD_ZERO(&fds);
  FD_SET(fd, &fds);
  rc = select(fd+1, &fds, NULL, NULL, NULL);
  if (rc < 0) {
   perror("select()");
   close(fd);
   return EXIT_FAILURE;
  }

  len = read (fd, events_buffer, BUF_LEN);
  if (len < 0) {
   perror ("read");
   close(fd);
   return EXIT_FAILURE;
  }
  else if (!len) {/* what does it mean ?*/
   /* in doubt it is as if something changed */
   return EXIT_SUCCESS;
  }
  
  while (i < len)
  {
   struct inotify_event *event;
   event = (struct inotify_event *) &events_buffer[i];
   if (debug)
   {
     printf ("wd=%d mask=%u cookie=%u len=%u\n",
        event->wd, event->mask, event->cookie, event->len);
     if (event->len)
      printf ("name=%s\n", event->name); 
   }
   if (watch_sysconfdir && (event->wd == watch_desc_sysconfdir) && event->len) {
    for (watched_file = watched_config_files; watched_file->filename != NULL; watched_file++) {
     if ((strcmp(event->name, basename(watched_file->filename)) == 0) && (!watched_file->already_here)) 
      return EXIT_SUCCESS;
    }
    i += EVENT_SIZE + event->len;
   }
   else 
    return EXIT_SUCCESS;
  }
 }
}