util  rndcbytes.lua at [6bda93a905]

File rndcbytes.lua artifact b0df5b89e1 part of check-in 6bda93a905


-- [ʞ] rndcbytes.lua
--  ~ lexi hale <lexi@hale.su>
--  © CC0/public domain
--  # requires lua 5.4
--  ? generates random bytes in the form of a maximally
--    compact C string. note that this only works for
--    values small enough to fit into a string literal.
--  > lua rndcbytes.lua <n> <max>
--    <n> is the number of bytes to generate 
--    <max> is the number of characters (NOT bytes) to
--          wrap after.

local rnd_srcs = {
	'/dev/urandom';
	'/dev/random';
}

local rng
for _, r in ipairs(rnd_srcs) do
	local ur = io.open(r, 'rb')
	if ur then
		rng = function(n)
			return ur:read(n)
		end
		break
	end
end
if rng == nil then
	math.randomseed()
	io.stderr:write("WARNING: relying on internal lua RNG. bytes generated are NOT cryptographically reliable!\n")
	rng = function(n)
		local str = {}
		for i = 1,n do
			str[i] = string.pack('B', math.random(0,0xff))
		end
		return table.concat(str)
	end
end

local n = 48
local max = 48
if arg[1] then n = tonumber(arg[1]) end
if arg[2] then max = tonumber(arg[2]) end

local bytes = rng(n)

local lns = {}
local cur, chc = {}, 0
local function flush()
	if next(cur) then
		table.insert(lns, cur)
		cur = {}
		chc = 0
	end
end

local escapes <const> = {
	[0x09] = "t";
	[0x0a] = "n";
	[0x22] = '"';
}
for i=1, #bytes do
	local val = bytes:byte(i)
	local r
	if escapes[val] then
		r = '\\' .. escapes[val]
	elseif val >= 0x20 and val < 0x7f then
		r = string.char(val)
	else
		r = string.format("\\x%02X", val)
	end
	if chc + #r > max then flush() end
	chc = chc + #r
	table.insert(cur, r)
end
flush()

for _, chars in ipairs(lns) do
	print(string.format('"%s"', table.concat(chars)))
end