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
main(argc,argv)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
usage()118 usage()
119 {
120
121 (void)fprintf(stderr, "usage: random [-er] [denominator]\n");
122 exit(1);
123 }
124