rand.c revision 92986
11573Srgrimes/*-
21573Srgrimes * Copyright (c) 1990, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * Redistribution and use in source and binary forms, with or without
61573Srgrimes * modification, are permitted provided that the following conditions
71573Srgrimes * are met:
81573Srgrimes * 1. Redistributions of source code must retain the above copyright
91573Srgrimes *    notice, this list of conditions and the following disclaimer.
101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111573Srgrimes *    notice, this list of conditions and the following disclaimer in the
121573Srgrimes *    documentation and/or other materials provided with the distribution.
131573Srgrimes * 3. All advertising materials mentioning features or use of this software
141573Srgrimes *    must display the following acknowledgement:
151573Srgrimes *	This product includes software developed by the University of
161573Srgrimes *	California, Berkeley and its contributors.
171573Srgrimes * 4. Neither the name of the University nor the names of its contributors
181573Srgrimes *    may be used to endorse or promote products derived from this software
191573Srgrimes *    without specific prior written permission.
201573Srgrimes *
211573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311573Srgrimes * SUCH DAMAGE.
3247474Swes *
3347474Swes * Posix rand_r function added May 1999 by Wes Peters <wes@softweyr.com>.
341573Srgrimes */
351573Srgrimes
361573Srgrimes#if defined(LIBC_SCCS) && !defined(lint)
371573Srgrimesstatic char sccsid[] = "@(#)rand.c	8.1 (Berkeley) 6/14/93";
381573Srgrimes#endif /* LIBC_SCCS and not lint */
3992986Sobrien#include <sys/cdefs.h>
4092986Sobrien__FBSDID("$FreeBSD: head/lib/libc/stdlib/rand.c 92986 2002-03-22 21:53:29Z obrien $");
411573Srgrimes
4275845Sache#include <sys/time.h>          /* for sranddev() */
431573Srgrimes#include <sys/types.h>
4475845Sache#include <fcntl.h>             /* for sranddev() */
451573Srgrimes#include <stdlib.h>
4675845Sache#include <unistd.h>            /* for sranddev() */
4775863Sache#include "un-namespace.h"
481573Srgrimes
4947474Swes#ifdef TEST
5047474Swes#include <stdio.h>
5147474Swes#endif /* TEST */
5247474Swes
5347474Swesstatic int
5447474Swesdo_rand(unsigned long *ctx)
5547474Swes{
5673156Sache#ifdef  USE_WEAK_SEEDING
5773156Sache/*
5873156Sache * Historic implementation compatibility.
5973156Sache * The random sequences do not vary much with the seed,
6073156Sache * even with overflowing.
6173156Sache */
6247474Swes	return ((*ctx = *ctx * 1103515245 + 12345) % ((u_long)RAND_MAX + 1));
6373156Sache#else   /* !USE_WEAK_SEEDING */
6473156Sache/*
6573156Sache * Compute x = (7^5 * x) mod (2^31 - 1)
6673156Sache * wihout overflowing 31 bits:
6773156Sache *      (2^31 - 1) = 127773 * (7^5) + 2836
6873156Sache * From "Random number generators: good ones are hard to find",
6973156Sache * Park and Miller, Communications of the ACM, vol. 31, no. 10,
7073156Sache * October 1988, p. 1195.
7173156Sache */
7273156Sache	long hi, lo, x;
7373156Sache
7473156Sache	hi = *ctx / 127773;
7573156Sache	lo = *ctx % 127773;
7673156Sache	x = 16807 * lo - 2836 * hi;
7773156Sache	if (x <= 0)
7873156Sache		x += 0x7fffffff;
7973156Sache	return ((*ctx = x) % ((u_long)RAND_MAX + 1));
8073156Sache#endif  /* !USE_WEAK_SEEDING */
8147474Swes}
8247474Swes
8347474Swes
8447474Swesint
8547474Swesrand_r(unsigned int *ctx)
8647474Swes{
8747474Swes	u_long val = (u_long) *ctx;
8847474Swes	*ctx = do_rand(&val);
8947474Swes	return (int) *ctx;
9047474Swes}
9147474Swes
9247474Swes
931573Srgrimesstatic u_long next = 1;
941573Srgrimes
951573Srgrimesint
961573Srgrimesrand()
971573Srgrimes{
9847474Swes	return do_rand(&next);
991573Srgrimes}
1001573Srgrimes
1011573Srgrimesvoid
1021573Srgrimessrand(seed)
1031573Srgrimesu_int seed;
1041573Srgrimes{
1051573Srgrimes	next = seed;
1061573Srgrimes}
10747474Swes
10875845Sache
10975845Sache/*
11075845Sache * sranddev:
11175845Sache *
11275845Sache * Many programs choose the seed value in a totally predictable manner.
11375845Sache * This often causes problems.  We seed the generator using the much more
11477851Sdd * secure random(4) interface.
11575845Sache */
11675845Sachevoid
11775845Sachesranddev()
11875845Sache{
11975845Sache	int fd, done;
12075845Sache
12175845Sache	done = 0;
12285752Smarkm	fd = _open("/dev/random", O_RDONLY, 0);
12375845Sache	if (fd >= 0) {
12475845Sache		if (_read(fd, (void *) &next, sizeof(next)) == sizeof(next))
12575845Sache			done = 1;
12675845Sache		_close(fd);
12775845Sache	}
12875845Sache
12975845Sache	if (!done) {
13075845Sache		struct timeval tv;
13175845Sache		unsigned long junk;
13275845Sache
13375845Sache		gettimeofday(&tv, NULL);
13475862Sache		next = (getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk;
13575845Sache	}
13675845Sache}
13775845Sache
13875845Sache
13947474Swes#ifdef TEST
14047474Swes
14147474Swesmain()
14247474Swes{
14347474Swes    int i;
14447474Swes    unsigned myseed;
14547474Swes
14647474Swes    printf("seeding rand with 0x19610910: \n");
14747474Swes    srand(0x19610910);
14847474Swes
14947474Swes    printf("generating three pseudo-random numbers:\n");
15047474Swes    for (i = 0; i < 3; i++)
15147474Swes    {
15247474Swes	printf("next random number = %d\n", rand());
15347474Swes    }
15447474Swes
15547474Swes    printf("generating the same sequence with rand_r:\n");
15647474Swes    myseed = 0x19610910;
15747474Swes    for (i = 0; i < 3; i++)
15847474Swes    {
15947474Swes	printf("next random number = %d\n", rand_r(&myseed));
16047474Swes    }
16147474Swes
16247474Swes    return 0;
16347474Swes}
16447474Swes
16547474Swes#endif /* TEST */
16647474Swes
167