static int setup_unnamed_pipe (ACE_Process_Options &opt) { // Create an unnamed pipe instance. ACE_Pipe pipe; // Check if the pipe is created successfully. if (pipe.open () == -1) ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "pipe.open"), -1); // Setting up pipe between parent and child process. Use the pipe // as child process'es ACE_STDIN. ACE_Process_Options will keep // copies (by dup) of fd's that we pass in. Notice that we have to // specify child process to use ACE_STDOUT for output explicitly // because we'll close it down in the line after. Child process // will use whatever we use to dup2 ACE_STDOUT as its stdout. opt.set_handles (pipe.read_handle (), ACE_STDOUT); // The previous keep a copy of original ACE_STDOUT fd, now we // can replace ACE_STDOUT of parent process to the pipe. ACE_OS::dup2 (pipe.write_handle (), ACE_STDOUT); // Don't forget to close the unused fd. pipe.close (); return 0; }
// This shows how to set handles. static void test_more (void) { ACE_HANDLE infile = ACE_OS::open (print_file, O_RDONLY); if (infile == ACE_INVALID_HANDLE) { ACE_ERROR ((LM_DEBUG, ACE_TEXT ("%p\n"), print_file)); return; } ACE_Process new_process; ACE_Process_Options options; options.command_line (executable); options.set_handles (infile); if (new_process.spawn (options) == -1) { int const error_number = ACE_OS::last_error (); ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p errno = %d.\n"), ACE_TEXT ("test_more"), error_number)); } ACE_exitcode status; new_process.wait (&status); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Process exit with status %d\n"), status)); ACE_OS::close (infile); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("More succeeded.\n"))); }
int setStdHandles (ACE_Process_Options &options) { ACE_TRACE ("Manager::setStdHandles"); ACE_OS::unlink ("output.dat"); this->outputfd_ = ACE_OS::open ("output.dat", O_RDWR | O_CREAT); return options.set_handles (ACE_STDIN, ACE_STDOUT, this->outputfd_); }
static int setup_named_pipes (ACE_Process_Options &opt) { // Create a unique temporary name for named pipe. ACE_TCHAR *rendezvous = ACE_OS::tempnam (rendezvous_dir, rendezvous_pfx); // Out of memory? if (rendezvous == 0) return -1; // Alright, this is indeed strange. Named pipes are meant to be // used for unrelated processes. Because of the constraints in // ACE_Process, I have to pre-open the named pipes here. ACE_FIFO_Recv rfifo; // read end fifo. ACE_FIFO_Send wfifo; // write end fifo. // Check if the pipes are created successfully. if (rfifo.open (rendezvous) == -1 || wfifo.open (rendezvous) == -1) { ACE_OS::free (rendezvous); ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "fifo.open"), -1); } // Remove (rm, del) the file after no one uses it any more. ACE_OS::unlink (rendezvous); ACE_OS::free (rendezvous); // Setting up pipe between parent and child process. Use the read // end of the named pipe as child process'es ACE_STDIN. // ACE_Process_Options will keep copies (by dup) of fd's that we // pass in. Notice that we have to specify child process to use // ACE_STDOUT for output explicitly because we'll close it down in // the line after. Child process will use whatever we use to dup2 // ACE_STDOUT as its stdout. opt.set_handles (rfifo.get_handle (), ACE_STDOUT); // The previous keep a copy of original ACE_STDOUT fd, now we // can replace ACE_STDOUT of parent process to the write end // of the named pipe. ACE_OS::dup2 (wfifo.get_handle (), ACE_STDOUT); // Close unused fd's. Notice ACE_FIFO doesn't close the fd // when it goes out of scope. rfifo.close (); wfifo.close (); return 0; }
int Handle_Events::serve (char *buf) { ACE_ARGV arguments (buf); if (ACE_OS::strcmp (arguments[0], TESTER) == 0) { ACE_Process_Options po; ACE_Process p; po.set_handles (ACE_INVALID_HANDLE, OUTPUT_FILE, OUTPUT_FILE); po.command_line (arguments.argv ()); p.spawn (po); return 0; } else return -1; }
int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) { // Ignore SIGPIPE signal on Unix platforms in case // child process (more) terminates before we finish // writing to stdout. #if !defined (ACE_WIN32) ACE_Sig_Action sig_act (SIG_IGN); if (sig_act.register_action (SIGPIPE) == -1) ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Sig_Action::register_action"), -1); #endif /* ACE_WIN32 */ // Alright, what you want me to do now? if (::parse_args (argc, argv) == -1) return -1; // Can I find the file you want? ACE_HANDLE infile = ACE_OS::open (fname, O_RDONLY); if (infile == ACE_INVALID_HANDLE) ACE_ERROR_RETURN ((LM_DEBUG, "%p\n", fname), -1); ACE_Process new_process; // The ACE_Process_Options does not need to be enclosed in a block // because it does not close the file handles, the ACE_Process closes // them upon destruction. #if !defined (ACE_WIN32) ACE_Process_Options options; if ((use_named_pipe ? ::setup_named_pipes : ::setup_unnamed_pipe) (options) == -1) ACE_ERROR_RETURN ((LM_ERROR, "Error, bailing out!\n"), -1); options.command_line (executable); if (new_process.spawn (options) == -1) { int const error_number = ACE_OS::last_error (); ACE_ERROR_RETURN ((LM_ERROR, "%p errno = %d.\n", "test_more", error_number), -1); } // write file to ACE_STDOUT. if (::print_file (infile) == -1) ACE_ERROR_RETURN ((LM_ERROR, "Error, bailing out!\n"), -1); // Close the STDOUT to inform child eof. ACE_OS::close (ACE_STDOUT); #else // We can only pass a file handler directly to child process // otherwise "more" doesn't act quite the way we want. Nonetheless, // if your child process don't need to interact with the terminal, // we can use the exact code for Unixes on NT. ACE_Process_Options options; options.command_line (executable); options.set_handles (infile); if (new_process.spawn (options) == -1) { int error = ACE_OS::last_error (); ACE_ERROR_RETURN ((LM_ERROR, "%p errno = %d.\n", "test_more", error), -1); } #endif /* ! ACE_WIN32 */ // Wait till we are done. ACE_exitcode status; new_process.wait (&status); ACE_DEBUG ((LM_DEBUG, "Process exit with status %d\n", status)); ACE_OS::close (infile); return 0; }
void SO_Group::add_executable (const char * path) { ACE_Process proc; ACE_Process_Options opts; ACE_HANDLE pipe[2]; ACE_Pipe io(pipe); opts.set_handles (ACE_STDIN,pipe[1]); int result = opts.command_line ("ldd %s",path); // Prevent compiler warning about "unused variable" if ACE_ASSERT is // an empty macro. ACE_UNUSED_ARG (result); ACE_ASSERT (result == 0); proc.spawn (opts); if (ACE_OS::close(pipe[1]) == -1) ACE_DEBUG ((LM_DEBUG, "%p\n", "close")); opts.release_handles(); const int max_line_length = 1000; char line[max_line_length]; while (1) { ACE_OS::memset (line,0,max_line_length); int len = 0; int nread = 0; int bogus = 0; // skip initial whitespace while ((nread = ACE_OS::read(pipe[0],line,1)) == 1 && (*line == ' ' || *line == '\t')); if (nread != 1) break; // read the library name len = 1; while ((nread = ACE_OS::read(pipe[0],line + len,1)) == 1 && (line[len] != ' ')) if (! bogus && ++len == max_line_length) { bogus = 1; break; } if (nread != 1 || bogus) break; line[len] = 0; char * dot = ACE_OS::strchr (line,'.'); if (dot) *dot = 0; char * libname = line + 3; // skip over "lib" // check to see if this is a new library int found = 0; for (int i = 0; !found && i < num_libs_; i++) found = (libs_[i]->name() == libname); if (!found) { Library *nlib = new Library(libname); ACE_OS::memset (line,0,max_line_length); // skip over '=> ' if (ACE_OS::read(pipe[0],line,3) != 3) break; // get library path len = 0; while ((nread = ACE_OS::read(pipe[0],line + len,1)) == 1 && (line[len] != ' ')) if (! bogus && ++len == max_line_length) { bogus = 1; break; } if (nread != 1 || bogus) break; line[len] = 0; nlib->set_path (line); libs_[num_libs_++] = nlib; ACE_ASSERT (num_libs_ < max_libs_); // grow max libs? } // skip the rest of the line while ((nread = ACE_OS::read(pipe[0],line,1)) == 1 && *line != '\n'); if (nread != 1) break; } proc.wait (); ACE_OS::close (pipe[0]); undef_wrapper_.add_source(path,1); // now do the ldd, iterate over the results to add new libs, etc. }