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));