Perl IPC::Run3: How to emulate a pty for stdin to child process?

天涯浪子 提交于 2019-12-08 02:43:36

问题


This is a follow up question to IPC::Open3 and determining if child is waiting for input though they admittedly are not related.

Take the following sample code:

use strict;
use warnings;
use IPC::Run3;

sub foo
{
    my $cmd = shift;
    my $CH_IN = "foo\n";
    run3($cmd, \$CH_IN, my $CH_OUT, my $CH_ERR);
    return 1;
}
my @LIST = ( 'command','arg1','arg2','arg3' );
foo \@LIST;

For the above code command is another perl script. The child script calls who -m to find who owns stdin from the terminal, which is intended to be used in case the child or parent script is called using root or another generic system user.

The error I get from the child when called by the parent is as follows.

Use of uninitialized value in split at child.pl line 354.
WHOAMI is undef

Child code below.

Code around line 354:

# Function Name:        'determine_user'
# Function Inputs:      'Optional Scalar: Username to login as'
# Function Returns:     'If username is provided: Scalar: the username provided, If username is not provided: The output of who -m'
# Function Description: 'Figures out the user to login as'
sub determine_user
{
    my $USER = shift;
    if (!defined $USER)
    {
        my $WHOAMI;
        open my $WHOPROC, q{-|}, 'who -m'                   or die "Unable to open 'who -m' for output.\n";
        $WHOAMI=<$WHOPROC>;
        close $WHOPROC                                      or die "Unable to close 'who -m'.\n";
        $USER       = split m{[\s]+}xms, $WHOAMI          or die "WHOAMI is undef\n";    # This is line 354
    }

    chomp $USER;

    return $USER;
}

The code above works just fine when I call the child script from the command line, but since who -m is trying to see who owns stdin of the terminal and the terminal has been replaced by the parent script, I believe I need to find a way to call who -m with an emulated pty when running from the parent. Whether that's by modifying the child or the parent or both doesn't matter, as I can modify both.

So my question is: how can I run the child inside of the parent and still rely on the output of who -m being fed to the child?

EDIT: ikegami has provided the best solution in the comments of his answer. It does not answer the question, but it does solve my problem.

My ssh daemon sets env var SSH_TTY, so you could use perl -MFile::stat -E'say scalar(getpwuid(stat($ENV{SSH_TTY})->uid))'. Default to scalar(getpwuid($>)) if it's not set.


回答1:


who -m specifically gives information about the terminal connected to its stdin.

-m     only hostname and user associated with stdin

You've replaced the terminal, so you can't obtain information from it.

$ who -m
ikegami  pts/1        ...

$ who -m </dev/null

$

You could drop the -m and use just who.

$ who </dev/null
ikegami  pts/1        ...

Alternatively, you could use $ENV{USER} or getpwuid($>) (the name of the user as which the process is executing) instead.



来源:https://stackoverflow.com/questions/41475421/perl-ipcrun3-how-to-emulate-a-pty-for-stdin-to-child-process

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!