void BinaryDebugger::attach(const std::vector<std::string> &exeNameAndArgs) { ASSERT_forbid(exeNameAndArgs.empty()); detach(); child_ = fork(); if (0==child_) { char **argv = new char*[exeNameAndArgs.size()+1]; for (size_t i=0; i<exeNameAndArgs.size(); ++i) argv[i] = strdup(exeNameAndArgs[i].c_str()); argv[exeNameAndArgs.size()] = NULL; if (-1 == ptrace(PTRACE_TRACEME, 0, 0, 0)) { std::cerr <<"BinaryDebugger::attach: ptrace_traceme failed: " <<strerror(errno) <<"\n"; exit(1); } execv(argv[0], argv); std::cerr <<"BinaryDebugger::attach: exec \"" <<StringUtility::cEscape(argv[0]) <<"\" failed: " <<strerror(errno) <<"\n"; exit(1); } howDetach_ = DETACH; waitForChild(); if (isTerminated()) throw std::runtime_error("BinaryDebugger::attach: subordinate " + howTerminated() + " before we gained control"); }
int PasswdProcess::exec(const char *oldpass, const char *newpass, int check) { if(m_User.isEmpty()) return -1; // if (check) // setTerminal(true); // Try to set the default locale to make the parsing of the output // of `passwd' easier. setenv("LANG", "C", true /* override */); KStringList args; if(bOtherUser) args += m_User; int ret = PtyProcess::exec("passwd", args); if(ret < 0) { kdDebug(1512) << k_lineinfo << "Passwd not found!\n"; return PasswdNotFound; } ret = ConversePasswd(oldpass, newpass, check); if(ret < 0) kdDebug(1512) << k_lineinfo << "Conversation with passwd failed. pid = " << pid() << endl; if((waitForChild() != 0) && !check) return PasswordNotGood; return ret; }
MprCmd::~MprCmd() { mprLog(5, log, "~MprCmd: pid %d\n", pid); // // All this should have been done already, but we play it safe and make // sure everthing is cleaned up. Increment inuse to prevent stop() and // waitForChild() calling us again. // inUse++; mprAssert(flags & MPR_CMD_DISPOSED); if (flags & MPR_CMD_RUNNING) { stop(1, 0); if (!(flags & MPR_CMD_WAITED)) { waitForChild(MPR_TIMEOUT_STOP); } } if (timer) { timer->dispose(); } if (task) { task->dispose(); } mpr->cmdService->removeCmd(this); mprFree(cwd); #if BLD_FEATURE_LOG delete log; #endif delete mutex; inUse--; }
bool MprCmd::dispose() { lock(); mprAssert(inUse > 0); if (flags & MPR_CMD_DISPOSED) { mprAssert(0); unlock(); return 0; } flags |= MPR_CMD_DISPOSED; mprLog(5, log, "dispose: inUse %d, pid %d\n", inUse, pid); if (flags & MPR_CMD_RUNNING) { mprAssert(!(flags & MPR_CMD_WAITED)); // // Do our best to reap the child death. Forced kill and then wait // stop(1, 0); waitForChild(MPR_TIMEOUT_STOP); } if (--inUse == 0) { delete this; return 1; } else { unlock(); return 0; } }
void Daemon::setDefault( bool wait ) { connections().lockedClear(); _rope.reset(); if ( _state == State::Grouped || _state == State::Leaving ) _quit = true; _state = State::Free; if ( _childPid != NoChild ) { waitForChild( wait ); _childPid = NoChild; } rank( 0 ); worldSize( 0 ); }
void BinaryDebugger::runToBreakpoint() { if (breakpoints_.isEmpty()) { sendCommand(PTRACE_CONT, child_, 0, (void*)sendSignal_); waitForChild(); } else { while (1) { singleStep(); if (isTerminated()) break; user_regs_struct regs; sendCommand(PTRACE_GETREGS, child_, 0, ®s); if (breakpoints_.exists(getInstructionPointer(regs))) break; } } }
int ChfnProcess::exec(const char *pass, const char *name) { // Try to set the default locale to make the parsing of the output // of `chfn' easier. putenv((char*)"LC_ALL=C"); QCStringList args; args += "-f"; args += name; int ret = PtyProcess::exec("chfn", args); if (ret < 0) return ChfnNotFound; ret = ConverseChfn(pass); waitForChild(); return ret; }
void BinaryDebugger::attach(int child, bool attach) { if (-1 == child) { detach(); } else if (child == child_) { // do nothing } else if (attach) { child_ = child; howDetach_ = NOTHING; sendCommand(PTRACE_ATTACH, child_); howDetach_ = DETACH; waitForChild(); if (SIGSTOP==sendSignal_) sendSignal_ = 0; } else { child_ = child; howDetach_ = NOTHING; } }
void BinaryDebugger::detach() { if (child_ && !isTerminated()) { switch (howDetach_) { case NOTHING: break; case CONTINUE: kill(child_, SIGCONT); break; case DETACH: sendCommand(PTRACE_DETACH, child_); break; case KILL: sendCommand(PTRACE_KILL, child_); waitForChild(); } } howDetach_ = NOTHING; child_ = 0; }
int MprCmd::getExitCode(int *status) { mprAssert(status); lock(); if (! (flags & MPR_CMD_WAITED)) { // // May get EOF before process has actually exited. Nap for up to 5 sec // if (waitForChild(5000) < 0) { mprLog(5, log, "%d: getExitCode: pid %d\n", waitFd, pid); unlock(); return MPR_ERR_NOT_READY; } } if (status) { *status = exitStatus; } unlock(); mprLog(5, log, "%d: getExitCode: pid %d, code %d\n", waitFd, pid, *status); return 0; }
static LRESULT CALLBACK mainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDCANCEL: // save data if (saveMainWindow(hwnd, true)) { // quit PostQuitMessage(0); } return 0; case IDOK: case IDC_MAIN_TEST: { // note if testing const bool testing = (LOWORD(wParam) == IDC_MAIN_TEST); // save data if (saveMainWindow(hwnd, false)) { // launch child app DWORD threadID; HANDLE thread = launchApp(hwnd, testing, &threadID); if (thread == NULL) { return 0; } // handle child program if (testing) { // wait for process to stop, allowing the user to kill it waitForChild(hwnd, thread, threadID); // clean up CloseHandle(thread); } else { // don't need thread handle CloseHandle(thread); // notify of success askOkay(hwnd, getString(IDS_STARTED_TITLE), getString(IDS_STARTED)); // quit PostQuitMessage(0); } } return 0; } case IDC_MAIN_AUTOSTART: { CString cmdLine; if (saveMainWindow(hwnd, false, &cmdLine)) { // run dialog CAutoStart autoStart(hwnd, !isClientChecked(hwnd), cmdLine); autoStart.doModal(); } return 0; } case IDC_MAIN_CLIENT_RADIO: case IDC_MAIN_SERVER_RADIO: enableMainWindowControls(hwnd); return 0; case IDC_MAIN_SCREENS: s_screensLinks->doModal(); break; case IDC_MAIN_OPTIONS: s_globalOptions->doModal(); break; case IDC_MAIN_ADVANCED: s_advancedOptions->doModal(isClientChecked(hwnd)); break; } default: break; } return DefDlgProc(hwnd, message, wParam, lParam); }
int main() { XPCTcpSocket *clientConnection; // Pointer to new XPCTcpSocket instance // derived from the vAccept method. STcpThreadStruct *newTCPThreadStruct; // Pointer to an instance of STcpThreadStruct int iChildpid; // Stores the process ID of the child // spawned. char sHost[80]; // Name of the host machine that connected // Create an unnamed semaphore XPCSemaphore positionSem((int)PRIVATE_SEM, (unsigned int)1); try { // Instance of XPCTcpSocket creates and opens a new TCP socket. This instance // of XPCTcpSocket is dedicated to accepting client connections. XPCTcpSocket portfolioSocket((long int)UNIX_PORT_NUM); // Socket is bound to the port number specified by the UNIX_PORT_NUM definition // and client connections are listened for. portfolioSocket.vBindSocket(); portfolioSocket.vListen(); iNumUsers = 0; // Set the number of portfolios to 0 // The server loops forever accepting client connections and spawning additional // server processes. The additional server processes are dedicated for // communicating position adjustments with its connected client. while(1) { // Client is accepted and a new socket file descriptor is created for // communication clientConnection = portfolioSocket.Accept(sHost); // Fork a child pricess if ((iChildpid = fork()) == -1) { cerr << "Error Forking: " << strerror(errno) << endl; return 0; } if (iChildpid == 0) { execlp("TCPPrice", "TCPPrice", sHost, NULL); } // Prevent a zombie process from being created else { XPCWaitPid waitForChild(); } // Create an instance of STcpThreadStruct and store the thread related // information newTCPThreadStruct = new STcpThreadStruct; newTCPThreadStruct->clientConnection = clientConnection; newTCPThreadStruct->positionSem = &positionSem; newTCPThreadStruct->iChildPid = iChildpid; // Create a thread to process the client's request XPCPthread<int> newPositionKeeper(vStockPositionTracker, (void *)newTCPThreadStruct); } } // All XPC related exceptions are caught. catch(XPCException &exceptObject) { cout << exceptObject.sGetException() << endl; return 0; } }
static LRESULT CALLBACK mainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDCANCEL: // test for unsaved data if (ARG->m_config != ARG->m_oldConfig) { if (!askVerify(hwnd, getString(IDS_UNSAVED_DATA_REALLY_QUIT))) { return 0; } } // quit PostQuitMessage(0); return 0; case IDOK: case IDC_MAIN_TEST: { // note if testing const bool testing = (LOWORD(wParam) == IDC_MAIN_TEST); // save data if (ARG->m_config != ARG->m_oldConfig) { if (!saveConfig(ARG->m_config, false)) { showError(hwnd, CStringUtil::format( getString(IDS_SAVE_FAILED).c_str(), getErrorString(GetLastError()).c_str())); return 0; } ARG->m_oldConfig = ARG->m_config; enableSaveControls(hwnd); } // launch child app DWORD threadID; HANDLE thread = launchApp(hwnd, testing, &threadID); if (thread == NULL) { return 0; } // handle child program if (testing) { // wait for process to stop, allowing the user to kill it waitForChild(hwnd, thread, threadID); // clean up CloseHandle(thread); } else { // don't need thread handle CloseHandle(thread); // notify of success askOkay(hwnd, getString(IDS_STARTED_TITLE), getString(IDS_STARTED)); // quit PostQuitMessage(0); } return 0; } case IDC_MAIN_AUTOSTART: { // construct command line CString cmdLine = getCommandLine(hwnd, false); if (!cmdLine.empty()) { // run dialog CAutoStart autoStart(hwnd, isClientChecked(hwnd) ? NULL : &ARG->m_config, cmdLine); autoStart.doModal(); if (autoStart.wasUserConfigSaved()) { ARG->m_oldConfig = ARG->m_config; enableSaveControls(hwnd); } } return 0; } case IDC_MAIN_SAVE: if (!saveConfig(ARG->m_config, false)) { showError(hwnd, CStringUtil::format( getString(IDS_SAVE_FAILED).c_str(), getErrorString(GetLastError()).c_str())); } else { ARG->m_oldConfig = ARG->m_config; enableSaveControls(hwnd); } return 0; case IDC_MAIN_CLIENT_RADIO: case IDC_MAIN_SERVER_RADIO: enableMainWindowControls(hwnd); return 0; case IDC_MAIN_SERVER_ADD_BUTTON: addScreen(hwnd); return 0; case IDC_MAIN_SERVER_EDIT_BUTTON: editScreen(hwnd); return 0; case IDC_MAIN_SERVER_REMOVE_BUTTON: removeScreen(hwnd); return 0; case IDC_MAIN_SERVER_SCREENS_LIST: if (HIWORD(wParam) == LBN_SELCHANGE) { enableScreensControls(hwnd); updateNeighbors(hwnd); } else if (HIWORD(wParam) == LBN_DBLCLK) { editScreen(hwnd); return 0; } break; case IDC_MAIN_SERVER_LEFT_COMBO: if (HIWORD(wParam) == CBN_SELENDOK) { changeNeighbor(hwnd, (HWND)lParam, kLeft); return 0; } break; case IDC_MAIN_SERVER_RIGHT_COMBO: if (HIWORD(wParam) == CBN_SELENDOK) { changeNeighbor(hwnd, (HWND)lParam, kRight); return 0; } break; case IDC_MAIN_SERVER_TOP_COMBO: if (HIWORD(wParam) == CBN_SELENDOK) { changeNeighbor(hwnd, (HWND)lParam, kTop); return 0; } break; case IDC_MAIN_SERVER_BOTTOM_COMBO: if (HIWORD(wParam) == CBN_SELENDOK) { changeNeighbor(hwnd, (HWND)lParam, kBottom); return 0; } break; case IDC_MAIN_OPTIONS: s_globalOptions->doModal(); enableSaveControls(hwnd); break; case IDC_MAIN_ADVANCED: s_advancedOptions->doModal(isClientChecked(hwnd)); enableSaveControls(hwnd); break; } default: break; } return DefDlgProc(hwnd, message, wParam, lParam); }
int SshProcess::exec(const char *password, int check) { if(check) setTerminal(true); KStringList args; args += "-l"; args += m_User; args += "-o"; args += "StrictHostKeyChecking=no"; args += m_Host; args += m_Stub; if(StubProcess::exec("ssh", args) < 0) { return check ? SshNotFound : -1; } int ret = ConverseSsh(password, check); if(ret < 0) { if(!check) kdError(900) << k_lineinfo << "Conversation with ssh failed\n"; return ret; } if(check == 2) { if(ret == 1) { kill(m_Pid, SIGTERM); waitForChild(); } return ret; } if(m_bErase && password) { char *ptr = const_cast< char * >(password); const uint plen = strlen(password); for(unsigned i = 0; i < plen; i++) ptr[i] = '\000'; } ret = ConverseStub(check); if(ret < 0) { if(!check) kdError(900) << k_lineinfo << "Converstation with kdesu_stub failed\n"; return ret; } else if(ret == 1) { kill(m_Pid, SIGTERM); waitForChild(); ret = SshIncorrectPassword; } if(check == 1) { waitForChild(); return 0; } setExitString("Waiting for forwarded connections to terminate"); ret = waitForChild(); return ret; }
void BinaryDebugger::singleStep() { sendCommand(PTRACE_SINGLESTEP, child_, 0, (void*)sendSignal_); waitForChild(); }
int PasswdProcess::ConversePasswd(const char *oldpass, const char *newpass, int check) { QCString line, errline; int state = 0; while(state != 7) { line = readLine(); if(line.isNull()) { return -1; } if(state == 0 && isPrompt(line, "new")) // If root is changing a user's password, // passwd can't prompt for the original password. // Therefore, we have to start at state=2. state = 2; switch(state) { case 0: // Eat garbage, wait for prompt m_Error += line + "\n"; if(isPrompt(line, "password")) { WaitSlave(); write(m_Fd, oldpass, strlen(oldpass)); write(m_Fd, "\n", 1); state++; break; } if(m_bTerminal) fputs(line, stdout); break; case 1: case 3: case 6: // Wait for \n if(line.isEmpty()) { state++; break; } // error return -1; case 2: m_Error = ""; if(line.contains("again")) { m_Error = line; kill(m_Pid, SIGKILL); waitForChild(); return PasswordIncorrect; } // Wait for second prompt. errline = line; // use first line for error message while(!isPrompt(line, "new")) { line = readLine(); if(line.isNull()) { // We didn't get the new prompt so assume incorrect password. if(m_bTerminal) fputs(errline, stdout); m_Error = errline; return PasswordIncorrect; } } // we have the new prompt if(check) { kill(m_Pid, SIGKILL); waitForChild(); return 0; } WaitSlave(); write(m_Fd, newpass, strlen(newpass)); write(m_Fd, "\n", 1); state++; break; case 4: // Wait for third prompt if(isPrompt(line, "re")) { WaitSlave(); write(m_Fd, newpass, strlen(newpass)); write(m_Fd, "\n", 1); state += 2; break; } // Warning or error about the new password if(m_bTerminal) fputs(line, stdout); m_Error = line + "\n"; state++; break; case 5: // Wait for either a "Reenter password" or a "Enter password" prompt if(isPrompt(line, "re")) { WaitSlave(); write(m_Fd, newpass, strlen(newpass)); write(m_Fd, "\n", 1); state++; break; } else if(isPrompt(line, "password")) { kill(m_Pid, SIGKILL); waitForChild(); return PasswordNotGood; } if(m_bTerminal) fputs(line, stdout); m_Error += line + "\n"; break; } } // Are we ok or do we still get an error thrown at us? m_Error = ""; state = 0; while(state != 1) { line = readLine(); if(line.isNull()) { // No more input... OK return 0; } if(isPrompt(line, "password")) { // Uh oh, another prompt. Not good! kill(m_Pid, SIGKILL); waitForChild(); return PasswordNotGood; } m_Error += line + "\n"; // Collect error message } kdDebug(1512) << k_lineinfo << "Conversation ended successfully.\n"; return 0; }
int main(int argc, char **argv, char **envp) { /* Pager 1 = less, 2 = more */ char* pager = "less"; int i; /* Letar igenom miljövariablerna efter PAGER. Finns den, använd less om den finns, om den finns men inte innehåller less används more.*/ for(i = 0; envp[i] != NULL; i++) { if(strcmp_lim(envp[i], "PAGER", 5)) { if(!strcmp_lim(envp[i]+6,"less",4)) pager = "more"; } } /* Pipes */ int pipe_filedesc[3][2]; /* Skapa så många pipes som behövs, beror på om vi fick parametrar eller inte */ int child_count = (argc > 1)?4:3; for(i = 0; i< child_count-1; i++) { return_value = pipe(pipe_filedesc[i]); check_return_value_pipe(); } /* Håller koll på vilken pipe som skall användas. */ int current_pipe = 0; childpid = fork(); /* skapa första child-processen (för printenv) */ if(0 == childpid) { /* Bind om stdout till pipe. */ return_value = dup2( pipe_filedesc[current_pipe][ PIPE_WRITE_SIDE ], STDOUT_FILENO ); /* STDOUT_FILENO == 1 */ /* Kolla om allt gick bra */ check_return_value_pipe(); /* Stäng alla pipes */ close_pipes(child_count-1, pipe_filedesc); (void) execlp( "printenv", "printenv", (char *) 0 ); } current_pipe++; /* Skriv ut processens childpid */ fprintf(stderr, "printenv: %d\n",childpid ); /* Om vi har fått en parameterlista skall vi utföra grep här. */ if(argc > 1) { childpid = fork(); if( 0 == childpid ) { /* Bind om stdin till pipe. */ return_value = dup2( pipe_filedesc[current_pipe-1][ PIPE_READ_SIDE ], STDIN_FILENO ); /* STDIN_FILENO == 0 */ /* Kolla om allt gick bra */ check_return_value_pipe(); /* Bind om stdout till pipe. */ return_value = dup2( pipe_filedesc[current_pipe][ PIPE_WRITE_SIDE ], STDOUT_FILENO ); /* STDOUT_FILENO == 1 */ /* Kolla om allt gick bra */ check_return_value_pipe(); /* Stäng alla pipes */ close_pipes(child_count-1, pipe_filedesc); argv[0] = "grep"; execvp( "grep", argv); fprintf(stderr, "Error in grep\n"); } current_pipe++; /* Skriv ut processens childpid */ fprintf(stderr, "grep: %d\n",childpid ); } childpid = fork(); /* skapa andra child-processen (för sort) */ if (0 == childpid ) { /* Bind om stdin */ return_value = dup2( pipe_filedesc[current_pipe-1][ PIPE_READ_SIDE ], STDIN_FILENO ); /* STDIN_FILENO == 0 */ /* Kolla om allt gick bra */ check_return_value_pipe(); /* Bind om stdout */ return_value = dup2( pipe_filedesc[current_pipe][ PIPE_WRITE_SIDE ], STDOUT_FILENO ); /* STOUT_FILENO == 1 */ /* Kolla om allt gick bra */ check_return_value_pipe(); /* Stäng alla pipes */ close_pipes(child_count-1, pipe_filedesc); (void) execlp( "sort", "sort", (char *) 0 ); } /* Skriv ut processens childpid */ fprintf(stderr, "sort: %d\n",childpid ); current_pipe++; childpid = fork(); if( 0 == childpid ) { /* bind om stdin */ return_value = dup2( pipe_filedesc[current_pipe-1][ PIPE_READ_SIDE ], STDIN_FILENO ); /* STDIN_FILENO == 0 */ /* Kolla om allt gick bra */ check_return_value_pipe(); /* Stäng alla pipes */ close_pipes(child_count-1, pipe_filedesc); (void) execlp( pager, pager, (char *) 0 ); } /* Skriv ut processens childpid */ fprintf(stderr, "less: %d\n",childpid ); /* Stäng alla pipes */ close_pipes(child_count-1, pipe_filedesc); /* Vänta på alla barn */ for(i = 0; i<child_count; i++) { waitForChild(); } exit( 0 ); /* Avsluta parent-processen på normalt sätt */ }
int MprCmd::start(char *program, char **argv, char **envp, MprCmdProc completionFn, void *fnData, int userFlags) { PROCESS_INFORMATION procInfo; STARTUPINFO startInfo; char dirBuf[MPR_MAX_FNAME], *systemRoot; char *envBuf, **ep, *cmdBuf, **ap, *destp, *cp, *dir, *key; char progBuf[MPR_MAX_STRING], *localArgv[2], *saveArg0; int argc, len, inheritFiles; mprAssert(program); mprAssert(argv); reset(); flags |= (userFlags & MPR_CMD_USER_FLAGS); exitStatus = -1; mprStrcpy(progBuf, sizeof(progBuf), program); progBuf[sizeof(progBuf) - 1] = '\0'; program = progBuf; // // Sanitize the command line (program name only) // for (cp = program; *cp; cp++) { if (*cp == '/') { *cp = '\\'; } else if (*cp == '\r' || *cp == '\n') { *cp = ' '; } } if (*program == '"') { if ((cp = strrchr(++program, '"')) != 0) { *cp = '\0'; } } saveArg0 = argv[0]; if (argv == 0) { argv = localArgv; argv[1] = 0; } argv[0] = program; // // Determine the command line length and arg count // argc = 0; for (len = 0, ap = argv; *ap; ap++) { len += strlen(*ap) + 1 + 2; // Space and possible quotes argc++; } cmdBuf = (char*) mprMalloc(len + 1); cmdBuf[len] = '\0'; // // Add quotes to all args that have spaces in them including "program" // destp = cmdBuf; for (ap = &argv[0]; *ap; ) { cp = *ap; if ((strchr(cp, ' ') != 0) && cp[0] != '\"') { *destp++ = '\"'; strcpy(destp, cp); destp += strlen(cp); *destp++ = '\"'; } else { strcpy(destp, cp); destp += strlen(cp); } if (*++ap) { *destp++ = ' '; } } *destp = '\0'; mprAssert((int) strlen(destp) < (len - 1)); mprAssert(cmdBuf[len] == '\0'); argv[0] = saveArg0; envBuf = 0; if (envp) { for (len = 0, ep = envp; *ep; ep++) { len += strlen(*ep) + 1; } key = "SYSTEMROOT"; systemRoot = getenv(key); if (systemRoot) { len += strlen(key) + 1 + strlen(systemRoot) + 1; } envBuf = (char*) mprMalloc(len + 2); // Win requires two nulls destp = envBuf; for (ep = envp; *ep; ep++) { strcpy(destp, *ep); mprLog(6, log, "Set CGI variable: %s\n", destp); destp += strlen(*ep) + 1; } strcpy(destp, key); destp += strlen(key); *destp++ = '='; strcpy(destp, systemRoot); destp += strlen(systemRoot) + 1; *destp++ = '\0'; *destp++ = '\0'; // WIN requires two nulls } memset(&startInfo, 0, sizeof(startInfo)); startInfo.cb = sizeof(startInfo); startInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; if (flags & MPR_CMD_SHOW) { startInfo.wShowWindow = SW_SHOW; } else { startInfo.wShowWindow = SW_HIDE; } // // CMD_OUT is stdin for the client. CMD_IN is stdout for the client // if (files.clientFd[MPR_CMD_OUT] > 0) { startInfo.hStdInput = (HANDLE) _get_osfhandle(files.clientFd[MPR_CMD_OUT]); } if (files.clientFd[MPR_CMD_IN] > 0) { startInfo.hStdOutput = (HANDLE)_get_osfhandle(files.clientFd[MPR_CMD_IN]); } #if UNUSED if (files.clientFd[MPR_CMD_ERR] > 0) { startInfo.hStdError = (HANDLE) _get_osfhandle(files.clientFd[MPR_CMD_ERR]); } #endif #if UNUSED SECURITY_ATTRIBUTES secAtt; memset(&secAtt, 0, sizeof(secAtt)); secAtt.nLength = sizeof(SECURITY_ATTRIBUTES); secAtt.bInheritHandle = TRUE; #endif if (userFlags & MPR_CMD_CHDIR) { if (cwd) { dir = cwd; } else { mprGetDirName(dirBuf, sizeof(dirBuf), argv[0]); dir = dirBuf; } } else { dir = 0; } inheritFiles = (flags & MPR_CMD_STDIO_MADE) ? 1 : 0; flags &= ~(MPR_CMD_STDIO_MADE); mprLog(5, log, "Running: %s\n", cmdBuf); if (! CreateProcess(0, cmdBuf, 0, 0, inheritFiles, CREATE_NEW_CONSOLE, envBuf, dir, &startInfo, &procInfo)) { mprError(MPR_L, MPR_LOG, "Can't create process: %s, %d", cmdBuf, mprGetOsError()); return MPR_ERR_CANT_CREATE; } process = (int) procInfo.hProcess; // // Wait for the child to initialize // WaitForInputIdle((HANDLE) process, 1000); if (procInfo.hThread != 0) { CloseHandle(procInfo.hThread); } mprFree(cmdBuf); mprFree(envBuf); cmdDoneProc = completionFn; data = fnData; if (flags & MPR_CMD_DETACHED) { CloseHandle((HANDLE) process); process = 0; } else if (userFlags & MPR_CMD_WAIT) { waitForChild(INT_MAX); if (getExitCode() < 0) { return MPR_ERR_BAD_STATE; } return exitStatus; } else { mprGetMpr()->cmdService->startWatcher(); } return 0; }
int MprCmd::start(char *program, char **argv, char **envp, MprCmdProc fn, void *fnData, int userFlags) { char dir[MPR_MAX_FNAME]; int pid, i, err; mprAssert(program != 0); mprAssert(argv != 0); mprLog(4, log, "start: %s\n", program); reset(); flags |= (userFlags & MPR_CMD_USER_FLAGS); for (i = 0; argv[i]; i++) { mprLog(6, log, " arg[%d]: %s\n", i, argv[i]); } if (envp) { for (i = 0; envp[i]; i++) { mprLog(6, log, " envp[%d]: %s\n", i, envp[i]); } } if (access(program, X_OK) < 0) { mprLog(5, log, "start: can't access %s, errno %d\n", program, mprGetOsError()); return MPR_ERR_CANT_ACCESS; } data = fnData; cmdDoneProc = fn; reapIndex = -1; // // Create the child // pid = vfork(); if (pid < 0) { mprLog(0, log, "Can't fork a new process to run %s\n", program); return MPR_ERR_CANT_INITIALIZE; } else if (pid == 0) { // // Child // umask(022); if (flags & MPR_CMD_NEW_SESSION) { setsid(); } if (flags & MPR_CMD_CHDIR) { if (cwd) { chdir(cwd); } else { mprGetDirName(dir, sizeof(dir), program); chdir(dir); } } // // FUTURE -- could chroot as a security feature (perhaps cgi-bin) // if (files.clientFd[MPR_CMD_OUT] >= 0) { dup2(files.clientFd[MPR_CMD_OUT], 0); // Client stdin } else { close(0); } if (files.clientFd[MPR_CMD_IN] >= 0) { dup2(files.clientFd[MPR_CMD_IN], 1); // Client stdout dup2(files.clientFd[MPR_CMD_IN], 2); // Client stderr } else { close(1); close(2); } // // FUTURE -- need to get a better max file limit than this // for (i = 3; i < 128; i++) { close(i); } if (envp) { execve(program, argv, envp); } else { // // Do this rather than user execv to avoid errors in valgrind // char *env[2]; env[0] = "_appweb=1"; env[1] = 0; execve(program, argv, (char**) &env); } err = errno; getcwd(dir, sizeof(dir)); mprStaticPrintf("Can't exec %s, err %d, cwd %s\n", program, err, dir); mprAssert(0); exit(-(MPR_ERR_CANT_INITIALIZE)); } else { // // Close the client handles // for (i = 0; i < MPR_CMD_MAX_FD; i++) { if (files.clientFd[i] >= 0) { close(files.clientFd[i]); files.clientFd[i] = -1; } } data = fnData; cmdDoneProc = fn; process = (ulong) pid; if (flags & MPR_CMD_DETACHED) { process = 0; return 0; } else if (flags & MPR_CMD_WAIT) { waitForChild(INT_MAX); if (getExitCode() < 0) { return MPR_ERR_BAD_STATE; } return exitStatus; } else { mprGetMpr()->cmdService->startWatcher(); } } return 0; }
int MprCmd::start(char *program, char **argv, char **envp, MprCmdProc fn, void *fnData, int userFlags) { PROCESS_INFORMATION procInfo; STARTUPINFO startInfo; char dirBuf[MPR_MAX_FNAME]; char *envBuf, **ep, *cmdBuf, **ap, *destp, *cp, *dir; char progBuf[MPR_MAX_STRING], *localArgv[2], *saveArg0; int argc, i, len, inheritFiles; mprAssert(program); mprAssert(argv); flags &= ~(MPR_CMD_WAITED | MPR_CMD_RUNNING); flags |= (userFlags & MPR_CMD_USER_FLAGS); exitStatus = -1; mprStrcpy(progBuf, sizeof(progBuf), program); progBuf[sizeof(progBuf) - 1] = '\0'; program = progBuf; // // Sanitize the command line (program name only) // for (cp = program; *cp; cp++) { if (*cp == '/') { *cp = '\\'; } else if (*cp == '\r' || *cp == '\n') { *cp = ' '; } } if (*program == '"') { if ((cp = strrchr(++program, '"')) != 0) { *cp = '\0'; } } saveArg0 = argv[0]; if (argv == 0) { argv = localArgv; argv[1] = 0; } argv[0] = program; // // Determine the command line length and arg count // argc = 0; for (len = 0, ap = argv; *ap; ap++) { len += strlen(*ap) + 1 + 2; // Space and possible quotes argc++; } cmdBuf = (char*) mprMalloc(len + 1); cmdBuf[len] = '\0'; // // Add quotes to all args that have spaces in them including "program" // destp = cmdBuf; for (ap = &argv[0]; *ap; ) { cp = *ap; if ((strchr(cp, ' ') != 0) && cp[0] != '\"') { *destp++ = '\"'; strcpy(destp, cp); destp += strlen(cp); *destp++ = '\"'; } else { strcpy(destp, cp); destp += strlen(cp); } if (*++ap) { *destp++ = ' '; } } *destp = '\0'; mprAssert((int) strlen(destp) < (len - 1)); mprAssert(cmdBuf[len] == '\0'); argv[0] = saveArg0; envBuf = 0; if (envp) { for (len = 0, ep = envp; *ep; ep++) { len += strlen(*ep) + 1; } envBuf = (char*) mprMalloc(len + 2); // Win requires two nulls destp = envBuf; for (ep = envp; *ep; ep++) { strcpy(destp, *ep); mprLog(6, log, "Set CGI variable: %s\n", destp); destp += strlen(*ep) + 1; } *destp++ = '\0'; *destp++ = '\0'; // WIN requires two nulls } memset(&startInfo, 0, sizeof(startInfo)); startInfo.cb = sizeof(startInfo); startInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; if (flags & MPR_CMD_SHOW) { startInfo.wShowWindow = SW_SHOW; } else { startInfo.wShowWindow = SW_HIDE; } if (files.clientFd[MPR_CMD_IN] > 0) { startInfo.hStdInput = (HANDLE) _get_osfhandle(files.clientFd[MPR_CMD_IN]); } if (files.clientFd[MPR_CMD_OUT] > 0) { startInfo.hStdOutput = (HANDLE)_get_osfhandle(files.clientFd[MPR_CMD_OUT]); } if (files.clientFd[MPR_CMD_ERR] > 0) { startInfo.hStdError = (HANDLE) _get_osfhandle(files.clientFd[MPR_CMD_ERR]); } #if UNUSED SECURITY_ATTRIBUTES secAtt; memset(&secAtt, 0, sizeof(secAtt)); secAtt.nLength = sizeof(SECURITY_ATTRIBUTES); secAtt.bInheritHandle = TRUE; #endif if (userFlags & MPR_CMD_CHDIR) { if (cwd) { dir = cwd; } else { mprGetDirName(dirBuf, sizeof(dirBuf), argv[0]); dir = dirBuf; } } else { dir = 0; } inheritFiles = (flags & MPR_CMD_STDIO_MADE) ? 1 : 0; mprLog(5, log, "Running: %s\n", cmdBuf); if (! CreateProcess(0, cmdBuf, 0, 0, inheritFiles, CREATE_NEW_CONSOLE, envBuf, dir, &startInfo, &procInfo)) { mprError(MPR_L, MPR_LOG, "Can't create process: %s, %d", cmdBuf, mprGetOsError()); return MPR_ERR_CANT_CREATE; } handle = (long) procInfo.hProcess; pid = procInfo.dwProcessId; if (procInfo.hThread != 0) { CloseHandle(procInfo.hThread); } for (i = 0; i < MPR_CMD_MAX_FD; i++) { if (files.clientFd[i] >= 0) { close(files.clientFd[i]); files.clientFd[i] = -1; } } if (cmdBuf) { mprFree(cmdBuf); } if (envBuf) { mprFree(envBuf); } if (userFlags & MPR_CMD_WAIT) { waitForChild(INT_MAX); for (i = 0; i < MPR_CMD_MAX_FD; i++) { if (files.serverFd[i] >= 0) { close(files.serverFd[i]); files.serverFd[i] = -1; } } return exitStatus; } lock(); outputDataProc = fn; data = fnData; flags |= MPR_CMD_RUNNING; if (1 || ! mpr->getAsyncSelectMode()) { timer = new MprTimer(MPR_TIMEOUT_CMD_WAIT, singleThreadedOutputData, (void*) this); #if FUTURE // // Want non blocking reads if we are in single-threaded mode. // Can't use this yet as we are holding a Request lock and so blocking // in a read stops everything. Need proper Async I/O in windows. // if (mprGetMpr()->poolService->getMaxPoolThreads() == 0) { } else { task = new MprTask(multiThreadedOutputData, (void*) this); task->start(); } #endif } unlock(); return 0; }
static LRESULT CALLBACK mainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_ACTIVATE: if (LOWORD(wParam) != WA_INACTIVE) { // activated // see if the configuration changed if (isConfigNewer(s_configTime, s_userConfig)) { CString message2 = getString(IDS_CONFIG_CHANGED); if (askVerify(hwnd, message2)) { time_t configTime; bool userConfig; CConfig newConfig; if (loadConfig(newConfig, configTime, userConfig) && userConfig == s_userConfig) { ARG->m_config = newConfig; s_lastConfig = ARG->m_config; } else { message2 = getString(IDS_LOAD_FAILED); showError(hwnd, message2); s_lastConfig = CConfig(); } } } } else { // deactivated; write configuration if (!isShowingDialog()) { saveMainWindow(hwnd, SAVE_QUIET); } } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDCANCEL: // save data if (saveMainWindow(hwnd, SAVE_QUITING)) { // quit PostQuitMessage(0); } return 0; case IDOK: case IDC_MAIN_TEST: { // note if testing const bool testing = (LOWORD(wParam) == IDC_MAIN_TEST); // save data if (saveMainWindow(hwnd, SAVE_NORMAL)) { // launch child app DWORD threadID; HANDLE thread; if (!launchApp(hwnd, testing, &thread, &threadID)) { return 0; } // handle child program if (testing) { // wait for process to stop, allowing the user to kill it waitForChild(hwnd, thread, threadID); // clean up CloseHandle(thread); } else { // don't need thread handle if (thread != NULL) { CloseHandle(thread); } // notify of success: now disabled - it's silly to notify a success //askOkay(hwnd, getString(IDS_STARTED_TITLE), getString(IDS_STARTED)); // quit PostQuitMessage(0); } } return 0; } case IDC_MAIN_AUTOSTART: { CString cmdLine; if (saveMainWindow(hwnd, SAVE_NORMAL, &cmdLine)) { // run dialog CAutoStart autoStart(hwnd, !isClientChecked(hwnd), cmdLine); autoStart.doModal(); } return 0; } case IDC_MAIN_CLIENT_RADIO: case IDC_MAIN_SERVER_RADIO: enableMainWindowControls(hwnd); return 0; case IDC_MAIN_SCREENS: s_screensLinks->doModal(); break; case IDC_MAIN_OPTIONS: s_globalOptions->doModal(); break; case IDC_MAIN_ADVANCED: s_advancedOptions->doModal(isClientChecked(hwnd)); break; case IDC_MAIN_HOTKEYS: s_hotkeyOptions->doModal(); break; case IDC_MAIN_INFO: s_info->doModal(); break; } default: break; } return DefDlgProc(hwnd, message, wParam, lParam); }