Как я могу по желанию использовать Win32 :: Console и его константы кроссплатформенным способом? - PullRequest
0 голосов
/ 03 февраля 2012

Начнем с того, что я работаю с Perl v5.8.4, и у меня нет возможности обновить Perl или установить Term::ReadKey или IO::Prompt (или что-то, кроме того, что находится в Core), поэтому, пожалуйста, примите этопри ответе / комментировании.

Я пытаюсь написать полностью автономный скрипт Perl, который (помимо прочего) запрашивает пароль.Он должен быть кросс-платформенным, совместимым между Windows, AIX и Solaris.Я не хочу, чтобы он отображал пароль, когда он напечатан.Вот что у меня есть:

BEGIN {
    if ($^O eq 'MSWin32') {
        require Win32::Console; 
        Win32::Console->import();
    }
}
sub get_password {
    print "Enter password: ";
    my $pass = '';
    # Change terminal settings to not display password
    if ($os eq 'MSWin32') {
        my $stdin = new Win32::Console STD_INPUT_HANDLE;
        my $orig_mode = $stdin->Mode();
        $stdin->Mode(ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | +ENABLE_MOUSE_INPUT);
        chomp($pass = <STDIN>);
        $stdin->Mode($orig_mode);
    }
    else {
        system('stty', '-echo');
        chomp($password = <STDIN>);
        system('stty', 'echo');
    }
    print "\n";
    return $pass;
}

Это прекрасно работает на всех платформах (при условии, что я не use strict), однако, 4 константы, используемые в Win32, выдают ошибки при strict subs в Unix:

Bareword "STD_INPUT_HANDLE" not allowed while "strict subs" in use at script.pl line 488.
Bareword "ENABLE_LINE_INPUT" not allowed while "strict subs" in use at script.pl line 490.
Bareword "ENABLE_PROCESSED_INPUT" not allowed while "strict subs" in use at script.pl line 490.
Bareword "ENABLE_MOUSE_INPUT" not allowed while "strict subs" in use at script.pl line 490.

Я не могу понять, как сделать так, чтобы Windows и Unix были довольны этими 4 константами.Если я попытаюсь определить их в блоке Unix only, компилятор Windows скажет мне, что я переопределяю их.

Можно ли это исправить?Или, возможно, сделать это по-другому?Заранее спасибо за помощь.

Ответы [ 2 ]

4 голосов
/ 03 февраля 2012

Вы должны использовать парены для вызовов подпрограмм в подпрограммы, которые вы не объявили.Таким образом, либо добавьте парены, изменив

STD_INPUT_HANDLE
ENABLE_LINE_INPUT
...

на

STD_INPUT_HANDLE()
ENABLE_LINE_INPUT()
...

, либо объявите подпрограммы, если они не будут объявлены Win32 :: Console путем изменения

    if ($^O eq 'MSWin32') {
        require Win32::Console; 
        Win32::Console->import();
    }
*От 1009 * до
    if ($^O eq 'MSWin32') {
        require Win32::Console; 
        Win32::Console->import();
    } else {
        eval <<'__EOI__'.';1' or die $@;
            sub STD_INPUT_HANDLE  { die }
            sub ENABLE_LINE_INPUT { die }
            ...
__EOI__
    }

Более понятный подход - перенос кода, специфичного для ОС, в отдельные модули.

BEGIN {
    my $mod = $^O eq 'MSWin32' ? 'My::IO::Win32' : 'My::IO::Default';
    eval "require $mod" or die $@;
    $mod->import(qw( get_password ));
}
0 голосов
/ 03 февраля 2012

Вы можете поместить версии get_password для Unix и Win32 в два отдельных модуля, скажем, My::Input::Unix и My::Input::Win32 соответственно, а затем require соответствующий в зависимости от платформы.Поэтому версия Win32 даже не будет скомпилирована на Unix-машине, избегая неопределенных констант и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...