(linenum→info "unix/slp.c:2238")

bsd-games/2.17/random/random.c

    1: /*      $NetBSD: random.c,v 1.9 2004/01/27 20:30:30 jsm Exp $        */
    2: 
    3: /*
    4:  * Copyright (c) 1994
    5:  *      The Regents of the University of California.  All rights reserved.
    6:  *
    7:  * This code is derived from software contributed to Berkeley by
    8:  * Guy Harris at Network Appliance Corp.
    9:  *
   10:  * Redistribution and use in source and binary forms, with or without
   11:  * modification, are permitted provided that the following conditions
   12:  * are met:
   13:  * 1. Redistributions of source code must retain the above copyright
   14:  *    notice, this list of conditions and the following disclaimer.
   15:  * 2. Redistributions in binary form must reproduce the above copyright
   16:  *    notice, this list of conditions and the following disclaimer in the
   17:  *    documentation and/or other materials provided with the distribution.
   18:  * 3. Neither the name of the University nor the names of its contributors
   19:  *    may be used to endorse or promote products derived from this software
   20:  *    without specific prior written permission.
   21:  *
   22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32:  * SUCH DAMAGE.
   33:  */
   34: 
   35: #include <sys/cdefs.h>
   36: #ifndef lint
   37: __COPYRIGHT("@(#) Copyright (c) 1994\n\
   38:         The Regents of the University of California.  All rights reserved.\n");
   39: #endif /* not lint */
   40: 
   41: #ifndef lint
   42: #if 0
   43: static char sccsid[] = "@(#)random.c    8.6 (Berkeley) 6/1/94";
   44: #else
   45: __RCSID("$NetBSD: random.c,v 1.9 2004/01/27 20:30:30 jsm Exp $");
   46: #endif
   47: #endif /* not lint */
   48: 
   49: #include <sys/types.h>
   50: #include <sys/time.h>
   51: 
   52: #include <err.h>
   53: #include <errno.h>
   54: #include <stdio.h>
   55: #include <stdlib.h>
   56: #include <time.h>
   57: #include <unistd.h>
   58: #include <limits.h>
   59: 
   60: #define MAXRANDOM       2147483647
   61: 
   62: int  main(int, char **);
   63: void usage(void) __attribute__((__noreturn__));
   64: 
   65: int
   66: main(argc, argv)
   67:         int argc;
   68:         char *argv[];
   69: {
   70:         struct timeval tp;
   71:         double denom;
   72:         int ch, random_exit, selected, unbuffer_output;
   73:         char *ep;
   74: 
   75:         /* Revoke setgid privileges */
   76:         setregid(getgid(), getgid());
   77: 
   78:         denom = 0;
   79:         random_exit = unbuffer_output = 0;
   80:         while ((ch = getopt(argc, argv, "er")) != -1)
   81:                 switch (ch) {
   82:                 case 'e':
   83:                         random_exit = 1;
   84:                         break;
   85:                 case 'r':
   86:                         unbuffer_output = 1;
   87:                         break;
   88:                 default:
   89:                 case '?':
   90:                         usage();
   91:                         /* NOTREACHED */
   92:                 }
   93: 
   94:         argc -= optind;
   95:         argv += optind;
   96: 
   97:         switch (argc) {
   98:         case 0:
   99:                 denom = 2;
  100:                 break;
  101:         case 1:
  102:                 errno = 0;
  103:                 denom = strtod(*argv, &ep);
  104:                 if (errno == ERANGE)
  105:                         err(1, "%s", *argv);
  106:                 if (denom == 0 || *ep != '\0')
  107:                         errx(1, "denominator is not valid.");
  108:                 break;
  109:         default:
  110:                 usage(); 
  111:                 /* NOTREACHED */
  112:         }
  113: 
  114:         (void)gettimeofday(&tp, NULL);
  115:         srandom((u_int)(tp.tv_usec + tp.tv_sec + getpid()));
  116: 
  117:         /* Compute a random exit status between 0 and denom - 1. */
  118:         if (random_exit)
  119:                 return ((denom * random()) / MAXRANDOM);
  120: 
  121:         /*
  122:          * Act as a filter, randomly choosing lines of the standard input
  123:          * to write to the standard output.
  124:          */
  125:         if (unbuffer_output)
  126:                 setbuf(stdout, NULL);
  127:         
  128:         /*
  129:          * Select whether to print the first line.  (Prime the pump.)
  130:          * We find a random number between 0 and denom - 1 and, if it's
  131:          * 0 (which has a 1 / denom chance of being true), we select the
  132:          * line.
  133:          */
  134:         selected = (int)(denom * random() / MAXRANDOM) == 0;
  135:         while ((ch = getchar()) != EOF) {
  136:                 if (selected)
  137:                         (void)putchar(ch);
  138:                 if (ch == '\n') {
  139:                         /* End of that line.  See if we got an error. */
  140:                         if (ferror(stdout))
  141:                                 err(2, "stdout");
  142: 
  143:                         /* Now see if the next line is to be printed. */
  144:                         selected = (int)(denom * random() / MAXRANDOM) == 0;
  145:                 }
  146:         }
  147:         if (ferror(stdin))
  148:                 err(2, "stdin");
  149:         exit (0);
  150: }
  151: 
  152: void
  153: usage()
  154: {
  155: 
  156:         (void)fprintf(stderr, "usage: random [-er] [denominator]\n");
  157:         exit(1);
  158: }
Syntax (Markdown)