home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / xampp / xampp-perl-addon-1.4.9-installer.exe / Run.pm < prev    next >
Encoding:
Perl POD Document  |  2004-01-29  |  46.8 KB  |  1,486 lines

  1. # $Id: Run.pm,v 1.58 2004/01/28 23:19:13 rcaputo Exp $
  2.  
  3. package POE::Wheel::Run;
  4.  
  5. use strict;
  6.  
  7. use vars qw($VERSION);
  8. $VERSION = do {my@r=(q$Revision: 1.58 $=~/\d+/g);sprintf"%d."."%04d"x$#r,@r};
  9.  
  10. use Carp qw(carp croak);
  11. use POSIX qw(
  12.   sysconf _SC_OPEN_MAX ECHO ICANON IEXTEN ISIG BRKINT ICRNL INPCK
  13.   ISTRIP IXON CSIZE PARENB OPOST TCSANOW
  14. );
  15.  
  16. use POE qw( Wheel Pipe::TwoWay Pipe::OneWay Driver::SysRW Filter::Line );
  17.  
  18. BEGIN {
  19.   die "$^O does not support fork()\n" if $^O eq 'MacOS';
  20.   die "$^O does not fully support fork+exec\n" if $^O eq 'MSWin32';
  21.  
  22.   local $SIG{'__DIE__'} = 'DEFAULT';
  23.   eval    { require IO::Pty; };
  24.   if ($@) { eval 'sub PTY_AVAILABLE () { 0 }';  }
  25.   else {
  26.     IO::Pty->import();
  27.     eval 'sub PTY_AVAILABLE () { 1 }';
  28.   }
  29.  
  30.   # How else can I get them out?!
  31.   if (eval '&IO::Tty::Constant::TIOCSCTTY') {
  32.     *TIOCSCTTY = *IO::Tty::Constant::TIOCSCTTY;
  33.   }
  34.   else {
  35.     eval 'sub TIOCSCTTY () { undef }';
  36.   }
  37.  
  38.   if (eval '&IO::Tty::Constant::CIBAUD') {
  39.     *CIBAUD = *IO::Tty::Constant::CIBAUD;
  40.   }
  41.   else {
  42.     eval 'sub CIBAUD () { undef; }';
  43.   }
  44.  
  45.   if ( eval '&IO::Tty::Constant::TIOCSWINSZ' and
  46.        eval '&IO::Tty::Constant::TIOCGWINSZ'
  47.      ) {
  48.     *TIOCSWINSZ = *IO::Tty::Constant::TIOCSWINSZ;
  49.     *TIOCGWINSZ = *IO::Tty::Constant::TIOCGWINSZ;
  50.   }
  51.   else {
  52.     eval 'sub TIOCSWINSZ () { undef; }';
  53.     eval 'sub TIOCGWINSZ () { undef; }';
  54.   }
  55.  
  56.   # Determine the most file descriptors we can use.
  57.   my $max_open_fds;
  58.   eval {
  59.     $max_open_fds = sysconf(_SC_OPEN_MAX);
  60.   };
  61.   $max_open_fds = 1024 unless $max_open_fds;
  62.   eval "sub MAX_OPEN_FDS () { $max_open_fds }";
  63.   die if $@;
  64. };
  65.  
  66. # Offsets into $self.
  67. sub UNIQUE_ID     () {  0 }
  68. sub ERROR_EVENT   () {  1 }
  69. sub CLOSE_EVENT   () {  2 }
  70. sub PROGRAM       () {  3 }
  71. sub CHILD_PID     () {  4 }
  72. sub CONDUIT_TYPE  () {  5 }
  73. sub IS_ACTIVE     () {  6 }
  74. sub CLOSE_ON_CALL () {  7 }
  75. sub STDIO_TYPE    () {  8 }
  76.  
  77. sub HANDLE_STDIN  () {  9 }
  78. sub FILTER_STDIN  () { 10 }
  79. sub DRIVER_STDIN  () { 11 }
  80. sub EVENT_STDIN   () { 12 }
  81. sub STATE_STDIN   () { 13 }
  82. sub OCTETS_STDIN  () { 14 }
  83.  
  84. sub HANDLE_STDOUT () { 15 }
  85. sub FILTER_STDOUT () { 16 }
  86. sub DRIVER_STDOUT () { 17 }
  87. sub EVENT_STDOUT  () { 18 }
  88. sub STATE_STDOUT  () { 19 }
  89.  
  90. sub HANDLE_STDERR () { 20 }
  91. sub FILTER_STDERR () { 21 }
  92. sub DRIVER_STDERR () { 22 }
  93. sub EVENT_STDERR  () { 23 }
  94. sub STATE_STDERR  () { 24 }
  95.  
  96. # Used to work around a bug in older perl versions.
  97. sub CRIMSON_SCOPE_HACK ($) { 0 }
  98.  
  99. #------------------------------------------------------------------------------
  100.  
  101. sub new {
  102.   my $type = shift;
  103.   croak "$type needs an even number of parameters" if @_ & 1;
  104.   my %params = @_;
  105.  
  106.   croak "wheels no longer require a kernel reference as their first parameter"
  107.     if @_ and ref($_[0]) eq 'POE::Kernel';
  108.  
  109.   croak "$type requires a working Kernel" unless defined $poe_kernel;
  110.  
  111.   my $program = delete $params{Program};
  112.   croak "$type needs a Program parameter" unless defined $program;
  113.  
  114.   my $prog_args = delete $params{ProgramArgs};
  115.   $prog_args = [] unless defined $prog_args;
  116.   croak "ProgramArgs must be an ARRAY reference"
  117.     unless ref($prog_args) eq "ARRAY";
  118.  
  119.   my $priority_delta = delete $params{Priority};
  120.   $priority_delta = 0 unless defined $priority_delta;
  121.  
  122.   my $close_on_call = delete $params{CloseOnCall};
  123.   $close_on_call = 0 unless defined $close_on_call;
  124.  
  125.   my $user_id  = delete $params{User};
  126.   my $group_id = delete $params{Group};
  127.  
  128.   # The following $stdio_type is new.  $conduit is kept around for now
  129.   # to preserve the logic of the rest of the module.  This change
  130.   # allows a Session using POE::Wheel::Run to define the type of pipe
  131.   # to be created for stdin and stdout.  Read the POD on Conduit.
  132.   # However, the documentation lies, because if Conduit is undefined,
  133.   # $stdio_type is set to undefined (so the default pipe type provided
  134.   # by POE::Pipe::TwoWay will be used). Otherwise, $stdio_type
  135.   # determines what type of pipe Pipe:TwoWay creates unless it's
  136.   # 'pty'.
  137.  
  138.   my $conduit = delete $params{Conduit};
  139.   my $stdio_type;
  140.   if (defined $conduit) {
  141.     croak "$type\'s Conduit type ($conduit) is unknown"
  142.       if (
  143.         $conduit ne 'pipe' and
  144.         $conduit ne 'pty'  and
  145.         $conduit ne 'socketpair' and
  146.         $conduit ne 'inet'
  147.       );
  148.     unless ($conduit eq "pty") {
  149.       $stdio_type = $conduit;
  150.       $conduit = "pipe";
  151.     }
  152.   }
  153.   else {
  154.     $conduit = "pipe";
  155.   }
  156.  
  157.   my $winsize = delete $params{Winsize};
  158.   croak "Winsize needs to be an array ref"
  159.     if (defined($winsize) and ref($winsize) ne 'ARRAY');
  160.  
  161.   my $stdin_event  = delete $params{StdinEvent};
  162.   my $stdout_event = delete $params{StdoutEvent};
  163.   my $stderr_event = delete $params{StderrEvent};
  164.  
  165.   if ($conduit eq 'pty' and defined $stderr_event) {
  166.     carp "ignoring StderrEvent with pty conduit";
  167.     undef $stderr_event;
  168.   }
  169.  
  170.   croak "$type needs at least one of StdinEvent, StdoutEvent or StderrEvent"
  171.     unless( defined($stdin_event) or defined($stdout_event) or
  172.             defined($stderr_event)
  173.           );
  174.  
  175.   my $stdio_driver  = delete $params{StdioDriver}
  176.     || POE::Driver::SysRW->new();
  177.   my $stdin_driver  = delete $params{StdinDriver}  || $stdio_driver;
  178.   my $stdout_driver = delete $params{StdoutDriver} || $stdio_driver;
  179.   my $stderr_driver = delete $params{StderrDriver}
  180.     || POE::Driver::SysRW->new();
  181.  
  182.   my $stdio_filter  = delete $params{Filter};
  183.   my $stdin_filter  = delete $params{StdinFilter};
  184.   my $stdout_filter = delete $params{StdoutFilter};
  185.   my $stderr_filter = delete $params{StderrFilter};
  186.  
  187.   if (defined $stdio_filter) {
  188.     croak "Filter and StdioFilter cannot be used together"
  189.       if defined $params{StdioFilter};
  190.     croak "Replace deprecated Filter with StdioFilter and StderrFilter"
  191.       if defined $stderr_event and not defined $stderr_filter;
  192.     carp "Filter is deprecated.  Please try StdioFilter and/or StderrFilter";
  193.   }
  194.   else {
  195.     $stdio_filter = delete $params{StdioFilter};
  196.   }
  197.   $stdio_filter = POE::Filter::Line->new(Literal => "\n")
  198.     unless defined $stdio_filter;
  199.  
  200.   $stdin_filter  = $stdio_filter unless defined $stdin_filter;
  201.   $stdout_filter = $stdio_filter unless defined $stdout_filter;
  202.  
  203.   if ($conduit eq 'pty' and defined $stderr_filter) {
  204.     carp "ignoring StderrFilter with pty conduit";
  205.     undef $stderr_filter;
  206.   }
  207.   else {
  208.     $stderr_filter = POE::Filter::Line->new(Literal => "\n")
  209.       unless defined $stderr_filter;
  210.   }
  211.  
  212.   croak "$type needs either StdioFilter or StdinFilter when using StdinEvent"
  213.     if defined($stdin_event) and not defined($stdin_filter);
  214.   croak "$type needs either StdioFilter or StdoutFilter when using StdoutEvent"
  215.     if defined($stdout_event) and not defined($stdout_filter);
  216.   croak "$type needs a StderrFilter when using StderrEvent"
  217.     if defined($stderr_event) and not defined($stderr_filter);
  218.  
  219.   my $error_event = delete $params{ErrorEvent};
  220.   my $close_event = delete $params{CloseEvent};
  221.  
  222.   # Make sure the user didn't pass in parameters we're not aware of.
  223.   if (scalar keys %params) {
  224.     carp( "unknown parameters in $type constructor call: ",
  225.           join(', ', sort keys %params)
  226.         );
  227.   }
  228.  
  229.   my ( $stdin_read, $stdout_write, $stdout_read, $stdin_write,
  230.        $stderr_read, $stderr_write,
  231.      );
  232.  
  233.   # Create a semaphore pipe.  This is used so that the parent doesn't
  234.   # begin listening until the child's stdio has been set up.
  235.   my ($sem_pipe_read, $sem_pipe_write) = POE::Pipe::OneWay->new();
  236.   croak "could not create semaphore pipe: $!" unless defined $sem_pipe_read;
  237.  
  238.   # Use IO::Pty if requested.  IO::Pty turns on autoflush for us.
  239.   if ($conduit eq 'pty') {
  240.     croak "IO::Pty is not available" unless PTY_AVAILABLE;
  241.  
  242.     $stdin_write = $stdout_read = IO::Pty->new();
  243.     croak "could not create master pty: $!" unless defined $stdout_read;
  244.   }
  245.  
  246.   # Use pipes otherwise.
  247.   elsif ($conduit eq 'pipe') {
  248.     # We make more pipes than strictly necessary in case someone wants
  249.     # to turn some on later.  Uses a TwoWay pipe for STDIN/STDOUT and
  250.     # a OneWay pipe for STDERR.  This may save 2 filehandles if
  251.     # socketpair() is available and no other $stdio_type is selected.
  252.     ($stdin_read, $stdout_write, $stdout_read, $stdin_write) =
  253.       POE::Pipe::TwoWay->new($stdio_type);
  254.     croak "could not make stdin pipe: $!"
  255.       unless defined $stdin_read and defined $stdin_write;
  256.     croak "could not make stdout pipe: $!"
  257.       unless defined $stdout_read and defined $stdout_write;
  258.  
  259.     ($stderr_read, $stderr_write) = POE::Pipe::OneWay->new();
  260.     croak "could not make stderr pipes: $!"
  261.       unless defined $stderr_read and defined $stderr_write;
  262.   }
  263.  
  264.   # Sanity check.
  265.   else {
  266.     croak "unknown conduit type $conduit";
  267.   }
  268.  
  269.   # Fork!  Woo-hoo!
  270.   my $pid = fork;
  271.  
  272.   # Child.  Parent side continues after this block.
  273.   unless ($pid) {
  274.     croak "couldn't fork: $!" unless defined $pid;
  275.  
  276.     # If running pty, we delay the slave side creation 'til after
  277.     # doing the necessary bits to become our own [unix] session.
  278.     if ($conduit eq 'pty') {
  279.  
  280.       # Become a new unix session.
  281.       # Program 19.3, APITUE.  W. Richard Stevens built my hot rod.
  282.       eval 'setsid()';
  283.  
  284.       # Open the slave side of the pty.
  285.       $stdin_read = $stdout_write = $stderr_write = $stdin_write->slave();
  286.       croak "could not create slave pty: $!" unless defined $stdin_read;
  287.  
  288.       # Acquire a controlling terminal.  Program 19.3, APITUE.
  289.       if (defined TIOCSCTTY and not defined CIBAUD) {
  290.         ioctl( $stdin_read, TIOCSCTTY, 0 );
  291.       }
  292.  
  293.       # Put the pty conduit (slave side) into "raw" or "cbreak" mode,
  294.       # per APITUE 19.4 and 11.10.
  295.       my $tio = POSIX::Termios->new();
  296.       $tio->getattr(fileno($stdin_read));
  297.       my $lflag = $tio->getlflag;
  298.       $lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
  299.       $tio->setlflag($lflag);
  300.       my $iflag = $tio->getiflag;
  301.       $iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
  302.       $tio->setiflag($iflag);
  303.       my $cflag = $tio->getcflag;
  304.       $cflag &= ~(CSIZE | PARENB);
  305.       $tio->setcflag($cflag);
  306.       my $oflag = $tio->getoflag;
  307.       $oflag &= ~(OPOST);
  308.       $tio->setoflag($oflag);
  309.       $tio->setattr(fileno($stdin_read), TCSANOW);
  310.  
  311.       # Set the pty conduit (slave side) window size to our window
  312.       # size.  APITUE 19.4 and 19.5.
  313.       if (defined TIOCGWINSZ) {
  314.         my $window_size = '!' x 25;
  315.         if (-t STDIN and !$winsize) {
  316.           ioctl( STDIN, TIOCGWINSZ, $window_size ) or die $!;
  317.         }
  318.         $window_size = pack('SSSS', @$winsize) if ref($winsize);
  319.         if ($window_size ne '!' x 25) {
  320.           ioctl( $stdin_read, TIOCSWINSZ, $window_size ) or die $!;
  321.         }
  322.         else {
  323.           carp "STDIN is not a terminal.  Can't set slave pty's window size";
  324.         }
  325.       }
  326.     }
  327.  
  328.     # Reset all signals in the child process.  POE's own handlers are
  329.     # silly to keep around in the child process since POE won't be
  330.     # using them.
  331.     my @safe_signals = $poe_kernel->_data_sig_get_safe_signals();
  332.     @SIG{@safe_signals} = ("DEFAULT") x @safe_signals;
  333.  
  334.     # -><- How to pass events to the parent process?  Maybe over a
  335.     # expedited (OOB) filehandle.
  336.  
  337.     # Fix the child process' priority.  Don't bother doing this if it
  338.     # wasn't requested.  Can't emit events on failure because we're in
  339.     # a separate process, so just fail quietly.
  340.  
  341.     if ($priority_delta) {
  342.       eval {
  343.         if (defined(my $priority = getpriority(0, $$))) {
  344.           unless (setpriority(0, $$, $priority + $priority_delta)) {
  345.             # -><- can't set child priority
  346.           }
  347.         }
  348.         else {
  349.           # -><- can't get child priority
  350.         }
  351.       };
  352.       if ($@) {
  353.         # -><- can't get child priority
  354.       }
  355.     }
  356.  
  357.     # Fix the group ID.  -><- Add getgrnam so group IDs can be
  358.     # specified by name.  -><- Warn if not superuser to begin with.
  359.     if (defined $group_id) {
  360.       $( = $) = $group_id;
  361.     }
  362.  
  363.     # Fix the user ID.  -><- Add getpwnam so user IDs can be specified
  364.     # by name.  -><- Warn if not superuser to begin with.
  365.     if (defined $user_id) {
  366.       $< = $> = $user_id;
  367.     }
  368.  
  369.     # Close what the child won't need.
  370.     close $stdin_write;
  371.     close $stdout_read;
  372.     close $stderr_read if defined $stderr_read;
  373.  
  374.     # Redirect STDIN from the read end of the stdin pipe.
  375.     open( STDIN, "<&" . fileno($stdin_read) )
  376.       or die "can't redirect STDIN in child pid $$: $!";
  377.  
  378.     # Redirect STDOUT to the write end of the stdout pipe.
  379.     open( STDOUT, ">&" . fileno($stdout_write) )
  380.       or die "can't redirect stdout in child pid $$: $!";
  381.  
  382.     # Redirect STDERR to the write end of the stderr pipe.  If the
  383.     # stderr pipe's undef, then we use STDOUT.
  384.     open( STDERR, ">&" . fileno($stderr_write) )
  385.       or die "can't redirect stderr in child: $!";
  386.  
  387.     # Make STDOUT and/or STDERR auto-flush.
  388.     select STDERR;  $| = 1;
  389.     select STDOUT;  $| = 1;
  390.  
  391.     # Tell the parent that the stdio has been set up.
  392.     close $sem_pipe_read unless $^O eq 'MSWin32';
  393.     print $sem_pipe_write "go\n";
  394.     close $sem_pipe_write unless $^O eq 'MSWin32';
  395.  
  396.     # Exec the program depending on its form.
  397.     if (ref($program) eq 'ARRAY') {
  398.       exec(@$program, @$prog_args)
  399.         or die "can't exec (@$program) in child pid $$: $!";
  400.     }
  401.     elsif (ref($program) eq 'CODE') {
  402.  
  403.       # Close any close-on-exec file descriptors.
  404.       if ($close_on_call) {
  405.         POSIX::close($_) for $^F+1..MAX_OPEN_FDS;
  406.       }
  407.  
  408.       $program->(@$prog_args);
  409.  
  410.       # In case flushing them wasn't good enough.
  411.       close STDOUT if defined fileno(STDOUT);
  412.       close STDERR if defined fileno(STDERR);
  413.  
  414.       # Try to exit without triggering END or object destructors.
  415.       # Give up with a plain exit if we must.
  416.       eval { POSIX::_exit(0);  };
  417.       eval { kill KILL => $$;  };
  418.       eval { exec("$^X -e 0"); };
  419.       exit(0);
  420.     }
  421.     else {
  422.       exec(join(" ", $program, @$prog_args))
  423.         or die "can't exec ($program) in child pid $$: $!";
  424.     }
  425.  
  426.     die "insanity check passed";
  427.   }
  428.  
  429.   # Parent here.  Close what the parent won't need.
  430.   close $stdin_read   if defined $stdin_read;
  431.   close $stdout_write if defined $stdout_write;
  432.   close $stderr_write if defined $stderr_write;
  433.  
  434.   my $handle_count = 0;
  435.   $handle_count++ if defined $stdout_read;
  436.   $handle_count++ if defined $stderr_read;
  437.  
  438.   my $self = bless
  439.     [ &POE::Wheel::allocate_wheel_id(),  # UNIQUE_ID
  440.       $error_event,   # ERROR_EVENT
  441.       $close_event,   # CLOSE_EVENT
  442.       $program,       # PROGRAM
  443.       $pid,           # CHILD_PID
  444.       $conduit,       # CONDUIT_TYPE
  445.       $handle_count,  # IS_ACTIVE
  446.       $close_on_call, # CLOSE_ON_CALL
  447.       $stdio_type,    # STDIO_TYPE
  448.       # STDIN
  449.       $stdin_write,   # HANDLE_STDIN
  450.       $stdin_filter,  # FILTER_STDIN
  451.       $stdin_driver,  # DRIVER_STDIN
  452.       $stdin_event,   # EVENT_STDIN
  453.       undef,          # STATE_STDIN
  454.       0,              # OCTETS_STDIN
  455.       # STDOUT
  456.       $stdout_read,   # HANDLE_STDOUT
  457.       $stdout_filter, # FILTER_STDOUT
  458.       $stdout_driver, # DRIVER_STDOUT
  459.       $stdout_event,  # EVENT_STDOUT
  460.       undef,          # STATE_STDOUT
  461.       # STDERR
  462.       $stderr_read,   # HANDLE_STDERR
  463.       $stderr_filter, # FILTER_STDERR
  464.       $stderr_driver, # DRIVER_STDERR
  465.       $stderr_event,  # EVENT_STDERR
  466.       undef,          # STATE_STDERR
  467.     ], $type;
  468.  
  469.   # Wait here while the child sets itself up.
  470.   <$sem_pipe_read>;
  471.   close $sem_pipe_read;
  472.   close $sem_pipe_write;
  473.  
  474.   $self->_define_stdin_flusher();
  475.   $self->_define_stdout_reader() if defined $stdout_read;
  476.   $self->_define_stderr_reader() if defined $stderr_read;
  477.  
  478.   return $self;
  479. }
  480.  
  481. #------------------------------------------------------------------------------
  482. # Define the internal state that will flush output to the child
  483. # process' STDIN pipe.
  484.  
  485. sub _define_stdin_flusher {
  486.   my $self = shift;
  487.  
  488.   # Read-only members.  If any of these change, then the write state
  489.   # is invalidated and needs to be redefined.
  490.   my $unique_id    = $self->[UNIQUE_ID];
  491.   my $driver       = $self->[DRIVER_STDIN];
  492.   my $error_event  = \$self->[ERROR_EVENT];
  493.   my $close_event  = \$self->[CLOSE_EVENT];
  494.   my $stdin_filter = $self->[FILTER_STDIN];
  495.   my $stdin_event  = \$self->[EVENT_STDIN];
  496.   my $is_active    = \$self->[IS_ACTIVE];
  497.  
  498.   # Read/write members.  These are done by reference, to avoid pushing
  499.   # $self into the anonymous sub.  Extra copies of $self are bad and
  500.   # can prevent wheels from destructing properly.
  501.   my $stdin_octets = \$self->[OCTETS_STDIN];
  502.  
  503.   # Register the select-write handler.
  504.   $poe_kernel->state
  505.     ( $self->[STATE_STDIN] = ref($self) . "($unique_id) -> select stdin",
  506.       sub {                             # prevents SEGV
  507.         0 && CRIMSON_SCOPE_HACK('<');
  508.                                         # subroutine starts here
  509.         my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
  510.  
  511.         $$stdin_octets = $driver->flush($handle);
  512.  
  513.         # When you can't write, nothing else matters.
  514.         if ($!) {
  515.           $$error_event && $k->call( $me, $$error_event,
  516.                                      'write', ($!+0), $!, $unique_id, "STDIN"
  517.                                    );
  518.           $k->select_write($handle);
  519.         }
  520.  
  521.         # Could write, or perhaps couldn't but only because the
  522.         # filehandle's buffer is choked.
  523.         else {
  524.  
  525.           # All chunks written; fire off a "flushed" event.
  526.           unless ($$stdin_octets) {
  527.             $k->select_pause_write($handle);
  528.             $$stdin_event && $k->call($me, $$stdin_event, $unique_id);
  529.           }
  530.         }
  531.       }
  532.     );
  533.  
  534.   $poe_kernel->select_write($self->[HANDLE_STDIN], $self->[STATE_STDIN]);
  535.  
  536.   # Pause the write select immediately, unless output is pending.
  537.   $poe_kernel->select_pause_write($self->[HANDLE_STDIN])
  538.     unless ($self->[OCTETS_STDIN]);
  539. }
  540.  
  541. #------------------------------------------------------------------------------
  542. # Define the internal state that will read input from the child
  543. # process' STDOUT pipe.  This is virtually identical to
  544. # _define_stderr_reader, but they aren't implemented as a common
  545. # function for speed reasons.
  546.  
  547. sub _define_stdout_reader {
  548.   my $self = shift;
  549.  
  550.   # Register the select-read handler for STDOUT.
  551.   if (defined $self->[HANDLE_STDOUT]) {
  552.  
  553.     # If any of these change, then the read state is invalidated and
  554.     # needs to be redefined.
  555.     my $unique_id     = $self->[UNIQUE_ID];
  556.     my $driver        = $self->[DRIVER_STDOUT];
  557.     my $error_event   = \$self->[ERROR_EVENT];
  558.     my $close_event   = \$self->[CLOSE_EVENT];
  559.     my $stdout_filter = $self->[FILTER_STDOUT];
  560.     my $stdout_event  = \$self->[EVENT_STDOUT];
  561.     my $is_active     = \$self->[IS_ACTIVE];
  562.  
  563.     if ( $stdout_filter->can("get_one") and
  564.          $stdout_filter->can("get_one_start")
  565.        ) {
  566.       $poe_kernel->state
  567.         ( $self->[STATE_STDOUT] = ref($self) . "($unique_id) -> select stdout",
  568.           sub {
  569.             # prevents SEGV
  570.             0 && CRIMSON_SCOPE_HACK('<');
  571.  
  572.             # subroutine starts here
  573.             my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
  574.             if (defined(my $raw_input = $driver->get($handle))) {
  575.               $stdout_filter->get_one_start($raw_input);
  576.               while (1) {
  577.                 my $next_rec = $stdout_filter->get_one();
  578.                 last unless @$next_rec;
  579.                 foreach my $cooked_input (@$next_rec) {
  580.                   $k->call($me, $$stdout_event, $cooked_input, $unique_id);
  581.                 }
  582.               }
  583.             }
  584.             else {
  585.               $$error_event and
  586.                 $k->call( $me, $$error_event,
  587.                           'read', ($!+0), $!, $unique_id, 'STDOUT'
  588.                         );
  589.               unless (--$$is_active) {
  590.                 $k->call( $me, $$close_event, $unique_id )
  591.                   if defined $$close_event;
  592.               }
  593.               $k->select_read($handle);
  594.             }
  595.           }
  596.         );
  597.     }
  598.  
  599.     # Otherwise we can't get one.
  600.     else {
  601.       $poe_kernel->state
  602.         ( $self->[STATE_STDOUT] = ref($self) . "($unique_id) -> select stdout",
  603.           sub {
  604.             # prevents SEGV
  605.             0 && CRIMSON_SCOPE_HACK('<');
  606.  
  607.             # subroutine starts here
  608.             my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
  609.             if (defined(my $raw_input = $driver->get($handle))) {
  610.               foreach my $cooked_input (@{$stdout_filter->get($raw_input)}) {
  611.                 $k->call($me, $$stdout_event, $cooked_input, $unique_id);
  612.               }
  613.             }
  614.             else {
  615.               $$error_event and
  616.                 $k->call( $me, $$error_event,
  617.                           'read', ($!+0), $!, $unique_id, 'STDOUT'
  618.                         );
  619.               unless (--$$is_active) {
  620.                 $k->call( $me, $$close_event, $unique_id )
  621.                   if defined $$close_event;
  622.               }
  623.               $k->select_read($handle);
  624.             }
  625.           }
  626.         );
  627.     }
  628.  
  629.     # register the state's select
  630.     $poe_kernel->select_read($self->[HANDLE_STDOUT], $self->[STATE_STDOUT]);
  631.   }
  632.  
  633.   # Register the select-read handler for STDOUT.
  634.   else {
  635.     $poe_kernel->select_read($self->[HANDLE_STDOUT])
  636.       if defined $self->[HANDLE_STDOUT];
  637.   }
  638. }
  639.  
  640. #------------------------------------------------------------------------------
  641. # Define the internal state that will read input from the child
  642. # process' STDERR pipe.
  643.  
  644. sub _define_stderr_reader {
  645.   my $self = shift;
  646.  
  647.   # Register the select-read handler for STDERR.
  648.   if (defined $self->[HANDLE_STDERR]) {
  649.     # If any of these change, then the read state is invalidated and
  650.     # needs to be redefined.
  651.     my $unique_id     = $self->[UNIQUE_ID];
  652.     my $driver        = $self->[DRIVER_STDERR];
  653.     my $error_event   = \$self->[ERROR_EVENT];
  654.     my $close_event   = \$self->[CLOSE_EVENT];
  655.     my $stderr_filter = $self->[FILTER_STDERR];
  656.     my $stderr_event  = \$self->[EVENT_STDERR];
  657.     my $is_active     = \$self->[IS_ACTIVE];
  658.  
  659.     if ( $stderr_filter->can("get_one") and
  660.          $stderr_filter->can("get_one_start")
  661.        ) {
  662.       $poe_kernel->state
  663.         ( $self->[STATE_STDERR] = ref($self) . "($unique_id) -> select stderr",
  664.           sub {
  665.             # prevents SEGV
  666.             0 && CRIMSON_SCOPE_HACK('<');
  667.  
  668.             # subroutine starts here
  669.             my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
  670.             if (defined(my $raw_input = $driver->get($handle))) {
  671.               $stderr_filter->get_one_start($raw_input);
  672.               while (1) {
  673.                 my $next_rec = $stderr_filter->get_one();
  674.                 last unless @$next_rec;
  675.                 foreach my $cooked_input (@$next_rec) {
  676.                   $k->call($me, $$stderr_event, $cooked_input, $unique_id);
  677.                 }
  678.               }
  679.             }
  680.             else {
  681.               $$error_event and
  682.                 $k->call( $me, $$error_event,
  683.                           'read', ($!+0), $!, $unique_id, 'STDERR'
  684.                         );
  685.               unless (--$$is_active) {
  686.                 $k->call( $me, $$close_event, $unique_id )
  687.                   if defined $$close_event;
  688.               }
  689.               $k->select_read($handle);
  690.             }
  691.           }
  692.         );
  693.     }
  694.  
  695.     # Otherwise we can't get_one().
  696.     else {
  697.       $poe_kernel->state
  698.         ( $self->[STATE_STDERR] = ref($self) . "($unique_id) -> select stderr",
  699.           sub {
  700.             # prevents SEGV
  701.             0 && CRIMSON_SCOPE_HACK('<');
  702.  
  703.             # subroutine starts here
  704.             my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
  705.             if (defined(my $raw_input = $driver->get($handle))) {
  706.               foreach my $cooked_input (@{$stderr_filter->get($raw_input)}) {
  707.                 $k->call($me, $$stderr_event, $cooked_input, $unique_id);
  708.               }
  709.             }
  710.             else {
  711.               $$error_event and
  712.                 $k->call( $me, $$error_event,
  713.                           'read', ($!+0), $!, $unique_id, 'STDERR'
  714.                         );
  715.               unless (--$$is_active) {
  716.                 $k->call( $me, $$close_event, $unique_id )
  717.                   if defined $$close_event;
  718.               }
  719.               $k->select_read($handle);
  720.             }
  721.           }
  722.         );
  723.     }
  724.  
  725.     # register the state's select
  726.     $poe_kernel->select_read($self->[HANDLE_STDERR], $self->[STATE_STDERR]);
  727.   }
  728.  
  729.   # Register the select-read handler for STDERR.
  730.   else {
  731.     $poe_kernel->select_read($self->[HANDLE_STDERR])
  732.       if defined $self->[HANDLE_STDERR];
  733.   }
  734. }
  735.  
  736. #------------------------------------------------------------------------------
  737. # Redefine events.
  738.  
  739. sub event {
  740.   my $self = shift;
  741.   push(@_, undef) if (scalar(@_) & 1);
  742.  
  743.   my ($redefine_stdin, $redefine_stdout, $redefine_stderr) = (0, 0, 0);
  744.  
  745.   while (@_) {
  746.     my ($name, $event) = splice(@_, 0, 2);
  747.  
  748.     if ($name eq 'StdinEvent') {
  749.       $self->[EVENT_STDIN] = $event;
  750.       $redefine_stdin = 1;
  751.     }
  752.     elsif ($name eq 'StdoutEvent') {
  753.       $self->[EVENT_STDOUT] = $event;
  754.       $redefine_stdout = 1;
  755.     }
  756.     elsif ($name eq 'StderrEvent') {
  757.       if ($self->[CONDUIT_TYPE] ne 'pty') {
  758.         $self->[EVENT_STDERR] = $event;
  759.         $redefine_stderr = 1;
  760.       }
  761.       else {
  762.         carp "ignoring StderrEvent on a pty conduit";
  763.       }
  764.     }
  765.     elsif ($name eq 'ErrorEvent') {
  766.       $self->[ERROR_EVENT] = $event;
  767.     }
  768.     elsif ($name eq 'CloseEvent') {
  769.       $self->[CLOSE_EVENT] = $event;
  770.     }
  771.     else {
  772.       carp "ignoring unknown Run parameter '$name'";
  773.     }
  774.   }
  775.  
  776.   $self->_define_stdin_flusher() if defined $redefine_stdin;
  777.   $self->_define_stdout_reader() if defined $redefine_stdout;
  778.   $self->_define_stderr_reader() if defined $redefine_stderr;
  779. }
  780.  
  781. #------------------------------------------------------------------------------
  782. # Destroy the wheel.
  783.  
  784. sub DESTROY {
  785.   my $self = shift;
  786.  
  787.   # Turn off the STDIN thing.
  788.   if ($self->[HANDLE_STDIN]) {
  789.     $poe_kernel->select($self->[HANDLE_STDIN]);
  790.     $self->[HANDLE_STDIN] = undef;
  791.   }
  792.   if ($self->[STATE_STDIN]) {
  793.     $poe_kernel->state($self->[STATE_STDIN]);
  794.     $self->[STATE_STDIN] = undef;
  795.   }
  796.  
  797.   if ($self->[HANDLE_STDOUT]) {
  798.     $poe_kernel->select($self->[HANDLE_STDOUT]);
  799.     $self->[HANDLE_STDOUT] = undef;
  800.   }
  801.   if ($self->[STATE_STDOUT]) {
  802.     $poe_kernel->state($self->[STATE_STDOUT]);
  803.     $self->[STATE_STDOUT] = undef;
  804.   }
  805.  
  806.   if ($self->[HANDLE_STDERR]) {
  807.     $poe_kernel->select($self->[HANDLE_STDERR]);
  808.     $self->[HANDLE_STDERR] = undef;
  809.   }
  810.   if ($self->[STATE_STDERR]) {
  811.     $poe_kernel->state($self->[STATE_STDERR]);
  812.     $self->[STATE_STDERR] = undef;
  813.   }
  814.  
  815.   &POE::Wheel::free_wheel_id($self->[UNIQUE_ID]);
  816. }
  817.  
  818. #------------------------------------------------------------------------------
  819. # Queue input for the child process.
  820.  
  821. sub put {
  822.   my ($self, @chunks) = @_;
  823.   if ( $self->[OCTETS_STDIN] =
  824.        $self->[DRIVER_STDIN]->put($self->[FILTER_STDIN]->put(\@chunks))
  825.   ) {
  826.     $poe_kernel->select_resume_write($self->[HANDLE_STDIN]);
  827.   }
  828.  
  829.   # No watermark.
  830.   return 0;
  831. }
  832.  
  833. #------------------------------------------------------------------------------
  834. # Pause and resume various input events.
  835.  
  836. sub pause_stdout {
  837.   my $self = shift;
  838.   return unless defined $self->[HANDLE_STDOUT];
  839.   $poe_kernel->select_pause_read($self->[HANDLE_STDOUT]);
  840. }
  841.  
  842. sub pause_stderr {
  843.   my $self = shift;
  844.   return unless defined $self->[HANDLE_STDERR];
  845.   $poe_kernel->select_pause_read($self->[HANDLE_STDERR]);
  846. }
  847.  
  848. sub resume_stdout {
  849.   my $self = shift;
  850.   return unless defined $self->[HANDLE_STDOUT];
  851.   $poe_kernel->select_resume_read($self->[HANDLE_STDOUT]);
  852. }
  853.  
  854. sub resume_stderr {
  855.   my $self = shift;
  856.   return unless defined $self->[HANDLE_STDERR];
  857.   $poe_kernel->select_resume_read($self->[HANDLE_STDERR]);
  858. }
  859.  
  860. # Shutdown the pipe that leads to the child's STDIN.
  861. sub shutdown_stdin {
  862.   my $self = shift;
  863.   return unless defined $self->[HANDLE_STDIN];
  864.  
  865.   if ($self->[STDIO_TYPE] eq "pipe" or $self->[STDIO_TYPE] eq "pty") {
  866.     close $self->[HANDLE_STDIN];
  867.   }
  868.   else {
  869.     eval { local $^W = 0; shutdown($self->[HANDLE_STDIN], 1) };
  870.   }
  871.  
  872.   $poe_kernel->select_write($self->[HANDLE_STDIN], undef);
  873. }
  874.  
  875. #------------------------------------------------------------------------------
  876. # Redefine filters, one at a time or at once.  This is based on PG's
  877. # code in Wheel::ReadWrite.
  878.  
  879. sub _transfer_stdout_buffer {
  880.   my ($self, $buf) = @_;
  881.  
  882.   my $old_output_filter = $self->[FILTER_STDOUT];
  883.  
  884.   # Assign old buffer contents to the new filter, and send out any
  885.   # pending packets.
  886.  
  887.   # Use "get_one" if the new filter implements it.
  888.   if (defined $buf) {
  889.     if ( $old_output_filter->can("get_one") and
  890.          $old_output_filter->can("get_one_start")
  891.        ) {
  892.       $old_output_filter->get_one_start($buf);
  893.  
  894.       # Don't bother to continue if the filter has switched out from
  895.       # under our feet again.  The new switcher will finish the job.
  896.  
  897.       while ($self->[FILTER_STDOUT] == $old_output_filter) {
  898.         my $next_rec = $old_output_filter->get_one();
  899.         last unless @$next_rec;
  900.         foreach my $cooked_input (@$next_rec) {
  901.           $poe_kernel->call( $poe_kernel->get_active_session(),
  902.                              $self->[EVENT_STDOUT],
  903.                              $cooked_input, $self->[UNIQUE_ID]
  904.                            );
  905.         }
  906.       }
  907.     }
  908.  
  909.     # Otherwise use the old get() behavior.
  910.     else {
  911.       foreach my $cooked_input (@{$self->[FILTER_STDOUT]->get($buf)}) {
  912.         $poe_kernel->call( $poe_kernel->get_active_session(),
  913.                            $self->[EVENT_STDOUT],
  914.                            $cooked_input, $self->[UNIQUE_ID]
  915.                          );
  916.       }
  917.     }
  918.   }
  919. }
  920.  
  921. sub _transfer_stderr_buffer {
  922.   my ($self, $buf) = @_;
  923.  
  924.   my $old_output_filter = $self->[FILTER_STDERR];
  925.  
  926.   # Assign old buffer contents to the new filter, and send out any
  927.   # pending packets.
  928.  
  929.   # Use "get_one" if the new filter implements it.
  930.   if (defined $buf) {
  931.     if ( $old_output_filter->can("get_one") and
  932.          $old_output_filter->can("get_one_start")
  933.        ) {
  934.       $old_output_filter->get_one_start($buf);
  935.  
  936.       # Don't bother to continue if the filter has switched out from
  937.       # under our feet again.  The new switcher will finish the job.
  938.  
  939.       while ($self->[FILTER_STDERR] == $old_output_filter) {
  940.         my $next_rec = $old_output_filter->get_one();
  941.         last unless @$next_rec;
  942.         foreach my $cooked_input (@$next_rec) {
  943.           $poe_kernel->call( $poe_kernel->get_active_session(),
  944.                              $self->[EVENT_STDERR],
  945.                              $cooked_input, $self->[UNIQUE_ID]
  946.                            );
  947.         }
  948.       }
  949.     }
  950.  
  951.     # Otherwise use the old get() behavior.
  952.     else {
  953.       foreach my $cooked_input (@{$self->[FILTER_STDERR]->get($buf)}) {
  954.         $poe_kernel->call( $poe_kernel->get_active_session(),
  955.                            $self->[EVENT_STDERR],
  956.                            $cooked_input, $self->[UNIQUE_ID]
  957.                          );
  958.       }
  959.     }
  960.   }
  961. }
  962.  
  963. sub set_stdio_filter {
  964.   my ($self, $new_filter) = @_;
  965.   $self->set_stdout_filter($new_filter);
  966.   $self->set_stdin_filter($new_filter);
  967. }
  968.  
  969. sub set_stdin_filter {
  970.   my ($self, $new_filter) = @_;
  971.   $self->[FILTER_STDIN] = $new_filter;
  972. }
  973.  
  974. sub set_stdout_filter {
  975.   my ($self, $new_filter) = @_;
  976.  
  977.   my $buf = $self->[FILTER_STDOUT]->get_pending();
  978.   $self->[FILTER_STDOUT] = $new_filter;
  979.  
  980.   $self->_define_stdout_reader();
  981.   $self->_transfer_stdout_buffer($buf);
  982. }
  983.  
  984. sub set_stderr_filter {
  985.   my ($self, $new_filter) = @_;
  986.  
  987.   my $buf = $self->[FILTER_STDERR]->get_pending();
  988.   $self->[FILTER_STDERR] = $new_filter;
  989.  
  990.   $self->_define_stderr_reader();
  991.   $self->_transfer_stderr_buffer($buf);
  992. }
  993.  
  994. sub get_stdin_filter {
  995.   my $self = shift;
  996.   return $self->[FILTER_STDIN];
  997. }
  998.  
  999. sub get_stdout_filter {
  1000.   my $self = shift;
  1001.   return $self->[FILTER_STDOUT];
  1002. }
  1003.  
  1004. sub get_stderr_filter {
  1005.   my $self = shift;
  1006.   return $self->[FILTER_STDERR];
  1007. }
  1008.  
  1009. #------------------------------------------------------------------------------
  1010. # Data accessors.
  1011.  
  1012. sub get_driver_out_octets {
  1013.   $_[0]->[OCTETS_STDIN];
  1014. }
  1015.  
  1016. sub get_driver_out_messages {
  1017.   $_[0]->[DRIVER_STDIN]->get_out_messages_buffered();
  1018. }
  1019.  
  1020. sub ID {
  1021.   $_[0]->[UNIQUE_ID];
  1022. }
  1023.  
  1024. sub PID {
  1025.   $_[0]->[CHILD_PID];
  1026. }
  1027.  
  1028. sub kill {
  1029.   my ($self, $signal) = @_;
  1030.   $signal = 'TERM' unless defined $signal;
  1031.   eval { kill $signal, $self->[CHILD_PID] };
  1032. }
  1033.  
  1034. ###############################################################################
  1035. 1;
  1036.  
  1037. __END__
  1038.  
  1039. =head1 NAME
  1040.  
  1041. POE::Wheel::Run - event driven fork/exec with added value
  1042.  
  1043. =head1 SYNOPSIS
  1044.  
  1045.   # Program may be scalar or \@array.
  1046.   $program = '/usr/bin/cat -';
  1047.   $program = [ '/usr/bin/cat', '-' ];
  1048.  
  1049.   $wheel = POE::Wheel::Run->new(
  1050.     Program     => $program,
  1051.     ProgramArgs => \@program_args,     # Parameters for $program.
  1052.     Priority    => +5,                 # Adjust priority.  May need to be root.
  1053.     User        => getpwnam('nobody'), # Adjust UID. May need to be root.
  1054.     Group       => getgrnam('nobody'), # Adjust GID. May need to be root.
  1055.     ErrorEvent  => 'oops',             # Event to emit on errors.
  1056.     CloseEvent  => 'child_closed',     # Child closed all output.
  1057.  
  1058.     StdinEvent  => 'stdin',  # Event to emit when stdin is flushed to child.
  1059.     StdoutEvent => 'stdout', # Event to emit with child stdout information.
  1060.     StderrEvent => 'stderr', # Event to emit with child stderr information.
  1061.  
  1062.     # Specify different I/O formats.
  1063.     StdinFilter  => POE::Filter::Line->new(),   # Child accepts input as lines.
  1064.     StdoutFilter => POE::Filter::Stream->new(), # Child output is a stream.
  1065.     StderrFilter => POE::Filter::Line->new(),   # Child errors are lines.
  1066.  
  1067.     # Set StdinFilter and StdoutFilter together.
  1068.     StdioFilter => POE::Filter::Line->new(),    # Or some other filter.
  1069.  
  1070.     # Specify different I/O methods.
  1071.     StdinDriver  => POE::Driver::SysRW->new(),  # Defaults to SysRW.
  1072.     StdoutDriver => POE::Driver::SysRW->new(),  # Same.
  1073.     StderrDriver => POE::Driver::SysRW->new(),  # Same.
  1074.  
  1075.     # Set StdinDriver and StdoutDriver together.
  1076.     StdioDriver  => POE::Driver::SysRW->new(),
  1077.   );
  1078.  
  1079.   print "Unique wheel ID is  : ", $wheel->ID;
  1080.   print "Wheel's child PID is: ", $wheel->PID;
  1081.  
  1082.   # Send something to the child's STDIN.
  1083.   $wheel->put( 'input for the child' );
  1084.  
  1085.   # Kill the child.
  1086.   $wheel->kill();  # TERM by default
  1087.   $wheel->kill(9);
  1088.  
  1089. =head1 DESCRIPTION
  1090.  
  1091. Wheel::Run spawns child processes and establishes non-blocking, event
  1092. based communication with them.
  1093.  
  1094. =head1 PUBLIC METHODS
  1095.  
  1096. =over 2
  1097.  
  1098. =item new LOTS_OF_STUFF
  1099.  
  1100. new() creates a new Run wheel.  If successful, the new wheel
  1101. represents a child process and the input, output and error pipes that
  1102. speak with it.
  1103.  
  1104. new() accepts lots of stuff.  Each parameter is name/value pair.
  1105.  
  1106. =over 2
  1107.  
  1108. =item Conduit
  1109.  
  1110. C<Conduit> describes how Wheel::Run should talk with the child
  1111. process.  By default it will try various forms of inter-process
  1112. communication to build a pipe between the parent and child processes.
  1113. If a particular method is preferred, it can be set to "pipe",
  1114. "socketpair", or "inet".  It may also be set to "pty" if the child
  1115. process should have its own pseudo tty.
  1116.  
  1117. The reasons to define this parameter would be if you want to use
  1118. "pty", if the default pipe type doesn't work properly on your
  1119. system, or the default pipe type's performance is poor.
  1120.  
  1121. Pty conduits require the IO::Pty module.
  1122.  
  1123. =item Winsize
  1124.  
  1125. C<Winsize> is only valid for C<Conduit = "pty"> and used to set the
  1126. window size of the pty device.
  1127.  
  1128. The window size is given as an array reference.  The first element is
  1129. the number of lines, the second the number of columns. The third and
  1130. the fourth arguments are optional and specify the X and Y dimensions
  1131. in pixels.
  1132.  
  1133. =item CloseOnCall
  1134.  
  1135. C<CloseOnCall> emulates the close-on-exec feature for child processes
  1136. which are not started by exec().  When it is set to 1, all open file
  1137. handles whose descriptors are greater than $^F are closed in the child
  1138. process.  This is only effective when POE::Wheel::Run is called with a
  1139. code reference for its Program parameter.
  1140.  
  1141.   CloseOnCall => 1,
  1142.   Program => \&some_function,
  1143.  
  1144. CloseOnCall defaults to 0 (off) to remain compatible with existing
  1145. programs.
  1146.  
  1147. For more details, please the discussion of $^F in L<perlvar>.
  1148.  
  1149. =item StdioDriver
  1150.  
  1151. =item StdinDriver
  1152.  
  1153. =item StdoutDriver
  1154.  
  1155. =item StderrDriver
  1156.  
  1157. These parameters change the drivers for Wheel::Run.  The default
  1158. drivers are created internally with C<<POE::Driver::SysRW->new()>>.
  1159.  
  1160. C<StdioDriver> changes both C<StdinDriver> and C<StdoutDriver> at the
  1161. same time.
  1162.  
  1163. =item CloseEvent
  1164.  
  1165. =item ErrorEvent
  1166.  
  1167. =item StdinEvent
  1168.  
  1169. =item StdoutEvent
  1170.  
  1171. =item StderrEvent
  1172.  
  1173. C<CloseEvent> contains the name of an event to emit when the child
  1174. process closes all its output handles.  This is a consistent
  1175. notification that the child will not be sending any more output.  It
  1176. does not, however, signal that the client process has stopped
  1177. accepting input.
  1178.  
  1179. C<ErrorEvent> contains the name of an event to emit if something
  1180. fails.  It is optional and if omitted, the wheel will not notify its
  1181. session if any errors occur.  The event receives 5 parameters as
  1182. follows: ARG0 = the return value of syscall(), ARG1 = errno() - the
  1183. numeric value of the error generated, ARG2 = error() - a descriptive
  1184. for the given error, ARG3 = the wheel id, and ARG4 = the handle on
  1185. which the error ocurred (stdout, stderr, etc.)
  1186.  
  1187. Wheel::Run requires at least one of the following three events:
  1188.  
  1189. C<StdinEvent> contains the name of an event that Wheel::Run emits
  1190. whenever all its output has been flushed to the child process' STDIN
  1191. handle.
  1192.  
  1193. C<StdoutEvent> and C<StderrEvent> contain names of events that
  1194. Wheel::Run emits whenever the child process writes something to its
  1195. STDOUT or STDERR handles, respectively.
  1196.  
  1197. =item StdioFilter
  1198.  
  1199. =item StdinFilter
  1200.  
  1201. =item StdoutFilter
  1202.  
  1203. =item StderrFilter
  1204.  
  1205. C<StdioFilter> contains an instance of a POE::Filter subclass.  The
  1206. filter describes how the child process performs input and output.
  1207. C<Filter> will be used to describe the child's stdin and stdout
  1208. methods.  If stderr is also to be used, StderrFilter will need to be
  1209. specified separately.
  1210.  
  1211. C<Filter> is optional.  If left blank, it will default to an
  1212. instance of C<POE::Filter::Line->new(Literal => "\n");>
  1213.  
  1214. C<StdinFilter> and C<StdoutFilter> can be used instead of or in
  1215. addition to C<StdioFilter>.  They will override the default filter's
  1216. selection in situations where a process' input and output are in
  1217. different formats.
  1218.  
  1219. =item Group
  1220.  
  1221. C<Group> contains a numerical group ID that the child process should
  1222. run at.  This may not be meaningful on systems that have no concept of
  1223. group IDs.  The current process may need to run as root in order to
  1224. change group IDs.  Mileage varies considerably.
  1225.  
  1226. =item Priority
  1227.  
  1228. C<Priority> contains an offset from the current process's priority.
  1229. The child will be executed at the current priority plus the offset.
  1230. The priority offset may be negative, but the current process may need
  1231. to be running as root for that to work.
  1232.  
  1233. =item Program
  1234.  
  1235. C<Program> is the program to exec() once pipes and fork have been set
  1236. up.  C<Program>'s type determines how the program will be run.
  1237.  
  1238. If C<Program> holds a scalar, it will be executed as exec($scalar).
  1239. Shell metacharacters will be expanded in this form.
  1240.  
  1241. If C<Program> holds an array reference, it will executed as
  1242. exec(@$array).  This form of exec() doesn't expand shell
  1243. metacharacters.
  1244.  
  1245. If C<Program> holds a code reference, it will be called in the forked
  1246. child process, and then the child will exit.  This allows Wheel::Run
  1247. to fork off bits of long-running code which can accept STDIN input and
  1248. pass responses to STDOUT and/or STDERR.  Note, however, that POE's
  1249. services are effectively disabled in the child process.
  1250.  
  1251. L<perlfunc> has more information about exec() and the different ways
  1252. to call it.
  1253.  
  1254. Note: Do not call exit() explicitly when executing a subroutine.
  1255. POE::Wheel::Run takes special care to avoid object destructors and END
  1256. blocks in the child process, and calling exit() will thwart that.  You
  1257. may see "POE::Kernel's run() method was never called." or worse.
  1258.  
  1259. =item ProgramArgs => ARRAY
  1260.  
  1261. If specified, C<ProgramArgs> should refer to a list of parameters for
  1262. the program being run.
  1263.  
  1264.   my @parameters = qw(foo bar baz);  # will be passed to Program
  1265.   ProgramArgs => \@parameters;
  1266.  
  1267. =back
  1268.  
  1269. =item event EVENT_TYPE => EVENT_NAME, ...
  1270.  
  1271. event() changes the event that Wheel::Run emits when a certain type of
  1272. event occurs.  C<EVENT_TYPE> may be one of the event parameters in
  1273. Wheel::Run's constructor.
  1274.  
  1275.   $wheel->event( StdinEvent  => 'new-stdin-event',
  1276.                  StdoutEvent => 'new-stdout-event',
  1277.                );
  1278.  
  1279. =item put LIST
  1280.  
  1281. put() queues a LIST of different inputs for the child process.  They
  1282. will be flushed asynchronously once the current state returns.  Each
  1283. item in the LIST is processed according to the C<StdinFilter>.
  1284.  
  1285. =item get_stdin_filter
  1286.  
  1287. =item get_stdout_filter
  1288.  
  1289. =item get_stderr_filter
  1290.  
  1291. Get C<StdinFilter>, C<StdoutFilter>, or C<StderrFilter> respectively.
  1292.  
  1293. =item set_stdio_filter FILTER_REFERENCE
  1294.  
  1295. Set C<StdinFilter> and C<StdoutFilter> at once.
  1296.  
  1297. =item set_stdin_filter FILTER_REFERENCE
  1298.  
  1299. =item set_stdout_filter FILTER_REFERENCE
  1300.  
  1301. =item set_stderr_filter FILTER_REFERENCE
  1302.  
  1303. Set C<StdinFilter>, C<StdoutFilter>, or C<StderrFilter> respectively.
  1304.  
  1305. =item pause_stdout
  1306.  
  1307. =item pause_stderr
  1308.  
  1309. =item resume_stdout
  1310.  
  1311. =item resume_stderr
  1312.  
  1313. Pause or resume C<StdoutEvent> or C<StderrEvent> events.  By using
  1314. these methods a session can control the flow of Stdout and Stderr
  1315. events coming in from this child process.
  1316.  
  1317. =item shutdown_stdin
  1318.  
  1319. Closes the child process' STDIN and stops the wheel from reporting
  1320. StdinEvent.  It is extremely useful for running utilities that expect
  1321. to receive EOF on their standard inputs before they respond.
  1322.  
  1323. =item ID
  1324.  
  1325. Returns the wheel's unique ID, which is not the same as the child
  1326. process' ID.  Every event generated by Wheel::Run includes a wheel ID
  1327. so that it can be matched up with its generator.  This lets a single
  1328. session manage several wheels without becoming confused about which
  1329. one generated what event.
  1330.  
  1331. =item PID
  1332.  
  1333. Returns the child process' ID.  It's useful for matching up to SIGCHLD
  1334. events, which include child process IDs as well, so that wheels can be
  1335. destroyed properly when children exit.
  1336.  
  1337. =item kill SIGNAL
  1338.  
  1339. Sends a signal to the child process.  It's useful for processes which
  1340. tend to be reluctant to exit when their terminals are closed.
  1341.  
  1342. The kill() method will send SIGTERM if SIGNAL is undef or omitted.
  1343.  
  1344. =back
  1345.  
  1346. =head1 EVENTS AND PARAMETERS
  1347.  
  1348. =over 2
  1349.  
  1350. =item CloseEvent
  1351.  
  1352. CloseEvent contains the name of the event Wheel::Run emits whenever a
  1353. child process has closed all its output handles.  It signifies that
  1354. the child will not be sending more information.  In addition to the
  1355. usual POE parameters, each CloseEvent comes with one of its own:
  1356.  
  1357. C<ARG0> contains the wheel's unique ID.  This can be used to keep
  1358. several child processes separate when they're managed by the same
  1359. session.
  1360.  
  1361. A sample close event handler:
  1362.  
  1363.   sub close_state {
  1364.     my ($heap, $wheel_id) = @_[HEAP, ARG0];
  1365.  
  1366.     my $child = delete $heap->{child}->{$wheel_id};
  1367.     print "Child ", $child->PID, " has finished.\n";
  1368.   }
  1369.  
  1370. =item ErrorEvent
  1371.  
  1372. ErrorEvent contains the name of an event that Wheel::Run emits
  1373. whenever an error occurs.  Every error event comes with four
  1374. parameters:
  1375.  
  1376. C<ARG0> contains the name of the operation that failed.  It may be
  1377. 'read' or 'write' or 'fork' or 'exec' or something.  The actual values
  1378. aren't yet defined.  Note: This is not necessarily a function name.
  1379.  
  1380. C<ARG1> and C<ARG2> hold numeric and string values for C<$!>,
  1381. respectively.
  1382.  
  1383. C<ARG3> contains the wheel's unique ID.
  1384.  
  1385. C<ARG4> contains the name of the child filehandle that has the error.
  1386. It may be "STDIN", "STDOUT", or "STDERR".  The sense of C<ARG0> will
  1387. be the opposite of what you might normally expect for these handles.
  1388. For example, Wheel::Run will report a "read" error on "STDOUT" because
  1389. it tried to read data from that handle.
  1390.  
  1391. A sample error event handler:
  1392.  
  1393.   sub error_state {
  1394.     my ($operation, $errnum, $errstr, $wheel_id) = @_[ARG0..ARG3];
  1395.     warn "Wheel $wheel_id generated $operation error $errnum: $errstr\n";
  1396.   }
  1397.  
  1398. =item StdinEvent
  1399.  
  1400. StdinEvent contains the name of an event that Wheel::Run emits
  1401. whenever everything queued by its put() method has been flushed to the
  1402. child's STDIN handle.
  1403.  
  1404. StdinEvent's C<ARG0> parameter contains its wheel's unique ID.
  1405.  
  1406. =item StdoutEvent
  1407.  
  1408. =item StderrEvent
  1409.  
  1410. StdoutEvent and StderrEvent contain names for events that Wheel::Run
  1411. emits whenever the child process makes output.  StdoutEvent contains
  1412. information the child wrote to its STDOUT handle, and StderrEvent
  1413. includes whatever arrived from the child's STDERR handle.
  1414.  
  1415. Both of these events come with two parameters.  C<ARG0> contains the
  1416. information that the child wrote.  C<ARG1> holds the wheel's unique
  1417. ID.
  1418.  
  1419.   sub stdout_state {
  1420.     my ($heap, $input, $wheel_id) = @_[HEAP, ARG0, ARG1];
  1421.     print "Child process in wheel $wheel_id wrote to STDOUT: $input\n";
  1422.   }
  1423.  
  1424.   sub stderr_state {
  1425.     my ($heap, $input, $wheel_id) = @_[HEAP, ARG0, ARG1];
  1426.     print "Child process in wheel $wheel_id wrote to STDERR: $input\n";
  1427.   }
  1428.  
  1429. =back
  1430.  
  1431. =head1 TIPS AND TRICKS
  1432.  
  1433. One common task is scrubbing a child process' environment.  This
  1434. amounts to clearing the contents of %ENV and setting it up with some
  1435. known, secure values.
  1436.  
  1437. Environment scrubbing is easy when the child process is running a
  1438. subroutine, but it's not so easy---or at least not as intuitive---when
  1439. executing external programs.
  1440.  
  1441. The way we do it is to run a small subroutine in the child process
  1442. that performs the exec() call for us.
  1443.  
  1444.   Program => \&exec_with_scrubbed_env,
  1445.  
  1446.   sub exec_with_scrubbed_env {
  1447.     delete @ENV{keys @ENV};
  1448.     $ENV{PATH} = "/bin";
  1449.     exec(@program_and_args);
  1450.   }
  1451.  
  1452. That deletes everything from the environment, sets a simple, secure
  1453. PATH, and executes a program with its arguments.
  1454.  
  1455. =head1 SEE ALSO
  1456.  
  1457. POE::Wheel.
  1458.  
  1459. The SEE ALSO section in L<POE> contains a table of contents covering
  1460. the entire POE distribution.
  1461.  
  1462. =head1 BUGS
  1463.  
  1464. Wheel::Run's constructor doesn't emit proper events when it fails.
  1465. Instead, it just dies, carps or croaks.
  1466.  
  1467. Filter changing hasn't been implemented yet.  Let the author know if
  1468. it's needed.  Better yet, patch the file based on the code in
  1469. Wheel::ReadWrite.
  1470.  
  1471. Priority is a delta; there's no way to set it directly to some value.
  1472.  
  1473. User must be specified by UID.  It would be nice to support login
  1474. names.
  1475.  
  1476. Group must be specified by GID.  It would be nice to support group
  1477. names.
  1478.  
  1479. ActiveState Perl doesn't like this module one bit.
  1480.  
  1481. =head1 AUTHORS & COPYRIGHTS
  1482.  
  1483. Please see L<POE> for more information about authors and contributors.
  1484.  
  1485. =cut
  1486.