2013-04-20 2 views
1

Когда я ввожу материал в свою программу, похоже, что никакой символ, как 0x4, не указывает на EOF.Термин :: ReadKey, неблокирующее чтение в сыром режиме: обнаружение EOF?

$ echo "abc" | map 'cat' 
saw a: \x61 
saw b: \x62 
saw c: \x63 
saw 
: \x0A 
zzzbc 
^C 

Я должен нажать Ctrl + C, чтобы выйти, но я не уверен, что действует Ctrl + C. Вероятно, оболочка отправляет SIGINT в конвейер? Я не знаю, как работают трубопроводы на этом уровне.

Вот моя программа map:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use IO::Pty::Easy; 
use Term::ReadKey; 
use Encode; 

$#ARGV % 2 and die "Odd number of args required.\n"; 

if ($#ARGV == -1) { 
    warn ("No args provided. A command must be specified.\n"); 
    exit 1; 
} 

# be sure to enter the command as a string 
my %mapping = @ARGV[[email protected]]; 

my $interactive = -t STDIN; 

# my %mapping = @ARGV; 
# my @mapkeys = keys %mapping; 

# warn @mapkeys; 
if ($interactive) { 
    print "Spawning command in pty: @ARGV\n" 
    # print "\nContinue? (y/n)"; 
    # my $y_n; 
    # while (($y_n = <STDIN>) !~ /^(y|n)$/) { 
    #  print '(y/n)'; 
    # } 
    # exit if $y_n eq "n\n"; 
} 

my $pty = IO::Pty::Easy->new(); 
my $spawnret = $pty->spawn("@ARGV")."\n"; 

print STDERR "Spawning has failed: @ARGV\n" if !$spawnret; 

ReadMode 4; 
END { 
    ReadMode 0; # Reset tty mode before exiting 
} 

my $i = undef; 
my $j = 0; 

{ 
    local $| = 1; 
    while (1) { 
     myread(); 

     # responsive to key input, and pty output may be behind by 50ms 
     my $key = ReadKey(0.05); 
     # last if !defined($key) || !$key; 
     if (defined($key)) { 
      my $code = ord($key); # this byte is... 
      if ($interactive and $code == 4) { 
       # User types Ctrl+D 
       print STDERR "Saw ^D from term, embarking on filicide with TERM signal\n"; 
       $pty->kill("TERM", 0); # blocks till death of child 
       myread(); 
       $pty->close(); 
       last; 
      } 
      printf("saw %s: \\x%02X\n", $key, $code); 

      # echo translated input to pty 
      if ($key eq "a") { 
       $pty->write("zzz"); # print 'Saw "a", wrote "zzz" to pty'; 
      } else { 
       $pty->write($key); # print "Wrote to pty: $key"; 
      } 
     } 
    } 
} 

sub myread { 
    # read out pty's activity to echo to stdout 
    my $from_pty = $pty->read(0); 
    if (defined($from_pty)) { 
     if ($from_pty) { 
      # print "read from pty -->$from_pty<--\n"; 
      print $from_pty; 
     } else { 
      if ($from_pty eq '') { 
       # empty means EOF means pty has exited, so I exit because my fate is sealed 
       print STDERR "Got back from pty EOF, quitting\n" if $interactive; 
       $pty->close(); 
       last; 
      } 
     } 
    } 
} 

Это объясняет, почему он произвел "zzzbc".

Теперь мой вопрос: как я могу получить map, чтобы узнать о echo "abc", достигнув конца ввода? ср echo "abc" | cat выполняет самостоятельно. ReadKey, похоже, не предоставляет API для определения этой ситуации.

Точно так же я не уверен, как сделать то же самое, чтобы пройти по EOF ребенку в pty. Я думаю, что это может вызвать проблемы, когда команда состоит в том, чтобы писать в файл или что-то в этом роде, потому что EOF против отправки сигнала уничтожения - это разница между написанием файла правильно и не выходящим чисто.

ответ

0

Попробуйте прочитать STDIN, а не этот объект $ pty. Труба, которую вы создаете через оболочку, передает данные в дескриптор файла STDIN 0, который в perl является вашим дескриптором.

$ pty, я предполагаю, что это ваш терминал. Вот почему сценарий просто висит (я думаю).

Смежные вопросы