App-Tel

 view release on metacpan or  search on metacpan

COMMANDS.md  view on Meta::CPAN

In my case, some of our commercial devices use a prefix of "c-" to designate
them, but we don't always type it when we're making a connection.  So we have
an alias like this:

    'hostsearch' => sub { "c-$_[0]"; }

## password

If a password is blank in the config file then the script will attempt to use
a Keyring for authentication.  It uses the Passwd::Keyring::Auto module for
this if it's installed.  If the password isn't found it will prompt you for it
and store it in the keyring.

We also support retrieving the password from KeePass, or Password Safe if the
appropriate module is available

## Crypt::PWSafe3

### Password safe file

If you set this argument to a file then it will attempt to read the password

COMMANDS.md  view on Meta::CPAN


Specifies the passphrase to decrypt the file

    pass_passwd => 'verysafe',
    pass_passwd => $ENV{SECRET_ENVIRONMENT_VARIABLE},
    pass_passwd => 'KEYRING',

## Storing safe passphrases in the keyring

If you want you can put the keepass password inside your keyring so you won't be
prompted after you've logged in.  If you've done this you can specify it by
saying

    keepass_passwd => 'KEYRING',

or

    pwsafe_passwd => 'KEYRING',

or

    pass_passwd => 'KEYRING',

### On keyring and DBUS

At least on my system, Gnome Keyring doesn't work if you ssh into your
machine.  This is normal because DBUS is intended to represent one user
session (The X session running locally).  Even so, it's nice to be able to
work around this and use unprompted login.  Add this to your .bashrc if you
need to:

    # Export $DBUS_SESSION_BUS_ADDRESS when connected via SSH to enable access
    # to gnome-keyring-daemon.
    export PASSWD_KEYRING_AUTO_PREFER=Gnome
    if [[ -z $DBUS_SESSION_BUS_ADDRESS ]]; then
        # workaround until I figure out why my machine gets the wrong information
        # out of dbus session-bus
        export DBUS_SESSION_BUS_ADDRESS=$(ps -ax | grep dbus-daemon | grep "\-\-address=unix" | awk '{print $8}' | sed 's/--address=//')
    #    if [[ -f ~/.dbus/session-bus/$(dbus-uuidgen --get)-0 ]]; then

COMMANDS.md  view on Meta::CPAN


If you want to load a syntax highlight module then you can specify the prefix
here.  For example, DlinkColor.pm would be loaded by

    syntax => 'Dlink',

You can chain load these so you can have a default set of highlight rules for
your company and specific set of rules for Cisco routers or switches or
whatever..

## username_prompt and password_prompt

    username_prompt => "nom d'utilisateur:",
    password_prompt => 'mot de passe:',

You might have a system that has a prompt that isn't like one of the standard
ones used by most vendors.  You might even find systems that have been
regionalized and prompt you in your native language.  If this is the case you
can override the default username and password prompts.

## ena_username_prompt and ena_password_prompt

    ena_username_prompt => "nom d'utilisateur:",
    ena_password_prompt => 'mot de passe:',

Very similar to the normal username prompt.  If your enable prompt has been
changed to something you can override it using these commands.

## pagercmd

    pagercmd => 'disable clipaging',

Extreme networks and Dlink both use 'disable clipaging' while Cisco uses 'term
length 0'.  Juniper uses 'set cli screen-length 0', but also might need 'set
cli complete-on-space off' to avoid annoying you while running scripts.

Some vendors don't have a command to turn off the pager.  In those cases I
tried setting tty rows to 10000.  Not suprisingly, the vendors that I tried it
on don't use the actual terminal size to control paging, so they still had
more prompts every 20 or so lines.

If your particular device does respect tty sizing, and you have the
Term::ReadKey module, then you can set:

    pagercmd => sub { _stty_rows(10000) },

In any case, these pagercmds take effect when tel is run in a non-interactive
mode, using either the -c or -x flags to specify scripts to run.

# Host Ranges

Changes  view on Meta::CPAN


app-tel (0.2015.07) unstable; urgency=medium

  * bump because color tests were broken (not sure why make test was passing here)

 -- Robert Drake <rdrake@cpan.org>  Wed, 12 Aug 2015 18:01:36 -0400

app-tel (0.2015-06) unstable; urgency=medium

  * added support for PWSafe3 password safes
  * changed keyring support slightly.  You may be prompted once to re-enter
    your passphrase if you're storing your keepass passphrase in the keyring.

 -- Robert Drake <rdrake@cpan.org>  Mon, 10 Aug 2015 17:32:41 -0400

app-tel (0.2015-05) unstable; urgency=medium

  * fix for NetAddr::IP being required

 -- Robert Drake <rdrake@cpan.org>  Thu, 21 May 2015 10:21:24 -0400

Changes  view on Meta::CPAN

  * perlcritic fixes

 -- Robert Drake <rdrake@cpan.org>  Thu, 15 Jan 2015 20:38:28 -0500

app-tel (0.2010_03) unstable; urgency=medium

  * pod2usage for -h help and summary if no arguments given
  * changed it so Term::ReadKey is loaded instead of used.  Term::ReadKey is
    an optional module loaded if you set the pagercmd to a special value.  It
    fakes an infinately long screen to try get output from a device with no
    "more" prompts.
  * applying chomp() to -x script input because we supply newlines when we
    send to the device.
  * adding -a to override autocmds via the cli when needed.

 -- Robert Drake <rdrake@cpan.org>  Fri, 26 Dec 2014 11:52:48 -0500

app-tel (0.2010) unstable; urgency=medium

  * lots of documentation updates
  * timing problems fixed by 0.2009 suppressing expect output in tests

README.md  view on Meta::CPAN

3. make install

A far easier way to install is to use cpanminus if you're
comfortable with it, now that the app is on CPAN:

1. curl -L https://cpanmin.us | perl - App::cpanminus

2. cpanm App::Tel

When you've installed and are ready to use the app, you can instruct your users
to run "mktelrc".  This will prompt them for the username and password they use
for routers, then write them to a .telrc2 file in their home directory.

This file should be only readable by the user for security reasons, although
the very act of storing passwords for your routers in a file means you are
already defeating some security.  I advise you to only run this on a heavily
firewalled box that is only used to allow users to access routers.

Obviously, if the router supports real ssh keys or any other secure
authentication you should let the login be handled by that.  This script can
still provide value without the need to login for you.

README.md  view on Meta::CPAN

    with.

5.  SecureCRT or MacOS iTerm2 can highlight sections by regex, if you prefer
    doing it at the terminal emulator level

6.  If you want to do it at the ssh protocol level, there is
https://github.com/mxtommy/Cisco-SSH-Client

# Bugs or Caveats

1.  Sending a "#" to the router via -c will match that as a prompt if that is what
    your prompt is set for.  clear_accum doesn't fix this.. need to put more
    thought into it.

2.  See [ISSUES] for a complete list of currently existing bugs

# Information

Please let me know about bugs or feature requests via github.  Submit patches
when possible to fix or enhance something, or to improve the testing.

## Screenshots

bin/tel  view on Meta::CPAN

Enables debugging, which will warn you if some of the runtime modules fail to
load.

Example: tel -d gw1-my-device

=item -x or --xscript

Runs a command-file file, which is a list of commands for the device.  Can be
specified multiple times to run multiple scripts.

If you need to use a newline in the script to get through a prompt then you
can use \r.  An example of this might be "reload\ry"

Example: tel -x changes.txt gw1-my-device

=item -a

Specify auto commands to run.  This overrides any commands loaded from profiles
and is used for all devices during the session.

Example: tel -a "sh run int vlan35; conf t" gw1-my-device

debian/changelog  view on Meta::CPAN


app-tel (0.2015.07) unstable; urgency=medium

  * bump because color tests were broken (not sure why make test was passing here)

 -- Robert Drake <rdrake@cpan.org>  Wed, 12 Aug 2015 18:01:36 -0400

app-tel (0.2015-06) unstable; urgency=medium

  * added support for PWSafe3 password safes
  * changed keyring support slightly.  You may be prompted once to re-enter
    your passphrase if you're storing your keepass passphrase in the keyring.

 -- Robert Drake <rdrake@cpan.org>  Mon, 10 Aug 2015 17:32:41 -0400

app-tel (0.2015-05) unstable; urgency=medium

  * fix for NetAddr::IP being required

 -- Robert Drake <rdrake@cpan.org>  Thu, 21 May 2015 10:21:24 -0400

debian/changelog  view on Meta::CPAN

  * perlcritic fixes

 -- Robert Drake <rdrake@cpan.org>  Thu, 15 Jan 2015 20:38:28 -0500

app-tel (0.2010_03) unstable; urgency=medium

  * pod2usage for -h help and summary if no arguments given
  * changed it so Term::ReadKey is loaded instead of used.  Term::ReadKey is
    an optional module loaded if you set the pagercmd to a special value.  It
    fakes an infinately long screen to try get output from a device with no
    "more" prompts.
  * applying chomp() to -x script input because we supply newlines when we
    send to the device.
  * adding -a to override autocmds via the cli when needed.

 -- Robert Drake <rdrake@cpan.org>  Fri, 26 Dec 2014 11:52:48 -0500

app-tel (0.2010) unstable; urgency=medium

  * lots of documentation updates
  * timing problems fixed by 0.2009 suppressing expect output in tests

dottelrc.sample  view on Meta::CPAN

$telrc = {
          'profile' => {
                       'default' => { 'password' => 'DINGLEHOPPER!', 'user' => $ENV{USER},
                                      'sshoptions' => [ 'UserKnownHostsFile=/dev/null', 'StrictHostKeyChecking=no' ],
                                      'pagercmd' => 'term len 0',
                                      'syntax' => 'Cisco',
                       },
                       'casa' => { 'handlers' =>  { '\cZ' => \&handle_ctrl_z } },
                       'zhone' => { 'user' => 'admin', 'method' => 'telnet', 'prompt' => '>', 'enablecmd' => 'priv' },
                       'vyos' => { 'prompt' => '\$', 'pagercmd' => 'set term length 0' },
                       'juniper' => { 'logoutcmd' => 'exit', 'syntax' => 'Juniper',
                                      'pagercmd' => 'set cli screen-length 0', 'prompt' => '>' },
                       'dlink' => { 'method' => 'telnet', 'handlers' => { '\177' => \&handle_backspace },
                                          'syntax' => 'Dlink', 'pagercmd' => 'disable clipaging' },
                       'mikrotik' => { 'logoutcmd' => '/quit', 'prompt' => '>' },
                       'at' => { 'ciphertype' => 'des', 'user' => 'engr' },
                       'hatteras' => { 'ciphertype' => 'des' }
                     },
          'rtr' => [   # this is an array so order matters
                   { 'regex' => '^cerf$', 'method' => 'telnet', 'hostname' => 'route-server.cerf.net', 'prompt' => 'route-server>' },
                   { 'regex' => '^att$', 'user' => 'rviews', 'method' => 'telnet', 'hostname' => 'route-server.ip.att.net', 'prompt' => 'route-server>' },
                   { 'regex' => '^ix$', 'user' => 'rviews', 'method' => 'telnet',
                                  'hostname' => 'route-views.oregon-ix.net', 'prompt' => 'route-views>' },
                   { 'regex' => '^quagga$', 'method' => 'telnet', 'hostname' => '127.0.0.1', port => 2605 },
                   { 'regex' => '^ubi', 'user' => 'ubnt', 'method' => 'ssh' },
                   { 'regex' => '192.168.13.10-28', 'profile' => 'zhone_olt' },
                   # to clarify what we're doing here, if the name matches
                   # these regex we load the listed profile.
                   { 'profile' => 'casa', 'regex' => '^casa1-' },
                   { 'profile' => 'zhone', 'regex' => '^dsl' },
                   { 'profile' => 'hatteras', 'regex' => '^hat' },
                   { 'profile' => 'mikrotik', 'regex' => '^gw1-mkt-site' },
                   { 'profile' => 'at', 'regex' => '^(ds|sw).*(site-name).*' },

inc/Module/AutoInstall.pm  view on Meta::CPAN

        }
        elsif ( $arg =~ /^--test(?:only)?$/ ) {
            $TestOnly = 1;
        }
        elsif ( $arg =~ /^--all(?:deps)?$/ ) {
            $AllDeps = 1;
        }
    }
}

# overrides MakeMaker's prompt() to automatically accept the default choice
sub _prompt {
    goto &ExtUtils::MakeMaker::prompt unless $AcceptDefault;

    my ( $prompt, $default ) = @_;
    my $y = ( $default =~ /^[Yy]/ );

    print $prompt, ' [', ( $y ? 'Y' : 'y' ), '/', ( $y ? 'n' : 'N' ), '] ';
    print "$default\n";
    return $default;
}

# the workhorse
sub import {
    my $class = shift;
    my @args  = @_ or return;
    my $core_all;

inc/Module/AutoInstall.pm  view on Meta::CPAN

              map  {
                ref($_)
                  ? ( ( ref($_) eq 'HASH' ) ? keys(%$_) : @{$_} )
                  : ''
              }
              map { +{@args}->{$_} }
              grep { /^[^\-]/ or /^-core$/i } keys %{ +{@args} }
        )[0]
    );

    # We want to know if we're under CPAN early to avoid prompting, but
    # if we aren't going to try and install anything anyway then skip the
    # check entirely since we don't want to have to load (and configure)
    # an old CPAN just for a cosmetic message

    $UnderCPAN = _check_lock(1) unless $SkipInstall || $InstallDepsTarget;

    while ( my ( $feature, $modules ) = splice( @args, 0, 2 ) ) {
        my ( @required, @tests, @skiptests );
        my $default  = 1;
        my $conflict = 0;

inc/Module/AutoInstall.pm  view on Meta::CPAN


        my $mandatory = ( $feature eq '-core' or $core_all );

        if (
            !$SkipInstall
            and (
                $CheckOnly
                or ($mandatory and $UnderCPAN)
                or $AllDeps
                or $InstallDepsTarget
                or _prompt(
                    qq{==> Auto-install the }
                      . ( @required / 2 )
                      . ( $mandatory ? ' mandatory' : ' optional' )
                      . qq{ module(s) from CPAN?},
                    $default ? 'y' : 'n',
                ) =~ /^[Yy]/
            )
          )
        {
            push( @Missing, @required );
            $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
        }

        elsif ( !$SkipInstall
            and $default
            and $mandatory
            and
            _prompt( qq{==> The module(s) are mandatory! Really skip?}, 'n', )
            =~ /^[Nn]/ )
        {
            push( @Missing, @required );
            $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
        }

        else {
            $DisabledTests{$_} = 1 for map { glob($_) } @tests;
        }
    }

inc/Module/AutoInstall.pm  view on Meta::CPAN

}

sub _update_to {
    my $class = __PACKAGE__;
    my $ver   = shift;

    return
      if _version_cmp( _version_of($class), $ver ) >= 0;  # no need to upgrade

    if (
        _prompt( "==> A newer version of $class ($ver) is required. Install?",
            'y' ) =~ /^[Nn]/
      )
    {
        die "*** Please install $class $ver manually.\n";
    }

    print << ".";
*** Trying to fetch it from CPAN...
.

inc/Module/AutoInstall.pm  view on Meta::CPAN


*** Cannot bootstrap myself. :-( Installation terminated.
.
}

# check if we're connected to some host, using inet_aton
sub _connected_to {
    my $site = shift;

    return (
        ( _load('Socket') and Socket::inet_aton($site) ) or _prompt(
            qq(
*** Your host cannot resolve the domain name '$site', which
    probably means the Internet connections are unavailable.
==> Should we try to install the required module(s) anyway?), 'n'
          ) =~ /^[Yy]/
    );
}

# check if a directory is writable; may create it on demand
sub _can_write {

inc/Module/AutoInstall.pm  view on Meta::CPAN

    mkdir( $path, 0755 ) unless -e $path;

    return 1 if -w $path;

    print << ".";
*** You are not allowed to write to the directory '$path';
    the installation may fail due to insufficient permissions.
.

    if (
        eval '$>' and lc(`sudo -V`) =~ /version/ and _prompt(
            qq(
==> Should we try to re-execute the autoinstall process with 'sudo'?),
            ((-t STDIN) ? 'y' : 'n')
        ) =~ /^[Yy]/
      )
    {

        # try to bootstrap ourselves from sudo
        print << ".";
*** Trying to re-execute the autoinstall process with 'sudo'...

inc/Module/AutoInstall.pm  view on Meta::CPAN


        return
          unless system( 'sudo', $^X, $0, "--config=$config",
            "--installdeps=$missing" );

        print << ".";
*** The 'sudo' command exited with error!  Resuming...
.
    }

    return _prompt(
        qq(
==> Should we try to install the required module(s) anyway?), 'n'
    ) =~ /^[Yy]/;
}

# load a module and return the version it reports
sub _load {
    my $mod  = pop; # method/function doesn't matter
    my $file = $mod;
    $file =~ s|::|/|g;

inc/Module/Install/Makefile.pm  view on Meta::CPAN

BEGIN {
	$VERSION = '1.16';
	@ISA     = 'Module::Install::Base';
	$ISCORE  = 1;
}

sub Makefile { $_[0] }

my %seen = ();

sub prompt {
	shift;

	# Infinite loop protection
	my @c = caller();
	if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) {
		die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])";
	}

	# In automated testing or non-interactive session, always use defaults
	if ( ($ENV{AUTOMATED_TESTING} or -! -t STDIN) and ! $ENV{PERL_MM_USE_DEFAULT} ) {
		local $ENV{PERL_MM_USE_DEFAULT} = 1;
		goto &ExtUtils::MakeMaker::prompt;
	} else {
		goto &ExtUtils::MakeMaker::prompt;
	}
}

# Store a cleaned up version of the MakeMaker version,
# since we need to behave differently in a variety of
# ways based on the MM version.
my $makemaker = eval $ExtUtils::MakeMaker::VERSION;

# If we are passed a param, do a "newer than" comparison.
# Otherwise, just return the MakeMaker version.

lib/App/Tel.pm  view on Meta::CPAN

    if ($type eq 'enable' and $profile->{$type} eq '' && $profile->{'password'} ne '') {
        return $profile->{'password'};
    }

    # if we get here, the password is blank so try other means
    my $pass = App::Tel::Passwd::load_from_profile($profile);
    if ($pass ne '') {
        return $pass;
    }

    # I was wondering how to decide what to prompt for, but I think it should
    # be whichever profile loaded.  So maybe we check for hostname and check
    # for profile name and then save as profile name. If they want to be
    # explicit they should specify the password format as KEYRING or
    # something.. I dunno.
    App::Tel::Passwd::keyring($profile->{user}, $profile->{profile_name}, $profile->{profile_name});

    # if they make it here and still don't have a password then none was
    # defined anywhere and we probably should prompt for one.  Consider
    # turning off echo then normal read.
    return App::Tel::Passwd::input_password($router);
}

=head2 session

    my $session = $self->session;

Expect won't let you reuse a connection that has spawned a process, so you
can call this with an argument to reset the session.  If called without an

lib/App/Tel.pm  view on Meta::CPAN


    if ($self->connected);
or
    $self->connected(1);

Returns connection status, or sets the status to whatever value is supplied to
the method.

Note: This isn't the session state, but an indicator that our session has
gotten through the login stage and is now waiting for input.  i.e., the router
is at a prompt of some kind.

=cut

sub connected {
    my ($self, $status) = @_;
    if (defined($status)) {
        $self->{connected}=$status;
    }

    return $self->{connected};

lib/App/Tel.pm  view on Meta::CPAN


=cut

sub enable {
    my $self = shift;
    my $profile = $self->profile;

    if ($profile->{enablecmd}) {
        $self->send($profile->{enablecmd} . "\r");

        $profile->{ena_username_prompt} ||= qr/[Uu]ser[Nn]ame:|Login:/;
        $profile->{ena_password_prompt} ||= qr/[Pp]ass[Ww]ord/;

        # we need to be able to handle routers that prompt for username and password
        # need to check the results to see if enable succeeded
        $self->expect($self->{timeout},
                [ $profile->{ena_username_prompt} => sub { $self->send("$profile->{user}\r"); exp_continue; } ],
                [ $profile->{ena_password_prompt} => sub { $self->send($self->password('enable') . "\r"); } ]
        );
    }

    $self->{enabled}=1;
    return $self;
}

=head2 enabled

    my $enabled = $self->enabled;

lib/App/Tel.pm  view on Meta::CPAN

    if (defined($rtr->{sshoptions}) && scalar $rtr->{sshoptions} > 0) {
        $ssho = '-o '. join(' -o ', @{$rtr->{sshoptions}});
    }
    $ssho .= $rtr->{ciphertype} ? " -c $rtr->{ciphertype}" : '';

    # because we use last METHOD; in anonymous subs this suppresses the
    # warning of "exiting subroutine via last;"
    no warnings 'exiting';
    # handle MOTD profile loading, and other things parsed from the config
    my @dynamic;
    if (defined($rtr->{prompt})) {
        push @dynamic, [ qr/$rtr->{prompt}/, sub { $self->connected(1); last METHOD; } ];
    }

    # handle prompts in foreign languages or other things we didn't think of
    $rtr->{username_prompt} ||= qr/[Uu]ser[Nn]ame:|[Ll]ogin:/;
    $rtr->{password_prompt} ||= qr/[Pp]ass[Ww]ord/;

    $self->{port} ||= $self->{opts}->{p} || $rtr->{port}; # get port from CLI or the profile
    # if it's not set in the profile or CLI above, it gets set in the
    # method below, but needs to be reset on each loop to change from
    # telnet to ssh defaults

    my $family = '';
    $family = '-4' if ($self->{opts}->{4});
    $family = '-6' if ($self->{opts}->{6});

lib/App/Tel.pm  view on Meta::CPAN


        # need to make this optional
        # also need to make it display whatever the user cares about.
        print "\e[22t\033]0;$_ $hostname\007";
        $self->{title_stack}++;
        $SIG{INT} = sub { for (1..$self->{title_stack}) { print "\e[23t"; } $self->{title_stack}=0; };

        $self->expect($self->{timeout},
                @{$self->_banners},
                @dynamic,
                [ $rtr->{username_prompt} => sub {
                    $self->send("$rtr->{user}\r");
                    exp_continue;
                } ],
                [ $rtr->{password_prompt} => sub {
                    $self->send($self->password() ."\r");
                    $self->connected(1);
                    last METHOD;
                } ],
                [ qr/Name or service not known|hostname nor servname provided, or not known|could not resolve / => sub
                    {
                        # if host lookup fails then check to see if there is an alternate method defined
                        if ($rtr->{hostsearch} && !$rtr->{hostsearched}) {
                            $hostname = &{$rtr->{hostsearch}}($hostname);
                            $rtr->{hostsearched}=1;

lib/App/Tel.pm  view on Meta::CPAN

                #[ qr/ssh_exchange_identification/ => sub { next METHOD; } ],
                #[ qr/[Cc]onnection (refused|closed)/ => sub { next METHOD; } ],
                #[ qr/key_verify failed/ => sub { next METHOD; } ],
                #[ qr/Corrupted/ => sub { next METHOD; } ],
                [ 'eof' => sub { next METHOD; } ],
                [ 'timeout' => sub { next METHOD; } ],
        );
    }

    $rtr->{logoutcmd} ||= "logout";
    $rtr->{prompt} ||= '#';

    warn "Connection to $hostname failed.\n" if !$self->connected;
    return $self;
}

=head2 logging

    $self->logging('filename');

Turns on logging for this session.  If you specify a filename it will log to

lib/App/Tel.pm  view on Meta::CPAN


sub run_commands {
    my $self = shift;
    my $opts = $self->{opts};

    foreach my $arg (@_) {
        $arg =~ s/\\r/\r/g; # fix for reload\ry.  I believe 'perldoc quotemeta' explains why this happens
        chomp($arg);
        $self->send("$arg\r");
        $self->expect($self->{timeout},
            [ $self->profile->{prompt} => sub { } ],
            [ 'eof' => sub { die "EOF From host.\n"; } ],
        );
        sleep($opts->{s}) if ($opts->{s});
    }

    return $self;
}

=head2 control_loop

lib/App/Tel.pm  view on Meta::CPAN

command line, or via autocmds in the profile.

Calling this without any commands will just run interact()

=cut

sub control_loop {
    my $self = shift;
    my $profile = $self->profile;
    my $opts = $self->{opts};
    my $prompt = $profile->{prompt};
    my $pagercmd = $profile->{pagercmd};
    my $autocmds;
    my @args;

    if ($opts->{a}) {
        $autocmds = [ split(/;/, $opts->{a}) ];
    } else {
        $autocmds = $profile->{autocmds};
    }

lib/App/Tel.pm  view on Meta::CPAN


    if ($opts->{x}) {
        for (@{$opts->{x}}) {
            open(my $X, '<', $_) || die "Can't open file $_\n";
            push(@args,<$X>);
            close $X;
        }
    }

    if (@args) {
        $self->expect($self->{timeout},'-re',$prompt);
        if (ref($pagercmd) eq 'CODE') {
            $pagercmd->();
        } elsif ($pagercmd) {
            $self->run_commands("$pagercmd");
        }
        $self->run_commands(@args);
        $self->send($profile->{logoutcmd} ."\r");
    } else {
        die 'STDIN Not a tty' if (!POSIX::isatty($self->{stdin}));
        if ($autocmds) {
            $self->expect($self->{timeout},'-re',$prompt);
            eval { $self->run_commands(@$autocmds); };
            return $self if ($@);
        }

        my $color_cb = sub {
            my ($session) = @_;
            $self->_winch() if $_winch_it;
            ${*$session}{exp_Pty_Buffer} = $self->{colors}->colorize(${*$session}{exp_Pty_Buffer});
            return 1;
        };

        my $sleep_cb = sub {
            sleep($self->{opts}->{S});
            return 1;
        };
        $self->session->set_cb($self->session,$color_cb, [ \${$self->session} ]);
        $self->{stdin}->set_seq("\r",$sleep_cb) if ($self->{opts}->{S});
        $self->session->interact($self->{stdin}, '\cD');
        # q\b is to end anything that's at a More prompt or other dialog and
        # get you back to the command prompt
        # would be nice to detect if the session is closing down and not send
        # this.  I've tried checking for session and session->pid but they
        # both still exist at this point so unless we wait for soft_close
        # we're kinda stuck doing this.
        $self->send("q\b" . $profile->{logoutcmd}. "\r");
    }
    return $self;
}

1;

lib/App/Tel/Passwd.pm  view on Meta::CPAN

    my $load = eval {
        Module::Load::load $mod;
        $mod->new(file => $file, passwd => $passwd);
    };
    croak "Something went wrong with our load of passwd module $type:\n$@" if ($@);
    return $load;
}

=head2 input_password

    my $password = input_password($prompt);

Prompts the user for a password then disables local echo on STDIN, reads a
line and returns it.

=cut

sub input_password {
    my $prompt = shift;
    $prompt ||= '';
    my $old_mode;
    # uncoverable branch true
    if (!$_mock) {
        die 'STDIN not a tty' if (!POSIX::isatty(\*STDIN));
        $old_mode=IO::Stty::stty(\*STDIN,'-g');
        IO::Stty::stty(\*STDIN,'-echo');
    }
    print "Enter password for $prompt: ";
    my $password=<STDIN>;

    chomp($password);
    # uncoverable branch true
    if (!$_mock) {
        IO::Stty::stty(\*STDIN,$old_mode);
    } else {
        print "\n";
    }
    return $password;
}

=head2 keyring

    my $password = keyring($user, $domain, $group);

Reads a password from a keyring using Passwd::Keyring::Auto if it's available.
If the password isn't found the user is prompted to enter a password, then we
try to store it in the keyring.

=cut

sub keyring {
    my ($user, $domain, $group) = @_;

    my $p = eval {
        load Passwd::Keyring::Auto, 'get_keyring';
        my $keyring = get_keyring(app=>$appname, group=>$group);

local/lib/perl5/Module/AutoInstall.pm  view on Meta::CPAN

        }
        elsif ( $arg =~ /^--test(?:only)?$/ ) {
            $TestOnly = 1;
        }
        elsif ( $arg =~ /^--all(?:deps)?$/ ) {
            $AllDeps = 1;
        }
    }
}

# overrides MakeMaker's prompt() to automatically accept the default choice
sub _prompt {
    goto &ExtUtils::MakeMaker::prompt unless $AcceptDefault;

    my ( $prompt, $default ) = @_;
    my $y = ( $default =~ /^[Yy]/ );

    print $prompt, ' [', ( $y ? 'Y' : 'y' ), '/', ( $y ? 'n' : 'N' ), '] ';
    print "$default\n";
    return $default;
}

# the workhorse
sub import {
    my $class = shift;
    my @args  = @_ or return;
    my $core_all;

local/lib/perl5/Module/AutoInstall.pm  view on Meta::CPAN

              map  {
                ref($_)
                  ? ( ( ref($_) eq 'HASH' ) ? keys(%$_) : @{$_} )
                  : ''
              }
              map { +{@args}->{$_} }
              grep { /^[^\-]/ or /^-core$/i } keys %{ +{@args} }
        )[0]
    );

    # We want to know if we're under CPAN early to avoid prompting, but
    # if we aren't going to try and install anything anyway then skip the
    # check entirely since we don't want to have to load (and configure)
    # an old CPAN just for a cosmetic message

    $UnderCPAN = _check_lock(1) unless $SkipInstall || $InstallDepsTarget;

    while ( my ( $feature, $modules ) = splice( @args, 0, 2 ) ) {
        my ( @required, @tests, @skiptests );
        my $default  = 1;
        my $conflict = 0;

local/lib/perl5/Module/AutoInstall.pm  view on Meta::CPAN


        my $mandatory = ( $feature eq '-core' or $core_all );

        if (
            !$SkipInstall
            and (
                $CheckOnly
                or ($mandatory and $UnderCPAN)
                or $AllDeps
                or $InstallDepsTarget
                or _prompt(
                    qq{==> Auto-install the }
                      . ( @required / 2 )
                      . ( $mandatory ? ' mandatory' : ' optional' )
                      . qq{ module(s) from CPAN?},
                    $default ? 'y' : 'n',
                ) =~ /^[Yy]/
            )
          )
        {
            push( @Missing, @required );
            $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
        }

        elsif ( !$SkipInstall
            and $default
            and $mandatory
            and
            _prompt( qq{==> The module(s) are mandatory! Really skip?}, 'n', )
            =~ /^[Nn]/ )
        {
            push( @Missing, @required );
            $DisabledTests{$_} = 1 for map { glob($_) } @skiptests;
        }

        else {
            $DisabledTests{$_} = 1 for map { glob($_) } @tests;
        }
    }

local/lib/perl5/Module/AutoInstall.pm  view on Meta::CPAN

}

sub _update_to {
    my $class = __PACKAGE__;
    my $ver   = shift;

    return
      if _version_cmp( _version_of($class), $ver ) >= 0;  # no need to upgrade

    if (
        _prompt( "==> A newer version of $class ($ver) is required. Install?",
            'y' ) =~ /^[Nn]/
      )
    {
        die "*** Please install $class $ver manually.\n";
    }

    print << ".";
*** Trying to fetch it from CPAN...
.

local/lib/perl5/Module/AutoInstall.pm  view on Meta::CPAN


*** Cannot bootstrap myself. :-( Installation terminated.
.
}

# check if we're connected to some host, using inet_aton
sub _connected_to {
    my $site = shift;

    return (
        ( _load('Socket') and Socket::inet_aton($site) ) or _prompt(
            qq(
*** Your host cannot resolve the domain name '$site', which
    probably means the Internet connections are unavailable.
==> Should we try to install the required module(s) anyway?), 'n'
          ) =~ /^[Yy]/
    );
}

# check if a directory is writable; may create it on demand
sub _can_write {

local/lib/perl5/Module/AutoInstall.pm  view on Meta::CPAN

    mkdir( $path, 0755 ) unless -e $path;

    return 1 if -w $path;

    print << ".";
*** You are not allowed to write to the directory '$path';
    the installation may fail due to insufficient permissions.
.

    if (
        eval '$>' and lc(`sudo -V`) =~ /version/ and _prompt(
            qq(
==> Should we try to re-execute the autoinstall process with 'sudo'?),
            ((-t STDIN) ? 'y' : 'n')
        ) =~ /^[Yy]/
      )
    {

        # try to bootstrap ourselves from sudo
        print << ".";
*** Trying to re-execute the autoinstall process with 'sudo'...

local/lib/perl5/Module/AutoInstall.pm  view on Meta::CPAN


        return
          unless system( 'sudo', $^X, $0, "--config=$config",
            "--installdeps=$missing" );

        print << ".";
*** The 'sudo' command exited with error!  Resuming...
.
    }

    return _prompt(
        qq(
==> Should we try to install the required module(s) anyway?), 'n'
    ) =~ /^[Yy]/;
}

# load a module and return the version it reports
sub _load {
    my $mod  = pop; # method/function doesn't matter
    my $file = $mod;
    $file =~ s|::|/|g;

local/lib/perl5/Module/AutoInstall.pm  view on Meta::CPAN

        make_args   => '--hello',   # option(s) for CPAN::Config
        force       => 1,           # pseudo-option to force install
        do_once     => 1,           # skip previously failed modules
    );
    
    WriteAll;

Invoking the resulting F<Makefile.PL>:

    % perl Makefile.PL                  # interactive behaviour
    % perl Makefile.PL --defaultdeps    # accept default value on prompts
    % perl Makefile.PL --checkdeps      # check only, no Makefile produced
    % perl Makefile.PL --skipdeps       # ignores all dependencies
    % perl Makefile.PL --testonly       # don't write installation targets

Note that the trailing 'deps' of arguments may be omitted, too.

Using C<--defaultdeps> will make F<Makefile.PL> behave similarly to a regular
Makefile.PL file with C<PREREQ_PM> dependencies.

One can use environment variables (see "ENVIRONMENT") below to set a default

local/lib/perl5/Module/Build.pm  view on Meta::CPAN


This can be a good idea, as it helps prevent multiple versions of a
module from being present on your system, which can be a confusing
situation indeed.

=item installdeps

[version 0.36]

This action will use the C<cpan_client> parameter as a command to install
missing prerequisites.  You will be prompted whether to install
optional dependencies.

The C<cpan_client> option defaults to 'cpan' but can be set as an option or in
F<.modulebuildrc>.  It must be a shell command that takes a list of modules to
install as arguments (e.g. 'cpanp -i' for CPANPLUS).  If the program part is a
relative path (e.g. 'cpan' or 'cpanp'), it will be located relative to the perl
program that executed Build.PL.

  /opt/perl/5.8.9/bin/perl Build.PL
  ./Build installdeps --cpan_client 'cpanp -i'

local/lib/perl5/Module/Build/API.pod  view on Meta::CPAN


This method returns a reasonable facsimile of the currently-executing
C<Module::Build> object representing the current build.  You can use
this object to query its L</notes()> method, inquire about installed
modules, and so on.  This is a great way to share information between
different parts of your build process.  For instance, you can ask
the user a question during C<perl Build.PL>, then use their answer
during a regression test:

  # In Build.PL:
  my $color = $build->prompt("What is your favorite color?");
  $build->notes(color => $color);

  # In t/colortest.t:
  use Module::Build;
  my $build = Module::Build->current;
  my $color = $build->notes('color');
  ...

The way the C<current()> method is currently implemented, there may be
slight differences between the C<$build> object in Build.PL and the

local/lib/perl5/Module/Build/API.pod  view on Meta::CPAN


[version 0.28]

Returns a human-readable (table-form) string showing all
prerequisites, the versions required, and the versions actually
installed.  This can be useful for reviewing the configuration of your
system prior to a build, or when compiling data to send for a bug
report.  The C<prereq_report> action is just a thin wrapper around the
C<prereq_report()> method.

=item prompt($message, $default)

[version 0.12]

Asks the user a question and returns their response as a string.  The
first argument specifies the message to display to the user (for
example, C<"Where do you keep your money?">).  The second argument,
which is optional, specifies a default answer (for example,
C<"wallet">).  The user will be asked the question once.

If C<prompt()> detects that it is not running interactively and there
is nothing on STDIN or if the PERL_MM_USE_DEFAULT environment variable
is set to true, the $default will be used without prompting.

To prevent automated processes from blocking, the user must either set
PERL_MM_USE_DEFAULT or attach something to STDIN (this can be a
pipe/file containing a scripted set of answers or /dev/null.)

If no $default is provided an empty string will be used instead.  In
non-interactive mode, the absence of $default is an error (though
explicitly passing C<undef()> as the default is valid as of 0.27.)

This method may be called as a class or object method.

local/lib/perl5/Module/Build/API.pod  view on Meta::CPAN

derived files, it returns false.  Additionally, if any of the derived
files do not exist, it returns false.  Otherwise it returns true.

The arguments may be either a scalar or an array reference of file
names.

=item y_n($message, $default)

[version 0.12]

Asks the user a yes/no question using C<prompt()> and returns true or
false accordingly.  The user will be asked the question repeatedly
until they give an answer that looks like "yes" or "no".

The first argument specifies the message to display to the user (for
example, C<"Shall I invest your money for you?">), and the second
argument specifies the default answer (for example, C<"y">).

Note that the default is specified as a string like C<"y"> or C<"n">,
and the return value is a Perl boolean value like 1 or 0.  I thought
about this for a while and this seemed like the most useful way to do

local/lib/perl5/Module/Build/Base.pm  view on Meta::CPAN


sub _readline {
  my $self = shift;
  return undef if $self->_is_unattended;

  my $answer = <STDIN>;
  chomp $answer if defined $answer;
  return $answer;
}

sub prompt {
  my $self = shift;
  my $mess = shift
    or die "prompt() called without a prompt message";

  # use a list to distinguish a default of undef() from no default
  my @def;
  @def = (shift) if @_;
  # use dispdef for output
  my @dispdef = scalar(@def) ?
    ('[', (defined($def[0]) ? $def[0] . ' ' : ''), ']') :
    (' ', '');

  local $|=1;

local/lib/perl5/Module/Build/Base.pm  view on Meta::CPAN

    $ans = scalar(@def) ? $def[0] : '';
  }

  return $ans;
}

sub y_n {
  my $self = shift;
  my ($mess, $def)  = @_;

  die "y_n() called without a prompt message" unless $mess;
  die "Invalid default value: y_n() default must be 'y' or 'n'"
    if $def && $def !~ /^[yn]/i;

  my $answer;
  while (1) { # XXX Infinite or a large number followed by an exception ?
    $answer = $self->prompt(@_);
    return 1 if $answer =~ /^y/i;
    return 0 if $answer =~ /^n/i;
    local $|=1;
    print "Please answer 'y' or 'n'.\n";
  }
}

sub current_action { shift->{action} }
sub invoked_action { shift->{invoked_action} }

local/lib/perl5/Module/Build/Compat.pm  view on Meta::CPAN

    Module::Build::Compat->write_makefile(build_class => '%s');
EOF

  } elsif ($type eq 'passthrough') {
    printf {$fh} <<'EOF', $subclass_load, ref($build), ref($build);

    unless (eval "use Module::Build::Compat 0.02; 1" ) {
      print "This module requires Module::Build to install itself.\n";

      require ExtUtils::MakeMaker;
      my $yn = ExtUtils::MakeMaker::prompt
	('  Install Module::Build now from CPAN?', 'y');

      unless ($yn =~ /^y/i) {
	die " *** Cannot install without Module::Build.  Exiting ...\n";
      }

      require Cwd;
      require File::Spec;
      require CPAN;

local/lib/perl5/Module/Install/API.pod  view on Meta::CPAN


=head2 recommends (L<Module::Install::Metadata>)

  recommends 'ExtUtils::Foo::Bar';
  recommends 'ExtUtils::Foo::Baz' => '1.00';

B<recommends> command also takes a module name and a minimum required
version if any. As of this writing, C<recommends> is purely
advisory, only written in the C<META.yml>. Recommended modules will
B<not> usually be installed by the current CPAN toolchains (other
system package managers may possibly prompt you to install them).

=head2 features, feature (L<Module::Install::Metadata>)

  feature( 'share directory support',
    -default => 1,
    'File::ShareDir' => '1.00',
  );

  features(
    'JSON support', [

local/lib/perl5/Module/Install/API.pod  view on Meta::CPAN

versions if any. B<features> command takes an array of a description
and an array of modules.

As of this writing, both C<feature> and C<features> work only when 
B<auto_install> (see below) is set. These are used to allow
distribution users to choose what they install along with the
distribution. This may be useful if the distribution has lots of
optional features that may not work on all the platforms, or that
require too many modules for average users.

However, prompting users also hinders automated installation or smoke
testing, and is considered a bad practice (giving sane default
values is much preferred).

Though C<feature>d modules are optional and can be chosen during the
installation, the chosen modules are treated the same as the ones
set by C<requires> command. (They are not listed in the
C<recommends> section in the C<META.yml>). This may change in the
future.

You can add C<< -default => [01] >> in an array of required modules
in the C<feature(s)>, to set a default value for the prompt.

=head1 COMMANDS TO WRITE METADATA

These are the commands to write actual meta files.

=head2 WriteAll (L<Module::Install::WriteAll>)

  use inc::Module::Install;
  
  all_from 'lib/Foo/Bar.pm';

local/lib/perl5/Module/Install/Admin/Manifest.pm  view on Meta::CPAN


It appears that your MANIFEST does not contain the same components that
are currently in the 'inc' directory. 

Please try running 'make manifest' and then run 'make dist' again.

Remember to use the MANIFEST.SKIP file to control things that should not
end up in your MANIFEST. See 'perldoc ExtUtils::Manifest' for details.

END_MESSAGE
	return if $self->prompt(
		'Do you *really* want to continue making a distribution?', 'n'
	) =~ /^[Yy]/;

	if ( -d $distdir ) {
		require File::Path;
		File::Path::rmtree($distdir);
	}

	exit(1);
}

local/lib/perl5/Module/Install/Makefile.pm  view on Meta::CPAN

BEGIN {
	$VERSION = '1.16';
	@ISA     = 'Module::Install::Base';
	$ISCORE  = 1;
}

sub Makefile { $_[0] }

my %seen = ();

sub prompt {
	shift;

	# Infinite loop protection
	my @c = caller();
	if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) {
		die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])";
	}

	# In automated testing or non-interactive session, always use defaults
	if ( ($ENV{AUTOMATED_TESTING} or -! -t STDIN) and ! $ENV{PERL_MM_USE_DEFAULT} ) {
		local $ENV{PERL_MM_USE_DEFAULT} = 1;
		goto &ExtUtils::MakeMaker::prompt;
	} else {
		goto &ExtUtils::MakeMaker::prompt;
	}
}

# Store a cleaned up version of the MakeMaker version,
# since we need to behave differently in a variety of
# ways based on the MM version.
my $makemaker = eval $ExtUtils::MakeMaker::VERSION;

# If we are passed a param, do a "newer than" comparison.
# Otherwise, just return the MakeMaker version.

local/lib/perl5/Module/Install/Makefile.pm  view on Meta::CPAN

=head1 SYNOPSIS

In your F<Makefile.PL>:

    use inc::Module::Install;
    WriteMakefile();

=head1 DESCRIPTION

This module is a wrapper around B<ExtUtils::MakeMaker>.  It exports
two functions: C<prompt> (an alias for C<ExtUtils::MakeMaker::prompt>)
and C<WriteMakefile>.

The C<WriteMakefile> function will pass on keyword/value pair functions
to C<ExtUtils::MakeMaker::WriteMakefile>. The required parameters
C<NAME> and C<VERSION> (or C<VERSION_FROM>) are not necessary if
it can find them unambiguously in your code.

=head1 CONFIGURATION OPTIONS

This module also adds some Configuration parameters of its own:

local/lib/perl5/Module/Install/With.pm  view on Meta::CPAN



#####################################################################
# Testing and Configuration Contexts

=pod

=head2 interactive

The C<interactive> function tests for an install that has a user present
(or at least, one in which it is reasonable for us to present prompts
and other similar types of things).

Returns true if in an interactive environment, or false otherwise.

=cut

sub interactive {
	# Treat things interactively ONLY based on input
	!! (-t STDIN and ! automated_testing());
}

t/rc/hostname.rc  view on Meta::CPAN

$telrc = {
          'rtr' => [   # this is an array so order matters
                   { 'regex' => '^\d{4}$', method => 'telnet', 'hostname' => sub { '172.18.0.'.($_[0] -2000+90); } },
                   { 'regex' => '^cerf$', 'method' => 'telnet', 'hostname' => 'route-server.cerf.net', 'prompt' => 'route-server>' },
                 ],
};



( run in 1.209 second using v1.01-cache-2.11-cpan-0b5f733616e )