Article 9920 of comp.lang.perl:
Xref: feenix.metronet.com comp.lang.perl:9920 comp.sys.sun.apps:4147 comp.sys.sun.misc:7363
Path: feenix.metronet.com!news.ecn.bgu.edu!usenet.ins.cwru.edu!howland.reston.ans.net!cs.utexas.edu!swrinde!sgiblab!bridge2!alantec!alantec!paul
From: [email protected] (G. Paul Ziemba)
Newsgroups: comp.lang.perl,comp.sys.sun.apps,comp.sys.sun.misc
Subject: Re: Problem with passwd
Message-ID: <[email protected]>
Date: 18 Jan 94 23:31:51 GMT
References: <[email protected]>
Organization: Alantec, San Jose, CA
Lines: 111
NNTP-Posting-Host: alantec.alantec.com

[email protected] (Dale Worley) writes:

>(All of this is using Perl 4.35 under SunOS 4.1.1.)

>[chat2 doesn't seem to give exec-ed program a tty]

>says "Input not a tty".  My guess is that passwd is doing some fairly
>sophisticated checks to see that it is being run in the "ordinary" way.
>However, it's not impossible to fake it out -- I can run passwd in a shell
>window under Gnu Emacs quite easily.  So what is going wrong?

>Does anyone know what I'm missing?  What changes to chat2 will solve this
>little problem?

Interestingly (to me, anyway), I encountered this very same problem
last week.  I am running perl 4.0.36 on SunOS 4.1.2.

At first I thought, surely chat2 is doing the right thing. However,
I open_proc-ed "cat /dev/tty", and cat complained about "no tty".

I looked at the chat2.pl code, and I could not understand why the
slave side of the pty did not become the controlling terminal.
However, I did make a one-line change to chat2'open_proc (below)
that seems to fix it.

I would dearly love for someone more knowledgeable to explain why
chat2 was not doing the right thing, and whether my change is an
appropriate one.

~!paul


## chat.pl: chat with a server
## V2.01.alpha.7 91/06/16
## Randal L. Schwartz

[deleted]

## $handle = &chat'open_proc("command","arg1","arg2",...);
## opens a /bin/sh on a pseudo-tty

sub open_proc { ## public
       local(@cmd) = @_;

       *S = ++$next;
       local(*TTY) = "__TTY" . time;
       local($pty,$tty) = &_getpty(S,TTY);
       die "Cannot find a new pty" unless defined $pty;
       local($pid) = fork;
       die "Cannot fork: $!" unless defined $pid;
       unless ($pid) {
               close STDIN; close STDOUT; close STDERR;
               setpgrp(0,$$);
               if (open(DEVTTY, "/dev/tty")) {
                   ioctl(DEVTTY,0x20007471,0);         # XXX s/b &TIOCNOTTY
                   close DEVTTY;
               }
               open(STDIN,"<&TTY");
               open(STDOUT,">&TTY");
               open(STDERR,">&STDOUT");
               die "Oops" unless fileno(STDERR) == 2;  # sanity
               close(S);



               ##################################################
               # add this to force controlling terminal
               ##################################################
               close DEVTTY if (open(DEVTTY, "+>$tty")); # force ctl term
               ##################################################
               ##################################################



               exec @cmd;
               die "Cannot exec @cmd: $!";
       }
       close(TTY);
       $next; # return symbol for switcharound
}

# ($pty,$tty) = $chat'_getpty(PTY,TTY):
# internal procedure to get the next available pty.
# opens pty on handle PTY, and matching tty on handle TTY.
# returns undef if can't find a pty.

sub _getpty { ## private
       local($_PTY,$_TTY) = @_;
       $_PTY =~ s/^([^']+)$/(caller)[$[]."'".$1/e;
       $_TTY =~ s/^([^']+)$/(caller)[$[]."'".$1/e;
       local($pty,$tty);
       for $bank (112..127) {
               next unless -e sprintf("/dev/pty%c0", $bank);
               for $unit (48..57) {
                       $pty = sprintf("/dev/pty%c%c", $bank, $unit);
                       open($_PTY,"+>$pty") || next;
                       select((select($_PTY), $| = 1)[0]);
                       ($tty = $pty) =~ s/pty/tty/;
                       open($_TTY,"+>$tty") || next;
                       select((select($_TTY), $| = 1)[0]);
                       system "stty nl>$tty";
                       return ($pty,$tty);
               }
       }
       undef;
}
--
Paul Ziemba, software archaeologist: [email protected]   alantec!paul
   "The reasonable man adapts himself to the world; the unreasonable one
persists in trying to adapt the world to himself. Therefore, all progress
depends on the unreasonable man." - George Bernard Shaw