//
// Ce démon sert a activer des événements lorsqu'un répertoire est modifie
// par l'ajout de fichier.
//
// Ce démon s'appelle Nagy et le script d'analyse Bosca parce que
// nous avons écrit ce script juste après l’élection de Nicolas Sarkozy.
// en effet, son nom complet est :
// Nicolas, Paul, Stéphane Sarközy de Nagy-Bocsa
//
// Auteur : Serge Noiraud : Serge.Noiraud@bull.net
#define _GNU_SOURCE
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <dirent.h>
#include <syslog.h>
static volatile int event_fd;
char *progname;
static char *repertoire; // répertoire courant par défaut
static char *commande; // commande par défaut
static char *bocsanalyse; // script analyse du répertoire
static int debug=0;
static int occupe=0;
static int periodicite=300; // toutes les 5 minutes
#define MAX_CMD_LEN 4096
void usage(char *error)
{
if (strlen(error) != 0) fprintf (stderr, "%s: %s\n", progname, error);
fprintf (stderr, "Utilisation: %s \n",progname);
fprintf (stderr, "\t\tÅ[[b<Bocsanalyse> : script a appliquer au repertoire]\n");
fprintf (stderr, "\t\tÅ[[-c<Commande>: script a appliquer au fichier]\n");
fprintf (stderr, "\t\t [-d <Repertoire> a surveiller]\n");
fprintf (stderr, "\t\t [-h ( cette aide ) ]\n");
fprintf (stderr, "\t\t [-p <periodicite> : de 1 a 86400 secondes ]\n");
fprintf (stderr, "\t\t [-s DEBUG : ajout de messages dans syslog]\n");
exit (0);
}
static void handler(int sig, siginfo_t *si, void *data)
{
event_fd = si->si_fd;
}
static void Analyse_repertoire(char *repertoire)
{
DIR *dirp;
int ret;
struct dirent *dp;
char point[2]=".";
char point2[3]="..";
char *cmd;
if ( occupe == 0 ) {
occupe=1;
cmd=malloc(MAX_CMD_LEN);
sprintf(cmd,"%s -d %s -c %s ", bocsanalyse,repertoire,commande);
syslog(LOG_LOCAL7|LOG_NOTICE|LOG_ERR,
"%s : cmd='%s'", progname,cmd);
ret=system(cmd);
if ( ret == -1 )
syslog(LOG_LOCAL7|LOG_NOTICE|LOG_ERR,
"%s : erreur system %s", progname,cmd);
free(cmd);
occupe=0;
};
}
void timeout(int signr)
{
// En cas de non envoi, re-balayons le répertoire.
if ( debug == 1 ) syslog(LOG_LOCAL7|LOG_NOTICE,
"%s : analyse cyclique %s", progname,repertoire);
if ( occupe == 0 )
Analyse_repertoire(repertoire);
signal(SIGALRM,timeout); // re-armement du signal.
alarm(periodicite); // relance.
}
int main(int argc, char **argv)
{
struct sigaction act;
int fd;
int c;
extern char *optarg;
progname=argv[0];
struct stat statb;
static char *MESSAGE;
// Analyse des options données
while((c = getopt(argc, argv, "b:c:hs")) != EOF) {
switch(c){
case 'h':
usage("");
break;
case 'b':
bocsanalyse=optarg;
break;
case 'c':
commande=optarg;
break;
case 'd':
repertoire=optarg;
break;
case 's':
debug=1;
break;
case 'p':
periodicite=atoi(optarg);
if ( periodicite < 1 )
usage("Cycle analyse > ou = 1 seconde.");
if ( periodicite > 86400 )
usage("Cycle analyse < ou = 1 jour ( 86400 secondes).");
break;
case ':':
usage("argument absent");
case '?':
usage("argument non reconnu");
default:
usage("erreur inconnue");
}
}
if (strlen(bocsanalyse) == 0) {
usage("commande bocsanalyse vide");
}
MESSAGE="";
fd = open(bocsanalyse, O_RDONLY);
if ( fd == -1 ) {
MESSAGE="n'existe pas.";
} else {
if (fstat(fd,&statb) == -1) {
perror("fstat commande bocsanalyse");
MESSAGE="est impossible a analyser.";
};
if ((statb.st_mode & S_IXGRP)== 0) {
MESSAGE="n'est pas executable par le groupe.";
};
close(fd);
};
if (strlen(MESSAGE) != 0 ) {
printf("commande %s %s\n",commande,MESSAGE);
exit(1); // anomalie détectée.
};
if (strlen(commande) == 0) {
usage("commande vide");
}
MESSAGE="";
fd = open(commande, O_RDONLY);
if ( fd == -1 ) {
MESSAGE="n'existe pas.";
} else {
if (fstat(fd,&statb) == -1) {
perror("fstat commande");
MESSAGE="est impossible a analyser.";
};
if ((statb.st_mode & S_IXGRP)== 0) {
MESSAGE="n'est pas executable par le groupe.";
};
close(fd);
};
if (strlen(MESSAGE) != 0 ) {
printf("commande %s %s\n",commande,MESSAGE);
exit(1); // anomalie détectée
};
if (strlen(repertoire) == 0) {
usage("repertoire inconnu");
}
MESSAGE="";
fd = open(repertoire, O_RDONLY);
if ( fd == -1 ) {
MESSAGE="n'existe pas.";
} else {
if (fstat(fd,&statb) == -1) {
perror("fstat repertoire");
MESSAGE="est impossible a analyser.";
};
if (!S_ISDIR(statb.st_mode)) {
MESSAGE="n'est pas un repertoire.";
};
};
printf(" Le repertoire : %s %s\n",repertoire,MESSAGE);
printf(" La commande : %s\n",commande);
printf("Analyse repertoire : %s\n",bocsanalyse);
if (strlen(MESSAGE) != 0 ) exit(1); // anomalie détectée
// OK. tout semble correct.
// devenons un démon !
switch(fork()) {
case 0:
// je suis le fils. C'est OK.
break;
case -1:
// je suis le père. une erreur s'est produite.
syslog(LOG_LOCAL7|LOG_ERR,
"%s ( %d ) : ne peux pas devenir un demon",
progname,getpid());
return 127; // je signale une erreur.
default:
// je suis le père. j'ai fini mon travail.
return 0; // je m’arrête
}
// se détacher ...
if ( debug == 1 ) syslog(LOG_LOCAL7|LOG_NOTICE, "%s ( %d ) : avant setsid", progname,getpid());
setsid();
if ( debug == 1 ) syslog(LOG_LOCAL7|LOG_NOTICE, "%s ( %d ) : apres setsid", progname,getpid());
act.sa_sigaction = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
sigaction(SIGRTMIN, &act, NULL);
if ( debug == 1 ) syslog(LOG_LOCAL7|LOG_NOTICE,
"%s ( %d ) : analyse du repertoire %s",
progname,getpid(),repertoire);
// En cas de reprise, re-balayons le répertoire.
Analyse_repertoire(repertoire);
// Activer l'analyse cyclique du répertoire.
signal(SIGALRM,timeout); // re-armement du signal.
alarm(periodicite); // relance.
// OK, mettons nous en attente d'événement ...
fcntl(fd, F_SETSIG, SIGRTMIN);
fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_ATTRIB|DN_MULTISHOT);
// Bouclons jusqu'à la fin des temps.
// Seul un événement nous sortira de la fonction pause.
while (1) {
pause();
Analyse_repertoire(repertoire);
}
}
Via
oros
Par contre pardon pour les probs d'encodage, pfff :/
EDIT: J'ai essayé de réglé un peu le problème d'encodage.
T'façon y a mieux que ça pour surveiller les changements sur un fichiers ou dossiers.
inotifwait