Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Scalars as hash keys?

by ybiC (Prior)
on Oct 26, 2000 at 22:31 UTC ( [id://38699]=perlquestion: print w/replies, xml ) Need Help??

ybiC has asked for the wisdom of the Perl Monks concerning the following question:

I have an existing script to automate password resets for a passel o' Cisco switches.   The following snippet is my attempt at having the script prompt for old+new passwords (instead of having them coded in the script's config parameters).

But it doesn't work.  
Looks like keyboard-entered passwords aren't getting pushed(?) into the scalars.   Multiple "uninitialized value" errors result for each of lines 8, 21, 26.

Would any clueful Monks care to enlighten me on whatever fundamental concept/syntax I'm lacking?
    cheers,
    Don
    striving for Perl Adept

1 #!/usr/bin/perl -w 2 # getpass.pl 3 4 use Term::ReadKey; 5 use Tie::IxHash; 6 use vars qw($key $t %passwds); 7 8 $t = tie(%passwds, Tie::IxHash, 9 'Enter old password:' => "$oldpass", 10 'Enter old enable password:' => "$oldenable", 11 'Enter new password:' => "$newpass", 12 'Confirm new password:' => "$newpassConf", 13 'Enter new enable password:' => "$newenable", 14 'Confirm new enable password:' => "$newenableConf", 15 ); 16 17 print "Prompting for passwords (won't appear on-screen)\n"; 18 foreach $prompt (keys (%passwds)) { 19 print "$prompt "; 20 ReadMode('noecho'); 21 chomp($prompt{$key} = <STDIN>); 22 ReadMode(0); 23 print "\n" 24 } 25 26 unless (("$newpass" eq "$newpassConf") and ("$newenable" eq "$ne +wenableConf")) 27 {die "\nNew password(s) confirmation didn't match. Tough be +ans. Try again.\n"}

Replies are listed 'Best First'.
Re: Scalars as hash keys?
by Fastolfe (Vicar) on Oct 26, 2000 at 22:34 UTC
    What is $key? You aren't defining it anywhere. You've declared it via 'use vars', but you haven't set it anywhere. Do you mean to use $prompt here?
      Hmmm... I see what you mean.

      I meant it to be the value of the password scalar in the above hash (at line 21) as entered from keyboard.   Should it push <STDIN> into each scalar?

      I'm not at all familiar with what I'm trying to do here, so pointers to relevent docs are quite welcome.
          cheers,
          Don
          striving for Perl Adept

        Looking at your code, it seems like you want to be trying your hash values as the variable for your resulting hash. Your variable names aren't consistent, but I believe you want something like this:
        chomp($prompt{$passwds{$prompt}} = <STDIN>);
        That would set up your resulting %prompt hash like this:
        %prompt = ( '$oldpass' = 'whatever I typed for old password', '$oldenable' = 'whatever I typed for old enable, ... );
        Note the presence of the dollar signs in the hash keys, which is weird. You probably want to take them out unless for whatever reason you want your hash keys to all be prefixed with dollar signs.. *shrug*..

        You also probably want to use a new name for your resulting hash, like, %new or %input. And use strict;! You're doing good by keeping track of variables via 'use vars', but you aren't running with strict turned on, which would have told you that %prompt was being used undeclared, and might have pointed you in the direction of this problem.

Re: Scalars as hash keys?
by chromatic (Archbishop) on Oct 27, 2000 at 00:15 UTC
    I can answer lines 8 and possibly 26.

    In line 8 (the hash declaration, which continues through line 15), you have the curious construct Fastolfe mentioned in passing. The scalar variables in double quotes will be interpolated -- unfortunately, as the variables have never been defined, they throw the undefined value warning on line 8.

    I think this may be more to your liking:

    my %prompts = ( 'Enter new password' => 'newpass', 'Enter old password' => 'oldpass' ); my %tied_hash; # tie here for my $prompt (keys %prompts) { print $prompt; chomp(my $input = <STDIN>); $tied_hash{$prompts{$prompt}} = $input; }
    Does that make more sense? The key in the %prompts hash is the prompt. The value is the slot in the tied hash to which the data entered at that prompt corresponds.
      I think he wanted to tie %prompts so that his loop would ask the prompts in the order he defined them above. A normal hash would have asked them all out-of-order...
        Now it's Fastolfe who's reading my mind {g}.   Just encountered "asked them all out-of-order".

        So... 2 questions:
        A - how do I tie my %prompts = (blah blah); ?
        II - does $tied_hash{$prompts{$prompt}} = $input still need to be tied?

        Here's what I've got so far:

        1 #!/usr/bin/perl -w 2 # getpass.pl 3 4 use strict; 5 use Term::ReadKey; 6 use Tie::IxHash; 7 8 # Hash of on-screen prompts for old/new passwords 9 my %prompts = ( 10 'Enter old password:' => 'oldpass', 11 'Enter old enable password:' => 'oldenable', 12 'Enter new password:' => 'newpass', 13 'Confirm new password:' => 'newpassconf', 14 'Enter new enable password:' => 'newenable', 15 'Confirm new enable password:' => 'newenableconf', 16 ); 17 18 # Walk through each on-screen prompt to populate new Hash of passwo +rds 19 print "Prompting for passwords (*won't* appear on-screen)\n\n" 20 my %passwds; 21 for my $prompt (keys %prompts) { 22 print " $prompt " 23 ReadMode('noecho'); 24 chomp(my $input = <STDIN>); 25 $passwds{$prompts{$prompt}} = $input; 26 ReadMode(0); 27 print "\n" 28 }

        In case I haven't already mentioned it, y'all's help is truly appreciated.   Double, no, make that triple++.
            cheers,
            Don
            striving for Perl Adept

      Hmmmm....   I think this resolves my remaining confusion.   Chromatic, you were reading my mind.
      Hope to post working snippet soon.   8^)
          cheers,
          Don
          striving for Perl Adept

      Update: As shown above, I'm still confused.
      Nonetheless, with more research into Tie::IxHash I still hope to post a working snippet soon.

(code) RE: Scalars as hash keys? (solution!)
by ybiC (Prior) on Oct 27, 2000 at 08:34 UTC
    Here's what I finally came up with.

    This time around thanks go to Fastolfe and chromatic for all but drawing me a picture of how to use Tie::IxHash, to tilly for pointing me to Data::Dumper recently on an unrelated question in the Chatbox, to ChOas for Yet Another (simpler) Way To Do It, and to AgentM even though I didnt' use his idea.

    /msg's or replies welcome if any fine Monks spot something I'm doing in a dumb or dangerous manner.
        cheers,
        Don
        striving for Perl Adept

    1 #!/usr/bin/perl -w 2 # getpass.pl 3 4 5 use strict; 6 use Term::ReadKey; 7 use Tie::IxHash; 8 #use Data::Dumper; # Only for testing. 9 #use vars qw(); # Don't need if all vars declared with "my". 10 11 12 # Tied hash of on-screen prompts for old/new passwords 13 tie my %prompts, "Tie::IxHash" 14 %prompts = ( 15 'Enter old password:' => 'oldpass', 16 'Enter old enable password:' => 'oldenable', 17 'Enter new password:' => 'newpass', 18 'Confirm new password:' => 'passconf', 19 'Enter new enable password:' => 'newenable', 20 'Confirm new enable password:' => 'enableconf', 21 ); 22 23 24 # Walk through each prompt to populate a new tied Hash of passwords +: 25 print "Prompting for passwords (no screen echo)\n\n" 26 tie my %passwds, "Tie::IxHash" 27 for my $prompt (keys %prompts) { 28 print " $prompt " 29 ReadMode('noecho'); # don't echo to screen. 30 chomp(my $input = <STDIN>); 31 $passwds{$prompts{$prompt}} = $input; 32 ReadMode(0); # re-activate screen echo. 33 print "\n" 34 } 35 print "\n" 36 37 38 # Create named scalars for %passwds values: 39 # Probably a kludge-free way to do this, 40 # but I haven't encountered it yet. 41 my $oldpass = ($passwds{"oldpass"}); 42 my $oldenable = ($passwds{"oldenable"}); 43 my $newpass = ($passwds{"newpass"}); 44 my $passconf = ($passwds{"passconf"}); 45 my $newenable = ($passwds{"newenable"}); 46 my $enableconf = ($passwds{"enableconf"}); 47 48 49 ## Following stuff only for testing, 50 ## since they display what's so carefully hidden 51 ## using Term::Readky's ReadMode('noecho'). 52 53 54 # print values via named scalars: 55 #print $oldpass, "\n" 56 #print $oldenable, "\n" 57 #print $newpass, "\n" 58 #print $passconf, "\n" 59 #print $newenable, "\n" 60 #print $enableconf, "\n" 61 62 63 # print values individually: 64 #print $passwds{"oldpass"}, "\n" 65 #print $passwds{"oldenable"}, "\n" 66 #print $passwds{"newpass"}, "\n" 67 #print $passwds{"passconf"}, "\n" 68 #print $passwds{"newenable"}, "\n" 69 #print $passwds{"enableconf"}, "\n" 70 #print "\n" 71 72 73 # print all key/value pairs for both hashes: 74 #print Dumper(%prompts), "\n" 75 #print Dumper(%passwds), "\n" 76 77 78 # print all 6 key/value pairs: 79 #while ((my $key, my $value) = each %passwds) { 80 # print " $key => $value\n" 81 #} 82 #print "\n" 83 84 85 # print all 6 keys: 86 #for my $passwd (keys %passwds) { 87 # print " $passwd \n" 88 #} 89 #print "\n" 90 91 92 # print all 6 values: 93 #for my $passwd (values %passwds) { 94 # print " $passwd \n" 95 #} 96 #print "\n"
Re: Scalars as hash keys?
by AgentM (Curate) on Oct 26, 2000 at 22:39 UTC
    just for debug purposes, you could try system('stty -noecho'); or on other UN*X- system('ssty -echo'); or some variant thereof and still use normal input and see if your problem still pops up. Or for a heavy duty program- convert to use Curses; (it's fun and entertaining and looks nice with colors!- not really necessary for this script but it's an option...) Update: Good call Fastolfe: i didn't catch that.
    AgentM Systems nor Nasca Enterprises nor Bone::Easy nor Macperl is responsible for the comments made by AgentM. Remember, you can build any logical system with NOR.
Re: Scalars as hash keys?
by ChOas (Curate) on Oct 27, 2000 at 15:18 UTC
    I'm sorry, I'm a lazy programmer, and when I can ask
    The user something and I can pose the question myself...

    I'm not gonna load an extra module
    #!/usr/bin/perl -w use strict; use Term::ReadKey; my %Prompts=( 'Step 1: Enter old password: ' => 'oldpass', 'Step 2: Enter old enable password: ' => 'oldenable', 'Step 3: Enter new password: ' => 'newpass', 'Step 4: Confirm new password: ' => 'passconf', 'Step 5: Enter new enable password : ' => 'newenable', 'Step 6: Confirm new enable password: ' => 'enableconf'); my $Key; my %Passwd; foreach my $Prompt (sort keys %Prompts) { print "$Prompt"; ReadMode('noecho'); chomp($Passwd{$Prompt} = <STDIN>); ReadMode(0); };

    I hope this wont cost me XP... ;))

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://38699]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (9)
As of 2024-04-18 20:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found