17 #include <sipwitch-config.h>
18 #include <ucommon/ucommon.h>
19 #include <ucommon/export.h>
31 static const char *replytarget = NULL;
41 #include <sys/resource.h>
47 static FILE *fifo = NULL;
48 static char fifopath[128] =
"";
50 static void cleanup(
void)
54 char *cp = strrchr(fifopath,
'/');
55 String::set(cp, 10,
"/pidfile");
65 String::set(fifopath,
sizeof(fifopath),
env(
"control"));
67 if(mkfifo(fifopath, fsys::GROUP_PRIVATE)) {
72 shell::exiting(&cleanup);
74 fifo = fopen(fifopath,
"r+");
83 shell::log(shell::INFO,
"shutdown");
99 if(fgets(buf,
sizeof(buf), fifo) == NULL) {
103 cp = String::strip(buf,
" \t\r\n");
108 if(strncmp(cp,
"/tmp/.reply.", 12))
112 if(*cp ==
'/' || isdigit(*cp)) {
114 while(*cp && !isspace(*cp))
125 static HANDLE hFifo = INVALID_HANDLE_VALUE;
126 static HANDLE hLoopback = INVALID_HANDLE_VALUE;
127 static HANDLE hEvent = INVALID_HANDLE_VALUE;
128 static OVERLAPPED ovFifo;
130 static void cleanup(
void)
132 if(hFifo != INVALID_HANDLE_VALUE) {
134 CloseHandle(hLoopback);
136 hFifo = hLoopback = hEvent = INVALID_HANDLE_VALUE;
146 String::set(buf,
sizeof(buf),
env(
"control"));
147 hFifo = CreateMailslot(buf, 0, MAILSLOT_WAIT_FOREVER, NULL);
148 if(hFifo == INVALID_HANDLE_VALUE)
151 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
152 hLoopback = CreateFile(buf, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
154 ovFifo.OffsetHigh = 0;
155 ovFifo.hEvent = hEvent;
156 shell::exiting(&cleanup);
162 static char buf[464];
168 if(hFifo == INVALID_HANDLE_VALUE)
174 result = ReadFile(hFifo, buf,
sizeof(buf) - 1, &msgresult, &ovFifo);
175 if(!result && GetLastError() == ERROR_IO_PENDING) {
176 int ret = WaitForSingleObject(ovFifo.hEvent, INFINITE);
177 if(ret != WAIT_OBJECT_0)
179 result = GetOverlappedResult(hFifo, &ovFifo, &msgresult, TRUE);
182 if(!result || msgresult < 1)
186 cp = String::strip(buf,
" \t\r\n");
192 if(strncmp(cp,
"\\\\.\\mailslot\\", 14))
196 if(*cp ==
'\\' || isdigit(*cp)) {
198 while(*cp && !isspace(*cp))
203 lp = replytarget + strlen(replytarget) - 6;
204 if(stricmp(lp,
"_temp"))
212 shell::log(shell::INFO,
"shutdown");
220 assert(msg == NULL || *msg != 0);
227 shell::log(shell::ERR,
"control failed; %s", msg);
232 if(isdigit(*replytarget)) {
234 pid_t pid = atoi(replytarget);
242 sid = (
char *)strchr(replytarget,
';');
249 snprintf(buffer,
sizeof(buffer),
"%s msg %s\n", sid, msg);
251 snprintf(buffer,
sizeof(buffer),
"%s ok\n", sid);
252 fd.open(replytarget, fsys::WRONLY);
254 fd.write(buffer, strlen(buffer));
268 va_start(vargs, fmt);
270 vsnprintf(buf,
sizeof(buf), fmt, vargs);
273 shell::debug(5,
"executing %s", buf);
277 int max =
sizeof(fd_set) * 8;
282 if(!getrlimit(RLIMIT_NOFILE, &rlim))
286 waitpid(pid, NULL, 0);
289 ::signal(SIGABRT, SIG_DFL);
290 ::signal(SIGQUIT, SIG_DFL);
291 ::signal(SIGINT, SIG_DFL);
292 ::signal(SIGCHLD, SIG_DFL);
293 ::signal(SIGPIPE, SIG_DFL);
294 int fd = open(
"/dev/null", O_RDWR);
297 dup2(fileno(fifo), 1);
298 for(fd = 3; fd < max; ++fd)
303 ::execlp(
"/bin/sh",
"sh",
"-c", buf, NULL);
311 assert(fmt != NULL && *fmt != 0);
319 va_start(vargs, fmt);
321 fd = CreateFile(
env(
"control"), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
322 if(fd == INVALID_HANDLE_VALUE) {
328 fd = open(
env(
"control"), O_WRONLY | O_NONBLOCK);
335 vsnprintf(buf,
sizeof(buf) - 1, fmt, vargs);
338 if(buf[len - 1] !=
'\n')
341 if(!WriteFile(fd, buf, (DWORD)strlen(buf) + 1, NULL, NULL))
347 if(::write(fd, buf, len) < len)
359 char buf[256], buf1[256];
361 String::set(buf,
sizeof(buf), _STR(
path(
"prefix") +
"/states/" + state +
".xml"));
362 if(!fsys::is_file(buf))
364 String::set(buf1,
sizeof(buf1), _STR(
path(
"prefix") +
"state.xml"));
366 if(!stricmp(state,
"up") || !stricmp(state,
"none"))
370 if(symlink(buf, buf1))
386 return fopen(_STR(
path(
"controls") +
"/" +
id +
".out"),
"w");
388 if(replytarget && isdigit(*replytarget))
389 return fopen(
path(
"reply") + str((Unsigned)atol(replytarget)),
"w");
392 return fopen(_STR(
path(
"controls") +
"/" +
id),
"w");
Used for definitions of plugin modules.
static String path(const char *id)
Get a string from a server environment variable.
static void reply(const char *error=NULL)
Used by the server to send replies back to control requests.
static size_t attach(shell_t *env)
Creates the control fifo using server configuration.
static bool send(const char *format,...) __PRINTF(1
Send a printf-style message to the control fifo via the file system.
static void release(void)
Used by the server to destroy the control fifo.
static bool static char * receive(void)
Used by the server to pull pending fifo requests.
static bool static FILE * output(const char *id)
Used to open an output session for returning control data.
static bool libexec(const char *fmt,...) __PRINTF(1
Execute an external shell command on behalf of the server.
static bool state(const char *value)
Sets server run state configuration.
Service configuration and component callbacks.
Manage control interface.
static const char * env(const char *id)
Return the value of a server environment variable.