PERL

Hiding Keyboard Input From the Screen

For my current job I'm in charge of writing a script that requires a person to input their password and me being the semi-security conscious individual that I am knew that regular input for a script like this would be bad, as that would allow for over the shoulder (literally) view of someone's password. This is just unacceptable.

To solve this problem I hit the internets for a way to hide user input in Perl script. And in my travels I came across this old PERL FAQ site. I decided to try out the code and update it, throw it into a little dummy script. This is what I got (minus the dummy script):

  1. sub get_password
  2. {
  3. print "enter your password: ";
  4. system("stty -echo");
  5. chop(my $password=<>);
  6. print "\n";
  7. system("stty echo");
  8.  
  9. return $password;
  10. }

Saved it, ran it, and Holy Missing Characters Batman, it worked. So just as a mental exercise, I wanted to see if I could get it to emulate the password request when you run sudo, and I wrote this up in Python (because I need the practice):

  1. #!/usr/bin/python
  2.  
  3. import os
  4. import getpass
  5.  
  6. def get_password():
  7. #print "Please enter your password:"
  8. os.system("stty -echo")
  9. password = raw_input( getpass.getuser() + "'s password")
  10. os.system("stty echo")
  11. print "\n"
  12.  
  13. return password
  14.  
  15. def main():
  16. local_password = get_password()
  17. print local_password
  18.  
  19. main()

And again... it worked. Of course I finally realized that the reason why it worked is because of the line "stty -echo". Taking that I typed it into a standard terminal and after hitting enter the results were the same. My terminal functioned normally, but without showing me the characters I was typing. After returning my terminal back to normal I decided to read a little more about stty. After digging through the man page for a little while I came across this argument which is an alias for echo:

[-]crterase
echo erase characters as backspace-space-backspace

Thus the reason why I couldn't see anything change is because my terminal is treating all characters I type on the screen as a three part sequence of non alphanumeric characters. Although I find this a little odd; I have to just go with the words of Bugs Bunny on this one, “I don't ask questions. I just have fun.”

Interview question: Recreate groups

I was in an interview and another interview walked in and said “Hi, do you know the groups tool in unix?” At which point i said “Yes”. At which point the interview hands me a whiteboard marker and says “Great. Write it”. And after a couple of minutes of thinking about how to do it, I wrote it down.

Now, I didn't end up doing it on a whiteboard, I did it on a piece of paper I had, which I kept, but unfortunately I have not beed able to scan it for everyone's reading enjoyment. But I'll do that in the future.

So once I got home after the interview, I took the algorithm, and applied proper PERL syntax. And here is the code:

  1. #!/usr/bin/perl
  2. #######################################################################
  3. # Created By: Bryce Verdier
  4. # on 1/19/10
  5. # Function: rework the output of the unix groups command
  6. # NOTE: FOR USE ON UNIX MACHINES!
  7. #######################################################################
  8. use warnings;
  9. use strict;
  10. use Getopt::Std;
  11.  
  12. our($opt_u);
  13. getopts('u:');
  14.  
  15. #Get the results from /etc/groups
  16. my $groups= `grep -w $opt_u /etc/group`;
  17.  
  18. #split it into an array for per line processing
  19. my @split_groups= split(/\n/, $groups);
  20.  
  21. #output the username we're looking for ( to emulate groups better)
  22. print ("$opt_u : ");
  23.  
  24. #where all the magic really happens
  25. #split the array again, and output the first part of the split, as based
  26. #on the strcuture of the /etc/groups file
  27. foreach (@split_groups){
  28. my @temp_split= split(/:/, $_);
  29. print ("$temp_split[0] ");
  30. }
  31.  
  32. #clean up
  33. print ("\n");

So after writing the code above originally, the interviewer looks things over and asks me a couple of questions. I don't remember all of them, the only one I can remember now ( almost two weeks later ) is below:

“Why are you using calling out instead of using a system call?”
After looking around, PERL's systems calls abilities are fairly minimal. I could open a file, and parse through it. But I figured why not save myself some of the work and use the tools in the shell to ease my work.

Regardless, if you are in preparing for an interview maybe this might give you a leg up. Or at least now other interviewers will have to start using a different question.

Pop Quiz

So, while at work you wrote some scripts. And after a code review your boss tells you that he would like to see some variable names changed, to help make the code more readable. So at the beginning of your code you have:

#set script variables
use vars qw/ %opts /;
my $append="\@pdx\.edu";

getopts( 'hrl:m:',\%opts );

#make sure the arguments are provided, fail if #not
usage() if ( $opts{h} || (!$opts{m} || !$opts{l}));

#everything's good, program can start now
my $ldap= signin('true') || die;

#rename variables from opts to something more #"readable"
my $username= $opts{l};
my $mail_alias= $opts{m};
my $remove_flag= $opts{r};

But below this code section, $opts is being called quite a few times, and the script is another 100 hundred lines of code or so. So what do you do?

1)Tell your boss how adding these variables will reduce efficiency and the overall speed of the code and revert the variables name.
2)Do the changes manually
3)open up vim or use sed with the expression s/$opts{}/$/g
4)I don't care... but I do wanna see what you think
5)Other (Please leave a comment. How else will the rest of us learn?)

Answer:

Ok, this isn't the “only” answer, but it is what I did. Opened up VIM, and used the following commands:

:32,$ s/$opts{l}/$username/g
:32,$ s/$opts{r}/$remove_flag/g
:32,$ s/$opts{m}/$mail_alias/g

For those of you not familiar with this let me explain. The explore the first part “:31,$”. The “:” is just a way to signify to vim that your going to preform a command. And the “31,$” is saying between lines 31 and the end of the file (which is what $ means). And then the second part s/$opts{l}/$username/g the command itself. It says that your going to substitute an instance of $opts{l} for $username. The ending g means to it more than once.

So when you put the whole command together you get, between line 31 and the end of the file, replace all instances of $opts{l} with $username.

Hopefully this will help someone else as much as it helped me.

Syndicate content