chiark / gitweb /
@@ -1,3 +1,10 @@
[chiark-utils.git] / scripts / random-word
diff --git a/scripts/random-word b/scripts/random-word
new file mode 100755 (executable)
index 0000000..a7a2799
--- /dev/null
@@ -0,0 +1,69 @@
+#!/usr/bin/perl
+
+use IO::Handle;
+use IO::File;
+use POSIX;
+
+$want= 1;
+$filename= "/usr/share/dict/words";
+@randfile= ("/dev/urandom", "/dev/random");
+
+sub fail ($) { die "random-word: $_[0]\n"; }
+open D, ">/dev/null" or fail("open /dev/null: $!");
+
+while ($ARGV[0] =~ m/^\-/) {
+    $_= shift @ARGV;
+    if (m/^\-\-?$/) {
+       last;
+    } elsif (m/^\-n(\d+)$/) {
+       $want= $1;
+    } elsif (m/^\-f/ && length > 2) {
+       $filename= $';
+    } elsif (m/^\-r/ && length > 2) {
+       @randfile= ($');
+    } elsif (m/^\-D$/) {
+       open D, ">&STDERR" or fail("dup stderr for debug: $!");
+    } else {
+       fail("unknown option \`$_'");
+    }
+}
+
+sub debug ($) {
+    print D "random-word: debug: $_[0]\n"
+       or fail("write debug: $!");
+}
+
+for $randfile (@randfile) {
+    $r= new IO::File "$randfile", 'r';
+    debug("open $randfile ".($r ? "ok" : "failed $!"));
+    last if $r;
+    $!==&ENOENT or fail("cannot open $randfile: $!");
+}
+$r or fail("could not open any random device: $!\n (tried @randfile)");
+$r->autoflush(0);
+
+$w= new IO::File $filename, 'r';
+$w or fail("cannot open $filename: $!");
+debug("open $filename ok");
+@words= <$w>;
+$w->error and fail("cannot read $filename: $!");
+debug("read $filename ok");
+
+while (@out < $want) {
+    $!=0; read $r,$rbytes,4;
+    length $rbytes==4 or fail("cannot read $randfile: $!");
+    $wordno= unpack 'L',$rbytes;
+    $wordno &= ~0x80000000;
+    $wordno %= @words;
+    $_= $words[$wordno];
+    chomp;
+    debug("picked $wordno \`$_'");
+    next unless m/^([a-z][-a-z]+)$/;
+    push @out, $1;
+    debug("good, now ".scalar @out);
+}
+
+debug("enough");
+
+print join(' ',@out), "\n"
+    or fail("cannot write output: $!");