HeeksObj* CreatePipeFromProfile(const TopoDS_Wire &spine, std::list<TopoDS_Shape> &faces) { std::list<HeeksObj*> pipe_shapes; for(std::list<TopoDS_Shape>::iterator It2 = faces.begin(); It2 != faces.end(); It2++) { TopoDS_Shape& face = *It2; try { // pipe profile algong spine BRepOffsetAPI_MakePipe makePipe(spine, face); makePipe.Build(); TopoDS_Shape shape = makePipe.Shape(); HeeksObj* new_object = CShape::MakeObject(shape, _("Pipe"), SOLID_TYPE_UNKNOWN, wxGetApp().current_color, 1.0f); if(new_object)pipe_shapes.push_back(new_object); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); wxMessageBox(wxString(_("Error making pipe")) + _T(": ") + Ctt(e->GetMessageString())); } } if(pipe_shapes.size() > 0) { wxGetApp().StartHistory(); for(std::list<HeeksObj*>::iterator It = pipe_shapes.begin(); It != pipe_shapes.end(); It++) { HeeksObj* object = *It; wxGetApp().AddUndoably(object, NULL, NULL); } wxGetApp().EndHistory(); return pipe_shapes.front(); } return NULL; }
extern "C" JNIEXPORT void JNICALL Java_java_lang_Runtime_exec(JNIEnv* e, jclass, jobjectArray command, jlongArray process) { #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) int size = 0; for (int i = 0; i < e->GetArrayLength(command); ++i) { jstring element = (jstring)e->GetObjectArrayElement(command, i); if (element) { // worst case, assuming every character is '"', and we escape all of them size += 2 * e->GetStringUTFLength(element) + 3; } else { throwNew(e, "java/lang/NullPointerException", strdup("null string array element")); } } RUNTIME_ARRAY(char, line, size); char* linep = RUNTIME_ARRAY_BODY(line); for (int i = 0; i < e->GetArrayLength(command); ++i) { if (i) *(linep++) = _T(' '); jstring element = (jstring)e->GetObjectArrayElement(command, i); const char* s = e->GetStringUTFChars(element, 0); copyAndEscape(&linep, s, e->GetStringUTFLength(element)); e->ReleaseStringUTFChars(element, s); } *(linep++) = _T('\0'); HANDLE in[] = {0, 0}; HANDLE out[] = {0, 0}; HANDLE err[] = {0, 0}; makePipe(e, in); SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0); jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0])); if (e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 2, 1, &inDescriptor); makePipe(e, out); SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0); jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1])); if (e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 3, 1, &outDescriptor); makePipe(e, err); SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0); jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0])); if (e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 4, 1, &errDescriptor); PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdOutput = in[1]; si.hStdInput = out[0]; si.hStdError = err[1]; BOOL success = CreateProcess(0, (LPSTR)RUNTIME_ARRAY_BODY(line), 0, 0, 1, CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, 0, 0, &si, &pi); CloseHandle(in[1]); CloseHandle(out[0]); CloseHandle(err[1]); if (not success) { throwNew(e, "java/io/IOException", getErrorStr(GetLastError())); return; } jlong pid = reinterpret_cast<jlong>(pi.hProcess); e->SetLongArrayRegion(process, 0, 1, &pid); jlong tid = reinterpret_cast<jlong>(pi.hThread); e->SetLongArrayRegion(process, 1, 1, &tid); #else throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); #endif }
/** Initialize a plugin to be executed in its own process * * This will prepare all the required resources and then fork the current * process. After the initialization the child process will typically * call the command loop while the parent starts to send commands to it. * Also the resulting process information has to be stored for the plugin. * In order to allow users to handle custom plugin data this will not * automatically call elektraPluginSetData. * * Typically called in a plugin's open function like (assuming no custom plugin data): * @code int elektraPluginOpen (Plugin * handle, Key * errorKey) { ElektraPluginProcess * pp = elektraPluginGetData (handle); if (pp == NULL) { if ((pp = elektraPluginProcessInit (errorKey)) == NULL) return ELEKTRA_PLUGIN_STATUS_ERROR; elektraPluginSetData (handle, pp); if (!elektraPluginProcessIsParent (pp)) elektraPluginProcessStart (handle, pp); } if (elektraPluginProcessIsParent (pp)) return elektraPluginProcessOpen (pp, errorKey); // actual plugin functionality to be executed in a child process return ELEKTRA_PLUGIN_STATUS_SUCCESS; } * @endcode * * @param handle the plugin's handle * @param errorKey a key where error messages will be set * @retval NULL if the initialization failed * @retval a pointer to the information * @ingroup processplugin **/ ElektraPluginProcess * elektraPluginProcessInit (Key * errorKey) { // First time initialization ElektraPluginProcess * pp; pp = elektraMalloc (sizeof (ElektraPluginProcess)); pp->counter = 0; pp->pluginData = NULL; pp->parentCommandPipeKey = NULL; pp->parentPayloadPipeKey = NULL; pp->childCommandPipeKey = NULL; pp->childPayloadPipeKey = NULL; pp->dump = elektraInvokeOpen ("dump", 0, errorKey); if (!pp->dump) { cleanupPluginData (pp, errorKey, 0); ELEKTRA_SET_ERROR (190, errorKey, "Failed to initialize the dump plugin"); return NULL; } // As generally recommended, ignore SIGPIPE because we will notice that the // commandKeySet has been transferred incorrectly anyway to detect broken pipes signal (SIGPIPE, SIG_IGN); // Prepare the pipes if (!makePipe (pp, errorKey, "parentCommandPipe", pp->parentCommandPipe) || !makePipe (pp, errorKey, "parentPayloadPipe", pp->parentPayloadPipe) || !makePipe (pp, errorKey, "childCommandPipe", pp->childCommandPipe) || !makePipe (pp, errorKey, "childPayloadPipe", pp->childPayloadPipe)) return NULL; pp->pid = fork (); if (pp->pid < 0) { cleanupPluginData (pp, errorKey, 1); ELEKTRA_SET_ERRORF (190, errorKey, "Failed to fork the plugin process, fork () returned %d", pp->pid); return NULL; } int pipeIdx = elektraPluginProcessIsParent (pp); close (pp->parentCommandPipe[!pipeIdx]); close (pp->parentPayloadPipe[!pipeIdx]); close (pp->childCommandPipe[pipeIdx]); close (pp->childPayloadPipe[pipeIdx]); ELEKTRA_LOG_DEBUG ("parentCommandPipe[%d] has file descriptor %d", pipeIdx, pp->parentCommandPipe[pipeIdx]); ELEKTRA_LOG_DEBUG ("parentPayloadPipe[%d] has file descriptor %d", pipeIdx, pp->parentPayloadPipe[pipeIdx]); ELEKTRA_LOG_DEBUG ("childCommandPipe[%d] has file descriptor %d", !pipeIdx, pp->childCommandPipe[!pipeIdx]); ELEKTRA_LOG_DEBUG ("childPayloadPipe[%d] has file descriptor %d", !pipeIdx, pp->childPayloadPipe[!pipeIdx]); // Prepare the keys for the pipes to use with dump pp->parentCommandPipeKey = makePipeKey ("parentCommandPipe", pp->parentCommandPipe[pipeIdx]); pp->parentPayloadPipeKey = makePipeKey ("parentPayloadPipe", pp->parentPayloadPipe[pipeIdx]); pp->childCommandPipeKey = makePipeKey ("childCommandPipe", pp->childCommandPipe[!pipeIdx]); pp->childPayloadPipeKey = makePipeKey ("childPayloadPipe", pp->childPayloadPipe[!pipeIdx]); ELEKTRA_LOG_DEBUG ("parentCommandPipeKey is %s on %d", keyString (pp->parentCommandPipeKey), pp->pid); ELEKTRA_LOG_DEBUG ("parentPayloadPipeKey is %s on %d", keyString (pp->parentPayloadPipeKey), pp->pid); ELEKTRA_LOG_DEBUG ("childCommandPipeKey is %s on %d", keyString (pp->childCommandPipeKey), pp->pid); ELEKTRA_LOG_DEBUG ("childPayloadPipeKey is %s on %d", keyString (pp->childPayloadPipeKey), pp->pid); ELEKTRA_LOG_DEBUG ("The pluginprocess is set with the pid %d", pp->pid); return pp; }
extern "C" JNIEXPORT void JNICALL Java_java_lang_Runtime_exec(JNIEnv* e, jclass, jobjectArray command, jlongArray process) { char** argv = static_cast<char**> (malloc((e->GetArrayLength(command) + 1) * sizeof(char*))); int i; for(i = 0; i < e->GetArrayLength(command); i++){ jstring element = (jstring) e->GetObjectArrayElement(command, i); char* s = const_cast<char*>(e->GetStringUTFChars(element, 0)); argv[i] = s; } argv[i] = 0; int in[] = { -1, -1 }; int out[] = { -1, -1 }; int err[] = { -1, -1 }; int msg[] = { -1, -1 }; makePipe(e, in); if(e->ExceptionCheck()) return; jlong inDescriptor = static_cast<jlong>(in[0]); e->SetLongArrayRegion(process, 2, 1, &inDescriptor); makePipe(e, out); if(e->ExceptionCheck()) return; jlong outDescriptor = static_cast<jlong>(out[1]); e->SetLongArrayRegion(process, 3, 1, &outDescriptor); makePipe(e, err); if(e->ExceptionCheck()) return; jlong errDescriptor = static_cast<jlong>(err[0]); e->SetLongArrayRegion(process, 4, 1, &errDescriptor); makePipe(e, msg); if(e->ExceptionCheck()) return; if(fcntl(msg[1], F_SETFD, FD_CLOEXEC) != 0) { throwNewErrno(e, "java/io/IOException"); return; } #ifdef __QNX__ // fork(2) doesn't work in multithreaded QNX programs. See // http://www.qnx.com/developers/docs/6.4.1/neutrino/getting_started/s1_procs.html pid_t pid = vfork(); #else // We might be able to just use vfork on all UNIX-style systems, but // the manual makes it sound dangerous due to the shared // parent/child address space, so we use fork if we can. pid_t pid = fork(); #endif switch(pid){ case -1: // error throwNewErrno(e, "java/io/IOException"); return; case 0: { // child // Setup stdin, stdout and stderr dup2(in[1], 1); close(in); dup2(out[0], 0); close(out); dup2(err[1], 2); close(err); close(msg[0]); execvp(argv[0], argv); // Error if here int val = errno; ssize_t rv UNUSED = write(msg[1], &val, sizeof(val)); exit(127); } break; default: { //parent jlong JNIPid = static_cast<jlong>(pid); e->SetLongArrayRegion(process, 0, 1, &JNIPid); safeClose(in[1]); safeClose(out[0]); safeClose(err[1]); safeClose(msg[1]); int val; int r = read(msg[0], &val, sizeof(val)); if(r == -1) { throwNewErrno(e, "java/io/IOException"); return; } else if(r) { errno = val; throwNewErrno(e, "java/io/IOException"); return; } } break; } safeClose(msg[0]); clean(e, command, argv); fcntl(in[0], F_SETFD, FD_CLOEXEC); fcntl(out[1], F_SETFD, FD_CLOEXEC); fcntl(err[0], F_SETFD, FD_CLOEXEC); }
extern "C" JNIEXPORT void JNICALL Java_java_lang_Runtime_exec(JNIEnv* e, jclass, jobjectArray command, jlongArray process) { int size = 0; for (int i = 0; i < e->GetArrayLength(command); ++i){ jstring element = (jstring) e->GetObjectArrayElement(command, i); size += e->GetStringUTFLength(element) + 1; } RUNTIME_ARRAY(char, line, size); char* linep = RUNTIME_ARRAY_BODY(line); for (int i = 0; i < e->GetArrayLength(command); ++i) { if (i) *(linep++) = _T(' '); jstring element = (jstring) e->GetObjectArrayElement(command, i); const char* s = e->GetStringUTFChars(element, 0); #ifdef _MSC_VER _tcscpy_s(linep, size - (linep - RUNTIME_ARRAY_BODY(line)), s); #else _tcscpy(linep, s); #endif e->ReleaseStringUTFChars(element, s); linep += e->GetStringUTFLength(element); } *(linep++) = _T('\0'); HANDLE in[] = { 0, 0 }; HANDLE out[] = { 0, 0 }; HANDLE err[] = { 0, 0 }; makePipe(e, in); SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0); jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0])); if(e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 2, 1, &inDescriptor); makePipe(e, out); SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0); jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1])); if(e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 3, 1, &outDescriptor); makePipe(e, err); SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0); jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0])); if(e->ExceptionCheck()) return; e->SetLongArrayRegion(process, 4, 1, &errDescriptor); PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdOutput = in[1]; si.hStdInput = out[0]; si.hStdError = err[1]; BOOL success = CreateProcess(0, (LPSTR) RUNTIME_ARRAY_BODY(line), 0, 0, 1, CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, 0, 0, &si, &pi); CloseHandle(in[1]); CloseHandle(out[0]); CloseHandle(err[1]); if (not success) { throwNew(e, "java/io/IOException", getErrorStr(GetLastError())); return; } jlong pid = reinterpret_cast<jlong>(pi.hProcess); e->SetLongArrayRegion(process, 0, 1, &pid); jlong tid = reinterpret_cast<jlong>(pi.hThread); e->SetLongArrayRegion(process, 1, 1, &tid); }
// ------------------ primary function ------------------ int popen_pipes(int *parentWritesChild, int *parentReadsChild, int *readChildStderr, execFunction func, void *extraArgs) { int childReadsParent; int childWritesParent; int childWritesStderr; int childPid; int stderrToStdout = 0; // create pipes makePipe(&childReadsParent, parentWritesChild); makePipe(parentReadsChild, &childWritesParent); if (parentReadsChild == readChildStderr) { // caller wants child stdout and stderr going to same place stderrToStdout = 1; *readChildStderr = *parentReadsChild; readChildStderr = NULL; // most of the code behaves as if stderr isn't being changed } else if (readChildStderr) { makePipe(readChildStderr, &childWritesStderr); } // fork a child childPid = fork(); if (childPid < 0) { die("fork"); } if (childPid != 0) { // parent // close the pipe ends I'm not going to use if (close(childReadsParent) < -1 || close(childWritesParent) < -1 || (readChildStderr && close(childWritesStderr) < -1)) { die("close"); } return childPid; } else { // child // rearrange file descriptors so stdin and stdout of the // program we're about to exec will talk to parent // sleep so debugger can attach //sleep(10); // close the pipe ends I'm not going to use if (close(*parentReadsChild) < -1 || close(*parentWritesChild) < -1 || (readChildStderr && close(*readChildStderr) < -1)) { die("close"); } // first, close parent's stdin/stdout if (close(STDIN) < -1 || close(STDOUT) < -1 || (readChildStderr && close(STDERR) < -1)) { die("close"); } // now, duplicate the pipe fds to stdin/stdout if (dup2(childReadsParent, STDIN) < -1 || dup2(childWritesParent, STDOUT) < -1 || (readChildStderr && dup2(childWritesStderr, STDERR) < -1) || (stderrToStdout && dup2(childWritesParent, STDERR) < -1) ) { die("dup2"); } // finally, close the original pipe fds if (close(childReadsParent) < -1 || close(childWritesParent) < -1 || (readChildStderr && close(childWritesStderr) < -1)) { die("close"); } // ok, fds are in order. let's exec the child program func(extraArgs); // not reached; silence warning return -1; } }