summaryrefslogtreecommitdiff
path: root/support/dktools/dk-recv.c
diff options
context:
space:
mode:
Diffstat (limited to 'support/dktools/dk-recv.c')
-rw-r--r--support/dktools/dk-recv.c1226
1 files changed, 1226 insertions, 0 deletions
diff --git a/support/dktools/dk-recv.c b/support/dktools/dk-recv.c
new file mode 100644
index 0000000000..6ff288b381
--- /dev/null
+++ b/support/dktools/dk-recv.c
@@ -0,0 +1,1226 @@
+/*
+ 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-recv.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-recv.c The dk-recv module.
+*/
+
+
+#line 10 "dk-recv.ctr"
+
+#include "dk4conf.h"
+
+#if DK4_HAVE_MATH_H
+#ifndef MATH_H_INCLUDED
+#include <math.h>
+#define MATH_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_ERRNO_H
+#ifndef ERRNO_H_INCLUDED
+#include <errno.h>
+#define ERRNO_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
+
+#include "dk4sock.h"
+#include "dk4socka.h"
+#include "dk4fput.h"
+#include "dk4vers.h"
+#include "dk4aopt.h"
+#include "dk4numco.h"
+#include "dk4fopda.h"
+#include "dk4isadm.h"
+#include "dk4fdwre.h"
+#include "dk4mpl.h"
+#include "dk4mem.h"
+#include "dk4mema.h"
+#include "dk4strd.h"
+#include "dk4pathd.h"
+
+
+
+
+
+#line 59 "dk-recv.ctr"
+
+
+
+/** Default help text, shown if no localized help text is found.
+*/
+static const dkChar * const dk_recv_help_text[] = {
+dkT(""),
+dkT("Receive data from a dk-send process."),
+dkT(""),
+dkT("dk-recv [<options>] <host> <port> [<file>]"),
+dkT(""),
+dkT("Arguments:"),
+dkT("host\t\tSender host to connect to (name or IP)."),
+dkT("port\t\tPort number to connect to."),
+dkT("file\t\tOutput file to create. Default: Write to standard output."),
+dkT(""),
+dkT("Options:"),
+dkT("-t\t\tTell peer to start transmission."),
+dkT("-l <port>\tLocal port number to bind."),
+dkT("-c <int>\tTimeout for connect attempt."),
+dkT(""),
+dkT("--help\t\tShow this short help text."),
+dkT("--manual\t*** SHOW FULL MANUAL. ***"),
+dkT("--version\tShow version information."),
+dkT("--license\tShow license information."),
+dkT(""),
+NULL
+
+
+#line 87 "dk-recv.ctr"
+};
+
+
+
+/** License text.
+*/
+static const dkChar * const dk_recv_license_text[] = {
+dkT("This software uses code from the following projects, either directly or as"),
+dkT("a library:"),
+dkT(""),
+dkT("dktools\t\tDirk Krause's tools and libraries."),
+dkT("\t\tSee http://dktools.sourceforge.net/ for more information."),
+#if DK4_HAVE_ZLIB_H
+dkT(""),
+dkT("zlib\t\tData compression library."),
+dkT("\t\tSee http://www.zlib.net/ for more information."),
+#endif
+#if DK4_HAVE_BZLIB_H
+dkT(""),
+dkT("bzip2\t\tData compression program and library."),
+dkT("\t\tSee http://www.bzip.org/ for more information."),
+#endif
+dkT(""),
+dkT("All the licenses below apply to the program."),
+dkT("Licenses for used libraries are shown as found on my Scientific Linux 6.x"),
+dkT("computer in the /usr/share/doc directory on 2015-04-01. Check the project"),
+dkT("homepages of the used libraries for additional information and/or updated"),
+dkT("license terms."),
+dkT(""),
+dkT(""),
+dkT("DK tools and libraries license"),
+dkT("=============================="),
+dkT("Copyright (c) 2015-2016, Dirk Krause"),
+dkT("All rights reserved."),
+dkT(""),
+dkT("Redistribution and use in source and binary forms, with or without"),
+dkT("modification, are permitted provided that the following conditions are met:"),
+dkT(""),
+dkT("* Redistributions of source code must retain the above copyright notice,"),
+dkT(" this list of conditions and the following disclaimer."),
+dkT("* Redistributions in binary form must reproduce the above copyright"),
+dkT(" notice, this list of conditions and the following disclaimer in the"),
+dkT(" documentation and/or other materials provided with the distribution."),
+dkT("* Neither the name of the Dirk Krause nor the names of contributors may be"),
+dkT(" used to endorse or promote products derived from this software without"),
+dkT(" specific prior written permission."),
+dkT(""),
+dkT("THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\""),
+dkT("AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE"),
+dkT("IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE"),
+dkT("ARE DISCLAIMED."),
+dkT(""),
+dkT("IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,"),
+dkT("INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,"),
+dkT("BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"),
+dkT("DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY"),
+dkT("OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING"),
+dkT("NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,"),
+dkT("EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."),
+#if DK4_HAVE_ZLIB_H
+dkT(""),
+dkT(""),
+dkT("Zlib license"),
+dkT("============"),
+dkT("(C) 1995-2004 Jean-loup Gailly and Mark Adler"),
+dkT(""),
+dkT("This software is provided 'as-is', without any express or implied"),
+dkT("warranty. In no event will the authors be held liable for any damages"),
+dkT("arising from the use of this software."),
+dkT(""),
+dkT("Permission is granted to anyone to use this software for any purpose,"),
+dkT("including commercial applications, and to alter it and redistribute it"),
+dkT("freely, subject to the following restrictions:"),
+dkT(""),
+dkT("1. The origin of this software must not be misrepresented; you must not"),
+dkT(" claim that you wrote the original software. If you use this software"),
+dkT(" in a product, an acknowledgment in the product documentation would be"),
+dkT(" appreciated but is not required."),
+dkT("2. Altered source versions must be plainly marked as such, and must not be"),
+dkT(" misrepresented as being the original software."),
+dkT("3. This notice may not be removed or altered from any source distribution."),
+dkT(""),
+dkT("Jean-loup Gailly Mark Adler"),
+dkT("jloup@gzip.org madler@alumni.caltech.edu"),
+#endif
+#if DK4_HAVE_BZLIB_H
+dkT(""),
+dkT(""),
+dkT("Bzip2 and libbzip2 library license"),
+dkT("=================================="),
+dkT("This program, \"bzip2\", the associated library \"libbzip2\", and all"),
+dkT("documentation, are copyright (C) 1996-2007 Julian R Seward. All"),
+dkT("rights reserved."),
+dkT(""),
+dkT("Redistribution and use in source and binary forms, with or without"),
+dkT("modification, are permitted provided that the following conditions"),
+dkT("are met:"),
+dkT(""),
+dkT("1. Redistributions of source code must retain the above copyright"),
+dkT(" notice, this list of conditions and the following disclaimer."),
+dkT(""),
+dkT("2. The origin of this software must not be misrepresented; you must "),
+dkT(" not claim that you wrote the original software. If you use this "),
+dkT(" software in a product, an acknowledgment in the product "),
+dkT(" documentation would be appreciated but is not required."),
+dkT(""),
+dkT("3. Altered source versions must be plainly marked as such, and must"),
+dkT(" not be misrepresented as being the original software."),
+dkT(""),
+dkT("4. The name of the author may not be used to endorse or promote "),
+dkT(" products derived from this software without specific prior written "),
+dkT(" permission."),
+dkT(""),
+dkT("THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS"),
+dkT("OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED"),
+dkT("WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE"),
+dkT("ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY"),
+dkT("DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL"),
+dkT("DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE"),
+dkT("GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS"),
+dkT("INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,"),
+dkT("WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING"),
+dkT("NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS"),
+dkT("SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."),
+dkT(""),
+dkT("Julian Seward, jseward@bzip.org"),
+dkT("bzip2/libbzip2 version 1.0.5 of 10 December 2007"),
+#endif
+dkT(""),
+NULL
+
+
+#line 218 "dk-recv.ctr"
+};
+
+
+
+/** Constant texts used by the program, not localized.
+*/
+static const dkChar * const dk_recv_kwnl[] = {
+/* 0 */
+dkT("dktools"),
+
+/* 1 */
+dkT("dk-recv.txt"),
+
+/* 2 */
+dkT("dk-recv.str"),
+
+/* 3 */
+dkT("\\"),
+
+/* 4 */
+dkT("wb"),
+
+NULL
+
+
+#line 247 "dk-recv.ctr"
+};
+
+
+
+/** Constant texts used by the program, replaced by localized
+ versions if found.
+*/
+static const dkChar * const dk_recv_kw_def[] = {
+/* 0 */
+dkT("Failed to set up signal handlers!"),
+
+/* 1 */
+dkT("Failed to restore signal handlers!"),
+
+/* 2 */
+dkT("stdin"),
+
+/* 3 */
+dkT("Failed to close file!"),
+
+/* 4 */
+dkT("Timeout too large!"),
+
+/* 5 */
+dkT("Timeout must not be negative!"),
+
+/* 6 */
+dkT("Timeout value not found!"),
+
+/* 7 */
+dkT("Wrong number of arguments!\n\thost port [filename]"),
+
+/* 8 */
+dkT("Interrupted by SIGINT signal!"),
+
+/* 9 */
+dkT("Interrupted by SIGTERM signal!"),
+
+/* 10 */
+dkT("Interrupted by SIGPIPE signal!"),
+
+NULL
+
+
+#line 292 "dk-recv.ctr"
+};
+
+
+
+/** Options used by the program.
+*/
+static const dk4_option_specification_t dk_recv_options[] = {
+
+ /* I am the last client, server can start transmissin now.
+ */
+ { dkT('t'), dkT("transmission"), DK4_OPT_ARG_NONE },
+
+ /* Bind a certain local port number.
+ */
+ { dkT('l'), dkT("local-port"), DK4_OPT_ARG_STRING },
+
+ /* Use a timeout when connecting to the server.
+ */
+ { dkT('c'), dkT("connect-timeout"), DK4_OPT_ARG_DOUBLE }
+};
+
+
+
+/** Array of localized texts, loaded in the main() function.
+ Usable as long as the app pointer below is usable.
+*/
+static const dkChar * const *dk_recv_kw_loc = NULL;
+
+
+
+/** Local port number to use.
+*/
+static const dkChar *dk_recv_portno = NULL;
+
+
+
+/** Application structure for diagnostics.
+*/
+static dk4_app_t *app = NULL;
+
+
+
+/** Number of elements in the dk_recv_options array.
+*/
+static const size_t dk_recv_sz_options =
+sizeof(dk_recv_options)/sizeof(dk4_option_specification_t);
+
+
+
+/** Number of elements in the dk_recv_kw_def array.
+*/
+static const size_t dk_recv_sz_def =
+sizeof(dk_recv_kw_def)/sizeof(DK4_PCDKCHAR) - 1;
+
+
+
+/** Number of elements in the dk_recv_kw_def array.
+*/
+static size_t dk_recv_sz_loc =
+sizeof(dk_recv_kw_def)/sizeof(DK4_PCDKCHAR) - 1;
+
+
+
+/** Seconds for timeout.
+*/
+static long dk_recv_timeout_secs = 0L;
+
+
+
+/** Microseconds for timeout.
+*/
+static long dk_recv_timeout_usecs = 0L;
+
+
+
+/** Exit status code.
+*/
+static int exval = EXIT_FAILURE;
+
+
+
+/** Flag send to server: Start transmission immediately.
+*/
+static unsigned char start_transmission = 0x00;
+
+
+
+#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 a volatile pointer to an atomic integer.
+ 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 ptr Address of atomic integer variable.
+ @return The unmodified pointer.
+*/
+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 if a signal was received.
+ @param check_pipe Flag: Check for occured SIGPIPE signal too.
+ @return 1 if the program can continue, 0 if a signal was received.
+*/
+static
+int
+sig_can_continue(int check_pipe)
+{
+ int back = 1;
+#ifdef SIGPIPE
+ if (0 != check_pipe) {
+ if (0 != sig_read_atomic(&sig_had_pipe)) { back = 0; }
+ }
+#endif
+ if (0 != sig_read_atomic(&sig_had_int )) { back = 0; }
+ if (0 != sig_read_atomic(&sig_had_term)) { back = 0; }
+ return back;
+}
+
+
+
+#if 0
+
+/*
+ 2016-01-02:
+ Removed - replaced by sig_can_continue(1) - after profiling.
+*/
+
+/** Check whether we can continue.
+ @return 1 for yes, 0 for no.
+*/
+static
+int
+dk_recv_can_continue(void)
+{
+ int back = 1;
+ if (0 == sig_can_continue(1)) {
+ back = 0;
+ }
+ return back;
+}
+
+#endif
+/* if 0 */
+
+
+
+/** Data buffer
+*/
+#if DK4_SIZEOF_SIZE_T > 2
+static char bu[1048576];
+#else
+static char bu[16384];
+#endif
+
+/** Run for hostname, port specification and real file name
+ (wildcards * and ? resolved on Windows).
+ @param hostname Host to connect to (name or address).
+ @param portspec Port to connect to (number or service name).
+ @param filename File name to write, may be NULL (stdout).
+*/
+static
+void
+dk_recv_run_with_real_file_name(
+ const dkChar *hostname,
+ const dkChar *portspec,
+ const dkChar *filename
+)
+{
+#if 0
+ /* 2016-01-06:
+ Buffer size increased, do not use stack.
+ */
+ char bu[1460]; /* Data buffer */
+#endif
+ FILE *fipo = NULL; /* Output file */
+ size_t sz = 0; /* Buffer sizes */
+ size_t wrb = 0; /* Bytes written */
+ dk4_socket_t sock = INVALID_SOCKET; /* Client socket */
+#if DK4_ON_WINDOWS
+ int oldmode= _O_TEXT; /* File mode stdout */
+#endif
+ int cc = 1; /* Flag: Can continue */
+ int first = 1; /* Flag: First pass */
+ int res = 0; /* Operation result */
+ int we = 0; /* Flag: Write error */
+ int tests = 0;
+
+
+
+#line 553 "dk-recv.ctr"
+ /* Check for signals.
+ */
+ if (0 == sig_can_continue(1)) {
+ goto finished;
+ }
+
+#line 558 "dk-recv.ctr"
+
+ /* Bring socket subsystem up (Windows).
+ */
+ if (DK4_SOCKET_RESULT_SUCCESS != dk4socket_up_app(app)) {
+ /* ERROR: Failed to bring socket subsystem up, already reported */
+ goto finished;
+ }
+
+#line 565 "dk-recv.ctr"
+
+ /* Open TCP client socket.
+ */
+ sock = dk4socket_tcp_client_for_host_service_app(
+ hostname, portspec, dk_recv_portno,
+ dk_recv_timeout_secs, dk_recv_timeout_usecs, app
+ );
+ if (INVALID_SOCKET == sock) {
+ /* ERROR: Failed to create socket, already reported */
+ goto tcpip_down;
+ }
+
+#line 576 "dk-recv.ctr"
+ if (0 == sig_can_continue(1)) {
+ goto close_socket;
+ }
+
+#line 579 "dk-recv.ctr"
+
+ /* Send start-of-transmission byte and shutdown socket for writing.
+ */
+ sz = 1;
+ res = dk4socket_send_app(sock, &start_transmission, &sz, 0, 0L, 0L, app);
+ if (DK4_SOCKET_RESULT_SUCCESS != res) {
+ goto close_socket;
+ }
+
+#line 587 "dk-recv.ctr"
+ if (0 == sig_can_continue(1)) {
+ goto close_socket;
+ }
+
+#line 590 "dk-recv.ctr"
+ res = dk4socket_shutdown_app(sock, DK4_SOCKET_SHUT_WRITE, app);
+ if (DK4_SOCKET_RESULT_SUCCESS != res) {
+ goto close_socket;
+ }
+
+#line 594 "dk-recv.ctr"
+ if (0 == sig_can_continue(1)) {
+ goto close_socket;
+ }
+
+#line 597 "dk-recv.ctr"
+
+ /* Indicate success so far.
+ */
+ exval = EXIT_SUCCESS;
+
+ /* Now receive data.
+ */
+ do {
+ if (0 != sig_can_continue(1)) {
+
+#line 606 "dk-recv.ctr"
+ sz = sizeof(bu);
+ res = dk4socket_recv_app(sock, bu, &sz, 0, 0L, 0L, app);
+ if (DK4_SOCKET_RESULT_SUCCESS == res) {
+ if (0 < sz) {
+
+#line 610 "dk-recv.ctr"
+ if (0 != sig_can_continue(1)) {
+ if (0 != first) {
+
+#line 612 "dk-recv.ctr"
+ first = 0;
+ if (NULL != filename) {
+
+#line 614 "dk-recv.ctr"
+ tests = DK4_FOPEN_SC_USER;
+ if (0 != dk4isadmin()) { tests = DK4_FOPEN_SC_PRIVILEGED; }
+ fipo = dk4fopen_app(filename, dk_recv_kwnl[4], tests, app);
+ if (NULL == fipo) {
+
+#line 618 "dk-recv.ctr"
+ exval = EXIT_FAILURE;
+ }
+ } else {
+
+#line 621 "dk-recv.ctr"
+ /* MODE FOR WINDOWS */
+#if DK4_ON_WINDOWS
+ oldmode = _setmode(_fileno(stdout), _O_BINARY);
+#endif
+ fipo = stdout;
+ }
+ }
+ if (NULL != fipo) {
+
+#line 629 "dk-recv.ctr"
+ if (0 == we) {
+
+#line 630 "dk-recv.ctr"
+ errno = 0;
+
+#line 631 "dk-recv.ctr"
+ wrb = fwrite(bu, 1, sz, fipo);
+ if (wrb != sz) {
+
+#line 633 "dk-recv.ctr"
+ we = 1;
+ exval = EXIT_FAILURE;
+ /* ERROR: Write attempt failed */
+ dk4fd_write_error_msg(
+ app,
+ ((filename) ? (filename) : (dk_recv_kw_def[2])),
+ errno
+ );
+ }
+ }
+ }
+ } else {
+
+#line 645 "dk-recv.ctr"
+ cc = -1;
+ }
+ } else {
+
+#line 648 "dk-recv.ctr"
+ cc = 0;
+ }
+ } else {
+
+#line 651 "dk-recv.ctr"
+ cc = -1;
+ }
+ } else {
+
+#line 654 "dk-recv.ctr"
+ cc = -1;
+ }
+ } while (1 == cc);
+
+ /* Cleanup
+ */
+ if (0 == first) {
+
+#line 661 "dk-recv.ctr"
+ if (NULL != filename) {
+
+#line 662 "dk-recv.ctr"
+ if (NULL != fipo) {
+
+#line 663 "dk-recv.ctr"
+ if (0 != fclose(fipo)) {
+
+#line 664 "dk-recv.ctr"
+ /* ERROR: Failed to close file */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 3);
+ exval = EXIT_FAILURE;
+ }
+ }
+ } else {
+
+#line 670 "dk-recv.ctr"
+ if (0 != fflush(stdout)) {
+
+#line 671 "dk-recv.ctr"
+ exval = EXIT_FAILURE;
+ }
+#if DK4_ON_WINDOWS
+ _setmode(_fileno(stdout), oldmode);
+#endif
+ }
+ }
+
+ /* Close socket if open.
+ */
+ close_socket:
+ if (INVALID_SOCKET != sock) {
+
+#line 683 "dk-recv.ctr"
+ dk4socket_close_app(sock, app);
+ }
+
+ /* Shut socket subsystem down (Windows).
+ */
+ tcpip_down:
+ dk4socket_down_app(app);
+
+#line 690 "dk-recv.ctr"
+
+ finished: ;
+
+
+#line 693 "dk-recv.ctr"
+}
+
+
+
+#if DK4_ON_WINDOWS
+/** Expand file name and run for host, port and file name.
+ @param hostname Host name or address to connect to.
+ @param portspec Remote port to connect to.
+ @param filename File name pattern to expand.
+*/
+static
+void
+dk_recv_expand_file_name(
+ const dkChar *hostname,
+ const dkChar *portspec,
+ const dkChar *filename
+)
+{
+ dkChar buf[DK4_MAX_PATH];
+ dk4_dir_t *fne;
+ const dkChar *pt;
+ const dkChar *fn;
+ size_t szbuf;
+ int copied;
+
+ fne = dk4app_fne_open(filename, app);
+ if (NULL != fne) {
+ fn = dk4dir_next_file(fne);
+ if (NULL != fn) {
+ pt = dk4dir_get_path(fne);
+ if (NULL == dk4dir_next_file(fne)) {
+ if (NULL != pt) {
+ szbuf = DK4_SIZEOF(buf, dkChar);
+ copied = 0;
+ if (0 != dk4str_cpy_s(buf, szbuf, pt, NULL)) {
+ if (0 != dk4str_cat_s(buf, szbuf, dk_recv_kwnl[3], NULL)) {
+ if (0 != dk4str_cat_s(buf, szbuf, fn, NULL)) {
+ copied = 1;
+ dk_recv_run_with_real_file_name(hostname, portspec, buf);
+ }
+ }
+ }
+ if (0 == copied) {
+ /* ERROR: Path too long */
+ dk4app_log_base3(app, DK4_LL_ERROR, 100, 105, filename);
+ }
+ } else {
+ dk_recv_run_with_real_file_name(hostname, portspec, fn);
+ }
+ } else {
+ /* ERROR: Not a unique file name */
+ dk4app_log_base3(app, DK4_LL_ERROR, 100, 106, filename);
+ }
+ } else {
+ /* ERROR: No such file */
+ dk4app_log_base3(app, DK4_LL_ERROR, 100, 107, filename);
+ }
+ dk4dir_close(fne);
+ }
+}
+#endif
+
+
+
+/** Run for given host, port and file name.
+ @param hostname Host name or address to connect to.
+ @param portspec Remote port to connect to.
+ @param filename File name to write to, may be NULL (stdout).
+*/
+static
+void
+dk_recv_run_for_arguments(
+ const dkChar *hostname,
+ const dkChar *portspec,
+ const dkChar *filename
+)
+{
+#if DK4_ON_WINDOWS
+ if (0 != dk4path_must_expand(filename)) {
+ dk_recv_expand_file_name(hostname, portspec, filename);
+ } else {
+#endif
+ dk_recv_run_with_real_file_name(hostname, portspec, filename);
+#if DK4_ON_WINDOWS
+ }
+#endif
+}
+
+
+
+/** Process options, retrieve command line arguments and run
+ for given host, port and optionally file name.
+*/
+static
+void
+dk_recv_normal_run(void)
+{
+ double timeout;
+ double d1;
+ double d2;
+ int xargc;
+ int canrun;
+
+
+#line 796 "dk-recv.ctr"
+ canrun = 1;
+ /* Timeout specified?
+ */
+ if (0 != dk4app_opt_is_set_short(app, dkT('t'), NULL)) {
+ start_transmission = 0x01;
+ }
+ /* Local port number specified?
+ */
+ if (0 != dk4app_opt_is_set_short(app, dkT('l'), NULL)) {
+ dk_recv_portno = dk4app_opt_get_string_ptr_short(app, dkT('l'), NULL);
+ }
+ /* Connection timeout specified?
+ */
+ if (0 != dk4app_opt_is_set_short(app, dkT('c'), NULL)) {
+ if (0 != dk4app_opt_get_double_short(&timeout, app, dkT('c'), NULL)) {
+ if (0.0 <= timeout) {
+ d1 = floor(timeout);
+ d2 = timeout - d1;
+ d2 = 1000000.0 * d2;
+ if ((double)(LONG_MAX) >= d1) {
+ dk_recv_timeout_secs = (long)d1;
+ dk_recv_timeout_usecs = (long)d2;
+ } else {
+ canrun = 0;
+ /* ERROR: Timeout too large */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 4);
+ }
+ } else {
+ /* Warning: Can not use a negative timeout */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_WARNING, 5);
+ }
+ } else {
+ canrun = 0;
+ /* No timeout value found ! */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 6);
+ }
+ }
+ if (0 != canrun) {
+ xargc = dk4app_get_argc(app);
+ switch (xargc) {
+ case 2: {
+ dk_recv_run_for_arguments(
+ dk4app_get_argv(app, 0),
+ dk4app_get_argv(app, 1),
+ NULL
+ );
+ } break;
+ case 3: {
+ dk_recv_run_for_arguments(
+ dk4app_get_argv(app, 0),
+ dk4app_get_argv(app, 1),
+ dk4app_get_argv(app, 2)
+ );
+ } break;
+ default : {
+ /* ERROR: Wrong number of arguments */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 7);
+ } break;
+ }
+ }
+
+
+#line 857 "dk-recv.ctr"
+}
+
+
+
+#if DK4_HAVE_SIGACTION
+/** Set signal handlers and run.
+*/
+static
+void
+dk_recv_run_with_signal_handlers(void)
+{
+#ifdef SIGPIPE
+ struct sigaction opipe;
+#endif
+ struct sigaction oint;
+#ifdef SIGPIPE
+ struct sigaction npipe;
+#endif
+ struct sigaction nint;
+ struct sigaction oterm;
+ struct sigaction nterm;
+ int success = 0;
+
+#ifdef SIGPIPE
+ /* Set up signal handling for SIGPIPE.
+ */
+ DK4_MEMRES(&npipe, sizeof(npipe));
+ npipe.sa_handler = sig_handler_pipe;
+ npipe.sa_flags = 0;
+ if (0 != sigemptyset(&npipe.sa_mask)) {
+ /* ERROR: Failed to set up masked signal set for SIGPIPE */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0);
+ goto finished;
+ }
+ if (0 != sigaddset(&npipe.sa_mask, SIGPIPE)) {
+ /* ERROR: Failed to set up masked signal set for SIGPIPE */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0);
+ goto finished;
+ }
+ if (0 != sigaction(SIGPIPE, &npipe, &opipe)) {
+ /* ERROR: Failed to set up signal handler for SIGPIPE */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0);
+ goto finished;
+ }
+#endif
+
+ /* Set up signal handling for SIGINT.
+ */
+ DK4_MEMRES(&nint, sizeof(nint));
+ nint.sa_handler = sig_handler_int;
+ nint.sa_flags = 0;
+ if (0 != sigemptyset(&nint.sa_mask)) {
+ /* ERROR: Failed to set up masked signal set for SIGINT */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0);
+ goto restore_old_pipe;
+ }
+ if (0 != sigaddset(&nint.sa_mask, SIGINT)) {
+ /* ERROR: Failed to set up masked signal set for SIGINT */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0);
+ goto restore_old_pipe;
+ }
+ if (0 != sigaction(SIGINT, &nint, &oint)) {
+ /* ERROR: Failed to set up signal handler for SIGINT */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0);
+ goto restore_old_pipe;
+ }
+
+ /* Set up signal handling for SIGTERM
+ */
+ DK4_MEMRES(&nterm, sizeof(nterm));
+ nterm.sa_handler = sig_handler_term;
+ nterm.sa_flags = 0;
+ if (0 != sigemptyset(&nterm.sa_mask)) {
+ /* ERROR: Failed to set up masked signal set for SIGTERM */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0);
+ goto restore_old_int;
+ }
+ if (0 != sigaddset(&nterm.sa_mask, SIGTERM)) {
+ /* ERROR: Failed to set up masked signal set for SIGTERM */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0);
+ goto restore_old_int;
+ }
+ if (0 != sigaction(SIGTERM, &nterm, &oterm)) {
+ /* ERROR: Failed to set up signal handler for SIGTERM */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 0);
+ goto restore_old_int;
+ }
+
+ success = 1;
+ dk_recv_normal_run();
+
+ /* Restore signal handling for SIGTERM.
+ */
+ if (0 != sigaction(SIGTERM, &oterm, NULL)) {
+ /* ERROR: Failed to restore old SIGTERM settings */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 1);
+ success = 0;
+ }
+
+ /* Restore signal handling for SIGINT.
+ */
+ restore_old_int:
+ if (0 != sigaction(SIGINT, &oint, NULL)) {
+ /* ERROR: Failed to restore old SIGPIPE settings */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 1);
+ success = 0;
+ }
+
+#ifdef SIGPIPE
+ /* Restore signal handling for SIGPIPE.
+ */
+ restore_old_pipe:
+ if (0 != sigaction(SIGPIPE, &opipe, NULL)) {
+ /* ERROR: Failed to restore old SIGPIPE settings */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 1);
+ success = 0;
+ }
+#endif
+
+ /* Set exit status code if error occured.
+ */
+ finished:
+ if (0 == success) { exval = EXIT_FAILURE; }
+}
+#else
+#if DK4_HAVE_SIGSET
+/** Set signal handlers and run.
+*/
+static
+void
+dk_recv_run_with_signal_handlers(void)
+{
+#ifdef SIGPIPE
+ dk4_sig_handler_t *oldpipe = NULL;
+#endif
+ dk4_sig_handler_t *oldint = NULL;
+ dk4_sig_handler_t *oldterm = NULL;
+
+#ifdef SIGPIPE
+ oldpipe = sigset(SIGPIPE, sig_handler_pipe);
+#endif
+ oldint = sigset(SIGINT, sig_handler_int);
+ oldterm = sigset(SIGTERM, sig_handler_term);
+ dk_recv_normal_run();
+ sigset(SIGTERM, oldterm);
+ sigset(SIGINT, oldint);
+#ifdef SIGPIPE
+ sigset(SIGPIPE, oldpipe);
+#endif
+}
+#else
+#if DK4_HAVE_SIGNAL
+/** Set signal handlers and run.
+*/
+static
+void
+dk_recv_run_with_signal_handlers(void)
+{
+#ifdef SIGPIPE
+ dk4_sig_handler_t *oldpipe = NULL;
+#endif
+ dk4_sig_handler_t *oldint = NULL;
+ dk4_sig_handler_t *oldterm = NULL;
+
+#ifdef SIGPIPE
+ oldpipe = signal(SIGPIPE, sig_handler_pipe);
+#endif
+ oldint = signal(SIGINT, sig_handler_int);
+ oldterm = signal(SIGTERM, sig_handler_term);
+ dk_recv_normal_run();
+ signal(SIGTERM, oldterm);
+ signal(SIGINT, oldint);
+#ifdef SIGPIPE
+ signal(SIGPIPE, oldpipe);
+#endif
+}
+#else
+/** Set signal handlers and run.
+*/
+static
+void
+dk_recv_run_with_signal_handlers(void)
+{
+ dk_recv_normal_run();
+}
+#endif
+#endif
+#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
+{
+
+
+#line 1060 "dk-recv.ctr"
+
+
+#line 1061 "dk-recv.ctr"
+ dk4fput_initialize_stderr();
+ app = dk4app_open_cmd(
+ argc, argv, dk_recv_options, dk_recv_sz_options,
+ dk_recv_kwnl[0], DKT_VERSION_DK,
+ dk_recv_kwnl[1], dk_recv_help_text, dk_recv_license_text
+ );
+ if (NULL != app) {
+
+#line 1068 "dk-recv.ctr"
+ dk_recv_sz_loc = dk4app_string_table_size(dk_recv_kw_def);
+ dk_recv_kw_loc = dk4app_string_table(app, dk_recv_kwnl[2], dk_recv_kw_def);
+ dk_recv_sz_loc = dk4app_string_table_size(dk_recv_kw_loc);
+ if (0 != dk4app_can_run_normally(app)) {
+ dk_recv_run_with_signal_handlers();
+ } else {
+ if (0 != dk4app_help_version_license(app)) {
+ exval = EXIT_SUCCESS;
+ }
+ }
+ if (0 != sig_read_atomic(&sig_had_int )) {
+ /* Interrupted by SIGINT */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 8);
+ }
+ if (0 != sig_read_atomic(&sig_had_term)) {
+ /* Interrupted by SIGTERM */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 9);
+ }
+#if defined(SIGPIPE)
+ if (0 != sig_read_atomic(&sig_had_pipe)) {
+ /* Interrupted by SIGPIPE */
+ dk4app_log_1(app, dk_recv_kw_loc, dk_recv_sz_loc, DK4_LL_ERROR, 10);
+ }
+#endif
+ dk4app_close(app); app = NULL;
+ } else {
+
+#line 1094 "dk-recv.ctr"
+ }
+ fflush(stderr);
+ dk4fput_cleanup_stderr();
+ if (0 != sig_read_atomic(&sig_had_int )) {
+ exval = EXIT_FAILURE;
+ }
+ if (0 != sig_read_atomic(&sig_had_term)) {
+ exval = EXIT_FAILURE;
+ }
+#if defined(SIGPIPE)
+ if (0 != sig_read_atomic(&sig_had_pipe)) {
+ exval = EXIT_FAILURE;
+ }
+#endif
+
+
+#line 1109 "dk-recv.ctr"
+
+
+#line 1110 "dk-recv.ctr"
+ exit(exval); return exval;
+}
+