summaryrefslogtreecommitdiff
path: root/support/dktools/dk-rand.ctr
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk-rand.ctr
Initial commit
Diffstat (limited to 'support/dktools/dk-rand.ctr')
-rw-r--r--support/dktools/dk-rand.ctr999
1 files changed, 999 insertions, 0 deletions
diff --git a/support/dktools/dk-rand.ctr b/support/dktools/dk-rand.ctr
new file mode 100644
index 0000000000..b308de5f9c
--- /dev/null
+++ b/support/dktools/dk-rand.ctr
@@ -0,0 +1,999 @@
+%% options
+
+copyright owner = Dirk Krause
+copyright year = 2015-xxxx
+license = bsd
+
+
+%% module
+
+#include "dk4conf.h"
+#include "dk4types.h"
+
+#include <stdio.h>
+
+#if DK4_ON_WINDOWS
+/** Allow use of the getenv() function. */
+#define _CRT_SECURE_NO_WARNINGS 1
+#endif
+
+#if DK4_ON_WINDOWS
+#ifndef WINDOWS_H_INCLUDED
+#include <windows.h>
+#define WINDOWS_H_INCLUDED 1
+#endif
+#ifndef WINCRYPT_H_INCLUDED
+#include <wincrypt.h>
+#define WINCRYPT_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_UNISTD_H
+#ifndef UNISTD_H_INCLUDED
+#include <unistd.h>
+#define UNISTD_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_SYS_TYPES_H
+#ifndef SYS_TYPES_H_INCLUDED
+#include <sys/types.h>
+#define SYS_TYPES_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_SIGNAL_H
+#ifndef SIGNAL_H_INCLUDED
+#include <signal.h>
+#define SIGNAL_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_PROCESS_H
+#ifndef PROCESS_H_INCLUDED
+#include <process.h>
+#define PROCESS_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_IO_H
+#ifndef IO_H_INCLUDED
+#include <io.h>
+#define IO_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_FCNTL_H
+#ifndef FCNTL_H_INCLUDED
+#include <fcntl.h>
+#define FCNTL_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_OPENSSL_RAND_H
+
+#ifndef OPENSSL_RAND_H_INCLUDED
+#include <openssl/rand.h>
+#define OPENSSL_RAND_H_INCLUDED 1
+#endif
+
+#include "dk4const.h"
+#include "dk4mem.h"
+#include "dk4mema.h"
+#include "dk4memrs.h"
+#include "dk4strd.h"
+#include "dk4fput.h"
+#include "dk4vers.h"
+#include "dk4maiddsz.h"
+#include "dk4maasz.h"
+#include "dk4mpl.h"
+#include "dk4svbuf.h"
+
+
+
+$!trace-include
+
+
+
+
+/** Buffer for random data.
+*/
+static char dk_rand_buf[16384];
+
+
+
+#ifndef BUFSIZ
+#define BUFSIZ 8192
+#endif
+
+/** Use an explicitly specified buffer for stdout operations
+ so we can securely reset the memory before exiting.
+*/
+static char stdout_buffer[BUFSIZ];
+
+
+/** Buffer to read seed file.
+*/
+static char seed_file_buffer[BUFSIZ];
+
+
+
+/** Help text to show for --help option.
+*/
+static const char * const help_text[] = {
+$!text
+
+Generate binary random data
+
+dk-rand [-b bytes]
+
+-b bytes Number of bytes to generate.
+
+--help Show this short help text.
+--version Show version information.
+--license Show license information.
+
+http://dktools.sourceforge.net
+
+$!end
+};
+
+
+
+/** License information to show for --license option.
+*/
+static const char * const license_text[] = {
+$!text preprocessor
+This software uses code from the following projects, either directly or as
+a library:
+
+dktools Dirk Krause's tools and libraries.
+ See http://dktools.sourceforge.net/ for more information.
+#if DK4_HAVE_OPENSSL_RAND_H
+
+OpenSSL Cryptographic toolkit, used to build file checksums here.
+ See http://www.openssl.org/ for more information.
+
+This product includes software developed by the OpenSSL Project for use in
+the OpenSSL Toolkit (http://www.openssl.org/).
+This product includes cryptographic software written by
+Eric Young (eay@cryptsoft.com).
+This product includes software written by Tim Hudson (tjh@cryptsoft.com).
+#endif
+
+All the licenses below apply to the program.
+Licenses for used libraries are shown as found on my Scientific Linux 6.x
+computer in the /usr/share/doc directory on 2015-04-01. Check the project
+homepages of the used libraries for additional information and/or updated
+license terms.
+
+
+DK tools and libraries license
+==============================
+Copyright (c) 2015-2016, Dirk Krause
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of the Dirk Krause nor the names of contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS 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 COPYRIGHT OWNER OR 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.
+#if DK4_HAVE_OPENSSL_RAND_H
+
+
+OpenSSL license
+===============
+
+LICENSE ISSUES
+--------------
+
+The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
+the OpenSSL License and the original SSLeay license apply to the toolkit.
+See below for the actual license texts. Actually both licenses are BSD-style
+Open Source licenses. In case of any license issues related to OpenSSL
+please contact openssl-core@openssl.org.
+
+OpenSSL License
+---------------
+
+Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+3. All advertising materials mentioning features or use of this
+ software must display the following acknowledgment:
+ "This product includes software developed by the OpenSSL Project
+ for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+
+4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ endorse or promote products derived from this software without
+ prior written permission. For written permission, please contact
+ openssl-core@openssl.org.
+
+5. Products derived from this software may not be called "OpenSSL"
+ nor may "OpenSSL" appear in their names without prior written
+ permission of the OpenSSL Project.
+
+6. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes software developed by the OpenSSL Project
+ for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+
+THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``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 OpenSSL PROJECT OR
+ITS 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.
+
+This product includes cryptographic software written by Eric Young
+(eay@cryptsoft.com). This product includes software written by Tim
+Hudson (tjh@cryptsoft.com).
+
+
+Original SSLeay License
+-----------------------
+
+Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+All rights reserved.
+
+This package is an SSL implementation written
+by Eric Young (eay@cryptsoft.com).
+The implementation was written so as to conform with Netscapes SSL.
+
+This library is free for commercial and non-commercial use as long as
+the following conditions are aheared to. The following conditions
+apply to all code found in this distribution, be it the RC4, RSA,
+lhash, DES, etc., code; not just the SSL code. The SSL documentation
+included with this distribution is covered by the same copyright terms
+except that the holder is Tim Hudson (tjh@cryptsoft.com).
+
+Copyright remains Eric Young's, and as such any Copyright notices in
+the code are not to be removed.
+If this package is used in a product, Eric Young should be given attribution
+as the author of the parts of the library used.
+This can be in the form of a textual message at program startup or
+in documentation (online or textual) provided with the package.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+ "This product includes cryptographic software written by
+ Eric Young (eay@cryptsoft.com)"
+ The word 'cryptographic' can be left out if the rouines from the library
+ being used are not cryptographic related :-).
+4. If you include any Windows specific code (or a derivative thereof) from
+ the apps directory (application code) you must include an acknowledgement:
+ "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+
+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ANY EXPRESS 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 AUTHOR OR 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.
+
+The licence and distribution terms for any publically available version or
+derivative of this code cannot be changed. i.e. this code cannot simply be
+copied and put under another distribution licence
+[including the GNU Public Licence.]
+
+#endif
+
+$!end
+};
+
+
+
+/** Version information.
+*/
+static const char version_text[] = { DKT_VERSION_C8 };
+
+
+
+/** Options used by the program.
+*/
+static dk4_option_t options[] = {
+
+ /* Configuration file.
+ */
+ { { dkT('b'), dkT("bytes"), DK4_OPT_ARG_SIZE }, { NULL }, 0 },
+
+ /* 1 Help.
+ */
+ { { dkT('\0'),dkT("help"), DK4_OPT_ARG_NONE}, { NULL }, 0},
+
+ /* 2 Version.
+ */
+ { { dkT('\0'),dkT("version"), DK4_OPT_ARG_NONE}, { NULL }, 0},
+
+ /* 3 License
+ */
+ { { dkT('\0'),dkT("license"), DK4_OPT_ARG_NONE}, { NULL }, 0}
+
+};
+
+
+/** Constant texts used by the program, not localized.
+*/
+static const char * dk_rand_kw[] = {
+$!string-table
+#
+# Program name
+#
+dk-rand:
+#
+# 1 ERROR: Failed to write to standard output!
+#
+ERROR: Failed to write to standard output!\n
+#
+# 2 ERROR: Failed to obtain random data!
+#
+ERROR: Failed to obtain random data!\n
+#
+# 3 ERROR: Aborted by signal!
+#
+ERROR: Aborted by signal!\n
+#
+# 4 ERROR: Failed to reset used buffers!
+#
+ERROR: Failed to reset used buffers!\n
+#
+# 5 ERROR: Failed to seed OpenSSL PRNG!
+#
+ERROR: Failed to seed OpenSSL PRNG!\n
+#
+# 6 ERROR: Failed to set up signal handlers!
+#
+ERROR: Failed to set up signal handlers!\n
+#
+# 7 ERROR: Failed to restore signal handlers!
+#
+ERROR: Failed to restore signal handlers!\n
+#
+# 8 ERROR: Numeric overflow in size calculation!
+#
+ERROR: Numeric overflow in size calculation!\n
+$!end
+};
+
+
+
+/** Number of options in the options array.
+*/
+static const size_t szoptions = sizeof(options)/sizeof(dk4_option_t);
+
+
+
+/** Exit status code.
+*/
+static int exval = EXIT_FAILURE;
+
+
+
+/** Options: Help (1), version (2), license (4).
+*/
+static int hvl = 0;
+
+
+
+#ifdef SIGPIPE
+/** Indicator: SIGPIPE signal received.
+*/
+static
+DK4_VOLATILE
+dk4_sig_atomic_t sig_had_pipe = 0;
+#endif
+
+
+/** Indicator: SIGINT signal received.
+*/
+static
+DK4_VOLATILE
+dk4_sig_atomic_t sig_had_int = 0;
+
+
+/** Indicator: SIGTERM signal received.
+*/
+static
+DK4_VOLATILE
+dk4_sig_atomic_t sig_had_term = 0;
+
+
+/** Pass volatile pointer through to caller.
+ The CERT C coding standard recommends to set signal indicator
+ variables through pointers to avoid
+ compilers from optimizing too hard (they might attempt
+ to keep the value in a register although properly marked
+ as volatile).
+ @param ptr Address of volatile indicator variable.
+ @return Same pointer as ptr.
+*/
+static
+DK4_VOLATILE
+dk4_sig_atomic_t *
+sig_pass_pointer(DK4_VOLATILE dk4_sig_atomic_t *ptr)
+{
+ return ptr;
+}
+
+
+#ifdef SIGPIPE
+/** Handler for SIGPIPE signal.
+ @param signo Signal number (always SIGPIPE, ignored).
+*/
+static
+void
+sig_handler_pipe(int signo)
+{
+ *sig_pass_pointer(&sig_had_pipe) = 1;
+}
+#endif
+
+
+/** Handler for SIGINT signal.
+ @param signo Signal number (always SIGINT, ignored).
+*/
+static
+void
+sig_handler_int(int signo)
+{
+ *sig_pass_pointer(&sig_had_int) = 1;
+}
+
+
+/** Handler for SIGTERM signal.
+ @param signo Signal number (always SIGTERM, ignored).
+*/
+static
+void
+sig_handler_term(int signo)
+{
+ *sig_pass_pointer(&sig_had_term) = 1;
+}
+
+
+/** Read value from volatile atomic type.
+ This function is necessary as some compilers mis-optimize
+ direct access to volatile variables (at least if you believe
+ one of the coding standards).
+ @param ap Pointer to volatile atomic variable.
+ @return Contents of the variable.
+*/
+static
+dk4_sig_atomic_t
+sig_read_atomic(DK4_VOLATILE dk4_sig_atomic_t *ap)
+{
+ return (*ap);
+}
+
+
+/** Check whether we can continue or must abort due to signal.
+ @param dopipe Flag: Check for SIGPIPE too.
+ @return 1 if we can continue, 0 otherwise.
+*/
+static
+int
+can_continue(int dopipe)
+{
+ int back = 1;
+ if (0 != sig_read_atomic(&sig_had_term)) { back = 0; }
+ if (0 != sig_read_atomic(&sig_had_int)) { back = 0; }
+#ifdef SIGPIPE
+ if (0 != dopipe) {
+ if (0 != sig_read_atomic(&sig_had_pipe)) { back = 0; }
+ }
+#endif
+ return back;
+}
+
+
+
+/** Write a log message to stderr.
+ @param i Message index in dk_rand_kw.
+*/
+static
+void
+log_1(size_t i)
+{
+ fputs(dk_rand_kw[0], stderr);
+ fputs(dk_rand_kw[i], stderr);
+ fflush(stderr);
+}
+
+
+
+/** Seed pseudo random number generator.
+ @return 1 on success, 0 on error.
+*/
+static
+int
+seed_prng(void)
+{
+ char buffer[64];
+ char *envptr;
+#if DK4_ON_WINDOWS
+ HCRYPTPROV hcp;
+ BOOL res;
+#else
+ FILE *fipo;
+ size_t rdb;
+#endif
+ int cc;
+ int rounds = 0;
+ int back = 0;
+ int svbres = 0;
+ $? "+ dk_pwgen_seed_prng"
+
+ /* Let OpenSSL library functions try to initialize.
+ */
+ if (1 == RAND_status()) {
+ back = 1;
+ goto finished;
+ }
+
+ /* Attempt EGD socket if specified in environment.
+ */
+#if DK4_HAVE_RAND_EGD && DK4_HAVE_STRUCT_SOCKADDR_UN
+ envptr = getenv("EGDSOCKET");
+ if (NULL != envptr) {
+ if (0 < RAND_egd(envptr)) {
+ if (1 == RAND_status()) {
+ back = 1;
+ goto finished;
+ }
+ }
+ }
+#endif
+
+ /* Use platform specific mechanisms if available.
+ */
+#if DK4_ON_WINDOWS
+ res = CryptAcquireContext(
+ &hcp, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT
+ );
+ if (res) {
+ cc = 1;
+ do {
+ if (0 != can_continue(0)) {
+ res = CryptGenRandom(hcp, (DWORD)sizeof(buffer), buffer);
+ if (res) {
+ RAND_seed(buffer, sizeof(buffer));
+ if (1 == RAND_status()) {
+ cc = 0;
+ back = 1;
+ } else {
+ rounds++;
+ }
+ } else {
+ cc = -1;
+ /* ERROR: Failed to obtain random bytes from crypto context */
+ }
+ } else {
+ cc = -1;
+ }
+ } while ((1 == cc) && (128 > rounds));
+ CryptReleaseContext(hcp, (DWORD)0UL);
+ (void)dk4mem_reset_secure(buffer, sizeof(buffer), NULL);
+ if (0 == back) {
+ if (0 != can_continue(0)) {
+ RAND_screen();
+ if (1 == RAND_status()) {
+ back = 1;
+ }
+ }
+ }
+ } else {
+ /* ERROR: Failed to acquire crypto context */
+ }
+#else
+ fipo = fopen("/dev/random", "rb");
+ if (NULL == fipo) {
+ fipo = fopen("/dev/urandom", "rb");
+ }
+ if (NULL != fipo) {
+ dk4mem_reset(seed_file_buffer, sizeof(seed_file_buffer), NULL);
+ svbres = dk4setvbuf(
+ fipo, DK4_FILE_FULL_BUFFERING,
+ seed_file_buffer, sizeof(seed_file_buffer), NULL
+ );
+ if (0 != svbres) {
+ cc = 1;
+ do {
+ if (0 != can_continue(0)) {
+ rdb = fread(buffer, 1, sizeof(buffer), fipo);
+ if (0 < rdb) {
+ RAND_seed(buffer, rdb);
+ if (1 == RAND_status()) {
+ cc = 0;
+ back = 1;
+ } else {
+ rounds++;
+ }
+ } else {
+ cc = -1;
+ }
+ } else {
+ cc = -1;
+ }
+ } while ((1 == cc) && (128 > rounds));
+ } else {
+ /* ERROR: Failed to set file buffer */
+ }
+ fclose(fipo);
+ (void)dk4mem_reset_secure(seed_file_buffer, sizeof(seed_file_buffer), NULL);
+ (void)dk4mem_reset_secure(buffer, sizeof(buffer), NULL);
+ } else {
+ /* ERROR: Failed to open both /dev/random and /dev/urandom */
+ }
+#endif
+
+ finished:
+ $? "- dk_pwgen_seed_prng %d", back
+ return back;
+}
+
+
+
+/** Create random data, write to standard output.
+*/
+static
+void
+create_random_data(int pbso)
+{
+ size_t sz = 512; /* Amount of data to produce */
+ size_t by; /* Bytes to process */
+ size_t wrb; /* Bytes written */
+#if DK4_ON_WINDOWS
+ int oldmode = _O_TEXT; /* Previous stdout mode */
+#endif
+ int cc = 1; /* Flag: Can continue */
+
+#if DK4_ON_WINDOWS
+ oldmode = _setmode(_fileno(stdout), _O_BINARY);
+#endif
+ if (0 != seed_prng()) {
+ if (0 != options[0].found) {
+ if (0 < options[0].val.s) {
+ sz = options[0].val.s;
+ }
+ }
+ if (0 == sz) { sz = 512; }
+ exval = EXIT_SUCCESS;
+ do {
+ if (0 != can_continue(1)) {
+ by = sizeof(dk_rand_buf);
+ if (by > sz) { by = sz; }
+ if (0 == sz) {
+ cc = 0;
+ } else {
+ if ((dk4_um_t)(INT_MAX) >= (dk4_um_t)by) {
+ if (0 < RAND_bytes((unsigned char *)dk_rand_buf, (int)by)) {
+ if (0 != can_continue(1)) {
+ wrb = fwrite(dk_rand_buf, 1, by, stdout);
+ if (wrb == by) {
+ if (by >= sz) {
+ sz = 0;
+ cc = 0;
+ } else {
+ sz -= by;
+ }
+ } else {
+ /* ERROR: Failed to write bytes to standard output */
+ log_1(1);
+ exval = EXIT_FAILURE;
+ cc = 0;
+ }
+ } else {
+ cc = -1;
+ }
+ } else {
+ /* ERROR: Failed to obtain random data */
+ log_1(2);
+ exval = EXIT_FAILURE;
+ cc = 0;
+ }
+ } else {
+ /* ERROR: Numeric overflow */
+ cc = 0;
+ exval = EXIT_FAILURE;
+ log_1(8);
+ }
+ }
+ } else {
+ cc = -1;
+ }
+ } while (1 == cc);
+ if (-1 == cc) {
+ /* ERROR: Aborted by signal */
+ log_1(3);
+ exval = EXIT_FAILURE;
+ }
+
+ /* Securely reset buffers.
+ */
+ RAND_cleanup();
+ fflush(stdout);
+ if (0 == pbso) {
+ /* ERROR: Failed to reset buffer */
+ log_1(4);
+ exval = EXIT_FAILURE;
+ } else {
+ if (0 == dk4mem_reset_secure(stdout_buffer,sizeof(stdout_buffer),NULL)) {
+ /* ERROR: Failed to reset buffer */
+ log_1(4);
+ exval = EXIT_FAILURE;
+ }
+ }
+ if (0 == dk4mem_reset_secure(dk_rand_buf, sizeof(dk_rand_buf), NULL)) {
+ /* ERROR: Failed to reset buffer */
+ log_1(4);
+ exval = EXIT_FAILURE;
+ }
+ } else {
+ /* ERROR: Failed to seed PRNG */
+ log_1(5);
+ }
+#if DK4_ON_WINDOWS
+ _setmode(_fileno(stdout), oldmode);
+#endif
+}
+
+
+
+/** Show a text paragraph on standard output.
+ @param txt Text to show.
+*/
+static
+void
+show_text(const char * const *txt)
+{
+ if (NULL != txt) {
+ while (NULL != *txt) {
+ fputs(*(txt++), stdout);
+ fputc('\n', stdout);
+ }
+ fflush(stdout);
+ }
+}
+
+
+
+/** Handle --help, --version, --license options.
+*/
+static
+void
+run_hvl(void)
+{
+ if (0 != (1 & hvl)) {
+ show_text(help_text);
+ }
+ if (0 != (2 & hvl)) {
+ fputs(version_text, stdout);
+ fputc('\n', stdout);
+ fflush(stdout);
+ }
+ if (0 != (4 & hvl)) {
+ show_text(license_text);
+ }
+ exval = EXIT_SUCCESS;
+}
+
+
+
+#endif
+
+
+
+/** Main function.
+ @param argc Number of command line arguments.
+ @param argv Command line arguments array.
+ @return 0 on success, all other values indicate errors.
+*/
+#if DK4_CHAR_SIZE > 1
+int wmain(int argc, wchar_t *argv[])
+#else
+int main(int argc, char *argv[])
+#endif
+{
+#if DK4_HAVE_OPENSSL_RAND_H
+
+#if DK4_HAVE_SIGACTION
+#ifdef SIGPIPE
+ struct sigaction opipe; /* Old disposition for SIGPIPE */
+ struct sigaction npipe; /* New disposition for SIGPIPE */
+#endif
+ struct sigaction oint; /* Old disposition for SIGINT */
+ struct sigaction nint; /* New disposition for SIGINT */
+ struct sigaction oterm; /* Old disposition for SIGTERM */
+ struct sigaction nterm; /* New disposition for SIGTERM */
+#else
+#ifdef SIGPIPE
+ dk4_sig_handler_t *opipe = NULL; /* Old disposition for SIGPIPE */
+#endif
+ dk4_sig_handler_t *oterm = NULL; /* Old disposition for SIGTERM */
+ dk4_sig_handler_t *oint = NULL; /* Old disposition for SIGINT */
+#endif
+#if DK4_HAVE_SIGACTION
+#ifdef SIGPIPE
+ int set_pipe = 0; /* Flag: Disposition SIGPIPE changed */
+#endif
+ int set_int = 0; /* Flag: Disposition SIGINT changed */
+ int set_term = 0; /* Flag: Disposition SIGTERM changed */
+ int sig_i_f = 0; /* Flag: Handler installation failed */
+ int sig_r_f = 0; /* Flag: Handler restoration failed */
+#endif
+ int pbso = 0; /* Flag: Private buffer for stdout */
+ int res;
+
+ /* Use private buffer for standard output.
+ */
+ pbso = dk4setvbuf(
+ stdout, DK4_FILE_LINE_BUFFERING, stdout_buffer, sizeof(stdout_buffer), NULL
+ );
+
+ /* Process command line arguments.
+ */
+ res = dk4opt_process_argv(
+ options, szoptions, argc, argv, NULL, NULL, 1, 1, NULL
+ );
+ if (0 == res) {
+ goto finished;
+ }
+
+ /* Set up signal handlers.
+ */
+#if DK4_HAVE_SIGACTION
+#ifdef SIGPIPE
+ DK4_MEMRES(&npipe, sizeof(npipe));
+ npipe.sa_handler = sig_handler_pipe;
+ npipe.sa_flags = 0;
+ if (0 != sigemptyset(&npipe.sa_mask)) { sig_i_f = 1; goto finished; }
+ if (0 != sigaddset(&npipe.sa_mask, SIGPIPE)) { sig_i_f = 1; goto finished; }
+ if (0 != sigaction(SIGPIPE, &npipe, &opipe)) { sig_i_f = 1; goto finished; }
+ set_pipe = 1;
+#endif
+ DK4_MEMRES(&nterm, sizeof(nterm));
+ nterm.sa_handler = sig_handler_term;
+ nterm.sa_flags = 0;
+ if (0 != sigemptyset(&nterm.sa_mask)) { sig_i_f = 1; goto finished; }
+ if (0 != sigaddset(&nterm.sa_mask, SIGTERM)) { sig_i_f = 1; goto finished; }
+ if (0 != sigaction(SIGTERM, &nterm, &oterm)) { sig_i_f = 1; goto finished; }
+ set_term = 1;
+ DK4_MEMRES(&nint, sizeof(nint));
+ nint.sa_handler = sig_handler_int;
+ nint.sa_flags = 0;
+ if (0 != sigemptyset(&nint.sa_mask)) { sig_i_f = 1; goto finished; }
+ if (0 != sigaddset(&nint.sa_mask, SIGINT)) { sig_i_f = 1; goto finished; }
+ if (0 != sigaction(SIGINT, &nint, &oint)) { sig_i_f = 1; goto finished; }
+ set_int = 1;
+#else
+#if DK4_HAVE_SIGSET
+#ifdef SIGPIPE
+ opipe = sigset(SIGPIPE, sig_handler_pipe);
+#endif
+ oint = sigset(SIGINT, sig_handler_int);
+ oterm = sigset(SIGTERM, sig_handler_term);
+#else
+#ifdef SIGPIPE
+ opipe = signal(SIGPIPE, sig_handler_pipe);
+#endif
+ oint = signal(SIGINT, sig_handler_int);
+ oterm = signal(SIGTERM, sig_handler_term);
+#endif
+#endif
+
+ /* Check help, version, license.
+ */
+ if (0 != options[1].found) { hvl |= 1; }
+ if (0 != options[2].found) { hvl |= 2; }
+ if (0 != options[3].found) { hvl |= 4; }
+ if (0 != hvl) {
+ run_hvl();
+ goto finished;
+ }
+
+ /* Create random data.
+ */
+ create_random_data(pbso);
+
+ /* Clean up at end of program.
+ */
+ finished:
+
+ /* Restore signal handlers
+ */
+#if DK4_HAVE_SIGACTION
+ if (0 != sig_i_f) {
+ /* ERROR: Failed to set up signal handlers */
+ log_1(6);
+ }
+ if (0 != set_int) {
+ if (0 != sigaction(SIGINT, &oint, NULL)) { sig_r_f = 1; }
+ }
+ if (0 != set_term) {
+ if (0 != sigaction(SIGTERM, &oterm, NULL)) { sig_r_f = 1; }
+ }
+#ifdef SIGPIPE
+ if (0 != set_pipe) {
+ if (0 != sigaction(SIGPIPE, &opipe, NULL)) { sig_r_f = 1; }
+ }
+#endif
+ if (0 != sig_r_f) {
+ /* ERROR: Failed to restore signal handlers */
+ log_1(7);
+ }
+#else
+#if DK4_HAVE_SIGSET
+ if (NULL != oterm) { sigset(SIGTERM, oterm); }
+ if (NULL != oint ) { sigset(SIGINT, oint ); }
+#ifdef SIGPIPE
+ if (NULL != opipe) { sigset(SIGPIPE, opipe); }
+#endif
+#else
+ if (NULL != oterm) { signal(SIGTERM, oterm); }
+ if (NULL != oint ) { signal(SIGINT, oint ); }
+#ifdef SIGPIPE
+ if (NULL != opipe) { signal(SIGPIPE, opipe); }
+#endif
+#endif
+#endif
+
+#else
+ fputs(
+ "dk-rand: ERROR: OpenSSL support was not available during build!\n",
+ stderr
+ );
+ fflush(stderr);
+#endif
+ exit(exval); return exval;
+}
+
+