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); }
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; } }
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); }
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); }