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