- WAIT: for (;;) {
- my $missing = 0;
- KID: for my $kid (keys %KIDMAP) {
- my ($s, $what) = @{$KIDMAP{$kid}};
- next KID unless $kid == $s->{"_sshkid"};
- if (-S $s->{"_ssh_master"}) {
- inform " found socket from `$s->{_name}'";
- } else {
- inform " no socket yet from `$s->{_name}'";
- $missing = 1;
+ ## Collect up all the `stdout' pipes.
+ my %fd = ();
+ SETUP: for my $s (values %S) {
+ next SETUP unless $s->{"_sshkid"};
+ my $fd = fileno $s->{"_ssh_stdout"};
+ vec($rfd_in, $fd, 1) = 1;
+ $fd{$fd} = [$s->{"_ssh_stdout"}, $s];
+ }
+ unless (%fd) {
+ inform "no SSH tunnels to start";
+ return;
+ }
+
+ ## Wait for each of them to become readable, and try to read a thing.
+ ## Either we'll get a byte or EOF; either means that the respective tunnel
+ ## is as ready as it's ever going to be.
+ inform "waiting for SSH tunnels to start...";
+ my $nbad = 0;
+ SELECT: while (%fd) {
+ my ($n, $t) = select my $rfd_out = $rfd_in, undef, undef, undef;
+ if ($n >= 0) { }
+ elsif ($! == EINTR) { next SELECT; }
+ else { sysfail "select failed: $!"; }
+ FD: for my $fd (keys %fd) {
+ next FD unless vec $rfd_out, $fd, 1;
+ my ($sk, $s) = @{$fd{$fd}};
+ my $n = sysread $sk, my $hunoz, 128;
+ if (defined $n) {
+ vec($rfd_in, $fd, 1) = 0;
+ if ($n) { inform " tunnel to $s->{remote} started ok"; }
+ else { inform " tunnel to $s->{remote} FAILED"; $nbad++; }
+ delete $fd{$fd};
+ } elsif ($! != EAGAIN && $! != EWOULDBLOCK) {
+ sysfail "failed to read from pipe: $!";