chiark / gitweb /
changelog: finalise 5.0.0
[chiark-utils.git] / scripts / random-word
1 #!/usr/bin/perl -w
2
3 # Copyright 2004 Ian Jackson <ian@chiark.greenend.org.uk>
4 #
5 # This script and its documentation (if any) are free software; you
6 # can redistribute it and/or modify them under the terms of the GNU
7 # General Public License as published by the Free Software Foundation;
8 # either version 3, or (at your option) any later version.
9
10 # chiark-named-conf and its manpage are distributed in the hope that
11 # it will be useful, but WITHOUT ANY WARRANTY; without even the
12 # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 # PURPOSE.  See the GNU General Public License for more details.
14
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, consult the Free Software Foundation's
17 # website at www.fsf.org, or the GNU Project website at www.gnu.org.
18
19 use strict;
20
21 use IO::Handle;
22 use IO::File;
23 use POSIX;
24
25 our $want= 1;
26 our $filename= "/usr/share/dict/words";
27 our @randfile= ("/dev/urandom", "/dev/random");
28 our $filemaxlen;
29
30 sub fail ($) { die "random-word: $_[0]\n"; }
31 open D, ">/dev/null" or fail("open /dev/null: $!");
32
33 while (@ARGV && $ARGV[0] =~ m/^\-/) {
34     $_= shift @ARGV;
35     if (m/^\-\-?$/) {
36         last;
37     } elsif (m/^\-n(\d+)$/) {
38         $want= $1;
39     } elsif (m/^\-f/ && length > 2) {
40         $filename= $'; #';
41     } elsif (m/^\-F(\d+)$/) {
42         $filemaxlen= $1;
43     } elsif (m/^\-r/ && length > 2) {
44         @randfile= ($'); #');
45     } elsif (m/^\-D$/) {
46         open D, ">&STDERR" or fail("dup stderr for debug: $!");
47     } else {
48         fail("unknown option \`$_'");
49     }
50 }
51
52 sub debug ($) {
53     print D "random-word: debug: $_[0]\n"
54         or fail("write debug: $!");
55 }
56
57 our $randfile;
58 our $r;
59
60 for $randfile (@randfile) {
61     $r= new IO::File "$randfile", 'r';
62     debug("open $randfile ".($r ? "ok" : "failed $!"));
63     last if $r;
64     $!==&ENOENT or fail("cannot open $randfile: $!");
65 }
66 $r or fail("could not open any random device: $!\n (tried @randfile)");
67 $r->autoflush(0);
68
69 our $w= new IO::File $filename, 'r';
70 $w or fail("cannot open $filename: $!");
71 debug("open $filename ok");
72 our @words;
73 if (defined $filemaxlen) {
74     while (@words < $filemaxlen) {
75         my $l = <$w>;
76         last unless defined $l;
77         push @words, $l;
78     }
79 } else {
80     @words= <$w>;
81 }
82 $w->error and fail("cannot read $filename: $!");
83 debug("read $filename ok");
84
85 our @out;
86 while (@out < $want) {
87     my $rbytes;
88     $!=0; read $r,$rbytes,4;
89     length $rbytes==4 or fail("cannot read $randfile: $!");
90     my $wordno= unpack 'L',$rbytes;
91     $wordno &= ~0x80000000;
92     $wordno %= @words;
93     $_= $words[$wordno];
94     chomp;
95     debug("picked $wordno \`$_'");
96     next unless m/^([a-z][-a-z]+)$/;
97     push @out, $1;
98     debug("good, now ".scalar @out);
99 }
100
101 debug("enough");
102
103 print join(' ',@out), "\n"
104     or fail("cannot write output: $!");