void Inotify::RemoveAll() { IN_WATCH_MAP::iterator it = m_watches.begin(); while (it != m_watches.end()) { InotifyWatch* pW = (*it).second; inotify_rm_watch(m_fd, pW->GetMask()); pW->m_wd = -1; pW->m_pInotify = NULL; it++; } m_watches.clear(); }
//---------------------------------------------------------------------------------- void Monitor::addMonitor(IResourcePtr res, const std::string& file) { // do only add a watcher if inotify already initialized if (!mInotify || !res.valid() || file.length() < 1) return; // we monitor only non-empty resources res.lockResource(); { // create a watch descriptor try { // first check if such a watcher already exists InotifyWatch* watch = mInotify->FindWatch(file); if (watch == NULL) { watch = new InotifyWatch(file, IN_MODIFY); mInotify->Add(watch); } // add new watcher NR_Log(Log::LOG_PLUGIN, Log::LL_DEBUG, "dynamicResources: Monitor %s --> %s", res.getBase()->getResourceName().c_str(), file.c_str()); // add the watcher into the map WatchData data; data.resource = res; data.watcher = watch; data.resourceName = res.getBase()->getResourceName(); mWatchMap[watch->GetDescriptor()].push_back(data); }catch(InotifyException& e) { NR_Log(Log::LOG_PLUGIN, Log::LL_ERROR, "dynamicResources: Cannot add a monitor %s --> %s", res.getBase()->getResourceName().c_str(), file.c_str()); NR_Log(Log::LOG_PLUGIN, Log::LL_ERROR, "dynamicResources: %s", e.GetMessage().c_str()); return; } } res.unlockResource(); }
void Inotify::WaitForEvents(bool fNoIntr) throw (InotifyException) { ssize_t len = 0; do { len = read(m_fd, m_buf, INOTIFY_BUFLEN); } while (fNoIntr && len == -1 && errno == EINTR); if (len < 0) throw InotifyException(IN_EXC_MSG("reading events failed"), errno, this); ssize_t i = 0; while (i < len) { struct inotify_event* pEvt = (struct inotify_event*) &m_buf[i]; InotifyWatch* pW = FindWatch(pEvt->wd); if (pW != NULL && pW->IsEnabled()) { InotifyEvent evt(pEvt, pW); m_events.push_back(evt); } i += INOTIFY_EVENT_SIZE + (ssize_t) pEvt->len; } }
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); }
void UserTable::OnEvent(InotifyEvent& rEvt) { InotifyWatch* pW = rEvt.GetWatch(); InCronTabEntry* pE = FindEntry(pW); if (pE == NULL) 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 if (cs[px] == '@') { cmd.append(cs.substr(oldpos, pos-oldpos)); cmd.append(pW->GetPath()); oldpos = pos + 2; } else if (cs[px] == '#') { cmd.append(cs.substr(oldpos, pos-oldpos)); cmd.append(rEvt.GetName()); oldpos = pos + 2; } else { cmd.append(cs.substr(oldpos, pos-oldpos)); 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; } syslog(LOG_INFO, "(%s) CMD (%s)", m_user.c_str(), cmd.c_str()); pid_t pid = fork(); if (pid == 0) { struct passwd* pwd = getpwnam(m_user.c_str()); if (pwd == NULL) _exit(1); if (setuid(pwd->pw_uid) != 0) _exit(1); if (execvp(argv[0], argv) != 0) { _exit(1); } } else if (pid > 0) { } else { syslog(LOG_ERR, "cannot fork process: %s", strerror(errno)); } }