2  *    This program is free software; you can redistribute it and/or modify
 
   3  *    it under the terms of the GNU General Public License as published by
 
   4  *    the Free Software Foundation; either version 2 of the License, or
 
   5  *    (at your option) any later version.
 
   7  *    This program is distributed in the hope that it will be useful,
 
   8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
   9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  10  *    GNU General Public License for more details.
 
  12  *    You should have received a copy of the GNU General Public License
 
  13  *    along with this program; if not, write to the Free Software
 
  14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
  18  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
 
  23  $Date: 2010/10/04 20:19:12 $
 
  28 #include <sys/types.h>
 
  29 #include <sys/socket.h>
 
  30 #include <netinet/in.h>
 
  31 #include <arpa/inet.h>
 
  51 #include "traffcounter.h"
 
  52 #include "base_plugin.h"
 
  53 #include "stg_logger.h"
 
  54 #include "stg_timer.h"
 
  55 #include "plugin_runner.h"
 
  56 #include "script_executer.h"
 
  57 #include "conffiles.h"
 
  59 #include "store_loader.h"
 
  61 #include "eventloop.h"
 
  67     #define MAIN_DEBUG (1)
 
  71 #define START_FILE "/._ST_ART_ED_"
 
  73 static bool needRulesReloading = false;
 
  74 static bool childExited = false;
 
  75 //static pid_t executerPid;
 
  76 set<pid_t> executersPid;
 
  77 static pid_t stgChildPid;
 
  81 //-----------------------------------------------------------------------------
 
  82 bool StartModCmp(const PLUGIN_RUNNER & lhs, const PLUGIN_RUNNER & rhs)
 
  84 return lhs.GetStartPosition() < rhs.GetStartPosition();
 
  86 //-----------------------------------------------------------------------------
 
  87 bool StopModCmp(const PLUGIN_RUNNER & lhs, const PLUGIN_RUNNER & rhs)
 
  89 return lhs.GetStopPosition() > rhs.GetStopPosition();
 
  91 //-----------------------------------------------------------------------------
 
  95     STG_STOPPER() { nonstop = true; }
 
  96     bool    GetStatus() const { return nonstop; };
 
  98     void    Stop(const char * __file__, int __line__)
 
 100     void    Stop(const char *, int)
 
 104         printfd(__FILE__, "Stg stopped at %s:%d\n", __file__, __line__);
 
 111 //-----------------------------------------------------------------------------
 
 113 //-----------------------------------------------------------------------------
 
 114 static void StartTimer()
 
 116 STG_LOGGER & WriteServLog = GetStgLogger();
 
 120     WriteServLog("Cannot start timer. Fatal.");
 
 121     //printfd(__FILE__, "Cannot start timer. Fatal.\n");
 
 126     WriteServLog("Timer thread started successfully.");
 
 127     //printfd(__FILE__, "Timer thread started successfully.\n");
 
 130 //-----------------------------------------------------------------------------
 
 135 //-----------------------------------------------------------------------------
 
 136 void CatchTERM(int sig)
 
 139  *Function Name:CatchINT
 
 140  *Parameters: sig_num - ÎÏÍÅÒ ÓÉÇÎÁÌÁ
 
 141  *Description: ïÂÒÁÂÏÔÞÉË ÓÉÇÎÁÌÁ INT
 
 144 STG_LOGGER & WriteServLog = GetStgLogger();
 
 145 WriteServLog("Shutting down... %d", sig);
 
 148 nonstop.Stop(__FILE__, __LINE__);
 
 150 struct sigaction newsa, oldsa;
 
 153 sigemptyset(&sigmask);
 
 154 sigaddset(&sigmask, SIGTERM);
 
 155 newsa.sa_handler = SIG_IGN;
 
 156 newsa.sa_mask = sigmask;
 
 158 sigaction(SIGTERM, &newsa, &oldsa);
 
 160 sigemptyset(&sigmask);
 
 161 sigaddset(&sigmask, SIGINT);
 
 162 newsa.sa_handler = SIG_IGN;
 
 163 newsa.sa_mask = sigmask;
 
 165 sigaction(SIGINT, &newsa, &oldsa);
 
 167 //-----------------------------------------------------------------------------
 
 170 STG_LOGGER & WriteServLog = GetStgLogger();
 
 171 WriteServLog("Broken pipe!");
 
 173 //-----------------------------------------------------------------------------
 
 176 needRulesReloading = true;
 
 178 //-----------------------------------------------------------------------------
 
 183 childPid = waitpid(-1, &status, WNOHANG);
 
 185 set<pid_t>::iterator pid;
 
 186 pid = executersPid.find(childPid);
 
 187 if (pid != executersPid.end())
 
 189     executersPid.erase(pid);
 
 190     if (executersPid.empty() && nonstop.GetStatus())
 
 192         nonstop.Stop(__FILE__, __LINE__);
 
 195 if (childPid == stgChildPid)
 
 200 /*//-----------------------------------------------------------------------------
 
 201 void CatchSEGV(int, siginfo_t *, void *)
 
 204 sprintf(fileName, "/tmp/stg_segv.%d", getpid());
 
 205 FILE * f = fopen(fileName, "wt");
 
 208     fprintf(f, "\nSignal info:\n~~~~~~~~~~~~\n");
 
 209     fprintf(f, "numb:\t %d (%d)\n", sinfo->si_signo, sig);
 
 210     fprintf(f, "errn:\t %d\n", sinfo->si_errno);
 
 211     fprintf(f, "code:\t %d ", sinfo->si_code);
 
 213     switch (sinfo->si_code)
 
 216             fprintf(f, "(SEGV_MAPERR - address not mapped to object)\n");
 
 220             fprintf(f, "(SEGV_ACCERR - invalid permissions for mapped object)\n");
 
 227     fprintf(f, "addr:\t 0x%.8X\n",
 
 228         (unsigned int)sinfo->si_addr);
 
 231     //asm("movl %eip, eip");
 
 232     if (dladdr((void*)CatchCHLD, &dlinfo))
 
 234         fprintf(f, "SEGV point: %s %s\n", dlinfo.dli_fname, dlinfo.dli_sname);
 
 238         fprintf(f, "Cannot find SEGV point\n");
 
 244 struct sigaction segv_action, segv_action_old;
 
 246 segv_action.sa_handler = SIG_DFL;
 
 247 segv_action.sa_sigaction = NULL;
 
 248 segv_action.sa_flags = SA_SIGINFO;
 
 249 segv_action.sa_restorer = NULL;
 
 251 sigaction(SIGSEGV, &segv_action, &segv_action_old);
 
 253 //-----------------------------------------------------------------------------
 
 254 static void SetSignalHandlers()
 
 256 struct sigaction newsa, oldsa;
 
 259 sigemptyset(&sigmask);
 
 260 sigaddset(&sigmask, SIGTERM);
 
 261 newsa.sa_handler = CatchTERM;
 
 262 newsa.sa_mask = sigmask;
 
 264 sigaction(SIGTERM, &newsa, &oldsa);
 
 266 sigemptyset(&sigmask);
 
 267 sigaddset(&sigmask, SIGUSR1);
 
 268 newsa.sa_handler = CatchUSR1;
 
 269 newsa.sa_mask = sigmask;
 
 271 sigaction(SIGUSR1, &newsa, &oldsa);
 
 273 sigemptyset(&sigmask);
 
 274 sigaddset(&sigmask, SIGINT);
 
 275 newsa.sa_handler = CatchTERM;
 
 276 newsa.sa_mask = sigmask;
 
 278 sigaction(SIGINT, &newsa, &oldsa);
 
 280 sigemptyset(&sigmask);
 
 281 sigaddset(&sigmask, SIGPIPE);
 
 282 newsa.sa_handler = CatchPIPE;
 
 283 newsa.sa_mask = sigmask;
 
 285 sigaction(SIGPIPE, &newsa, &oldsa);
 
 287 sigemptyset(&sigmask);
 
 288 sigaddset(&sigmask, SIGHUP);
 
 289 newsa.sa_handler = CatchHUP;
 
 290 newsa.sa_mask = sigmask;
 
 292 sigaction(SIGHUP, &newsa, &oldsa);
 
 294 sigemptyset(&sigmask);
 
 295 sigaddset(&sigmask, SIGCHLD);
 
 296 newsa.sa_handler = CatchCHLD;
 
 297 newsa.sa_mask = sigmask;
 
 299 sigaction(SIGCHLD, &newsa, &oldsa);
 
 301 /*newsa.sa_handler = NULL;
 
 302 newsa.sa_sigaction = CatchSEGV;
 
 303 newsa.sa_flags = SA_SIGINFO;
 
 304 newsa.sa_restorer = NULL;
 
 305 sigaction(SIGSEGV, &newsa, &oldsa);*/
 
 309 //-----------------------------------------------------------------------------
 
 310 int StartScriptExecuter(char * procName, int msgKey, int * msgID, SETTINGS * settings)
 
 312 STG_LOGGER & WriteServLog = GetStgLogger();
 
 314 if (*msgID == -11)   // If msgID == -11 - first call. Create queue
 
 316     for (int i = 0; i < 2; i++)
 
 318         //WriteServLog("Creating queue with key=%d ...", msgKey);
 
 319         *msgID = msgget(msgKey, IPC_CREAT | IPC_EXCL | 0600);
 
 323             *msgID = msgget(msgKey, 0);
 
 326                 WriteServLog("Message queue not created.");
 
 331                 msgctl(*msgID, IPC_RMID, NULL);
 
 332                 //printfd(__FILE__, "Queue removed!");
 
 337             WriteServLog("Message queue created successfully. msgKey=%d msgID=%d", msgKey, *msgID);
 
 343 pid_t executerPid = fork();
 
 348         WriteServLog("Fork error!");
 
 357         Executer(msgKey, *msgID, executerPid, procName);
 
 360     default:    // ïÓÎÏ×ÎÏÊ ÐÒÏÃÅÓÓ
 
 361         if (executersPid.empty()) {
 
 362             Executer(msgKey, *msgID, executerPid, NULL);
 
 364         executersPid.insert(executerPid);
 
 368 //-----------------------------------------------------------------------------
 
 370 int ForkAndWait(const string & confDir)
 
 372 int ForkAndWait(const string &)
 
 376 stgChildPid = fork();
 
 377 string startFile = confDir + START_FILE;
 
 378 unlink(startFile.c_str());
 
 393     default:    // ïÓÎÏ×ÎÏÊ ÐÒÏÃÅÓÓ
 
 394         for (int i = 0; i < 120 * 5; i++)
 
 396             if (access(startFile.c_str(), F_OK) == 0)
 
 398                 //printf("Fork successfull. Exit.\n");
 
 399                 unlink(startFile.c_str());
 
 405                 unlink(startFile.c_str());
 
 410         unlink(startFile.c_str());
 
 417 //-----------------------------------------------------------------------------
 
 420 set<pid_t>::iterator pid;
 
 421 pid = executersPid.begin();
 
 422 while (pid != executersPid.end())
 
 424     printfd(__FILE__, "KillExecuters pid=%d\n", *pid);
 
 429 //-----------------------------------------------------------------------------
 
 430 int main(int argc, char * argv[])
 
 434   Initialization order:
 
 447   - Set signal nandlers
 
 451 SETTINGS * settings = NULL;
 
 452 BASE_STORE * dataStore = NULL;
 
 453 TARIFFS * tariffs = NULL;
 
 454 ADMINS * admins = NULL;
 
 455 USERS * users = NULL;
 
 456 TRAFFCOUNTER * traffCnt = NULL;
 
 460     STG_LOGGER & WriteServLog = GetStgLogger();
 
 461     WriteServLog.SetLogFileName("/var/log/stargazer.log");
 
 464 vector<MODULE_SETTINGS> modSettings;
 
 465 list<PLUGIN_RUNNER> modules;
 
 467 list<PLUGIN_RUNNER>::iterator modIter;
 
 471     printf("You must be root. Exit.\n");
 
 476     settings = new SETTINGS(argv[1]);
 
 478     settings = new SETTINGS();
 
 480 if (settings->ReadSettings())
 
 482     //printfd(__FILE__, "ReadSettings error.\n");
 
 483     STG_LOGGER & WriteServLog = GetStgLogger();
 
 485     if (settings->GetLogFileName() != "")
 
 486         WriteServLog.SetLogFileName(settings->GetLogFileName());
 
 488     WriteServLog("ReadSettings error. %s", settings->GetStrError().c_str());
 
 493 string startFile(settings->GetConfDir() + START_FILE);
 
 496 //SetSignalHandlers();
 
 497 if (ForkAndWait(settings->GetConfDir()) < 0)
 
 499     STG_LOGGER & WriteServLog = GetStgLogger();
 
 500     WriteServLog("Fork error!");
 
 504 STG_LOGGER & WriteServLog = GetStgLogger();
 
 505 WriteServLog.SetLogFileName(settings->GetLogFileName());
 
 506 WriteServLog("Stg v. %s", SERVER_VERSION);
 
 508 for (int i = 0; i < settings->GetExecutersNum(); i++)
 
 510     int ret = StartScriptExecuter(argv[0], settings->GetExecMsgKey(), &msgID, settings);
 
 513         STG_LOGGER & WriteServLog = GetStgLogger();
 
 514         WriteServLog("Start Script Executer error!");
 
 525 PIDFile pidFile(settings->GetPIDFileName());
 
 529 if (!IsStgTimerRunning())
 
 531     printfd(__FILE__, "Timer thread not started in 1 sec!\n");
 
 532     WriteServLog("Timer thread not started in 1 sec!");
 
 535 EVENT_LOOP & loop(EVENT_LOOP_SINGLETON::GetInstance());
 
 537 STORE_LOADER storeLoader(*settings);
 
 538 if (storeLoader.Load())
 
 540     WriteServLog("Storage plugin: '%s'", storeLoader.GetStrError().c_str());
 
 541     goto exitLblNotStarted;
 
 546     WriteServLog("Event loop not started.");
 
 547     goto exitLblNotStarted;
 
 550 dataStore = storeLoader.GetStore();
 
 551 WriteServLog("Storage plugin: %s. Loading successfull.", dataStore->GetVersion().c_str());
 
 553 tariffs = new TARIFFS(dataStore);
 
 554 admins = new ADMINS(dataStore);
 
 555 users = new USERS(settings, dataStore, tariffs, admins->GetSysAdmin());
 
 556 traffCnt = new TRAFFCOUNTER(users, tariffs, settings->GetRulesFileName());
 
 557 traffCnt->SetMonitorDir(settings->GetMonitorDir());
 
 558 //tariffs->SetUsers(users);
 
 560 modSettings = settings->GetModulesSettings();
 
 562 for (unsigned i = 0; i < modSettings.size(); i++)
 
 564     string modulePath = settings->GetModulesPath();
 
 565     modulePath += "/mod_";
 
 566     modulePath += modSettings[i].moduleName;
 
 568     printfd(__FILE__, "Module: %s\n", modulePath.c_str());
 
 570         PLUGIN_RUNNER(modulePath,
 
 581 modIter = modules.begin();
 
 583 while (modIter != modules.end())
 
 588         WriteServLog("Error: %s",
 
 589                      modIter->GetStrError().c_str());
 
 590         goto exitLblNotStarted;
 
 598     goto exitLblNotStarted;
 
 600 WriteServLog("Users started successfully.");
 
 602 if (traffCnt->Start())
 
 604     goto exitLblNotStarted;
 
 606 WriteServLog("Traffcounter started successfully.");
 
 608 //Sort by start order
 
 609 modules.sort(StartModCmp);
 
 610 modIter = modules.begin();
 
 612 while (modIter != modules.end())
 
 614     if (modIter->Start())
 
 616         WriteServLog("Error: %s",
 
 617                      modIter->GetStrError().c_str());
 
 618         //printfd(__FILE__, "Error: %s\n", capRunner.GetStrError().c_str());
 
 621     WriteServLog("Module: \'%s\'. Start successfull. %d", modIter->GetPlugin()->GetVersion().c_str(),
 
 622         modIter->GetPlugin()->GetStartPosition());
 
 630  * Note that an implementation in which nice returns the new nice value
 
 631  * can legitimately return -1.   To  reliably  detect  an  error,  set
 
 632  * errno to 0 before the call, and check its value when nice returns -1.
 
 638 if (nice(-19) && errno) {
 
 639     printfd(__FILE__, "nice failed: '%s'\n", strerror(errno));
 
 640     WriteServLog("nice failed: '%s'", strerror(errno));
 
 643 WriteServLog("Stg started successfully.");
 
 644 WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
 
 647 creat(startFile.c_str(), S_IRUSR);
 
 652 while (nonstop.GetStatus())
 
 654     if (needRulesReloading)
 
 656         needRulesReloading = false;
 
 659         modIter = modules.begin();
 
 660         for (; modIter != modules.end(); ++modIter)
 
 662             if (modIter->Reload())
 
 664                 WriteServLog("Error reloading %s ('%s')", modIter->GetPlugin()->GetVersion().c_str(),
 
 665                                                           modIter->GetStrError().c_str());
 
 666                 printfd(__FILE__, "Error reloading %s ('%s')\n", modIter->GetPlugin()->GetVersion().c_str(),
 
 667                                                                  modIter->GetStrError().c_str());
 
 676 WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
 
 678 //Sort by start order
 
 679 modules.sort(StopModCmp);
 
 680 modIter = modules.begin();
 
 681 while (modIter != modules.end())
 
 683     std::string name = modIter->GetFileName();
 
 684     printfd(__FILE__, "Stopping module '%s'\n", name.c_str());
 
 687         WriteServLog("Module \'%s\': Error: %s",
 
 688                      modIter->GetPlugin()->GetVersion().c_str(),
 
 689                      modIter->GetStrError().c_str());
 
 690         printfd(__FILE__, "Failed to stop module '%s'\n", name.c_str());
 
 691         //printfd(__FILE__, "Error: %s\n", capRunner.GetStrError().c_str());
 
 694     WriteServLog("Module: \'%s\'. Stop successfull.", modIter->GetPlugin()->GetVersion().c_str());
 
 700     WriteServLog("Event loop not stopped.");
 
 705 /*modIter = modules.begin();
 
 706 while (modIter != modules.end())
 
 708     std::string name = modIter->GetFileName();
 
 709     printfd(__FILE__, "Unloading module '%s'\n", name.c_str());
 
 710     if (modIter->Unload())
 
 712         WriteServLog("Module \'%s\': Error: %s",
 
 714                      modIter->GetStrError().c_str());
 
 715         printfd(__FILE__, "Failed to unload module '%s'\n", name.c_str());
 
 723     WriteServLog("Traffcounter: Stop successfull.");
 
 729     WriteServLog("Users: Stop successfull.");
 
 733 int res = msgctl(msgID, IPC_RMID, NULL);
 
 735     WriteServLog("Queue was not removed. id=%d", msgID);
 
 737     WriteServLog("Queue removed successfully.");
 
 739 /*struct sigaction newsa, oldsa;
 
 741 sigemptyset(&sigmask);
 
 742 sigaddset(&sigmask, SIGCHLD);
 
 743 newsa.sa_handler = SIG_IGN;
 
 744 newsa.sa_mask = sigmask;
 
 746 sigaction(SIGCHLD, &newsa, &oldsa);*/
 
 751 WriteServLog("StgTimer: Stop successfull.");
 
 753 WriteServLog("Stg stopped successfully.");
 
 755 WriteServLog("---------------------------------------------");
 
 765 //-----------------------------------------------------------------------------