xref: /csrg-svn/games/random/random.c (revision 66719)
166531Sbostic /*
266531Sbostic  * Copyright (c) 1994
366531Sbostic  *	The Regents of the University of California.  All rights reserved.
466531Sbostic  *
566531Sbostic  * This code is derived from software contributed to Berkeley by
666531Sbostic  * Guy Harris at Network Appliance Corp.
766531Sbostic  *
866531Sbostic  * %sccs.include.redist.c%
966531Sbostic  */
1066531Sbostic 
1166531Sbostic #ifndef lint
1266531Sbostic static char copyright[] =
1366531Sbostic "@(#) Copyright (c) 1994\n\
1466531Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1566531Sbostic #endif /* not lint */
1666531Sbostic 
1766531Sbostic #ifndef lint
18*66719Spendry static char sccsid[] = "@(#)random.c	8.4 (Berkeley) 04/05/94";
1966531Sbostic #endif /* not lint */
2066531Sbostic 
2166531Sbostic #include <sys/types.h>
2266531Sbostic 
2366531Sbostic #include <err.h>
2466531Sbostic #include <errno.h>
2566531Sbostic #include <stdio.h>
2666531Sbostic #include <stdlib.h>
2766531Sbostic #include <time.h>
2866531Sbostic #include <unistd.h>
2966531Sbostic 
3066531Sbostic void usage __P((void));
3166531Sbostic 
3266531Sbostic int
3366531Sbostic main(argc, argv)
3466531Sbostic 	int argc;
3566531Sbostic 	char *argv[];
3666531Sbostic {
3766531Sbostic 	extern int optind;
3866531Sbostic 	time_t now;
3966531Sbostic 	double denom;
4066531Sbostic 	int ch, random_exit, selected, unbuffer_output;
4166531Sbostic 	char *ep;
4266531Sbostic 
4366531Sbostic 	random_exit = unbuffer_output = 0;
4466531Sbostic 	while ((ch = getopt(argc, argv, "er")) != EOF)
4566531Sbostic 		switch (ch) {
4666531Sbostic 		case 'e':
4766531Sbostic 			random_exit = 1;
4866531Sbostic 			break;
4966531Sbostic 		case 'r':
5066531Sbostic 			unbuffer_output = 1;
5166531Sbostic 			break;
5266531Sbostic 		default:
5366531Sbostic 		case '?':
5466531Sbostic 			usage();
5566531Sbostic 			/* NOTREACHED */
5666531Sbostic 		}
5766531Sbostic 
5866531Sbostic 	argc -= optind;
5966531Sbostic 	argv += optind;
6066531Sbostic 
6166531Sbostic 	switch (argc) {
6266531Sbostic 	case 0:
6366531Sbostic 		denom = 2;
6466531Sbostic 		break;
6566531Sbostic 	case 1:
6666531Sbostic 		errno = 0;
6766531Sbostic 		denom = strtod(*argv, &ep);
6866531Sbostic 		if (errno == ERANGE)
6966531Sbostic 			err(1, "%s", *argv);
7066531Sbostic 		if (denom == 0 || *ep != '\0')
7166531Sbostic 			errx(1, "denominator is not valid.");
7266531Sbostic 		break;
7366531Sbostic 	default:
7466531Sbostic 		usage();
7566531Sbostic 		/* NOTREACHED */
7666531Sbostic 	}
7766531Sbostic 
7866531Sbostic 	(void)time(&now);
7966531Sbostic 	srandom((u_int)(now + getpid()));
8066531Sbostic 
8166531Sbostic 	/* Compute a random exit status between 0 and denom - 1. */
8266531Sbostic 	if (random_exit)
8366531Sbostic 		return ((denom * random()) / LONG_MAX);
8466531Sbostic 
8566531Sbostic 	/*
8666531Sbostic 	 * Act as a filter, randomly choosing lines of the standard input
8766531Sbostic 	 * to write to the standard output.
8866531Sbostic 	 */
8966531Sbostic 	if (unbuffer_output)
9066531Sbostic 		setbuf(stdout, NULL);
9166531Sbostic 
9266531Sbostic 	/*
9366531Sbostic 	 * Select whether to print the first line.  (Prime the pump.)
9466531Sbostic 	 * We find a random number between 0 and denom - 1 and, if it's
9566531Sbostic 	 * 0 (which has a 1 / denom chance of being true), we select the
9666531Sbostic 	 * line.
9766531Sbostic 	 */
98*66719Spendry 	selected = !(int)((denom * random()) / LONG_MAX);
9966531Sbostic 	while ((ch = getchar()) != EOF) {
10066531Sbostic 		if (selected)
10166531Sbostic 			(void)putchar(ch);
10266531Sbostic 		if (ch == '\n') {
10366531Sbostic 			/* End of that line.  See if we got an error. */
10466531Sbostic 			if (ferror(stdout))
10566531Sbostic 				err(2, "stdout");
10666531Sbostic 
10766531Sbostic 			/* Now see if the next line is to be printed. */
108*66719Spendry 			selected = !(int)((denom * random()) / LONG_MAX);
10966531Sbostic 		}
11066531Sbostic 	}
11166531Sbostic 	if (ferror(stdin))
11266531Sbostic 		err(2, "stdin");
11366531Sbostic 	exit (0);
11466531Sbostic }
11566531Sbostic 
11666531Sbostic void
11766531Sbostic usage()
11866531Sbostic {
119*66719Spendry 
12066533Sbostic 	(void)fprintf(stderr, "usage: random [-er] [denominator]\n");
12166531Sbostic 	exit(1);
12266531Sbostic }
123