Yes thanks for pointing that out, I wrote a slightly faster version below. I took your advice and wanted just a single invoke on the C program, so I modified it to take an argument. I'm satisfied!
> cat arc4random-v2.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
if ( ! (argc == 1 || argc == 2) ) {
printf("usage: %s [n_output]\n", argv[0]);
} else {
int n_iter = (argc == 2) ? atoi(argv[1]) : 1;
for (int i = 0; i < n_iter; i++) {
printf("%u\n", arc4random());
}
}
return 0;
}
> ./arc4random 3
4282823399
333796506
762478899
> cat pwgen-v2.sh
#!/usr/bin/env bash
dict=/usr/share/dict/words
n=4 # of words to include in passphrase
nl=$(wc -l $dict | sed 's_[ \t]*\([0-9]*\).*_\1_')
fmt_flag() { echo $[$1 % $nl] | sed -n -e 's_^_-e _' -e 's_$_p_p' ; }
flags=$(./arc4random $n | while read -r i; do fmt_flag "$i"; done)
words=$(sed -n $flags < $dict)
echo $words
> time ./pwgen.sh
liparite evade retiringly spacious
real 0m0.268s
user 0m0.251s
sys 0m0.015s
> time ./pwgen-v2.sh
latherin prideling thumbscrew unraveled
real 0m0.082s
user 0m0.072s
sys 0m0.013s
EDIT: note that the single call to sed results in alphabetical/dictionary-dependent results... (!) oops