[comp.lang.perl] reading AND writing to processes

al@io.ee.pitt.edu (Alan Martello) (05/04/90)

I have a perl script which must rsh to another system and
run specific commands (depending on the result of querying the
system with other commands).  

The following works as expected:
   open (RSH_FH, "rsh othermachine ls |");

but is a little too clunky for my needs (I don't want an open
for each command).

Instead, I'd prefer something like the following:
    open (RSH_FH, "| rsh othermachine |");

That is, I want to read AND write to the same rsh process.  
For example, the first thing I need to do is to supply a password 
if logging in as a different user.

I tried minimal experimentation and couldn't get it to do
the desired thing... Perhaps a perl/shell wizard can shed
some light on the feasability of my endeavor.  I though about
trying to use forks, etc. but didn't try it.  Ideas?

*******************************************************************
       Alan R. Martello        Electrical Engineering Dept.
        al@ee.pitt.edu           University of Pittsburgh
*******************************************************************

henkp@ruuinf.cs.ruu.nl (Henk P. Penning) (05/04/90)

In article <7497@pitt.UUCP> al@io.ee.pitt.edu (Alan Martello) writes:

>Instead, I'd prefer something like the following:
>    open (RSH_FH, "| rsh othermachine |");
>That is, I want to read AND write to the same rsh process.  

Here is my solution.
Subroutine open2(READHANDLE,WRITEHANDLE,arg,arg,...) expects
names of a READHANDLE and a WRITEHANDLE (as strings).
It sets up pipes, forks, and calls exec(arg,arg,...) in the child.

The example should print the first few lines of the sorted passwd file.

				===  HenkP  ===

Henk P. Penning, Dept of Computer Science, Utrecht University.
Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands.
Telephone: +31-30-534106
e-mail   : henkp@cs.ruu.nl (uucp to hp4nl!ruuinf!henkp)
---------------------------------------------------
sub open2 # ( READHANDLE, WRITEHANDLE, argument(s) to exec() )
  { local($p1,$p2,@execParms) = @_ ;
    eval "pipe($p1,APPOUT)" || die "open2 can't create pipe $p1/APPOUT" ; 
    eval "pipe(APPIN,$p2)"  || die "open2 can't create pipe APPIN/$p2" ; 

    $open2Pid = fork ;

    if ( $open2Pid == 0 ) # CHILD
      { close($p1)              || die "child can't close $p1" ;
        close($p2)              || die "child can't close $p2" ;
        close(STDIN)            || die "child can't close STDIN" ;
        close(STDOUT)           || die "child can't close STDOUT" ;
        open(STDIN, "<&APPIN")  || die "child can't redirect STDIN" ;
        open(STDOUT,">&APPOUT") || die "child can't redirect STDOUT" ;
        close(APPIN)            || die "child can't close APPIN" ;
        close(APPOUT)           || die "child can't close APPOUT" ;
        exec(@execParms) ;
        die "open2 can't exec " . join(' ',@execParms) ;
      }
    else # PARENT
      { close(APPIN)  || die "open2 can\'t close APPIN" ;
        close(APPOUT) || die "open2 can\'t close APPOUT" ;
      }
  }

sub flush # ( FILEHANDLE )
  { $oldselect = select($_[0]) ;
    $oldpipe = $| ; $| = 1 ; print "" ; $| = $oldpipe ;
    select($oldselect) ;
  }

$INP = 'INP' ; $OUT = 'OUT' ;

&open2($INP,$OUT,'sort | head') ;

open(PW,'/etc/passwd') || die "can't open /etc/passwd\n" ;
while ($_ = <PW> ) { print OUT "out> $_" ; }
close(OUT) || die "can't close OUT\n" ;

while ( $_ = <INP> )
  { print "<in $_" ; }

close(INP) || die "can't close INP\n" ;
---------------------------------------------------
-- 
Henk P. Penning, Dept of Computer Science, Utrecht University.
Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands.
Telephone: +31-30-534106
e-mail   : henkp@cs.ruu.nl (uucp to hp4nl!ruuinf!henkp)