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>
19 * Author : Maxim Mamontov <faust@stargazer.dp.ua>
25 $Date: 2010/09/10 06:37:45 $
28 #include <sys/types.h>
33 #include <fcntl.h> // creat
41 #include "stg/common.h"
42 #include "stg/logger.h"
43 #include "stg/scriptexecuter.h"
44 #include "stg/conffiles.h"
45 #include "stg/version.h"
56 #define START_FILE "/._ST_ART_ED_"
58 static bool childExited = false;
59 set<pid_t> executersPid;
60 static pid_t stgChildPid;
61 volatile time_t stgTime = time(NULL);
66 STG_STOPPER() { nonstop = true; }
67 bool GetStatus() const { return nonstop; };
68 void Stop(const char * __file__, int __line__)
71 printfd(__FILE__, "rscriptd stopped at %s:%d\n", __file__, __line__);
78 //-----------------------------------------------------------------------------
80 //-----------------------------------------------------------------------------
84 //-----------------------------------------------------------------------------
88 //-----------------------------------------------------------------------------
89 void CatchTERM(int sig)
92 *Function Name:CatchINT
93 *Parameters: sig_num - signal number
94 *Description: INT signal handler
97 STG_LOGGER & WriteServLog = GetStgLogger();
98 WriteServLog("Shutting down... %d", sig);
100 nonstop.Stop(__FILE__, __LINE__);
102 struct sigaction newsa, oldsa;
105 sigemptyset(&sigmask);
106 sigaddset(&sigmask, SIGTERM);
107 newsa.sa_handler = SIG_IGN;
108 newsa.sa_mask = sigmask;
110 sigaction(SIGTERM, &newsa, &oldsa);
112 sigemptyset(&sigmask);
113 sigaddset(&sigmask, SIGINT);
114 newsa.sa_handler = SIG_IGN;
115 newsa.sa_mask = sigmask;
117 sigaction(SIGINT, &newsa, &oldsa);
119 //-----------------------------------------------------------------------------
122 STG_LOGGER & WriteServLog = GetStgLogger();
123 WriteServLog("Broken pipe!");
125 //-----------------------------------------------------------------------------
129 //-----------------------------------------------------------------------------
134 childPid = waitpid(-1, &status, WNOHANG);
136 set<pid_t>::iterator pid;
137 pid = executersPid.find(childPid);
138 if (pid != executersPid.end())
140 executersPid.erase(pid);
142 if (childPid == stgChildPid)
147 //-----------------------------------------------------------------------------
148 void SetSignalHandlers()
150 struct sigaction newsa, oldsa;
153 sigemptyset(&sigmask);
154 sigaddset(&sigmask, SIGTERM);
155 newsa.sa_handler = CatchTERM;
156 newsa.sa_mask = sigmask;
158 sigaction(SIGTERM, &newsa, &oldsa);
160 sigemptyset(&sigmask);
161 sigaddset(&sigmask, SIGUSR1);
162 newsa.sa_handler = CatchUSR1;
163 newsa.sa_mask = sigmask;
165 sigaction(SIGUSR1, &newsa, &oldsa);
167 sigemptyset(&sigmask);
168 sigaddset(&sigmask, SIGINT);
169 newsa.sa_handler = CatchTERM;
170 newsa.sa_mask = sigmask;
172 sigaction(SIGINT, &newsa, &oldsa);
174 sigemptyset(&sigmask);
175 sigaddset(&sigmask, SIGPIPE);
176 newsa.sa_handler = CatchPIPE;
177 newsa.sa_mask = sigmask;
179 sigaction(SIGPIPE, &newsa, &oldsa);
181 sigemptyset(&sigmask);
182 sigaddset(&sigmask, SIGHUP);
183 newsa.sa_handler = CatchHUP;
184 newsa.sa_mask = sigmask;
186 sigaction(SIGHUP, &newsa, &oldsa);
188 sigemptyset(&sigmask);
189 sigaddset(&sigmask, SIGCHLD);
190 newsa.sa_handler = CatchCHLD;
191 newsa.sa_mask = sigmask;
193 sigaction(SIGCHLD, &newsa, &oldsa);
195 //-----------------------------------------------------------------------------
196 int StartScriptExecuter(char * procName, int msgKey, int * msgID)
198 STG_LOGGER & WriteServLog = GetStgLogger();
200 if (*msgID == -11) // If msgID == -11 - first call. Create queue
202 for (int i = 0; i < 2; i++)
204 *msgID = msgget(msgKey, IPC_CREAT | IPC_EXCL | 0600);
208 *msgID = msgget(msgKey, 0);
211 WriteServLog("Message queue not created.");
216 msgctl(*msgID, IPC_RMID, NULL);
221 WriteServLog("Message queue created successfully. msgKey=%d msgID=%d", msgKey, *msgID);
227 pid_t executerPid = fork();
232 WriteServLog("Fork error!");
240 Executer(msgKey, *msgID, executerPid, procName);
244 if (executersPid.empty())
245 Executer(msgKey, *msgID, executerPid, NULL);
246 executersPid.insert(executerPid);
250 //-----------------------------------------------------------------------------
252 int ForkAndWait(const string &)
254 int ForkAndWait(const string & confDir)
258 stgChildPid = fork();
280 //-----------------------------------------------------------------------------
283 set<pid_t>::iterator pid;
284 pid = executersPid.begin();
285 while (pid != executersPid.end())
287 printfd(__FILE__, "KillExecuters pid=%d\n", *pid);
292 //-----------------------------------------------------------------------------
293 int main(int argc, char * argv[])
297 Initialization order:
300 - Set signal nandlers
304 CONFIGFILE * cfg = NULL;
305 LISTENER * listener = NULL;
320 printf("You must be root. Exit.\n");
325 cfg = new CONFIGFILE(argv[1]);
327 cfg = new CONFIGFILE("/etc/rscriptd/rscriptd.conf");
331 STG_LOGGER & WriteServLog = GetStgLogger();
332 WriteServLog.SetLogFileName("/var/log/rscriptd.log");
333 WriteServLog("Error reading config file!");
338 cfg->ReadString("LogFileName", &logFileName, "/var/log/rscriptd.log");
339 cfg->ReadInt("ExecutersNum", &execNum, 1);
340 cfg->ReadInt("ExecMsgKey", &execMsgKey, 5555);
341 cfg->ReadString("ConfigDir", &confDir, "/etc/rscriptd");
342 cfg->ReadString("Password", &password, "");
343 cfg->ReadInt("Port", &port, 5555);
344 cfg->ReadInt("UserTimeout", &userTimeout, 60);
345 cfg->ReadString("ScriptOnConnect", &onConnect, "/etc/rscriptd/OnConnect");
346 cfg->ReadString("ScriptOnDisconnect", &onDisconnect, "/etc/rscriptd/OnDisconnect");
349 if (ForkAndWait(confDir) < 0)
351 STG_LOGGER & WriteServLog = GetStgLogger();
352 WriteServLog("Fork error!");
357 STG_LOGGER & WriteServLog = GetStgLogger();
358 PIDFile pidFile("/var/run/rscriptd.pid");
359 WriteServLog.SetLogFileName(logFileName);
360 WriteServLog("rscriptd v. %s", SERVER_VERSION);
362 for (int i = 0; i < execNum; i++)
364 int ret = StartScriptExecuter(argv[0], execMsgKey, &msgID);
367 STG_LOGGER & WriteServLog = GetStgLogger();
368 WriteServLog("Start Script Executer error!");
379 listener = new LISTENER();
380 listener->SetPort(port);
381 listener->SetPassword(password);
382 listener->SetUserTimeout(userTimeout);
383 listener->SetScriptOnConnect(onConnect);
384 listener->SetScriptOnDisconnect(onDisconnect);
388 WriteServLog("rscriptd started successfully.");
389 WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
391 while (nonstop.GetStatus())
398 WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
400 int res = msgctl(msgID, IPC_RMID, NULL);
402 WriteServLog("Queue was not removed. id=%d", msgID);
404 WriteServLog("Queue removed successfully.");
408 WriteServLog("rscriptd stopped successfully.");
409 WriteServLog("---------------------------------------------");
415 //-----------------------------------------------------------------------------