1*0Sstevel@tonic-gate#!./perl -w 2*0Sstevel@tonic-gate 3*0Sstevel@tonic-gateBEGIN { 4*0Sstevel@tonic-gate chdir 't' if -d 't'; 5*0Sstevel@tonic-gate @INC = '../lib'; 6*0Sstevel@tonic-gate require Config; import Config; 7*0Sstevel@tonic-gate if (!$Config{'d_fork'} 8*0Sstevel@tonic-gate # open2/3 supported on win32 (but not Borland due to CRT bugs) 9*0Sstevel@tonic-gate && (($^O ne 'MSWin32' && $^O ne 'NetWare') || $Config{'cc'} =~ /^bcc/i)) 10*0Sstevel@tonic-gate { 11*0Sstevel@tonic-gate print "1..0\n"; 12*0Sstevel@tonic-gate exit 0; 13*0Sstevel@tonic-gate } 14*0Sstevel@tonic-gate # make warnings fatal 15*0Sstevel@tonic-gate $SIG{__WARN__} = sub { die @_ }; 16*0Sstevel@tonic-gate} 17*0Sstevel@tonic-gate 18*0Sstevel@tonic-gateuse strict; 19*0Sstevel@tonic-gateuse IO::Handle; 20*0Sstevel@tonic-gateuse IPC::Open3; 21*0Sstevel@tonic-gate#require 'open3.pl'; use subs 'open3'; 22*0Sstevel@tonic-gate 23*0Sstevel@tonic-gatemy $perl = $^X; 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gatesub ok { 26*0Sstevel@tonic-gate my ($n, $result, $info) = @_; 27*0Sstevel@tonic-gate if ($result) { 28*0Sstevel@tonic-gate print "ok $n\n"; 29*0Sstevel@tonic-gate } 30*0Sstevel@tonic-gate else { 31*0Sstevel@tonic-gate print "not ok $n\n"; 32*0Sstevel@tonic-gate print "# $info\n" if $info; 33*0Sstevel@tonic-gate } 34*0Sstevel@tonic-gate} 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gatesub cmd_line { 37*0Sstevel@tonic-gate if ($^O eq 'MSWin32' || $^O eq 'NetWare') { 38*0Sstevel@tonic-gate my $cmd = shift; 39*0Sstevel@tonic-gate $cmd =~ tr/\r\n//d; 40*0Sstevel@tonic-gate $cmd =~ s/"/\\"/g; 41*0Sstevel@tonic-gate return qq/"$cmd"/; 42*0Sstevel@tonic-gate } 43*0Sstevel@tonic-gate else { 44*0Sstevel@tonic-gate return $_[0]; 45*0Sstevel@tonic-gate } 46*0Sstevel@tonic-gate} 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gatemy ($pid, $reaped_pid); 49*0Sstevel@tonic-gateSTDOUT->autoflush; 50*0Sstevel@tonic-gateSTDERR->autoflush; 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gateprint "1..22\n"; 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate# basic 55*0Sstevel@tonic-gateok 1, $pid = open3 'WRITE', 'READ', 'ERROR', $perl, '-e', cmd_line(<<'EOF'); 56*0Sstevel@tonic-gate $| = 1; 57*0Sstevel@tonic-gate print scalar <STDIN>; 58*0Sstevel@tonic-gate print STDERR "hi error\n"; 59*0Sstevel@tonic-gateEOF 60*0Sstevel@tonic-gateok 2, print WRITE "hi kid\n"; 61*0Sstevel@tonic-gateok 3, <READ> =~ /^hi kid\r?\n$/; 62*0Sstevel@tonic-gateok 4, <ERROR> =~ /^hi error\r?\n$/; 63*0Sstevel@tonic-gateok 5, close(WRITE), $!; 64*0Sstevel@tonic-gateok 6, close(READ), $!; 65*0Sstevel@tonic-gateok 7, close(ERROR), $!; 66*0Sstevel@tonic-gate$reaped_pid = waitpid $pid, 0; 67*0Sstevel@tonic-gateok 8, $reaped_pid == $pid, $reaped_pid; 68*0Sstevel@tonic-gateok 9, $? == 0, $?; 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate# read and error together, both named 71*0Sstevel@tonic-gate$pid = open3 'WRITE', 'READ', 'READ', $perl, '-e', cmd_line(<<'EOF'); 72*0Sstevel@tonic-gate $| = 1; 73*0Sstevel@tonic-gate print scalar <STDIN>; 74*0Sstevel@tonic-gate print STDERR scalar <STDIN>; 75*0Sstevel@tonic-gateEOF 76*0Sstevel@tonic-gateprint WRITE "ok 10\n"; 77*0Sstevel@tonic-gateprint scalar <READ>; 78*0Sstevel@tonic-gateprint WRITE "ok 11\n"; 79*0Sstevel@tonic-gateprint scalar <READ>; 80*0Sstevel@tonic-gatewaitpid $pid, 0; 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate# read and error together, error empty 83*0Sstevel@tonic-gate$pid = open3 'WRITE', 'READ', '', $perl, '-e', cmd_line(<<'EOF'); 84*0Sstevel@tonic-gate $| = 1; 85*0Sstevel@tonic-gate print scalar <STDIN>; 86*0Sstevel@tonic-gate print STDERR scalar <STDIN>; 87*0Sstevel@tonic-gateEOF 88*0Sstevel@tonic-gateprint WRITE "ok 12\n"; 89*0Sstevel@tonic-gateprint scalar <READ>; 90*0Sstevel@tonic-gateprint WRITE "ok 13\n"; 91*0Sstevel@tonic-gateprint scalar <READ>; 92*0Sstevel@tonic-gatewaitpid $pid, 0; 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate# dup writer 95*0Sstevel@tonic-gateok 14, pipe PIPE_READ, PIPE_WRITE; 96*0Sstevel@tonic-gate$pid = open3 '<&PIPE_READ', 'READ', '', 97*0Sstevel@tonic-gate $perl, '-e', cmd_line('print scalar <STDIN>'); 98*0Sstevel@tonic-gateclose PIPE_READ; 99*0Sstevel@tonic-gateprint PIPE_WRITE "ok 15\n"; 100*0Sstevel@tonic-gateclose PIPE_WRITE; 101*0Sstevel@tonic-gateprint scalar <READ>; 102*0Sstevel@tonic-gatewaitpid $pid, 0; 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate# dup reader 105*0Sstevel@tonic-gate$pid = open3 'WRITE', '>&STDOUT', 'ERROR', 106*0Sstevel@tonic-gate $perl, '-e', cmd_line('print scalar <STDIN>'); 107*0Sstevel@tonic-gateprint WRITE "ok 16\n"; 108*0Sstevel@tonic-gatewaitpid $pid, 0; 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate# dup error: This particular case, duping stderr onto the existing 111*0Sstevel@tonic-gate# stdout but putting stdout somewhere else, is a good case because it 112*0Sstevel@tonic-gate# used not to work. 113*0Sstevel@tonic-gate$pid = open3 'WRITE', 'READ', '>&STDOUT', 114*0Sstevel@tonic-gate $perl, '-e', cmd_line('print STDERR scalar <STDIN>'); 115*0Sstevel@tonic-gateprint WRITE "ok 17\n"; 116*0Sstevel@tonic-gatewaitpid $pid, 0; 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate# dup reader and error together, both named 119*0Sstevel@tonic-gate$pid = open3 'WRITE', '>&STDOUT', '>&STDOUT', $perl, '-e', cmd_line(<<'EOF'); 120*0Sstevel@tonic-gate $| = 1; 121*0Sstevel@tonic-gate print STDOUT scalar <STDIN>; 122*0Sstevel@tonic-gate print STDERR scalar <STDIN>; 123*0Sstevel@tonic-gateEOF 124*0Sstevel@tonic-gateprint WRITE "ok 18\n"; 125*0Sstevel@tonic-gateprint WRITE "ok 19\n"; 126*0Sstevel@tonic-gatewaitpid $pid, 0; 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate# dup reader and error together, error empty 129*0Sstevel@tonic-gate$pid = open3 'WRITE', '>&STDOUT', '', $perl, '-e', cmd_line(<<'EOF'); 130*0Sstevel@tonic-gate $| = 1; 131*0Sstevel@tonic-gate print STDOUT scalar <STDIN>; 132*0Sstevel@tonic-gate print STDERR scalar <STDIN>; 133*0Sstevel@tonic-gateEOF 134*0Sstevel@tonic-gateprint WRITE "ok 20\n"; 135*0Sstevel@tonic-gateprint WRITE "ok 21\n"; 136*0Sstevel@tonic-gatewaitpid $pid, 0; 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate# command line in single parameter variant of open3 139*0Sstevel@tonic-gate# for understanding of Config{'sh'} test see exec description in camel book 140*0Sstevel@tonic-gatemy $cmd = 'print(scalar(<STDIN>))'; 141*0Sstevel@tonic-gate$cmd = $Config{'sh'} =~ /sh/ ? "'$cmd'" : cmd_line($cmd); 142*0Sstevel@tonic-gateeval{$pid = open3 'WRITE', '>&STDOUT', 'ERROR', "$perl -e " . $cmd; }; 143*0Sstevel@tonic-gateif ($@) { 144*0Sstevel@tonic-gate print "error $@\n"; 145*0Sstevel@tonic-gate print "not ok 22\n"; 146*0Sstevel@tonic-gate} 147*0Sstevel@tonic-gateelse { 148*0Sstevel@tonic-gate print WRITE "ok 22\n"; 149*0Sstevel@tonic-gate waitpid $pid, 0; 150*0Sstevel@tonic-gate} 151