diff options
author | orlikowski <orlikowski@13f79535-47bb-0310-9956-ffa450edef68> | 2002-07-10 05:54:12 +0000 |
---|---|---|
committer | orlikowski <orlikowski@13f79535-47bb-0310-9956-ffa450edef68> | 2002-07-10 05:54:12 +0000 |
commit | a56172a7141e17dc0e99d61fb7313c81ccbe955e (patch) | |
tree | 40342595c6b0eb8d6a96ff99cb3ad1de6a299ad5 /misc | |
parent | c1d29ba186a3631a6ea144e5553a4b64ab9ed203 (diff) | |
download | libapr-a56172a7141e17dc0e99d61fb7313c81ccbe955e.tar.gz |
Inspired by the OpenSSL guys, this allows the --with-egd parameter to
use defaults, if a socket is not specified.
Reviewed by: Jeff Trawick
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@63594 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'misc')
-rw-r--r-- | misc/unix/rand.c | 121 |
1 files changed, 66 insertions, 55 deletions
diff --git a/misc/unix/rand.c b/misc/unix/rand.c index 3cb9e7d20..94970dccb 100644 --- a/misc/unix/rand.c +++ b/misc/unix/rand.c @@ -86,7 +86,7 @@ APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf, #ifdef DEV_RANDOM int rnd; - size_t got, tot; + apr_size_t got, tot; if ((rnd = open(STR(DEV_RANDOM), O_RDONLY)) == -1) return errno; @@ -119,76 +119,87 @@ APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf, * 0x04 (report PID) * 0xMM (length of PID string, not null-terminated) MM chars */ - int egd_socket, egd_path_len, rv; + static const char *egd_sockets[] = { EGD_DEFAULT_SOCKET, NULL }; + const char **egdsockname = NULL; + + int egd_socket, egd_path_len, rv, bad_errno; struct sockaddr_un addr; apr_socklen_t egd_addr_len; - size_t resp_expected; + apr_size_t resp_expected; unsigned char req[2], resp[255]; unsigned char *curbuf = buf; - egd_path_len = strlen(STR(EGD_DEFAULT_SOCKET)); - - if (egd_path_len > sizeof(addr.sun_path)) { - return APR_EINVAL; - } - - memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - memcpy(addr.sun_path, STR(EGD_DEFAULT_SOCKET), egd_path_len); - egd_addr_len = APR_OFFSETOF(struct sockaddr_un, sun_path) + - egd_path_len; - - egd_socket = socket(PF_UNIX, SOCK_STREAM, 0); - - if (egd_socket == -1) { - return errno; - } - - rv = connect(egd_socket, (struct sockaddr*)&addr, egd_addr_len); - - if (rv == -1) { - return errno; - } + for (egdsockname = egd_sockets; *egdsockname && length > 0; egdsockname++) { + egd_path_len = strlen(*egdsockname); + + if (egd_path_len > sizeof(addr.sun_path)) { + return APR_EINVAL; + } - /* EGD can only return 255 bytes of data at a time. Silly. */ - while (length > 0) { - ssize_t srv; - req[0] = 2; /* We'll block for now. */ - req[1] = length > 255 ? 255: length; + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, *egdsockname, egd_path_len); + egd_addr_len = APR_OFFSETOF(struct sockaddr_un, sun_path) + + egd_path_len; - srv = write(egd_socket, req, 2); - if (srv == -1) { - int bad_errno = errno; + egd_socket = socket(PF_UNIX, SOCK_STREAM, 0); - shutdown(egd_socket, SHUT_RDWR); - close(egd_socket); - return bad_errno; + if (egd_socket == -1) { + return errno; } - if (srv != 2) { - shutdown(egd_socket, SHUT_RDWR); - close(egd_socket); - return APR_EGENERAL; /* Try again. */ - } + rv = connect(egd_socket, (struct sockaddr*)&addr, egd_addr_len); - resp_expected = req[1]; - srv = read(egd_socket, resp, resp_expected); - if (srv == -1) { - int bad_errno = errno; + if (rv == -1) { + bad_errno = errno; + continue; + } - shutdown(egd_socket, SHUT_RDWR); - close(egd_socket); - return bad_errno; + /* EGD can only return 255 bytes of data at a time. Silly. */ + while (length > 0) { + apr_ssize_t srv; + req[0] = 2; /* We'll block for now. */ + req[1] = length > 255 ? 255: length; + + srv = write(egd_socket, req, 2); + if (srv == -1) { + bad_errno = errno; + shutdown(egd_socket, SHUT_RDWR); + close(egd_socket); + break; + } + + if (srv != 2) { + shutdown(egd_socket, SHUT_RDWR); + close(egd_socket); + return APR_EGENERAL; + } + + resp_expected = req[1]; + srv = read(egd_socket, resp, resp_expected); + if (srv == -1) { + bad_errno = errno; + shutdown(egd_socket, SHUT_RDWR); + close(egd_socket); + return bad_errno; + } + + memcpy(curbuf, resp, srv); + curbuf += srv; + length -= srv; } + + shutdown(egd_socket, SHUT_RDWR); + close(egd_socket); + } - memcpy(curbuf, resp, srv); - curbuf += srv; - length -= srv; + if (length > 0) { + /* We must have iterated through the list of sockets, + * and no go. Return the errno. + */ + return bad_errno; } - shutdown(egd_socket, SHUT_RDWR); - close(egd_socket); - #elif defined(HAVE_TRUERAND) /* use truerand */ extern int randbyte(void); /* from the truerand library */ |