in reply to genpass Password Generator

Thank you everyone for your comments, critiques and suggestions. I have looked over my code and made changes where they made sense to me.

Some of the suggestions left me with nothing to do but cut and paste the code in the reply (see the GenPass function, the use of a flags hash, the heredocs tip.) I did, of course, look over what the code did and saw why it was a better way, because unlike some who post questions on forums, I have no problem doing the work, I'm not looking for other people to do the work for me. I am here to learn. I just want that to be clear.

I think the biggest efficiency tip for me was putting all the characters in a string, then using regex to pull excluded types out of the string. Not only did that alone cut nearly 50 lines of code from the script, but it also cut out all the extraoneous loops that tested "dead" value characters between 33 and 126.

One thing that I may look into is incorporating a switch to handle (or offer) different character sets.

Again, thank all you monks, and here I post the updated version. Cheers:

#!/usr/bin/perl use strict; use warnings; use Getopt::Long; Getopt::Long::Configure ("bundling"); ## PARSE AND SET COMMAND-LINE OPTIONS ## ----------------------------------------------------- my %flags=('symbols', 0, 'numbers', 0, 'uppercase', 0, 'lowercase', 0, + 'confusable', 0, 'help', 0, 'qty', 1); GetOptions( 's|S|symbols' => \$flags{symbols}, 'n|N|numbers' => \$flags{numbers}, 'u|U|uppercase' => \$flags{uppercase}, 'l|L|lowercase' => \$flags{lowercase}, 'c|C|confusable' => \$flags{confusable}, 'q|Q:i' => \$flags{qty}, 'help' => \$flags{help}, ); # Set password characters, excluding those flagged on the command-line my $pwdchars = join( '', map {chr} ( 0x21 .. 0x7e )); $pwdchars =~ s/\d+// if ( $flags{numbers} ); $pwdchars =~ s/[A-Z]+// if ( $flags{uppercase} ); $pwdchars =~ s/[a-z]+// if ( $flags{lowercase} ); $pwdchars =~ s/[_\W]+//g if ( $flags{symbols} ); $pwdchars =~ tr/1Il0O//d if ( $flags{confusable} ); # If user triggered the --help option flag, display and exit if ($flags{help}) { &DisplayUsage(); exit(); } ## START VALIDATE INPUT ## ----------------------------------------------------- my $kill=0; # flag to stop the script if input is invalid (or - +-help is used) my @errmsg; # error message descriptions # If -q option was used to set a quantity of passwords, make sure it c +ontains at # least a value of 1 so that a password can be generated if ($flags{qty} == 0 || $flags{qty} < 0) { $flags{qty}=1; } # Check that user hasn't excluded all character-types, warn user, kill + script if ( length($pwdchars) == 0) { push @errmsg, "** 0x1: At least 1 character-type must be included" +; $kill=1; } # Check that user has passed only 1 argument (LENGTH) other than optio +ns flags, warn user, kill script if ($#ARGV > 0 || $#ARGV < 0) { push @errmsg, "** 0x2: Incorrect number of arguments passed"; $kill=1; } # Check for only numeric input in LENGTH argument, warn user, kill scr +ipt if ($ARGV[0] !~ /^[0-9]+$/) { push @errmsg, "** 0x3: Invalid input. LENGTH argument must be +a numeric value"; $kill=1; } # If any of the above validation tests triggered the $kill flag... if ($kill == 1) { print "\n** GENPASS ERROR ---------------------------------------- +-----------------"; print "\n** ".@errmsg." Error(s) found"; # display number of +errors foreach my $err (@errmsg) { # display error messages print "\n".$err; } print "\n**\n** Type genpass --help for command usage\n"; print "** -------------------------------------------------------- +---------------\n\n"; exit(); # exit script } ## END VALIDATE INPUT ## START MAIN SCRIPT ## ----------------------------------------------------- # From 1 to qty for ( 1..$flags{qty} ) { print &GenPass( $ARGV[0] )."\n"; } exit(); ## END MAIN SCRIPT ## FUNCTION DEFINITIONS ## ----------------------------------------------------- sub GenPass() { my ($pwdlen) = @_; my $limit = length( $pwdchars ); my $pwd = ''; for ( 0..$pwdlen-1 ) { $pwd .= substr( $pwdchars, rand( $limit ), 1 ); } return $pwd; } # use Here-Documents to display usage text sub DisplayUsage { print <<" USAGE"; Usage: genpass [-OPTIONS] LENGTH Generate secure passwords LENGTH characters long. -s, --symbols\t\tExclude symbols. -n, --numbers\t\tExclude numbers. -u, --uppercase\t\tExclude uppercase letters. -l, --lowercase\t\tExclude lowercase letters. -c, --confusable\tExclude confusable characters like: l,I,1,0,O -q(X)\t\t\tCreate X number of passwords. --help\t\t\tDisplay this usage screen. Report bugs, comments, and questions to jbrown_home\@yahoo.ca USAGE } __END__

Replies are listed 'Best First'.
Re^2: genpass Password Generator
by munkyeetr (Initiate) on Jun 04, 2007 at 03:06 UTC
    Sorry, I wasn't logged in when I posted that last...That was me, munkyeetr.

      A few more comments mixing in random order matters of personal style and more substantial things:

      Putting all of the above (and a few minor cosmetic touches) together:

      Some tests:

      One thing that I may look into is incorporating a switch to handle (or offer) different character sets.

      That, IMO, would be asking for a lot of trouble that you really don't need, in order to supply a "feature" that virtually all sensible users really don't want.

      Frankly, the world is just not ready yet for passwords containing non-ASCII characters. Not only do we lack stable/consistent conventions for their keyboard entry, but their encoding and transmission are still mired in an embarrassingly wide range of "alternative methods" and obscure constraints. Forget about it.