Subversion Repositories public

Rev

Rev 67 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed


/// inotify cron daemon user tables header
/**
 * \file usertable.h
 *
 * inotify cron system
 *
 * Copyright (C) 2006, 2007 Lukas Jelinek, <lukas@aiken.cz>
 *
 * This program is free software; you can use it, redistribute
 * it and/or modify it under the terms of the GNU General Public
 * License, version 2 (see LICENSE-GPL).
 *  
 */


#ifndef _USERTABLE_H_
#define _USERTABLE_H_

#include <map>
#include <deque>
#include <sys/poll.h>

#include "inotify-cxx.h"
#include "incrontab.h"


class UserTable;

/// User name to user table mapping definition
typedef std::map<std::string, UserTable*> SUT_MAP;

/// Callback for calling after a process finishes.
typedef void (*proc_done_cb)(InotifyWatch*);

/// Child process data
typedef struct
{
  pid_t pid;            ///< PID
  proc_done_cb onDone;  ///< function called after process finishes
  InotifyWatch* pWatch; ///< related watch
} ProcData_t;

/// fd-to-usertable mapping
typedef std::map<int, UserTable*> FDUT_MAP;

/// Watch-to-tableentry mapping
typedef std::map<InotifyWatch*, InCronTabEntry*> IWCE_MAP;

/// Child process list
typedef std::deque<ProcData_t> PROC_LIST;

/// Event dispatcher class.
/**
 * This class processes events and distributes them as needed.
 */

class EventDispatcher
{
public:
  /// Constructor.
  /**
   * \param[in] iPipeFd pipe descriptor
   * \param[in] pIn inotify object for table management
   * \param[in] pSys watch for system tables
   * \param[in] pUser watch for user tables
   */

  EventDispatcher(int iPipeFd, Inotify* pIn, InotifyWatch* pSys, InotifyWatch* pUser);
 
  /// Destructor.
  ~EventDispatcher();

  /// Processes events.
  /**
   * \return pipe event occurred yes/no
   */

  bool ProcessEvents();
 
  /// Registers an user table.
  /**
   * \param[in] pTab user table
   */

  void Register(UserTable* pTab);
 
  /// Unregisters an user table.
  /**
   * \param[in] pTab user table
   */

  void Unregister(UserTable* pTab);
 
  /// Returns the poll data size.
  /**
   * \return poll data size
   */

  inline size_t GetSize() const
  {
    return m_size;
  }
 
  /// Returns the poll data.
  /**
   * \return poll data
   */

  inline struct pollfd* GetPollData()
  {
    return m_pPoll;
  }
 
 
private:
  int m_iPipeFd;    ///< pipe file descriptor
  int m_iMgmtFd;    ///< table management file descriptor
  Inotify* m_pIn;   ///< table management inotify object
  InotifyWatch* m_pSys;   ///< watch for system tables
  InotifyWatch* m_pUser;  ///< watch for user tables
  FDUT_MAP m_maps;  ///< watch-to-usertable mapping
  size_t m_size;    ///< poll data size
  struct pollfd* m_pPoll; ///< poll data array
 
  /// Rebuilds the poll array data.
  void Rebuild();
 
  /// Processes events on the table management inotify object.
  void ProcessMgmtEvents();
};


/// User table class.
/**
 * This class processes inotify events for an user. It creates
 * child processes which do appropriate actions as defined
 * in the user table file.
 */

class UserTable
{
public:
  /// Constructor.
  /**
   * \param[in] pEd event dispatcher
   * \param[in] rUser user name
   * \param[in] fSysTable system table yes/no
   */

        UserTable(EventDispatcher* pEd, const std::string& rUser, bool fSysTable);
 
  /// Destructor.
        virtual ~UserTable();
 
  /// Loads the table.
  /**
   * All loaded entries have their inotify watches and are
   * registered for event dispatching.
   * If loading fails the table remains empty.
   */

  void Load();
 
  /// Removes all entries from the table.
  /**
   * All entries are unregistered from the event dispatcher and
   * their watches are destroyed.
   */

  void Dispose();
 
  /// Processes an inotify event.
  /**
   * \param[in] rEvt inotify event
   */

  void OnEvent(InotifyEvent& rEvt);
 
  /// Cleans-up all zombie child processes and enables disabled watches.
  /**
   * \attention This method must be called AFTER processing all events
   *            which has been caused by the processes.
   */

  static void FinishDone();
 
  /// Checks whether the user may access a file.
  /**
   * Any access right (RWX) is sufficient.
   *
   * \param[in] rPath absolute file path
   * \param[in] fNoFollow don't follow a symbolic link
   * \return true = access granted, false = otherwise
   */

  bool MayAccess(const std::string& rPath, bool fNoFollow) const;
 
  /// Checks whether it is a system table.
  /**
   * \return true = system table, false = user table
   */

  bool IsSystem() const;
 
  /// Returns the related inotify object.
  /**
   * \return related inotify object
   */

  Inotify* GetInotify()
  {
    return &m_in;
  }
 
  /// 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()
   */

  inline static bool CheckUser(const char* user)
  {
    struct passwd* pw = getpwnam(user);
    if (pw == NULL)
      return false;
     
    return InCronTab::CheckUser(user);
  }
 
private:
  Inotify m_in;           ///< inotify object
  EventDispatcher* m_pEd; ///< event dispatcher
  std::string m_user;     ///< user name
  bool m_fSysTable;       ///< system table yes/no
  InCronTab m_tab;        ///< incron table
  IWCE_MAP m_map;         ///< watch-to-entry mapping

  static PROC_LIST s_procList;  ///< child process list
 
  /// Finds an entry for a watch.
  /**
   * \param[in] pWatch inotify watch
   * \return pointer to the appropriate entry; NULL if no such entry exists
   */

  InCronTabEntry* FindEntry(InotifyWatch* pWatch);
 
  /// Prepares arguments for creating a child process.
  /**
   * \param[in] rCmd command string
   * \param[out] argc argument count
   * \param[out] argv argument array
   * \return true = success, false = failure
   */

  bool PrepareArgs(const std::string& rCmd, int& argc, char**& argv);
 
  /// Frees memory allocated for arguments.
  /**
   * \param[in] argc argument count
   * \param[in] argv argument array
   */

  void CleanupArgs(int argc, char** argv);
 
};

#endif //_USERTABLE_H_