1*6ae1554aSColin Percival /* 2*6ae1554aSColin Percival * Copyright (c) 1994 3*6ae1554aSColin Percival * The Regents of the University of California. All rights reserved. 4*6ae1554aSColin Percival * 5*6ae1554aSColin Percival * This code is derived from software contributed to Berkeley by 6*6ae1554aSColin Percival * Guy Harris at Network Appliance Corp. 7*6ae1554aSColin Percival * 8*6ae1554aSColin Percival * Redistribution and use in source and binary forms, with or without 9*6ae1554aSColin Percival * modification, are permitted provided that the following conditions 10*6ae1554aSColin Percival * are met: 11*6ae1554aSColin Percival * 1. Redistributions of source code must retain the above copyright 12*6ae1554aSColin Percival * notice, this list of conditions and the following disclaimer. 13*6ae1554aSColin Percival * 2. Redistributions in binary form must reproduce the above copyright 14*6ae1554aSColin Percival * notice, this list of conditions and the following disclaimer in the 15*6ae1554aSColin Percival * documentation and/or other materials provided with the distribution. 16*6ae1554aSColin Percival * 3. Neither the name of the University nor the names of its contributors 17*6ae1554aSColin Percival * may be used to endorse or promote products derived from this software 18*6ae1554aSColin Percival * without specific prior written permission. 19*6ae1554aSColin Percival * 20*6ae1554aSColin Percival * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21*6ae1554aSColin Percival * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*6ae1554aSColin Percival * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*6ae1554aSColin Percival * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24*6ae1554aSColin Percival * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25*6ae1554aSColin Percival * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26*6ae1554aSColin Percival * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27*6ae1554aSColin Percival * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28*6ae1554aSColin Percival * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29*6ae1554aSColin Percival * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30*6ae1554aSColin Percival * SUCH DAMAGE. 31*6ae1554aSColin Percival */ 32*6ae1554aSColin Percival 33*6ae1554aSColin Percival #if 0 34*6ae1554aSColin Percival #ifndef lint 35*6ae1554aSColin Percival static const char copyright[] = 36*6ae1554aSColin Percival "@(#) Copyright (c) 1994\n\ 37*6ae1554aSColin Percival The Regents of the University of California. All rights reserved.\n"; 38*6ae1554aSColin Percival #endif /* not lint */ 39*6ae1554aSColin Percival 40*6ae1554aSColin Percival #ifndef lint 41*6ae1554aSColin Percival static const char sccsid[] = "@(#)random.c 8.5 (Berkeley) 4/5/94"; 42*6ae1554aSColin Percival #endif /* not lint */ 43*6ae1554aSColin Percival #endif 44*6ae1554aSColin Percival #include <sys/cdefs.h> 45*6ae1554aSColin Percival __FBSDID("$FreeBSD$"); 46*6ae1554aSColin Percival 47*6ae1554aSColin Percival #include <sys/types.h> 48*6ae1554aSColin Percival 49*6ae1554aSColin Percival #include <err.h> 50*6ae1554aSColin Percival #include <errno.h> 51*6ae1554aSColin Percival #include <fcntl.h> 52*6ae1554aSColin Percival #include <limits.h> 53*6ae1554aSColin Percival #include <locale.h> 54*6ae1554aSColin Percival #include <stdio.h> 55*6ae1554aSColin Percival #include <stdlib.h> 56*6ae1554aSColin Percival #include <string.h> 57*6ae1554aSColin Percival #include <time.h> 58*6ae1554aSColin Percival #include <unistd.h> 59*6ae1554aSColin Percival 60*6ae1554aSColin Percival #include "randomize_fd.h" 61*6ae1554aSColin Percival 62*6ae1554aSColin Percival static void usage(void); 63*6ae1554aSColin Percival 64*6ae1554aSColin Percival int 65*6ae1554aSColin Percival main(int argc, char *argv[]) 66*6ae1554aSColin Percival { 67*6ae1554aSColin Percival double denom; 68*6ae1554aSColin Percival int ch, fd, random_exit, randomize_lines, random_type, ret, 69*6ae1554aSColin Percival selected, unique_output, unbuffer_output; 70*6ae1554aSColin Percival char *ep; 71*6ae1554aSColin Percival const char *filename; 72*6ae1554aSColin Percival 73*6ae1554aSColin Percival denom = 0; 74*6ae1554aSColin Percival filename = "/dev/fd/0"; 75*6ae1554aSColin Percival random_type = RANDOM_TYPE_UNSET; 76*6ae1554aSColin Percival random_exit = randomize_lines = unbuffer_output = 0; 77*6ae1554aSColin Percival unique_output = 1; 78*6ae1554aSColin Percival 79*6ae1554aSColin Percival (void)setlocale(LC_CTYPE, ""); 80*6ae1554aSColin Percival 81*6ae1554aSColin Percival while ((ch = getopt(argc, argv, "ef:hlruUw")) != -1) 82*6ae1554aSColin Percival switch (ch) { 83*6ae1554aSColin Percival case 'e': 84*6ae1554aSColin Percival random_exit = 1; 85*6ae1554aSColin Percival break; 86*6ae1554aSColin Percival case 'f': 87*6ae1554aSColin Percival randomize_lines = 1; 88*6ae1554aSColin Percival if (strcmp(optarg, "-") != 0) 89*6ae1554aSColin Percival filename = optarg; 90*6ae1554aSColin Percival break; 91*6ae1554aSColin Percival case 'l': 92*6ae1554aSColin Percival randomize_lines = 1; 93*6ae1554aSColin Percival random_type = RANDOM_TYPE_LINES; 94*6ae1554aSColin Percival break; 95*6ae1554aSColin Percival case 'r': 96*6ae1554aSColin Percival unbuffer_output = 1; 97*6ae1554aSColin Percival break; 98*6ae1554aSColin Percival case 'u': 99*6ae1554aSColin Percival randomize_lines = 1; 100*6ae1554aSColin Percival unique_output = 1; 101*6ae1554aSColin Percival break; 102*6ae1554aSColin Percival case 'U': 103*6ae1554aSColin Percival randomize_lines = 1; 104*6ae1554aSColin Percival unique_output = 0; 105*6ae1554aSColin Percival break; 106*6ae1554aSColin Percival case 'w': 107*6ae1554aSColin Percival randomize_lines = 1; 108*6ae1554aSColin Percival random_type = RANDOM_TYPE_WORDS; 109*6ae1554aSColin Percival break; 110*6ae1554aSColin Percival default: 111*6ae1554aSColin Percival case '?': 112*6ae1554aSColin Percival usage(); 113*6ae1554aSColin Percival /* NOTREACHED */ 114*6ae1554aSColin Percival } 115*6ae1554aSColin Percival 116*6ae1554aSColin Percival argc -= optind; 117*6ae1554aSColin Percival argv += optind; 118*6ae1554aSColin Percival 119*6ae1554aSColin Percival switch (argc) { 120*6ae1554aSColin Percival case 0: 121*6ae1554aSColin Percival denom = (randomize_lines ? 1 : 2); 122*6ae1554aSColin Percival break; 123*6ae1554aSColin Percival case 1: 124*6ae1554aSColin Percival errno = 0; 125*6ae1554aSColin Percival denom = strtod(*argv, &ep); 126*6ae1554aSColin Percival if (errno == ERANGE) 127*6ae1554aSColin Percival err(1, "%s", *argv); 128*6ae1554aSColin Percival if (denom <= 0 || *ep != '\0') 129*6ae1554aSColin Percival errx(1, "denominator is not valid."); 130*6ae1554aSColin Percival if (random_exit && denom > 256) 131*6ae1554aSColin Percival errx(1, "denominator must be <= 256 for random exit."); 132*6ae1554aSColin Percival break; 133*6ae1554aSColin Percival default: 134*6ae1554aSColin Percival usage(); 135*6ae1554aSColin Percival /* NOTREACHED */ 136*6ae1554aSColin Percival } 137*6ae1554aSColin Percival 138*6ae1554aSColin Percival srandomdev(); 139*6ae1554aSColin Percival 140*6ae1554aSColin Percival /* 141*6ae1554aSColin Percival * Act as a filter, randomly choosing lines of the standard input 142*6ae1554aSColin Percival * to write to the standard output. 143*6ae1554aSColin Percival */ 144*6ae1554aSColin Percival if (unbuffer_output) 145*6ae1554aSColin Percival setbuf(stdout, NULL); 146*6ae1554aSColin Percival 147*6ae1554aSColin Percival /* 148*6ae1554aSColin Percival * Act as a filter, randomizing lines read in from a given file 149*6ae1554aSColin Percival * descriptor and write the output to standard output. 150*6ae1554aSColin Percival */ 151*6ae1554aSColin Percival if (randomize_lines) { 152*6ae1554aSColin Percival if ((fd = open(filename, O_RDONLY, 0)) < 0) 153*6ae1554aSColin Percival err(1, "%s", filename); 154*6ae1554aSColin Percival ret = randomize_fd(fd, random_type, unique_output, denom); 155*6ae1554aSColin Percival if (!random_exit) 156*6ae1554aSColin Percival return(ret); 157*6ae1554aSColin Percival } 158*6ae1554aSColin Percival 159*6ae1554aSColin Percival /* Compute a random exit status between 0 and denom - 1. */ 160*6ae1554aSColin Percival if (random_exit) 161*6ae1554aSColin Percival return (int)(denom * random() / RANDOM_MAX_PLUS1); 162*6ae1554aSColin Percival 163*6ae1554aSColin Percival /* 164*6ae1554aSColin Percival * Select whether to print the first line. (Prime the pump.) 165*6ae1554aSColin Percival * We find a random number between 0 and denom - 1 and, if it's 166*6ae1554aSColin Percival * 0 (which has a 1 / denom chance of being true), we select the 167*6ae1554aSColin Percival * line. 168*6ae1554aSColin Percival */ 169*6ae1554aSColin Percival selected = (int)(denom * random() / RANDOM_MAX_PLUS1) == 0; 170*6ae1554aSColin Percival while ((ch = getchar()) != EOF) { 171*6ae1554aSColin Percival if (selected) 172*6ae1554aSColin Percival (void)putchar(ch); 173*6ae1554aSColin Percival if (ch == '\n') { 174*6ae1554aSColin Percival /* End of that line. See if we got an error. */ 175*6ae1554aSColin Percival if (ferror(stdout)) 176*6ae1554aSColin Percival err(2, "stdout"); 177*6ae1554aSColin Percival 178*6ae1554aSColin Percival /* Now see if the next line is to be printed. */ 179*6ae1554aSColin Percival selected = (int)(denom * random() / 180*6ae1554aSColin Percival RANDOM_MAX_PLUS1) == 0; 181*6ae1554aSColin Percival } 182*6ae1554aSColin Percival } 183*6ae1554aSColin Percival if (ferror(stdin)) 184*6ae1554aSColin Percival err(2, "stdin"); 185*6ae1554aSColin Percival exit (0); 186*6ae1554aSColin Percival } 187*6ae1554aSColin Percival 188*6ae1554aSColin Percival static void 189*6ae1554aSColin Percival usage(void) 190*6ae1554aSColin Percival { 191*6ae1554aSColin Percival 192*6ae1554aSColin Percival fprintf(stderr, "usage: random [-elrUuw] [-f filename] [denominator]\n"); 193*6ae1554aSColin Percival exit(1); 194*6ae1554aSColin Percival } 195