#!/usr/bin/env mksh
# From MirOS: contrib/code/Snippets/shuffle,v 1.8 2014/02/10 00:36:12 tg Exp $
#-
# Copyright © 2006, 2010, 2011, 2012, 2015, 2017, 2018
# mirabilos
#
# Provided that these terms and disclaimer and all copyright notices
# are retained or reproduced in an accompanying document, permission
# is granted to deal in this work without restriction, including un‐
# limited rights to use, publicly perform, distribute, sell, modify,
# merge, give away, or sublicence.
#
# This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
# the utmost extent permitted by applicable law, neither express nor
# implied; without malicious intent or gross negligence. In no event
# may a licensor, author or contributor be held liable for indirect,
# direct, other damage, loss, or other issues arising in any way out
# of dealing in the work, even if advised of the possibility of such
# damage or existence of a defect, except proven that it results out
# of said person’s immediate fault when using the work as intended.
#-
# Hack for _remfor shuffling the input
ulimit -c 0
local _i _fm=$2 _h=$1
shift; shift
[[ $_fm = *'*' ]] || _fm=${_fm@Q}
set -A files
integer nfiles=0
trap "" INT
ssh -n "$_h" find "$_fm" -follow -type f -print0 |&
while IFS= read -p -r -d "" _i; do
files[nfiles++]=$_i
done
# arc4random(3) in Pure mksh™
set -A seedbuf -- $(dd if=/dev/arandom bs=257 count=1 2>/dev/null | \
hexdump -ve '1/1 "0x%02X "')
set -A rs_S
typeset -i rs_S rs_i=-1 rs_j=0 n
while (( ++rs_i < 256 )); do
(( rs_S[rs_i] = rs_i ))
done
rs_i=-1
while (( ++rs_i < 256 )); do
(( n = rs_S[rs_i] ))
(( rs_j = (rs_j + n + seedbuf[rs_i]) & 0xFF ))
(( rs_S[rs_i] = rs_S[rs_j] ))
(( rs_S[rs_j] = n ))
done
rs_i=0
rs_j=0
typeset -i rs_out
function arcfour_byte {
typeset -i si sj
(( rs_i = (rs_i + 1) & 0xFF ))
(( si = rs_S[rs_i] ))
(( rs_j = (rs_j + si) & 0xFF ))
(( sj = rs_S[rs_j] ))
(( rs_S[rs_i] = sj ))
(( rs_S[rs_j] = si ))
(( rs_out = rs_S[(si + sj) & 0xFF] ))
}
(( n = 256 * 12 + seedbuf[256] + (RANDOM & 0xFF) ))
while (( n-- )); do
arcfour_byte
done
(( n = rs_out ))
while (( n-- )); do
arcfour_byte
done
typeset -Uui16 -Z11 arc4random_rv
function arc4random {
# apply uncertainty
arcfour_byte
(( rs_out & 1 )) && arcfour_byte
# read four octets into result dword
arcfour_byte
(( arc4random_rv = rs_out ))
arcfour_byte
(( arc4random_rv |= rs_out << 8 ))
arcfour_byte
(( arc4random_rv |= rs_out << 16 ))
arcfour_byte
(( arc4random_rv |= rs_out << 24 ))
}
# arc4random_uniform(3) in Pure mksh™
function arc4random_uniform {
# Derived from code written by Damien Miller
# published under the ISC licence, with simplifications by
# Jinmei Tatuya. Written in mksh by Thorsten Glaser.
#-
# Calculate a uniformly distributed random number less than
# upper_bound avoiding “modulo bias”.
# Uniformity is achieved by generating new random numbers
# until the one returned is outside the range
# [0, 2^32 % upper_bound[. This guarantees the selected
# random number will be inside the range
# [2^32 % upper_bound, 2^32[ which maps back to
# [0, upper_bound[ after reduction modulo upper_bound.
#-
typeset -Ui upper_bound=$1 min
if (( upper_bound < 2 )); then
arc4random_rv=0
return
fi
# calculate (2^32 % upper_bound) avoiding 64-bit math
# if upper_bound > 2^31: 2^32 - upper_bound (only one
# “value area”); otherwise (x <= 2^31) use the fact
# that ((2^32 - x) % x) == (2^32 % x)
((# min = upper_bound > 0x80000000 ? 1 + ~upper_bound :
(0xFFFFFFFF - upper_bound + 1) % upper_bound ))
# This could theoretically loop forever but each retry has
# p > 0.5 (worst case, usually far better) of selecting a
# number inside the range we need, so it should rarely need
# to re-roll (at all).
while :; do
arc4random
((# arc4random_rv >= min )) && break
done
((# arc4random_rv %= upper_bound ))
}
(( ++nfiles ))
while (( --nfiles )); do
arc4random_uniform $nfiles
_i=${files[arc4random_rv]}
print -r "◖${_i}◗"
ssh -n "$_h" cat "${_i@Q}" | "$@"
unset files[arc4random_rv]
set -A files -- "${files[@]}"
done