xref: /original-bsd/games/random/random.c (revision e58c8952)
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