diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk-rand.ctr |
Initial commit
Diffstat (limited to 'support/dktools/dk-rand.ctr')
-rw-r--r-- | support/dktools/dk-rand.ctr | 999 |
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; +} + + |