]> git.stg.codes - stg.git/blob - projects/stargazer/settings_impl.cpp
stg-2.409 pre-merge.
[stg.git] / projects / stargazer / settings_impl.cpp
1 /*
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.
6  *
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.
11  *
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
15  */
16
17 /*
18  *    Date: 27.10.2002
19  */
20
21 /*
22  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
23  */
24
25 /*
26 $Revision: 1.45 $
27 $Date: 2010/08/19 13:42:30 $
28 $Author: faust $
29 */
30
31 #include <cstring>
32 #include <cerrno>
33 #include <string>
34
35 #include "stg/logger.h"
36 #include "stg/dotconfpp.h"
37 #include "settings_impl.h"
38
39 //-----------------------------------------------------------------------------
40 SETTINGS_IMPL::SETTINGS_IMPL(const std::string & cd)
41     : modulesPath("/usr/lib/stg"),
42       dirName(DIR_NUM),
43       confDir(cd.empty() ? "/etc/stargazer" : cd),
44       scriptsDir(confDir),
45       rules(confDir + "/rules"),
46       logFile("/var/log/stargazer.log"),
47       pidFile("/var/run/stargazer.pid"),
48       monitorDir("/var/stargazer/monitoring"),
49       monitoring(false),
50       detailStatWritePeriod(dsPeriod_1_6),
51       statWritePeriod(10),
52       stgExecMsgKey(5555),
53       executersNum(1),
54       fullFee(false),
55       dayFee(0),
56       dayResetTraff(0),
57       spreadFee(false),
58       freeMbAllowInet(false),
59       dayFeeIsLastDay(false),
60       stopOnError(true),
61       writeFreeMbTraffCost(false),
62       showFeeInCash(true),
63       messageTimeout(0),
64       feeChargeType(0),
65       reconnectOnTariffChange(false),
66       logger(GetStgLogger())
67 {
68 }
69 //-----------------------------------------------------------------------------
70 SETTINGS_IMPL::SETTINGS_IMPL(const SETTINGS_IMPL & rval)
71     : modulesPath(rval.modulesPath),
72       dirName(rval.dirName),
73       confDir(rval.confDir),
74       scriptsDir(rval.scriptsDir),
75       rules(rval.rules),
76       logFile(rval.logFile),
77       pidFile(rval.pidFile),
78       monitorDir(rval.monitorDir),
79       monitoring(rval.monitoring),
80       detailStatWritePeriod(rval.detailStatWritePeriod),
81       statWritePeriod(rval.statWritePeriod),
82       stgExecMsgKey(rval.stgExecMsgKey),
83       executersNum(rval.executersNum),
84       fullFee(rval.fullFee),
85       dayFee(rval.dayFee),
86       dayResetTraff(rval.dayResetTraff),
87       spreadFee(rval.spreadFee),
88       freeMbAllowInet(rval.freeMbAllowInet),
89       dayFeeIsLastDay(rval.dayFeeIsLastDay),
90       stopOnError(rval.stopOnError),
91       writeFreeMbTraffCost(rval.writeFreeMbTraffCost),
92       showFeeInCash(rval.showFeeInCash),
93       messageTimeout(rval.messageTimeout),
94       feeChargeType(rval.feeChargeType),
95       reconnectOnTariffChange(rval.reconnectOnTariffChange),
96       modulesSettings(rval.modulesSettings),
97       storeModuleSettings(rval.storeModuleSettings),
98       logger(GetStgLogger())
99 {
100 }
101 //-----------------------------------------------------------------------------
102 SETTINGS_IMPL & SETTINGS_IMPL::operator=(const SETTINGS_IMPL & rhs)
103 {
104     modulesPath = rhs.modulesPath;
105     dirName = rhs.dirName;
106     confDir = rhs.confDir;
107     scriptsDir = rhs.scriptsDir;
108     rules = rhs.rules;
109     logFile = rhs.logFile;
110     pidFile = rhs.pidFile;
111     monitorDir = rhs.monitorDir;
112     scriptParams = rhs.scriptParams;
113     monitoring = rhs.monitoring;
114     detailStatWritePeriod = rhs.detailStatWritePeriod;
115     statWritePeriod = rhs.statWritePeriod;
116     stgExecMsgKey = rhs.stgExecMsgKey;
117     executersNum = rhs.executersNum;
118     fullFee = rhs.fullFee;
119     dayFee = rhs.dayFee;
120     dayResetTraff = rhs.dayResetTraff;
121     spreadFee = rhs.spreadFee;
122     freeMbAllowInet = rhs.freeMbAllowInet;
123     dayFeeIsLastDay = rhs.dayFeeIsLastDay;
124     stopOnError = rhs.stopOnError;
125     writeFreeMbTraffCost = rhs.writeFreeMbTraffCost;
126     showFeeInCash = rhs.showFeeInCash;
127     messageTimeout = rhs.messageTimeout;
128     feeChargeType = rhs.feeChargeType;
129     reconnectOnTariffChange = rhs.reconnectOnTariffChange;
130
131     modulesSettings = rhs.modulesSettings;
132     storeModuleSettings = rhs.storeModuleSettings;
133     return *this;
134 }
135 //-----------------------------------------------------------------------------
136 int SETTINGS_IMPL::ParseModuleSettings(const DOTCONFDocumentNode * node, std::vector<PARAM_VALUE> * params)
137 {
138 const DOTCONFDocumentNode * childNode;
139 PARAM_VALUE pv;
140 const char * value;
141
142 pv.param = node->getName();
143
144 if (node->getValue(1))
145     {
146     strError = "Unexpected value \'" + std::string(node->getValue(1)) + "\'.";
147     return -1;
148     }
149
150 value = node->getValue(0);
151
152 if (!value)
153     {
154     strError = "Module name expected.";
155     return -1;
156     }
157
158 childNode = node->getChildNode();
159 while (childNode)
160     {
161     pv.param = childNode->getName();
162     int i = 0;
163     while ((value = childNode->getValue(i++)) != NULL)
164         {
165         pv.value.push_back(value);
166         }
167     params->push_back(pv);
168     pv.value.clear();
169     childNode = childNode->getNextNode();
170     }
171
172 return 0;
173 }
174 //-----------------------------------------------------------------------------
175 void SETTINGS_IMPL::ErrorCallback(void * data, const char * buf)
176 {
177     printfd(__FILE__, "SETTINGS_IMPL::ErrorCallback() - %s\n", buf);
178     SETTINGS_IMPL * settings = static_cast<SETTINGS_IMPL *>(data);
179     settings->logger("%s", buf);
180 }
181 //-----------------------------------------------------------------------------
182 int SETTINGS_IMPL::ReadSettings()
183 {
184 const char * requiredOptions[] = {
185     "ModulesPath",
186     "Modules",
187     "StoreModule",
188     "Rules",
189     "LogFile",
190     "DetailStatWritePeriod",
191     "DayFee",
192     "DayResetTraff",
193     "SpreadFee",
194     "FreeMbAllowInet",
195     "DayFeeIsLastDay",
196     "WriteFreeMbTraffCost",
197     NULL
198     };
199 int storeModulesCount = 0;
200 modulesSettings.clear();
201
202 DOTCONFDocument conf(DOTCONFDocument::CASEINSENSITIVE);
203 conf.setErrorCallback(SETTINGS_IMPL::ErrorCallback, this);
204 conf.setRequiredOptionNames(requiredOptions);
205 std::string confFile = confDir + "/stargazer.conf";
206
207 if(conf.setContent(confFile.c_str()) != 0)
208     {
209     strError = "Cannot read file " + confFile;
210     return -1;
211     }
212
213 const DOTCONFDocumentNode * node = conf.getFirstNode();
214
215 while (node)
216     {
217     if (strcasecmp(node->getName(), "ScriptDir") == 0)
218         {
219         scriptsDir = node->getValue(0);
220         }
221
222     if (strcasecmp(node->getName(), "LogFile") == 0)
223         {
224         logFile = node->getValue(0);
225         }
226
227     if (strcasecmp(node->getName(), "PIDFile") == 0)
228         {
229         pidFile = node->getValue(0);
230         }
231
232     if (strcasecmp(node->getName(), "ModulesPath") == 0)
233         {
234         modulesPath = node->getValue(0);
235         }
236
237     if (strcasecmp(node->getName(), "Rules") == 0)
238         {
239         rules = node->getValue(0);
240         }
241
242     if (strcasecmp(node->getName(), "DetailStatWritePeriod") == 0)
243         {
244         if (ParseDetailStatWritePeriod(node->getValue(0)) != 0)
245             {
246             strError = "Incorrect DetailStatWritePeriod value: \'" + std::string(node->getValue(0)) + "\'";
247             return -1;
248             }
249         }
250
251     if (strcasecmp(node->getName(), "StatWritePeriod") == 0)
252         {
253         if (ParseUnsignedInRange(node->getValue(0), 1, 1440, &statWritePeriod) != 0)
254             {
255             strError = "Incorrect StatWritePeriod value: \'" + std::string(node->getValue(0)) + "\'";
256             return -1;
257             }
258         }
259
260     if (strcasecmp(node->getName(), "ExecMsgKey") == 0)
261         {
262         if (ParseInt(node->getValue(0), &stgExecMsgKey) != 0)
263             {
264             strError = "Incorrect ExecMsgKey value: \'" + std::string(node->getValue(0)) + "\'";
265             return -1;
266             }
267         }
268
269     if (strcasecmp(node->getName(), "ExecutersNum") == 0)
270         {
271         if (ParseUnsignedInRange(node->getValue(0), 1, 1024, &executersNum) != 0)
272             {
273             strError = "Incorrect ExecutersNum value: \'" + std::string(node->getValue(0)) + "\'";
274             return -1;
275             }
276         }
277
278     if (strcasecmp(node->getName(), "DayFee") == 0)
279         {
280         if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayFee) != 0)
281             {
282             strError = "Incorrect DayFee value: \'" + std::string(node->getValue(0)) + "\'";
283             return -1;
284             }
285         }
286
287     if (strcasecmp(node->getName(), "FullFee") == 0)
288         {
289         if (ParseYesNo(node->getValue(0), &fullFee) != 0)
290             {
291             strError = "Incorrect FullFee value: \'" + std::string(node->getValue(0)) + "\'";
292             return -1;
293             }
294         }
295
296     if (strcasecmp(node->getName(), "DayResetTraff") == 0)
297         {
298         if (ParseUnsignedInRange(node->getValue(0), 0, 31, &dayResetTraff) != 0)
299             {
300             strError = "Incorrect DayResetTraff value: \'" + std::string(node->getValue(0)) + "\'";
301             return -1;
302             }
303         }
304
305     if (strcasecmp(node->getName(), "SpreadFee") == 0)
306         {
307         if (ParseYesNo(node->getValue(0), &spreadFee) != 0)
308             {
309             strError = "Incorrect SpreadFee value: \'" + std::string(node->getValue(0)) + "\'";
310             return -1;
311             }
312         }
313
314     if (strcasecmp(node->getName(), "FreeMbAllowInet") == 0)
315         {
316         if (ParseYesNo(node->getValue(0), &freeMbAllowInet) != 0)
317             {
318             strError = "Incorrect FreeMbAllowInet value: \'" + std::string(node->getValue(0)) + "\'";
319             return -1;
320             }
321         }
322
323     if (strcasecmp(node->getName(), "DayFeeIsLastDay") == 0)
324         {
325         if (ParseYesNo(node->getValue(0), &dayFeeIsLastDay) != 0)
326             {
327             strError = "Incorrect DayFeeIsLastDay value: \'" + std::string(node->getValue(0)) + "\'";
328             return -1;
329             }
330         }
331
332     if (strcasecmp(node->getName(), "StopOnError") == 0)
333         {
334         if (ParseYesNo(node->getValue(0), &stopOnError) != 0)
335             {
336             strError = "Incorrect StopOnError value: \'" + std::string(node->getValue(0)) + "\'";
337             return -1;
338             }
339         }
340
341     if (strcasecmp(node->getName(), "WriteFreeMbTraffCost") == 0)
342         {
343         if (ParseYesNo(node->getValue(0), &writeFreeMbTraffCost) != 0)
344             {
345             strError = "Incorrect WriteFreeMbTraffCost value: \'" + std::string(node->getValue(0)) + "\'";
346             return -1;
347             }
348         }
349
350     if (strcasecmp(node->getName(), "ShowFeeInCash") == 0)
351         {
352         if (ParseYesNo(node->getValue(0), &showFeeInCash) != 0)
353             {
354             strError = "Incorrect ShowFeeInCash value: \'" + std::string(node->getValue(0)) + "\'";
355             return -1;
356             }
357         }
358
359     if (strcasecmp(node->getName(), "MonitorDir") == 0)
360         {
361         monitorDir = node->getValue(0);
362         struct stat stat;
363         monitoring = false;
364
365         if (!lstat(monitorDir.c_str(), &stat) && S_ISDIR(stat.st_mode))
366             {
367             monitoring = true;
368             }
369         }
370
371     if (strcasecmp(node->getName(), "MessageTimeout") == 0)
372         {
373         if (ParseUnsigned(node->getValue(0), &messageTimeout) != 0)
374             {
375             strError = "Incorrect MessageTimeout value: \'" + std::string(node->getValue(0)) + "\'";
376             return -1;
377             }
378         }
379
380     if (strcasecmp(node->getName(), "FeeChargeType") == 0)
381         {
382         if (ParseUnsignedInRange(node->getValue(0), 0, 3, &feeChargeType) != 0)
383             {
384             strError = "Incorrect FeeChargeType value: \'" + std::string(node->getValue(0)) + "\'";
385             return -1;
386             }
387         }
388
389     if (strcasecmp(node->getName(), "ReconnectOnTariffChange") == 0)
390         {
391         if (ParseYesNo(node->getValue(0), &reconnectOnTariffChange) != 0)
392             {
393             strError = "Incorrect ReconnectOnTariffChange value: \'" + std::string(node->getValue(0)) + "\'";
394             return -1;
395             }
396         }
397
398     if (strcasecmp(node->getName(), "DirNames") == 0)
399         {
400         const DOTCONFDocumentNode * child = node->getChildNode();
401         if (child)
402             {
403             const DOTCONFDocumentNode * dirNameNode;
404             dirName.reserve(DIR_NUM);
405             for (int i = 0; i < DIR_NUM; i++)
406                 {
407                 char strDirName[12];
408                 sprintf(strDirName, "DirName%d", i);
409                 dirNameNode = conf.findNode(strDirName, node);
410                 if (dirNameNode && dirNameNode->getValue(0))
411                     {
412                     dirName[i] = dirNameNode->getValue(0);
413                     }
414                 }
415             }
416         }
417
418     if (strcasecmp(node->getName(), "StoreModule") == 0)
419         {
420         if (node->getValue(1))
421             {
422             strError = "Unexpected \'" + std::string(node->getValue(1)) + "\'.";
423             return -1;
424             }
425
426         if (storeModulesCount)
427             {
428             strError = "Should be only one StoreModule.";
429             return -1;
430             }
431         storeModulesCount++;
432
433         storeModuleSettings.moduleName = node->getValue(0);
434         ParseModuleSettings(node, &storeModuleSettings.moduleParams);
435         }
436
437     if (strcasecmp(node->getName(), "Modules") == 0)
438         {
439         if (node->getValue(0))
440             {
441             strError = "Unexpected \'" + std::string(node->getValue(0)) + "\'.";
442             return -1;
443             }
444         const DOTCONFDocumentNode * child = node->getChildNode();
445         while (child)
446             {
447             if (strcasecmp(child->getName(), "Module") != 0)
448                 {
449                 child = child->getNextNode();
450                 continue;
451                 }
452             MODULE_SETTINGS modSettings;
453             modSettings.moduleParams.clear();
454             modSettings.moduleName = child->getValue();
455
456             ParseModuleSettings(child, &modSettings.moduleParams);
457
458             modulesSettings.push_back(modSettings);
459
460             child = child->getNextNode();
461             }
462         }
463
464     if (strcasecmp(node->getName(), "ScriptParams") == 0)
465         {
466         for (int i = 0; node->getValue(i) != NULL; ++i)
467             {
468             scriptParams.push_back(node->getValue(i));
469             }
470         }
471     node = node->getNextNode();
472     }
473
474 return 0;
475 }
476 //-----------------------------------------------------------------------------
477 int SETTINGS_IMPL::ParseDetailStatWritePeriod(const std::string & detailStatPeriodStr)
478 {
479 if (detailStatPeriodStr == "1")
480     {
481     detailStatWritePeriod = dsPeriod_1;
482     return 0;
483     }
484 else if (detailStatPeriodStr == "1/2")
485     {
486     detailStatWritePeriod = dsPeriod_1_2;
487     return 0;
488     }
489 else if (detailStatPeriodStr == "1/4")
490     {
491     detailStatWritePeriod = dsPeriod_1_4;
492     return 0;
493     }
494 else if (detailStatPeriodStr == "1/6")
495     {
496     detailStatWritePeriod = dsPeriod_1_6;
497     return 0;
498     }
499
500 return -1;
501 }
502 //-----------------------------------------------------------------------------