166531Sbostic /* 266531Sbostic * Copyright (c) 1994 366531Sbostic * The Regents of the University of California. All rights reserved. 466531Sbostic * 566531Sbostic * This code is derived from software contributed to Berkeley by 666531Sbostic * Guy Harris at Network Appliance Corp. 766531Sbostic * 866531Sbostic * %sccs.include.redist.c% 966531Sbostic */ 1066531Sbostic 1166531Sbostic #ifndef lint 1266531Sbostic static char copyright[] = 1366531Sbostic "@(#) Copyright (c) 1994\n\ 1466531Sbostic The Regents of the University of California. All rights reserved.\n"; 1566531Sbostic #endif /* not lint */ 1666531Sbostic 1766531Sbostic #ifndef lint 18*66719Spendry static char sccsid[] = "@(#)random.c 8.4 (Berkeley) 04/05/94"; 1966531Sbostic #endif /* not lint */ 2066531Sbostic 2166531Sbostic #include <sys/types.h> 2266531Sbostic 2366531Sbostic #include <err.h> 2466531Sbostic #include <errno.h> 2566531Sbostic #include <stdio.h> 2666531Sbostic #include <stdlib.h> 2766531Sbostic #include <time.h> 2866531Sbostic #include <unistd.h> 2966531Sbostic 3066531Sbostic void usage __P((void)); 3166531Sbostic 3266531Sbostic int 3366531Sbostic main(argc, argv) 3466531Sbostic int argc; 3566531Sbostic char *argv[]; 3666531Sbostic { 3766531Sbostic extern int optind; 3866531Sbostic time_t now; 3966531Sbostic double denom; 4066531Sbostic int ch, random_exit, selected, unbuffer_output; 4166531Sbostic char *ep; 4266531Sbostic 4366531Sbostic random_exit = unbuffer_output = 0; 4466531Sbostic while ((ch = getopt(argc, argv, "er")) != EOF) 4566531Sbostic switch (ch) { 4666531Sbostic case 'e': 4766531Sbostic random_exit = 1; 4866531Sbostic break; 4966531Sbostic case 'r': 5066531Sbostic unbuffer_output = 1; 5166531Sbostic break; 5266531Sbostic default: 5366531Sbostic case '?': 5466531Sbostic usage(); 5566531Sbostic /* NOTREACHED */ 5666531Sbostic } 5766531Sbostic 5866531Sbostic argc -= optind; 5966531Sbostic argv += optind; 6066531Sbostic 6166531Sbostic switch (argc) { 6266531Sbostic case 0: 6366531Sbostic denom = 2; 6466531Sbostic break; 6566531Sbostic case 1: 6666531Sbostic errno = 0; 6766531Sbostic denom = strtod(*argv, &ep); 6866531Sbostic if (errno == ERANGE) 6966531Sbostic err(1, "%s", *argv); 7066531Sbostic if (denom == 0 || *ep != '\0') 7166531Sbostic errx(1, "denominator is not valid."); 7266531Sbostic break; 7366531Sbostic default: 7466531Sbostic usage(); 7566531Sbostic /* NOTREACHED */ 7666531Sbostic } 7766531Sbostic 7866531Sbostic (void)time(&now); 7966531Sbostic srandom((u_int)(now + getpid())); 8066531Sbostic 8166531Sbostic /* Compute a random exit status between 0 and denom - 1. */ 8266531Sbostic if (random_exit) 8366531Sbostic return ((denom * random()) / LONG_MAX); 8466531Sbostic 8566531Sbostic /* 8666531Sbostic * Act as a filter, randomly choosing lines of the standard input 8766531Sbostic * to write to the standard output. 8866531Sbostic */ 8966531Sbostic if (unbuffer_output) 9066531Sbostic setbuf(stdout, NULL); 9166531Sbostic 9266531Sbostic /* 9366531Sbostic * Select whether to print the first line. (Prime the pump.) 9466531Sbostic * We find a random number between 0 and denom - 1 and, if it's 9566531Sbostic * 0 (which has a 1 / denom chance of being true), we select the 9666531Sbostic * line. 9766531Sbostic */ 98*66719Spendry selected = !(int)((denom * random()) / LONG_MAX); 9966531Sbostic while ((ch = getchar()) != EOF) { 10066531Sbostic if (selected) 10166531Sbostic (void)putchar(ch); 10266531Sbostic if (ch == '\n') { 10366531Sbostic /* End of that line. See if we got an error. */ 10466531Sbostic if (ferror(stdout)) 10566531Sbostic err(2, "stdout"); 10666531Sbostic 10766531Sbostic /* Now see if the next line is to be printed. */ 108*66719Spendry selected = !(int)((denom * random()) / LONG_MAX); 10966531Sbostic } 11066531Sbostic } 11166531Sbostic if (ferror(stdin)) 11266531Sbostic err(2, "stdin"); 11366531Sbostic exit (0); 11466531Sbostic } 11566531Sbostic 11666531Sbostic void 11766531Sbostic usage() 11866531Sbostic { 119*66719Spendry 12066533Sbostic (void)fprintf(stderr, "usage: random [-er] [denominator]\n"); 12166531Sbostic exit(1); 12266531Sbostic } 123