|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Rand::Urandom;  | 
| 
2
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
72414
 | 
 use strict;  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
    | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
78
 | 
    | 
| 
3
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
12
 | 
 use warnings;  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
    | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
81
 | 
    | 
| 
4
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
15
 | 
 use Config;  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
    | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
111
 | 
    | 
| 
5
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
2553
 | 
 use POSIX qw(EINTR ENOSYS);  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24192
 | 
    | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
    | 
| 
6
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
4137
 | 
 use Exporter qw(import);  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
    | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2016
 | 
    | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our @EXPORT_OK = qw(perl_rand rand_bytes);  | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $VERSION = '0.03';  | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ## no critic (Subroutines::ProhibitSubroutinePrototypes)  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub use_urandom(;$) {  | 
| 
13
 | 
11
 | 
 
 | 
  
100
  
 | 
  
11
  
 | 
  
0
  
 | 
1367
 | 
 	my $max = shift || 1;  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
15
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
83
 | 
 	my $buf = rand_bytes(8);  | 
| 
16
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
 	my $n;  | 
| 
17
 | 
11
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
487
 | 
 	if($Config{'use64bitint'}) {  | 
| 
18
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
74
 | 
 		$n = unpack('Q', $buf);  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}else {  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		# just treat it as 2 longs for now...  | 
| 
21
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$n = unpack('LL', $buf);  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
23
 | 
11
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
76
 | 
 	return $n if ($max == 2**64);  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
25
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
 	$max *= $n / 2**64;  | 
| 
26
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
222
 | 
 	return $max;  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $syscall;  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $bsd;  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub try_syscall {  | 
| 
32
 | 
15
 | 
 
 | 
 
 | 
  
15
  
 | 
  
0
  
 | 
27
 | 
 	my $num = shift;  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
34
 | 
15
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
42
 | 
 	if(!defined $syscall) {  | 
| 
35
 | 
3
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
78
 | 
 		if($Config{'osname'} =~ m/openbsd/i && $Config{'archname'} =~ m/amd64/) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
36
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$syscall = 7;  | 
| 
37
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$bsd = 1;  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}elsif ($Config{'osname'} =~ m/linux/) {  | 
| 
39
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
27
 | 
 			$syscall = $Config{'archname'} =~ m/x86_64/ ? 318 : 355;  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}else {  | 
| 
41
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$syscall = -1;  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
44
 | 
15
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
45
 | 
 	return if($syscall < 0);  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
46
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
 	my $ret;  | 
| 
47
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
71
 | 
 	my $buf   = ' ' x $num;  | 
| 
48
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
 	my $tries = 0;  | 
| 
49
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
182
 | 
 	local $! = undef;  | 
| 
50
 | 
15
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
27
 | 
 	do {  | 
| 
51
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
58
 | 
 		$ret = syscall($syscall, $buf, $num, 0);  | 
| 
52
 | 
15
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
225
 | 
 		if ($! == ENOSYS) {  | 
| 
53
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
68
 | 
 			return;  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
56
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		if ($ret != ($bsd ? 0 : $num)) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
57
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			warn "Rand::Urandom: huh, getrandom() returned $ret... trying again";  | 
| 
58
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$ret = -1;  | 
| 
59
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$!   = EINTR;  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
62
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		if ($tries++ > 100) {  | 
| 
63
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			warn 'Rand::Urandom: getrandom() looped lots, falling back';  | 
| 
64
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			return;  | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} while ($ret == -1 && $! == EINTR);  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	# didn't fill in the buffer? fallback  | 
| 
69
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	return if($buf =~ m/^ +$/);  | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
71
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	return $buf;  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub rand_bytes {  | 
| 
75
 | 
15
 | 
 
 | 
 
 | 
  
15
  
 | 
  
1
  
 | 
1661
 | 
 	my $num = shift;  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
77
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
 	my $buf;  | 
| 
78
 | 
15
 | 
  
 50
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
157
 | 
 	$buf = try_syscall($num) if(!defined $syscall || $syscall > 0);  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
80
 | 
15
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
47
 | 
 	if (!$buf) {  | 
| 
81
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
41
 | 
 		local $! = undef;  | 
| 
82
 | 
15
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
363
 | 
 		my $file = -r '/dev/arandom' ? '/dev/arandom' : '/dev/urandom';  | 
| 
83
 | 
15
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
706
 | 
 		open(my $fh, '<:raw', $file) || die "Rand::Urandom: Can't open $file: $!";  | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
85
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16952
 | 
 		my $got = read($fh, $buf, $num);  | 
| 
86
 | 
15
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
103
 | 
 		if ($got == 0 || $got != $num) {  | 
| 
87
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			die "Rand::Urandom: failed to read from $file: $!";  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
89
 | 
15
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
183
 | 
 		close($fh) || die "Rand::Urandom: close failed: $!";  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
91
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
91
 | 
 	return $buf;  | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $orig_rand;  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub perl_rand {  | 
| 
96
 | 
4
 | 
  
 50
  
 | 
 
 | 
  
4
  
 | 
  
1
  
 | 
262
 | 
 	if ($^V lt 'v5.16') {  | 
| 
97
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		die 'Rand::Urandom: sorry, you cant access the original rand function on perls older than 5.16';  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
100
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
338
 | 
 	goto &$orig_rand;  | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub BEGIN {  | 
| 
104
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
15
 | 
 	no warnings 'redefine';  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
    | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
126
 | 
    | 
| 
105
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
12
 | 
 	no warnings 'prototype';  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
    | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
213
 | 
    | 
| 
106
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
6
 | 
 	$orig_rand           = \&CORE::rand;  | 
| 
107
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
75
 | 
 	*CORE::GLOBAL::rand = \&use_urandom;  | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |