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