use strict; use warnings; use IO::Handle qw( ); # For autoflush. use IO::Select qw( ); use IPC::Open3 qw( open3 ); use Symbol qw( gensym ); use constant BLK_SIZE => 64*1024; my $pid = open3( my $stdin_fh = gensym(), my $stdout_fh = gensym(), my $stderr_fh = gensym(), 'server.pl', ); $stdin_fh->autoflush(1); my $stdin_buf = ''; my $stdout_buf = ''; my $stderr_buf = ''; my $writers = IO::Select->new(); my $readers = IO::Select->new($stdout_fh, $stderr_fh); my %answers = ( "What is your name?" => 'ikegami', "What is your mission?" => 'To become the King of Halloween', "What is your favorite color?" => 'orange', ); while ($readers->count()) { my ($ready_readers, $ready_writers) = IO::Select::select($readers, $writers, undef); foreach my $fh (@$ready_readers) { if ($fh == $stdout_fh) { my $rv = sysread($fh, $stdout_buf, BLK_SIZE, length($stdout_buf)); if (!defined($rv)) { $readers->remove($fh); # ...[ Do something in response to error from sysread. ]... } elsif (!$rv) { $readers->remove($fh); # ...[ Do something in response to EOF from sysread. ]... } else { while ($stdout_buf =~ s/(.*)\n//) { my $query = $1; if ($query =~ /Have a nice day!\z/) { $readers->remove($fh); print("$query\n"); } elsif ($answers{$query}) { $stdin_buf .= "$answers{$query}\n"; $writers->add($stdin_fh); } else { # ...[ Do something with unrecognised output from STDIN. ]... } } } } if ($fh == $stderr_fh) { my $rv = sysread($fh, $stderr_buf, BLK_SIZE, length($stderr_buf)); if (!defined($rv)) { $readers->remove($fh); # ...[ Do something in response to error from sysread. ]... } elsif (!$rv) { $readers->remove($fh); # ...[ Do something in response to EOF from sysread. ]... } else { # ...[ Do something in response to output to STDERR. ]... } } } foreach my $fh (@$ready_writers) { if (length($stdin_buf)) { # It's only safe to send one bytes unless you # somehow query the system to find otherwise. print($stdin_fh substr($stdin_buf, 0, 1, '')); # ...[ Do something if print returned an error. ]... } if (!length($stdin_buf)) { $writers->remove($fh); } } } waitpid($pid, 0); # ...[ Do something if waitpid returned an error. ]...