1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/as_rand.cpp Fri Nov 28 11:21:08 2008 +0100 1.3 @@ -0,0 +1,137 @@ 1.4 +// 1.5 +// OSSP asgui - Accounting system graphical user interface 1.6 +// Copyright (c) 2002-2004 The OSSP Project (http://www.ossp.org/) 1.7 +// Copyright (c) 2002-2004 Ralf S. Engelschall <rse@engelschall.com> 1.8 +// Copyright (c) 2002-2004 Michael Schloh von Bennewitz <michael@schloh.com> 1.9 +// Copyright (c) 2002-2004 Cable & Wireless Telecommunications Services GmbH 1.10 +// 1.11 +// This file is part of OSSP asgui, an accounting system graphical user 1.12 +// interface which can be found at http://www.ossp.org/pkg/tool/asgui/. 1.13 +// 1.14 +// Permission to use, copy, modify, and distribute this software for 1.15 +// any purpose with or without fee is hereby granted, provided that 1.16 +// the above copyright notice and this permission notice appear in all 1.17 +// copies. 1.18 +// 1.19 +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 1.20 +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1.21 +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1.22 +// IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR 1.23 +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.24 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.25 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 1.26 +// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 1.27 +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 1.28 +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 1.29 +// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1.30 +// SUCH DAMAGE. 1.31 +// 1.32 +// as_rand.cpp: ISO C++ implementation 1.33 +// 1.34 + 1.35 +#include <fcntl.h> 1.36 +#include <cerrno> 1.37 + 1.38 +#include "as_rand.h" 1.39 + 1.40 +#if HAVE_UNISTD_H 1.41 +#include <unistd.h> 1.42 +#endif // HAVE_UNISTD_H 1.43 +#if HAVE_STDLIB_H 1.44 +#include <stdlib.h> 1.45 +#endif // HAVE_STDLIB_H 1.46 + 1.47 +#if TIME_WITH_SYS_TIME 1.48 +#include <sys/time.h> 1.49 +#include <time.h> 1.50 +#else 1.51 +#if HAVE_SYS_TIME_H 1.52 +#include <sys/time.h> 1.53 +#else 1.54 +#include <time.h> 1.55 +#endif // HAVE_SYS_TIME_H 1.56 +#endif // TIME_WITH_SYS_TIME 1.57 + 1.58 + 1.59 +namespace AS { 1.60 + 1.61 +// Constructor 1.62 +Rand::Rand(void) 1.63 +{ 1.64 + this->nFd = -4; // Object fresh status 1.65 + this->openDevice(); // Open the random device 1.66 +// if (this->nFd < 0) 1.67 +// throw Genexcept("Could not open /dev/urandom or /dev/random."); 1.68 +} 1.69 + 1.70 +// Destructor 1.71 +Rand::~Rand(void) 1.72 +{ 1.73 + this->closeDevice(); // Close the random device 1.74 + this->nFd = -4; // Return this object to its fresh status 1.75 +} 1.76 + 1.77 +// 1.78 +// Rand::openDevice(void) 1.79 +// Open the random device associated with this object 1.80 +// 1.81 +void Rand::openDevice(void) 1.82 +{ 1.83 + struct timeval Time; 1.84 + 1.85 + if (this->nFd == -4) { // -4 indicates a fresh object 1.86 + gettimeofday(&Time, 0); 1.87 + this->nFd = open("/dev/urandom", O_RDONLY); 1.88 + if (this->nFd == -1) 1.89 + this->nFd = open("/dev/random", O_RDONLY | O_NONBLOCK); 1.90 + srand((getpid() << 16) ^ getuid() ^ Time.tv_sec ^ Time.tv_usec); // Seed 1.91 + } 1.92 + 1.93 + // Improve randomness by stirring in entropy 1.94 + gettimeofday(&Time, 0); 1.95 + for (int nIter = (Time.tv_sec ^ Time.tv_usec) & 0x1F; nIter > 0; nIter--) 1.96 + rand(); 1.97 +} 1.98 + 1.99 +// 1.100 +// Rand::closeDevice(void) 1.101 +// Close the random device associated with this object 1.102 +// 1.103 +void Rand::closeDevice(void) 1.104 +{ 1.105 + if (this->nFd >= 0) 1.106 + close(this->nFd); 1.107 +} 1.108 + 1.109 +// 1.110 +// Rand::genData(void *pvBuf, int nBytes) 1.111 +// Generate a series of random data from the system 1.112 +// standard random devices /dev/[u|s]random 1.113 +// 1.114 +void Rand::genData(void *pBuf, int nBytes) 1.115 +{ 1.116 + int nRead = 0; 1.117 + int nLost = 0; 1.118 + char *szOut = (char *)pBuf; 1.119 + 1.120 + if (this->nFd >= 0) { 1.121 + while (nBytes > 0) { 1.122 + nRead = read(this->nFd, szOut, nBytes); 1.123 + if ((nRead < 0) && ((errno == EINTR) || (errno == EAGAIN))) 1.124 + continue; 1.125 + if (nRead <= 0) { 1.126 + if (nLost++ == 8) 1.127 + break; 1.128 + continue; 1.129 + } 1.130 + nBytes -= nRead; 1.131 + szOut += nRead; 1.132 + nLost = 0; 1.133 + } 1.134 + } 1.135 + 1.136 + // For systems with no /dev/random, we do the next best thing 1.137 + for (int nIter = 0; nIter< nBytes; nIter++) 1.138 + *szOut++ = rand() & 0xFF; 1.139 +} 1.140 +} // namespace AS