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