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