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