[comp.lang.perl] perl and pttys

peebles@mips.COM (Andrew Peebles) (03/16/90)

Why can't I seem to run perl attached to the slave side of a psuedo tty?
I have a program that creates a ptty, and fork/execs a perl script with
its stdin, stdout, and stderr duped to the slave half of the ptty.
My wish is to make the perl script think its getting input from stdin
and producing output on stdout, when its this parent process that is
doing the work.

Perl seems to be doing something to its stdin and stdout file descriptors
that prevents such control.  Anyone done this sort of thing before?  How?


-- 
Andrew Peebles
{ames,prls,pyramid,decwrl}!mips!peebles  or  peebles@mips.com 
MIPS Computer Systems, 930 Arques, Sunnyvale, CA 94086, (408) 991-0443
"quote"

hakanson@ogicse.ogi.edu (Marion Hakanson) (03/17/90)

It's not exactly what you described, but should get you started.  This
must be the third or fourth time I've posted this fragment.  PTY's are
tricky, even if you aren't using Perl.  If you want the middle of the
"pipeline" to be a Perl routine, just replace the "exec 'tr'..." with
your code.

=============ptytst5.pl===========
#!/usr/bin/perl
# Pseudo-tty test program -- 89/12/01
#   Marion Hakanson (hakanson@cse.ogi.edu)
#   Oregon Graduate Institute of Science and Technology

do 'getpty.pl';
die "$@, aborted" if $@;

$MAST = 'MASTER';
$SLAV = 'SLAVE';
($mast,$slav) = do getpty($MAST,$SLAV);
print STDERR "getpty returns '$mast','$slav'\n";
die 'Cannot get pty, aborted' if ($mast eq '');

if ( fork ) {			# parent
  close($SLAV);		# not needed


  if ( fork ) { 	# still parent
    open(MASTOUT, "+>&$MAST") || die "Cannot dup $MAST to MASTOUT, aborted";
    close($MAST);
    select(MASTOUT); $| = 1;
    select(STDOUT); $| = 1;

    for ($i=0; $i<10; $i++ ) {
      print MASTOUT "LINE out $i\n" || die "Cannot print to $mast, aborted";
      sleep(1);
    }
    exit(0);
  } else {		# child 2
    open(MASTIN, "+>&$MAST") || die "Cannot dup $MAST to MASTIN, aborted";
    close($MAST);

    while ($mastin = <MASTIN>) {
      print STDOUT "$$: $mastin";
    }
    exit(0);
  }
} else {				# child 1
  close($MAST);	# not needed

  open(STDOUT, "+>&$SLAV") || die "Cannot dup $SLAV to STDOUT, aborted";
  open(STDIN, "+>&$SLAV") || die "Cannot dup $SLAV to STDIN, aborted";
  close($SLAV);

  select(STDOUT); $| = 1;

  exec ('tr','A-Z','a-z') || die "Cannot start 'tr', aborted";
}
=============end of ptytst5.pl===========

=============getpty.pl==========
#
# $Id: getpty.pl,v 1.3 90/01/02 17:18:56 hakanson Exp $
#
# Perl subroutine to allocate a free pseudo-tty (master/slave pair).
#   Marion Hakanson (hakanson@cse.ogi.edu)
#   Oregon Graduate Institute of Science and Technology

sub getpty {

  local ($MASTER,$SLAVE) = @_;
  local ($master,$slave);
  
  $master = '';
  $slave = '';

  pty: while ( </dev/pty*> ) {
#    print STDERR "trying '$_'\n";
    $master = $_;
    unless ( open($MASTER,"+>$master") ) {
#      print STDERR "open failed: $master\n";
      $master = '';
      next pty;
    }
    
    s/pty/tty/;
    $slave = $_;
    last pty if ( open($SLAVE,"+>$slave") );

#    print STDERR "open failed: $slave\n";
    close($MASTER);
    $master = '';
    $slave = '';
  }

#  print STDERR "getpty returning '$master','$slave'\n";

  ($master,$slave);
}
=============end of getpty.pl==========

-- 
Marion Hakanson         Domain: hakanson@cse.ogi.edu
                        UUCP  : {hp-pcd,tektronix}!ogicse!hakanson

peebles@ling.Berkeley.EDU (Andrew Peebles) (03/17/90)

> 
> It's not exactly what you described, but should get you started.  This
> must be the third or fourth time I've posted this fragment.  PTY's are
> tricky, even if you aren't using Perl.  If you want the middle of the
> "pipeline" to be a Perl routine, just replace the "exec 'tr'..." with
> your code.
> 
> -- 
> Marion Hakanson         Domain: hakanson@cse.ogi.edu
>                         UUCP  : {hp-pcd,tektronix}!ogicse!hakanson

Nice code, I'll use it elsewhere, but this does not really address my
particular problem.  I don't have access to the parent's code (I do
but I don't want to have to) to play w/ its ptys.

Since emacs uses a pty when you have an emacs shell, you can't (or at
least I can't) run a perl script from w/in an emacs shell.  This
behavior is what I'm asking about, i.e. can YOU run a perl script
from w/in an emacs shell?  Can you run `perl -d' on this same script
from w/in an emacs shell?


Andrew Peebles
{ames,prls,pyramid,decwrl}!mips!peebles  or  peebles@mips.com 
MIPS Computer Systems, 930 Arques, Sunnyvale, CA 94086, (408) 991-0443
"quote"

inc@tc.fluke.COM (Gary Benson) (03/20/90)

The question was raised about using perl-d inside emacs.

I thought I had a way, but I don't. I regularly run perl scripts on emacs
buffers, and it works really slick. I set a mark, advance to the area in
question, and fast-filter-region {the script}. This works for the stuff I
normally do, but when I set the -d, whoo-boy! I got knocked into the 0-zone.

It also fails if I set up a shell internal to emacs. I was hoping the debug
messages would go to the shell window, but alas no. STDOUT it is, and I am
not sufficiently emacs conversant to change that. I suppose one ramification
is that any perl script that is talking to STDOUT will fail inside emacs.
-- 
Gary Benson    -=[ S M I L E R ]=-   -_-_-_-inc@fluke.tc.com_-_-_-_-_-_-_-_-_-

The most evident characteristic of God is an inordinate fondness for beetles.
                                                             -J.B.S. Haldane

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (03/20/90)

In article <1990Mar19.235021.19961@tc.fluke.COM> inc@tc.fluke.COM (Gary Benson) writes:
: The question was raised about using perl-d inside emacs.
: 
: I thought I had a way, but I don't. I regularly run perl scripts on emacs
: buffers, and it works really slick. I set a mark, advance to the area in
: question, and fast-filter-region {the script}. This works for the stuff I
: normally do, but when I set the -d, whoo-boy! I got knocked into the 0-zone.
: 
: It also fails if I set up a shell internal to emacs. I was hoping the debug
: messages would go to the shell window, but alas no. STDOUT it is, and I am
: not sufficiently emacs conversant to change that. I suppose one ramification
: is that any perl script that is talking to STDOUT will fail inside emacs.

Is the problem simply that perldb.pl can't open /dev/tty?  There are two
lines that say

open(IN,"/dev/tty");            # so we don't dingle stdin
open(OUT,">/dev/tty");  # so we don't dongle stdout

Try changing them to

open(IN, "</dev/tty") || open(IN, "<&STDIN");	# so we don't dingle stdin
open(OUT,">/dev/tty") || open(OUT,">&STDOUT");	# so we don't dongle stdout

and see if that makes any difference.

Larry