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