// -------------------------------------------------------------------- // S c a n d i r . c p p // // Fido messages tracker // Scan dir class. // -------------------------------------------------------------------- // Copyright (c) 1998-2000 by Fyodor Ustinov // FIDONet 2:5020/79 // // All rights reserved. // -------------------------------------------------------------------- #ifndef __GNUC__ #include #include #else #include #include #include #include #include #endif #include #include #include #include #include #include #include "constant.hpp" #include "vars.hpp" #include "nodelist.hpp" #include "utils.hpp" #include "msg.hpp" #include "msgbase.hpp" #include "age.hpp" #include "scandir.hpp" #include "attach.hpp" #include "aka.hpp" #include "wildmat.hpp" #include "script.hpp" #include #include // --------------------------------------------------------- // --------------------------------------------------------- Action::Action() { _Act = ACT_ERROR; _TplName = NULL; _OutDir = NULL; _Base = NULL; _Mask = NULL; _Tpl = NULL; _Times.Clear(); sd = NULL; _f.Clean(); } // -------------------------------------------------------------------- Action::~Action() { CHP = 1; _Times.Clear(); if (_TplName != NULL) free(_TplName); if (_OutDir != NULL) free(_OutDir); if (_Base != NULL) delete _Base; if (_Mask != NULL) delete _Mask; if (_Tpl != NULL) delete _Tpl; } // -------------------------------------------------------------------- #include "scd_do.cpp" // -------------------------------------------------------------------- void Action::Print(void) { char *tmt2; char Buff[1024]; IndBiList::ElemPtr tmt; if (LogLevel < 5) return; CHP = 22; switch(_Act) { case ACT_ERROR: tmt2 = "Error!"; break; case ACT_IGNORE: tmt2 = "Ignore"; break; default: tmt2 = "Unknown"; break; } sprintf(Buff,"Action: %s",tmt2); Log.Level(LOGD) << Buff << EOL; Log.Level(LOGD) << "--" << EOL; if (_Times.IsEmpty()) { Log.Level(LOGD) << "Always"; } else { for (tmt = _Times.GetFirst(); tmt != NULL; tmt++) { tmt->Print(); Log.Level(LOGD) << " "; } } Log.Level(LOGD) << EOL; Log.Level(LOGD) << "--" << EOL; } // --------------------------------------------------------- // --------------------------------------------------------- void DoList::AddAction(Action &a) { CHP = 30; Actions.AddToEnd(&a); } // --------------------------------------------------------- void DoList::AddMask(Mask &m) { CHP = 31; Masks.AddToEnd(&m); } // --------------------------------------------------------- DoList::DoList() { CHP = 32; } // --------------------------------------------------------- DoList::~DoList() { CHP = 33; Actions.Clear(); Masks.Clear(); } // --------------------------------------------------------- int DoList::Do(MSGBASE &b, cMSG &m) { IndBiList::ElemPtr tmt; CHP = 34; for (tmt = Actions.GetFirst(); tmt != NULL; tmt++) { if (InTime(tmt->_Times.GetFirst())) { if (!tmt->Do(b,m)) { return FALSE; } } } return TRUE; } // --------------------------------------------------------- MaskType DoList::InMask(cMSG &m) { IndBiList::ElemPtr tmt; int SkipFlag; CHP = 35; SkipFlag = FALSE; tmt = Masks.GetFirst(); while (tmt != NULL) { if (*tmt == m) { SkipFlag = (tmt->_Type == MASK_SKIP ? TRUE : FALSE); tmt++; while (tmt != NULL && tmt->_Type == MASK_ADD && *tmt == m) { tmt++; } if (tmt == NULL || tmt->_Type != MASK_ADD) { return (SkipFlag ? MASK_SKIP : MASK_NORMAL); } while (tmt != NULL && tmt->_Type == MASK_ADD) { tmt++; } } else { tmt++; while (tmt != NULL && tmt->_Type == MASK_ADD) { tmt++; } } } return MASK_ERROR; } // --------------------------------------------------------- void DoList::Print(void) { IndBiList::ElemPtr tmt; IndBiList::ElemPtr dtmt; if (LogLevel < 5) return; CHP = 36; for (tmt = Masks.GetFirst(); tmt != NULL; tmt++) { tmt->Print(); Log.Level(LOGD) << EOL; } for (dtmt = Actions.GetFirst(); dtmt != NULL; dtmt++) { dtmt->Print(); } } // --------------------------------------------------------- // --------------------------------------------------------- ScanDir::ScanDir() { CHP = 37; _Renumber = FALSE; _Unpack = FALSE; _Fresh = FALSE; _MaxAge = 0; _MaxAttachSize = 0; _LoopStr = NULL; _FlagFile = NULL; _FileInbound = NULL; _ScriptBefore = NULL; _ScriptAfter = NULL; _Base = NULL; } // --------------------------------------------------------- ScanDir::~ScanDir() { CHP = 38; _DoLists.Clear(); _Times.Clear(); if (_LoopStr != NULL) { free(_LoopStr); _LoopStr = NULL; } if (_FileInbound != NULL) { free(_FileInbound); _FileInbound = NULL; } if (_FlagFile != NULL) { free(_FlagFile); _FlagFile = NULL; } if (_Base != NULL) { delete _Base; _Base = NULL; } if (_ScriptBefore != NULL) { free(_ScriptBefore); _ScriptBefore = NULL; } if (_ScriptAfter != NULL) { free(_ScriptAfter); _ScriptAfter = NULL; } } // --------------------------------------------------------- int ScanDir::Flagged(void) { if (_FlagFile == NULL) return TRUE; if (_FlagFile[0] == '!') { return (access(&_FlagFile[1],F_OK) != 0); } else { if (_FlagFile[0] == '#') { return (access(&_FlagFile[1],F_OK) == 0); } else { return (access(_FlagFile,F_OK) == 0); } } } // --------------------------------------------------------- int ScanDir::Execute(MSGBASE &b, cMSG &m) { IndBiList::ElemPtr tmt; MaskType tmtm; CHP = 67; PrepareMsgForScript(m); for (tmt = _DoLists.GetFirst(); tmt != NULL; tmt++) { CHP = 68; if ((tmtm = tmt->InMask(m)) != MASK_ERROR) { CHP = 69; if (!tmt->Do(b,m)) { CHP = 70; return(FALSE); } CHP = 71; if (tmtm != MASK_SKIP) { break; } } CHP = 72; } return TRUE; } // --------------------------------------------------------- int ScanDir::Do(void) { cMSG m; MSGBASE *s; CHP = 39; if (_Base == NULL) return TRUE; if (_Base->Open() != TRUE) { return FALSE; } if (!Flagged()) { Log.Level(LOGI) << "Skip base '" << _Base->BaseName() << "' by Flag." << EOL; _Base->Close(); return TRUE; } if (!InTime(_Times.GetFirst())) { Log.Level(LOGI) << "Skip base '" << _Base->BaseName() << "' by Time." << EOL; _Base->Close(); return TRUE; } Log.Level(LOGD) << EOL; Log.Level(LOGI) << "Scanning message base " << _Base->BaseName() << EOL; Log.Level(LOGD) << "--------------------------------------" << EOL; if (_ScriptBefore != NULL) { switch (DoSomeWordRc(_ScriptBefore)) { case SS_OK: // do nothing, all is OK case SS_NOTDEF: break; // the same case SS_ERROR: _Base->Close(); Log.Level(LOGE) << "Stop ScanDir: by scritp '" << _ScriptBefore << "' error." << EOL; return FALSE; case SS_FALSE: _Base->Close(); Log.Level(LOGI) << "Leave FTrack: by script '" << _ScriptBefore << "' return." << EOL; return TRUE; default: break; } } if (_Unpack) { s = TempMail; Log.Level(LOGI) << "Unpack outbound to " << _Base->BaseName() << EOL; TempMail = _Base; if (!DoRepack()) { Log.Level(LOGE) << "Unable unpack outbound" << EOL; TempMail = s; _Base->Close(); // DoSomeWord("ErrorInScandir"); return FALSE; } TempMail = s; } if (!_Base->Rewind()) { Log.Level(LOGD) << "Base is empty." << EOL; goto DoneOK; } CHP = 64; if (!_DoLists.IsEmpty()) { do { Log.Level(LOGD) << EOL; Log.Level(LOGD) << "Current message: " << _Base->MessageName() << EOL; if (!_Base->ReadMsg(m)) { if (errno == EACCES) { Log.Level(LOGE) << "Message " << _Base->MessageName() << " Locked by another process." << EOL; errno = 0; } else { CHP = 65; if (errno == ENOENT) { _Base->Close(); } else { DoBadMsg(*_Base); CHP = 66; } } } else { if (LogLevel >= 5) { m.Print(); } if (Execute(*_Base,m) != TRUE) { _Base->Close(); return FALSE; } CHP = 73; } CHP = 74; } while(_Base->Next()); Log.Level(LOGD) << "No more messages." << EOL; } else { Log.Level(LOGD) << "No masks in scandir." << EOL; } if (_FlagFile != NULL && _FlagFile[0] == '#') { unlink(&_FlagFile[1]); } if (_Renumber) { Log.Level(LOGI) << "Renumber message base " << _Base->BaseName() << EOL; if (!_Base->Renumber()) { _Base->Close(); return FALSE; } } DoneOK: if (_ScriptAfter != NULL) { switch (DoSomeWordRc(_ScriptAfter)) { case SS_OK: // do nothing, all is OK case SS_NOTDEF: break; // the same case SS_ERROR: _Base->Close(); Log.Level(LOGE) << "Stop ScanDir: by script '" << _ScriptAfter << "' error." << EOL; return FALSE; case SS_FALSE: _Base->Close(); Log.Level(LOGI) << "Leave ScanDir: by script '" << _ScriptAfter << "' return." << EOL; return TRUE; default: break; } } _Base->Close(); CHP = 75; return TRUE; } // --------------------------------------------------------- int ScanDir::DoWithRoute(MSGBASE &b, cMSG &m) { CHP = 390001; if (_Base != NULL) { Log.Level(LOGE) << "Internal error. ScanDir::DoWithRoute _Base != NULL" << EOL; return FALSE; } Log.Level(LOGD) << EOL; Log.Level(LOGD) << "----- ScanDir::DoWithRoute -----" << EOL; if (!Flagged()) { Log.Level(LOGI) << "Skip this base by flag state." << EOL; return TRUE; } CHP = 390010; _Base = &b; if (!_DoLists.IsEmpty()) { Log.Level(LOGD) << EOL; if (LogLevel >= 5) { m.Print(); } CHP = 390020; if (Execute(*_Base,m) != TRUE) { _Base = NULL; return FALSE; } CHP = 390030; } else { Log.Level(LOGD) << "No masks in scandir." << EOL; } _Base = NULL; if (_FlagFile != NULL && _FlagFile[0] == '#') { unlink(&_FlagFile[1]); } CHP = 390040; return TRUE; } // --------------------------------------------------------- void ScanDir::Print(void) { IndBiList::ElemPtr tmt; IndBiList::ElemPtr dtmt; if (LogLevel < 5) return; Log.Level(LOGD) << "------------------------------------" << EOL; Log.Level(LOGD) << "ScanDir.Print()" << EOL; Log.Level(LOGD) << "Base: '" << ((_Base != NULL) ? _Base->BaseName() : "--NONE--") << "'" << EOL; Log.Level(LOGD) << "Renumber: " << ((_Renumber) ? "YES" : "NO") << EOL; Log.Level(LOGD) << "Unpack: " << ((_Unpack) ? "YES" : "NO") << EOL; Log.Level(LOGD) << "Fresh: " << ((_Fresh) ? "YES" : "NO") << EOL; Log.Level(LOGD) << "MaxAge: " << _MaxAge << EOL; Log.Level(LOGD) << "MaxAttachSize: " << _MaxAttachSize << EOL; Log.Level(LOGD) << "LoopStr: '" << ((LoopStr() != NULL) ? LoopStr() : "--NONE--") << "'" << EOL; Log.Level(LOGD) << "FileInbound: '" << ((_FileInbound != NULL) ? _FileInbound : "--NONE--") << "'" << EOL; Log.Level(LOGD) << "FlagFile: '" << ((_FlagFile != NULL) ? _FlagFile : "--NONE--") << "'" << EOL; Log.Level(LOGD) << "ScriptBefore: '" << ((_ScriptBefore != NULL) ? _ScriptBefore : "--NONE--") << "'" << EOL; Log.Level(LOGD) << "ScriptAfter: '" << ((_ScriptAfter != NULL) ? _ScriptAfter : "--NONE--") << "'" << EOL; Log.Level(LOGD) << "Times: "; if (_Times.IsEmpty()) { Log.Level(LOGD) << "Always"; } else { for (tmt = _Times.GetFirst(); tmt != NULL; tmt++) { tmt->Print(); Log.Level(LOGD) << " "; } } Log.Level(LOGD) << EOL; Log.Level(LOGD) << "--" << EOL; if (_DoLists.IsEmpty()) { Log.Level(LOGD) << "ScanDir without masks and actions" << EOL; } else { for (dtmt = _DoLists.GetFirst(); dtmt != NULL; dtmt++) { dtmt->Print(); } } Log.Level(LOGD) << "------------------------------------" << EOL; } // --------------------------------------------------------- IndBiList ScanDirs; void PrintScanDirs(void) { IndBiList::ElemPtr tmt; CHP = 41; for (tmt = ScanDirs.GetFirst(); tmt != NULL; tmt++) { tmt->Print(); } } void DoScanDirs(void) { IndBiList::ElemPtr tmt; CHP = 42; for (tmt = ScanDirs.GetFirst(); tmt != NULL; tmt++) { CHP = 43; if (!tmt->Do()) { return; } CHP = 44; } } // --------------------------------------------------------------------