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: paul@alantec.com (G. Paul Ziemba)
Newsgroups: comp.lang.perl,comp.sys.sun.apps,comp.sys.sun.misc
Subject: Re: Problem with passwd
Message-ID: <paul.758935911@alantec.alantec.com>
Date: 18 Jan 94 23:31:51 GMT
References: <2hh6n7$8h1@village.com>
Organization: Alantec, San Jose, CA
Lines: 111
NNTP-Posting-Host: alantec.alantec.com

worley@village.com (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: paul@alantec.com	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


