1 /* 2 * Copyright (c) 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Guy Harris at Network Appliance Corp. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char copyright[] = 13 "@(#) Copyright (c) 1994\n\ 14 The Regents of the University of California. All rights reserved.\n"; 15 #endif /* not lint */ 16 17 #ifndef lint 18 static char sccsid[] = "@(#)random.c 8.5 (Berkeley) 04/05/94"; 19 #endif /* not lint */ 20 21 #include <sys/types.h> 22 23 #include <err.h> 24 #include <errno.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <time.h> 28 #include <unistd.h> 29 30 void usage __P((void)); 31 32 int 33 main(argc, argv) 34 int argc; 35 char *argv[]; 36 { 37 extern int optind; 38 time_t now; 39 double denom; 40 int ch, random_exit, selected, unbuffer_output; 41 char *ep; 42 43 random_exit = unbuffer_output = 0; 44 while ((ch = getopt(argc, argv, "er")) != EOF) 45 switch (ch) { 46 case 'e': 47 random_exit = 1; 48 break; 49 case 'r': 50 unbuffer_output = 1; 51 break; 52 default: 53 case '?': 54 usage(); 55 /* NOTREACHED */ 56 } 57 58 argc -= optind; 59 argv += optind; 60 61 switch (argc) { 62 case 0: 63 denom = 2; 64 break; 65 case 1: 66 errno = 0; 67 denom = strtod(*argv, &ep); 68 if (errno == ERANGE) 69 err(1, "%s", *argv); 70 if (denom == 0 || *ep != '\0') 71 errx(1, "denominator is not valid."); 72 break; 73 default: 74 usage(); 75 /* NOTREACHED */ 76 } 77 78 (void)time(&now); 79 srandom((u_int)(now + getpid())); 80 81 /* Compute a random exit status between 0 and denom - 1. */ 82 if (random_exit) 83 return ((denom * random()) / LONG_MAX); 84 85 /* 86 * Act as a filter, randomly choosing lines of the standard input 87 * to write to the standard output. 88 */ 89 if (unbuffer_output) 90 setbuf(stdout, NULL); 91 92 /* 93 * Select whether to print the first line. (Prime the pump.) 94 * We find a random number between 0 and denom - 1 and, if it's 95 * 0 (which has a 1 / denom chance of being true), we select the 96 * line. 97 */ 98 selected = (int)(denom * random() / LONG_MAX) == 0; 99 while ((ch = getchar()) != EOF) { 100 if (selected) 101 (void)putchar(ch); 102 if (ch == '\n') { 103 /* End of that line. See if we got an error. */ 104 if (ferror(stdout)) 105 err(2, "stdout"); 106 107 /* Now see if the next line is to be printed. */ 108 selected = (int)(denom * random() / LONG_MAX) == 0; 109 } 110 } 111 if (ferror(stdin)) 112 err(2, "stdin"); 113 exit (0); 114 } 115 116 void 117 usage() 118 { 119 120 (void)fprintf(stderr, "usage: random [-er] [denominator]\n"); 121 exit(1); 122 } 123