Subversion Repositories public

Compare Revisions

Ignore whitespace Rev 46 → Rev 47

/incron/trunk/icd-main.cpp
20,6 → 20,7
#include <dirent.h>
#include <syslog.h>
#include <errno.h>
#include <sys/poll.h>
 
#include "inotify-cxx.h"
#include "incrontab.h"
26,7 → 27,7
 
#include "usertable.h"
 
#define DAEMON false
#define DAEMON true
 
#define INCRON_APP_NAME "incrond"
#define INCRON_LOG_OPTS (LOG_CONS | LOG_PID)
38,19 → 39,31
 
SUT_MAP g_ut;
 
bool g_fFinish = false;
volatile bool g_fFinish = false;
 
 
/// Handles a signal.
/**
* For SIGTERM and SIGINT it sets the program finish variable.
*
* \param[in] signo signal number
*/
void on_signal(int signo)
{
g_fFinish = true;
if (signo == SIGTERM || signo == SIGINT)
g_fFinish = true;
}
 
void on_child(int signo)
{
wait(NULL);
}
 
/// Checks whether an user exists and has permission to use incron.
/**
* It searches for the given user name in the user database.
* If it failes it returns 'false'. Otherwise it checks
* permission files for this user (see InCronTab::CheckUser()).
*
* \param[in] user user name
* \return true = user has permission to use incron, false = otherwise
*
* \sa InCronTab::CheckUser()
*/
bool check_user(const char* user)
{
struct passwd* pw = getpwnam(user);
60,13 → 73,20
return InCronTab::CheckUser(user);
}
 
bool load_tables(Inotify* pIn, EventDispatcher* pEd)
/// Attempts to load all user incron tables.
/**
* Loaded tables are registered for processing events.
*
* \param[in] pIn inotify object
* \param[in] pEd inotify event dispatcher
*
* \throw InotifyException thrown if base table directory cannot be read
*/
void load_tables(Inotify* pIn, EventDispatcher* pEd) throw (InotifyException)
{
DIR* d = opendir(INCRON_TABLE_BASE);
if (d == NULL) {
syslog(LOG_CRIT, "cannot open table directory: %s", strerror(errno));
return false;
}
if (d == NULL)
throw InotifyException("cannot open table directory", errno);
syslog(LOG_NOTICE, "loading user tables");
87,9 → 107,16
}
closedir(d);
return true;
}
 
/// Main application function.
/**
* \param[in] argc argument count
* \param[in] argv argument array
* \return 0 on success, 1 on error
*
* \attention In daemon mode, it finishes immediately.
*/
int main(int argc, char** argv)
{
openlog(INCRON_APP_NAME, INCRON_LOG_OPTS, INCRON_LOG_FACIL);
96,38 → 123,56
syslog(LOG_NOTICE, "starting service");
Inotify in;
EventDispatcher ed(&in);
if (!load_tables(&in, &ed)) {
closelog();
return 1;
}
signal(SIGTERM, on_signal);
signal(SIGINT, on_signal);
signal(SIGCHLD, on_child);
if (DAEMON)
daemon(0, 0);
uint32_t wm = IN_CLOSE_WRITE | IN_DELETE | IN_MOVE | IN_DELETE_SELF | IN_UNMOUNT;
InotifyWatch watch(INCRON_TABLE_BASE, wm);
in.Add(watch);
syslog(LOG_NOTICE, "ready to process filesystem events");
InotifyEvent e;
while (!g_fFinish) {
if (in.WaitForEvents()) {
try {
Inotify in;
in.SetNonBlock(true);
EventDispatcher ed(&in);
try {
load_tables(&in, &ed);
} catch (InotifyException e) {
int err = e.GetErrorNumber();
syslog(LOG_CRIT, "%s: (%i) %s", e.GetMessage().c_str(), err, strerror(err));
syslog(LOG_NOTICE, "stopping service");
closelog();
return 1;
}
signal(SIGTERM, on_signal);
signal(SIGINT, on_signal);
signal(SIGCHLD, on_signal);
if (DAEMON)
daemon(0, 0);
uint32_t wm = IN_CLOSE_WRITE | IN_DELETE | IN_MOVE | IN_DELETE_SELF | IN_UNMOUNT;
InotifyWatch watch(INCRON_TABLE_BASE, wm);
in.Add(watch);
syslog(LOG_NOTICE, "ready to process filesystem events");
InotifyEvent e;
struct pollfd pfd;
pfd.fd = in.GetDescriptor();
pfd.events = POLLIN;
pfd.revents = (short) 0;
while (!g_fFinish) {
int res = poll(&pfd, 1, -1);
if (res > 0) {
in.WaitForEvents(true);
UserTable::FinishDone();
}
else if (res < 0) {
if (errno != EINTR)
throw InotifyException("polling failed", errno, NULL);
}
while (in.GetEvent(e)) {
std::string s;
e.DumpTypes(s);
//syslog(LOG_DEBUG, "EVENT: wd=%i, cookie=%u, name=%s, mask: %s", (int) e.GetDescriptor(), (unsigned) e.GetCookie(), e.GetName().c_str(), s.c_str());
if (e.GetWatch() == &watch) {
if (e.IsType(IN_DELETE_SELF) || e.IsType(IN_UNMOUNT)) {
syslog(LOG_CRIT, "base directory destroyed, exitting");
163,6 → 208,11
}
}
}
} catch (InotifyException e) {
int err = e.GetErrorNumber();
syslog(LOG_CRIT, "*** unhandled exception occurred ***");
syslog(LOG_CRIT, " %s", e.GetMessage().c_str());
syslog(LOG_CRIT, " error: (%i) %s", err, strerror(err));
}
 
syslog(LOG_NOTICE, "stopping service");