/* Generated automatically by jlpp - do not edit. */ #include static jakelib::lang::String* jakelib2_strings[] = {null, null, null, null, null, null, null, null, null, null, null, null, null, null}; // "CreatePipe failed for stdin: " static jchar chars_jakelib2_str_0[] = {67,114,101,97,116,101,80,105,112,101,32,102,97,105,108,101,100,32,102,111,114,32,115,116,100,105,110,58,32}; // "CreatePipe failed for stderr: " static jchar chars_jakelib2_str_1[] = {67,114,101,97,116,101,80,105,112,101,32,102,97,105,108,101,100,32,102,111,114,32,115,116,100,101,114,114,58,32}; // "CreatePipe failed for stdout: " static jchar chars_jakelib2_str_2[] = {67,114,101,97,116,101,80,105,112,101,32,102,97,105,108,101,100,32,102,111,114,32,115,116,100,111,117,116,58,32}; // "DuplicateHandle failed: " static jchar chars_jakelib2_str_3[] = {68,117,112,108,105,99,97,116,101,72,97,110,100,108,101,32,102,97,105,108,101,100,58,32}; // ":" static jchar chars_jakelib2_str_4[] = {58}; // "Cannot create pipe" static jchar chars_jakelib2_str_5[] = {67,97,110,110,111,116,32,99,114,101,97,116,101,32,112,105,112,101}; // "Cannot create pipe" static jchar chars_jakelib2_str_6[] = {67,97,110,110,111,116,32,99,114,101,97,116,101,32,112,105,112,101}; // "Cannot create pipe" static jchar chars_jakelib2_str_7[] = {67,97,110,110,111,116,32,99,114,101,97,116,101,32,112,105,112,101}; // "Unable to fork new process" static jchar chars_jakelib2_str_8[] = {85,110,97,98,108,101,32,116,111,32,102,111,114,107,32,110,101,119,32,112,114,111,99,101,115,115}; // "Cannot determine exit code: #" static jchar chars_jakelib2_str_9[] = {67,97,110,110,111,116,32,100,101,116,101,114,109,105,110,101,32,101,120,105,116,32,99,111,100,101,58,32,35}; // "Subprocess has not yet terminated" static jchar chars_jakelib2_str_10[] = {83,117,98,112,114,111,99,101,115,115,32,104,97,115,32,110,111,116,32,121,101,116,32,116,101,114,109,105,110,97,116,101,100}; // "Subprocess has not yet terminated" static jchar chars_jakelib2_str_11[] = {83,117,98,112,114,111,99,101,115,115,32,104,97,115,32,110,111,116,32,121,101,116,32,116,101,114,109,105,110,97,116,101,100}; // "Process was stopped: #" static jchar chars_jakelib2_str_12[] = {80,114,111,99,101,115,115,32,119,97,115,32,115,116,111,112,112,101,100,58,32,35}; // "Process aborted abnormally: #" static jchar chars_jakelib2_str_13[] = {80,114,111,99,101,115,115,32,97,98,111,114,116,101,100,32,97,98,110,111,114,109,97,108,108,121,58,32,35}; #line 1 "lang/Process.jlc" // -*- c++ -*- /* * Jakelib2 - General purpose C++ library * Copyright (C) 2001 Florian Wolff (florian@donuz.de) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: Process.jlc,v 1.19 2006-02-18 11:56:47 florian Exp $ */ #include "jakelib2.h" #include "jakelib2/lang/Process.h" #include "jakelib2/lang/System.h" #include "jakelib2/io/PipeInputStream.h" #include "jakelib2/io/PipeOutputStream.h" #include using namespace jakelib::lang; using namespace jakelib::io; JAKELIB_IMPLEMENT_CLASS("jakelib.lang.Process", Process, Object) #ifdef HAVE_SCHED_H # include #endif #ifdef HAVE_ERRNO_H # include #endif #if defined(HAVE_STDARG_H) || defined(JAKELIB_WIN32API) # include #endif #ifdef HAVE_SYS_WAIT_H # include #endif #ifdef HAVE_SIGNAL_H # include #endif #include /*****************************************************************************\ * Process | *****************************************************************************/ Process::Process(String* cmdline, ...) { init1(); #if defined(JAKELIB_WIN32API) ZeroMemory(&procInfo, sizeof(PROCESS_INFORMATION)); SECURITY_ATTRIBUTES secAttr; secAttr.nLength = sizeof(SECURITY_ATTRIBUTES); secAttr.bInheritHandle = TRUE; secAttr.lpSecurityDescriptor = NULL; // Create pipes for stdin, stdout and stderr: HANDLE childInPipe, childOutPipe, childErrPipe; if (!CreatePipe(&inPipe, &childOutPipe, &secAttr, 0)) { throw new IOException(JAKELIB_ONDEMAND(jakelib2_strings[0], new jakelib::lang::String(chars_jakelib2_str_0, 0, 29)) ->plus( System::explainErrorCode(GetLastError()) )->plus( JAKELIB_AT2("jakelib.lang.Process.Process"))); } if (!CreatePipe(&errPipe, &childErrPipe, &secAttr, 0)) { throw new IOException(JAKELIB_ONDEMAND(jakelib2_strings[1], new jakelib::lang::String(chars_jakelib2_str_1, 0, 30)) ->plus( System::explainErrorCode(GetLastError()) )->plus( JAKELIB_AT2("jakelib.lang.Process.Process"))); } if (!CreatePipe(&childInPipe, &outPipe, &secAttr, 0)) { throw new IOException(JAKELIB_ONDEMAND(jakelib2_strings[2], new jakelib::lang::String(chars_jakelib2_str_2, 0, 30)) ->plus( System::explainErrorCode(GetLastError()) )->plus( JAKELIB_AT2("jakelib.lang.Process.Process"))); } // Duplicate write end of StdOut pipe : HANDLE dupHandle; if (!DuplicateHandle(GetCurrentProcess(), outPipe, GetCurrentProcess(), &dupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { throw new IOException(JAKELIB_ONDEMAND(jakelib2_strings[3], new jakelib::lang::String(chars_jakelib2_str_3, 0, 24)) ->plus( System::explainErrorCode(GetLastError()) )->plus( JAKELIB_AT2("jakelib.lang.Process.Process"))); } CloseHandle(outPipe); outPipe = dupHandle; // Build up one command line string: va_list ptr; va_start(ptr, cmdline); StringBuffer* args = new StringBuffer(); String* s; args->append(cmdline)->append(' '); while ((s = va_arg(ptr, String*)) != null) { args->append(s)->append(' '); } // Build up Startup-Info structure: STARTUPINFO startInfo; ZeroMemory(&startInfo, sizeof(STARTUPINFO)); startInfo.cb = sizeof(STARTUPINFO); startInfo.wShowWindow = SW_SHOW; startInfo.dwFlags = STARTF_USESTDHANDLES; startInfo.hStdInput = childInPipe; startInfo.hStdOutput = childOutPipe; startInfo.hStdError = childErrPipe; // Actually create the new process: if (!CreateProcess(NULL, args->toString()->latin1(), NULL, NULL, TRUE, 0, 0, 0, &startInfo, &procInfo)) { throw new IOException(System::explainErrorCode(GetLastError()) ->plus( JAKELIB_ONDEMAND(jakelib2_strings[4], new jakelib::lang::String(chars_jakelib2_str_4, 0, 1)) )->plus( System::eol )->plus( args )->plus( JAKELIB_AT2("jakelib.lang.Process.Process"))); } // Close children's end of all pipes: CloseHandle(childInPipe); CloseHandle(childOutPipe); CloseHandle(childErrPipe); #else int stdoutPipes[2], stdinPipes[2], stderrPipes[2]; pid_t pid; if (pipe(stdoutPipes) != 0) { throw new IOException(JAKELIB_ONDEMAND(jakelib2_strings[5], new jakelib::lang::String(chars_jakelib2_str_5, 0, 18)) ->plus( JAKELIB_AT2("jakelib.lang.Process.Process"))); } if (pipe(stdinPipes) != 0) { throw new IOException(JAKELIB_ONDEMAND(jakelib2_strings[6], new jakelib::lang::String(chars_jakelib2_str_6, 0, 18)) ->plus( JAKELIB_AT2("jakelib.lang.Process.Process"))); } if (pipe(stderrPipes) != 0) { throw new IOException(JAKELIB_ONDEMAND(jakelib2_strings[7], new jakelib::lang::String(chars_jakelib2_str_7, 0, 18)) ->plus( JAKELIB_AT2("jakelib.lang.Process.Process"))); } childPid = fork(); if (childPid < 0) { throw new IOException(JAKELIB_ONDEMAND(jakelib2_strings[8], new jakelib::lang::String(chars_jakelib2_str_8, 0, 26)) ->plus( JAKELIB_AT2("jakelib.lang.Process.Process"))); } if (childPid == 0) { // Child process: // Count the number of arguments given: va_list ptr; va_start(ptr, cmdline); String* s; int num = 0; while ((s = va_arg(ptr, String*)) != null) num++; // Put all arguments in an array - element 0 is the program name, last element is null: char** argv = (char**) malloc(sizeof(char*) * (num +2)); num = 0; va_start(ptr, cmdline); argv[num++] = JAKELIB_LATIN1((String*) cmdline); while ((s = va_arg(ptr, String*)) != null) argv[num++] = JAKELIB_LATIN1(s); argv[num] = null; dup2(stdoutPipes[1], fileno(stdout)); dup2(stderrPipes[1], fileno(stderr)); dup2(stdinPipes[0], fileno(stdin)); execvp(JAKELIB_LATIN1(cmdline), argv); int e = errno; fprintf(stderr, "Cannot exec: %s - %s", JAKELIB_LATIN1(cmdline), strerror(e)); exit(2); } else { // Parent process: inPipe = stdoutPipes[0]; outPipe = stdinPipes[1]; errPipe = stderrPipes[0]; close(stdinPipes[0]); close(stdoutPipes[1]); close(stderrPipes[1]); // FIXME: Throw Exception if execvp failed! } #endif } Process::~Process() { #if defined(JAKELIB_WIN32API) if (procInfo.hProcess != INVALID_HANDLE_VALUE) { CloseHandle(procInfo.hProcess); CloseHandle(procInfo.hThread); } #endif } /*****************************************************************************\ * init1 | *****************************************************************************/ void Process::init1() { inputStream = null; outputStream = null; errorStream = null; terminated = false; _exitValue = 255; } /*****************************************************************************\ * getInputStream | *****************************************************************************/ InputStream* Process::getInputStream() { if (inputStream == null) { inputStream = new PipeInputStream(inPipe); inputStream; } return inputStream; } /*****************************************************************************\ * getErrorStream | *****************************************************************************/ InputStream* Process::getErrorStream() { if (errorStream == null) { errorStream = new PipeInputStream(errPipe); errorStream; } return errorStream; } /*****************************************************************************\ * getOutputStream | *****************************************************************************/ jakelib::io::OutputStream* Process::getOutputStream() { if (outputStream == null) { outputStream = new PipeOutputStream(outPipe); outputStream; } return outputStream; } /*****************************************************************************\ * destroy | *****************************************************************************/ void Process::destroy() { #if defined(JAKELIB_WIN32API) TerminateProcess(procInfo.hProcess, -1); CloseHandle(procInfo.hProcess); CloseHandle(procInfo.hThread); procInfo.hProcess = INVALID_HANDLE_VALUE; procInfo.hThread = INVALID_HANDLE_VALUE; #else kill(childPid, SIGKILL); #endif } /*****************************************************************************\ * waitFor | *****************************************************************************/ void Process::waitFor() { #if defined(JAKELIB_WIN32API) WaitForSingleObject(procInfo.hProcess, INFINITE); #else // FIXME: error handling waitpid(childPid, &_exitValue, 0); terminated = true; #endif } /*****************************************************************************\ * exitValue | *****************************************************************************/ int Process::exitValue() { if (terminated) { return _exitValue; } #if defined(JAKELIB_WIN32API) if (!GetExitCodeProcess(procInfo.hProcess, &_exitValue)) { throw new IOException(JAKELIB_ONDEMAND(jakelib2_strings[9], new jakelib::lang::String(chars_jakelib2_str_9, 0, 29)) ->plus( (jlong) GetLastError() )->plus( JAKELIB_AT2("jakelib.lang.Process.exitValue"))); } if (_exitValue == STILL_ACTIVE) { throw new IllegalThreadStateException(JAKELIB_ONDEMAND(jakelib2_strings[10], new jakelib::lang::String(chars_jakelib2_str_10, 0, 33)) ->plus( JAKELIB_AT2("jakelib.lang.Process.exitValue"))); } #else if (waitpid(childPid, &_exitValue, WNOHANG) <= 0) { throw new IllegalThreadStateException(JAKELIB_ONDEMAND(jakelib2_strings[11], new jakelib::lang::String(chars_jakelib2_str_11, 0, 33)) ->plus( JAKELIB_AT2("jakelib.lang.Process.exitValue"))); if (WIFEXITED(_exitValue)) { _exitValue = WEXITSTATUS(_exitValue); } else if (WIFSTOPPED(_exitValue)) { throw new IOException(JAKELIB_ONDEMAND(jakelib2_strings[12], new jakelib::lang::String(chars_jakelib2_str_12, 0, 22)) ->plus( _exitValue )->plus( JAKELIB_AT2("jakelib.lang.Process.exitValue"))); } else { throw new IOException(JAKELIB_ONDEMAND(jakelib2_strings[13], new jakelib::lang::String(chars_jakelib2_str_13, 0, 29)) ->plus( _exitValue )->plus( JAKELIB_AT2("jakelib.lang.Process.exitValue"))); } _exitValue = _exitValue & 0xff; } #endif terminated = true; return _exitValue; }