Password generator: Difference between revisions

Ada version
(Ada version)
Line 315:
rnddat: resb 4 ; RNG state
buffer: resb 257 ; Space to store password</lang>
 
=={{header|Ada}}==
<lang Ada>with Ada.Numerics.Discrete_Random;
with Ada.Strings.Fixed;
with Ada.Command_Line;
with Ada.Integer_Text_IO;
with Ada.Text_IO;
 
procedure Mkpw is
 
procedure Put_Usage;
procedure Parse_Command_Line (Success : out Boolean);
function Create_Password (Length : in Positive;
Safe : in Boolean)
return String;
 
procedure Put_Usage is
use Ada.Text_IO;
begin
Put_Line ("Usage: ");
Put_Line (" mkpw help - Show this help text ");
Put_Line (" mkpw [count <n>] [length <l>] [seed <s>] [safe] ");
Put_Line (" count <n> - Number of passwords generated (default 4)");
Put_Line (" length <l> - Password length (min 4) (default 4)");
Put_Line (" seed <l> - Seed for random generator (default 0)");
Put_Line (" safe - Do not use unsafe characters (0O1lIS52Z)");
end Put_Usage;
 
Lower_Set : constant String := "abcdefghijklmnopqrstuvwxyz";
Upper_Set : constant String := "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
Digit_Set : constant String := "0123456789";
Spec_Set : constant String := "!""#$%&'()*+,-./:;<=>?@[]^_{|}~";
Unsafe_Set : constant String := "0O1lI5S2Z";
 
Full_Set : constant String := Lower_Set & Upper_Set & Digit_Set & Spec_Set;
subtype Full_Indices is Positive range Full_Set'Range;
 
package Full_Index_Generator is
new Ada.Numerics.Discrete_Random (Full_Indices);
 
Index_Generator : Full_Index_Generator.Generator;
 
Config_Safe : Boolean := False;
Config_Count : Natural := 4;
Config_Length : Positive := 6;
Config_Seed : Integer := 0;
Config_Show_Help : Boolean := False;
 
procedure Parse_Command_Line (Success : out Boolean) is
use Ada.Command_Line;
Got_Safe, Got_Count : Boolean := False;
Got_Length, Got_Seed : Boolean := False;
Last : Positive;
Index : Positive := 1;
begin
Success := False;
if Argument_Count = 1 and then Argument (1) = "help" then
Config_Show_Help := True;
return;
end if;
 
while Index <= Argument_Count loop
if Ada.Command_Line.Argument (Index) = "safe" then
if Got_Safe then
return;
end if;
Got_Safe := True;
Config_Safe := True;
Index := Index + 1;
elsif Argument (Index) = "count" then
if Got_Count then
return;
end if;
Got_Count := True;
Ada.Integer_Text_IO.Get (Item => Config_Count,
From => Argument (Index + 1),
Last => Last);
if Last /= Argument (Index + 1)'Last then
return;
end if;
Index := Index + 2;
elsif Argument (Index) = "length" then
if Got_Length then
return;
end if;
Got_Length := True;
Ada.Integer_Text_IO.Get (Item => Config_Length,
From => Argument (Index + 1),
Last => Last);
if Last /= Argument (Index + 1)'Last then
return;
end if;
if Config_Length < 4 then
return;
end if;
Index := Index + 2;
elsif Argument (Index) = "seed" then
if Got_Seed then
return;
end if;
Got_Seed := True;
Ada.Integer_Text_IO.Get (Item => Config_Seed,
From => Argument (Index + 1),
Last => Last);
if Last /= Argument (Index + 1)'Last then
return;
end if;
Index := Index + 2;
else
return;
end if;
end loop;
Success := True;
exception
when Constraint_Error | Ada.Text_IO.Data_Error =>
null;
end Parse_Command_Line;
 
function Create_Password (Length : in Positive;
Safe : in Boolean)
return String
is
 
function Get_Random (Safe : in Boolean)
return Character;
 
function Get_Random (Safe : in Boolean)
return Character
is
use Ada.Strings.Fixed;
C : Character;
begin
loop
C := Full_Set (Full_Index_Generator.Random (Index_Generator));
if Safe then
exit when Index (Source => Unsafe_Set, Pattern => "" & C) = 0;
else
exit;
end if;
end loop;
return C;
end Get_Random;
 
function Has_Four (Item : in String)
return Boolean;
 
function Has_Four (Item : in String)
return Boolean
is
use Ada.Strings.Fixed;
Has_Upper, Has_Lower : Boolean := False;
Has_Digit, Has_Spec : Boolean := False;
begin
for C of Item loop
if Index (Upper_Set, "" & C) /= 0 then Has_Upper := True; end if;
if Index (Lower_Set, "" & C) /= 0 then Has_Lower := True; end if;
if Index (Digit_Set, "" & C) /= 0 then Has_Digit := True; end if;
if Index (Spec_Set, "" & C) /= 0 then Has_Spec := True; end if;
end loop;
return Has_Upper and Has_Lower and Has_Digit and Has_Spec;
end Has_Four;
 
Password : String (1 .. Length);
begin
loop
for I in Password'Range loop
Password (I) := Get_Random (Safe);
end loop;
exit when Has_Four (Password);
end loop;
return Password;
end Create_Password;
 
Parse_Success : Boolean;
begin
 
Parse_Command_Line (Parse_Success);
 
if Config_Show_Help or not Parse_Success then
Put_Usage; return;
end if;
 
if Config_Seed = 0 then
Full_Index_Generator.Reset (Index_Generator);
else
Full_Index_Generator.Reset (Index_Generator, Config_Seed);
end if;
 
for Count in 1 .. Config_Count loop
Ada.Text_IO.Put_Line (Create_Password (Length => Config_Length,
Safe => Config_Safe));
end loop;
 
end Mkpw;</lang>
{{out}}
<pre>$ ./mkpw count 8 length 22 safe
">M<P]GMHf77cbT%b8.eX]
W3Q&k~L*R,z)39(a{AvGon
3Xvh=:P9BGGU$=YPD{dFW@
^X)]vV4fFtCXksgv+,usHx
$89*bxyb?@aQEQ8~~vaq9o
FW{F*-]tDJH~]/7CLtRe-k
6%K6(8&fyX=,&TBFvW%kz3
+@pyJ'3YQ'%~9?Tm/BHk?A</pre>
 
=={{header|AWK}}==
210

edits