/* WARNING: This file was generated by dkct. Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk-rand.ctr */ /* Copyright (C) 2015-2017, Dirk Krause 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 opyright 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 author 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. */ /** @file dk-rand.c The dk-rand module. */ #line 9 "dk-rand.ctr" #include "dk4conf.h" #include "dk4types.h" #include #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 #define WINDOWS_H_INCLUDED 1 #endif #ifndef WINCRYPT_H_INCLUDED #include #define WINCRYPT_H_INCLUDED 1 #endif #endif #if DK4_HAVE_UNISTD_H #ifndef UNISTD_H_INCLUDED #include #define UNISTD_H_INCLUDED 1 #endif #endif #if DK4_HAVE_SYS_TYPES_H #ifndef SYS_TYPES_H_INCLUDED #include #define SYS_TYPES_H_INCLUDED 1 #endif #endif #if DK4_HAVE_SIGNAL_H #ifndef SIGNAL_H_INCLUDED #include #define SIGNAL_H_INCLUDED 1 #endif #endif #if DK4_HAVE_PROCESS_H #ifndef PROCESS_H_INCLUDED #include #define PROCESS_H_INCLUDED 1 #endif #endif #if DK4_HAVE_IO_H #ifndef IO_H_INCLUDED #include #define IO_H_INCLUDED 1 #endif #endif #if DK4_HAVE_FCNTL_H #ifndef FCNTL_H_INCLUDED #include #define FCNTL_H_INCLUDED 1 #endif #endif #if DK4_HAVE_OPENSSL_RAND_H #ifndef OPENSSL_RAND_H_INCLUDED #include #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" #line 95 "dk-rand.ctr" /** 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[] = { "", "Generate binary random data", "", "dk-rand [-b bytes]", "", "-b bytes\tNumber of bytes to generate.", "", "--help\t\tShow this short help text.", "--version\tShow version information.", "--license\tShow license information.", "", "http://dktools.sourceforge.net", "", NULL #line 139 "dk-rand.ctr" }; /** License information to show for --license option. */ static const char * const license_text[] = { "This software uses code from the following projects, either directly or as", "a library:", "", "dktools\t\tDirk Krause's tools and libraries.", "\t\tSee http://dktools.sourceforge.net/ for more information.", #if DK4_HAVE_OPENSSL_RAND_H "", "OpenSSL\t\tCryptographic toolkit, used to build file checksums here.", "\t\tSee 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 "", NULL #line 331 "dk-rand.ctr" }; /** 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[] = { /* 0 */ "dk-rand: ", /* 1 */ "ERROR: Failed to write to standard output!\n", /* 2 */ "ERROR: Failed to obtain random data!\n", /* 3 */ "ERROR: Aborted by signal!\n", /* 4 */ "ERROR: Failed to reset used buffers!\n", /* 5 */ "ERROR: Failed to seed OpenSSL PRNG!\n", /* 6 */ "ERROR: Failed to set up signal handlers!\n", /* 7 */ "ERROR: Failed to restore signal handlers!\n", /* 8 */ "ERROR: Numeric overflow in size calculation!\n", NULL #line 405 "dk-rand.ctr" }; /** 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; #line 574 "dk-rand.ctr" /* 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: #line 680 "dk-rand.ctr" 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; }