// // 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