/* * rasgen - random ASCII string generator */ /*- * Copyright (c) 2009-2018 * Jeffrey Allen Neitzel . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JEFFREY ALLEN NEITZEL ``AS IS'', AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL JEFFREY ALLEN NEITZEL BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @(#)$Id: rasgen.c,v 1.2 2018/09/27 07:53:18 jneitzel Exp $ */ /* * **** Required Header Files **** */ #include "config.h" #ifndef S_SPLINT_S #include #include #include #include #include #include #include #include #endif /* * #undef DEBUG for production build */ #undef DEBUG extern char *__progname; #define STRANDMAX 95 /* assumes 94 usable characters */ static int strand[STRANDMAX]; static bool isunique(int, int); /* * NAME * rasgen - random ASCII string generator * * SYNOPSIS * rasgen length * * DESCRIPTION * See the rasgen(1) manual page for full details. */ int main(int argc, char **argv) { char *blen; long llen; int i, ilen, n, t; /* Check for incorrect usage. */ if (argc != 2) { (void)fprintf(stderr, "usage: %s length\n", __progname); return 1; } /* Get length, and check if it is invalid. */ errno = 0; llen = strtol(argv[1], &blen, 10); if (errno != 0 || *argv[1] == '\0' || (*argv[1] == '0' && *(argv[1] + 1) >= '0' && *(argv[1] + 1) <= '9') || *blen != '\0' || llen <= 0 || llen > (int)(sizeof(strand) / sizeof(int) - 1)) { (void)fprintf(stderr, "%s: %s: Invalid length\n", __progname, argv[1]); return 1; } #if HAVE_ARC4RANDOM_UNIFORM == 0 /* * Delay srandom(3) seeding w/ time(2) by 1 second. This is so that * doing `rasgen length ; rasgen length ; rasgen length' or similar * doesn't generate 3 identical strings for the specified lengths. */ (void)sleep(1); /* Seed random number generator. */ srandom((unsigned int)time(NULL)); #endif /* Generate string. */ for (ilen = (int)llen, i = t = 0; i < ilen; t++) { #if HAVE_ARC4RANDOM_UNIFORM == 0 n = (int)(random() & 0177); #else n = (int)arc4random_uniform(0200); #endif if (isprint(n) && n != 040 && isunique(n, i)) { strand[i] = n; i++; } } /* Print string to standard output. */ for (i = 0; i < ilen; i++) (void)printf("%c", strand[i]); (void)printf("\n"); #ifdef DEBUG (void)fprintf(stderr, "total iterations == %d\n", t); #endif return 0; } /* * Return true if specified num is unique from 0 to specified idx * of global strand. Otherwise, return false if it is not unique. */ static bool isunique(int num, int idx) { int i; for (i = 0; i < idx; i++) if (strand[i] == num) return false; #ifdef DEBUG (void)fprintf(stderr, "isunique: %c @ %d\n", num, idx); #endif return true; }