/*============================================================================= testrandom =============================================================================== Test for the random number generator type by generating 5 values with rand() and comparing them against values in a table. Currently only recognizes ISO glibc rand(). Options: -q : quiet mode -x : print exit code to stdout, otherwise equivalent to quite mode -v : verbose mode : Use to generate values for new table This is a self-contained program which does not require any libnetpbm functions. =============================================================================*/ #include #include #define bool int #define TRUE 1 #define FALSE 0 /* Exit values */ #define EXIT_ERROR 1 #define EXIT_UNKNOWN 80 #define ISO_GLIBC 81 #define MAC_OS 82 /* 83-90: reserved */ typedef enum {QUIET=0, NORMAL=1, VERBOSE=2} VerbosityLevel; /* On some Sun systems RAND_MAX is not defined */ #ifndef RAND_MAX #define RAND_MAX 0 #endif #define SEED 3791 static struct { int const type; /* Exit value for this rand() function */ int const randMax; /* Usually 0x7fffffff, sometimes 0x7fff */ /* Other values are possible; 0 means undefined */ unsigned int const res[5]; /* Sample values returned from our tests */ const char * const name; /* Name for this rand() function */ } rTable[3] = { { ISO_GLIBC, /* glibc rand() */ 0x7fffffff, /* 31 bits */ { 217313873, 969144303, 1757357552, 1096307597, 818311031 }, "ISO C glibc rand() or equivalent" }, { MAC_OS, 0x7fffffff, /* 31 bits */ { 63715337, 1416812753, 1073261735, 1594828992, 1547470337 }, "MAC OS c library rand() or equivalent" }, /* Insert additional entries here */ { 0, /* terminating code */ 0, {0, 0, 0, 0, 0}, NULL /* unknown type */} }; static void parseCommandLine(int const argc, const char * const argv[], VerbosityLevel * const verbosityP, bool * const printExitCodeP) { *verbosityP = NORMAL; /* Initial value */ *printExitCodeP = FALSE; /* Initial value */ if (argc == 2) { if (argv[1][0] == '-' && argv[1][2] == '\0') { switch ( argv[1][1] ) { case 'v' : *verbosityP = VERBOSE; break; case 'q' : *verbosityP = QUIET ; break; case 'x' : *verbosityP = QUIET ; *printExitCodeP = TRUE ; break; default : fprintf (stderr, "Error: Unrecognized argument: %s\n", argv[1]); exit (EXIT_ERROR); } } } if (argc > 2 ) { fprintf (stderr, "Error: Too many arguments.\n"); exit (EXIT_ERROR); } } int main(int const argc, const char * const argv[]) { unsigned int i; unsigned int res[5]; VerbosityLevel verbosity; bool printExitCode; parseCommandLine(argc, argv, &verbosity, &printExitCode); if (verbosity == VERBOSE) { if (RAND_MAX > 0) fprintf(stderr, "RAND_MAX = 0x%x (%d)\n", RAND_MAX, RAND_MAX); else fprintf(stderr, "RAND_MAX is undefined\n"); } /* Set seed for pseudo-random number generator */ if (verbosity == VERBOSE) fprintf(stderr, "Generating samples. Seed=%u\n", SEED); srand(SEED); /* Generate five samples and store in array res[] */ for (i = 0; i < 5; ++i) { res[i] = rand(); if (verbosity == VERBOSE) fprintf (stderr, "%d\n",res[i]); } /* Look for a match in table */ for (i = 0; rTable[i].type != 0; ++i) { if (rTable[i].randMax == RAND_MAX && rTable[i].res[0] == res[0] && rTable[i].res[1] == res[1] && rTable[i].res[2] == res[2] && rTable[i].res[3] == res[3] && rTable[i].res[4] == res[4]) { if (verbosity != QUIET) fprintf(stderr, "Random number generator is %s.\n", rTable[i].name); if (printExitCode == TRUE) printf("%03u", rTable[i].type); exit(rTable[i].type); } } /* No matches */ if (verbosity != QUIET) fprintf(stderr, "Random number generator is of unknown type.\n"); if (printExitCode == TRUE) printf("%03u",EXIT_UNKNOWN); exit(EXIT_UNKNOWN); }