diff -r 27e940e8e5f3 -r d64aaa7d146f as_rand.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/as_rand.cpp Fri Nov 28 11:21:08 2008 +0100 @@ -0,0 +1,137 @@ +// +// OSSP asgui - Accounting system graphical user interface +// Copyright (c) 2002-2004 The OSSP Project (http://www.ossp.org/) +// Copyright (c) 2002-2004 Ralf S. Engelschall +// Copyright (c) 2002-2004 Michael Schloh von Bennewitz +// Copyright (c) 2002-2004 Cable & Wireless Telecommunications Services GmbH +// +// This file is part of OSSP asgui, an accounting system graphical user +// interface which can be found at http://www.ossp.org/pkg/tool/asgui/. +// +// Permission to use, copy, modify, and distribute this software for +// any purpose with or without fee is hereby granted, provided that +// the above copyright notice and this permission notice appear in all +// copies. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// SUCH DAMAGE. +// +// as_rand.cpp: ISO C++ implementation +// + +#include +#include + +#include "as_rand.h" + +#if HAVE_UNISTD_H +#include +#endif // HAVE_UNISTD_H +#if HAVE_STDLIB_H +#include +#endif // HAVE_STDLIB_H + +#if TIME_WITH_SYS_TIME +#include +#include +#else +#if HAVE_SYS_TIME_H +#include +#else +#include +#endif // HAVE_SYS_TIME_H +#endif // TIME_WITH_SYS_TIME + + +namespace AS { + +// Constructor +Rand::Rand(void) +{ + this->nFd = -4; // Object fresh status + this->openDevice(); // Open the random device +// if (this->nFd < 0) +// throw Genexcept("Could not open /dev/urandom or /dev/random."); +} + +// Destructor +Rand::~Rand(void) +{ + this->closeDevice(); // Close the random device + this->nFd = -4; // Return this object to its fresh status +} + +// +// Rand::openDevice(void) +// Open the random device associated with this object +// +void Rand::openDevice(void) +{ + struct timeval Time; + + if (this->nFd == -4) { // -4 indicates a fresh object + gettimeofday(&Time, 0); + this->nFd = open("/dev/urandom", O_RDONLY); + if (this->nFd == -1) + this->nFd = open("/dev/random", O_RDONLY | O_NONBLOCK); + srand((getpid() << 16) ^ getuid() ^ Time.tv_sec ^ Time.tv_usec); // Seed + } + + // Improve randomness by stirring in entropy + gettimeofday(&Time, 0); + for (int nIter = (Time.tv_sec ^ Time.tv_usec) & 0x1F; nIter > 0; nIter--) + rand(); +} + +// +// Rand::closeDevice(void) +// Close the random device associated with this object +// +void Rand::closeDevice(void) +{ + if (this->nFd >= 0) + close(this->nFd); +} + +// +// Rand::genData(void *pvBuf, int nBytes) +// Generate a series of random data from the system +// standard random devices /dev/[u|s]random +// +void Rand::genData(void *pBuf, int nBytes) +{ + int nRead = 0; + int nLost = 0; + char *szOut = (char *)pBuf; + + if (this->nFd >= 0) { + while (nBytes > 0) { + nRead = read(this->nFd, szOut, nBytes); + if ((nRead < 0) && ((errno == EINTR) || (errno == EAGAIN))) + continue; + if (nRead <= 0) { + if (nLost++ == 8) + break; + continue; + } + nBytes -= nRead; + szOut += nRead; + nLost = 0; + } + } + + // For systems with no /dev/random, we do the next best thing + for (int nIter = 0; nIter< nBytes; nIter++) + *szOut++ = rand() & 0xFF; +} +} // namespace AS