16ae1554aSColin Percival /* 26ae1554aSColin Percival * Copyright (c) 1994 36ae1554aSColin Percival * The Regents of the University of California. All rights reserved. 46ae1554aSColin Percival * 56ae1554aSColin Percival * This code is derived from software contributed to Berkeley by 66ae1554aSColin Percival * Guy Harris at Network Appliance Corp. 76ae1554aSColin Percival * 86ae1554aSColin Percival * Redistribution and use in source and binary forms, with or without 96ae1554aSColin Percival * modification, are permitted provided that the following conditions 106ae1554aSColin Percival * are met: 116ae1554aSColin Percival * 1. Redistributions of source code must retain the above copyright 126ae1554aSColin Percival * notice, this list of conditions and the following disclaimer. 136ae1554aSColin Percival * 2. Redistributions in binary form must reproduce the above copyright 146ae1554aSColin Percival * notice, this list of conditions and the following disclaimer in the 156ae1554aSColin Percival * documentation and/or other materials provided with the distribution. 166ae1554aSColin Percival * 3. Neither the name of the University nor the names of its contributors 176ae1554aSColin Percival * may be used to endorse or promote products derived from this software 186ae1554aSColin Percival * without specific prior written permission. 196ae1554aSColin Percival * 206ae1554aSColin Percival * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 216ae1554aSColin Percival * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 226ae1554aSColin Percival * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 236ae1554aSColin Percival * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 246ae1554aSColin Percival * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 256ae1554aSColin Percival * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 266ae1554aSColin Percival * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 276ae1554aSColin Percival * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 286ae1554aSColin Percival * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 296ae1554aSColin Percival * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 306ae1554aSColin Percival * SUCH DAMAGE. 316ae1554aSColin Percival */ 326ae1554aSColin Percival 336ae1554aSColin Percival #if 0 346ae1554aSColin Percival #ifndef lint 356ae1554aSColin Percival static const char copyright[] = 366ae1554aSColin Percival "@(#) Copyright (c) 1994\n\ 376ae1554aSColin Percival The Regents of the University of California. All rights reserved.\n"; 386ae1554aSColin Percival #endif /* not lint */ 396ae1554aSColin Percival 406ae1554aSColin Percival #ifndef lint 416ae1554aSColin Percival static const char sccsid[] = "@(#)random.c 8.5 (Berkeley) 4/5/94"; 426ae1554aSColin Percival #endif /* not lint */ 436ae1554aSColin Percival #endif 446ae1554aSColin Percival #include <sys/cdefs.h> 456ae1554aSColin Percival __FBSDID("$FreeBSD$"); 466ae1554aSColin Percival 476ae1554aSColin Percival #include <sys/types.h> 486ae1554aSColin Percival 496ae1554aSColin Percival #include <err.h> 506ae1554aSColin Percival #include <errno.h> 516ae1554aSColin Percival #include <fcntl.h> 526ae1554aSColin Percival #include <limits.h> 536ae1554aSColin Percival #include <locale.h> 54*06257a71SConrad Meyer #include <stdbool.h> 55c7b8411cSConrad Meyer #include <stdint.h> 566ae1554aSColin Percival #include <stdio.h> 576ae1554aSColin Percival #include <stdlib.h> 586ae1554aSColin Percival #include <string.h> 596ae1554aSColin Percival #include <time.h> 606ae1554aSColin Percival #include <unistd.h> 616ae1554aSColin Percival 626ae1554aSColin Percival #include "randomize_fd.h" 636ae1554aSColin Percival 646ae1554aSColin Percival static void usage(void); 656ae1554aSColin Percival 666ae1554aSColin Percival int 676ae1554aSColin Percival main(int argc, char *argv[]) 686ae1554aSColin Percival { 696ae1554aSColin Percival double denom; 706ae1554aSColin Percival int ch, fd, random_exit, randomize_lines, random_type, ret, 71*06257a71SConrad Meyer unique_output, unbuffer_output; 72*06257a71SConrad Meyer bool selected; 736ae1554aSColin Percival char *ep; 746ae1554aSColin Percival const char *filename; 756ae1554aSColin Percival 76*06257a71SConrad Meyer denom = 0.; 776ae1554aSColin Percival filename = "/dev/fd/0"; 786ae1554aSColin Percival random_type = RANDOM_TYPE_UNSET; 796ae1554aSColin Percival random_exit = randomize_lines = unbuffer_output = 0; 806ae1554aSColin Percival unique_output = 1; 816ae1554aSColin Percival 826ae1554aSColin Percival (void)setlocale(LC_CTYPE, ""); 836ae1554aSColin Percival 846ae1554aSColin Percival while ((ch = getopt(argc, argv, "ef:hlruUw")) != -1) 856ae1554aSColin Percival switch (ch) { 866ae1554aSColin Percival case 'e': 876ae1554aSColin Percival random_exit = 1; 886ae1554aSColin Percival break; 896ae1554aSColin Percival case 'f': 906ae1554aSColin Percival randomize_lines = 1; 916ae1554aSColin Percival if (strcmp(optarg, "-") != 0) 926ae1554aSColin Percival filename = optarg; 936ae1554aSColin Percival break; 946ae1554aSColin Percival case 'l': 956ae1554aSColin Percival randomize_lines = 1; 966ae1554aSColin Percival random_type = RANDOM_TYPE_LINES; 976ae1554aSColin Percival break; 986ae1554aSColin Percival case 'r': 996ae1554aSColin Percival unbuffer_output = 1; 1006ae1554aSColin Percival break; 1016ae1554aSColin Percival case 'u': 1026ae1554aSColin Percival randomize_lines = 1; 1036ae1554aSColin Percival unique_output = 1; 1046ae1554aSColin Percival break; 1056ae1554aSColin Percival case 'U': 1066ae1554aSColin Percival randomize_lines = 1; 1076ae1554aSColin Percival unique_output = 0; 1086ae1554aSColin Percival break; 1096ae1554aSColin Percival case 'w': 1106ae1554aSColin Percival randomize_lines = 1; 1116ae1554aSColin Percival random_type = RANDOM_TYPE_WORDS; 1126ae1554aSColin Percival break; 1136ae1554aSColin Percival default: 1146ae1554aSColin Percival case '?': 1156ae1554aSColin Percival usage(); 1166ae1554aSColin Percival /* NOTREACHED */ 1176ae1554aSColin Percival } 1186ae1554aSColin Percival 1196ae1554aSColin Percival argc -= optind; 1206ae1554aSColin Percival argv += optind; 1216ae1554aSColin Percival 1226ae1554aSColin Percival switch (argc) { 1236ae1554aSColin Percival case 0: 124*06257a71SConrad Meyer denom = (randomize_lines ? 1. : 2.); 1256ae1554aSColin Percival break; 1266ae1554aSColin Percival case 1: 1276ae1554aSColin Percival errno = 0; 1286ae1554aSColin Percival denom = strtod(*argv, &ep); 1296ae1554aSColin Percival if (errno == ERANGE) 1306ae1554aSColin Percival err(1, "%s", *argv); 131*06257a71SConrad Meyer if (denom < 1. || *ep != '\0') 1326ae1554aSColin Percival errx(1, "denominator is not valid."); 133*06257a71SConrad Meyer if (random_exit && denom > 256.) 1346ae1554aSColin Percival errx(1, "denominator must be <= 256 for random exit."); 1356ae1554aSColin Percival break; 1366ae1554aSColin Percival default: 1376ae1554aSColin Percival usage(); 1386ae1554aSColin Percival /* NOTREACHED */ 1396ae1554aSColin Percival } 1406ae1554aSColin Percival 1416ae1554aSColin Percival /* 1426ae1554aSColin Percival * Act as a filter, randomly choosing lines of the standard input 1436ae1554aSColin Percival * to write to the standard output. 1446ae1554aSColin Percival */ 1456ae1554aSColin Percival if (unbuffer_output) 1466ae1554aSColin Percival setbuf(stdout, NULL); 1476ae1554aSColin Percival 1486ae1554aSColin Percival /* 1496ae1554aSColin Percival * Act as a filter, randomizing lines read in from a given file 1506ae1554aSColin Percival * descriptor and write the output to standard output. 1516ae1554aSColin Percival */ 1526ae1554aSColin Percival if (randomize_lines) { 1536ae1554aSColin Percival if ((fd = open(filename, O_RDONLY, 0)) < 0) 1546ae1554aSColin Percival err(1, "%s", filename); 1556ae1554aSColin Percival ret = randomize_fd(fd, random_type, unique_output, denom); 1566ae1554aSColin Percival if (!random_exit) 1576ae1554aSColin Percival return(ret); 1586ae1554aSColin Percival } 1596ae1554aSColin Percival 1606ae1554aSColin Percival /* Compute a random exit status between 0 and denom - 1. */ 1616ae1554aSColin Percival if (random_exit) 162c7b8411cSConrad Meyer return (arc4random_uniform(denom)); 1636ae1554aSColin Percival 1646ae1554aSColin Percival /* 165*06257a71SConrad Meyer * Filter stdin, selecting lines with probability 1/denom, one 166*06257a71SConrad Meyer * character at a time. 1676ae1554aSColin Percival */ 168*06257a71SConrad Meyer do { 169*06257a71SConrad Meyer selected = random_uniform_denom(denom); 170*06257a71SConrad Meyer if (selected) { 1716ae1554aSColin Percival while ((ch = getchar()) != EOF) { 172*06257a71SConrad Meyer putchar(ch); 173*06257a71SConrad Meyer if (ch == '\n') 174*06257a71SConrad Meyer break; 175*06257a71SConrad Meyer } 176*06257a71SConrad Meyer } else { 177*06257a71SConrad Meyer while ((ch = getchar()) != EOF) 178*06257a71SConrad Meyer if (ch == '\n') 179*06257a71SConrad Meyer break; 180*06257a71SConrad Meyer } 1816ae1554aSColin Percival if (ferror(stdout)) 1826ae1554aSColin Percival err(2, "stdout"); 183*06257a71SConrad Meyer } while (ch != EOF); 1846ae1554aSColin Percival if (ferror(stdin)) 1856ae1554aSColin Percival err(2, "stdin"); 1866ae1554aSColin Percival exit (0); 1876ae1554aSColin Percival } 1886ae1554aSColin Percival 1896ae1554aSColin Percival static void 1906ae1554aSColin Percival usage(void) 1916ae1554aSColin Percival { 1926ae1554aSColin Percival 1936ae1554aSColin Percival fprintf(stderr, "usage: random [-elrUuw] [-f filename] [denominator]\n"); 1946ae1554aSColin Percival exit(1); 1956ae1554aSColin Percival } 196