15 #define RUN_TIMEOUT 10.0 //seconds
16 #define STOP_TIMEOUT 15.0
17 #define KILL_TIMEOUT 10.0
18 #define CONNECTION_TIMEOUT 2.0
20 #define WRITE_TO_PIPE 1
21 #define READ_FROM_PIPE 0
28 #include <sys/types.h>
35 #define PIPE_TIMEOUT 0
37 #define PIPE_SIGNALED 2
38 #define C_MAXARGS 128 // max number of the command parameters
47 class LocalTerminateParams
50 LocalTerminateParams(DWORD
id) {
55 ~LocalTerminateParams(){}
60 BOOL CALLBACK LocalTerminateAppEnum(HWND hwnd, LPARAM lParam)
62 LocalTerminateParams* params=(LocalTerminateParams*)lParam;
64 GetWindowThreadProcessId(hwnd, &dwID);
65 if (dwID==params->dwID)
68 PostMessage(hwnd,WM_CLOSE,0,0);
73 volatile LONGLONG uniquePipeNumber = 0;
75 volatile LONG uniquePipeNumber = 0;
82 OUT LPHANDLE lpReadPipe,
83 OUT LPHANDLE lpWritePipe,
84 IN LPSECURITY_ATTRIBUTES lpPipeAttributes,
87 HANDLE ReadPipeHandle, WritePipeHandle;
89 char PipeNameBuffer[MAX_PATH];
90 nSize = (nSize ==0) ? 100*8096: nSize;
93 InterlockedIncrement64(&uniquePipeNumber);
95 InterlockedIncrement(&uniquePipeNumber);
98 sprintf( PipeNameBuffer,
99 "\\\\.\\Pipe\\RemoteExeAnon.%08x.%08x",
100 GetCurrentProcessId(),
104 ReadPipeHandle = CreateNamedPipeA(
105 (LPSTR)PipeNameBuffer,
106 PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
107 PIPE_TYPE_BYTE | PIPE_WAIT,
115 if (! ReadPipeHandle) {
119 WritePipeHandle = CreateFileA(
120 (LPSTR)PipeNameBuffer,
125 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
129 if (INVALID_HANDLE_VALUE == WritePipeHandle)
131 dwError = GetLastError();
132 CloseHandle( ReadPipeHandle );
133 SetLastError(dwError);
137 *lpReadPipe = ReadPipeHandle;
138 *lpWritePipe = WritePipeHandle;
144 LocalBroker::LocalBroker()
146 bOnlyConnector = bInitialized =
false;
149 setWindowMode(WINDOW_HIDDEN);
153 LocalBroker::~LocalBroker()
158 void LocalBroker::fini()
164 bool LocalBroker::init()
174 bOnlyConnector =
true;
178 bool LocalBroker::init(
const char* szcmd,
const char* szparam,
179 const char* szhost,
const char* szstdio,
180 const char* szworkdir,
const char* szenv )
193 strError =
"command is not specified.";
197 if(szparam && strlen(szparam))
200 if(szhost && strlen(szhost))
202 if(szworkdir && strlen(szworkdir))
203 strWorkdir = szworkdir;
205 if(szstdio && strlen(szstdio))
207 if(szstdio[0] !=
'/')
208 strStdio = string(
"/") + string(szstdio);
213 if(szenv && strlen(szenv))
235 struct sigaction new_action;
236 new_action.sa_handler = SIG_IGN;
237 sigemptyset (&new_action.sa_mask);
238 new_action.sa_flags = 0;
239 sigaction (SIGCHLD, &new_action,
nullptr);
247 bool LocalBroker::start()
249 if(!bInitialized)
return false;
250 if(bOnlyConnector)
return false;
267 bool LocalBroker::stop()
269 if(!bInitialized)
return true;
270 if(bOnlyConnector)
return false;
288 strError =
"Timeout! cannot stop ";
295 bool LocalBroker::kill()
297 if(!bInitialized)
return true;
298 if(bOnlyConnector)
return false;
317 strError =
"Timeout! cannot kill ";
325 int LocalBroker::running()
327 if(!bInitialized)
return 0;
328 if(bOnlyConnector)
return 0;
329 return (psCmd(ID))?1:0;
336 bool LocalBroker::connect(
const char* from,
const char* to,
337 const char* carrier,
bool persist)
342 strError =
"no source port is introduced.";
348 strError =
"no destination port is introduced.";
355 strError +=
" does not exist.";
362 strError +=
" does not exist.";
368 strError =
"cannot connect ";
370 strError +=
" to " + string(to);
376 bool LocalBroker::disconnect(
const char* from,
const char* to,
const char *carrier)
381 strError =
"no source port is introduced.";
387 strError =
"no destination port is introduced.";
394 strError +=
" does not exist.";
401 strError +=
" does not exist.";
405 if(!connected(from, to, carrier))
410 strError =
"cannot disconnect ";
412 strError +=
" from " + string(to);
419 bool LocalBroker::exists(
const char* port)
425 const char* LocalBroker::requestRpc(
const char* szport,
const char* request,
double timeout)
427 if((szport==
nullptr) || (request==
nullptr))
436 if(!port.
open(
"..."))
443 for(
int i=0; i<10; i++) {
467 bool LocalBroker::connected(
const char* from,
const char* to,
const char* carrier)
469 if(!exists(from) || !exists(to))
475 const char* LocalBroker::error()
477 return strError.c_str();
480 bool LocalBroker::attachStdout()
486 strError =
"Module is not running";
489 return startStdout();
492 void LocalBroker::detachStdout()
498 bool LocalBroker::timeout(
double base,
double timeout)
506 bool LocalBroker::threadInit()
512 void LocalBroker::run()
521 BOOL bRet = ReadFile(read_from_pipe_cmd_to_stdout,
522 buff, 1023, &dwRead,
nullptr);
525 buff[dwRead] = (CHAR)0;
526 if(eventSink && strlen(buff))
527 eventSink->onBrokerStdout(buff);
539 while(fgets(buff, 1024, fd_stdout))
540 strmsg += string(buff);
541 if(eventSink && strmsg.size())
542 eventSink->onBrokerStdout(strmsg.c_str());
551 void LocalBroker::threadRelease()
564 string LocalBroker::lastError2String()
566 int error=GetLastError();
568 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
nullptr,error,0,buff,1024,
nullptr);
572 bool LocalBroker::startStdout()
574 if (!CloseHandle(write_to_pipe_cmd_to_stdout))
580 void LocalBroker::stopStdout()
585 int LocalBroker::ExecuteCmd()
587 string strCmdLine = strCmd + string(
" ") + strParam;
589 PROCESS_INFORMATION cmd_process_info;
590 STARTUPINFO cmd_startup_info;
591 ZeroMemory(&cmd_process_info,
sizeof(PROCESS_INFORMATION));
592 ZeroMemory(&cmd_startup_info,
sizeof(STARTUPINFO));
593 cmd_startup_info.cb =
sizeof(STARTUPINFO);
596 string strDisplay=getDisplay();
598 DWORD dwCreationFlags;
611 if (windowMode==WINDOW_VISIBLE)
614 cmd_startup_info.dwFlags |= STARTF_USESHOWWINDOW;
615 cmd_startup_info.wShowWindow = SW_SHOWNA;
616 dwCreationFlags=CREATE_NEW_CONSOLE;
618 if (windowMode==WINDOW_HIDDEN)
621 SECURITY_ATTRIBUTES pipe_sec_attr;
622 pipe_sec_attr.nLength =
sizeof(SECURITY_ATTRIBUTES);
623 pipe_sec_attr.bInheritHandle = TRUE;
624 pipe_sec_attr.lpSecurityDescriptor =
nullptr;
625 CreatePipeAsync(&read_from_pipe_cmd_to_stdout,
626 &write_to_pipe_cmd_to_stdout,
629 cmd_startup_info.hStdError = write_to_pipe_cmd_to_stdout;
630 cmd_startup_info.hStdOutput = write_to_pipe_cmd_to_stdout;
632 cmd_startup_info.dwFlags |= STARTF_USESTDHANDLES;
634 dwCreationFlags=CREATE_NEW_PROCESS_GROUP;
642 TCHAR chNewEnv[32767];
645 LPTCH chOldEnv = GetEnvironmentStrings();
648 LPTSTR lpOld = (LPTSTR) chOldEnv;
649 LPTSTR lpNew = (LPTSTR) chNewEnv;
652 lstrcpy(lpNew, lpOld);
653 lpOld += lstrlen(lpOld) + 1;
654 lpNew += lstrlen(lpNew) + 1;
658 std::string cstrEnvName;
662 for(
int i=0; i<ss.size(); i++) {
663 lstrcpy(lpNew, (LPTCH) ss.get(i));
664 lpNew += lstrlen(lpNew) + 1;
671 bool bWorkdir=(strWorkdir.size()) ?
true :
false;
672 string strWorkdirOk = bWorkdir ? strWorkdir+string(
"\\") :
"";
674 BOOL bSuccess=CreateProcess(
nullptr,
675 (
char*)(strWorkdirOk+strCmdLine).c_str(),
681 bWorkdir?strWorkdirOk.c_str():
nullptr,
685 if (!bSuccess && bWorkdir)
687 bSuccess=CreateProcess(
nullptr,
688 (
char*)(strCmdLine.c_str()),
694 strWorkdirOk.c_str(),
700 FreeEnvironmentStrings(chOldEnv);
702 CloseHandle(cmd_process_info.hProcess);
703 CloseHandle(cmd_process_info.hThread);
707 strError = string(
"Can't execute command because ") + lastError2String();
711 return cmd_process_info.dwProcessId;
714 bool LocalBroker::psCmd(
int pid)
716 HANDLE hProc=OpenProcess(SYNCHRONIZE|PROCESS_QUERY_INFORMATION, FALSE, pid);
721 GetExitCodeProcess(hProc , &status);
723 return (status==STILL_ACTIVE);
726 bool LocalBroker::killCmd(
int pid)
728 HANDLE hProc=OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, pid);
732 BOOL bRet = TerminateProcess(hProc, 0);
734 return bRet ? true :
false;
737 bool LocalBroker::stopCmd(
int pid)
739 HANDLE hProc=OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, pid);
743 LocalTerminateParams params(pid);
744 EnumWindows((WNDENUMPROC)LocalTerminateAppEnum,(LPARAM)¶ms);
747 GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid);
750 GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid);
758 bool LocalBroker::psCmd(
int pid)
762 return !::kill(pid, 0);
766 bool LocalBroker::killCmd(
int pid)
770 return !::kill(pid, SIGKILL);
774 bool LocalBroker::stopCmd(
int pid)
778 return !::kill(pid, SIGTERM);
781 int LocalBroker::waitPipe(
int pipe_fd)
783 struct timeval timeout;
788 timeout.tv_usec = 500000;
791 FD_SET(pipe_fd, &fd);
792 rc = select(pipe_fd + 1, &fd,
nullptr,
nullptr, &timeout);
797 int LocalBroker::waitPipeSignal(
int pipe_fd)
799 struct timespec timeout;
805 FD_SET(pipe_fd, &fd);
822 if(pselect(pipe_fd + 1, &fd,
nullptr,
nullptr, &timeout,
nullptr))
828 bool LocalBroker::startStdout()
833 strError =
"cannot open pipe. " + string(strerror(errno));
839 if(fcntl(pipe_to_stdout[
READ_FROM_PIPE], F_SETFL, oflags|O_NONBLOCK) == -1)
841 strError =
"cannot set flag on pipe: " + string(strerror(errno));
849 void LocalBroker::stopStdout()
859 int LocalBroker::ExecuteCmd()
861 int pipe_child_to_parent[2];
862 int ret = pipe(pipe_child_to_parent);
865 strError = string(
"Can't create child pipe because") + string(strerror(errno));
869 ret = pipe(pipe_to_stdout);
872 strError = string(
"Can't create stdout pipe because") + string(strerror(errno));
876 int pid_cmd =
fork();
878 if(IS_INVALID(pid_cmd))
880 strError = string(
"Can't fork command because ") + string(strerror(errno));
884 if (IS_NEW_PROCESS(pid_cmd))
890 if (fcntl(STDOUT_FILENO, F_SETFL, fcntl(STDOUT_FILENO, F_GETFL) | O_NONBLOCK) == -1) {
891 strError = string(
"Can't set flag on stdout: ") + string(strerror(errno));
894 if (fcntl(STDERR_FILENO, F_SETFL, fcntl(STDERR_FILENO, F_GETFL) | O_NONBLOCK) == -1) {
895 strError = string(
"Can't set flag on stderr: ") + string(strerror(errno));
902 strCmd = strCmd + string(
" ") + strParam;
903 char *szcmd =
new char[strCmd.size()+1];
904 strcpy(szcmd,strCmd.c_str());
908 szarg[nargs]=
nullptr;
912 for(
int i=0; i<ss.size(); i++) {
913 char* szenv =
new char[strlen(ss.get(i))+1];
914 strcpy(szenv,ss.get(i));
920 if(strWorkdir.size())
922 int ret = chdir(strWorkdir.c_str());
925 strError = string(
"Can't set working directory because ") + string(strerror(errno));
926 FILE* out_to_parent = fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
927 fprintf(out_to_parent,
"%s", strError.c_str());
928 fflush(out_to_parent);
929 fclose(out_to_parent);
937 char currWorkDirBuff[1024];
938 char *currWorkDir =
getcwd(currWorkDirBuff,1024);
943 char **cwd_szarg=
new char*[nargs+1];
944 for (
int i=1; i<nargs; ++i) cwd_szarg[i]=szarg[i];
945 cwd_szarg[nargs]=
nullptr;
946 cwd_szarg[0]=
new char[strlen(currWorkDir)+strlen(szarg[0])+16];
948 strcpy(cwd_szarg[0],currWorkDir);
949 strcat(cwd_szarg[0],
"/");
950 strcat(cwd_szarg[0],szarg[0]);
951 ret=execvp(cwd_szarg[0],cwd_szarg);
952 delete [] cwd_szarg[0];
958 ret=execvp(szarg[0],szarg);
963 strError = string(
"Can't execute command because ") + string(strerror(errno));
964 FILE* out_to_parent = fdopen(pipe_child_to_parent[
WRITE_TO_PIPE],
"w");
965 fprintf(out_to_parent,
"%s", strError.c_str());
966 fflush(out_to_parent);
967 fclose(out_to_parent);
975 if (IS_PARENT_OF(pid_cmd))
978 FILE* in_from_child = fdopen(pipe_child_to_parent[
READ_FROM_PIPE],
"r");
980 if (fcntl(pipe_child_to_parent[
READ_FROM_PIPE],F_SETFL,flags|O_NONBLOCK) == -1)
982 strError = string(
"Can't set flag on pipe: ") + string(strerror(errno));
983 fclose(in_from_child);
990 for (
char buff[1024]; fgets(buff,1024,in_from_child);)
991 retError +=
string(buff);
992 fclose(in_from_child);
1014 char *pTmp = strchr(pLine,
' ');
1019 while ((*pTmp) && (*pTmp ==
' ')) {
1022 if (*pTmp ==
'\0') {
1036 char *pNext = io_pLine;
1040 size_t len = strlen(io_pLine);
1043 for(i = 0; i < len; i++) {
1044 if ((!quoted) && (
'"' == io_pLine[i])) {
1047 }
else if ((quoted) && (
'"' == io_pLine[i])) {
1050 }
else if ((quoted) && (
' ' == io_pLine[i])) {
1056 memset(o_pArgv, 0x00,
sizeof(
char*) *
C_MAXARGS);
1058 o_pArgv[0] = io_pLine;
1060 while ((
nullptr != pNext) && (*o_pArgc <
C_MAXARGS)) {
1062 pNext = o_pArgv[*o_pArgc];
1064 if (
nullptr != o_pArgv[*o_pArgc]) {
1069 for(j = 0; j < *o_pArgc; j++) {
1070 len = strlen(o_pArgv[j]);
1071 for(i = 0; i < len; i++) {
1072 if(
'\1' == o_pArgv[j][i]) {
1073 o_pArgv[j][i] =
' ';