/dev/random
by: G.E. Ozz Nixon Jr.
Published: May 2009
©opyright 2009 by Friends of FPC
While researching a random character generator for a routine to generate a new password when someone forgets theirs... I came across
the following code (I ported to FPC) which reads random numbers from the linux device urandom (/dev/urandom).
//////////////////////////////////////////////////////////////
// Application: devrandom
// Author: G.E. Ozz Nixon Jr.
// ===========================================================
// Code ported from: http://www.linuxquestions.org/questions/programming-9/shell-script-random-variable-4088/
//
// RANGES: ./devrandom 0 999999999
//////////////////////////////////////////////////////////////
{$mode DELPHI} // for "raise"
uses
sysutils, // for format, and exception
baseunix;
var
fd:longint;
result:longint;
min,max:longint;
number:int64;
err:longint;
begin
if paramcount=2 then begin
val(paramstr(1),min,err);
val(paramstr(2),max,err);
end
else if paramcount=1 then begin
min := 0;
val(paramstr(1),max,err);
end
else begin
system.writeln('Usage: devrandom [[min] max]');
halt(2);
end;
fd := fpopen('/dev/urandom', O_RDONLY);
if fd<0 then begin
raise exception.create('');
halt(1);
end;
result := fpread(fd, @number, sizeof(number));
if result<0 then begin
raise exception.create('');
halt(1);
end;
fpclose(fd); // was missing in the C code!
number := number shr 1;
number := number mod (max - min + 1) + min;
system.writeln(format('%d', [number]));
halt(0);
end.
In the above code the application is opening a
Linux device as a file and reading sizeof(number) bytes into the memory address
reserved by number. Finally it does a shr to drop the negative bit, then using
math it does a mod to make sure the result is between min and max. One of the
flaws to this concept is the use of
mod affects the
quality of
the random. The modulo operation finds the remainder of the division. Whereas,
random is working bit by bit to truly generate a unique bit pattern (byte).
Doing a shr to drop the sign also changes
the value luckily we could simply say
number := abs(number); in pascal
to simply do shl 1, shr 1 ... while forcing the bit to be zero. Another possible
solution, which I prefer is to use bitwise AND and drop the "sign" bit.
number := number and $7FFFFFFF; // this works for all languages
G.E. Ozz Nixon Jr.