rand.c revision 110236
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 110236 2003-02-02 14:27:51Z ache $");
411573Srgrimes
42108625Stjr#include "namespace.h"
4375845Sache#include <sys/time.h>          /* for sranddev() */
441573Srgrimes#include <sys/types.h>
4575845Sache#include <fcntl.h>             /* for sranddev() */
461573Srgrimes#include <stdlib.h>
4775845Sache#include <unistd.h>            /* for sranddev() */
4875863Sache#include "un-namespace.h"
491573Srgrimes
5047474Swes#ifdef TEST
5147474Swes#include <stdio.h>
5247474Swes#endif /* TEST */
5347474Swes
5447474Swesstatic int
5547474Swesdo_rand(unsigned long *ctx)
5647474Swes{
5773156Sache#ifdef  USE_WEAK_SEEDING
5873156Sache/*
5973156Sache * Historic implementation compatibility.
6073156Sache * The random sequences do not vary much with the seed,
6173156Sache * even with overflowing.
6273156Sache */
6347474Swes	return ((*ctx = *ctx * 1103515245 + 12345) % ((u_long)RAND_MAX + 1));
6473156Sache#else   /* !USE_WEAK_SEEDING */
6573156Sache/*
6673156Sache * Compute x = (7^5 * x) mod (2^31 - 1)
6773156Sache * wihout overflowing 31 bits:
6873156Sache *      (2^31 - 1) = 127773 * (7^5) + 2836
6973156Sache * From "Random number generators: good ones are hard to find",
7073156Sache * Park and Miller, Communications of the ACM, vol. 31, no. 10,
7173156Sache * October 1988, p. 1195.
7273156Sache */
7373156Sache	long hi, lo, x;
7473156Sache
7573156Sache	hi = *ctx / 127773;
7673156Sache	lo = *ctx % 127773;
7773156Sache	x = 16807 * lo - 2836 * hi;
7873156Sache	if (x <= 0)
7973156Sache		x += 0x7fffffff;
8073156Sache	return ((*ctx = x) % ((u_long)RAND_MAX + 1));
8173156Sache#endif  /* !USE_WEAK_SEEDING */
8247474Swes}
8347474Swes
8447474Swes
8547474Swesint
8647474Swesrand_r(unsigned int *ctx)
8747474Swes{
8847474Swes	u_long val = (u_long) *ctx;
89110236Sache	int r = do_rand(&val);
90110236Sache
91110236Sache	*ctx = (unsigned int) val;
92110236Sache	return (r);
9347474Swes}
9447474Swes
9547474Swes
961573Srgrimesstatic u_long next = 1;
971573Srgrimes
981573Srgrimesint
991573Srgrimesrand()
1001573Srgrimes{
10147474Swes	return do_rand(&next);
1021573Srgrimes}
1031573Srgrimes
1041573Srgrimesvoid
1051573Srgrimessrand(seed)
1061573Srgrimesu_int seed;
1071573Srgrimes{
1081573Srgrimes	next = seed;
1091573Srgrimes}
11047474Swes
11175845Sache
11275845Sache/*
11375845Sache * sranddev:
11475845Sache *
11575845Sache * Many programs choose the seed value in a totally predictable manner.
11675845Sache * This often causes problems.  We seed the generator using the much more
11777851Sdd * secure random(4) interface.
11875845Sache */
11975845Sachevoid
12075845Sachesranddev()
12175845Sache{
12275845Sache	int fd, done;
12375845Sache
12475845Sache	done = 0;
12585752Smarkm	fd = _open("/dev/random", O_RDONLY, 0);
12675845Sache	if (fd >= 0) {
12775845Sache		if (_read(fd, (void *) &next, sizeof(next)) == sizeof(next))
12875845Sache			done = 1;
12975845Sache		_close(fd);
13075845Sache	}
13175845Sache
13275845Sache	if (!done) {
13375845Sache		struct timeval tv;
13475845Sache		unsigned long junk;
13575845Sache
13675845Sache		gettimeofday(&tv, NULL);
13775862Sache		next = (getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk;
13875845Sache	}
13975845Sache}
14075845Sache
14175845Sache
14247474Swes#ifdef TEST
14347474Swes
14447474Swesmain()
14547474Swes{
14647474Swes    int i;
14747474Swes    unsigned myseed;
14847474Swes
14947474Swes    printf("seeding rand with 0x19610910: \n");
15047474Swes    srand(0x19610910);
15147474Swes
15247474Swes    printf("generating three pseudo-random numbers:\n");
15347474Swes    for (i = 0; i < 3; i++)
15447474Swes    {
15547474Swes	printf("next random number = %d\n", rand());
15647474Swes    }
15747474Swes
15847474Swes    printf("generating the same sequence with rand_r:\n");
15947474Swes    myseed = 0x19610910;
16047474Swes    for (i = 0; i < 3; i++)
16147474Swes    {
16247474Swes	printf("next random number = %d\n", rand_r(&myseed));
16347474Swes    }
16447474Swes
16547474Swes    return 0;
16647474Swes}
16747474Swes
16847474Swes#endif /* TEST */
16947474Swes
170