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/stg_logger.h"
43 #include "stg/script_executer.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();
259 string startFile = confDir + START_FILE;
260 unlink(startFile.c_str());
276 for (int i = 0; i < 120 * 5; i++)
278 if (access(startFile.c_str(), F_OK) == 0)
280 //printf("Fork successfull. Exit.\n");
281 unlink(startFile.c_str());
287 unlink(startFile.c_str());
292 unlink(startFile.c_str());
299 //-----------------------------------------------------------------------------
302 set<pid_t>::iterator pid;
303 pid = executersPid.begin();
304 while (pid != executersPid.end())
306 printfd(__FILE__, "KillExecuters pid=%d\n", *pid);
311 //-----------------------------------------------------------------------------
312 int main(int argc, char * argv[])
316 Initialization order:
319 - Set signal nandlers
323 CONFIGFILE * cfg = NULL;
324 LISTENER * listener = NULL;
339 printf("You must be root. Exit.\n");
344 cfg = new CONFIGFILE(argv[1]);
346 cfg = new CONFIGFILE("/etc/rscriptd/rscriptd.conf");
350 STG_LOGGER & WriteServLog = GetStgLogger();
351 WriteServLog.SetLogFileName("/var/log/rscriptd.log");
352 WriteServLog("Error reading config file!");
357 cfg->ReadString("LogFileName", &logFileName, "/var/log/rscriptd.log");
358 cfg->ReadInt("ExecutersNum", &execNum, 1);
359 cfg->ReadInt("ExecMsgKey", &execMsgKey, 5555);
360 cfg->ReadString("ConfigDir", &confDir, "/etc/rscriptd");
361 cfg->ReadString("Password", &password, "");
362 cfg->ReadInt("Port", &port, 5555);
363 cfg->ReadInt("UserTimeout", &userTimeout, 60);
364 cfg->ReadString("ScriptOnConnect", &onConnect, "/etc/rscriptd/OnConnect");
365 cfg->ReadString("ScriptOnDisconnect", &onDisconnect, "/etc/rscriptd/OnDisconnect");
368 if (ForkAndWait(confDir) < 0)
370 STG_LOGGER & WriteServLog = GetStgLogger();
371 WriteServLog("Fork error!");
376 STG_LOGGER & WriteServLog = GetStgLogger();
377 PIDFile pidFile("/var/run/rscriptd.pid");
378 WriteServLog.SetLogFileName(logFileName);
379 WriteServLog("rscriptd v. %s", SERVER_VERSION);
381 for (int i = 0; i < execNum; i++)
383 int ret = StartScriptExecuter(argv[0], execMsgKey, &msgID);
386 STG_LOGGER & WriteServLog = GetStgLogger();
387 WriteServLog("Start Script Executer error!");
398 listener = new LISTENER();
399 listener->SetPort(port);
400 listener->SetPassword(password);
401 listener->SetUserTimeout(userTimeout);
402 listener->SetScriptOnConnect(onConnect);
403 listener->SetScriptOnDisconnect(onDisconnect);
407 WriteServLog("rscriptd started successfully.");
408 WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
411 string startFile(confDir + START_FILE);
412 creat(startFile.c_str(), S_IRUSR);
415 while (nonstop.GetStatus())
422 WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++");
424 int res = msgctl(msgID, IPC_RMID, NULL);
426 WriteServLog("Queue was not removed. id=%d", msgID);
428 WriteServLog("Queue removed successfully.");
432 WriteServLog("rscriptd stopped successfully.");
433 WriteServLog("---------------------------------------------");
439 //-----------------------------------------------------------------------------