commit: 5ee035a364bea8d12bc8abfe769014e230a212a6
Author: Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Sun Jun 2 17:46:43 2024 +0000
Commit: Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Wed Jun 12 07:06:41 2024 +0000
URL:
https://gitweb.gentoo.org/proj/gentoo-functions.git/commit/?id=5ee035a3
Add the srandom() function
This is based on the behaviour of the special SRANDOM variable in bash.
It should be noted that sh is capable of bitwise arithmetic. For
instance, it is possible to clamp the number in such a way that it does
not exceed the minimum possible value of RAND_MAX (32767).
n=$(srandom) && : $(( n >>= 17 ))
Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>
functions.sh | 27 +++++++++++++++++++++++++++
test-functions | 22 ++++++++++++++++++++++
2 files changed, 49 insertions(+)
diff --git a/functions.sh b/functions.sh
index a97dde7..0c35b2d 100644
--- a/functions.sh
+++ b/functions.sh
@@ -12,6 +12,7 @@
# The following variables affect initialisation and/or function behaviour.
# BASH : whether bash-specific features may be employed
+# BASH_VERSINFO : whether bash-specific features may be employed
# BASHPID : potentially used by _update_columns() to detect subshells
# COLUMNS : potentially used by _update_columns() to get the column count
# EERROR_QUIET : whether error printing functions should be silenced
@@ -473,6 +474,32 @@ vewend()
fi
}
+#
+# Generates a random uint32 with the assistance of the kernel CSPRNG.
+#
+srandom()
+{
+ # shellcheck disable=3028
+ if [ "${BASH_VERSINFO:-0}" -ge 5 ]; then
+ srandom()
+ {
+ printf '%d\n' "${SRANDOM}"
+ }
+ elif [ -c /dev/urandom ]; then
+ srandom()
+ {
+ printf '%d\n' "0x$(
+ LC_ALL=C od -vAn -N4 -tx1 /dev/urandom | tr -d
'[:space:]'
+ )"
+ }
+ else
+ warn "srandom: /dev/urandom doesn't exist as a character device"
+ return 1
+ fi
+
+ srandom
+}
+
#
# Prints a diagnostic message prefixed with the basename of the running script.
#
diff --git a/test-functions b/test-functions
index 8ff6380..0c4a222 100755
--- a/test-functions
+++ b/test-functions
@@ -397,6 +397,27 @@ test_yesno() {
iterate_tests 3 "$@"
}
+test_srandom() {
+ set -- \
+ eq 0 \
+ eq 0 \
+ eq 0 \
+ eq 0 \
+ eq 0
+
+ row=0
+
+ callback() {
+ number=$(srandom)
+ test_description="srandom ($(( row += 1 ))/5: ${number:-blank})"
+ is_int "${number}" \
+ && test "${number}" -ge 0 \
+ && test "${number}" -le 4294967295
+ }
+
+ iterate_tests 2 "$@"
+}
+
iterate_tests() {
slice_width=$1
shift
@@ -457,6 +478,7 @@ test_is_visible || rc=1
test_yesno || rc=1
test_die || rc=1
test_edo || rc=1
+test_srandom || rc=1
cleanup_tmpdir