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