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
40 #include <cstring> // strerror
43 #include "stg/common.h"
44 #include "stg/logger.h"
45 #include "stg/scriptexecuter.h"
46 #include "stg/conffiles.h"
47 #include "stg/version.h"
58 #define START_FILE "/._ST_ART_ED_"
60 static bool childExited = false;
61 set<pid_t> executersPid;
62 static pid_t stgChildPid;
63 volatile time_t stgTime = time(NULL);
68 STG_STOPPER() { nonstop = true; }
69 bool GetStatus() const { return nonstop; };
70 void Stop(const char * __file__, int __line__)
73 printfd(__FILE__, "rscriptd stopped at %s:%d\n", __file__, __line__);
80 //-----------------------------------------------------------------------------
82 //-----------------------------------------------------------------------------
86 //-----------------------------------------------------------------------------
90 //-----------------------------------------------------------------------------
91 void CatchTERM(int sig)
94 *Function Name:CatchINT
95 *Parameters: sig_num - signal number
96 *Description: INT signal handler
99 STG_LOGGER & WriteServLog = GetStgLogger();
100 WriteServLog("Shutting down... %d", sig);
102 nonstop.Stop(__FILE__, __LINE__);
104 struct sigaction newsa, oldsa;
107 sigemptyset(&sigmask);
108 sigaddset(&sigmask, SIGTERM);
109 newsa.sa_handler = SIG_IGN;
110 newsa.sa_mask = sigmask;
112 sigaction(SIGTERM, &newsa, &oldsa);
114 sigemptyset(&sigmask);
115 sigaddset(&sigmask, SIGINT);
116 newsa.sa_handler = SIG_IGN;
117 newsa.sa_mask = sigmask;
119 sigaction(SIGINT, &newsa, &oldsa);
121 //-----------------------------------------------------------------------------
124 STG_LOGGER & WriteServLog = GetStgLogger();
125 WriteServLog("Broken pipe!");
127 //-----------------------------------------------------------------------------
131 //-----------------------------------------------------------------------------
136 childPid = waitpid(-1, &status, WNOHANG);
138 set<pid_t>::iterator pid;
139 pid = executersPid.find(childPid);
140 if (pid != executersPid.end())
142 executersPid.erase(pid);
144 if (childPid == stgChildPid)
149 //-----------------------------------------------------------------------------
150 void SetSignalHandlers()
152 struct sigaction newsa, oldsa;
155 sigemptyset(&sigmask);
156 sigaddset(&sigmask, SIGTERM);
157 newsa.sa_handler = CatchTERM;
158 newsa.sa_mask = sigmask;
160 sigaction(SIGTERM, &newsa, &oldsa);
162 sigemptyset(&sigmask);
163 sigaddset(&sigmask, SIGUSR1);
164 newsa.sa_handler = CatchUSR1;
165 newsa.sa_mask = sigmask;
167 sigaction(SIGUSR1, &newsa, &oldsa);
169 sigemptyset(&sigmask);
170 sigaddset(&sigmask, SIGINT);
171 newsa.sa_handler = CatchTERM;
172 newsa.sa_mask = sigmask;
174 sigaction(SIGINT, &newsa, &oldsa);
176 sigemptyset(&sigmask);
177 sigaddset(&sigmask, SIGPIPE);
178 newsa.sa_handler = CatchPIPE;
179 newsa.sa_mask = sigmask;
181 sigaction(SIGPIPE, &newsa, &oldsa);
183 sigemptyset(&sigmask);
184 sigaddset(&sigmask, SIGHUP);
185 newsa.sa_handler = CatchHUP;
186 newsa.sa_mask = sigmask;
188 sigaction(SIGHUP, &newsa, &oldsa);
190 sigemptyset(&sigmask);
191 sigaddset(&sigmask, SIGCHLD);
192 newsa.sa_handler = CatchCHLD;
193 newsa.sa_mask = sigmask;
195 sigaction(SIGCHLD, &newsa, &oldsa);
197 //-----------------------------------------------------------------------------
200 set<pid_t>::iterator pid;
201 pid = executersPid.begin();
202 while (pid != executersPid.end())
204 printfd(__FILE__, "KillExecuters pid=%d\n", *pid);
209 //-----------------------------------------------------------------------------
210 int StartScriptExecuter(char * procName, int msgKey, int * msgID)
212 STG_LOGGER & WriteServLog = GetStgLogger();
214 if (*msgID == -11) // If msgID == -11 - first call. Create queue
216 for (int i = 0; i < 2; i++)
218 *msgID = msgget(msgKey, IPC_CREAT | IPC_EXCL | 0600);
222 *msgID = msgget(msgKey, 0);
225 WriteServLog("Message queue not created.");
230 msgctl(*msgID, IPC_RMID, NULL);
235 WriteServLog("Message queue created successfully. msgKey=%d msgID=%d", msgKey, *msgID);
241 pid_t executerPid = fork();
246 WriteServLog("Fork error!");
254 Executer(msgKey, *msgID, executerPid, procName);
258 if (executersPid.empty())
259 Executer(msgKey, *msgID, executerPid, NULL);
260 executersPid.insert(executerPid);
264 //-----------------------------------------------------------------------------
265 void StopScriptExecuter(int msgID)
267 STG_LOGGER & WriteServLog = GetStgLogger();
269 for (int i = 0; i < 5; ++i)
271 struct msqid_ds data;
272 if (msgctl(msgID, IPC_STAT, &data))
275 printfd(__FILE__, "StopScriptExecuter() - msgctl for IPC_STAT failed: '%s'\n", strerror(e));
276 WriteServLog( "Failed to check queue emptiness: '%s'", strerror(e));
280 WriteServLog("Messages in queue: %d", data.msg_qnum);
282 if (data.msg_qnum == 0)
285 struct timespec ts = {1, 0};
286 nanosleep(&ts, NULL);
289 if (msgctl(msgID, IPC_RMID, NULL))
292 printfd(__FILE__, "StopScriptExecuter() - msgctl for IPC_STAT failed: '%s'\n", strerror(e));
293 WriteServLog("Failed to remove queue: '%s'", strerror(e));
297 WriteServLog("Queue removed successfully.");
302 //-----------------------------------------------------------------------------
304 int ForkAndWait(const string &)
306 int ForkAndWait(const string & confDir)
310 stgChildPid = fork();
332 //-----------------------------------------------------------------------------
333 int main(int argc, char * argv[])
337 Initialization order:
340 - Set signal nandlers
344 CONFIGFILE * cfg = NULL;
345 LISTENER * listener = NULL;
360 printf("You must be root. Exit.\n");
365 cfg = new CONFIGFILE(argv[1]);
367 cfg = new CONFIGFILE("/etc/rscriptd/rscriptd.conf");
371 STG_LOGGER & WriteServLog = GetStgLogger();
372 WriteServLog.SetLogFileName("/var/log/rscriptd.log");
373 WriteServLog("Error reading config file!");
378 cfg->ReadString("LogFileName", &logFileName, "/var/log/rscriptd.log");
379 cfg->ReadInt("ExecutersNum", &execNum, 1);
380 cfg->ReadInt("ExecMsgKey", &execMsgKey, 5555);
381 cfg->ReadString("ConfigDir", &confDir, "/etc/rscriptd");
382 cfg->ReadString("Password", &password, "");
383 cfg->ReadInt("Port", &port, 5555);
384 cfg->ReadInt("UserTimeout", &userTimeout, 60);
385 cfg->ReadString("ScriptOnConnect", &onConnect, "/etc/rscriptd/OnConnect");
386 cfg->ReadString("ScriptOnDisconnect", &onDisconnect, "/etc/rscriptd/OnDisconnect");
389 if (ForkAndWait(confDir) < 0)
391 STG_LOGGER & WriteServLog = GetStgLogger();
392 WriteServLog("Fork error!");
397 STG_LOGGER & WriteServLog = GetStgLogger();
398 PIDFile pidFile("/var/run/rscriptd.pid");
399 WriteServLog.SetLogFileName(logFileName);
400 WriteServLog("rscriptd v. %s", SERVER_VERSION);
402 for (int i = 0; i < execNum; i++)
404 int ret = StartScriptExecuter(argv[0], execMsgKey, &msgID);
407 STG_LOGGER & WriteServLog = GetStgLogger();
408 WriteServLog("Start Script Executer error!");
419 listener = new LISTENER();
420 listener->SetPort(port);
421 listener->SetPassword(password);
422 listener->SetUserTimeout(userTimeout);
423 listener->SetScriptOnConnect(onConnect);
424 listener->SetScriptOnDisconnect(onDisconnect);
428 WriteServLog("rscriptd started successfully.");
429 WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
431 while (nonstop.GetStatus())
438 WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
440 StopScriptExecuter(msgID);
442 WriteServLog("rscriptd stopped successfully.");
443 WriteServLog("---------------------------------------------");
449 //-----------------------------------------------------------------------------