imore.cpp

来自「ace开发环境 用来开发网络程序 其运用了设计模式、多平台、C++等多种知识」· C++ 代码 · 共 267 行

CPP
267
字号
// ============================================================================// $Id: imore.cpp 78918 2007-07-17 04:06:30Z sowayaa $//// = LIBRARY//    examples//// = FILENAME//    imore.cpp (imore stands for indirect more.)//// = DESCRIPTION//    This program demonstrates how to redirect stdout of a parent//    process to the stdin of its child process using either unnamed pipe//    or named pipes to relay data to subprocess which runs "more" to//    display data on the screen.  Run imore to see how to use this//    program.////    Unfortunately, on Win32, this program doesn't use any pipe at all because//    using pipes confuses MORE.COM on Win32 and it just acts like "cat" on Unix.//// = AUTHOR//    Nanbor Wang <nanbor@cs.wustl.edu>//// ============================================================================#include "ace/OS_NS_stdio.h"#include "ace/OS_NS_errno.h"#include "ace/OS_NS_unistd.h"#include "ace/OS_NS_fcntl.h"#include "ace/FIFO_Recv.h"#include "ace/FIFO_Send.h"#include "ace/Pipe.h"#include "ace/Get_Opt.h"#include "ace/Log_Msg.h"#include "ace/Process.h"#include "ace/Signal.h"ACE_RCSID(Process, imore, "$Id: imore.cpp 78918 2007-07-17 04:06:30Z sowayaa $")#if defined (ACE_WIN32)static const ACE_TCHAR *executable = ACE_TEXT("MORE.COM");static const ACE_TCHAR *rendezvous_dir = ACE_TEXT("c:/temp");static const ACE_TCHAR *rendezvous_pfx = ACE_TEXT("imore");#elsestatic const char * executable = "more"; // I like less better.static const ACE_TCHAR *rendezvous_dir = ACE_TEXT("/tmp");static const ACE_TCHAR *rendezvous_pfx = ACE_TEXT("imore");#endif /* ACE_WIN32 */static ACE_TCHAR *fname = 0;   // File you want to view.static int use_named_pipe = 0;	// Do we want to use named pipe?static voidusage (void){  ACE_ERROR ((LM_ERROR, "Usage: imore [-n|-u] <filename>\n"	      "\t-n Use named pipe.\n"	      "\t-u Use unnamed pipe.\n"));}static intparse_args (int argc, ACE_TCHAR **argv){  ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("un"));  int c;  while ((c = get_opt ()) != -1)    {    switch (c)      {      case 'n':			// We want to use named pipe.#if !defined (ACE_WIN32)	use_named_pipe = 1;#else	ACE_ERROR_RETURN ((LM_ERROR, "Named pipes not supported on Win32\n"), -1);#endif /* !ACE_WIN32 */	break;      case 'u':			// Use unnamed pipe.	use_named_pipe = 0;	break;      default:			// What are you talking about?	usage ();	return -1;      }    }  if (get_opt.opt_ind () >= argc)	// Do you forget to give me a filename to "more?"    {      usage ();      return -1;    }  else    fname = argv[get_opt.opt_ind ()]; // Alright.  return 0;}static intsetup_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;}static intsetup_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;}static intprint_file (ACE_HANDLE infd){  char buffer[BUFSIZ];  ssize_t len;  while ((len = ACE_OS::read (infd, buffer, BUFSIZ)) > 0)    {      if ((ACE_OS::write (ACE_STDOUT, buffer, len) != len))	if (errno == EPIPE)	  {	    // I tried to "produce" EPIPE warning to test	    // the program but never seen one.  (odd.)	    // ACE_ERROR ((LM_ERROR, "\n\nEPIPE\n"));	    break;	  }	else	  ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "write"), -1);    }  return 0;}intACE_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 error = ACE_OS::last_error ();      ACE_ERROR_RETURN ((LM_ERROR, "%p errno = %d.\n",                         "test_more", error), -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;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?