Mercurial > make_username
changeset 3:fa7be81d0e33
Many changes: Made generic, not cPanel specific. Reads /etc/passwd using fast I/O to check for existing users. Converted to standalone command line utility with several options: -h -d -t -m
author | Eris Caffee <discordia@eldalin.com> |
---|---|
date | Mon, 18 Jul 2011 07:01:16 -0500 |
parents | 706c20861682 |
children | |
files | make-username.pl passwd-huge.gz passwd.gz |
diffstat | 3 files changed, 191 insertions(+), 59 deletions(-) [+] |
line diff
1.1 --- a/make-username.pl Sat Jul 16 13:23:21 2011 -0500 1.2 +++ b/make-username.pl Mon Jul 18 07:01:16 2011 -0500 1.3 @@ -1,72 +1,123 @@ 1.4 #!/usr/bin/env perl 1.5 1.6 +################################################################################ 1.7 +# 1.8 +# Creates a new unused username for use on a cPanel server. 1.9 +# 1.10 +################################################################################ 1.11 + 1.12 +use 5.010; 1.13 + 1.14 use warnings; 1.15 use strict; 1.16 +use English; 1.17 +use File::Basename; 1.18 1.19 -my $base; 1.20 -my $user ; 1.21 +my $base =""; 1.22 +my $user; 1.23 +my $debug = 0; 1.24 +my $maxlen = 8; 1.25 +my $test = 0; 1.26 1.27 -$base = ""; 1.28 -$user = make_username($base); 1.29 -printf("%30s %s\n", $base, $user); 1.30 +foreach my $arg (@ARGV) { 1.31 + if ("-d" eq $arg) { 1.32 + $debug = 1; 1.33 + } elsif ($arg =~ /^-m/) { 1.34 + $arg =~ s/^..//; 1.35 + if ($arg =~ /^(\d+)$/) { 1.36 + $maxlen = $1; 1.37 + $debug and print "Setting maxlen to $maxlen\n"; 1.38 + } else { 1.39 + printf(STDERR "Invalid username length specified: $arg\n"); 1.40 + } 1.41 + } elsif ($arg eq "-h") { 1.42 + usage(); 1.43 + exit 0; 1.44 + } elsif ($arg eq "-t") { 1.45 + $test = 1; 1.46 + } else { 1.47 + $base = $arg; 1.48 + } 1.49 +} 1.50 1.51 -$base = "eightchr"; 1.52 -$user = make_username($base); 1.53 -printf("%30s %s\n", $base, $user); 1.54 +if (! $test) { 1.55 + $user = make_username($base); 1.56 + defined $user and printf("%s\n", $user); 1.57 + exit 0; 1.58 +} else { 1.59 + my $pwdfile = "passwd"; 1.60 + $base = ""; 1.61 + my $t1 = time; 1.62 + $user = make_username($base, $pwdfile); 1.63 + my $t2 = time; 1.64 + defined $user and printf("%30s %-".$maxlen."s in %ds\n", $base, $user, $t2 - $t1); 1.65 + 1.66 + $base = "eightchr"; 1.67 + $t1 = time; 1.68 + $user = make_username($base, $pwdfile); 1.69 + $t2 = time; 1.70 + defined $user and printf("%30s %-".$maxlen."s in %ds\n", $base, $user, $t2 - $t1); 1.71 + 1.72 + $base = "short"; 1.73 + $t1 = time; 1.74 + $user = make_username($base, $pwdfile); 1.75 + $t2 = time; 1.76 + defined $user and printf("%30s %-".$maxlen."s in %ds\n", $base, $user, $t2 - $t1); 1.77 + 1.78 + $base = "this *&% is not allowed &^$%&^m"; 1.79 + $t1 = time; 1.80 + $user = make_username($base, $pwdfile); 1.81 + $t2 = time; 1.82 + defined $user and printf("%30s %-".$maxlen."s in %ds\n", $base, $user, $t2 - $t1); 1.83 1.84 -$base = "short"; 1.85 -$user = make_username($base); 1.86 -printf("%30s %s\n", $base, $user); 1.87 + $base = "123digits"; 1.88 + $t1 = time; 1.89 + $user = make_username($base, $pwdfile); 1.90 + $t2 = time; 1.91 + defined $user and printf("%30s %-".$maxlen."s in %ds\n", $base, $user, $t2 - $t1); 1.92 1.93 -$base = "this *&% is not allowed &^$%&^m"; 1.94 -$user = make_username($base); 1.95 -printf("%30s %s\n", $base, $user); 1.96 + $base = "this-is-a-domain.com"; 1.97 + $t1 = time; 1.98 + $user = make_username($base, $pwdfile); 1.99 + $t2 = time; 1.100 + defined $user and printf("%30s %-".$maxlen."s in %ds\n", $base, $user, $t2 - $t1); 1.101 1.102 -$base = "123digits"; 1.103 -$user = make_username($base); 1.104 -printf("%30s %s\n", $base, $user); 1.105 + $base = '&$%#&$*&$%*&'; 1.106 + $t1 = time; 1.107 + $user = make_username($base, $pwdfile); 1.108 + $t2 = time; 1.109 + defined $user and printf("%30s %-".$maxlen."s in %ds\n", $base, $user, $t2 - $t1); 1.110 1.111 -$base = "this-is-a-domain.com"; 1.112 -$user = make_username($base); 1.113 -printf("%30s %s\n", $base, $user); 1.114 + $base = "testqwer"; 1.115 + $t1 = time; 1.116 + $user = make_username($base, $pwdfile); 1.117 + $t2 = time; 1.118 + defined $user and printf("%30s %-".$maxlen."s in %ds\n", $base, $user, $t2 - $t1); 1.119 1.120 -$base = '&$%#&$*&$%*&'; 1.121 -$user = make_username($base); 1.122 -printf("%30s %s\n", $base, $user); 1.123 + $base = "testabc"; 1.124 + $t1 = time; 1.125 + $user = make_username($base, $pwdfile); 1.126 + $t2 = time; 1.127 + defined $user and printf("%30s %-".$maxlen."s in %ds\n", $base, $user, $t2 - $t1); 1.128 1.129 -# For the next test, run this first in the shell as root (not on a production system, obviously!): 1.130 -# 1.131 -# [ ! -d /var/cpanel/users ] && mkdir -p /var/cpanel/users 1.132 -# touch /var/cpanel/users/testqwer 1.133 -# touch /var/cpanel/users/testabc 1.134 -# i=1 ; while [ $i -lt 10 ] ; do touch /var/cpanel/users/testabc${i} ; let i=$i+1 ; done 1.135 -# touch /var/cpanel/users/testzx 1.136 -# i=1 ; while [ $i -lt 100 ] ; do touch /var/cpanel/users/testzx${i} ; let i=$i+1 ; done 1.137 -# touch /var/cpanel/users/test 1.138 -# i=1 ; while [ $i -lt 100 ] ; do touch /var/cpanel/users/test${i} ; let i=$i+1 ; done 1.139 -# touch /var/cpanel/users/t 1.140 -# i=1 ; while [ $i -lt 10346 ] ; do touch /var/cpanel/users/t${i} ; let i=$i+1 ; done 1.141 + $base = "testzx"; 1.142 + $t1 = time; 1.143 + $user = make_username($base, $pwdfile); 1.144 + $t2 = time; 1.145 + defined $user and printf("%30s %-".$maxlen."s in %ds\n", $base, $user, $t2 - $t1); 1.146 1.147 -$base = "testqwer"; 1.148 -$user = make_username($base); 1.149 -printf("%30s %s\n", $base, $user); 1.150 + $base = "test"; 1.151 + $t1 = time; 1.152 + $user = make_username($base, $pwdfile); 1.153 + $t2 = time; 1.154 + defined $user and printf("%30s %-".$maxlen."s in %ds\n", $base, $user, $t2 - $t1); 1.155 1.156 -$base = "testabc"; 1.157 -$user = make_username($base); 1.158 -printf("%30s %s\n", $base, $user); 1.159 - 1.160 -$base = "testzx"; 1.161 -$user = make_username($base); 1.162 -printf("%30s %s\n", $base, $user); 1.163 - 1.164 -$base = "test"; 1.165 -$user = make_username($base); 1.166 -printf("%30s %s\n", $base, $user); 1.167 - 1.168 -$base = "t"; 1.169 -$user = make_username($base); 1.170 -printf("%30s %s\n", $base, $user); 1.171 - 1.172 + $base = "t"; 1.173 + $t1 = time; 1.174 + $user = make_username($base, $pwdfile); 1.175 + $t2 = time; 1.176 + defined $user and printf("%30s %-".$maxlen."s in %ds\n", $base, $user, $t2 - $t1); 1.177 +} 1.178 1.179 sub make_username { 1.180 # Arguments: 1.181 @@ -81,12 +132,19 @@ 1.182 # A string containing the new username or undef if no username 1.183 # could be generated (unlikely) 1.184 1.185 - my ($base) = @_; 1.186 + my ($base, $pwdfile) = @_; 1.187 1.188 if ($base eq "") { 1.189 $base = "user"; 1.190 } 1.191 1.192 + ! defined $pwdfile and $pwdfile = "/etc/passwd"; 1.193 + 1.194 + if (! -e $pwdfile) { 1.195 + printf(STDERR "Error: non-existant passwd file specified: $pwdfile\n"); 1.196 + return undef; 1.197 + } 1.198 + 1.199 # Remove non-alpha-numeric characters and make sure the first character is a letter. 1.200 $base =~ s/[^A-Za-z0-9]//g; 1.201 if ($base !~ /^[a-z]/ ) { 1.202 @@ -98,17 +156,91 @@ 1.203 # Print the number into the last portion of the new username. 1.204 # Delete spaces (in case the passed username candidate was short). 1.205 # Churn until we find an unused name. 1.206 + my $tries=0; 1.207 my $i=1; 1.208 my $numstr; 1.209 - my $newuser = sprintf("%.8s", $base); 1.210 - while ( (-e "/var/cpanel/users/$newuser") && ($i < 10000000) ) { 1.211 + my $newuser = sprintf("%.".$maxlen."s", $base); 1.212 + 1.213 + 1.214 + # ----- Times: 88s, 89s, 85s ----- 1.215 + # open(F,$pwdfile); 1.216 + # my @passwd=<F>; 1.217 + # close F; 1.218 + # while ((grep {/^${newuser}:/ } @passwd) && ($i < 10000000) ) { 1.219 + 1.220 + # ----- Times: 67s, 67s, 67s ----- 1.221 + # while ( (! system('grep -qsP "^'.$newuser.':" '.$pwdfile)) && ($i < 10000000) ) { 1.222 + 1.223 + # ----- with user_exists1() Times: 47s, 50s, 50s ----- 1.224 + # ----- with user_exists() using sysread Times: 4s, 4s, 4s ----- 1.225 + while ( (user_exists($newuser, $pwdfile)) && ($i < 10000000) ) { 1.226 + $tries = 1; 1.227 $numstr = sprintf("%d", $i); 1.228 - $newuser = sprintf("%-8s", $base); 1.229 + $newuser = sprintf("%-".$maxlen."s", $base); 1.230 substr($newuser, -length($numstr), length($numstr), $numstr); 1.231 $newuser =~ s/ //g; 1.232 $i++; 1.233 + $debug and printf(STDERR "Checking for $newuser\n"); 1.234 } 1.235 1.236 - $i == 10000000 && return undef; 1.237 + $i == 10000000 and return undef; 1.238 + $debug and print "final is $newuser in $tries attempts\n"; 1.239 return $newuser; 1.240 } 1.241 + 1.242 +sub user_exists { 1.243 + my ($user, $pwdfile) = @_; 1.244 + 1.245 + my $retval = 0; 1.246 + my $i; 1.247 + my $buffer; 1.248 + 1.249 + open my $handle, "<", $pwdfile; 1.250 + while (sysread($handle, $buffer, 65536, 0)) { 1.251 + if ($buffer =~ /(^|\n)${user}:/) { 1.252 + $retval = 1; 1.253 + last; 1.254 + } 1.255 + } 1.256 + close $handle; 1.257 + return $retval; 1.258 +} 1.259 + 1.260 +sub user_exists1 { 1.261 + my ($user, $pwdfile) = @_; 1.262 + my $retval = 0; 1.263 + open my $handle, "<", $pwdfile; 1.264 + while (<$handle>) { 1.265 + if ($_ =~ /^${user}:/) { 1.266 + $retval = 1; 1.267 + last; 1.268 + } 1.269 + } 1.270 + close $handle; 1.271 + return $retval; 1.272 +} 1.273 + 1.274 +################################################################################ 1.275 +sub usage { 1.276 + printf( 1.277 +"Usage: ".basename($PROGRAM_NAME)." [-h] [-d] [-mM] [-t] [basename] 1.278 + 1.279 +Generate a new unused username suitable for assigning to a new account. 1.280 + 1.281 +basename If specified this will be used as the basis of the new username 1.282 + 1.283 + The basename will be stripped of all characters other than letters 1.284 + and digits, and it will be truncated to no more than the maximum 1.285 + allowed username length (8 by default, but settable with the 1.286 + -m option). 1.287 + In the event that a user already exists by the given name a number 1.288 + will be inserted at the end of the username and sequentially 1.289 + increased until an available name is found. 1.290 + If basename is not specified, then \"user\" will be used as the base. 1.291 +-h Print these instructions. 1.292 +-d Enable debug messages. 1.293 +-mM Set maximum allowed username length to M (default is 8). 1.294 +-t Perform test code. You must have a suitable passwd file in the 1.295 + current directory in order to run this. 1.296 +"); 1.297 +}
2.1 Binary file passwd-huge.gz has changed
3.1 Binary file passwd.gz has changed