8 #include <mLib/alloc.h>
9 #include <mLib/base64.h>
10 #include <mLib/base32.h>
11 #include <mLib/dstr.h>
13 #include <mLib/mdwopt.h>
14 #include <mLib/quis.h>
15 #include <mLib/report.h>
17 #include <catacomb/rand.h>
18 #include <catacomb/noise.h>
22 void (*out
)(size_t, unsigned);
27 static void do_format(size_t n
, unsigned line
, void *ctx
,
28 void (*encode
)(void *, char *, size_t, dstr
*),
29 void (*fix
)(char *, size_t))
37 rand_get(RAND_GLOBAL
, buf
, nn
);
38 encode(ctx
, buf
, nn
, &d
);
39 if (fix
) fix(d
.buf
, d
.len
);
44 encode(ctx
, 0, 0, &d
);
46 while (d
.len
&& d
.buf
[d
.len
- 1] == '=')
49 if (fix
) fix(d
.buf
, d
.len
);
54 static void do_base64(void *ctx
, char *p
, size_t sz
, dstr
*d
)
55 { base64_encode(ctx
, p
, sz
, d
); }
56 static void do_format_base64(size_t n
, unsigned line
,
57 void (*fix
)(char *, size_t))
62 if (line
) { b
.indent
= "\n"; b
.maxline
= line
; }
63 else { b
.indent
= ""; b
.maxline
= 0; }
64 do_format(n
, line
, &b
, do_base64
, fix
);
66 static void format_base64(size_t n
, unsigned line
)
67 { do_format_base64(n
, line
, 0); }
69 static void do_base32(void *ctx
, char *p
, size_t sz
, dstr
*d
)
70 { base32_encode(ctx
, p
, sz
, d
); }
71 static void format_base32(size_t n
, unsigned line
)
76 if (line
) { b
.indent
= "\n"; b
.maxline
= line
; }
77 else { b
.indent
= ""; b
.maxline
= 0; }
78 do_format(n
, line
, &b
, do_base32
, 0);
81 static void fix_file64(char *p
, size_t n
)
84 if (*p
== '/') *p
= '%';
88 static void format_file64(size_t n
, unsigned line
)
89 { do_format_base64(n
, line
, fix_file64
); }
91 static void fix_safe64(char *p
, size_t n
)
94 if (*p
== '+') *p
= '-';
95 else if (*p
== '/') *p
= '_';
99 static void format_safe64(size_t n
, unsigned line
)
100 { do_format_base64(n
, line
, fix_safe64
); }
102 static void do_hex(void *ctx
, char *p
, size_t sz
, dstr
*d
)
103 { hex_encode(ctx
, p
, sz
, d
); }
104 static void format_hex(size_t n
, unsigned line
)
109 if (line
) { b
.indent
= "\n"; b
.maxline
= line
; }
110 else { b
.indent
= ""; b
.maxline
= 0; }
111 do_format(n
, line
, &b
, do_hex
, 0);
114 static void format_raw(size_t n
, unsigned line
)
116 unsigned char buf
[CHUNK
];
121 rand_get(RAND_GLOBAL
, buf
, nn
);
122 fwrite(buf
, 1, nn
, stdout
);
127 static const struct format fmt
[] = {
128 { "base64", format_base64
},
129 { "file64", format_file64
},
130 { "safe64", format_safe64
},
131 { "base32", format_base32
},
132 { "hex", format_hex
},
133 { "raw", format_raw
},
137 static int uarg(const char *p
, const char *what
)
142 x
= strtoul(p
, &q
, 0);
143 if (*q
|| errno
|| x
> INT_MAX
) die(EXIT_FAILURE
, "bad %s", what
);
147 static void version(FILE *fp
)
149 pquis(stderr
, "$, version " VERSION
"\n");
152 static void usage(FILE *fp
)
154 pquis(stderr
, "Usage: $ [-y] [-l LEN] [-f FORMAT] [BITS]\n");
157 static void help(FILE *fp
)
163 Generates a random string, and prints it to standard output.\n\
167 -h, --help Print this help message.\n\
168 -v, --version Print program version number.\n\
169 -u, --usage Print short usage summary.\n\
171 -y, --bytes Output length is bytes, not bits.\n\
172 -l, --line=LENGTH For textual output, limit line length to LENGTH.\n\
173 -f, --format=FORMAT Select output format:\n\
174 base64, file64, safe64, base32, hex, raw.\n\
178 int main(int argc
, char *argv
[])
184 const struct format
*ff
= &fmt
[0];
190 static const struct option opt
[] = {
191 { "help", 0, 0, 'h' },
192 { "version", 0, 0, 'v' },
193 { "usage", 0, 0, 'u' },
195 { "format", OPTF_ARGREQ
, 0, 'f' },
196 { "line", OPTF_ARGREQ
, 0, 'l' },
197 { "bytes", 0, 0, 'y' },
202 i
= mdwopt(argc
, argv
, "hvuf:l:y", opt
, 0, 0, 0);
219 len
= uarg(optarg
, "line length");
224 for (i
= 0; fmt
[i
].name
; i
++) {
225 if (strncmp(fmt
[i
].name
, optarg
, n
) != 0)
227 if (!fmt
[i
].name
[n
]) {
232 die(EXIT_FAILURE
, "ambiguous format name `%s'", optarg
);
236 die(EXIT_FAILURE
, "unknown format name `%s'", optarg
);
246 if (f
& f_bogus
&& argc
> 1) {
250 n
= argc
== 1 ?
uarg(argv
[0], "bit count") : 128;
251 if (!n
|| n
% mul
) die(EXIT_FAILURE
, "bad bit count");
253 rand_noisesrc(RAND_GLOBAL
, &noise_source
);
254 rand_seed(RAND_GLOBAL
, 160);
257 die(EXIT_FAILURE
, "output error: %s", strerror(errno
));