1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
/*
* Copyright(c) 2012 Tim Ruehsen
* Copyright(c) 2016-2018 Free Software Foundation, Inc.
*
* This file is part of libwget.
*
* Libwget is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Libwget is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libwget. If not, see <https://www.gnu.org/licenses/>.
*
*
* a multi-thread safe wrapper around gnulib random_r()
*
* Changelog
* 22.01.2016 Tim Ruehsen created
*
*/
#include <config.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#ifdef _WIN32
# include <process.h> /* getpid() */
#endif
#include <wget.h>
#include "private.h"
/**
* \file
* \brief Random functions
* \defgroup libwget-random Random functions
* @{
*
* This is wrapper code around gnulib's srandom_r() and random_r() with automatic seeding
*/
static int seeded;
static char statebuf[64];
static struct random_data state;
static wget_thread_mutex_t mutex;
static bool initialized;
static void __attribute__ ((constructor)) _wget_random_init(void)
{
if (!initialized) {
wget_thread_mutex_init(&mutex);
initialized = 1;
}
}
static void __attribute__ ((destructor)) _wget_random_exit(void)
{
if (initialized) {
wget_thread_mutex_destroy(&mutex);
initialized = 0;
}
}
/**
* Random API initialization, allocating/preparing the internal resources.
*
* On systems with automatic library constructors, this function
* doesn't have to be called explictly.
*
* This function is not thread-safe.
*/
void wget_random_init(void)
{
_wget_random_init();
}
/**
* Random API deinitialization, free'ing all internal resources.
*
* On systems with automatic library destructors, this function
* doesn't have to be called explictly.
*
* This function is not thread-safe.
*/
void wget_random_exit(void)
{
_wget_random_exit();
}
/**
* \return Random value between 0 and RAND_MAX
*
* This functions wraps around gnulib's random_r(). It performs a thread-safe seeding on the first use,
* if not done before by wget_srandom();
*/
int wget_random(void)
{
int32_t r;
wget_thread_mutex_lock(mutex);
if (!seeded) {
// seed random generator, used e.g. by Digest Authentication and --random-wait
initstate_r((unsigned)(time(NULL) ^ getpid()), statebuf, sizeof(statebuf), &state);
seeded = 1;
}
if (random_r(&state, &r))
r = 0; // return 0 on failure
wget_thread_mutex_unlock(mutex);
return (int)r;
}
/**
* \param[in] seed Value to seed the random generator
*
* This functions wraps around srandom_r() to make a thread-safe seeding for wget_random().
*/
void wget_srandom(unsigned int seed)
{
wget_thread_mutex_lock(mutex);
initstate_r(seed, statebuf, sizeof(statebuf), &state);
seeded = 1;
wget_thread_mutex_unlock(mutex);
}
/**@}*/
|