Пример #1
0
void UserTable::Load()
{
  m_tab.Load(m_fSysTable
      ? IncronTab::GetSystemTablePath(m_user)
      : IncronTab::GetUserTablePath(m_user));
  
  int cnt = m_tab.GetCount();
  for (int i=0; i<cnt; i++) {
    IncronTabEntry& rE = m_tab.GetEntry(i);
    InotifyWatch* pW = new InotifyWatch(rE.GetPath(), rE.GetMask());
    
    // warning only - permissions may change later
    if (!(m_fSysTable || MayAccess(rE.GetPath(), DONT_FOLLOW(rE.GetMask()))))
      syslog(LOG_WARNING, "access denied on %s - events will be discarded silently", rE.GetPath().c_str());
    
    try {
      m_in.Add(pW);
      m_map.insert(IWCE_MAP::value_type(pW, &rE));
    } catch (InotifyException e) {
      if (m_fSysTable)
        syslog(LOG_ERR, "cannot create watch for system table %s: (%i) %s", m_user.c_str(), e.GetErrorNumber(), strerror(e.GetErrorNumber()));
      else
        syslog(LOG_ERR, "cannot create watch for user %s: (%i) %s", m_user.c_str(), e.GetErrorNumber(), strerror(e.GetErrorNumber()));
      delete pW;
    }
  }
  
  m_pEd->Register(this);
}
Пример #2
0
void UserTable::AddWatch(const std::string& sPath, IncronTabEntry* pEntry)
{
  InotifyWatch* pW = new InotifyWatch(sPath, pEntry->GetMask());

  syslog(LOG_DEBUG, "adding directory watch %s", sPath.c_str());

  // warning only - permissions may change later
  if (!(m_fSysTable || MayAccess(sPath, DONT_FOLLOW(pEntry->GetMask()))))
    syslog(LOG_WARNING, "access denied on %s - events will be discarded silently", sPath.c_str());

  try {
    m_in.Add(pW);
    m_map.insert(IWCE_MAP::value_type(pW, pEntry));
  } catch (InotifyException& e) {
    if (m_fSysTable)
      syslog(LOG_ERR, "cannot create watch for system table %s: (%i) %s", m_user.c_str(), e.GetErrorNumber(), strerror(e.GetErrorNumber()));
    else
      syslog(LOG_ERR, "cannot create watch for user %s: (%i) %s", m_user.c_str(), e.GetErrorNumber(), strerror(e.GetErrorNumber()));
    delete pW;
  }
}
Пример #3
0
void UserTable::OnEvent(InotifyEvent& rEvt)
{
  InotifyWatch* pW = rEvt.GetWatch();
  IncronTabEntry* pE = FindEntry(pW);

  // no entry found - this shouldn't occur
  if (pE == NULL)
    return;

  // discard event if user has no access rights to watch path
  if (!(m_fSysTable || MayAccess(pW->GetPath(), DONT_FOLLOW(rEvt.GetMask()))))
    return;

  std::string cmd;
  const std::string& cs = pE->GetCmd();
  size_t pos = 0;
  size_t oldpos = 0;
  size_t len = cs.length();
  while ((pos = cs.find('$', oldpos)) != std::string::npos) {
    if (pos < len - 1) {
      size_t px = pos + 1;
      if (cs[px] == '$') {
        cmd.append(cs.substr(oldpos, pos-oldpos+1));
        oldpos = pos + 2;
      }
      else {
        cmd.append(cs.substr(oldpos, pos-oldpos));
        if (cs[px] == '@') {          // base path
          cmd.append(IncronTabEntry::GetSafePath(pW->GetPath()));
          oldpos = pos + 2;
        }
        else if (cs[px] == '#') {     // file name
          cmd.append(IncronTabEntry::GetSafePath(rEvt.GetName()));
          oldpos = pos + 2;
        }
        else if (cs[px] == '%') {     // mask symbols
          std::string s;
          rEvt.DumpTypes(s);
          cmd.append(s);
          oldpos = pos + 2;
        }
        else if (cs[px] == '&') {     // numeric mask
          char s[11];
          snprintf(s, sizeof(s), "%u", (unsigned) rEvt.GetMask());
          cmd.append(s);
          oldpos = pos + 2;
        }
        else {
          oldpos = pos + 1;
        }
      }
    }
    else {
      cmd.append(cs.substr(oldpos, pos-oldpos));
      oldpos = pos + 1;
    }
  }
  cmd.append(cs.substr(oldpos));

  int argc;
  char** argv;
  if (!PrepareArgs(cmd, argc, argv)) {
    syslog(LOG_ERR, "cannot prepare command arguments");
    return;
  }

  if (m_fSysTable)
    syslog(LOG_INFO, "(system::%s) CMD (%s)", m_user.c_str(), cmd.c_str());
  else
    syslog(LOG_INFO, "(%s) CMD (%s)", m_user.c_str(), cmd.c_str());

  if (pE->IsNoLoop())
    pW->SetEnabled(false);

  if (m_maxForks > 0 && s_procMap.size() >= m_maxForks) {
    // time to wait for a forked process to finish before we continue
    int status;
    pid_t res = wait(&status);
    UserTable::ClearProcess(res);
  }

  pid_t pid = fork();
  if (pid == 0) {

    // for system table
    if (m_fSysTable) {
      if (execvp(argv[0], argv) != 0) // exec failed
      {
        syslog(LOG_ERR, "cannot exec process: %s", strerror(errno));
        _exit(1);
      }
    }
    else {
      // for user table
      RunAsUser(argv);
    }
  }
  else if (pid > 0) {
    ProcData_t pd;
    if (pE->IsNoLoop()) {
      pd.onDone = on_proc_done;
      pd.pWatch = pW;
    }
    else {
      pd.onDone = NULL;
      pd.pWatch = NULL;
    }

    s_procMap.insert(PROC_MAP::value_type(pid, pd));

    // Remove watches if it's a directory
    OnEventDirectory(rEvt, pW, pE);
  }
  else {
    if (pE->IsNoLoop())
      pW->SetEnabled(true);

    syslog(LOG_ERR, "cannot fork process: %s", strerror(errno));
  }

  CleanupArgs(argc, argv);
}
Пример #4
0
void UserTable::OnEvent(InotifyEvent& rEvt)
{
  InotifyWatch* pW = rEvt.GetWatch();
  IncronTabEntry* pE = FindEntry(pW);
  
  // no entry found - this shouldn't occur
  if (pE == NULL)
    return;
  
  // discard event if user has no access rights to watch path
  if (!(m_fSysTable || MayAccess(pW->GetPath(), DONT_FOLLOW(rEvt.GetMask()))))
    return;
  
  std::string cmd;
  const std::string& cs = pE->GetCmd();
  size_t pos = 0;
  size_t oldpos = 0;
  size_t len = cs.length();
  while ((pos = cs.find('$', oldpos)) != std::string::npos) {
    if (pos < len - 1) {
      size_t px = pos + 1;
      if (cs[px] == '$') {
        cmd.append(cs.substr(oldpos, pos-oldpos+1));
        oldpos = pos + 2;
      }
      else {
        cmd.append(cs.substr(oldpos, pos-oldpos));
        if (cs[px] == '@') {          // base path
          cmd.append(pW->GetPath());
          oldpos = pos + 2;
        }
        else if (cs[px] == '#') {     // file name
          cmd.append(rEvt.GetName());
          oldpos = pos + 2;
        }
        else if (cs[px] == '%') {     // mask symbols
          std::string s;
          rEvt.DumpTypes(s);
          cmd.append(s);
          oldpos = pos + 2;
        }
        else if (cs[px] == '&') {     // numeric mask
          char* s;
          asprintf(&s, "%u", (unsigned) rEvt.GetMask());
          cmd.append(s);
          free(s);
          oldpos = pos + 2;
        }
        else {
          oldpos = pos + 1;
        }
      }
    }
    else {
      cmd.append(cs.substr(oldpos, pos-oldpos));
      oldpos = pos + 1;
    }
  }    
  cmd.append(cs.substr(oldpos));
  
  int argc;
  char** argv;
  if (!PrepareArgs(cmd, argc, argv)) {
    syslog(LOG_ERR, "cannot prepare command arguments");
    return;
  }
  
  if (m_fSysTable)
    syslog(LOG_INFO, "(system::%s) CMD (%s)", m_user.c_str(), cmd.c_str());
  else
    syslog(LOG_INFO, "(%s) CMD (%s)", m_user.c_str(), cmd.c_str());
  
  if (pE->IsNoLoop())
    pW->SetEnabled(false);
  
  pid_t pid = fork();
  if (pid == 0) {
    
    // for system table
    if (m_fSysTable) {
      if (execvp(argv[0], argv) != 0) // exec failed
      {
        syslog(LOG_ERR, "cannot exec process: %s", strerror(errno));
        _exit(1);
      }
    }
    else {
      // for user table
      struct passwd* pwd = getpwnam(m_user.c_str());
      if (    pwd == NULL                 // user not found
          ||  setgid(pwd->pw_gid) != 0    // setting GID failed
          ||  setuid(pwd->pw_uid) != 0    // setting UID failed
          ||  execvp(argv[0], argv) != 0) // exec failed
      {
        syslog(LOG_ERR, "cannot exec process: %s", strerror(errno));
        _exit(1);
      }
    }
  }
  else if (pid > 0) {
    ProcData_t pd;
    if (pE->IsNoLoop()) {
      pd.onDone = on_proc_done;
      pd.pWatch = pW;
    }
    else {
      pd.onDone = NULL;
      pd.pWatch = NULL;
    }
    
    s_procMap.insert(PROC_MAP::value_type(pid, pd));
  }
  else {
    if (pE->IsNoLoop())
      pW->SetEnabled(true);
      
    syslog(LOG_ERR, "cannot fork process: %s", strerror(errno));
  }
  
  CleanupArgs(argc, argv);
}