+ if (flags & f_progress)
+ fputc('\n', stderr);
+ return (0);
+}
+
+/*----- Main code ---------------------------------------------------------*/
+
+int main(int ac, char *av[])
+{
+ gen *g = &optsg;
+ grand *r;
+
+ /* --- Initialize mLib --- */
+
+ ego(av[0]);
+ sub_init();
+
+ /* --- Set up the main Catacomb generator --- */
+
+ rand_noisesrc(RAND_GLOBAL, &noise_source);
+ rand_seed(RAND_GLOBAL, 160);
+
+ /* --- Initialize the options table --- */
+
+ addopts(sopts, opts);
+ argc = ac;
+ argv = av;
+ outfp = stdout;
+
+ /* --- Read the generator out of the first argument --- */
+
+ if (argc > 1 && *argv[1] != '-') {
+ const char *arg = av[1];
+ size_t sz = strlen(arg);
+ gen *gg;
+
+ g = 0;
+ for (gg = generators; gg->name; gg++) {
+ if (strncmp(arg, gg->name, sz) == 0) {
+ if (gg->name[sz] == 0) {
+ g = gg;
+ break;
+ } else if (g)
+ die(EXIT_FAILURE, "ambiguous generator name `%s'", arg);
+ else
+ g = gg;
+ }
+ }
+ if (!g)
+ die(EXIT_FAILURE, "unknown generator name `%s'", arg);
+ argc--;
+ argv++;
+ }
+
+ /* --- Get a generic random number generator --- */
+
+ r = g->seed(g->i);
+ if (!r || optind != ac - 1) {
+ usage(stderr);
+ exit(EXIT_FAILURE);
+ }
+
+ /* --- Do the FIPS test --- */
+
+ if (flags & f_fips) {
+ octet buf[FIPSTEST_BUFSZ];
+ unsigned rc;
+ octet *p = buf;
+
+ generate(r, sizeof(buf), genbuf, &p);
+ rc = fipstest(buf);
+ if (rc & FIPSTEST_MONOBIT)
+ moan("failed monobit test");
+ if (rc & FIPSTEST_POKER)
+ moan("failed poker test");
+ if (rc & FIPSTEST_RUNS)
+ moan("failed runs test");
+ if (rc & FIPSTEST_LONGRUNS)
+ moan("failed long runs test");
+ if (!rc && (flags & f_progress))
+ puts("test passed");
+ return (rc ? EXIT_FAILURE : 0);
+ }
+
+ /* --- Do Maurer's test --- */
+
+ if (flags & f_maurer) {
+ octet *buf;
+ size_t bufsz;
+ unsigned i;
+ unsigned rc = 0;
+ unsigned f = 0, jj = 0;
+ double maxz = 0;
+ octet *p;
+
+ static struct { double x; const char *sig; } sigtab[] = {
+ { 3.2905, "1e-3" },
+ { 3.0902, "2e-3" },
+ { 2.8070, "5e-3" },
+ { 2.5758, "1e-2" },
+ { 0 , 0 }
+ };
+
+ bufsz = (100 * maurer_hi) << maurer_hi;
+ if ((buf = a_alloc(arena_global, bufsz)) == 0)
+ die(EXIT_FAILURE, "not enough memory for data buffer");
+ p = buf;
+ generate(r, bufsz, genbuf, &p);
+
+ for (i = maurer_lo; i <= maurer_hi; i++) {
+ double z = maurer(buf, bufsz, i);
+ double zz = fabs(z);
+ unsigned j;
+
+ for (j = 0; sigtab[j].sig; j++) {
+ if (zz > sigtab[j].x) {
+ if (zz > fabs(maxz)) {
+ maxz = z;
+ f = i;
+ jj = j;
+ }
+ rc = EXIT_FAILURE;
+ moan("failed, bits = %u, sig = %s, Z_u = %g",
+ i, sigtab[j].sig, z);
+ break;
+ }
+ }
+ if (flags & f_progress)
+ printf("bits = %u, Z_u = %g\n", i, z);
+ }
+
+ return (rc);
+ }
+
+ /* --- Write to a file --- */
+
+#ifndef PORTABLE
+ if (!(flags & f_file) && isatty(STDOUT_FILENO))
+ die(EXIT_FAILURE, "writing output to a terminal is a bad idea");
+#endif
+
+ generate(r, outsz, genfile, outfp);
+