xref: /csrg-svn/games/random/random.c (revision 67358)
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*67358Sbostic static char sccsid[] = "@(#)random.c	8.6 (Berkeley) 06/01/94";
1966531Sbostic #endif /* not lint */
2066531Sbostic 
2166531Sbostic #include <sys/types.h>
22*67358Sbostic #include <sys/time.h>
2366531Sbostic 
2466531Sbostic #include <err.h>
2566531Sbostic #include <errno.h>
2666531Sbostic #include <stdio.h>
2766531Sbostic #include <stdlib.h>
2866531Sbostic #include <time.h>
2966531Sbostic #include <unistd.h>
3066531Sbostic 
3166531Sbostic void usage __P((void));
3266531Sbostic 
3366531Sbostic int
main(argc,argv)3466531Sbostic main(argc, argv)
3566531Sbostic 	int argc;
3666531Sbostic 	char *argv[];
3766531Sbostic {
3866531Sbostic 	extern int optind;
39*67358Sbostic 	struct timeval tp;
4066531Sbostic 	double denom;
4166531Sbostic 	int ch, random_exit, selected, unbuffer_output;
4266531Sbostic 	char *ep;
4366531Sbostic 
4466531Sbostic 	random_exit = unbuffer_output = 0;
4566531Sbostic 	while ((ch = getopt(argc, argv, "er")) != EOF)
4666531Sbostic 		switch (ch) {
4766531Sbostic 		case 'e':
4866531Sbostic 			random_exit = 1;
4966531Sbostic 			break;
5066531Sbostic 		case 'r':
5166531Sbostic 			unbuffer_output = 1;
5266531Sbostic 			break;
5366531Sbostic 		default:
5466531Sbostic 		case '?':
5566531Sbostic 			usage();
5666531Sbostic 			/* NOTREACHED */
5766531Sbostic 		}
5866531Sbostic 
5966531Sbostic 	argc -= optind;
6066531Sbostic 	argv += optind;
6166531Sbostic 
6266531Sbostic 	switch (argc) {
6366531Sbostic 	case 0:
6466531Sbostic 		denom = 2;
6566531Sbostic 		break;
6666531Sbostic 	case 1:
6766531Sbostic 		errno = 0;
6866531Sbostic 		denom = strtod(*argv, &ep);
6966531Sbostic 		if (errno == ERANGE)
7066531Sbostic 			err(1, "%s", *argv);
7166531Sbostic 		if (denom == 0 || *ep != '\0')
7266531Sbostic 			errx(1, "denominator is not valid.");
7366531Sbostic 		break;
7466531Sbostic 	default:
7566531Sbostic 		usage();
7666531Sbostic 		/* NOTREACHED */
7766531Sbostic 	}
7866531Sbostic 
79*67358Sbostic 	(void)gettimeofday(&tp, NULL);
80*67358Sbostic 	srandom((u_int)(tp.tv_usec + tp.tv_sec + getpid()));
8166531Sbostic 
8266531Sbostic 	/* Compute a random exit status between 0 and denom - 1. */
8366531Sbostic 	if (random_exit)
8466531Sbostic 		return ((denom * random()) / LONG_MAX);
8566531Sbostic 
8666531Sbostic 	/*
8766531Sbostic 	 * Act as a filter, randomly choosing lines of the standard input
8866531Sbostic 	 * to write to the standard output.
8966531Sbostic 	 */
9066531Sbostic 	if (unbuffer_output)
9166531Sbostic 		setbuf(stdout, NULL);
9266531Sbostic 
9366531Sbostic 	/*
9466531Sbostic 	 * Select whether to print the first line.  (Prime the pump.)
9566531Sbostic 	 * We find a random number between 0 and denom - 1 and, if it's
9666531Sbostic 	 * 0 (which has a 1 / denom chance of being true), we select the
9766531Sbostic 	 * line.
9866531Sbostic 	 */
9966720Sbostic 	selected = (int)(denom * random() / LONG_MAX) == 0;
10066531Sbostic 	while ((ch = getchar()) != EOF) {
10166531Sbostic 		if (selected)
10266531Sbostic 			(void)putchar(ch);
10366531Sbostic 		if (ch == '\n') {
10466531Sbostic 			/* End of that line.  See if we got an error. */
10566531Sbostic 			if (ferror(stdout))
10666531Sbostic 				err(2, "stdout");
10766531Sbostic 
10866531Sbostic 			/* Now see if the next line is to be printed. */
10966720Sbostic 			selected = (int)(denom * random() / LONG_MAX) == 0;
11066531Sbostic 		}
11166531Sbostic 	}
11266531Sbostic 	if (ferror(stdin))
11366531Sbostic 		err(2, "stdin");
11466531Sbostic 	exit (0);
11566531Sbostic }
11666531Sbostic 
11766531Sbostic void
usage()11866531Sbostic usage()
11966531Sbostic {
12066719Spendry 
12166533Sbostic 	(void)fprintf(stderr, "usage: random [-er] [denominator]\n");
12266531Sbostic 	exit(1);
12366531Sbostic }
124