# HG changeset patch # User Eris Caffee # Date 1310991192 18000 # Node ID 742a3d2c99d64face2f7f7668cd6af9c681cae09 # Parent 706c20861682d2f1885cc435fd9919fc9d83e914 Removed commented code and timing notes left from I/O testing. diff -r 706c20861682 -r 742a3d2c99d6 make-username.pl --- a/make-username.pl Sat Jul 16 13:23:21 2011 -0500 +++ b/make-username.pl Mon Jul 18 07:13:12 2011 -0500 @@ -2,71 +2,90 @@ use warnings; use strict; +use English; +use File::Basename; -my $base; -my $user ; +my $base =""; +my $user; +my $debug = 0; +my $maxlen = 8; +my $test = 0; -$base = ""; -$user = make_username($base); -printf("%30s %s\n", $base, $user); +foreach my $arg (@ARGV) { + if ("-d" eq $arg) { + $debug = 1; + } elsif ($arg =~ /^-m/) { + $arg =~ s/^..//; + if ($arg =~ /^(\d+)$/) { + $maxlen = $1; + $debug and print "Setting maxlen to $maxlen\n"; + } else { + printf(STDERR "Invalid username length specified: $arg\n"); + } + } elsif ($arg eq "-h") { + usage(); + exit 0; + } elsif ($arg eq "-t") { + $test = 1; + } else { + $base = $arg; + } +} -$base = "eightchr"; -$user = make_username($base); -printf("%30s %s\n", $base, $user); +if (! $test) { + $user = make_username($base); + defined $user and printf("%s\n", $user); + exit 0; +} else { + my $pwdfile = "passwd"; + $base = ""; + $user = make_username($base, $pwdfile); + defined $user and printf("%30s %s\n", $base, $user); + + $base = "eightchr"; + $user = make_username($base, $pwdfile); + defined $user and printf("%30s %s\n", $base, $user); + + $base = "short"; + $user = make_username($base, $pwdfile); + defined $user and printf("%30s %s\n", $base, $user); + + $base = "this *&% is not allowed &^$%&^m"; + $user = make_username($base, $pwdfile); + defined $user and printf("%30s %s\n", $base, $user); -$base = "short"; -$user = make_username($base); -printf("%30s %s\n", $base, $user); + $base = "123digits"; + $user = make_username($base, $pwdfile); + defined $user and printf("%30s %s\n", $base, $user); -$base = "this *&% is not allowed &^$%&^m"; -$user = make_username($base); -printf("%30s %s\n", $base, $user); + $base = "this-is-a-domain.com"; + $user = make_username($base, $pwdfile); + defined $user and printf("%30s %s\n", $base, $user); -$base = "123digits"; -$user = make_username($base); -printf("%30s %s\n", $base, $user); + $base = '&$%#&$*&$%*&'; + $user = make_username($base, $pwdfile); + defined $user and printf("%30s %s\n", $base, $user); -$base = "this-is-a-domain.com"; -$user = make_username($base); -printf("%30s %s\n", $base, $user); + $base = "testqwer"; + $user = make_username($base, $pwdfile); + defined $user and printf("%30s %s\n", $base, $user); -$base = '&$%#&$*&$%*&'; -$user = make_username($base); -printf("%30s %s\n", $base, $user); + $base = "testabc"; + $user = make_username($base, $pwdfile); + defined $user and printf("%30s %s\n", $base, $user); -# For the next test, run this first in the shell as root (not on a production system, obviously!): -# -# [ ! -d /var/cpanel/users ] && mkdir -p /var/cpanel/users -# touch /var/cpanel/users/testqwer -# touch /var/cpanel/users/testabc -# i=1 ; while [ $i -lt 10 ] ; do touch /var/cpanel/users/testabc${i} ; let i=$i+1 ; done -# touch /var/cpanel/users/testzx -# i=1 ; while [ $i -lt 100 ] ; do touch /var/cpanel/users/testzx${i} ; let i=$i+1 ; done -# touch /var/cpanel/users/test -# i=1 ; while [ $i -lt 100 ] ; do touch /var/cpanel/users/test${i} ; let i=$i+1 ; done -# touch /var/cpanel/users/t -# i=1 ; while [ $i -lt 10346 ] ; do touch /var/cpanel/users/t${i} ; let i=$i+1 ; done + $base = "testzx"; + $user = make_username($base, $pwdfile); + defined $user and printf("%30s %s\n", $base, $user); -$base = "testqwer"; -$user = make_username($base); -printf("%30s %s\n", $base, $user); + $base = "test"; + $user = make_username($base, $pwdfile); + defined $user and printf("%30s %s\n", $base, $user); -$base = "testabc"; -$user = make_username($base); -printf("%30s %s\n", $base, $user); - -$base = "testzx"; -$user = make_username($base); -printf("%30s %s\n", $base, $user); - -$base = "test"; -$user = make_username($base); -printf("%30s %s\n", $base, $user); - -$base = "t"; -$user = make_username($base); -printf("%30s %s\n", $base, $user); - + $base = "t"; + $user = make_username($base, $pwdfile); + defined $user and printf("%30s %s\n", $base, $user); +} sub make_username { # Arguments: @@ -81,12 +100,19 @@ # A string containing the new username or undef if no username # could be generated (unlikely) - my ($base) = @_; + my ($base, $pwdfile) = @_; if ($base eq "") { $base = "user"; } + ! defined $pwdfile and $pwdfile = "/etc/passwd"; + + if (! -e $pwdfile) { + printf(STDERR "Error: non-existant passwd file specified: $pwdfile\n"); + return undef; + } + # Remove non-alpha-numeric characters and make sure the first character is a letter. $base =~ s/[^A-Za-z0-9]//g; if ($base !~ /^[a-z]/ ) { @@ -98,17 +124,48 @@ # Print the number into the last portion of the new username. # Delete spaces (in case the passed username candidate was short). # Churn until we find an unused name. + my $tries=0; my $i=1; my $numstr; - my $newuser = sprintf("%.8s", $base); - while ( (-e "/var/cpanel/users/$newuser") && ($i < 10000000) ) { + my $newuser = sprintf("%.".$maxlen."s", $base); + + while ( (! system('grep -qsP "^'.$newuser.':" '.$pwdfile)) && + ($i < 10000000) ) { + $tries = 1; $numstr = sprintf("%d", $i); - $newuser = sprintf("%-8s", $base); + $newuser = sprintf("%-".$maxlen."s", $base); substr($newuser, -length($numstr), length($numstr), $numstr); $newuser =~ s/ //g; $i++; } $i == 10000000 && return undef; + $debug and print "final is $newuser in $tries attempts\n"; return $newuser; } + + +################################################################################ +sub usage { + printf( +"Usage: ".basename($PROGRAM_NAME)." [-h] [-d] [-mM] [-t] [basename] + +Generate a new unused username suitable for assigning to a new account. + +basename If specified this will be used as the basis of the new username + + The basename will be stripped of all characters other than letters + and digits, and it will be truncated to no more than the maximum + allowed username length (8 by default, but settable with the + -m option). + In the event that a user already exists by the given name a number + will be inserted at the end of the username and sequentially + increased until an available name is found. + If basename is not specified, then \"user\" will be used as the base. +-h Print these instructions. +-d Enable debug messages. +-mM Set maximum allowed username length to M (default is 8). +-t Perform test code. You must have a suitable passwd file in the + current directory in order to run this. +"); +}