Subversion Repositories public

Compare Revisions

Ignore whitespace Rev 48 → Rev 49

/incron/trunk/ict-main.cpp
29,10 → 29,10
#define INCRON_DEFAULT_EDITOR "vim"
 
 
const char* argp_program_version = "incrontab 0.1.0";
const char* argp_program_version = "incrontab 0.3.0";
const char* argp_program_bug_address = "<bugs@aiken.cz>";
 
static char doc[] = "Table manipulator for incrond (inotify Cron daemon)";
static char doc[] = "Table manipulator for incrond (inotify cron daemon)";
 
static char args_doc[] = "FILE";
 
44,22 → 44,31
{ 0 }
};
 
enum
/// incrontab operations
typedef enum
{
OPER_NONE,
OPER_LIST,
OPER_REMOVE,
OPER_EDIT
};
OPER_NONE, /// nothing
OPER_LIST, /// list table
OPER_REMOVE, /// remove table
OPER_EDIT /// edit table
} InCronTab_Operation_t;
 
/// incrontab arguments
struct arguments
{
char *user;
int oper;
char *file;
char *user; /// user name
int oper; /// operation code
char *file; /// file to import
};
 
static error_t parse_opt (int key, char *arg, struct argp_state *state)
/// Parses the program options (arguments).
/**
* \param[in] key argument key (name)
* \param[in] arg argument value
* \param[out] state options setting
* \return 0 on success, ARGP_ERR_UNKNOWN on unknown argument(s)
*/
static error_t parse_opt(int key, char *arg, struct argp_state *state)
{
struct arguments* arguments = (struct arguments*) state->input;
90,9 → 99,16
return 0;
}
 
 
/// Program arguments
static struct argp argp = { options, parse_opt, args_doc, doc };
 
/// Unlink a file with temporarily changed UID.
/**
* \param[in] file file to unlink
* \param[in] uid UID for unlink processing
*
* \attention No error checking is done!
*/
void unlink_suid(const char* file, uid_t uid)
{
uid_t iu = geteuid();
101,6 → 117,12
seteuid(iu);
}
 
/// Copies a file to an user table.
/**
* \param[in] path path to file
* \param[in] user user name
* \return true = success, false = failure
*/
bool copy_from_file(const char* path, const char* user)
{
InCronTab tab;
121,6 → 143,11
return true;
}
 
/// Removes an user table.
/**
* \param[in] user user name
* \return true = success, false = failure
*/
bool remove_table(const char* user)
{
std::string tp(InCronTab::GetUserTablePath(user));
133,6 → 160,13
return true;
}
 
/// Lists an user table.
/**
* \param[in] user user name
* \return true = success, false = failure
*
* \attention Listing is currently done through 'cat'.
*/
bool list_table(const char* user)
{
std::string tp(InCronTab::GetUserTablePath(user));
153,6 → 187,15
return system(cmd.c_str()) == 0;
}
 
/// Allows to edit an user table.
/**
* \param[in] user user name
* \return true = success, false = failure
*
* \attention This function is very complex and may contain
* various bugs including security ones. Please keep
* it in mind..
*/
bool edit_table(const char* user)
{
std::string tp(InCronTab::GetUserTablePath(user));
/incron/trunk/CHANGELOG
1,3 → 1,11
0.2.1 2006-10-14
* based on inotify-cxx 0.4.1 (it should also fix crashing as described in #0000085)
* build failure (due to missing 'useradd -M') on some distributions has been fixed
(#0000094)
* tarball structure has been fixed (#0000089)
* documentation slightly improved
 
 
0.2.0 2006-10-04
* based on inotify-cxx 0.3.1
* better signal handling (no "dirty" wait() in a handler)
/incron/trunk/inotify-cxx.cpp
81,6 → 81,16
else if (rName == "IN_ALL_EVENTS")
return IN_ALL_EVENTS;
#ifdef IN_DONT_FOLLOW
else if (rName == "IN_DONT_FOLLOW")
return IN_DONT_FOLLOW;
#endif // IN_DONT_FOLLOW
 
#ifdef IN_ONLYDIR
else if (rName == "IN_ONLYDIR")
return IN_ONLYDIR;
#endif // IN_ONLYDIR
return (uint32_t) 0;
}
 
169,6 → 179,20
DUMP_SEP;
rStr.append("IN_ONESHOT");
}
#ifdef IN_DONT_FOLLOW
if (IsType(uValue, IN_DONT_FOLLOW)) {
DUMP_SEP;
rStr.append("IN_DONT_FOLLOW");
}
#endif // IN_DONT_FOLLOW
#ifdef IN_ONLYDIR
if (IsType(uValue, IN_ONLYDIR)) {
DUMP_SEP;
rStr.append("IN_ONLYDIR");
}
#endif // IN_ONLYDIR
}
 
void InotifyEvent::DumpTypes(std::string& rStr) const
177,11 → 201,46
}
 
 
void InotifyWatch::SetMask(uint32_t uMask) throw (InotifyException)
{
if (m_wd != -1) {
int wd = inotify_add_watch(m_pInotify->GetDescriptor(), m_path.c_str(), uMask);
if (wd != m_wd)
throw InotifyException(IN_EXC_MSG("changing mask failed"), wd == -1 ? errno : EINVAL, this);
}
m_uMask = uMask;
}
 
void InotifyWatch::SetEnabled(bool fEnabled) throw (InotifyException)
{
if (fEnabled == m_fEnabled)
return;
if (m_pInotify != NULL) {
if (fEnabled) {
m_wd = inotify_add_watch(m_pInotify->GetDescriptor(), m_path.c_str(), m_uMask);
if (m_wd == -1)
throw InotifyException(IN_EXC_MSG("enabling watch failed"), errno, this);
m_pInotify->m_watches.insert(IN_WATCH_MAP::value_type(m_wd, this));
}
else {
if (inotify_rm_watch(m_pInotify->GetDescriptor(), m_wd) != 0)
throw InotifyException(IN_EXC_MSG("disabling watch failed"), errno, this);
m_pInotify->m_watches.erase(m_wd);
m_wd = -1;
}
}
m_fEnabled = fEnabled;
}
 
 
Inotify::Inotify() throw (InotifyException)
{
m_fd = inotify_init();
if (m_fd == -1)
throw InotifyException(std::string(__PRETTY_FUNCTION__) + ": inotify init failed", errno, NULL);
throw InotifyException(IN_EXC_MSG("inotify init failed"), errno, NULL);
}
Inotify::~Inotify()
200,43 → 259,81
 
void Inotify::Add(InotifyWatch* pWatch) throw (InotifyException)
{
// invalid descriptor - this case shouldn't occur - go away
if (m_fd == -1)
throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this);
 
// this path already watched - go away
if (FindWatch(pWatch->GetPath()) != NULL)
throw InotifyException(IN_EXC_MSG("path already watched"), EBUSY, this);
// for enabled watch
if (pWatch->IsEnabled()) {
pWatch->m_wd = inotify_add_watch(m_fd, pWatch->GetPath().c_str(), pWatch->GetMask());
 
if (pWatch->m_wd == -1)
throw InotifyException(IN_EXC_MSG("adding watch failed"), errno, this);
 
m_watches.insert(IN_WATCH_MAP::value_type(pWatch->m_wd, pWatch));
// try to add watch to kernel
int wd = inotify_add_watch(m_fd, pWatch->GetPath().c_str(), pWatch->GetMask());
// adding failed - go away
if (wd == -1)
throw InotifyException(IN_EXC_MSG("adding watch failed"), errno, this);
// this path already watched (but defined another way)
InotifyWatch* pW = FindWatch(wd);
if (pW != NULL) {
// try to recover old watch because it may be modified - then go away
if (inotify_add_watch(m_fd, pW->GetPath().c_str(), pW->GetMask()) < 0) {
throw InotifyException(IN_EXC_MSG("watch collision detected and recovery failed"), errno, this);
}
else {
// recovery failed - go away
throw InotifyException(IN_EXC_MSG("path already watched (but defined another way)"), EBUSY, this);
}
}
pWatch->m_wd = wd;
m_watches.insert(IN_WATCH_MAP::value_type(pWatch->m_wd, pWatch));
}
m_paths.insert(IN_WP_MAP::value_type(pWatch->m_path, pWatch));
pWatch->m_pInotify = this;
}
 
void Inotify::Remove(InotifyWatch* pWatch) throw (InotifyException)
{
// invalid descriptor - this case shouldn't occur - go away
if (m_fd == -1)
throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this);
// for enabled watch
if (pWatch->m_wd != -1) {
if (inotify_rm_watch(m_fd, pWatch->GetMask()) == -1)
throw InotifyException(IN_EXC_MSG("removing watch failed"), errno, this);
m_watches.erase(pWatch->m_wd);
pWatch->m_wd = -1;
// removing watch failed - go away
if (inotify_rm_watch(m_fd, pWatch->m_wd) == -1)
throw InotifyException(IN_EXC_MSG("removing watch failed"), errno, this);
m_watches.erase(pWatch->m_wd);
pWatch->m_wd = -1;
}
 
m_paths.erase(pWatch->m_path);
pWatch->m_pInotify = NULL;
}
 
void Inotify::RemoveAll()
{
IN_WATCH_MAP::iterator it = m_watches.begin();
while (it != m_watches.end()) {
IN_WP_MAP::iterator it = m_paths.begin();
while (it != m_paths.end()) {
InotifyWatch* pW = (*it).second;
inotify_rm_watch(m_fd, pW->GetMask());
pW->m_wd = -1;
if (pW->m_wd != -1) {
inotify_rm_watch(m_fd, pW->m_wd);
pW->m_wd = -1;
}
pW->m_pInotify = NULL;
it++;
}
m_watches.clear();
m_paths.clear();
}
 
void Inotify::WaitForEvents(bool fNoIntr) throw (InotifyException)
257,7 → 354,7
while (i < len) {
struct inotify_event* pEvt = (struct inotify_event*) &m_buf[i];
InotifyWatch* pW = FindWatch(pEvt->wd);
if (pW != NULL && pW->IsEnabled()) {
if (pW != NULL) {
InotifyEvent evt(pEvt, pW);
m_events.push_back(evt);
}
301,6 → 398,15
return (*it).second;
}
 
InotifyWatch* Inotify::FindWatch(const std::string& rPath)
{
IN_WP_MAP::iterator it = m_paths.find(rPath);
if (it == m_paths.end())
return NULL;
return (*it).second;
}
void Inotify::SetNonBlock(bool fNonBlock) throw (InotifyException)
{
/incron/trunk/icd-main.cpp
27,20 → 27,29
 
#include "usertable.h"
 
/// Daemon yes/no
#define DAEMON true
 
/// Application name
#define INCRON_APP_NAME "incrond"
 
/// Logging options (console as fallback, log PID)
#define INCRON_LOG_OPTS (LOG_CONS | LOG_PID)
 
/// Logging facility (use CRON)
#define INCRON_LOG_FACIL LOG_CRON
 
 
/// User name to user table mapping definition
typedef std::map<std::string, UserTable*> SUT_MAP;
 
 
/// User name to user table mapping table
SUT_MAP g_ut;
 
/// Finish program yes/no
volatile bool g_fFinish = false;
 
 
/// Handles a signal.
/**
* For SIGTERM and SIGINT it sets the program finish variable.
156,7 → 165,7
struct pollfd pfd;
pfd.fd = in.GetDescriptor();
pfd.events = POLLIN;
pfd.events = (short) POLLIN;
pfd.revents = (short) 0;
while (!g_fFinish) {
/incron/trunk/inotify-cxx.h
30,9 → 30,13
#include <deque>
#include <map>
 
// Please ensure that the following headers take the right place.
// Please ensure that the following headers take the right place
#include <sys/inotify.h>
 
// Use this if syscalls not defined
#ifndef __NR_inotify_init
#include <sys/inotify-syscalls.h>
#endif // __NR_inotify_init
 
/// Event struct size
#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event))
318,6 → 322,18
return (uint32_t) m_uMask;
}
/// Sets the watch event mask.
/**
* If the watch is active (added to an instance of Inofify)
* this method may fail due to unsuccessful re-setting
* the watch in the kernel.
*
* \param[in] uMask event mask
*
* \throw InotifyException thrown if changing fails
*/
void SetMask(uint32_t uMask) throw (InotifyException);
/// Returns the appropriate inotify class instance.
/**
* \return inotify instance
327,11 → 343,24
return m_pInotify;
}
inline void SetEnabled(bool fEnabled)
{
m_fEnabled = fEnabled;
}
/// Enables/disables the watch.
/**
* If the watch is active (added to an instance of Inofify)
* this method may fail due to unsuccessful re-setting
* the watch in the kernel.
*
* Re-setting the current state has no effect.
*
* \param[in] fEnabled set enabled yes/no
*
* \throw InotifyException thrown if enabling/disabling fails
*/
void SetEnabled(bool fEnabled) throw (InotifyException);
/// Checks whether the watch is enabled.
/**
* \return true = enables, false = disabled
*/
inline bool IsEnabled() const
{
return m_fEnabled;
351,7 → 380,10
/// Mapping from watch descriptors to watch objects.
typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP;
 
/// Mapping from paths to watch objects.
typedef std::map<std::string, InotifyWatch*> IN_WP_MAP;
 
 
/// inotify class
class Inotify
{
421,11 → 453,14
/// Returns the count of watches.
/**
* This is the total count of all watches (regardless whether
* enabled or not).
*
* \return count of watches
*/
inline size_t GetWatchCount() const
{
return (size_t) m_watches.size();
return (size_t) m_paths.size();
}
/// Waits for inotify events.
499,15 → 534,28
return PeekEvent(&rEvt);
}
/// Searches for a watch.
/// Searches for a watch by a watch descriptor.
/**
* It tries to find a watch by the given descriptor.
*
* \param[in] iDescriptor watch descriptor
* \return found descriptor; NULL if no such watch exists
* \return pointer to a watch; NULL if no such watch exists
*/
InotifyWatch* FindWatch(int iDescriptor);
/// Searches for a watch by a filesystem path.
/**
* It tries to find a watch by the given filesystem path.
*
* \param[in] rPath filesystem path
* \return pointer to a watch; NULL if no such watch exists
*
* \attention The path must be exactly identical to the one
* used for the searched watch. Be careful about
* absolute/relative and case-insensitive paths.
*/
InotifyWatch* FindWatch(const std::string& rPath);
/// Returns the file descriptor.
/**
* The descriptor can be used in standard low-level file
538,9 → 586,12
 
private:
int m_fd; ///< file descriptor
IN_WATCH_MAP m_watches; ///< watches
IN_WATCH_MAP m_watches; ///< watches (by descriptors)
IN_WP_MAP m_paths; ///< watches (by paths)
unsigned char m_buf[INOTIFY_BUFLEN]; ///< buffer for events
std::deque<InotifyEvent> m_events; ///< event queue
friend class InotifyWatch;
};
 
 
/incron/trunk/Makefile
40,7 → 40,7
 
install: all
[ -d $(PREFIX) ]
useradd -M -s /sbin/nologin $(USER)
useradd -M -s /sbin/nologin $(USER) || useradd -s /sbin/nologin $(USER)
$(INSTALL) -m 04755 -o $(USER) incrontab $(PREFIX)/bin/
$(INSTALL) -m 0755 incrond $(PREFIX)/sbin/
$(INSTALL) -m 0755 -o $(USER) -d $(DATADIR)